forked from PoliEcho-holding-org/kern
Implemented VMM!
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
/*
|
||||
* Virtual memory addresses
|
||||
*/
|
||||
#define USER_HEAP 0x10000000
|
||||
#define USER_STACK 0xBF000000
|
||||
#define USER_SHARED 0xA0000000
|
||||
#define KERNEL_BASE 0xC0000000
|
||||
#define KERNEL_SIZE 0x10000000
|
||||
#define KERNEL_MEM_BASE 0xD0000000
|
||||
#define KERNEL_MEM_SIZE 0x10000000
|
||||
#define KERNEL_SHARED 0xF0000000
|
||||
#define KERNEL_FRAMEBUF 0xC8000000
|
||||
#define USER_HEAP 0x10000000
|
||||
#define USER_STACK 0xBF000000
|
||||
#define USER_SHARED 0xA0000000
|
||||
#define KERNEL_BASE 0xC0000000
|
||||
#define KERNEL_SIZE 0x10000000
|
||||
#define KERNEL_HEAP_BASE 0xD0000000
|
||||
#define KERNEL_HEAP_SIZE 0x10000000
|
||||
#define KERNEL_SHARED 0xF0000000
|
||||
#define KERNEL_FRAMEBUF 0xC8000000
|
||||
|
||||
/*
|
||||
* Variable arguments
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user