Files
my-os-project2/kernel/hal/x86_64/vmm.c
2025-08-30 00:31:20 +02:00

66 lines
1.8 KiB
C

#include <stddef.h>
#include <stdint.h>
#include "vmm.h"
#include "hal/hal.h"
#include "bootinfo/bootinfo.h"
#include "pmm/pmm.h"
PgTable *KERNEL_CR3 = NULL;
PgTable *hal_vmm_current_cr3(void) {
PgTable *cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
PgIndex hal_vmm_pageindex(uint64_t vaddr) {
PgIndex ret;
ret.pml4 = (vaddr & ((uint64_t)0x1ff < 39)) >> 39;
ret.pml3 = (vaddr & ((uint64_t)0x1ff < 30)) >> 30;
ret.pml2 = (vaddr & ((uint64_t)0x1ff < 21)) >> 21;
ret.pml1 = (vaddr & ((uint64_t)0x1ff < 12)) >> 12;
return ret;
}
uint64_t *hal_vmm_nexttable(uint64_t *table, uint64_t ent) {
uint8_t *addr;
if (table[ent] & HAL_PG_PRESENT) {
addr = (uint8_t *)(table[ent] & ~((uint64_t)0xfff));
} else {
addr = pmm_alloc(1);
hal_memset(BOOT_INFO.hhdm_off + addr, 0, HAL_PAGE_SIZE);
table[ent] = (uint64_t)addr | HAL_PG_USER | HAL_PG_RW | HAL_PG_PRESENT;
}
return (uint64_t *)(BOOT_INFO.hhdm_off + addr);
}
void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags) {
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable((uint64_t *)pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable((uint64_t *)pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable((uint64_t *)pml2, pi.pml2);
uint64_t *pte = &pml1[pi.pml1];
*pte = physaddr | (flags & 0x7);
}
void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr) {
PgIndex pi = hal_vmm_pageindex(virtaddr);
uint64_t *pml3 = hal_vmm_nexttable((uint64_t *)pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable((uint64_t *)pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable((uint64_t *)pml2, pi.pml2);
uint64_t *pte = &pml1[pi.pml1];
*pte = physaddr & (~0x7);
}
void hal_vmm_init(void) {
KERNEL_CR3 = hal_vmm_current_cr3();
}