Add a more proper 64-bit vmm
This commit is contained in:
parent
9802c8d36e
commit
0c7e08d3c7
|
@ -65,6 +65,10 @@ void *balloc_aligned(size_t count, size_t alignment) {
|
|||
if (new_base >= BUMP_ALLOCATOR_LIMIT)
|
||||
panic("Memory allocation failed");
|
||||
bump_allocator_base = new_base;
|
||||
|
||||
// Zero out allocated space
|
||||
memset(ret, 0, count);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <mm/vmm64.h>
|
||||
#include <lib/blib.h>
|
||||
|
||||
#define PT_SIZE ((uint64_t)0x1000)
|
||||
|
||||
typedef uint64_t pt_entry_t;
|
||||
|
||||
static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) {
|
||||
pt_entry_t *ret;
|
||||
|
||||
if (current_level[entry] & 0x1) {
|
||||
// Present flag set
|
||||
ret = (pt_entry_t *)(current_level[entry] & ~((pt_entry_t)0xfff));
|
||||
} else {
|
||||
// Allocate a table for the next level
|
||||
ret = balloc_aligned(PT_SIZE, PT_SIZE);
|
||||
// Present + writable + user (0b111)
|
||||
current_level[entry] = (pt_entry_t)ret | 0b111;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
pagemap_t new_pagemap(void) {
|
||||
return (pagemap_t)(size_t)balloc_aligned(PT_SIZE, PT_SIZE);
|
||||
}
|
||||
|
||||
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 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);
|
||||
|
||||
// Set the entry as present and point it to the passed physical address
|
||||
// Also set the specified flags
|
||||
// We only use 2MiB pages else we would not have enough space
|
||||
pml2[pml2_entry] = (pt_entry_t)(phys_addr | flags | (1 << 7));
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef __MM__VMM64_H__
|
||||
#define __MM__VMM64_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PAGE_SIZE ((uint64_t)0x200000)
|
||||
|
||||
typedef uint64_t pagemap_t;
|
||||
|
||||
pagemap_t new_pagemap(void);
|
||||
void map_page(pagemap_t pagemap, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags);
|
||||
|
||||
#endif
|
|
@ -16,6 +16,7 @@
|
|||
#include <drivers/pic.h>
|
||||
#include <fs/file.h>
|
||||
#include <lib/asm.h>
|
||||
#include <mm/vmm64.h>
|
||||
|
||||
struct stivale_header {
|
||||
uint64_t stack;
|
||||
|
@ -304,35 +305,20 @@ __attribute__((noreturn)) void stivale_spinup(int bits, bool level5pg,
|
|||
for (size_t i = 0; i < 512 * 4; i++)
|
||||
(&pagemap->pml2_0gb[0])[i] = (i * 0x200000) | 0x03 | (1 << 7);
|
||||
} else {
|
||||
struct pagemap {
|
||||
uint64_t pml4[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_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;
|
||||
|
||||
// zero out the pagemap
|
||||
for (uint64_t *p = (uint64_t *)pagemap; p < &pagemap->pml3_hi[512]; p++)
|
||||
*p = 0;
|
||||
|
||||
pagemap->pml4[511] = (uint64_t)(size_t)pagemap->pml3_hi | 0x03;
|
||||
pagemap->pml4[256] = (uint64_t)(size_t)pagemap->pml3_lo | 0x03;
|
||||
pagemap->pml4[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);
|
||||
}
|
||||
|
||||
ASM(
|
||||
|
|
Loading…
Reference in New Issue