WP Testing on i[34]86 fixed

Martin Mares (mj@atrey.karlin.mff.cuni.cz)
Sun, 6 Apr 1997 19:50:52 +0200


Hello, world!

I don't know whether anyone mentioned the total malfunction of WP bit testing
in all recent kernels. I've found the bug and fixed it by the following patch:

Martin

diff -ruN linux-old/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c
--- linux-old/arch/i386/mm/fault.c Thu Jan 30 13:33:21 1997
+++ linux/arch/i386/mm/fault.c Sun Apr 6 19:27:53 1997
@@ -187,11 +187,10 @@
*
* First we check if it was the bootup rw-test, though..
*/
- if (wp_works_ok < 0 && !address && (error_code & 1)) {
+ if (wp_works_ok < 0 && address == 0xc0000000 && (error_code & 1)) {
wp_works_ok = 1;
pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
flush_tlb();
- printk("This processor honours the WP bit even when in supervisor mode. Good.\n");
goto out;
}
if (address < PAGE_SIZE) {
diff -ruN linux-old/arch/i386/mm/init.c linux/arch/i386/mm/init.c
--- linux-old/arch/i386/mm/init.c Thu Jan 30 13:33:21 1997
+++ linux/arch/i386/mm/init.c Sun Apr 6 19:31:21 1997
@@ -146,19 +146,20 @@
pg_dir = swapper_pg_dir;
/* unmap the original low memory mappings */
pgd_val(pg_dir[0]) = 0;
+
+ /* Map whole memory from 0xC0000000 */
+
while (address < end_mem) {
- /*
- * The following code enabled 4MB page tables for the
- * Intel Pentium cpu, unfortunately the SMP kernel can't
- * handle the 4MB page table optimizations yet
- */
- /*
- * This will create page tables that
- * span up to the next 4MB virtual
- * memory boundary, but that's ok,
- * we won't use that memory anyway.
- */
if (x86_capability & 8) {
+ /*
+ * If we're running on a Pentium CPU, we can use the 4MB
+ * page tables. Unfortunately, the SMP kernel can't
+ * handle the 4MB page table optimizations yet (???)
+ *
+ * The page tables we create span up to the next 4MB
+ * virtual memory boundary, but that's OK as we won't
+ * use that memory anyway.
+ */
#ifdef GAS_KNOWS_CR4
__asm__("movl %%cr4,%%eax\n\t"
"orl $16,%%eax\n\t"
@@ -176,8 +177,10 @@
address += 4*1024*1024;
continue;
}
- /* map the memory at virtual addr 0xC0000000 */
- /* pg_table is physical at this point */
+ /*
+ * We're on a [34]86, use normal page tables.
+ * pg_table is physical at this point
+ */
pg_table = (pte_t *) (PAGE_MASK & pgd_val(pg_dir[768]));
if (!pg_table) {
pg_table = (pte_t *) __pa(start_mem);
@@ -273,18 +276,25 @@
/* test if the WP bit is honoured in supervisor mode */
if (wp_works_ok < 0) {
unsigned char tmp_reg;
+ unsigned long old = pg0[0];
+ printk("Checking if this processor honours the WP bit even in supervisor mode... ");
pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_READONLY));
local_flush_tlb();
+ current->mm->mmap->vm_start += PAGE_SIZE;
__asm__ __volatile__(
"movb %0,%1 ; movb %1,%0"
:"=m" (*(char *) __va(0)),
"=q" (tmp_reg)
:/* no inputs */
:"memory");
- pg0[0] = pte_val(mk_pte(PAGE_OFFSET, PAGE_KERNEL));
+ pg0[0] = old;
local_flush_tlb();
- if (wp_works_ok < 0)
+ current->mm->mmap->vm_start -= PAGE_SIZE;
+ if (wp_works_ok < 0) {
wp_works_ok = 0;
+ printk("No.\n");
+ } else
+ printk("Ok.\n");
}
return;
}