summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/arch/amd64/boot.c11
-rw-r--r--src/kernel/linker.ld2
-rw-r--r--src/kernel/main.h8
-rw-r--r--src/kernel/mem/alloc.c74
-rw-r--r--src/kernel/proc.c2
5 files changed, 52 insertions, 45 deletions
diff --git a/src/kernel/arch/amd64/boot.c b/src/kernel/arch/amd64/boot.c
index 2707223..2347df4 100644
--- a/src/kernel/arch/amd64/boot.c
+++ b/src/kernel/arch/amd64/boot.c
@@ -36,15 +36,17 @@ void kmain_early(struct multiboot_info *multiboot) {
info.memtop = (void*)(long)(multiboot->mem_upper * 1024);
find_init(multiboot, &info);
+ info.fb.at = (void*)multiboot->framebuffer_addr;
+ info.fb.size = multiboot->framebuffer_pitch * multiboot->framebuffer_height;
kprintf("mem...\n");
mem_init(&info);
- kprintf("rootfs...");
+ kprintf("rootfs...\n");
vfs_root_init();
ps2_init();
serial_init();
- kprintf("ata...");
+ kprintf("ata...\n");
ata_init();
vid.b = (void*)multiboot->framebuffer_addr;
@@ -54,6 +56,11 @@ void kmain_early(struct multiboot_info *multiboot) {
vid.bpp = multiboot->framebuffer_bpp;
vid.size = vid.pitch * vid.height;
+ kprintf("kernel %8x -> %8x\n", 0, &_bss_end);
+ kprintf("init %8x -> %8x\n", info.init.at, info.init.at + info.init.size);
+ kprintf("video %8x -> %8x\n", vid.b, vid.b + vid.size);
+ kprintf("limit %8x\n", info.memtop);
+
kprintf("framebuffer at 0x%x, %ux%u bpp %u\n", vid.b, vid.width, vid.height, vid.bpp);
video_init(vid);
diff --git a/src/kernel/linker.ld b/src/kernel/linker.ld
index 278548e..a910d4e 100644
--- a/src/kernel/linker.ld
+++ b/src/kernel/linker.ld
@@ -37,4 +37,6 @@ SECTIONS
_stack_top = .;
}
_bss_end = (. + 0xFFF) & ~0xFFF; /* aligned to 4K */
+ pbitmap = _bss_end;
+ pbitmap_start = _bss_end;
}
diff --git a/src/kernel/main.h b/src/kernel/main.h
index e4ead31..edceb76 100644
--- a/src/kernel/main.h
+++ b/src/kernel/main.h
@@ -3,9 +3,13 @@
struct kmain_info {
struct {
- void *at; // page aligned
+ void *at; /* page aligned */
size_t size;
- } init; // a boot module loaded by GRUB, containing the initrd driver
+ } init; /* a boot module loaded by GRUB, containing the initrd driver */
+ struct {
+ void *at;
+ size_t size;
+ } fb; /* the framebuffer */
void *memtop;
};
diff --git a/src/kernel/mem/alloc.c b/src/kernel/mem/alloc.c
index a6f6b6d..c08b24a 100644
--- a/src/kernel/mem/alloc.c
+++ b/src/kernel/mem/alloc.c
@@ -17,32 +17,43 @@ struct malloc_hdr {
struct malloc_hdr *malloc_last = NULL;
+extern uint8_t pbitmap[], pbitmap_start[]; /* linker.ld */
+static size_t pbitmap_len;
-static void *memtop;
-static uint8_t *page_bitmap;
-static void *page_bitmap_start;
-static size_t page_bitmap_len;
+static bool bitmap_get(size_t i) {
+ size_t b = i / 8;
+ assert(b < pbitmap_len);
+ return 0 < (pbitmap[b] & (1 << (i&7)));
+}
+static void bitmap_set(size_t i, bool v) {
+ size_t b = i / 8;
+ uint8_t m = 1 << (i&7);
+ assert(b < pbitmap_len);
+ if (v) pbitmap[b] |= m;
+ else pbitmap[b] &= ~m;
+}
-static void *closest_page(void *p) {
- return (void*)(((uintptr_t)p + PAGE_MASK) & ~PAGE_MASK);
+static void bitmap_mark(void *start, size_t len) {
+ /* align to the previous page */
+ size_t off = (uintptr_t)start & PAGE_MASK;
+ start -= off;
+ len += off;
+ size_t first = ((uintptr_t)start - (uintptr_t)pbitmap_start) / PAGE_SIZE;
+ for (size_t i = 0; i * PAGE_SIZE < len; i++) {
+ if (first + i >= pbitmap_len) break;
+ bitmap_set(first + i, true);
+ }
}
void mem_init(struct kmain_info *info) {
- memtop = info->memtop;
-
- /* place the page_bitmap right at the first free spot in memory */
- page_bitmap = max((void*)&_bss_end, closest_page(info->init.at + info->init.size));
- page_bitmap_len = ((uintptr_t)memtop - (uintptr_t)page_bitmap) / PAGE_SIZE / 8;
- /* the page_bitmap_len calculation doesn't account for the space lost to itself,
- * so just take away a few pages to account for it. this could be solved with
- * actual math, but eh. */
- page_bitmap_len -= 8;
- memset(page_bitmap, 0, page_bitmap_len);
-
- /* start allocation on the page immediately following the page bitmap */
- page_bitmap_start = closest_page(page_bitmap + page_bitmap_len);
+ size_t pageamt = ((uintptr_t)info->memtop - (uintptr_t)pbitmap_start) / PAGE_SIZE;
+ pbitmap_len = pageamt / 8;
+ memset(pbitmap, 0, pbitmap_len);
+ bitmap_mark(pbitmap, pbitmap_len);
+ bitmap_mark(info->init.at, info->init.size);
+ bitmap_mark(info->fb.at, info->fb.size);
}
void mem_debugprint(void) {
@@ -59,25 +70,10 @@ void mem_debugprint(void) {
kprintf(" total 0x%x\n", total);
}
-static bool bitmap_get(size_t i) {
- size_t b = i / 8;
- assert(b < page_bitmap_len);
- return 0 < (page_bitmap[b] & (1 << (i&7)));
-}
-
-static void bitmap_set(size_t i, bool v) {
- size_t b = i / 8;
- uint8_t m = 1 << (i&7);
- assert(b < page_bitmap_len);
- if (v) page_bitmap[b] |= m;
- else page_bitmap[b] &= ~m;
-}
-
void *page_alloc(size_t pages) {
- // TODO can allocate in the framebuffer
/* i do realize how painfully slow this is */
size_t streak = 0;
- for (size_t i = 0; i < page_bitmap_len * 8; i++) {
+ for (size_t i = 0; i < pbitmap_len * 8; i++) {
if (bitmap_get(i)) {
streak = 0;
continue;
@@ -87,7 +83,7 @@ void *page_alloc(size_t pages) {
i = i + 1 - streak;
for (size_t j = 0; j < streak; j++)
bitmap_set(i + j, true);
- return page_bitmap_start + i * PAGE_SIZE;
+ return pbitmap_start + i * PAGE_SIZE;
}
}
kprintf("we ran out of memory :(\ngoodbye.\n");
@@ -102,10 +98,8 @@ void *page_zalloc(size_t pages) {
// frees `pages` consecutive pages starting from *first
void page_free(void *first_addr, size_t pages) {
- // TODO put init's pages into the allocator
- if (first_addr < page_bitmap_start)
- return;
- size_t first = (uintptr_t)(first_addr - page_bitmap_start) / PAGE_SIZE;
+ assert(first_addr >= (void*)pbitmap_start);
+ size_t first = ((uintptr_t)first_addr - (uintptr_t)pbitmap_start) / PAGE_SIZE;
for (size_t i = 0; i < pages; i++) {
assert(bitmap_get(first + i));
bitmap_set(first + i, false);
diff --git a/src/kernel/proc.c b/src/kernel/proc.c
index 6bc7057..fd02f33 100644
--- a/src/kernel/proc.c
+++ b/src/kernel/proc.c
@@ -148,7 +148,7 @@ void process_kill(struct process *p, int ret) {
p->execbuf.buf = NULL;
}
- pagedir_free(p->pages); // TODO put init's pages in the allocator
+ pagedir_free(p->pages);
// TODO VULN unbounded recursion
struct process *c2;