forked from PoliEcho-holding-org/kern
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 max(_x, _y) ({ typeof(_x) __x = (_x); typeof(_y) __y = (_y); __x > __y ? __x : __y; })
|
||||||
#define ceil(_x, _y) ((((_x) + (_y)) (_y)) * (_y))
|
#define ceil(_x, _y) ((((_x) + (_y)) (_y)) * (_y))
|
||||||
#define floor(_x, _y) ((_x) - ((_x) % (_y)))
|
#define floor(_x, _y) ((_x) - ((_x) % (_y)))
|
||||||
|
#define dceil(_x, _y) (((_x) + (_y) - 1) / (_y))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Attribute definitions
|
* Attribute definitions
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ extern uint32_t init_pagedir[1024]; // Defined in entry.s for initial paging
|
|||||||
extern size_t pag_pageCount;
|
extern size_t pag_pageCount;
|
||||||
|
|
||||||
int pag_init(void);
|
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);
|
void pag_mapPage(uint32_t vaddr, uint32_t paddr, uint32_t flags);
|
||||||
uint32_t pag_umapPage(uint32_t vaddr);
|
uint32_t pag_umapPage(uint32_t vaddr);
|
||||||
void* pag_virtToPhys(uint32_t vaddr);
|
void* pag_virtToPhys(uint32_t vaddr);
|
||||||
|
|||||||
@@ -6,6 +6,8 @@
|
|||||||
#define PMM_BS 4096 // Block Size
|
#define PMM_BS 4096 // Block Size
|
||||||
#define PMM_BPB 8 // Blocks per byte
|
#define PMM_BPB 8 // Blocks per byte
|
||||||
|
|
||||||
|
extern int pmm_ready;
|
||||||
|
|
||||||
int pmm_init(void);
|
int pmm_init(void);
|
||||||
void pmm_initRegion(size_t base, size_t len);
|
void pmm_initRegion(size_t base, size_t len);
|
||||||
void pmm_deinitRegion(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 <isr.h>
|
||||||
#include <pmm.h>
|
#include <pmm.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
|
#include <vmm.h>
|
||||||
// TODO: Commented out stuff
|
|
||||||
|
|
||||||
__noreturn
|
__noreturn
|
||||||
void kmain(void* ptr, uint32_t magic) {
|
void kmain(void* ptr, uint32_t magic) {
|
||||||
if (boot_initMB1(ptr, magic) != 0) panic("Unsupporred bootloader.");
|
if (boot_initMB1(ptr, magic) != 0) panic("Unsupporred bootloader.");
|
||||||
|
|
||||||
// Serial console for debugging
|
// 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");
|
debugf("\x1b[H\x1b[J\x1b[0mkern. \x1b[36m(serial console)\x1b[0m\n\n");
|
||||||
|
|
||||||
// VGA tty thingy
|
// VGA tty thingy
|
||||||
tty_init();
|
if (tty_init() != 0) panic("Failed to initalize TTY driver.");
|
||||||
tty_puts("kern.\n\n");
|
tty_puts("kern.\n\n");
|
||||||
|
|
||||||
// Memory manager init
|
// System init
|
||||||
pmm_init();
|
if (gdt_init() != 0) panic("Failed to initalize GDT.");
|
||||||
//vmm_init();
|
if (isr_init() != 0) panic("Failed to initalize ISRs.");
|
||||||
|
if (pag_init() != 0) panic("Failed to initalize Paging.");
|
||||||
|
|
||||||
gdt_init();
|
// Memory manager init
|
||||||
isr_init();
|
if (pmm_init() != 0) panic("Failed to initalize Physical Memory Manager.");
|
||||||
pag_init();
|
//if (vmm_init() != 0) panic("Failed to initalize Virtual Memory Manager.");
|
||||||
|
|
||||||
debugf("Basic initialization complete!\n");
|
debugf("Basic initialization complete!\n");
|
||||||
|
|
||||||
panic("kmain() reached end.");
|
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));
|
__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) {
|
int pag_init(void) {
|
||||||
// Unmap first MB
|
// Unmap first MB
|
||||||
init_pagedir[0] = 0;
|
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
|
// Switch to the init pagedir if in kernel memory
|
||||||
if (vaddr >= KERNEL_BASE) {
|
if (vaddr >= KERNEL_BASE) {
|
||||||
prevpd = pag_getPagedir();
|
prevpd = pag_getPagedir();
|
||||||
|
|
||||||
if (prevpd != init_pagedir) pag_setPagedir(init_pagedir);
|
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
|
// Allocate a pagetab if it didn't exist
|
||||||
if (!(pagedir[pdi] & PAGE_FLAG_PRESENT)) {
|
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 |
|
pagedir[pdi] = tabaddr |
|
||||||
PAGE_FLAG_PRESENT | PAGE_FLAG_WRITE | PAGE_FLAG_OWNER | flags;
|
PAGE_FLAG_PRESENT | PAGE_FLAG_WRITE | PAGE_FLAG_OWNER | flags;
|
||||||
invalidate(vaddr);
|
invalidate(vaddr);
|
||||||
|
|
||||||
|
|
||||||
for (size_t i = 0; i < 1024; i++) {
|
for (size_t i = 0; i < 1024; i++) {
|
||||||
pagetab[i] = 0;
|
pagetab[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The actuall mapping
|
// The actuall mapping
|
||||||
@@ -85,7 +96,6 @@ uint32_t pag_umapPage(uint32_t vaddr) {
|
|||||||
|
|
||||||
if (vaddr >= KERNEL_BASE) {
|
if (vaddr >= KERNEL_BASE) {
|
||||||
prevpd = pag_getPagedir();
|
prevpd = pag_getPagedir();
|
||||||
|
|
||||||
if (prevpd != init_pagedir) pag_setPagedir(init_pagedir);
|
if (prevpd != init_pagedir) pag_setPagedir(init_pagedir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+50
-12
@@ -1,13 +1,15 @@
|
|||||||
#include <bootloader.h>
|
#include <bootloader.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <paging.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pmm.h>
|
#include <pmm.h>
|
||||||
|
|
||||||
// Bitmap & helpers
|
// Bitmap & helpers
|
||||||
uint32_t* bitmap;
|
uint32_t* bitmap;
|
||||||
|
int pmm_ready = 0;
|
||||||
#define SET_BLOCK(_b) bitmap[(_b) / 32] |= (1 << ((_b) % 32))
|
#define SET_BLOCK(_b) bitmap[(_b) / 32] |= (1 << ((_b) % 32))
|
||||||
#define USET_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
|
// Status
|
||||||
size_t usedBlocks = 0;
|
size_t usedBlocks = 0;
|
||||||
@@ -15,27 +17,63 @@ size_t maxBlocks = 0;
|
|||||||
|
|
||||||
int pmm_init(void) {
|
int pmm_init(void) {
|
||||||
size_t totalmem = (bootloader.memLower + bootloader.memUpper) * 1024;
|
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;
|
usedBlocks = maxBlocks;
|
||||||
bitmap = NULL;
|
bitmap = NULL;
|
||||||
|
|
||||||
|
// # of pagetabs required to map the bitmap
|
||||||
|
size_t ptcount = dceil(dceil(bitmapBytes, PAGE_SIZE), 1024);
|
||||||
|
|
||||||
// Find enough space for the bitmap
|
// Find enough space for the bitmap
|
||||||
struct boot_memmap* mmap;
|
struct boot_memmap* mmap;
|
||||||
|
int found = 0;
|
||||||
for (size_t i = 0; i < bootloader.memmapLen; i++) {
|
for (size_t i = 0; i < bootloader.memmapLen; i++) {
|
||||||
mmap = &bootloader.memmap[i];
|
mmap = &bootloader.memmap[i];
|
||||||
|
|
||||||
if (mmap->type != BOOT_MMAP_AVAILABLE ||
|
if (mmap->type == BOOT_MMAP_AVAILABLE &&
|
||||||
mmap->size < maxBlocks / PMM_BPB) continue;
|
mmap->size >= maxBlocks / PMM_BPB) {
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) return 1; // Not enough memory
|
||||||
|
|
||||||
bitmap = (uint32_t*)mmap->base;
|
uint32_t pageFrameStart = mmap->base;
|
||||||
break;
|
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
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -45,11 +83,11 @@ int findFreeBlocks(size_t blockCount) {
|
|||||||
uint32_t max = maxBlocks / 32;
|
uint32_t max = maxBlocks / 32;
|
||||||
uint32_t freeCount = 0;
|
uint32_t freeCount = 0;
|
||||||
for (size_t i = 0; i < max; i++) {
|
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;
|
if (bitmap[i] == 0xffffffff) continue;
|
||||||
|
|
||||||
for (uint8_t j = 0; j < 32; j++) {
|
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;
|
else freeCount = 0;
|
||||||
|
|
||||||
if (freeCount >= blockCount) return i * PMM_BPB + j;
|
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;
|
uint32_t blockCount = len / PMM_BS;
|
||||||
|
|
||||||
while (blockCount-- > 0) {
|
while (blockCount-- > 0) {
|
||||||
align++;
|
|
||||||
SET_BLOCK(align); // We can't increment here, because macros -_(._.)_-
|
SET_BLOCK(align); // We can't increment here, because macros -_(._.)_-
|
||||||
|
align++;
|
||||||
usedBlocks++;
|
usedBlocks++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user