mirror of
https://github.com/Tom-on64/kern.git
synced 2026-11-04 02:23:10 +00:00
Added bitmap_t type and bmap_* functions & used them in PMM
This commit is contained in:
@@ -0,0 +1,23 @@
|
|||||||
|
#ifndef _BITMAP_H
|
||||||
|
#define _BITMAP_H
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -11,7 +11,9 @@
|
|||||||
#define USER_STACK 0xBF000000
|
#define USER_STACK 0xBF000000
|
||||||
#define USER_SHARED 0xA0000000
|
#define USER_SHARED 0xA0000000
|
||||||
#define KERNEL_BASE 0xC0000000
|
#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_SHARED 0xF0000000
|
||||||
#define KERNEL_FRAMEBUF 0xC8000000
|
#define KERNEL_FRAMEBUF 0xC8000000
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,15 @@
|
|||||||
#ifndef _PMM_H
|
#ifndef _PMM_H
|
||||||
#define _PMM_H
|
#define _PMM_H
|
||||||
|
|
||||||
#include <multiboot.h>
|
#include <bitmap.h>
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
#define PMM_BS 4096 // Block Size
|
extern bitmap_t pmm_bitmap;
|
||||||
#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);
|
||||||
void* pmm_alloc(size_t blockCount);
|
void* pmm_alloc(size_t len);
|
||||||
void pmm_free(void* ptr, size_t blockCount);
|
void pmm_free(void* ptr, size_t len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#include <kernel.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <bitmap.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <isr.h>
|
#include <isr.h>
|
||||||
#include <pmm.h>
|
#include <pmm.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
#include <vmm.h>
|
|
||||||
|
|
||||||
__noreturn
|
__noreturn
|
||||||
void kmain(void* ptr, uint32_t magic) {
|
void kmain(void* ptr, uint32_t magic) {
|
||||||
|
|||||||
+43
-85
@@ -4,26 +4,18 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pmm.h>
|
#include <pmm.h>
|
||||||
|
|
||||||
// Bitmap & helpers
|
// Bitmap
|
||||||
uint32_t* bitmap;
|
bitmap_t pmm_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;
|
|
||||||
|
|
||||||
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 = dceil(totalmem, PMM_BS);
|
|
||||||
size_t bitmapBytes = dceil(maxBlocks, PMM_BPB);
|
pmm_bitmap.blocks = dceil(totalmem, BLOCK_SIZE);
|
||||||
usedBlocks = maxBlocks;
|
pmm_bitmap.bytes = dceil(pmm_bitmap.blocks, 8);
|
||||||
bitmap = NULL;
|
pmm_bitmap.map = NULL;
|
||||||
|
|
||||||
// # of pagetabs required to map the bitmap
|
// # 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
|
// Find enough space for the bitmap
|
||||||
struct boot_memmap* mmap;
|
struct boot_memmap* mmap;
|
||||||
@@ -31,8 +23,7 @@ int pmm_init(void) {
|
|||||||
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 >= pmm_bitmap.bytes) {
|
||||||
mmap->size >= maxBlocks / PMM_BPB) {
|
|
||||||
found = 1;
|
found = 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -43,109 +34,76 @@ int pmm_init(void) {
|
|||||||
pag_registerTempFrame(pageFrameStart);
|
pag_registerTempFrame(pageFrameStart);
|
||||||
mmap->base += ptcount * PAGE_SIZE;
|
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;
|
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++) {
|
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);
|
pag_mapPage(bitmapStart + i * PAGE_SIZE, mmap->base + i * PAGE_SIZE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set all blocks as used
|
// 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++) {
|
for (size_t i = 0; i < bootloader.memmapLen; i++) {
|
||||||
mmap = &bootloader.memmap[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);
|
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);
|
pmm_deinitRegion(pageFrameStart, ptcount * PAGE_SIZE);
|
||||||
|
|
||||||
|
// Beatifull print statement :)
|
||||||
debugf(
|
debugf(
|
||||||
"[pmm] Physical memory manager initialized.\n"
|
"[pmm] Physical memory manager initialized.\n"
|
||||||
"\tAvailable memory: %d blocks free (%d bytes)\n"
|
"\tAvailable memory: %d blocks free (%d bytes)\n"
|
||||||
"\tBitmap at phys(%08x), virt(%08x), %d bytes\n",
|
"\tBitmap at 0x%08x mapped to 0x%08x\n"
|
||||||
maxBlocks - usedBlocks, (maxBlocks - usedBlocks) * PMM_BS,
|
"\tBitmap is %d bytes contained in %d pages\n",
|
||||||
bitmapStartPhys, bitmapStart, bitmapBytes
|
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;
|
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) {
|
void pmm_initRegion(size_t base, size_t len) {
|
||||||
uint32_t align = base / PMM_BS;
|
bmap_setarea(&pmm_bitmap, base, len, 0);
|
||||||
uint32_t blockCount = len / PMM_BS;
|
bmap_set(&pmm_bitmap, 0, 1);
|
||||||
|
|
||||||
while (blockCount-- > 0) {
|
|
||||||
USET_BLOCK(align);
|
|
||||||
align++;
|
|
||||||
usedBlocks--;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_BLOCK(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmm_deinitRegion(size_t base, size_t len) {
|
void pmm_deinitRegion(size_t base, size_t len) {
|
||||||
uint32_t align = base / PMM_BS;
|
bmap_setarea(&pmm_bitmap, base, len, 1);
|
||||||
uint32_t blockCount = len / PMM_BS;
|
bmap_set(&pmm_bitmap, 0, 1);
|
||||||
|
|
||||||
while (blockCount-- > 0) {
|
|
||||||
SET_BLOCK(align); // We can't increment here, because macros -_(._.)_-
|
|
||||||
align++;
|
|
||||||
usedBlocks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_BLOCK(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void* pmm_alloc(size_t blockCount) {
|
void* pmm_alloc(size_t len) {
|
||||||
if ((maxBlocks - usedBlocks) < blockCount) return NULL;
|
if (pmm_bitmap.blocks - pmm_bitmap.used < len) return NULL;
|
||||||
|
|
||||||
int startBlock = findFreeBlocks(blockCount);
|
size_t base = bmap_findarea(&pmm_bitmap, len, 0);
|
||||||
if (startBlock == -1) return NULL;
|
if (base == BMAP_NOT_FOUND) return NULL;
|
||||||
|
|
||||||
for (size_t i = 0; i < blockCount; i++) {
|
bmap_setarea(&pmm_bitmap, base, len, 1);
|
||||||
SET_BLOCK(startBlock + i);
|
|
||||||
usedBlocks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void*)(startBlock * PMM_BS);
|
return (void*)(base * BLOCK_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmm_free(void* ptr, size_t blockCount) {
|
void pmm_free(void* ptr, size_t len) {
|
||||||
size_t startBlock = (size_t)ptr / PMM_BS;
|
size_t base = (size_t)ptr / BLOCK_SIZE;
|
||||||
|
bmap_setarea(&pmm_bitmap, base, len, 0);
|
||||||
for (size_t i = 0; i < blockCount; i++) {
|
bmap_set(&pmm_bitmap, 0, 1);
|
||||||
USET_BLOCK(startBlock + i);
|
|
||||||
usedBlocks--;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_BLOCK(0); // Make sure block 0 is always set
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
#include <vsnprintf.h>
|
#include <vsnprintf.h>
|
||||||
|
|
||||||
int pf_isdigit(char c) {
|
int pf_isdigit(char c) {
|
||||||
@@ -25,10 +27,6 @@ char* pf_itoa(uint32_t num, uint8_t base) {
|
|||||||
return &buf[i + 1];
|
return &buf[i + 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
char* pf_ftoa(float f) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
int vsnprintf(char* buf, size_t len, char* fmt, va_list args) {
|
int vsnprintf(char* buf, size_t len, char* fmt, va_list args) {
|
||||||
size_t i = 0;
|
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
|
case 'x': // Unsigned hex int
|
||||||
s = pf_itoa(va_arg(args, unsigned int), 16);
|
s = pf_itoa(va_arg(args, unsigned int), 16);
|
||||||
goto string;
|
goto string;
|
||||||
case 'f': // Float
|
// TODO: %f for float
|
||||||
s = pf_ftoa(va_arg(args, double));
|
|
||||||
goto string;
|
|
||||||
case 's': // String
|
case 's': // String
|
||||||
s = va_arg(args, char*);
|
s = va_arg(args, char*);
|
||||||
string: // Prints the string in s
|
string: // Prints the string in s
|
||||||
if (s == NULL) s = "(null)";
|
if (s == NULL) s = "(null)";
|
||||||
|
width -= strlen(s);
|
||||||
|
while (width-- >= 0 && i < len) buf[i++] = pad;
|
||||||
while (*s != '\0' && i < len) buf[i++] = *s++;
|
while (*s != '\0' && i < len) buf[i++] = *s++;
|
||||||
break;
|
break;
|
||||||
default: // Something else
|
default: // Something else
|
||||||
|
|||||||
Reference in New Issue
Block a user