kvm, x86: Properly check whether a pfn is an MMIO or not
authorKarimAllah Ahmed <karahmed@amazon.de>
Thu, 31 Jan 2019 20:24:44 +0000 (21:24 +0100)
committerPaolo Bonzini <pbonzini@redhat.com>
Tue, 30 Apr 2019 19:49:46 +0000 (21:49 +0200)
pfn_valid check is not sufficient because it only checks if a page has a struct
page or not, if "mem=" was passed to the kernel some valid pages won't have a
struct page. This means that if guests were assigned valid memory that lies
after the mem= boundary it will be passed uncached to the guest no matter what
the guest caching attributes are for this memory.

Introduce a new function e820__mapped_raw_any which is equivalent to
e820__mapped_any but uses the original e820 unmodified and use it to
identify real *RAM*.

Signed-off-by: KarimAllah Ahmed <karahmed@amazon.de>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/include/asm/e820/api.h
arch/x86/kernel/e820.c
arch/x86/kvm/mmu.c

index 62be73b23d5cd89b778c791da28eb311e739abb9..e8f58ddd06d97fbce6ef1f701f9f91766ef2847d 100644 (file)
@@ -10,6 +10,7 @@ extern struct e820_table *e820_table_firmware;
 
 extern unsigned long pci_mem_start;
 
+extern bool e820__mapped_raw_any(u64 start, u64 end, enum e820_type type);
 extern bool e820__mapped_any(u64 start, u64 end, enum e820_type type);
 extern bool e820__mapped_all(u64 start, u64 end, enum e820_type type);
 
index 2879e234e1936f76e59383d56ee5c26b58ce6b53..76dd605ee2a38f78137c1f94c66d9e4f1d0d9171 100644 (file)
@@ -73,12 +73,13 @@ EXPORT_SYMBOL(pci_mem_start);
  * This function checks if any part of the range <start,end> is mapped
  * with type.
  */
-bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
+static bool _e820__mapped_any(struct e820_table *table,
+                             u64 start, u64 end, enum e820_type type)
 {
        int i;
 
-       for (i = 0; i < e820_table->nr_entries; i++) {
-               struct e820_entry *entry = &e820_table->entries[i];
+       for (i = 0; i < table->nr_entries; i++) {
+               struct e820_entry *entry = &table->entries[i];
 
                if (type && entry->type != type)
                        continue;
@@ -88,6 +89,17 @@ bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
        }
        return 0;
 }
+
+bool e820__mapped_raw_any(u64 start, u64 end, enum e820_type type)
+{
+       return _e820__mapped_any(e820_table_firmware, start, end, type);
+}
+EXPORT_SYMBOL_GPL(e820__mapped_raw_any);
+
+bool e820__mapped_any(u64 start, u64 end, enum e820_type type)
+{
+       return _e820__mapped_any(e820_table, start, end, type);
+}
 EXPORT_SYMBOL_GPL(e820__mapped_any);
 
 /*
index e10962dfc2032d982f124070b88f7d625d2b8f0b..b1f6451022e546d9aab51ce6d207a54e36271101 100644 (file)
@@ -44,6 +44,7 @@
 #include <asm/page.h>
 #include <asm/pat.h>
 #include <asm/cmpxchg.h>
+#include <asm/e820/api.h>
 #include <asm/io.h>
 #include <asm/vmx.h>
 #include <asm/kvm_page_track.h>
@@ -2892,7 +2893,9 @@ static bool kvm_is_mmio_pfn(kvm_pfn_t pfn)
                         */
                        (!pat_enabled() || pat_pfn_immune_to_uc_mtrr(pfn));
 
-       return true;
+       return !e820__mapped_raw_any(pfn_to_hpa(pfn),
+                                    pfn_to_hpa(pfn + 1) - 1,
+                                    E820_TYPE_RAM);
 }
 
 /* Bits which may be returned by set_spte() */