summaryrefslogtreecommitdiffstats
path: root/arch/i386/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/mm')
-rw-r--r--arch/i386/mm/fault.c9
-rw-r--r--arch/i386/mm/init.c64
2 files changed, 44 insertions, 29 deletions
diff --git a/arch/i386/mm/fault.c b/arch/i386/mm/fault.c
index e4847c070..8181fd6c7 100644
--- a/arch/i386/mm/fault.c
+++ b/arch/i386/mm/fault.c
@@ -186,16 +186,15 @@ bad_area:
*
* First we check if it was the bootup rw-test, though..
*/
- if (wp_works_ok < 0 && address == 0xc0000000 && (error_code & 1)) {
+ if (wp_works_ok < 0 && address == TASK_SIZE && (error_code & 1)) {
wp_works_ok = 1;
- pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
+ pg0[0] = pte_val(mk_pte(TASK_SIZE, PAGE_SHARED));
flush_tlb();
goto out;
}
- if (address < PAGE_SIZE) {
+ if (address < PAGE_SIZE)
printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
- pg0[0] = pte_val(mk_pte(0, PAGE_SHARED));
- } else
+ else
printk(KERN_ALERT "Unable to handle kernel paging request");
printk(" at virtual address %08lx\n",address);
__asm__("movl %%cr3,%0" : "=r" (page));
diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c
index 8f2852a48..6ed47e2ef 100644
--- a/arch/i386/mm/init.c
+++ b/arch/i386/mm/init.c
@@ -261,6 +261,43 @@ __initfunc(unsigned long paging_init(unsigned long start_mem, unsigned long end_
return free_area_init(start_mem, end_mem);
}
+/*
+ * Test if the WP bit works in supervisor mode. It isn't supported on 386's
+ * and also on some strange 486's (NexGen etc.). All 586+'s are OK. The jumps
+ * before and after the test are here to work-around some nasty CPU bugs.
+ */
+
+__initfunc(void test_wp_bit(void))
+{
+ 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__(
+ "jmp 1f; 1:\n"
+ "movb %0,%1\n"
+ "movb %1,%0\n"
+ "jmp 1f; 1:\n"
+ :"=m" (*(char *) __va(0)),
+ "=q" (tmp_reg)
+ :/* no inputs */
+ :"memory");
+ pg0[0] = old;
+ local_flush_tlb();
+ current->mm->mmap->vm_start -= PAGE_SIZE;
+ if (wp_works_ok < 0) {
+ wp_works_ok = 0;
+ printk("No.\n");
+#ifndef CONFIG_M386
+ panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!");
+#endif
+ } else
+ printk("Ok.\n");
+}
+
__initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
{
unsigned long start_low_mem = PAGE_SIZE;
@@ -339,30 +376,9 @@ __initfunc(void mem_init(unsigned long start_mem, unsigned long end_mem))
reservedpages << (PAGE_SHIFT-10),
datapages << (PAGE_SHIFT-10),
initpages << (PAGE_SHIFT-10));
-/* 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] = old;
- local_flush_tlb();
- current->mm->mmap->vm_start -= PAGE_SIZE;
- if (wp_works_ok < 0) {
- wp_works_ok = 0;
- printk("No.\n");
- } else
- printk("Ok.\n");
- }
- return;
+
+ if (wp_works_ok < 0)
+ test_wp_bit();
}
void free_initmem(void)