linux/arch/x86/mm
Ingo Molnar 5dfaf90f80 x86: mm: Read cr2 before prefetching the mmap_lock
Prefetch instructions can generate spurious faults on certain
models of older CPUs. The faults themselves cannot be stopped
and they can occur pretty much anywhere - so the way we solve
them is that we detect certain patterns and ignore the fault.

There is one small path of code where we must not take faults
though: the #PF handler execution leading up to the reading
of the CR2 (the faulting address). If we take a fault there
then we destroy the CR2 value (with that of the prefetching
instruction's) and possibly mishandle user-space or
kernel-space pagefaults.

It turns out that in current upstream we do exactly that:

	prefetchw(&mm->mmap_sem);

	/* Get the faulting address: */
	address = read_cr2();

This is not good.

So turn around the order: first read the cr2 then prefetch
the lock address. Reading cr2 is plenty fast (2 cycles) so
delaying the prefetch by this amount shouldnt be a big issue
performance-wise.

[ And this might explain a mystery fault.c warning that sometimes
  occurs on one an old AMD/Semptron based test-system i have -
  which does have such prefetch problems. ]

Cc: Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Cc: Vegard Nossum <vegard.nossum@gmail.com>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
LKML-Reference: <20090616030522.GA22162@Krystal>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-06-16 10:23:32 +02:00
..
dump_pagetables.c x86: remove (null) in /sys kernel_page_tables 2009-04-14 11:50:22 +02:00
extable.c x86: uaccess: introduce try and catch framework 2009-01-23 17:17:36 -08:00
fault.c x86: mm: Read cr2 before prefetching the mmap_lock 2009-06-16 10:23:32 +02:00
gup.c x86: Document get_user_pages_fast() 2009-04-10 13:14:08 +02:00
highmem_32.c Merge commit 'origin/master' into for-linus/xen/master 2009-04-07 13:34:16 -07:00
hugetlbpage.c x86: ignore VM_LOCKED when determining if hugetlb-backed page tables can be shared or not 2009-05-29 08:40:03 -07:00
init_32.c x86: make sparse mem work in non-NUMA mode 2009-05-12 11:26:35 +02:00
init_64.c x86: change kernel_physical_mapping_init() __init to __meminit 2009-06-12 14:39:21 +02:00
init.c Merge branch 'x86-mm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip 2009-06-10 16:13:20 -07:00
iomap_32.c Merge commit 'origin/master' into for-linus/xen/master 2009-04-07 13:34:16 -07:00
ioremap.c Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip 2009-04-17 09:56:11 -07:00
k8topology_64.c x86: k8 numa register active regions later 2009-01-06 13:21:21 +01:00
kmmio.c Merge branch 'linus' into tracing/core 2009-05-07 11:17:34 +02:00
Makefile x86: unify 32 and 64-bit node_to_cpumask_map 2009-03-13 14:49:52 +10:30
memtest.c x86: memtest: use pointers of equal type for comparison 2009-06-11 16:26:35 +02:00
mmap.c x86: update copyrights 2009-01-31 04:21:18 +01:00
mmio-mod.c tracing: x86, mmiotrace: only register for die notifier when tracer active 2009-04-29 11:33:34 +02:00
numa_32.c x86: mm/numa_32.c calculate_numa_remap_pages should use __init 2009-04-17 22:43:13 +02:00
numa_64.c x86, mm: Fix node_possible_map logic 2009-05-18 09:21:04 +02:00
numa.c cpumask: convert node_to_cpumask_map[] to cpumask_var_t 2009-03-13 14:35:31 +01:00
pageattr-test.c x86: make sure the CPA test code's use of _PAGE_UNUSED1 is obvious 2008-09-05 17:09:57 +02:00
pageattr.c Merge branch 'x86-xen-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip 2009-06-10 16:16:27 -07:00
pat.c Merge branch 'x86-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip 2009-04-17 09:56:11 -07:00
pf_in.c x86: fix mmiotrace 8-bit register decoding 2008-10-14 10:33:50 +02:00
pf_in.h x86 mmiotrace: move files into arch/x86/mm/. 2008-05-24 11:25:37 +02:00
pgtable_32.c x86/32: no need to use set_pte_present in set_pte_vaddr 2009-03-19 14:04:18 +01:00
pgtable.c x86: fix set_fixmap to use phys_addr_t 2009-04-10 20:27:13 +02:00
srat_32.c x86: Fix a typo in a printk message 2009-05-06 12:23:12 +02:00
srat_64.c x86, mm: Fix node_possible_map logic 2009-05-18 09:21:04 +02:00
testmmiotrace.c x86: add far read test to testmmiotrace 2009-03-02 10:20:35 +01:00
tlb.c x86: add x2apic_wrmsr_fence() to x2apic flush tlb paths 2009-03-18 09:36:14 +01:00