Implemented VMM!

This commit is contained in:
2025-04-08 15:09:57 +02:00
parent ced6cb250f
commit 7c2fcd8e9f
9 changed files with 139 additions and 54 deletions
+2
View File
@@ -11,9 +11,11 @@ typedef struct bitmap_t {
size_t blocks; // Eqiv. to # of bits
size_t bytes; // ceil(blocks / 8)
size_t used; // # of bits set to 0
size_t membase; // Used with allocators
int ready;
} bitmap_t;
void* bmap_ptr(bitmap_t* map, size_t bit);
void bmap_set(bitmap_t* map, size_t bit, int val);
int bmap_get(bitmap_t* map, size_t bit);
void bmap_setarea(bitmap_t* map, size_t base, size_t len, int val);
+2 -2
View File
@@ -12,8 +12,8 @@
#define USER_SHARED 0xA0000000
#define KERNEL_BASE 0xC0000000
#define KERNEL_SIZE 0x10000000
#define KERNEL_MEM_BASE 0xD0000000
#define KERNEL_MEM_SIZE 0x10000000
#define KERNEL_HEAP_BASE 0xD0000000
#define KERNEL_HEAP_SIZE 0x10000000
#define KERNEL_SHARED 0xF0000000
#define KERNEL_FRAMEBUF 0xC8000000
+2 -4
View File
@@ -7,9 +7,7 @@
extern bitmap_t pmm_bitmap;
int pmm_init(void);
void pmm_initRegion(size_t base, size_t len);
void pmm_deinitRegion(size_t base, size_t len);
void* pmm_alloc(size_t len);
void pmm_free(void* ptr, size_t len);
void* pmm_allocPage(void);
void pmm_freePage(void* page);
#endif
+13
View File
@@ -0,0 +1,13 @@
#ifndef _VMM_H
#define _VMM_H
#include <kernel.h>
#include <bitmap.h>
extern bitmap_t vmm_bitmap;
int vmm_init(void);
void* vmm_alloc(size_t pages);
void vmm_free(void* ptr, size_t pages);
#endif
+9 -7
View File
@@ -3,10 +3,15 @@
#include <bitmap.h>
void* bmap_ptr(bitmap_t* map, size_t bit) {
return (void*)(map->membase + bit * BLOCK_SIZE);
}
void bmap_set(bitmap_t* map, size_t bit, int val) {
uint32_t* p = (uint32_t*)map->map;
if (val) p[bit / 32] |= (1 << (bit % 32));
else p[bit / 32] &= ~(1 << (bit % 32));
map->used += (val) ? 1 : -1;
}
int bmap_get(bitmap_t* map, size_t bit) {
@@ -15,13 +20,10 @@ int bmap_get(bitmap_t* map, size_t bit) {
}
void bmap_setarea(bitmap_t* map, size_t base, size_t len, int val) {
uint32_t align = base / BLOCK_SIZE;
uint32_t count = len / BLOCK_SIZE;
uint32_t align = dceil(base, BLOCK_SIZE);
uint32_t count = dceil(len, BLOCK_SIZE);
while (count-- > 0) {
bmap_set(map, align++, val);
map->used += (val) ? 1 : -1;
}
while (count-- > 0) bmap_set(map, align++, val);
}
void bmap_setall(bitmap_t* map, int val) {
@@ -39,7 +41,7 @@ size_t bmap_findarea(bitmap_t* map, size_t len, int val) {
if (bmap_get(map, i) == val) found++;
else found = 0;
if (found >= len) return i - found;
if (found >= len) return i - found + 1;
}
return BMAP_NOT_FOUND;
+3 -2
View File
@@ -6,10 +6,11 @@
#include <isr.h>
#include <pmm.h>
#include <tty.h>
#include <vmm.h>
__noreturn
void kmain(void* ptr, uint32_t magic) {
if (boot_initMB1(ptr, magic) != 0) panic("Unsupporred bootloader.");
if (boot_initMB1(ptr, magic) != 0) panic("Unsupported bootloader.");
// Serial console for debugging
if (serial_init(COM1) != 0) panic("Failed to initialize Serial driver.");
@@ -26,7 +27,7 @@ void kmain(void* ptr, uint32_t magic) {
// Memory manager init
if (pmm_init() != 0) panic("Failed to initalize Physical Memory Manager.");
//if (vmm_init() != 0) panic("Failed to initalize Virtual Memory Manager.");
if (vmm_init() != 0) panic("Failed to initalize Virtual Memory Manager.");
debugf("Basic initialization complete!\n");
+5 -5
View File
@@ -65,7 +65,7 @@ void pag_mapPage(uint32_t vaddr, uint32_t paddr, uint32_t flags) {
// Allocate a pagetab if it didn't exist
if (!(pagedir[pdi] & PAGE_FLAG_PRESENT)) {
uint32_t tabaddr = pmm_bitmap.ready ? (uint32_t)pmm_alloc(1) : pag_tempFrame();
uint32_t tabaddr = pmm_bitmap.ready ? (uint32_t)pmm_allocPage() : pag_tempFrame();
pagedir[pdi] = tabaddr |
PAGE_FLAG_PRESENT | PAGE_FLAG_WRITE | PAGE_FLAG_OWNER | flags;
@@ -122,14 +122,14 @@ uint32_t pag_umapPage(uint32_t vaddr) {
uint32_t pde = pagedir[pdi];
if (remove && pde & PAGE_FLAG_OWNER) {
uint32_t tabaddr = PHYS_ADDR(pde);
pmm_free((void*)tabaddr, 1);
pmm_freePage((void*)tabaddr);
pagedir[pdi] = 0;
}
invalidate(vaddr);
// Free the page frame
if (pte & PAGE_FLAG_OWNER) pmm_free((void*)PHYS_ADDR(pte), 1);
if (pte & PAGE_FLAG_OWNER) pmm_freePage((void*)PHYS_ADDR(pte));
if (prevpd != NULL) {
pag_syncPagedir(); // Sync it to other pagedirs
@@ -221,11 +221,11 @@ void pag_freePagedir(uint32_t* pagedir) {
for (size_t j = 0; j < 1024; j++) {
uint32_t pte = pagetab[j];
if (pte & PAGE_FLAG_OWNER) pmm_free((void*)PHYS_ADDR(pte), 1);
if (pte & PAGE_FLAG_OWNER) pmm_freePage((void*)PHYS_ADDR(pte));
}
memset(pagetab, 0, PAGE_SIZE);
if (pde & PAGE_FLAG_OWNER) pmm_free((void*)PHYS_ADDR(pde), 1);
if (pde & PAGE_FLAG_OWNER) pmm_freePage((void*)PHYS_ADDR(pde));
pd[i] = 0;
}
+19 -27
View File
@@ -8,10 +8,10 @@
bitmap_t pmm_bitmap;
int pmm_init(void) {
size_t totalmem = (bootloader.memLower + bootloader.memUpper) * 1024;
pmm_bitmap.blocks = dceil(totalmem, BLOCK_SIZE);
pmm_bitmap.bytes = dceil(pmm_bitmap.blocks, 8);
// Full 32-bit address space
pmm_bitmap.membase = 0x00000000;
pmm_bitmap.blocks = 0x100000; // 0xFFFFFFFF / BLOCK_SIZE
pmm_bitmap.bytes = 0x20000; // blocks / 8
pmm_bitmap.map = NULL;
// # of pagetabs required to map the bitmap
@@ -34,7 +34,7 @@ int pmm_init(void) {
pag_registerTempFrame(pageFrameStart);
mmap->base += ptcount * PAGE_SIZE;
uint32_t bitmapStart = KERNEL_MEM_BASE - dceil(pmm_bitmap.bytes, PAGE_SIZE) * PAGE_SIZE;
uint32_t bitmapStart = KERNEL_HEAP_BASE - dceil(pmm_bitmap.bytes, PAGE_SIZE) * PAGE_SIZE;
uint32_t bitmapStartPhys = mmap->base;
pmm_bitmap.map = (void*)bitmapStart;
@@ -53,7 +53,9 @@ int pmm_init(void) {
mmap = &bootloader.memmap[i];
if (mmap->size == 0) continue; // Ignore dummy entries
if (mmap->type == BOOT_MMAP_AVAILABLE) pmm_initRegion(mmap->base, mmap->size);
if (mmap->type == BOOT_MMAP_AVAILABLE) {
bmap_setarea(&pmm_bitmap, mmap->base, mmap->size, 0);
}
// Print entry
debugf("\tRegion %2d: 0x%08x - 0x%08x (%d bytes) %s\n",
@@ -61,8 +63,9 @@ int pmm_init(void) {
(mmap->type == BOOT_MMAP_AVAILABLE) ? "AVAILABLE" : "RESERVED");
}
pmm_deinitRegion(bitmapStartPhys, pmm_bitmap.bytes);
pmm_deinitRegion(pageFrameStart, ptcount * PAGE_SIZE);
bmap_setarea(&pmm_bitmap, bitmapStartPhys, pmm_bitmap.bytes, 1);
bmap_setarea(&pmm_bitmap, pageFrameStart, ptcount * PAGE_SIZE, 1);
bmap_set(&pmm_bitmap, 0, 1); // Reserve block 0 - NULL page
// Beatifull print statement :)
debugf(
@@ -79,31 +82,20 @@ int pmm_init(void) {
return 0;
}
void* pmm_allocPage(void) {
if (pmm_bitmap.blocks - pmm_bitmap.used == 0) return NULL;
void pmm_initRegion(size_t base, size_t len) {
bmap_setarea(&pmm_bitmap, base, len, 0);
bmap_set(&pmm_bitmap, 0, 1);
}
void pmm_deinitRegion(size_t base, size_t len) {
bmap_setarea(&pmm_bitmap, base, len, 1);
bmap_set(&pmm_bitmap, 0, 1);
}
void* pmm_alloc(size_t len) {
if (pmm_bitmap.blocks - pmm_bitmap.used < len) return NULL;
size_t base = bmap_findarea(&pmm_bitmap, len, 0);
size_t base = bmap_findarea(&pmm_bitmap, 1, 0);
if (base == BMAP_NOT_FOUND) return NULL;
bmap_setarea(&pmm_bitmap, base, len, 1);
bmap_set(&pmm_bitmap, base, 1);
return (void*)(base * BLOCK_SIZE);
return bmap_ptr(&pmm_bitmap, base);
}
void pmm_free(void* ptr, size_t len) {
size_t base = (size_t)ptr / BLOCK_SIZE;
bmap_setarea(&pmm_bitmap, base, len, 0);
void pmm_freePage(void* page) {
size_t base = (size_t)page / BLOCK_SIZE;
bmap_setarea(&pmm_bitmap, base, 1, 0);
bmap_set(&pmm_bitmap, 0, 1);
}
+77
View File
@@ -0,0 +1,77 @@
#include <bitmap.h>
#include <kernel.h>
#include <paging.h>
#include <pmm.h>
#include <vmm.h>
#include <string.h>
bitmap_t vmm_bitmap;
int vmm_init(void) {
vmm_bitmap.ready = 0;
vmm_bitmap.membase = KERNEL_HEAP_BASE;
vmm_bitmap.blocks = dceil(KERNEL_HEAP_SIZE, BLOCK_SIZE);
vmm_bitmap.bytes = dceil(vmm_bitmap.blocks, 8);
uint32_t bitmaploc = 0xC6000000;
debugf("%d blocks in %d bytes\n", vmm_bitmap.blocks, vmm_bitmap.bytes);
size_t pagecount = dceil(vmm_bitmap.bytes, PAGE_SIZE);
for (size_t i = 0; i < pagecount; i++) {
void* fr = pmm_allocPage();
debugf("Allocating page %d/%d...\n", i+1, pagecount);
if (fr == NULL) return 1;
debugf("Mapping page at 0x%08x to 0x%08x\n", fr, bitmaploc + i * PAGE_SIZE);
pag_mapPage(bitmaploc + i * PAGE_SIZE, (uint32_t)fr, 0);
}
// Set all pages as
vmm_bitmap.map = (void*)bitmaploc;
bmap_setall(&vmm_bitmap, 0);
bmap_set(&vmm_bitmap, 0, 1);
bmap_set(&vmm_bitmap, 8, 1);
debugf(
"[vmm] Virtual memory manager initialized.\n"
"\tBitmap manages %d blocks\n"
"\tBitmap is at 0x%08x in virtual memory\n"
"\tBitmap is %d bytes over %d pages\n",
vmm_bitmap.blocks, vmm_bitmap.map,
vmm_bitmap.bytes, pagecount
);
vmm_bitmap.ready = 1;
return 0;
}
void* vmm_alloc(size_t pages) {
size_t idx = bmap_findarea(&vmm_bitmap, pages, 0);
if (idx == BMAP_NOT_FOUND) return NULL;
void* ptr = bmap_ptr(&vmm_bitmap, idx);
bmap_setarea(&vmm_bitmap, idx * BLOCK_SIZE, pages * PAGE_SIZE, 1);
for (size_t i = 0; i < pages; i++) {
void* fr = pmm_allocPage();
if (fr == NULL) return NULL;
pag_mapPage((uint32_t)ptr + i * PAGE_SIZE, (uint32_t)fr, 0);
}
return ptr;
}
void vmm_free(void* ptr, size_t pages) {
for (size_t i = 0; i < pages; i++) {
uint32_t vaddr = (uint32_t)ptr + i * PAGE_SIZE;
uint32_t paddr = (uint32_t)pag_virtToPhys((uint32_t)ptr);
pmm_freePage((void*)paddr);
pag_umapPage(vaddr);
}
size_t base = ((size_t)ptr - KERNEL_BASE) / BLOCK_SIZE;
bmap_setarea(&vmm_bitmap, base, pages, 0);
}