Adapt new vmm to 5-level paging as well

This commit is contained in:
mintsuki 2020-09-11 14:09:15 +02:00
parent 0c7e08d3c7
commit 1ccf8e34bc
4 changed files with 44 additions and 56 deletions

View File

@ -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

View File

@ -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

View File

@ -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;
pagemap_t pagemap = new_pagemap(level5pg ? 5 : 4);
// zero out the pagemap
for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
*p = 0;
// Map 0 to 2GiB at 0xffffffff80000000
for (uint64_t i = 0; i < 0x80000000; i += PAGE_SIZE) {
map_page(pagemap, i + 0xffffffff80000000, i, 0x03);
}
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);
}
// 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);
}
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"
);

View File

@ -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