:: commit f3ea5c7ab3cab30182b359e9a36485457021b0e0

mintsuki <mintsuki@protonmail.com> — 2023-08-08 18:47

parents: 917c1b5530

limine: Set up framebuffer caching as WC

diff --git a/PROTOCOL.md b/PROTOCOL.md
index ee31d678..edf1bcb7 100644
--- a/PROTOCOL.md
+++ b/PROTOCOL.md
@@ -100,9 +100,7 @@ that every usable, bootloader reclaimable, framebuffer, or kernel/modules
 memory map region is mapped at HHDM offset + its physical address.
 Additionally, the whole 0->4GiB physical memory region will also be mapped
 at HHDM offset + physical address, regardless of the contents of the
-memory map.
-These mappings are supervisor, read, write, execute (-rwx), and they use
-WB caching (on x86_64).
+memory map. These mappings are supervisor, read, write, execute (-rwx).
 
 The bootloader page tables are in bootloader-reclaimable memory (see Memory Map
 feature below), and their specific layout is undefined as long as they provide
@@ -112,6 +110,18 @@ If the kernel is a position independent executable, the bootloader is free to
 relocate it as it sees fit, potentially performing KASLR (as specified by the
 config).
 
+## Caching
+
+### x86_64
+
+All HHDM memory regions are mapped using write-back (WB) caching, except
+framebuffer regions which are mapped using write-combining (WC) caching.
+
+The MTRRs are left as the firmware set them up.
+
+The PAT's (Page Attribute Table) layout is unspecified and the OS should
+not be making assumptions about it.
+
 ## Entry machine state
 
 ### x86_64
diff --git a/common/mm/vmm.c b/common/mm/vmm.c
index b46dba2e..b4db155d 100644
--- a/common/mm/vmm.c
+++ b/common/mm/vmm.c
@@ -119,6 +119,12 @@ level4:
 
     pml1 = get_next_level(pagemap, pml2, virt_addr, pg_size, 1, pml2_entry);
 
+    // PML1 wants PAT bit at 7 instead of 12
+    if (flags & ((uint64_t)1 << 12)) {
+        flags &= ~((uint64_t)1 << 12);
+        flags |= ((uint64_t)1 << 7);
+    }
+
     pml1[pml1_entry] = (pt_entry_t)(phys_addr | flags);
 }
 
diff --git a/common/mm/vmm.h b/common/mm/vmm.h
index eac31001..20bd5765 100644
--- a/common/mm/vmm.h
+++ b/common/mm/vmm.h
@@ -8,7 +8,7 @@
 
 #define VMM_FLAG_WRITE   ((uint64_t)1 << 1)
 #define VMM_FLAG_NOEXEC  ((uint64_t)1 << 63)
-#define VMM_FLAG_FB      ((uint64_t)0)
+#define VMM_FLAG_FB      (((uint64_t)1 << 3) | ((uint64_t)1 << 12))
 
 #define VMM_MAX_LEVEL 3
 
diff --git a/common/protos/limine.c b/common/protos/limine.c
index dd8ec18b..28a6ccba 100644
--- a/common/protos/limine.c
+++ b/common/protos/limine.c
@@ -1080,6 +1080,12 @@ FEAT_END
     rm_int(0x15, &r, &r);
 #endif
 
+    // Enable PAT (write-combining/write-protect)
+    uint64_t pat = rdmsr(0x277);
+    pat &= 0xffffffff;
+    pat |= (uint64_t)0x0105 << 32;
+    wrmsr(0x277, pat);
+
     pic_mask_all();
     io_apic_mask_all();
 
tab: 248 wrap: offon