:: commit 57496ad0c73f596a2cdb6324d9d0100c84ad3bc5

mintsuki <mintsuki@protonmail.com> — 2021-01-03 01:43

parents: b63fad768a

stivale2: Implement MTRR Write Combining Framebuffer tag

diff --git a/STIVALE2.md b/STIVALE2.md
index 80963407..4575a204 100644
--- a/STIVALE2.md
+++ b/STIVALE2.md
@@ -210,6 +210,22 @@ struct stivale2_header_tag_framebuffer {
 } __attribute__((packed));
 ```
 
+#### Framebuffer MTRR write-combining header tag
+
+The presence of this tag tells the bootloader to, in case a framebuffer was
+requested, make that framebuffer's caching type write-combining using x86's
+MTRR model specific registers. This caching type helps speed up framebuffer writes
+on real hardware.
+
+It is recommended to use this tag in conjunction with the SMP tag in order to
+let the bootloader make the MTRR settings uniform across all CPUs.
+
+If no framebuffer was requested, this tag has no effect.
+
+Identifier: `0x4c7bb07731282e00`
+
+This tag does not have extra members.
+
 #### 5-level paging header tag
 
 The presence of this tag enables support for 5-level paging, if available.
@@ -345,6 +361,15 @@ struct stivale2_struct_tag_framebuffer {
 } __attribute__((packed));
 ```
 
+#### Framebuffer MTRR write-combining structure tag
+
+This tag exists if MTRR write-combining for the framebuffer was requested and
+successfully enabled.
+
+Identifier: `0x6bc1a78ebe871172`
+
+This tag does not have extra members.
+
 #### Modules structure tag
 
 This tag lists modules that the bootloader loaded alongside the kernel, if any.
diff --git a/limine-pxe.bin b/limine-pxe.bin
index 85cd4f51..4f668ce8 100644
Binary files a/limine-pxe.bin and b/limine-pxe.bin differ
diff --git a/limine.bin b/limine.bin
index 57c90ebf..9efcbd52 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2.map b/stage2.map
index 2e36b35d..c01d4271 100644
Binary files a/stage2.map and b/stage2.map differ
diff --git a/stage2/protos/stivale2.c b/stage2/protos/stivale2.c
index 8532f23a..6f354ff1 100644
--- a/stage2/protos/stivale2.c
+++ b/stage2/protos/stivale2.c
@@ -21,6 +21,7 @@
 #include <sys/lapic.h>
 #include <fs/file.h>
 #include <mm/pmm.h>
+#include <mm/mtrr.h>
 #include <stivale/stivale2.h>
 #include <pxe/tftp.h>
 
@@ -274,6 +275,19 @@ void stivale2_load(char *config, char *cmdline, bool pxe) {
             tag->blue_mask_shift    = fbinfo.blue_mask_shift;
 
             append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
+
+            if (get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_FB_MTRR_ID) != NULL) {
+                mtrr_restore();
+                bool ret = mtrr_set_range(tag->framebuffer_addr,
+                    (uint64_t)tag->framebuffer_pitch * tag->framebuffer_height,
+                    MTRR_MEMORY_TYPE_WC);
+                if (ret) {
+                    struct stivale2_tag *tag = ext_mem_alloc(sizeof(struct stivale2_tag));
+                    tag->identifier = STIVALE2_STRUCT_TAG_FB_MTRR_ID;
+                    append_tag(&stivale2_struct, (struct stivale2_tag *)tag);
+                }
+                mtrr_save();
+            }
         }
     }
     }
@@ -289,6 +303,8 @@ void stivale2_load(char *config, char *cmdline, bool pxe) {
     // Create SMP struct tag
     //////////////////////////////////////////////
     {
+    mtrr_restore();
+
     struct stivale2_header_tag_smp *smp_hdr_tag = get_tag(&stivale2_hdr, STIVALE2_HEADER_TAG_SMP_ID);
     if (smp_hdr_tag != NULL) {
         struct stivale2_struct_tag_smp *tag;
diff --git a/stage2/sys/smp_trampoline.asm b/stage2/sys/smp_trampoline.asm
index 2cf7ed60..06c6558d 100644
--- a/stage2/sys/smp_trampoline.asm
+++ b/stage2/sys/smp_trampoline.asm
@@ -3,6 +3,14 @@ extern smp_tpl_booted_flag
 extern smp_tpl_pagemap
 extern smp_tpl_target_mode
 
+extern mtrr_restore
+
+section .bss
+
+temp_stack:
+    resb 1024
+  .top:
+
 section .realmode
 
 global smp_trampoline
@@ -46,6 +54,10 @@ smp_trampoline:
     wrmsr
 
   .nox2apic:
+    mov esp, temp_stack.top
+
+    call mtrr_restore
+
     test dword [smp_tpl_target_mode], (1 << 0)
     jz parking32
 
diff --git a/stivale/stivale2.h b/stivale/stivale2.h
index 4086c7da..df1e6ba5 100644
--- a/stivale/stivale2.h
+++ b/stivale/stivale2.h
@@ -20,6 +20,8 @@ struct stivale2_header {
 
 #define STIVALE2_HEADER_TAG_FRAMEBUFFER_ID 0x3ecc1bc43d0f7971
 
+#define STIVALE2_HEADER_TAG_FB_MTRR_ID 0x4c7bb07731282e00
+
 struct stivale2_header_tag_framebuffer {
     struct stivale2_tag tag;
     uint16_t framebuffer_width;
@@ -103,6 +105,8 @@ struct stivale2_struct_tag_framebuffer {
     uint8_t  blue_mask_shift;
 } __attribute__((packed));
 
+#define STIVALE2_STRUCT_TAG_FB_MTRR_ID 0x6bc1a78ebe871172
+
 #define STIVALE2_STRUCT_TAG_MODULES_ID 0x4b6fe466aade04ce
 
 struct stivale2_module {
diff --git a/test/stivale2.c b/test/stivale2.c
index 609e9e48..6932227b 100644
--- a/test/stivale2.c
+++ b/test/stivale2.c
@@ -15,10 +15,15 @@ struct stivale2_header_tag_smp smp_request = {
     .flags = 0
 };
 
+struct stivale2_tag fb_mtrr_request = {
+    .identifier = STIVALE2_HEADER_TAG_FB_MTRR_ID,
+    .next       = (uint64_t)&smp_request
+};
+
 struct stivale2_header_tag_framebuffer framebuffer_request = {
     .tag = {
         .identifier = STIVALE2_HEADER_TAG_FRAMEBUFFER_ID,
-        .next       = (uint64_t)&smp_request
+        .next       = (uint64_t)&fb_mtrr_request
     },
     .framebuffer_width  = 0,
     .framebuffer_height = 0,
@@ -82,6 +87,11 @@ void stivale2_main(struct stivale2_struct *info) {
                 e9_printf("\tBlue mask size:  %d", f->blue_mask_shift);
                 break;
             }
+            case STIVALE2_STRUCT_TAG_FB_MTRR_ID: {
+                e9_puts("Framebuffer WC MTRR tag:");
+                e9_puts("\tFramebuffer WC MTRR enabled");
+                break;
+            }
             case STIVALE2_STRUCT_TAG_MODULES_ID: {
                 struct stivale2_struct_tag_modules *m = (struct stivale2_struct_tag_modules *)tag;
                 e9_puts("Modules tag:");
tab: 248 wrap: offon