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:");
