Messages in this thread | | | Date | Thu, 17 Oct 2013 15:27:48 -0700 | Subject | Re: [PATCH] perf, x86: Optimize intel_pmu_pebs_fixup_ip() | From | Linus Torvalds <> |
| |
On Thu, Oct 17, 2013 at 3:01 PM, Peter Zijlstra <peterz@infradead.org> wrote: > > Oh wait,.. now that Steven fixed being able to take faults from NMI > context; we could actually try copy_from_user_inatomic(). Being able to > directly access userspace would make the whole deal a lot easier again.
Careful! There is one magic piece of state that you need to save-and-restore if you do this, namely %cr2. Taking a page fault always writes to %cr2, and we must *not* corrupt it in the NMI handler.
Also, right now, it looks like we call notify_page_fault() in the atomic page fault case, and that would be deadly from within an NMI.
But if you move the "in_atomic()" check earlier in __do_page_fault(), you can *try* to do something like this:
unsigned long copy_from_user_nmi(void *to, const void __user *from, unsigned long n) { unsigned long cr2, flags,ret;
if (__range_not_ok(from, n, TASK_SIZE)) return 0; local_irq_save(flags); cr2 = read_cr2(); ret = __copy_from_user_inatomic(to, from, n); /* Reading cr2 is likely much faster than writing it - but go check this.. */ if (cr2 != read_cr2()) write_cr2(cr2); local_irq_restore(flags); return n - ret; }
or something close to that. But you absolutely *have* to save/restore %cr2 (the above tries to avoid writing it if it didn't change, somebody should check the timings on that to see whether it makes sense or not).
Linus
| |