mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
Add a WIP VMM
As of now the VMM (pretty much a doubly linked list of regions) supports allocating and demand paging. still no deallocation though so if you allocate something you can't free it yet :')
This commit is contained in:
@@ -3,10 +3,11 @@
|
||||
#include <stdint.h>
|
||||
|
||||
cls_t bspcls;
|
||||
|
||||
vmm_context initialvmmcontext;
|
||||
|
||||
void arch_setcls(cls_t* addr){
|
||||
wrmsr(MSR_GSBASE, (uint64_t)addr);
|
||||
wrmsr(MSR_KERNELGSBASE, (uint64_t)addr);
|
||||
}
|
||||
|
||||
cls_t* arch_getcls(){
|
||||
@@ -15,4 +16,5 @@ cls_t* arch_getcls(){
|
||||
|
||||
void bsp_setcls(){
|
||||
arch_setcls(&bspcls);
|
||||
bspcls.context = &initialvmmcontext;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ void idt_bspinit(){
|
||||
idt_setentry(&idt[i], asmisr_except, 0x28, FLAGS_PRESENT | FLAGS_TYPE_TRAP, 0);
|
||||
}
|
||||
|
||||
idt_setentry(&idt[VECTOR_PF], asmisr_pagefault, 0x28, FLAGS_PRESENT | FLAGS_TYPE_TRAP, 0);
|
||||
|
||||
idt_reload();
|
||||
|
||||
}
|
||||
|
||||
@@ -8,6 +8,21 @@
|
||||
#define FLAGS_TYPE_INTERRUPT (0xE << 8)
|
||||
#define FLAGS_TYPE_TRAP (0xF << 8)
|
||||
|
||||
#define VECTOR_DIV 0
|
||||
#define VECTOR_DEBUG 1
|
||||
#define VECTOR_NMI 2
|
||||
#define VECTOR_BREAKPOINT 3
|
||||
#define VECTOR_OVERFLOW 4
|
||||
#define VECTOR_BOUNDRANGE 5
|
||||
#define VECTOR_INVALIDOPCODE 6
|
||||
#define VECTOR_DEVUNAVAILABLE 7
|
||||
#define VECTOR_DOUBLEFAULT 8
|
||||
#define VECTOR_COPROCESSOR 9
|
||||
#define VECTOR_INVALIDTSS 10
|
||||
#define VECTOR_SEGMENTNOTPRESENT 11
|
||||
#define VECTOR_STACK 12
|
||||
#define VECTOR_GPF 13
|
||||
#define VECTOR_PF 14
|
||||
|
||||
|
||||
typedef struct{
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
extern void asmisr_general(arch_regsnoerror*);
|
||||
extern void asmisr_except(arch_regserror*);
|
||||
|
||||
extern void asmisr_pagefault(arch_regserror*);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
|
||||
#define PAGE_SIZE 4096
|
||||
|
||||
#define ARCH_MMU_MAP_READ (1 << 0)
|
||||
#define ARCH_MMU_MAP_WRITE (1 << 1)
|
||||
#define ARCH_MMU_MAP_USER (1 << 2)
|
||||
#define ARCH_MMU_MAP_NOEXEC (1 << 63)
|
||||
#define ARCH_MMU_MAP_PAGESIZE (1 << 7)
|
||||
#define ARCH_MMU_MAP_READ (uint64_t)(1 << 0)
|
||||
#define ARCH_MMU_MAP_WRITE (uint64_t)(1 << 1)
|
||||
#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)
|
||||
|
||||
typedef uint64_t* arch_mmu_tableptr;
|
||||
|
||||
|
||||
+17
-3
@@ -2,6 +2,8 @@ section .text
|
||||
|
||||
%macro pushregs 0
|
||||
|
||||
|
||||
|
||||
push rbp
|
||||
push rsi
|
||||
push rdi
|
||||
@@ -27,6 +29,11 @@ section .text
|
||||
mov rax, gs
|
||||
push rax
|
||||
|
||||
cmp rax,0x30
|
||||
jmp .noswapgs
|
||||
swapgs
|
||||
.noswapgs:
|
||||
|
||||
mov rdi,cr2
|
||||
push rdi
|
||||
|
||||
@@ -36,8 +43,10 @@ section .text
|
||||
%macro popregs 0
|
||||
|
||||
add rsp, 8 ; cr2
|
||||
|
||||
|
||||
pop rax
|
||||
cmp rax,0x30
|
||||
je .dontpopsegs
|
||||
mov gs,rax
|
||||
pop rax
|
||||
mov fs,rax
|
||||
@@ -45,7 +54,12 @@ section .text
|
||||
mov es,rax
|
||||
pop rax
|
||||
mov ds,rax
|
||||
|
||||
swapgs
|
||||
jmp .poprest
|
||||
.dontpopsegs:
|
||||
add rsp,24
|
||||
|
||||
.poprest:
|
||||
pop rax
|
||||
pop rbx
|
||||
pop rcx
|
||||
@@ -89,7 +103,7 @@ section .text
|
||||
|
||||
|
||||
%macro except 2
|
||||
|
||||
|
||||
global %1
|
||||
%1:
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <arch/isr.h>
|
||||
#include <arch/panic.h>
|
||||
#include <kernel/vmm.h>
|
||||
|
||||
void isr_general(arch_regsnoerror *reg){
|
||||
_panic("Unhandled interrupt", 0);
|
||||
@@ -11,6 +12,9 @@ void isr_except(arch_regserror *reg){
|
||||
asm("hlt;");
|
||||
}
|
||||
|
||||
void isr_pagefault(void*){
|
||||
void isr_pagefault(arch_regserror *reg){
|
||||
|
||||
if(!vmm_dealwithrequest(reg->cr2))
|
||||
_panic("Page fault!\n", 0);
|
||||
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <arch/idt.h>
|
||||
#include <arch/cls.h>
|
||||
#include <kernel/pmm.h>
|
||||
#include <kernel/vmm.h>
|
||||
|
||||
static volatile struct limine_terminal_request liminettyr = {
|
||||
.id = LIMINE_TERMINAL_REQUEST,
|
||||
@@ -40,8 +41,8 @@ void kmain(){
|
||||
|
||||
arch_mmu_init();
|
||||
|
||||
|
||||
|
||||
vmm_init();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
+10
-8
@@ -44,6 +44,7 @@ static bool setpage(arch_mmu_tableptr context, void* vaddr, uint64_t entry){
|
||||
|
||||
// TODO unallocate in case of failure
|
||||
|
||||
|
||||
if(!pdptaddr){
|
||||
pdptaddr = pmm_alloc(1);
|
||||
changeentry(&context[pdpt], pdptaddr, PTR_FLAGS);
|
||||
@@ -53,7 +54,7 @@ static bool setpage(arch_mmu_tableptr context, void* vaddr, uint64_t entry){
|
||||
pdptaddr = (void*)pdptaddr + (size_t)limine_hhdm_offset;
|
||||
|
||||
uint64_t* pdaddr = pdptaddr[pd] & ~0xFFF;
|
||||
|
||||
|
||||
if(!pdaddr){
|
||||
pdaddr = pmm_alloc(1);
|
||||
changeentry(&pdptaddr[pd], pdaddr, PTR_FLAGS);
|
||||
@@ -64,8 +65,6 @@ static bool setpage(arch_mmu_tableptr context, void* vaddr, uint64_t entry){
|
||||
|
||||
uint64_t* ptaddr = pdaddr[pt]& ~0xFFF;
|
||||
|
||||
|
||||
|
||||
if(!ptaddr){
|
||||
ptaddr = pmm_alloc(1);
|
||||
changeentry(&pdaddr[pt], ptaddr, PTR_FLAGS);
|
||||
@@ -87,7 +86,8 @@ int arch_mmu_map(arch_mmu_tableptr context, void* paddr, void* vaddr, size_t fla
|
||||
changeentry(&entry, paddr, flags);
|
||||
|
||||
int ret = setpage(context, vaddr, entry);
|
||||
|
||||
|
||||
|
||||
if(ret) invalidate(vaddr);
|
||||
|
||||
return ret;
|
||||
@@ -128,13 +128,13 @@ void arch_mmu_init(){
|
||||
for(size_t entry = 0; entry < count; ++entry){
|
||||
void* addr = entries[entry]->base;
|
||||
|
||||
for(size_t offset = 0; offset < entries[entry]->length; offset += PAGE_SIZE){
|
||||
for(size_t pageoffset = 0; pageoffset < entries[entry]->length / PAGE_SIZE; ++pageoffset){
|
||||
uint64_t entry;
|
||||
|
||||
changeentry(&entry, addr + offset, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE);
|
||||
changeentry(&entry, addr + pageoffset*PAGE_SIZE, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE);
|
||||
|
||||
setpage(context, addr + offset, entry);
|
||||
setpage(context, addr + offset + (size_t)limine_hhdm_offset, entry);
|
||||
setpage(context, addr + pageoffset*PAGE_SIZE, entry);
|
||||
setpage(context, addr + pageoffset*PAGE_SIZE + (size_t)limine_hhdm_offset, entry);
|
||||
|
||||
}
|
||||
|
||||
@@ -190,6 +190,8 @@ void arch_mmu_init(){
|
||||
|
||||
switchcontext(context);
|
||||
|
||||
arch_getcls()->context->context = context;
|
||||
|
||||
printf("In bootstrap context\n");
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#ifndef _VMM_H_INCLUDE
|
||||
#define _VMM_H_INCLUDE
|
||||
|
||||
#include <arch/mmu.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#define KERNEL_SPACE_START 0xFFFF800000000000
|
||||
#define KERNEL_SPACE_END 0xFFFFFFFFFFFFFFFF
|
||||
|
||||
#define VMM_TYPE_FREE 0
|
||||
#define VMM_TYPE_ANON 1
|
||||
#define VMM_TYPE_FILE 2
|
||||
|
||||
struct vmm_cacheheader;
|
||||
|
||||
typedef struct{
|
||||
int lock;
|
||||
struct vmm_cacheheader* next;
|
||||
size_t freecount;
|
||||
} vmm_cacheheader;
|
||||
|
||||
struct vmm_mapping;
|
||||
|
||||
typedef struct _vmm_mapping {
|
||||
struct _vmm_mapping *next;
|
||||
struct _vmm_mapping *prev;
|
||||
vmm_cacheheader* cache;
|
||||
void* start;
|
||||
void* end;
|
||||
size_t mmuflags;
|
||||
size_t type;
|
||||
void* data;
|
||||
size_t offset;
|
||||
} vmm_mapping;
|
||||
|
||||
|
||||
#define VMM_CACHE_ENTRY_COUNT ((PAGE_SIZE - sizeof(vmm_cacheheader)) / sizeof(vmm_mapping))
|
||||
|
||||
typedef struct{
|
||||
vmm_cacheheader header;
|
||||
vmm_mapping mappings[VMM_CACHE_ENTRY_COUNT];
|
||||
} vmm_cache;
|
||||
|
||||
typedef struct {
|
||||
vmm_mapping* userstart;
|
||||
arch_mmu_tableptr context;
|
||||
int lock;
|
||||
} vmm_context;
|
||||
|
||||
void vmm_init();
|
||||
|
||||
bool vmm_dealwithrequest(void* addr);
|
||||
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);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,444 @@
|
||||
#include <kernel/vmm.h>
|
||||
#include <kernel/pmm.h>
|
||||
#include <arch/panic.h>
|
||||
#include <string.h>
|
||||
#include <kernel/spinlock.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <limine.h>
|
||||
#include <arch/cls.h>
|
||||
|
||||
vmm_cache* caches;
|
||||
int klock;
|
||||
vmm_mapping *kmapstart;
|
||||
|
||||
static vmm_cache* newcache(){
|
||||
vmm_cache* cache = pmm_hhdmalloc(1);
|
||||
if(!cache) return NULL;
|
||||
memset(cache, 0, sizeof(vmm_cache));
|
||||
cache->header.freecount = VMM_CACHE_ENTRY_COUNT;
|
||||
return cache;
|
||||
}
|
||||
|
||||
static void freecache(vmm_cache* cache){
|
||||
pmm_hhdmfree(cache, 1);
|
||||
}
|
||||
|
||||
static void freeentry(vmm_mapping* entry){
|
||||
spinlock_acquire(&entry->cache->lock);
|
||||
|
||||
vmm_cacheheader* cache = entry->cache;
|
||||
|
||||
++entry->cache->freecount;
|
||||
memset(entry, 0, sizeof(vmm_mapping));
|
||||
|
||||
// TODO set first free
|
||||
|
||||
spinlock_release(&cache->lock);
|
||||
}
|
||||
|
||||
static vmm_mapping* allocentry(vmm_cache* cache){
|
||||
|
||||
vmm_mapping* found = NULL;
|
||||
|
||||
spinlock_acquire(&cache->header.lock);
|
||||
|
||||
if(cache->header.freecount == 0){
|
||||
spinlock_release(&cache->header.lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO keep first free in cache header
|
||||
|
||||
for(size_t i = 0; i < VMM_CACHE_ENTRY_COUNT; ++i){
|
||||
if(!cache->mappings[i].cache){
|
||||
found = &cache->mappings[i];
|
||||
goto _found;
|
||||
}
|
||||
}
|
||||
|
||||
_found:
|
||||
|
||||
--cache->header.freecount;
|
||||
if(found)
|
||||
found->cache = &cache->header;
|
||||
|
||||
spinlock_release(&cache->header.lock);
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
static vmm_mapping* allocatefirst(){
|
||||
|
||||
// FIXME there's a possible race condition here I think
|
||||
|
||||
vmm_mapping *map = NULL;
|
||||
vmm_cache *cache = caches;
|
||||
|
||||
map = allocentry(cache);
|
||||
|
||||
while(cache->header.next && map == NULL){
|
||||
cache = cache->header.next;
|
||||
map = allocentry(cache);
|
||||
}
|
||||
|
||||
if(!map){
|
||||
// try allocating new cache
|
||||
vmm_cache* new = newcache();
|
||||
if(!new) return NULL;
|
||||
map = allocentry(new);
|
||||
cache->header.next = new;
|
||||
}
|
||||
|
||||
|
||||
return map;
|
||||
|
||||
}
|
||||
|
||||
static char* debugnames[] = {
|
||||
"FREE",
|
||||
"ANON",
|
||||
"FILE"
|
||||
};
|
||||
|
||||
static void debug_dumpkernelmappings(){
|
||||
vmm_mapping* map = kmapstart;
|
||||
|
||||
printf("Kernel mappings:\n");
|
||||
|
||||
while(map != NULL){
|
||||
printf("START: %016p END: %016p MMUFLAGS: %016p DATA: %016p OFFSET: %lu TYPE: %s\n", map->start, map->end, map->mmuflags, map->data, map->offset, debugnames[map->type]);
|
||||
map = map->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void fragcheck(vmm_mapping* map){
|
||||
if(map->type == VMM_TYPE_FILE)
|
||||
return;
|
||||
|
||||
if(map->prev && map->prev->type == map->type && map->prev->mmuflags == map->mmuflags){
|
||||
vmm_mapping *prev = map->prev;
|
||||
prev->next = map->next;
|
||||
prev->end = map->end;
|
||||
if(map->next)
|
||||
map->next->prev = prev;
|
||||
freeentry(map);
|
||||
map = prev;
|
||||
}
|
||||
|
||||
if(map->next && map->next->type == map->type && map->next->mmuflags == map->mmuflags){
|
||||
vmm_mapping* next = map->next;
|
||||
map->next = next->next;
|
||||
map->end = next->end;
|
||||
if(next->next)
|
||||
next->next->prev = map;
|
||||
freeentry(next);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// FIXME I snatched this from the old codebase. This is ugly and it should definetively be
|
||||
// rewritten
|
||||
|
||||
static bool setmap(vmm_mapping** mapstart, void* addr, size_t pagec, size_t mmuflags, size_t type, void* data, size_t offset){
|
||||
|
||||
vmm_mapping* map = *mapstart;
|
||||
while(map && addr > map->end)
|
||||
map = map->next;
|
||||
|
||||
if(!map) return false;
|
||||
|
||||
vmm_mapping* newmap = allocatefirst();
|
||||
|
||||
if(!newmap) return false;
|
||||
|
||||
|
||||
newmap->start = addr;
|
||||
newmap->end = addr + pagec*PAGE_SIZE-1;
|
||||
newmap->mmuflags = mmuflags;
|
||||
newmap->type = type;
|
||||
newmap->data = data;
|
||||
newmap->offset = offset;
|
||||
|
||||
// spans multiple entries?
|
||||
if(newmap->end > map->end){
|
||||
vmm_mapping* nextmap = map->next;
|
||||
while(nextmap && newmap->end < nextmap->start)
|
||||
nextmap = nextmap->next;
|
||||
|
||||
if(!nextmap){
|
||||
freeentry(newmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
// unallocate entries inbetween
|
||||
|
||||
vmm_mapping* loopmap = map->next;
|
||||
|
||||
while(loopmap != nextmap){
|
||||
loopmap = loopmap->next;
|
||||
freeentry(loopmap->prev);
|
||||
}
|
||||
|
||||
map->end = newmap->start-1;
|
||||
|
||||
if(nextmap->type == VMM_TYPE_FILE)
|
||||
nextmap->offset += newmap->end - nextmap->start + 1;
|
||||
nextmap->start = newmap->end+1;
|
||||
|
||||
map->next = newmap;
|
||||
newmap->prev = map;
|
||||
newmap->next = nextmap;
|
||||
nextmap->prev = newmap;
|
||||
|
||||
if(map->start >= map->end){
|
||||
newmap->prev = map->prev;
|
||||
freeentry(map);
|
||||
if(map->prev == NULL)
|
||||
*mapstart = newmap;
|
||||
}
|
||||
|
||||
if(nextmap->start >= nextmap->end){
|
||||
newmap->next = nextmap->next;
|
||||
freeentry(nextmap);
|
||||
}
|
||||
|
||||
fragcheck(newmap);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// do we need to split?
|
||||
|
||||
if(map->start != newmap->start && map->end != newmap->end){
|
||||
vmm_mapping* splitmap = allocatefirst();
|
||||
if(!splitmap){
|
||||
freeentry(newmap);
|
||||
return false;
|
||||
}
|
||||
|
||||
splitmap->next = map->next;
|
||||
splitmap->prev = newmap;
|
||||
splitmap->end = map->end;
|
||||
splitmap->start = newmap->end+1;
|
||||
splitmap->type = map->type;
|
||||
if(splitmap->type == VMM_TYPE_FILE)
|
||||
splitmap->offset = map->offset + splitmap->start - map->start;
|
||||
splitmap->data = map->data;
|
||||
|
||||
map->next = newmap;
|
||||
map->end = newmap->start-1;
|
||||
|
||||
newmap->prev = map;
|
||||
newmap->next = splitmap;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if(map->start == newmap->start){
|
||||
newmap->next = map;
|
||||
newmap->prev = map->prev;
|
||||
if(newmap->prev){
|
||||
vmm_mapping* tmp = newmap->prev;
|
||||
tmp->next = newmap;
|
||||
}
|
||||
else
|
||||
*mapstart = newmap;
|
||||
|
||||
|
||||
map->start = newmap->end+1;
|
||||
if(map->type == VMM_TYPE_FILE)
|
||||
map->offset += newmap->end - newmap->start + 1;
|
||||
map->prev = newmap;
|
||||
|
||||
if(map->start >= map->end){
|
||||
newmap->next = map->next;
|
||||
freeentry(map);
|
||||
}
|
||||
}
|
||||
else{
|
||||
// end
|
||||
newmap->next = map->next;
|
||||
newmap->prev = map;
|
||||
|
||||
if(newmap->next){
|
||||
vmm_mapping* tmp = newmap->next;
|
||||
tmp->prev = newmap;
|
||||
}
|
||||
|
||||
map->end = newmap->start-1;
|
||||
map->next = newmap;
|
||||
|
||||
if(map->start >= map->end){
|
||||
newmap->prev = map->prev;
|
||||
freeentry(map);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fragcheck(newmap);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
static vmm_mapping* findmappingfromaddr(vmm_mapping* map, void* addr){
|
||||
|
||||
while(map && !(addr > map->start && addr <= map->end))
|
||||
map = map->next;
|
||||
|
||||
return map;
|
||||
|
||||
}
|
||||
|
||||
static void* findfirstfreearea(vmm_mapping* map, size_t pagec){
|
||||
while(map && map->end < map->start + pagec*PAGE_SIZE-1 || map->type != VMM_TYPE_FREE)
|
||||
map = map->next;
|
||||
|
||||
if(map) return map->start;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static bool unmap(vmm_mapping* start, void* addr, size_t pagec){
|
||||
|
||||
}
|
||||
|
||||
|
||||
// TODO do it in the lower half of memory as well
|
||||
|
||||
void* vmm_alloc(size_t pagec, size_t mmuflags){
|
||||
spinlock_acquire(&klock);
|
||||
|
||||
void* addr = findfirstfreearea(kmapstart, pagec);
|
||||
|
||||
if(!addr){
|
||||
spinlock_release(&klock);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
|
||||
|
||||
if(!setmap(&kmapstart, addr, pagec, mmuflags, VMM_TYPE_ANON, 0, 0))
|
||||
addr = NULL;
|
||||
|
||||
spinlock_release(&klock);
|
||||
|
||||
return addr;
|
||||
}
|
||||
|
||||
bool vmm_unmap(void* addr, size_t pagec){
|
||||
|
||||
spinlock_acquire(&klock);
|
||||
|
||||
unmap(kmapstart, addr, pagec);
|
||||
|
||||
spinlock_release(&klock);
|
||||
|
||||
}
|
||||
|
||||
// called by the page fault handler
|
||||
|
||||
bool vmm_dealwithrequest(void* addr){
|
||||
|
||||
spinlock_acquire(&klock);
|
||||
|
||||
bool status;
|
||||
|
||||
vmm_mapping* map = findmappingfromaddr(kmapstart, addr);
|
||||
void* paddr;
|
||||
|
||||
if((!map) || map->type == VMM_TYPE_FREE){
|
||||
status = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if(map->type == VMM_TYPE_FILE)
|
||||
_panic("File mappings are not supported (yet)", 0);
|
||||
|
||||
// allocate a page
|
||||
|
||||
addr = (size_t)addr & ~(0xFFF);
|
||||
|
||||
printf("Demand paging %p\n", addr);
|
||||
|
||||
|
||||
|
||||
cls_t* cls = arch_getcls();
|
||||
|
||||
|
||||
paddr = pmm_alloc(1);
|
||||
|
||||
|
||||
if(addr == NULL || arch_mmu_map(cls->context->context, paddr, addr, map->mmuflags) == false){
|
||||
status = false;
|
||||
goto done;
|
||||
}
|
||||
|
||||
status = true;
|
||||
|
||||
done:
|
||||
|
||||
spinlock_release(&klock);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
void vmm_init(){
|
||||
printf("%lu mappings per cache\n", VMM_CACHE_ENTRY_COUNT);
|
||||
caches = newcache();
|
||||
if(!caches) _panic("Out of memory", 0);
|
||||
|
||||
kmapstart = allocentry(caches);
|
||||
kmapstart->start = (void*)KERNEL_SPACE_START;
|
||||
kmapstart->end = (void*)KERNEL_SPACE_END;
|
||||
|
||||
|
||||
// add the hhdm to the maps
|
||||
|
||||
extern volatile struct limine_memmap_request memmap_req;
|
||||
size_t count = memmap_req.response->entry_count;
|
||||
struct limine_memmap_entry** entries = memmap_req.response->entries;
|
||||
|
||||
for(size_t entry = 0; entry < count; ++entry){
|
||||
setmap(&kmapstart, (size_t)entries[entry]->base + (size_t)limine_hhdm_offset & ~(0xFFF), entries[entry]->length / PAGE_SIZE, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_WRITE, VMM_TYPE_ANON, 0, 0);
|
||||
}
|
||||
|
||||
// now the kernel
|
||||
|
||||
extern int _text_start, _text_end, _rodata_start, _rodata_end, _data_start, _data_end;
|
||||
|
||||
void* textstart = &_text_start;
|
||||
void* textend = &_text_end;
|
||||
void* rodatastart = &_rodata_start;
|
||||
void* rodataend = &_rodata_end;
|
||||
void* datastart = &_data_start;
|
||||
void* dataend = &_data_end;
|
||||
|
||||
setmap(&kmapstart, textstart, (textend - textstart) / PAGE_SIZE, ARCH_MMU_MAP_READ, VMM_TYPE_ANON, 0, 0);
|
||||
|
||||
setmap(&kmapstart, rodatastart, (rodataend - rodatastart) / PAGE_SIZE, ARCH_MMU_MAP_READ | ARCH_MMU_MAP_NOEXEC, VMM_TYPE_ANON, 0, 0);
|
||||
|
||||
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