mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
finish the vmm
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
@@ -11,10 +12,13 @@
|
||||
#define ARCH_MMU_MAP_USER (uint64_t)(1 << 2)
|
||||
#define ARCH_MMU_MAP_NOEXEC (uint64_t)(1 << 63)
|
||||
#define ARCH_MMU_MAP_PAGESIZE (uint64_t)(1 << 7)
|
||||
#define ARCH_MMU_MAP_ACCESSED (uint64_t)(1 << 5)
|
||||
|
||||
typedef uint64_t* arch_mmu_tableptr;
|
||||
|
||||
int arch_mmu_map(arch_mmu_tableptr, void*, void*, size_t);
|
||||
bool arch_mmu_isaccessed(arch_mmu_tableptr, void*);
|
||||
void* arch_mmu_getphysicaladdr(arch_mmu_tableptr, void*);
|
||||
void arch_mmu_unmap(arch_mmu_tableptr, void*);
|
||||
void arch_mmu_init();
|
||||
|
||||
|
||||
@@ -31,6 +31,22 @@ static void invalidate(void* addr){
|
||||
asm("invlpg (%%rax)" : : "a"(addr));
|
||||
}
|
||||
|
||||
|
||||
static uint64_t* next(uint64_t* table, size_t offset){
|
||||
|
||||
table = (uint64_t)table & ~(0xFFF);
|
||||
|
||||
if(table < limine_hhdm_offset){
|
||||
table = (uint64_t)table & ~(1 << 63); // remove NX
|
||||
table = (uint64_t)table + (uint64_t)limine_hhdm_offset;
|
||||
}
|
||||
|
||||
return table[offset];
|
||||
|
||||
}
|
||||
|
||||
// FIXME make the accessed addresses be in the limine hhdm
|
||||
|
||||
static bool setpage(arch_mmu_tableptr context, void* vaddr, uint64_t entry){
|
||||
uint64_t addr = (uint64_t)vaddr;
|
||||
size_t pdpt = (addr >> 39) & 0b111111111;
|
||||
@@ -81,6 +97,40 @@ static bool setpage(arch_mmu_tableptr context, void* vaddr, uint64_t entry){
|
||||
|
||||
|
||||
|
||||
static uint64_t getmapping(arch_mmu_tableptr context, void* vaddr){
|
||||
uint64_t addr = (uint64_t)vaddr;
|
||||
size_t pdpt = (addr >> 39) & 0b111111111;
|
||||
size_t pd = (addr >> 30) & 0b111111111;
|
||||
size_t pt = (addr >> 21) & 0b111111111;
|
||||
size_t page = (addr >> 12) & 0b111111111;
|
||||
|
||||
if(!context[pdpt]) return 0;
|
||||
|
||||
uint64_t* table = next(context, pd);
|
||||
|
||||
if(!table) return 0;
|
||||
|
||||
table = next(table, pt);
|
||||
|
||||
if(!table) return 0;
|
||||
|
||||
table = next(table, page);
|
||||
|
||||
return table;
|
||||
|
||||
}
|
||||
|
||||
void* arch_mmu_getphysicaladdr(arch_mmu_tableptr context, void* addr){
|
||||
uint64_t paddr = getmapping(context, addr);
|
||||
paddr &= ~(0xFFF);
|
||||
paddr &= ~ARCH_MMU_MAP_NOEXEC;
|
||||
return paddr;
|
||||
}
|
||||
|
||||
bool arch_mmu_isaccessed(arch_mmu_tableptr context, void* addr){
|
||||
return (getmapping(context, addr) & ARCH_MMU_MAP_ACCESSED) != 0;
|
||||
}
|
||||
|
||||
int arch_mmu_map(arch_mmu_tableptr context, void* paddr, void* vaddr, size_t flags){
|
||||
uint64_t entry;
|
||||
changeentry(&entry, paddr, flags);
|
||||
|
||||
@@ -55,5 +55,5 @@ bool vmm_setused(void* addr, size_t pagec, size_t mmuflags);
|
||||
bool vmm_unmap(void* addr, size_t pagec);
|
||||
bool vmm_map(void* paddr, void* vaddr, size_t pagec, size_t mmuflags);
|
||||
void* vmm_alloc(size_t pagec, size_t mmuflags);
|
||||
|
||||
bool vmm_setfree(void* addr, size_t pagec);
|
||||
#endif
|
||||
|
||||
+59
-14
@@ -303,8 +303,36 @@ static void* findfirstfreearea(vmm_mapping* map, size_t pagec){
|
||||
}
|
||||
|
||||
|
||||
static bool unmap(vmm_mapping* start, void* addr, size_t pagec){
|
||||
static bool unmap(vmm_mapping** mapstart, void* addr, size_t pagec){
|
||||
if(pagec == 0) return true;
|
||||
vmm_mapping *map = *mapstart;
|
||||
void* savedaddr = addr;
|
||||
arch_mmu_tableptr context = arch_getcls()->context->context;
|
||||
|
||||
for(size_t page = 0; page < pagec; ++page, addr += PAGE_SIZE){
|
||||
map = findmappingfromaddr(map, addr);
|
||||
switch(map->type){
|
||||
case VMM_TYPE_ANON:
|
||||
if(arch_mmu_isaccessed(context, addr)){
|
||||
void* paddr = arch_mmu_getphysicaladdr(context, addr);
|
||||
pmm_free(paddr, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case VMM_TYPE_FILE:
|
||||
_panic("File mappings not supported!", 0);
|
||||
|
||||
default:
|
||||
continue;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
setmap(mapstart, savedaddr, pagec, 0, VMM_TYPE_FREE, 0, 0);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -340,6 +368,35 @@ bool vmm_unmap(void* addr, size_t pagec){
|
||||
|
||||
}
|
||||
|
||||
bool vmm_setused(void* addr, size_t pagec, size_t mmuflags){
|
||||
spinlock_acquire(&klock);
|
||||
|
||||
bool result = setmap(&kmapstart, addr, pagec, mmuflags, VMM_TYPE_ANON, 0, 0);
|
||||
|
||||
spinlock_release(&klock);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool vmm_setfree(void* addr, size_t pagec){
|
||||
spinlock_acquire(&klock);
|
||||
|
||||
bool result = setmap(&kmapstart, addr, pagec, 0, VMM_TYPE_FREE, 0, 0);
|
||||
|
||||
spinlock_release(&klock);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool vmm_map(void* paddr, void* vaddr, size_t pagec, size_t mmuflags){
|
||||
spinlock_acquire(&klock);
|
||||
bool result = setmap(&kmapstart, vaddr, pagec, mmuflags, VMM_TYPE_ANON, 0, 0);
|
||||
|
||||
for(size_t page = 0; page < pagec && result; ++page)
|
||||
result = arch_mmu_map(arch_getcls()->context->context, paddr + page*PAGE_SIZE, vaddr + page*PAGE_SIZE, mmuflags);
|
||||
|
||||
spinlock_release(&klock);
|
||||
return result;
|
||||
}
|
||||
|
||||
// called by the page fault handler
|
||||
|
||||
bool vmm_dealwithrequest(void* addr){
|
||||
@@ -425,20 +482,8 @@ void vmm_init(){
|
||||
|
||||
setmap(&kmapstart, datastart, (dataend - datastart) / PAGE_SIZE, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE | ARCH_MMU_MAP_NOEXEC, VMM_TYPE_ANON, 0, 0);
|
||||
|
||||
|
||||
|
||||
debug_dumpkernelmappings();
|
||||
|
||||
printf("Writing to 10 demand paged pages\n");
|
||||
|
||||
volatile char* all = vmm_alloc(10, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE);
|
||||
printf("Alloc at %p\n", all);
|
||||
|
||||
|
||||
|
||||
for(size_t i = 0; i < PAGE_SIZE*10; ++i)
|
||||
*(all + i) = 0;
|
||||
|
||||
|
||||
printf("WOOOOOO!!!\n");
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user