On 02/27/2014 02:31 PM, Steven Rostedt wrote:
> 
> Yeah, something is getting mesed up.
> 

What it *looks* like to me is that we try to nest the cr2 save/restore,
which doesn't nest because it is a percpu variable.

... except in the x86-64 case, we *ALSO* save/restore cr2 inside
entry_64.S, which makes the stuff in do_nmi completely redundant and
there for no good reason.

I would actually suggest we do the equivalent on i386 as well.

Vince, could you try this patch as an experiment?


diff --git a/arch/x86/lib/usercopy.c b/arch/x86/lib/usercopy.c
index ddf9ecb..938e45c 100644
--- a/arch/x86/lib/usercopy.c
+++ b/arch/x86/lib/usercopy.c
@@ -10,6 +10,8 @@
 #include <asm/word-at-a-time.h>
 #include <linux/sched.h>
 
+#include <asm/processor.h>
+
 /*
  * We rely on the nested NMI work to allow atomic faults from the NMI path; the
  * nested NMI paths are careful to preserve CR2.
@@ -18,6 +20,7 @@ unsigned long
 copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
 {
        unsigned long ret;
+       unsigned long cr2;
 
        if (__range_not_ok(from, n, TASK_SIZE))
                return 0;
@@ -27,9 +30,11 @@ copy_from_user_nmi(void *to, const void __user *from, 
unsigned long n)
         * disable pagefaults so that its behaviour is consistent even when
         * called form other contexts.
         */
+       cr2 = read_cr2();
        pagefault_disable();
        ret = __copy_from_user_inatomic(to, from, n);
        pagefault_enable();
+       write_cr2(cr2);
 
        return ret;
 }

Reply via email to