This commit is contained in:
2025-09-15 22:35:15 +02:00
parent ce63020b34
commit 0a5523f234
22 changed files with 374 additions and 177 deletions

View File

@ -9,11 +9,11 @@
#include "kprintf.h"
#include "spinlock/spinlock.h"
PgTable *KERNEL_CR3 = NULL;
uint64_t KERNEL_CR3 = 0;
SpinLock spinlock;
PgTable *hal_vmm_current_cr3(void) {
PgTable *cr3;
uint64_t hal_vmm_current_cr3(void) {
uint64_t cr3;
asm volatile("mov %%cr3, %0" : "=r"(cr3));
return cr3;
}
@ -30,92 +30,93 @@ PgIndex hal_vmm_pageindex(uint64_t vaddr) {
}
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));
uint64_t entry = table[ent];
uint64_t phys;
if (entry & HAL_PG_PRESENT) {
phys = entry & ~0xFFFULL;
} 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;
uint8_t *newphys = pmm_alloc(1);
phys = (uint64_t)newphys;
hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE);
table[ent] = phys | HAL_PG_USER | HAL_PG_RW | HAL_PG_PRESENT;
}
return (uint64_t *)(BOOT_INFO.hhdm_off + addr);
return (uint64_t *)((uint8_t *)VIRT(phys));
}
void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags) {
void hal_vmm_map_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr, uint32_t flags) {
uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
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 *pml3 = hal_vmm_nexttable(pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2);
uint64_t *pte = &pml1[pi.pml1];
*pte = (physaddr & ~0xFFF) | (flags & 0x7);
*pte = (physaddr & ~0xFFFULL) | ((uint64_t)flags & 0x7ULL);
}
void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr) {
void hal_vmm_unmap_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr) {
uint64_t *pml4 = (uint64_t *)VIRT(cr3phys);
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 *pml3 = hal_vmm_nexttable(pml4, pi.pml4);
uint64_t *pml2 = hal_vmm_nexttable(pml3, pi.pml3);
uint64_t *pml1 = hal_vmm_nexttable(pml2, pi.pml2);
uint64_t *pte = &pml1[pi.pml1];
*pte &= ~HAL_PG_PRESENT;
}
void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) {
void hal_vmm_map_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size, uint32_t flags) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PAGE_SIZE != 0) {
return;
}
spinlock_acquire(&spinlock);
uint8_t *vaddr = virtstart, *paddr = physstart;
for (; vaddr <= ((uint8_t *)virtstart + size); vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_map_page(cr3, (uint64_t)vaddr, (uint64_t)paddr, flags);
uint8_t *vaddr = (uint8_t *)virtstart;
uint8_t *paddr = (uint8_t *)physstart;
uint8_t *end = (uint8_t *)virtstart + size;
for (; vaddr < end; vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_map_page(cr3phys, (uint64_t)vaddr, (uint64_t)paddr, flags);
}
spinlock_release(&spinlock);
}
void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PG_PRESENT != 0) {
void hal_vmm_unmap_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size) {
if (size % HAL_PAGE_SIZE != 0 || (uint64_t)virtstart % HAL_PAGE_SIZE != 0 || (uint64_t)physstart % HAL_PAGE_SIZE != 0) {
return;
}
spinlock_acquire(&spinlock);
uint8_t *vaddr = virtstart, *paddr = physstart;
uint8_t *vaddr = (uint8_t *)virtstart;
uint8_t *paddr = (uint8_t *)physstart;
uint8_t *end = vaddr + size;
for (; vaddr <= ((uint8_t *)virtstart + size); vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_unmap_page(cr3, (uint64_t)vaddr, (uint64_t)paddr);
for (; vaddr < end; vaddr += HAL_PAGE_SIZE, paddr += HAL_PAGE_SIZE) {
hal_vmm_unmap_page(cr3phys, (uint64_t)vaddr, (uint64_t)paddr);
}
spinlock_release(&spinlock);
}
void hal_vmm_map_kern(PgTable *cr3) {
PgTable *kcr3 = BOOT_INFO.hhdm_off + KERNEL_CR3;
void hal_vmm_map_kern(uint64_t targetcr3) {
uint64_t *kcr3 = (uint64_t *)VIRT(KERNEL_CR3);
uint64_t *cr3 = (uint64_t *)VIRT(targetcr3);
for (size_t i = 256; i < 512; i++) {
cr3->ents[i] = kcr3->ents[i];
cr3[i] = kcr3[i];
}
}
void hal_vmm_switch_pd(PgTable *cr3) {
hal_loadpd(cr3);
}
PgTable *hal_vmm_userproc_pml4(Proc *proc) {
uint8_t *cr3 = pmm_alloc(1);
PgTable *pml4 = (PgTable *)VIRT(cr3);
hal_memset(pml4, 0, HAL_PAGE_SIZE);
PgTable *kcr3 = VIRT(KERNEL_CR3);
uint64_t hal_vmm_userproc_pml4_phys(Proc *proc) {
uint8_t *cr3phys = pmm_alloc(1);
uint64_t phys = (uint64_t)cr3phys;
hal_memset(VIRT(phys), 0, HAL_PAGE_SIZE);
uint64_t *kcr3 = (uint64_t *)VIRT(KERNEL_CR3);
uint64_t *pml4 = (uint64_t *)VIRT(phys);
for (size_t i = 256; i < 512; i++) {
pml4->ents[i] = kcr3->ents[i];
pml4[i] = kcr3[i];
}
return (PgTable *)cr3;
return phys;
}
void hal_vmm_init(void) {

View File

@ -26,10 +26,14 @@ enum {
};
typedef struct {
uint64_t pml4;
uint64_t pml3;
uint64_t pml2;
uint64_t pml1;
uint16_t pml4;
uint16_t pml3;
uint16_t pml2;
uint16_t pml1;
/* uint64_t pml4; */
/* uint64_t pml3; */
/* uint64_t pml2; */
/* uint64_t pml1; */
} PACKED PgIndex;
typedef struct {
@ -39,25 +43,32 @@ typedef struct {
bool writethrough: 1;
bool cachedisabled: 1;
bool accessed: 1;
bool zero0: 1;
bool size: 1;
bool zero1: 1;
bool dirty: 1;
bool hugepage: 1;
bool global: 1;
uint8_t avail: 3;
uint64_t addr: 52;
uint64_t addr: 40;
uint16_t osdef: 11;
bool nx: 1;
/* bool zero0: 1; */
/* bool size: 1; */
/* bool zero1: 1; */
/* uint8_t avail: 3; */
/* uint64_t addr: 52; */
} PACKED Pte;
typedef struct {
Pte ents[512];
} PACKED PgTable;
extern PgTable *KERNEL_CR3;
extern uint64_t KERNEL_CR3;
void hal_vmm_init(void);
void hal_vmm_unmap_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr);
void hal_vmm_map_page(PgTable *pml4, uint64_t virtaddr, uint64_t physaddr, uint32_t flags);
PgTable *hal_vmm_current_cr3(void);
void hal_vmm_map_range(PgTable *cr3, void *virtstart, void *physstart, size_t size, uint32_t flags);
void hal_vmm_unmap_range(PgTable *cr3, void *virtstart, void *physstart, size_t size);
PgTable *hal_vmm_userproc_pml4(struct Proc *proc);
void hal_vmm_unmap_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr);
void hal_vmm_map_page(uint64_t cr3phys, uint64_t virtaddr, uint64_t physaddr, uint32_t flags);
uint64_t hal_vmm_current_cr3(void);
void hal_vmm_map_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size, uint32_t flags);
void hal_vmm_unmap_range(uint64_t cr3phys, void *virtstart, void *physstart, size_t size);
uint64_t hal_vmm_userproc_pml4_phys(struct Proc *proc);
#endif // HAL_VMM_H_