lkml.org 
[lkml]   [2000]   [Oct]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] Clean up x86 write-protect test
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 Gerstdiff -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)
\
 
 \ /
  Last update: 2005-03-22 12:41    [W:0.090 / U:0.288 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site