Adapt new vmm to 5-level paging as well
diff --git a/src/mm/vmm64.c b/src/mm/vmm64.c
index 78e0ad4b..644a59b4 100644
--- a/src/mm/vmm64.c
+++ b/src/mm/vmm64.c
@@ -23,19 +23,35 @@ static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) {
return ret;
}
-pagemap_t new_pagemap(void) {
- return (pagemap_t)(size_t)balloc_aligned(PT_SIZE, PT_SIZE);
+pagemap_t new_pagemap(int lv) {
+ pagemap_t pagemap;
+ pagemap.levels = lv;
+ pagemap.top_level = balloc_aligned(PT_SIZE, PT_SIZE);
+ return pagemap;
}
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags) {
// Calculate the indices in the various tables using the virtual address
+ size_t pml5_entry = (virt_addr & ((uint64_t)0x1ff << 48)) >> 48;
size_t pml4_entry = (virt_addr & ((uint64_t)0x1ff << 39)) >> 39;
size_t pml3_entry = (virt_addr & ((uint64_t)0x1ff << 30)) >> 30;
size_t pml2_entry = (virt_addr & ((uint64_t)0x1ff << 21)) >> 21;
- pt_entry_t *pml4 = (pt_entry_t *)(size_t)pagemap;
- pt_entry_t *pml3 = get_next_level(pml4, pml4_entry);
- pt_entry_t *pml2 = get_next_level(pml3, pml3_entry);
+ pt_entry_t *pml5, *pml4, *pml3, *pml2;
+
+ // Paging levels
+ switch (pagemap.levels) {
+ case 5:
+ pml5 = pagemap.top_level;
+ pml4 = get_next_level(pml5, pml5_entry);
+ break;
+ case 4:
+ pml4 = pagemap.top_level;
+ break;
+ }
+
+ pml3 = get_next_level(pml4, pml4_entry);
+ pml2 = get_next_level(pml3, pml3_entry);
// Set the entry as present and point it to the passed physical address
// Also set the specified flags
diff --git a/src/mm/vmm64.h b/src/mm/vmm64.h
index 7e63f58e..a42511fc 100644
--- a/src/mm/vmm64.h
+++ b/src/mm/vmm64.h
@@ -5,9 +5,12 @@
#define PAGE_SIZE ((uint64_t)0x200000)
-typedef uint64_t pagemap_t;
+typedef struct {
+ int levels;
+ void *top_level;
+} pagemap_t;
-pagemap_t new_pagemap(void);
+pagemap_t new_pagemap(int lv);
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags);
#endif
diff --git a/src/protos/stivale.c b/src/protos/stivale.c
index beb8461e..b0583ff8 100644
--- a/src/protos/stivale.c
+++ b/src/protos/stivale.c
@@ -262,7 +262,6 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
pic_flush();
if (bits == 64) {
- void *pagemap_ptr;
if (level5pg) {
// Enable CR4.LA57
ASM(
@@ -270,55 +269,19 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
"bts eax, 12\n\t"
"mov cr4, eax\n\t", :: "eax", "memory"
);
+ }
- struct pagemap {
- uint64_t pml5[512];
- uint64_t pml4_lo[512];
- uint64_t pml4_hi[512];
- uint64_t pml3_lo[512];
- uint64_t pml3_hi[512];
- uint64_t pml2_0gb[512];
- uint64_t pml2_1gb[512];
- uint64_t pml2_2gb[512];
- uint64_t pml2_3gb[512];
- };
- struct pagemap *pagemap = balloc_aligned(sizeof(struct pagemap), 0x1000);
- pagemap_ptr = (void *)pagemap;
-
- // zero out the pagemap
- for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
- *p = 0;
-
- pagemap->pml5[511] = (uint64_t)(size_t)pagemap->pml4_hi | 0x03;
- pagemap->pml5[0] = (uint64_t)(size_t)pagemap->pml4_lo | 0x03;
- pagemap->pml4_hi[511] = (uint64_t)(size_t)pagemap->pml3_hi | 0x03;
- pagemap->pml4_hi[256] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
- pagemap->pml4_lo[0] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
- pagemap->pml3_hi[510] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
- pagemap->pml3_hi[511] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
- pagemap->pml3_lo[0] = (uint64_t)(size_t)pagemap->pml2_0gb | 0x03;
- pagemap->pml3_lo[1] = (uint64_t)(size_t)pagemap->pml2_1gb | 0x03;
- pagemap->pml3_lo[2] = (uint64_t)(size_t)pagemap->pml2_2gb | 0x03;
- pagemap->pml3_lo[3] = (uint64_t)(size_t)pagemap->pml2_3gb | 0x03;
-
- // populate the page directories
- for (size_t i = 0; i < 512 * 4; i++)
- (&pagemap->pml2_0gb[0])[i] = (i * 0x200000) | 0x03 | (1 << 7);
- } else {
- pagemap_t pagemap = new_pagemap();
-
- // Map 0 to 2GiB at 0xffffffff80000000
- for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) {
- map_page(pagemap, i + 0xffffffff80000000, i, 0x03);
- }
+ pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
- // Map 0 to 4GiB at 0xffff800000000000 and 0
- for (uint64_t i = 0; i < 0x100000000; i += PAGE_SIZE) {
- map_page(pagemap, i, i, 0x03);
- map_page(pagemap, i + 0xffff800000000000, i, 0x03);
- }
+ // Map 0 to 2GiB at 0xffffffff80000000
+ for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) {
+ map_page(pagemap, i + 0xffffffff80000000, i, 0x03);
+ }
- pagemap_ptr = (void *)pagemap;
+ // Map 0 to 4GiB at 0xffff800000000000 and 0
+ for (uint64_t i = 0; i < 0x100000000; i += PAGE_SIZE) {
+ map_page(pagemap, i, i, 0x03);
+ map_page(pagemap, i + 0xffff800000000000, i, 0x03);
}
ASM(
@@ -367,7 +330,7 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
"iretq\n\t"
".code32\n\t",
- : "a" (pagemap_ptr), "b" (&entry_point),
+ : "a" (pagemap.top_level), "b" (&entry_point),
"D" (stivale_struct), "S" (&stack)
: "memory"
);
diff --git a/test/test.asm b/test/test.asm
index 0d2aff6a..1596b2a3 100644
--- a/test/test.asm
+++ b/test/test.asm
@@ -7,7 +7,13 @@ stivale_header:
dq 0 ; entry point
dq stack.top ; rsp
dq 0 ; flags
- dq 0 ; tags
+ dq lv5 ; tags
+
+section .rodata
+
+lv5:
+ dq 0x932f477032007e8f
+ dq 0
section .bss
