diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2008-01-30 07:34:08 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-01-30 07:34:08 -0500 |
commit | cd8ddf1a2800026dd58433333cce7a65cbc6c6d2 (patch) | |
tree | 4f741ddde5efa85299e900a24a71f893fc7ed34d /arch/x86/mm | |
parent | af1e6844d60057774910a2d08bd75b67d73ba7d5 (diff) |
x86: clflush_page_range needs mfence
clflush is an unordered operation with respect to other memory
traffic, including other CLFLUSH instructions. This needs proper
fencing with mfence.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/pageattr.c | 12 |
1 files changed, 12 insertions, 0 deletions
diff --git a/arch/x86/mm/pageattr.c b/arch/x86/mm/pageattr.c index cdd2ea2a2239..90b658ac39c2 100644 --- a/arch/x86/mm/pageattr.c +++ b/arch/x86/mm/pageattr.c | |||
@@ -25,12 +25,24 @@ within(unsigned long addr, unsigned long start, unsigned long end) | |||
25 | /* | 25 | /* |
26 | * Flushing functions | 26 | * Flushing functions |
27 | */ | 27 | */ |
28 | |||
29 | |||
30 | /** | ||
31 | * clflush_cache_range - flush a cache range with clflush | ||
32 | * @addr: virtual start address | ||
33 | * @size: number of bytes to flush | ||
34 | * | ||
35 | * clflush is an unordered instruction which needs fencing with mfence | ||
36 | * to avoid ordering issues. | ||
37 | */ | ||
28 | void clflush_cache_range(void *addr, int size) | 38 | void clflush_cache_range(void *addr, int size) |
29 | { | 39 | { |
30 | int i; | 40 | int i; |
31 | 41 | ||
42 | mb(); | ||
32 | for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size) | 43 | for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size) |
33 | clflush(addr+i); | 44 | clflush(addr+i); |
45 | mb(); | ||
34 | } | 46 | } |
35 | 47 | ||
36 | static void __cpa_flush_all(void *arg) | 48 | static void __cpa_flush_all(void *arg) |