From 53c5d7d40c92e9f9dceaa7dcfc35a46d8710734c Mon Sep 17 00:00:00 2001 From: slinky55 Date: Sun, 14 Jun 2026 00:34:11 -0500 Subject: [PATCH] mm stuff --- .gitignore | 2 + compile_commands.json | 303 +++++++++++++++++++++++++++++++++++++++++- kernel/boot/boot.S | 2 + kernel/common_stubs.S | 12 +- kernel/globals.c | 11 +- kernel/interrupts.c | 6 +- kernel/kmain.c | 41 ++++-- kernel/lib/print.c | 78 ++++++++++- kernel/lib/print.h | 2 +- kernel/linker.ld | 2 + kernel/memory/mm.c | 103 ++++++++++++-- kernel/memory/mm.h | 16 +++ 12 files changed, 527 insertions(+), 51 deletions(-) create mode 100644 kernel/memory/mm.h diff --git a/.gitignore b/.gitignore index 6a21bed..1ce64fa 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,5 @@ build isodir + +compiler*/ \ No newline at end of file diff --git a/compile_commands.json b/compile_commands.json index 9a3b587..58fa469 100644 --- a/compile_commands.json +++ b/compile_commands.json @@ -1,19 +1,308 @@ [ { - "file": "kernel/kmain.c", "arguments": [ "/home/slinky/opt/cross/bin/i686-elf-gcc", "-c", - "kernel/kmain.c", - "-o", - "obj/kernel/kmain.o", "-ffreestanding", "-O2", "-Wall", "-Wextra", - "-Ikernel" + "-Ikernel", + "-o", + "obj/kernel/globals.o", + "kernel/globals.c" ], "directory": "/home/slinky/source/RockOS", - "output": "obj/kernel/kmain.o" + "file": "/home/slinky/source/RockOS/kernel/globals.c", + "output": "/home/slinky/source/RockOS/obj/kernel/globals.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/kmain.o", + "kernel/kmain.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/kmain.c", + "output": "/home/slinky/source/RockOS/obj/kernel/kmain.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/idt.o", + "kernel/idt.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/idt.c", + "output": "/home/slinky/source/RockOS/obj/kernel/idt.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/pic/pic.o", + "kernel/drivers/pic/pic.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/pic/pic.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/pic/pic.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/vga/vga_stream_writer.o", + "kernel/drivers/vga/vga_stream_writer.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/vga/vga_stream_writer.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/vga/vga_stream_writer.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/ps2/ps2.o", + "kernel/drivers/ps2/ps2.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/ps2/ps2.c", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/ps2/ps2.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/gdt.o", + "kernel/gdt.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/gdt.c", + "output": "/home/slinky/source/RockOS/obj/kernel/gdt.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/memory/mm.o", + "kernel/memory/mm.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/memory/mm.c", + "output": "/home/slinky/source/RockOS/obj/kernel/memory/mm.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/interrupts.o", + "kernel/interrupts.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/interrupts.c", + "output": "/home/slinky/source/RockOS/obj/kernel/interrupts.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/lib/stream.o", + "kernel/lib/stream.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/lib/stream.c", + "output": "/home/slinky/source/RockOS/obj/kernel/lib/stream.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/lib/print.o", + "kernel/lib/print.c" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/lib/print.c", + "output": "/home/slinky/source/RockOS/obj/kernel/lib/print.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/pic/pic_stubs.o", + "kernel/drivers/pic/pic_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/pic/pic_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/pic/pic_stubs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/pit/pit_stubs.o", + "kernel/drivers/pit/pit_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/pit/pit_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/pit/pit_stubs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/drivers/ps2/ps2_stubs.o", + "kernel/drivers/ps2/ps2_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/drivers/ps2/ps2_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/drivers/ps2/ps2_stubs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/boot/boot.o", + "kernel/boot/boot.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/boot/boot.S", + "output": "/home/slinky/source/RockOS/obj/kernel/boot/boot.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/gdt_stubs.o", + "kernel/gdt_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/gdt_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/gdt_stubs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/common_stubs.o", + "kernel/common_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/common_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/common_stubs.o" + }, + { + "arguments": [ + "/home/slinky/opt/cross/bin/i686-elf-gcc", + "-c", + "-ffreestanding", + "-O2", + "-Wall", + "-Wextra", + "-Ikernel", + "-o", + "obj/kernel/idt_stubs.o", + "kernel/idt_stubs.S" + ], + "directory": "/home/slinky/source/RockOS", + "file": "/home/slinky/source/RockOS/kernel/idt_stubs.S", + "output": "/home/slinky/source/RockOS/obj/kernel/idt_stubs.o" } -] \ No newline at end of file +] diff --git a/kernel/boot/boot.S b/kernel/boot/boot.S index 53c6d0f..22605b0 100644 --- a/kernel/boot/boot.S +++ b/kernel/boot/boot.S @@ -21,6 +21,8 @@ stack_top: _start: cli mov $stack_top, %esp + push %ebx + push %eax call kmain loop: jmp loop diff --git a/kernel/common_stubs.S b/kernel/common_stubs.S index ace90d6..72bee7f 100644 --- a/kernel/common_stubs.S +++ b/kernel/common_stubs.S @@ -13,14 +13,4 @@ enable_interrupts: .global io_wait io_wait: outb %al, $0x80 - ret - -.global load_grub_boot_struct -load_grub_boot_struct: - mov %ebx, grub_boot_struct_ptr - -.section .bss -.align 4 -.global grub_boot_struct_ptr -grub_boot_struct_ptr: - .int 0 \ No newline at end of file + ret \ No newline at end of file diff --git a/kernel/globals.c b/kernel/globals.c index 2ab6373..1460f59 100644 --- a/kernel/globals.c +++ b/kernel/globals.c @@ -1,3 +1,12 @@ #include +#include +#include "multiboot.h" -print_stream_t* kout; \ No newline at end of file +print_stream_t* kout; +multiboot_info* grub_boot_struct_ptr = NULL; + +extern char __kernel_start; +extern char __kernel_end; +size_t kernel_size() { + return (size_t)(&__kernel_end - &__kernel_start); +} \ No newline at end of file diff --git a/kernel/interrupts.c b/kernel/interrupts.c index d3310ca..a8f3fbf 100644 --- a/kernel/interrupts.c +++ b/kernel/interrupts.c @@ -44,9 +44,7 @@ void common_interrupt_handler(struct registers *args) { case 14: case 15: case 16: - kprint("CPU Error: "); - kprint(err_messages[args->int_no]); - kprint("\n"); + kprintf("CPU Error: %s", err_messages[args->int_no]); break; case 32: // wake the PIT timer driver @@ -58,7 +56,7 @@ void common_interrupt_handler(struct registers *args) { break; } default: - kprint("Received unhandled interrupt\n"); + kprintf("Received unhandled interrupt: %d\n", args->int_no); return; } } \ No newline at end of file diff --git a/kernel/kmain.c b/kernel/kmain.c index 681ed39..a5c7d59 100644 --- a/kernel/kmain.c +++ b/kernel/kmain.c @@ -1,10 +1,14 @@ +#include "multiboot.h" #include #include #include +#include #include +#include "memory/mm.h" + extern void init_idt(); extern void init_gdt(); extern void init_pic(); @@ -12,40 +16,51 @@ extern void init_pit(); extern int init_ps2(); extern void enable_interrupts(); -extern void load_grub_boot_struct(void); +void* page = NULL; -extern void* grub_boot_struct_ptr; - -void kmain(void) -{ +void kmain(uint32_t magic, multiboot_info* mbi) { extern print_stream_t vga_print_stream; extern print_stream_t* kout; kout = &vga_print_stream; kout->trunc(); - kprint("RockOS booting...\n"); + kprintf("RockOS booting...\n"); init_gdt(); - kprint("GDT set\n"); + kprintf("GDT set\n"); init_idt(); - kprint("IDT set\n"); + kprintf("IDT set\n"); init_pic(); - kprint("PIC initialized\n"); + kprintf("PIC initialized\n"); init_pit(); - kprint("PIT initialized\n"); + kprintf("PIT initialized\n"); int result = init_ps2(); if (result == -1) { - kprint("PS2 init failed\n"); + kprintf("PS2 init failed\n"); return; } - kprint("PS2 initialized\n"); + kprintf("PS2 initialized\n"); + + if (!(mbi->flags & (1 << 6))) { + return; + } + + init_mm((void*)mbi->mmap_addr, mbi->mmap_length); + uint32_t mem_size = total_free_memory(); + kprintf("Total available memory: %d MB\n", mem_size / 1024 / 1024); + + page = alloc_page(); + kprintf("Allocated page at: 0x%x\n", (uint32_t)page); + + free_page(page); + kprintf("Freed page"); enable_interrupts(); - kprint("Interrupts enabled\n"); + kprintf("Interrupts enabled\n"); while(1); } diff --git a/kernel/lib/print.c b/kernel/lib/print.c index 52eff96..9a938a6 100644 --- a/kernel/lib/print.c +++ b/kernel/lib/print.c @@ -1,15 +1,91 @@ #include "print.h" #include "stream.h" +#include extern print_stream_t* kout; +static char* hex_chars = "0123456789abcdef"; -void kprint(const char *str) { +static void kprint(const char *str) { while (*str) { kout->putchar(*str); str++; } } +static void kputd(int d) { + if (d == 0) { + kout->putchar('0'); + return; + } + char buffer[12]; + int i = 0; + while (d > 0) { + buffer[i++] = '0' + (d % 10); + d /= 10; + } + for (int j = i - 1; j >= 0; j--) { + kout->putchar(buffer[j]); + } +} + +static void kputx(unsigned int x) { + if (x == 0) { + kout->putchar('0'); + return; + } + char buffer[8]; + + int i = 0; + while (x > 0) { + buffer[i++] = hex_chars[x & 0xF]; + x >>= 4; + } + for (int j = i - 1; j >= 0; j--) { + kout->putchar(buffer[j]); + } +} + void kputc(const char c) { kout->putchar(c); +} + +void kprintf(const char* fmt, ...) { + va_list args; + va_start(args, fmt); + + while (*fmt) { + if (*fmt == '%') { + fmt++; + switch (*fmt) { + case 's': { + const char* str = va_arg(args, const char*); + kprint(str); + break; + } + case 'd': { + int d = va_arg(args, int); + kputd(d); + break; + } + case 'x': { + unsigned int x = va_arg(args, unsigned int); + kputx(x); + break; + } + case '%': + kout->putchar('%'); + break; + default: + kout->putchar('%'); + kout->putchar(*fmt); + break; + } + fmt++; + } else { + kout->putchar(*fmt); + fmt++; + } + } + + va_end(args); } \ No newline at end of file diff --git a/kernel/lib/print.h b/kernel/lib/print.h index 4949898..ae76fca 100644 --- a/kernel/lib/print.h +++ b/kernel/lib/print.h @@ -1,7 +1,7 @@ #ifndef KLIBPRINT_H #define KLIBPRINT_H -void kprint(const char* str); void kputc(const char c); +void kprintf(const char* fmt, ...); #endif \ No newline at end of file diff --git a/kernel/linker.ld b/kernel/linker.ld index c41d0da..007814f 100644 --- a/kernel/linker.ld +++ b/kernel/linker.ld @@ -3,6 +3,7 @@ ENTRY(_start) SECTIONS { . = 2M; + __kernel_start = .; .text BLOCK(4K) : ALIGN(4K) { @@ -25,4 +26,5 @@ SECTIONS *(COMMON) *(.bss) } + __kernel_end = .; } \ No newline at end of file diff --git a/kernel/memory/mm.c b/kernel/memory/mm.c index 6b2114b..66c3edd 100644 --- a/kernel/memory/mm.c +++ b/kernel/memory/mm.c @@ -1,13 +1,46 @@ #include "multiboot.h" +#include + +extern uint8_t __kernel_start; +extern uint8_t __kernel_end; + +#define PAGE_SIZE 4096 +#define MAX_RAM 0xFFFFFFFF // 4GB +#define BITMAP_SIZE ((MAX_RAM / PAGE_SIZE) / 8) + static uint32_t max_address = 0; static uint32_t total_available_memory = 0; +static uint8_t memory_bitmap[BITMAP_SIZE]; -void parse_mmap(void* base, uint32_t limit) { +static void mark_free(uint32_t addr) { + uint32_t page_index = addr / PAGE_SIZE; + uint32_t byte_index = page_index / 8; + uint32_t bit_index = page_index % 8; + memory_bitmap[byte_index] &= ~(1 << bit_index); +} + +static void mark_used(uint32_t addr) { + uint32_t page_index = addr / PAGE_SIZE; + uint32_t byte_index = page_index / 8; + uint32_t bit_index = page_index % 8; + memory_bitmap[byte_index] |= (1 << bit_index); +} + +static uint32_t align(uint32_t addr, uint32_t len, uint32_t* usable_start, uint32_t* usable_end) { + uint32_t start = addr; + uint32_t end = addr + len; + *usable_start = (start + 4095) & ~0xFFF; + *usable_end = end & ~0xFFF; + return *usable_end - *usable_start; +} + +static void parse_multiboot_mmap(void* base, uint32_t limit) { multiboot_mmap_entry* entry = (multiboot_mmap_entry*)base; void* end = (void*)((uint32_t)base + limit); - + total_available_memory = 0; while ((void*)entry < end) { + uint32_t entry_size = entry->size + sizeof(entry->size); if (entry->type == 1) { uint32_t region_start = (uint32_t)(entry->addr); uint32_t region_end = (uint32_t)(entry->addr + entry->len); @@ -15,23 +48,67 @@ void parse_mmap(void* base, uint32_t limit) { max_address = region_end; } - total_available_memory += entry->len; - - // start breaking up the address range - // if it's safe (not kernel, not BIOS structures, etc..), find the corresponding page in our PMM, mark it free - // need to align start and end to 4kb - if (entry->len < 4096) { + uint32_t usable_start, usable_end, usable_size; + usable_size = align(region_start, entry->len, &usable_start, &usable_end); + if (usable_size <= 4096) { continue; } - for (uint32_t addr = region_start; addr < region_end; addr += 4096) { - // check for physical kernel address range + for (uint32_t addr = usable_start; addr < usable_end; addr += 4096) { + if (addr <= (uint32_t)&__kernel_end && addr >= (uint32_t)&__kernel_start) { + continue; + } - // check if this address range contains our multiboot structure + if (addr >= (uint32_t)entry && addr <= (uint32_t)entry + entry_size) { + continue; + } - // don't allow pages under 1MB + if (addr <= 0x200000) { + continue; + } + + total_available_memory += 4096; + + mark_free(addr); } } - entry = (multiboot_mmap_entry*)((uint32_t)entry + entry->size + sizeof(entry->size)); + entry = (multiboot_mmap_entry*)((uint32_t)entry + entry_size); } +} + +void init_mm(void* mmap_base, uint32_t mmap_limit) { + for (int i = 0; i < BITMAP_SIZE; i++) { + memory_bitmap[i] = 0xFF; + } + + if (mmap_base != NULL && mmap_limit > 0) { + parse_multiboot_mmap(mmap_base, mmap_limit); + } +} + +uint32_t total_free_memory() { + return total_available_memory; +} + +void* alloc_page() { + for (uint32_t i = 0; i < BITMAP_SIZE; i++) { + uint8_t b = memory_bitmap[i]; + if (b == 0xFF) { + continue; + } + + for (int bit = 0; bit < 8; bit++) { + if ((b & (1 << bit)) == 0) { + uint32_t page_addr = (i * 8 + bit) * PAGE_SIZE; + mark_used(page_addr); + return (void*)page_addr; + } + } + } + + return 0; +} + +void free_page(void* addr) { + mark_free((uint32_t)addr); } \ No newline at end of file diff --git a/kernel/memory/mm.h b/kernel/memory/mm.h new file mode 100644 index 0000000..d3e7427 --- /dev/null +++ b/kernel/memory/mm.h @@ -0,0 +1,16 @@ +#ifndef KMM_H +#define KMM_H + +#include + +typedef struct __attribute__((packed)) { + uint32_t addr; +} mem_page_t; + +void init_mm(void* mmap_base, uint32_t mmap_limit); +uint32_t total_free_memory(); + +void* alloc_page(); +void free_page(void* addr); + +#endif \ No newline at end of file