[PATCH] Clean up x86 write-protect test

From: Brian Gerst (bgerst@didntduck.org)
Date: Fri Oct 13 2000 - 19:36:08 EST


This patch makes the write-protect test use the normal exception
handling mechanism. This removes the need for the special case check in
the page fault handler. The only concern I have is because of this
comment:

/*
 * Beware: Black magic here. The printk is needed here to flush
 * CPU state on certain buggy processors.
 */

Does anyone have an explanation as to why this printk is necessary? I
can't figure out why this case would need the printk but no other page
fault exception would.

Also, Could somebody who has a machine with a known buggy processor give
this patch a try?

-- 

Brian Gerst

diff -urN linux-2.4.0t10p2/Documentation/exception.txt linux/Documentation/exception.txt --- linux-2.4.0t10p2/Documentation/exception.txt Fri Jul 28 01:28:07 2000 +++ linux/Documentation/exception.txt Fri Oct 13 20:13:52 2000 @@ -284,3 +284,9 @@ successful, -EFAULT on failure. Our original code did not test this return value, however the inline assembly code in get_user tries to return -EFAULT. GCC selected EAX to return this value. + +NOTE: +Due to the way that the exception table is built and needs to be ordered, +only use exceptions for code in the .text section. Any other section +will cause the exception table to not be sorted correctly, and the +exceptions will fail. diff -urN linux-2.4.0t10p2/arch/i386/mm/fault.c linux/arch/i386/mm/fault.c --- linux-2.4.0t10p2/arch/i386/mm/fault.c Thu Oct 12 19:48:23 2000 +++ linux/arch/i386/mm/fault.c Fri Oct 13 20:13:52 2000 @@ -77,31 +77,6 @@ return 0; } -static void __init handle_wp_test (void) -{ - const unsigned long vaddr = PAGE_OFFSET; - pgd_t *pgd; - pmd_t *pmd; - pte_t *pte; - - /* - * make it read/writable temporarily, so that the fault - * can be handled. - */ - pgd = swapper_pg_dir + __pgd_offset(vaddr); - pmd = pmd_offset(pgd, vaddr); - pte = pte_offset(pmd, vaddr); - *pte = mk_pte_phys(0, PAGE_KERNEL); - __flush_tlb_all(); - - boot_cpu_data.wp_works_ok = 1; - /* - * Beware: Black magic here. The printk is needed here to flush - * CPU state on certain buggy processors. - */ - printk("Ok"); -} - asmlinkage void do_invalid_op(struct pt_regs *, unsigned long); extern unsigned long idt; @@ -274,14 +249,7 @@ /* * Oops. The kernel tried to access some bad page. We'll have to * terminate things with extreme prejudice. - * - * First we check if it was the bootup rw-test, though.. */ - if (boot_cpu_data.wp_works_ok < 0 && - address == PAGE_OFFSET && (error_code & 1)) { - handle_wp_test(); - return; - } if (address < PAGE_SIZE) printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference"); diff -urN linux-2.4.0t10p2/arch/i386/mm/init.c linux/arch/i386/mm/init.c --- linux-2.4.0t10p2/arch/i386/mm/init.c Thu Aug 10 08:10:02 2000 +++ linux/arch/i386/mm/init.c Fri Oct 13 20:15:42 2000 @@ -491,16 +491,43 @@ * before and after the test are here to work-around some nasty CPU bugs. */ +/* + * This function cannot be __init, since exceptions don't work in that + * section. + */ +static int do_test_wp_bit(unsigned long vaddr) +{ + char tmp_reg; + int flag = 0; + + __asm__ __volatile__( + " movb %0,%1 \n" + "1: movb %1,%0 \n" + " jmp 3f \n" + "2: incl %2 \n" + "3: \n" + ".section __ex_table,\"a\"\n" + " .align 4 \n" + " .long 1b,2b \n" + ".previous \n" + :"=m" (*(char *) vaddr), + "=q" (tmp_reg), + "=r" (flag) + :"2" (flag) + :"memory"); + + return flag; +} + void __init test_wp_bit(void) { /* - * Ok, all PAE-capable CPUs are definitely handling the WP bit right. + * Ok, all PSE-capable CPUs are definitely handling the WP bit right. */ const unsigned long vaddr = PAGE_OFFSET; pgd_t *pgd; pmd_t *pmd; pte_t *pte, old_pte; - char tmp_reg; printk("Checking if this processor honours the WP bit even in supervisor mode... "); @@ -511,27 +538,19 @@ *pte = mk_pte_phys(0, PAGE_READONLY); local_flush_tlb(); - __asm__ __volatile__( - "jmp 1f; 1:\n" - "movb %0,%1\n" - "movb %1,%0\n" - "jmp 1f; 1:\n" - :"=m" (*(char *) vaddr), - "=q" (tmp_reg) - :/* no inputs */ - :"memory"); + boot_cpu_data.wp_works_ok = do_test_wp_bit(vaddr); *pte = old_pte; local_flush_tlb(); - if (boot_cpu_data.wp_works_ok < 0) { - boot_cpu_data.wp_works_ok = 0; + if (!boot_cpu_data.wp_works_ok) { printk("No.\n"); #ifdef CONFIG_X86_WP_WORKS_OK panic("This kernel doesn't support CPU's with broken WP. Recompile it for a 386!"); #endif - } else - printk(".\n"); + } else { + printk("Ok.\n"); + } } static inline int page_is_ram (unsigned long pagenr)

- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Oct 15 2000 - 21:00:26 EST