mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-03 18:22:22 +00:00
Full PMM implementation
This commit is contained in:
@@ -40,6 +40,7 @@ typedef char* va_list;
|
||||
#define max(_x, _y) ({ typeof(_x) __x = (_x); typeof(_y) __y = (_y); __x > __y ? __x : __y; })
|
||||
#define ceil(_x, _y) ((((_x) + (_y)) (_y)) * (_y))
|
||||
#define floor(_x, _y) ((_x) - ((_x) % (_y)))
|
||||
#define dceil(_x, _y) (((_x) + (_y) - 1) / (_y))
|
||||
|
||||
/*
|
||||
* Attribute definitions
|
||||
|
||||
@@ -27,6 +27,8 @@ extern uint32_t init_pagedir[1024]; // Defined in entry.s for initial paging
|
||||
extern size_t pag_pageCount;
|
||||
|
||||
int pag_init(void);
|
||||
void pag_registerTempFrame(uint32_t target);
|
||||
uint32_t pag_tempFrame(void);
|
||||
void pag_mapPage(uint32_t vaddr, uint32_t paddr, uint32_t flags);
|
||||
uint32_t pag_umapPage(uint32_t vaddr);
|
||||
void* pag_virtToPhys(uint32_t vaddr);
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
#define PMM_BS 4096 // Block Size
|
||||
#define PMM_BPB 8 // Blocks per byte
|
||||
|
||||
extern int pmm_ready;
|
||||
|
||||
int pmm_init(void);
|
||||
void pmm_initRegion(size_t base, size_t len);
|
||||
void pmm_deinitRegion(size_t base, size_t len);
|
||||
|
||||
+10
-13
@@ -6,34 +6,31 @@
|
||||
#include <isr.h>
|
||||
#include <pmm.h>
|
||||
#include <tty.h>
|
||||
|
||||
// TODO: Commented out stuff
|
||||
#include <vmm.h>
|
||||
|
||||
__noreturn
|
||||
void kmain(void* ptr, uint32_t magic) {
|
||||
if (boot_initMB1(ptr, magic) != 0) panic("Unsupporred bootloader.");
|
||||
|
||||
// Serial console for debugging
|
||||
serial_init(COM1);
|
||||
if (serial_init(COM1) != 0) panic("Failed to initialize Serial driver.");
|
||||
debugf("\x1b[H\x1b[J\x1b[0mkern. \x1b[36m(serial console)\x1b[0m\n\n");
|
||||
|
||||
// VGA tty thingy
|
||||
tty_init();
|
||||
if (tty_init() != 0) panic("Failed to initalize TTY driver.");
|
||||
tty_puts("kern.\n\n");
|
||||
|
||||
// Memory manager init
|
||||
pmm_init();
|
||||
//vmm_init();
|
||||
// System init
|
||||
if (gdt_init() != 0) panic("Failed to initalize GDT.");
|
||||
if (isr_init() != 0) panic("Failed to initalize ISRs.");
|
||||
if (pag_init() != 0) panic("Failed to initalize Paging.");
|
||||
|
||||
gdt_init();
|
||||
isr_init();
|
||||
pag_init();
|
||||
// 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.");
|
||||
|
||||
debugf("Basic initialization complete!\n");
|
||||
|
||||
panic("kmain() reached end.");
|
||||
|
||||
// Temporary loop since panic() does not halt
|
||||
while (1);
|
||||
}
|
||||
|
||||
|
||||
+13
-3
@@ -16,6 +16,15 @@ static inline void invalidate(uint32_t vaddr) {
|
||||
__asm__ volatile ("invlpg %0" : : "m"(vaddr));
|
||||
}
|
||||
|
||||
// Temp paging thing
|
||||
uint32_t tempFrameStart;
|
||||
void pag_registerTempFrame(uint32_t target) { tempFrameStart = target; }
|
||||
uint32_t pag_tempFrame(void) {
|
||||
uint32_t fin = tempFrameStart;
|
||||
tempFrameStart += PAGE_SIZE;
|
||||
return fin;
|
||||
}
|
||||
|
||||
int pag_init(void) {
|
||||
// Unmap first MB
|
||||
init_pagedir[0] = 0;
|
||||
@@ -44,7 +53,6 @@ void pag_mapPage(uint32_t vaddr, uint32_t paddr, uint32_t flags) {
|
||||
// Switch to the init pagedir if in kernel memory
|
||||
if (vaddr >= KERNEL_BASE) {
|
||||
prevpd = pag_getPagedir();
|
||||
|
||||
if (prevpd != init_pagedir) pag_setPagedir(init_pagedir);
|
||||
}
|
||||
|
||||
@@ -57,14 +65,17 @@ 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 = (uint32_t)pmm_alloc(1);
|
||||
uint32_t tabaddr = pmm_ready ? (uint32_t)pmm_alloc(1) : pag_tempFrame();
|
||||
|
||||
pagedir[pdi] = tabaddr |
|
||||
PAGE_FLAG_PRESENT | PAGE_FLAG_WRITE | PAGE_FLAG_OWNER | flags;
|
||||
invalidate(vaddr);
|
||||
|
||||
|
||||
for (size_t i = 0; i < 1024; i++) {
|
||||
pagetab[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The actuall mapping
|
||||
@@ -85,7 +96,6 @@ uint32_t pag_umapPage(uint32_t vaddr) {
|
||||
|
||||
if (vaddr >= KERNEL_BASE) {
|
||||
prevpd = pag_getPagedir();
|
||||
|
||||
if (prevpd != init_pagedir) pag_setPagedir(init_pagedir);
|
||||
}
|
||||
|
||||
|
||||
+50
-12
@@ -1,13 +1,15 @@
|
||||
#include <bootloader.h>
|
||||
#include <kernel.h>
|
||||
#include <paging.h>
|
||||
#include <string.h>
|
||||
#include <pmm.h>
|
||||
|
||||
// Bitmap & helpers
|
||||
uint32_t* bitmap;
|
||||
int pmm_ready = 0;
|
||||
#define SET_BLOCK(_b) bitmap[(_b) / 32] |= (1 << ((_b) % 32))
|
||||
#define USET_BLOCK(_b) bitmap[(_b) / 32] &= ~(1 << ((_b) % 32))
|
||||
#define TEST_BLOCK(_b) ((bitmap[(_b) % 32] & (1 << ((_b) % 32))) ? 1 : 0)
|
||||
#define TEST_BLOCK(_b) ((bitmap[(_b) / 32] & (1 << ((_b) % 32))) ? 1 : 0)
|
||||
|
||||
// Status
|
||||
size_t usedBlocks = 0;
|
||||
@@ -15,27 +17,63 @@ size_t maxBlocks = 0;
|
||||
|
||||
int pmm_init(void) {
|
||||
size_t totalmem = (bootloader.memLower + bootloader.memUpper) * 1024;
|
||||
maxBlocks = totalmem / PMM_BS;
|
||||
maxBlocks = dceil(totalmem, PMM_BS);
|
||||
size_t bitmapBytes = dceil(maxBlocks, PMM_BPB);
|
||||
usedBlocks = maxBlocks;
|
||||
bitmap = NULL;
|
||||
|
||||
// # of pagetabs required to map the bitmap
|
||||
size_t ptcount = dceil(dceil(bitmapBytes, PAGE_SIZE), 1024);
|
||||
|
||||
// Find enough space for the bitmap
|
||||
struct boot_memmap* mmap;
|
||||
int found = 0;
|
||||
for (size_t i = 0; i < bootloader.memmapLen; i++) {
|
||||
mmap = &bootloader.memmap[i];
|
||||
|
||||
if (mmap->type != BOOT_MMAP_AVAILABLE ||
|
||||
mmap->size < maxBlocks / PMM_BPB) continue;
|
||||
if (mmap->type == BOOT_MMAP_AVAILABLE &&
|
||||
mmap->size >= maxBlocks / PMM_BPB) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) return 1; // Not enough memory
|
||||
|
||||
bitmap = (uint32_t*)mmap->base;
|
||||
break;
|
||||
uint32_t pageFrameStart = mmap->base;
|
||||
pag_registerTempFrame(pageFrameStart);
|
||||
mmap->base += ptcount * PAGE_SIZE;
|
||||
|
||||
uint32_t bitmapStart = KERNEL_HEAP - dceil(bitmapBytes, PAGE_SIZE) * PAGE_SIZE;
|
||||
uint32_t bitmapStartPhys = mmap->base;
|
||||
bitmap = (uint32_t*)bitmapStart;
|
||||
|
||||
size_t pagecount = dceil(bitmapBytes, PAGE_SIZE);
|
||||
for (size_t i = 0; i < pagecount; i++) {
|
||||
// We can't unmap this with pag_umapPage(), it's in a tempFrame
|
||||
pag_mapPage(bitmapStart + i * PAGE_SIZE, mmap->base + i * PAGE_SIZE, 0);
|
||||
}
|
||||
|
||||
if (bitmap == NULL) return 1;
|
||||
|
||||
// Set all blocks as used
|
||||
memset(bitmap, 1, maxBlocks / PMM_BPB);
|
||||
memset(bitmap, 0xff, maxBlocks / PMM_BPB);
|
||||
|
||||
for (size_t i = 0; i < bootloader.memmapLen; i++) {
|
||||
mmap = &bootloader.memmap[i];
|
||||
|
||||
if (mmap->type == BOOT_MMAP_AVAILABLE) pmm_initRegion(mmap->base, mmap->size);
|
||||
}
|
||||
|
||||
pmm_deinitRegion(bitmapStartPhys, bitmapBytes);
|
||||
pmm_deinitRegion(pageFrameStart, ptcount * PAGE_SIZE);
|
||||
|
||||
debugf(
|
||||
"[pmm] Physical memory manager initialized.\n"
|
||||
"\tAvailable memory: %d blocks free (%d bytes)\n"
|
||||
"\tBitmap at phys(%08x), virt(%08x), %d bytes\n",
|
||||
maxBlocks - usedBlocks, (maxBlocks - usedBlocks) * PMM_BS,
|
||||
bitmapStartPhys, bitmapStart, bitmapBytes
|
||||
);
|
||||
|
||||
pmm_ready = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -45,11 +83,11 @@ int findFreeBlocks(size_t blockCount) {
|
||||
uint32_t max = maxBlocks / 32;
|
||||
uint32_t freeCount = 0;
|
||||
for (size_t i = 0; i < max; i++) {
|
||||
// We don't have to check, cause it's all reserved
|
||||
// We don't have to check, cause it's all used
|
||||
if (bitmap[i] == 0xffffffff) continue;
|
||||
|
||||
for (uint8_t j = 0; j < 32; j++) {
|
||||
if (TEST_BLOCK(i * PMM_BPB + j)) freeCount++;
|
||||
if (TEST_BLOCK(i * PMM_BPB + j) == 0) freeCount++;
|
||||
else freeCount = 0;
|
||||
|
||||
if (freeCount >= blockCount) return i * PMM_BPB + j;
|
||||
@@ -78,8 +116,8 @@ void pmm_deinitRegion(size_t base, size_t len) {
|
||||
uint32_t blockCount = len / PMM_BS;
|
||||
|
||||
while (blockCount-- > 0) {
|
||||
align++;
|
||||
SET_BLOCK(align); // We can't increment here, because macros -_(._.)_-
|
||||
align++;
|
||||
usedBlocks++;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user