diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index f75c35c..b5b88ca 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -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 diff --git a/kernel/include/paging.h b/kernel/include/paging.h index 117cbe1..f8ccf40 100644 --- a/kernel/include/paging.h +++ b/kernel/include/paging.h @@ -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); diff --git a/kernel/include/pmm.h b/kernel/include/pmm.h index 72ac783..26369f0 100644 --- a/kernel/include/pmm.h +++ b/kernel/include/pmm.h @@ -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); diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index 42c4484..c6e2d59 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -6,34 +6,31 @@ #include #include #include - -// TODO: Commented out stuff +#include __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); } diff --git a/kernel/src/paging.c b/kernel/src/paging.c index b0ad0b5..3cdcf64 100644 --- a/kernel/src/paging.c +++ b/kernel/src/paging.c @@ -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); } diff --git a/kernel/src/pmm.c b/kernel/src/pmm.c index 5a0c6e9..b897465 100644 --- a/kernel/src/pmm.c +++ b/kernel/src/pmm.c @@ -1,13 +1,15 @@ #include #include +#include #include #include // 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++; }