diff --git a/kernel/include/bitmap.h b/kernel/include/bitmap.h new file mode 100644 index 0000000..1d093c9 --- /dev/null +++ b/kernel/include/bitmap.h @@ -0,0 +1,23 @@ +#ifndef _BITMAP_H +#define _BITMAP_H + +#include + +#define BLOCK_SIZE 4096 +#define BMAP_NOT_FOUND ((size_t)-1) + +typedef struct bitmap_t { + void* map; + size_t blocks; // Eqiv. to # of bits + size_t bytes; // ceil(blocks / 8) + size_t used; // # of bits set to 0 + int ready; +} bitmap_t; + +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); +void bmap_setall(bitmap_t* map, int val); +size_t bmap_findarea(bitmap_t* map, size_t len, int val); + +#endif diff --git a/kernel/include/kernel.h b/kernel/include/kernel.h index b5b88ca..7369137 100644 --- a/kernel/include/kernel.h +++ b/kernel/include/kernel.h @@ -11,7 +11,9 @@ #define USER_STACK 0xBF000000 #define USER_SHARED 0xA0000000 #define KERNEL_BASE 0xC0000000 -#define KERNEL_HEAP 0xD0000000 +#define KERNEL_SIZE 0x10000000 +#define KERNEL_MEM_BASE 0xD0000000 +#define KERNEL_MEM_SIZE 0x10000000 #define KERNEL_SHARED 0xF0000000 #define KERNEL_FRAMEBUF 0xC8000000 diff --git a/kernel/include/pmm.h b/kernel/include/pmm.h index 26369f0..047303c 100644 --- a/kernel/include/pmm.h +++ b/kernel/include/pmm.h @@ -1,17 +1,15 @@ #ifndef _PMM_H #define _PMM_H -#include +#include +#include -#define PMM_BS 4096 // Block Size -#define PMM_BPB 8 // Blocks per byte - -extern int pmm_ready; +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 blockCount); -void pmm_free(void* ptr, size_t blockCount); +void* pmm_alloc(size_t len); +void pmm_free(void* ptr, size_t len); #endif diff --git a/kernel/src/bitmap.c b/kernel/src/bitmap.c new file mode 100644 index 0000000..7107514 --- /dev/null +++ b/kernel/src/bitmap.c @@ -0,0 +1,47 @@ +#include +#include + +#include + +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)); +} + +int bmap_get(bitmap_t* map, size_t bit) { + uint32_t* p = (uint32_t*)map->map; + return (p[bit / 32] & (1 << (bit % 32))) ? 1 : 0; +} + +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; + + while (count-- > 0) { + bmap_set(map, align++, val); + map->used += (val) ? 1 : -1; + } +} + +void bmap_setall(bitmap_t* map, int val) { + uint8_t b = (val) ? 0xff : 0; + memset(map->map, b, map->bytes); + if (val) map->used = map->blocks; + else map->used = 0; +} + +size_t bmap_findarea(bitmap_t* map, size_t len, int val) { + if (len == 0) return BMAP_NOT_FOUND; + + uint32_t found = 0; + for (size_t i = 0; i < map->blocks; i++) { + if (bmap_get(map, i) == val) found++; + else found = 0; + + if (found >= len) return i - found; + } + + return BMAP_NOT_FOUND; +} + diff --git a/kernel/src/kernel.c b/kernel/src/kernel.c index c6e2d59..a6dba2c 100644 --- a/kernel/src/kernel.c +++ b/kernel/src/kernel.c @@ -6,7 +6,6 @@ #include #include #include -#include __noreturn void kmain(void* ptr, uint32_t magic) { diff --git a/kernel/src/pmm.c b/kernel/src/pmm.c index b897465..69a6e54 100644 --- a/kernel/src/pmm.c +++ b/kernel/src/pmm.c @@ -4,26 +4,18 @@ #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) - -// Status -size_t usedBlocks = 0; -size_t maxBlocks = 0; +// Bitmap +bitmap_t pmm_bitmap; int pmm_init(void) { size_t totalmem = (bootloader.memLower + bootloader.memUpper) * 1024; - maxBlocks = dceil(totalmem, PMM_BS); - size_t bitmapBytes = dceil(maxBlocks, PMM_BPB); - usedBlocks = maxBlocks; - bitmap = NULL; + + pmm_bitmap.blocks = dceil(totalmem, BLOCK_SIZE); + pmm_bitmap.bytes = dceil(pmm_bitmap.blocks, 8); + pmm_bitmap.map = NULL; // # of pagetabs required to map the bitmap - size_t ptcount = dceil(dceil(bitmapBytes, PAGE_SIZE), 1024); + size_t ptcount = dceil(dceil(pmm_bitmap.bytes, PAGE_SIZE), 1024); // Find enough space for the bitmap struct boot_memmap* mmap; @@ -31,8 +23,7 @@ int pmm_init(void) { for (size_t i = 0; i < bootloader.memmapLen; i++) { mmap = &bootloader.memmap[i]; - if (mmap->type == BOOT_MMAP_AVAILABLE && - mmap->size >= maxBlocks / PMM_BPB) { + if (mmap->type == BOOT_MMAP_AVAILABLE && mmap->size >= pmm_bitmap.bytes) { found = 1; break; } @@ -43,109 +34,76 @@ int pmm_init(void) { pag_registerTempFrame(pageFrameStart); mmap->base += ptcount * PAGE_SIZE; - uint32_t bitmapStart = KERNEL_HEAP - dceil(bitmapBytes, PAGE_SIZE) * PAGE_SIZE; + uint32_t bitmapStart = KERNEL_MEM_BASE - dceil(pmm_bitmap.bytes, PAGE_SIZE) * PAGE_SIZE; uint32_t bitmapStartPhys = mmap->base; - bitmap = (uint32_t*)bitmapStart; + pmm_bitmap.map = (void*)bitmapStart; - size_t pagecount = dceil(bitmapBytes, PAGE_SIZE); + size_t pagecount = dceil(pmm_bitmap.bytes, PAGE_SIZE); for (size_t i = 0; i < pagecount; i++) { - // We can't unmap this with pag_umapPage(), it's in a tempFrame + // NOTE: 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); } // Set all blocks as used - memset(bitmap, 0xff, maxBlocks / PMM_BPB); + bmap_setall(&pmm_bitmap, 1); + + debugf("[pmm] Memory map:\n"); // Use the loop to also print the memmap for (size_t i = 0; i < bootloader.memmapLen; i++) { mmap = &bootloader.memmap[i]; + if (mmap->size == 0) continue; // Ignore dummy entries if (mmap->type == BOOT_MMAP_AVAILABLE) pmm_initRegion(mmap->base, mmap->size); + + // Print entry + debugf("\tRegion %2d: 0x%08x - 0x%08x (%d bytes) %s\n", + i + 1, mmap->base, mmap->base + mmap->size - 1, mmap->size, + (mmap->type == BOOT_MMAP_AVAILABLE) ? "AVAILABLE" : "RESERVED"); } - pmm_deinitRegion(bitmapStartPhys, bitmapBytes); + pmm_deinitRegion(bitmapStartPhys, pmm_bitmap.bytes); pmm_deinitRegion(pageFrameStart, ptcount * PAGE_SIZE); + // Beatifull print statement :) 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 + "\tBitmap at 0x%08x mapped to 0x%08x\n" + "\tBitmap is %d bytes contained in %d pages\n", + pmm_bitmap.blocks - pmm_bitmap.used, + (pmm_bitmap.blocks - pmm_bitmap.used) * BLOCK_SIZE, + bitmapStartPhys, bitmapStart, pmm_bitmap.bytes, pagecount ); - pmm_ready = 1; + pmm_bitmap.ready = 1; return 0; } -int findFreeBlocks(size_t blockCount) { - if (blockCount == 0) return -1; - - 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 used - if (bitmap[i] == 0xffffffff) continue; - - for (uint8_t j = 0; j < 32; j++) { - if (TEST_BLOCK(i * PMM_BPB + j) == 0) freeCount++; - else freeCount = 0; - - if (freeCount >= blockCount) return i * PMM_BPB + j; - } - } - - // We didn't find enough free memory :( - return -1; -} void pmm_initRegion(size_t base, size_t len) { - uint32_t align = base / PMM_BS; - uint32_t blockCount = len / PMM_BS; - - while (blockCount-- > 0) { - USET_BLOCK(align); - align++; - usedBlocks--; - } - - SET_BLOCK(0); + bmap_setarea(&pmm_bitmap, base, len, 0); + bmap_set(&pmm_bitmap, 0, 1); } void pmm_deinitRegion(size_t base, size_t len) { - uint32_t align = base / PMM_BS; - uint32_t blockCount = len / PMM_BS; - - while (blockCount-- > 0) { - SET_BLOCK(align); // We can't increment here, because macros -_(._.)_- - align++; - usedBlocks++; - } - - SET_BLOCK(0); + bmap_setarea(&pmm_bitmap, base, len, 1); + bmap_set(&pmm_bitmap, 0, 1); } -void* pmm_alloc(size_t blockCount) { - if ((maxBlocks - usedBlocks) < blockCount) return NULL; +void* pmm_alloc(size_t len) { + if (pmm_bitmap.blocks - pmm_bitmap.used < len) return NULL; - int startBlock = findFreeBlocks(blockCount); - if (startBlock == -1) return NULL; + size_t base = bmap_findarea(&pmm_bitmap, len, 0); + if (base == BMAP_NOT_FOUND) return NULL; + + bmap_setarea(&pmm_bitmap, base, len, 1); - for (size_t i = 0; i < blockCount; i++) { - SET_BLOCK(startBlock + i); - usedBlocks++; - } - - return (void*)(startBlock * PMM_BS); + return (void*)(base * BLOCK_SIZE); } -void pmm_free(void* ptr, size_t blockCount) { - size_t startBlock = (size_t)ptr / PMM_BS; - - for (size_t i = 0; i < blockCount; i++) { - USET_BLOCK(startBlock + i); - usedBlocks--; - } - - SET_BLOCK(0); // Make sure block 0 is always set +void pmm_free(void* ptr, size_t len) { + size_t base = (size_t)ptr / BLOCK_SIZE; + bmap_setarea(&pmm_bitmap, base, len, 0); + bmap_set(&pmm_bitmap, 0, 1); } diff --git a/kernel/src/vsnprintf.c b/kernel/src/vsnprintf.c index 544ecc7..2f033bc 100644 --- a/kernel/src/vsnprintf.c +++ b/kernel/src/vsnprintf.c @@ -1,4 +1,6 @@ #include +#include + #include int pf_isdigit(char c) { @@ -25,10 +27,6 @@ char* pf_itoa(uint32_t num, uint8_t base) { return &buf[i + 1]; } -char* pf_ftoa(float f) { - return NULL; -} - int vsnprintf(char* buf, size_t len, char* fmt, va_list args) { size_t i = 0; @@ -68,13 +66,13 @@ int vsnprintf(char* buf, size_t len, char* fmt, va_list args) { case 'x': // Unsigned hex int s = pf_itoa(va_arg(args, unsigned int), 16); goto string; - case 'f': // Float - s = pf_ftoa(va_arg(args, double)); - goto string; + // TODO: %f for float case 's': // String s = va_arg(args, char*); string: // Prints the string in s if (s == NULL) s = "(null)"; + width -= strlen(s); + while (width-- >= 0 && i < len) buf[i++] = pad; while (*s != '\0' && i < len) buf[i++] = *s++; break; default: // Something else