Adapt new vmm to 5-level paging as well
This commit is contained in:
parent
0c7e08d3c7
commit
1ccf8e34bc
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
);
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user