ソースを参照

x86: fix clflush_page_range logic

only present ptes must be flushed.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Ingo Molnar 17 年 前
コミット
4c61afcdb2
2 ファイル変更25 行追加8 行削除
  1. 24 7
      arch/x86/mm/pageattr.c
  2. 1 1
      include/asm-x86/cacheflush.h

+ 24 - 7
arch/x86/mm/pageattr.c

@@ -26,7 +26,6 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  * Flushing functions
  */
 
-
 /**
  * clflush_cache_range - flush a cache range with clflush
  * @addr:	virtual start address
@@ -35,13 +34,19 @@ within(unsigned long addr, unsigned long start, unsigned long end)
  * clflush is an unordered instruction which needs fencing with mfence
  * to avoid ordering issues.
  */
-void clflush_cache_range(void *addr, int size)
+void clflush_cache_range(void *vaddr, unsigned int size)
 {
-	int i;
+	void *vend = vaddr + size - 1;
 
 	mb();
-	for (i = 0; i < size; i += boot_cpu_data.x86_clflush_size)
-		clflush(addr+i);
+
+	for (; vaddr < vend; vaddr += boot_cpu_data.x86_clflush_size)
+		clflush(vaddr);
+	/*
+	 * Flush any possible final partial cacheline:
+	 */
+	clflush(vend);
+
 	mb();
 }
 
@@ -74,9 +79,13 @@ static void __cpa_flush_range(void *arg)
 	__flush_tlb_all();
 }
 
-static void cpa_flush_range(unsigned long addr, int numpages)
+static void cpa_flush_range(unsigned long start, int numpages)
 {
+	unsigned int i, level;
+	unsigned long addr;
+
 	BUG_ON(irqs_disabled());
+	WARN_ON(PAGE_ALIGN(start) != start);
 
 	on_each_cpu(__cpa_flush_range, NULL, 1, 1);
 
@@ -86,7 +95,15 @@ static void cpa_flush_range(unsigned long addr, int numpages)
 	 * will cause all other CPUs to flush the same
 	 * cachelines:
 	 */
-	clflush_cache_range((void *) addr, numpages * PAGE_SIZE);
+	for (i = 0, addr = start; i < numpages; i++, addr += PAGE_SIZE) {
+		pte_t *pte = lookup_address(addr, &level);
+
+		/*
+		 * Only flush present addresses:
+		 */
+		if (pte && pte_present(*pte))
+			clflush_cache_range((void *) addr, PAGE_SIZE);
+	}
 }
 
 /*

+ 1 - 1
include/asm-x86/cacheflush.h

@@ -42,7 +42,7 @@ int set_memory_ro(unsigned long addr, int numpages);
 int set_memory_rw(unsigned long addr, int numpages);
 int set_memory_np(unsigned long addr, int numpages);
 
-void clflush_cache_range(void *addr, int size);
+void clflush_cache_range(void *addr, unsigned int size);
 
 #ifdef CONFIG_DEBUG_RODATA
 void mark_rodata_ro(void);