mm/vmm: Complement 704dd7ee250d5c9b1b7974fe2aa140abbd3a3d77 by not using WC caching on PTEs if not supported
diff --git a/PROTOCOL.md b/PROTOCOL.md
index 96e12cb4..6efcaa96 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -205,7 +205,7 @@ segments mapped using write-back (WB) caching at the page tables level.
All HHDM and identity map memory regions are mapped using write-back (WB) caching at the page
tables level, except framebuffer regions which are mapped using write-combining
-(WC) caching at the page tables level.
+(WC) caching at the page tables level (if the CPU support the PAT, see below).
If the CPU supports the PAT (Page Attribute Table), its layout is specified to be as follows:
```
diff --git a/common/mm/vmm.c b/common/mm/vmm.c
index 80d23312..8adacae2 100644
--- a/common/mm/vmm.c
+++ b/common/mm/vmm.c
@@ -76,7 +76,19 @@ void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_
pt_entry_t *pml5, *pml4, *pml3, *pml2, *pml1;
+ static bool pat_supported = false, pat_supported_got = false;
+ if (!pat_supported_got) {
+ uint32_t eax, ebx, ecx, edx;
+ if (cpuid(1, 0, &eax, &ebx, &ecx, &edx) && (edx & (1 << 16))) {
+ pat_supported = true;
+ }
+ pat_supported_got = true;
+ }
+
flags |= PT_FLAG_VALID; // Always present
+ if ((flags & VMM_FLAG_FB) && !pat_supported) {
+ flags &= ~(uint64_t)VMM_FLAG_FB;
+ }
// Paging levels
switch (pagemap.levels) {
