refactor AddressSpace to be a class

This commit is contained in:
2023-10-25 13:37:26 +02:00
parent bb62a3bbab
commit 6be61b5734
5 changed files with 63 additions and 51 deletions

View File

@@ -1,5 +1,6 @@
#include <cstddef>
#include <cstdint>
#include <new>
#include "gdt.hpp"
#include "globals.hpp"
@@ -13,7 +14,11 @@
#include "paging.hpp"
#include "serial.hpp"
struct AddressSpace BOOT_AddressSpace;
AddressSpace *BOOT_AddressSpace;
alignas(AddressSpace) char BOOT_AddressSpace_storage[sizeof(AddressSpace)];
AddressSpace *KERN_AddressSpace;
alignas(AddressSpace) char KERN_AddressSpace_storage[sizeof(AddressSpace)];
extern void kmain();
@@ -42,27 +47,28 @@ extern "C" void _start(void) {
barrier();
map_hddm(get_cr3());
barrier();
BOOT_AddressSpace.PML4 = (uint64_t *) HHDM_P2V(get_cr3());
new (BOOT_AddressSpace_storage) AddressSpace((uint64_t *) HHDM_P2V(get_cr3()));
BOOT_AddressSpace = reinterpret_cast<AddressSpace *>(BOOT_AddressSpace_storage);
limine_fb_save_response(&BOOT_AddressSpace);
limine_fb_save_response(BOOT_AddressSpace);
limine_mm_save_response();
parse_limine_memmap(limine_mm_entries, limine_mm_count, LIMINE_MEMMAP_USABLE);
KERN_AddressSpace = static_cast<AddressSpace *>(get4k());
assert2(!init_addr_space(KERN_AddressSpace), "Couldn't init kernel address space!");
uint64_t *KERN_AddressSpace_PML4 = static_cast<uint64_t *>(get4k());
for (int i = 0; i < 512; i++)
((struct AddressSpace *) (KERN_AddressSpace))->PML4[i] = 0x02;
KERN_AddressSpace_PML4[i] = 0x02;
map_hddm((uint64_t *) HHDM_V2P(KERN_AddressSpace_PML4));
map_hddm((uint64_t *) HHDM_V2P(((struct AddressSpace *) (KERN_AddressSpace))->PML4));
new (KERN_AddressSpace_storage) AddressSpace(KERN_AddressSpace_PML4);
KERN_AddressSpace = reinterpret_cast<AddressSpace *>(KERN_AddressSpace_storage);
// TODO: Accurate kernel length
for (int i = 0; i < 100000; i++) {
map((void *) (kernel_virt_base + i * 4096), (void *) (kernel_phys_base + i * 4096), PAGE_RW, KERN_AddressSpace);
KERN_AddressSpace->map((void *) (kernel_virt_base + i * 4096), (void *) (kernel_phys_base + i * 4096), PAGE_RW);
}
uint64_t real_new_cr3 = (uint64_t) HHDM_V2P(((struct AddressSpace *) (KERN_AddressSpace))->PML4);
uint64_t real_new_cr3 = (uint64_t) HHDM_V2P(KERN_AddressSpace_PML4);
uint64_t *new_stack_top = &KERN_stack[KERN_STACK_SIZE - 1];// Don't forget in which direction the stack grows...
barrier();

View File

@@ -34,7 +34,7 @@ void init_kern_heap() {
KERN_HeapBegin->len = 4096 - (sizeof(struct HeapEntry));
KERN_HeapBegin->next = NULL;
KERN_HeapBegin->prev = NULL;
map((void *) KERN_HeapVirtBegin, (void *) HHDM_V2P(KERN_HeapBegin), PAGE_RW, KERN_AddressSpace);
KERN_AddressSpace->map((void *) KERN_HeapVirtBegin, (void *) HHDM_V2P(KERN_HeapBegin), PAGE_RW);
KERN_HeapBegin = (struct HeapEntry *) KERN_HeapVirtBegin;
KERN_HeapEnd = (KERN_HeapVirtBegin + 4096);
initialized = true;
@@ -44,7 +44,7 @@ static void extend_heap(size_t n_pages) {
for (size_t i = 0; i < n_pages; i++) {
void *p = get4k();
assert2(p != NULL, "Kernel out of memory!");
map((void *) KERN_HeapEnd, (void *) HHDM_V2P(p), PAGE_RW, KERN_AddressSpace);
KERN_AddressSpace->map((void *) KERN_HeapEnd, (void *) HHDM_V2P(p), PAGE_RW);
KERN_HeapEnd += 4096;
}
allocated.fetch_add(n_pages * 4096);
@@ -263,9 +263,9 @@ static struct HeapEntry *try_shrink_heap(struct HeapEntry *entry) {
assert(((uint64_t) totallen & 0xFFF) == 0);
uint64_t total_pages = totallen / 4096;
for (uint64_t i = 0; i < total_pages; i++) {
free4k((void *) HHDM_P2V(virt2real((void *) (KERN_HeapEnd + 4096 * i), KERN_AddressSpace)));
free4k((void *) HHDM_P2V(KERN_AddressSpace->virt2real((void *) (KERN_HeapEnd + 4096 * i))));
allocated.fetch_sub(4096);
unmap((void *) (KERN_HeapEnd + 4096 * i), KERN_AddressSpace);
KERN_AddressSpace->unmap((void *) (KERN_HeapEnd + 4096 * i));
}
return ret;
}

View File

@@ -19,7 +19,7 @@ struct {
uint64_t len;
} framebufferAddrs[10];
void limine_fb_save_response(struct AddressSpace *boot_address_space) {
void limine_fb_save_response(AddressSpace *boot_address_space) {
if (framebuffer_request.response == NULL || framebuffer_request.response->framebuffer_count < 1) {
framebuffer_count = 0;
return;
@@ -29,17 +29,17 @@ void limine_fb_save_response(struct AddressSpace *boot_address_space) {
if (framebuffer_count >= 10) framebuffer_count = 10;
for (int i = 0; i < framebuffer_count; i++) {
memcpy(&framebuffers[i], framebuffer_request.response->framebuffers[i], sizeof(struct limine_framebuffer));
framebufferAddrs[i].base = virt2real(framebuffers[i].address, boot_address_space);
framebufferAddrs[i].base = boot_address_space->virt2real(framebuffers[i].address);
}
}
void limine_fb_remap(struct AddressSpace *space) {
void limine_fb_remap(AddressSpace *space) {
for (int i = 0; i < framebuffer_count; i++) {
void *base = framebuffers[i].address;
void *realbase = framebufferAddrs[i].base;
// TODO: Proper map
for (int i = 0; i < 100000; i++) {
map(base + i * 4096, realbase + i * 4096, PAGE_RW, space);
space->map(base + i * 4096, realbase + i * 4096, PAGE_RW);
}
}
_tlb_flush();

View File

@@ -8,21 +8,12 @@
#include "misc.hpp"
#include "serial.hpp"
struct AddressSpace *KERN_AddressSpace;
int init_addr_space(struct AddressSpace *space) {
assert2(space != NULL, "Got null!");
space->PML4 = static_cast<uint64_t *>(get4k());
if (space->PML4 == NULL) return 1;
return 0;
}
// Returns a free page frame in HHDM
uint64_t *get_free_frame() {
static uint64_t *get_free_frame() {
uint64_t *res = static_cast<uint64_t *>(get4k());
if (res)
for (int j = 0; j < 512; j++)
res[j] = 0;
assert(res != nullptr);
for (int j = 0; j < 512; j++)
res[j] = 0;
return res;
}
@@ -34,19 +25,30 @@ static inline void invlpg(void *m) {
: "memory");
}
void *virt2real(void *virt, struct AddressSpace *space) {
AddressSpace::AddressSpace() {
PML4 = static_cast<uint64_t *>(get4k());
}
AddressSpace::AddressSpace(uint64_t *PML4) : PML4(PML4) {}
AddressSpace::~AddressSpace() {
// TODO:
free4k(PML4);
}
void *AddressSpace::virt2real(void *virt) {
assert2(((uint64_t) virt & 0xFFF) == 0, "Trying to unmap non-aligned memory!");
// Assuming everything related to paging is HHDM
assert2((uint64_t) space->PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
assert2((uint64_t) space->PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
uint64_t *pml4e = space->PML4 + pml4i;
uint64_t *pml4e = PML4 + pml4i;
if (!((*pml4e) & PAGE_PRESENT)) return 0;
uint64_t *pdpeb = (uint64_t *) HHDM_P2V((*pml4e & 0x000FFFFFFFFFF000ULL));
@@ -68,13 +70,13 @@ void *virt2real(void *virt, struct AddressSpace *space) {
return (void *) (*ptse & 0x000FFFFFFFFFF000ULL);
}
int map(void *virt, void *real, uint32_t flags, struct AddressSpace *space) {
int AddressSpace::map(void *virt, void *real, uint32_t flags) {
assert2(((uint64_t) virt & 0xFFF) == 0, "Trying to map non-aligned memory!");
assert2(((uint64_t) real & 0xFFF) == 0, "Trying to map to non-aligned memory!");
// Assuming everything related to paging is HHDM
assert2((uint64_t) space->PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
assert2((uint64_t) space->PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
@@ -82,7 +84,7 @@ int map(void *virt, void *real, uint32_t flags, struct AddressSpace *space) {
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
uint64_t *pml4e = space->PML4 + pml4i;
uint64_t *pml4e = PML4 + pml4i;
if (!(*pml4e & PAGE_PRESENT)) {
uint64_t *newp = get_free_frame();
@@ -123,19 +125,19 @@ int map(void *virt, void *real, uint32_t flags, struct AddressSpace *space) {
invlpg((void *) ((uint64_t) virt & 0x000FFFFFFFFFF000ULL));
return 1;
}
int unmap(void *virt, struct AddressSpace *space) {
int AddressSpace::unmap(void *virt) {
assert2(((uint64_t) virt & 0xFFF) == 0, "Trying to map non-aligned memory!");
// Assuming everything related to paging is HHDM
assert2((uint64_t) space->PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
assert2((uint64_t) space->PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
assert2((uint64_t) PML4 >= HHDM_BEGIN, "CR3 here must be in HDDM!");
assert2((uint64_t) PML4 < kernel_virt_base, "CR3 here must be in HDDM!");
uint64_t pml4i = (uint64_t) virt >> 39 & 0x01FF;
uint64_t pdpei = (uint64_t) virt >> 30 & 0x01FF;
uint64_t pdei = (uint64_t) virt >> 21 & 0x01FF;
uint64_t ptsi = (uint64_t) virt >> 12 & 0x01FF;
uint64_t *pml4e = space->PML4 + pml4i;
uint64_t *pml4e = PML4 + pml4i;
assert((*pml4e & PAGE_PRESENT));

View File

@@ -8,14 +8,22 @@
#include <stddef.h>
#include <stdint.h>
struct AddressSpace {
class AddressSpace {
public:
AddressSpace();
AddressSpace(uint64_t *PML4);
~AddressSpace();
void *virt2real(void *virt);
int map(void *virt, void *real, uint32_t flags);
int unmap(void *virt);
private:
// Pointer to PML4 in HDDM
uint64_t *PML4;
};
extern struct AddressSpace *KERN_AddressSpace;
int init_addr_space(struct AddressSpace *space);
extern AddressSpace *KERN_AddressSpace;
extern uintptr_t kernel_phys_base;
extern uintptr_t kernel_virt_base;
@@ -34,10 +42,6 @@ void limine_kern_save_response();
#define PAGE_USER (1 << 2)
#define PAGE_PRESENT (0x01ULL)
int map(void *virt, void *real, uint32_t flags, struct AddressSpace *space);
int unmap(void *virt, struct AddressSpace *space);
void *virt2real(void *virt, struct AddressSpace *space);
void map_hddm(uint64_t *pml4);
extern "C" void _tlb_flush();