From 269f7f6845a6e001a41204032b672d3d423a4b3d Mon Sep 17 00:00:00 2001 From: rami Date: Tue, 2 Jul 2024 18:44:36 -0400 Subject: [PATCH] physical mem manager --- Makefile | 4 +- include/kernel/kernel.h | 6 +- include/kernel/mem.h | 26 ++++++++ include/kernel/multiboot.h | 2 +- kernel/init.asm | 1 - kernel/kernel.c | 9 ++- kernel/mem.c | 127 +++++++++++++++++++++++++++++++++++++ 7 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 include/kernel/mem.h create mode 100644 kernel/mem.c diff --git a/Makefile b/Makefile index 6cd44e8..f562848 100644 --- a/Makefile +++ b/Makefile @@ -20,8 +20,8 @@ ISO := Hazel.iso CFLAGS := -ffreestanding -Wall -Wextra -Werror -I $(INCLUDEDIR) -I lib LDFLAGS := -ffreestanding -nostdlib -lgcc -T kernel/kernel.ld QEMUFLAGS := -cdrom $(BUILDDIR)/$(ISO) \ - -d int \ - -serial stdio + -m 512M \ + -serial stdio $(BUILDDIR)/$(KIMG): $(KOBJ) $(LOBJ) $(CC) $^ -o $@ $(LDFLAGS) diff --git a/include/kernel/kernel.h b/include/kernel/kernel.h index 3e69dbc..23b8b07 100644 --- a/include/kernel/kernel.h +++ b/include/kernel/kernel.h @@ -8,8 +8,10 @@ #define CHECK_FLAG(x, n) (x & (1< +#include + +#define KERNEL_START 0x1000000 // 1 MiB +#define KERNEL_SIZE 0xC800 // 50 KiB +#define BLOCK_SIZE 4096 +#define BITS 32 + +uint8_t mmap_init(void); +void mmap_set_block(int block); +void mmap_free_block(int block); +void *mmap_find_first_free_block(void); +void *mmap_block_to_physical(int block); + +void memset(void *s, int c, uint32_t len); +void memcpy(void *dest, void *src, int n); + +typedef struct { + void *data; + void *next; +} linked_mem_t; + +#endif diff --git a/include/kernel/multiboot.h b/include/kernel/multiboot.h index 5ebf77e..c2e781d 100644 --- a/include/kernel/multiboot.h +++ b/include/kernel/multiboot.h @@ -40,7 +40,7 @@ struct multiboot_mmap_entry #define MULTIBOOT_MEMORY_BADRAM 5 uint32_t type; } __attribute__((packed)); -typedef struct multiboot_mmap_entry multiboot_memory_map_t; +typedef struct multiboot_mmap_entry multi_mmap_t; #endif diff --git a/kernel/init.asm b/kernel/init.asm index 0477f6e..6abe6a5 100644 --- a/kernel/init.asm +++ b/kernel/init.asm @@ -43,7 +43,6 @@ _start: mov esp, stack_bottom mov ebp, esp push ebx - and esp, 0xfffffff0 extern kernel call kernel cli diff --git a/kernel/kernel.c b/kernel/kernel.c index b6b6aef..1d85259 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -28,13 +29,15 @@ void sleep(int delay) { void kernel(multiboot_info_t *info) { if (!CHECK_FLAG(info->flags, 6)) goto halt; // Memory map if (!CHECK_FLAG(info->flags, 12)) goto halt; // VBE data - ctx.mem_map = (multiboot_memory_map_t *)info->memmapaddress; - ctx.mem_map_len = info->memmaplength; + ctx.multi_mmap = (multi_mmap_t *)info->memmapaddress; + ctx.multi_mmap_size = info->memmaplength; if (serial_port_init(COM1)) ctx.log_method = LOG_COM1; - LOG("Kernel log being sent to COM1\n"); + if (!mmap_init()) goto halt; + LOG("%d bytes of RAM detected\nCreated a %d byte large physical memory map at 0x%08X\n", ctx.mmap_size*BLOCK_SIZE*8, ctx.mmap_size, ctx.mmap); + for (int i = 0; i < 32; i++) { idt_encode_entry(idt, i, isr_stub_table[i], GDT_SEGMENT_SELECTOR(1, 0), TRAP_GATE_32 | INT_RING0 | INT_PRESENT); } diff --git a/kernel/mem.c b/kernel/mem.c new file mode 100644 index 0000000..43a10b3 --- /dev/null +++ b/kernel/mem.c @@ -0,0 +1,127 @@ +#include + +extern kernel_ctx_t ctx; + +// TODO: Fix this, it wastes memory when switching regions because the previous offset isnt being subtracted +// Should work fine for now? +void *mmap_block_to_physical(int block) { + uint32_t offset = block * BLOCK_SIZE; + + for (uint32_t i = 0; i < ctx.multi_mmap_size; i++) { + struct multiboot_mmap_entry entry = ctx.multi_mmap[i]; + if (entry.type != MULTIBOOT_MEMORY_AVAILABLE) continue; + + uint32_t len = (uint32_t)(entry.len_low | entry.len_high); + uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high); + if (len > offset) + return (void *)(addr + offset); + } + + return 0; +} + +void memset(void *s, int c, uint32_t len) { + unsigned char *dst = s; + while (len > 0) { + *dst = (unsigned char) c; + dst++; + len--; + } +} + +void memcpy(void *dest, void *src, int n) { + for (int i=0; i ctx.mmap_size) { + index = i; + break; + } + } + + if (index == -1) return 0; // Failed + + // Create map + struct multiboot_mmap_entry entry = ctx.multi_mmap[index]; + uint32_t addr = (uint32_t)(entry.addr_low | entry.addr_high); + ctx.mmap = (uint32_t *)addr; + // Zero the map + memset(ctx.mmap, 0, ctx.mmap_size); + // Reserve the blocks that hold the memory map + 1 + uint32_t blocks_to_set = ctx.mmap_size / BLOCK_SIZE + 1; + for (uint32_t i = 0; i < blocks_to_set; i++) + mmap_set_block(i); + // Reserve the kernel space + int bits = ctx.mmap_size * 8; + for (int i = 0; i < bits; i++) { + uint32_t phys = (uint32_t)mmap_block_to_physical(i); + if (phys > KERNEL_START && phys < KERNEL_START + KERNEL_SIZE) + mmap_set_block(i); + } + + return 1; +} + +void mmap_set_block(int block) { + int index = block / BITS; + int bit = block; + if (block >= BITS) + bit -= BITS; + + uint32_t mask = 1 << bit; + if (!(ctx.mmap[index] & mask)) + ctx.mmap[index] |= mask; +} + +void mmap_free_block(int block) { + int index = block / BITS; + int bit = block; + if (block >= BITS) + bit -= BITS; + + uint32_t mask = 1 << bit; + if (ctx.mmap[index] & mask) + ctx.mmap[index] ^= mask; +} + +void *mmap_find_first_free_block(void) { + int bits = ctx.mmap_size * 8; + for (int i = 0; i < bits; i++) { + int index = i / BITS; + int bit = i; + if (i >= BITS) + bit -= BITS; + + uint32_t mask = 1 << bit; + + uint32_t dword = ctx.mmap[index]; + if (!(dword & mask)) { + mmap_set_block(i); + return mmap_block_to_physical(i); + } + } + + return 0; +}