diff --git a/src/drivers/uart.c b/src/drivers/uart.c index c6b4e93..f4367dc 100644 --- a/src/drivers/uart.c +++ b/src/drivers/uart.c @@ -3,43 +3,54 @@ #include #include -void uart_put(size_t base_addr, uint8_t data) { +void uart_put(size_t base_addr, uint8_t data) +{ *(volatile uint8_t *)base_addr = data; } -int kputchar(int ch) { +int kputchar(int ch) +{ uart_put(UART_ADDRESS, ch); return ch; } -void kprint(const char *str) { - while (*str) { +void kprint(const char *str) +{ + while (*str) + { kputchar(*str++); } } -void kprint_int(int num) { +void kprint_int(int num) +{ char buffer[21]; int i = 0; - if (num == 0) { + if (num == 0) + { kputchar('0'); return; } - if (num < 0) { + if (num < 0) + { kputchar('-'); num = -num; } - while (num > 0) { + while (num > 0) + { buffer[i++] = '0' + (num % 10); num /= 10; } - while (i > 0) { + while (i > 0) + { kputchar(buffer[--i]); } } -void kprint_float(float num) { - if (num < 0) { +void kprint_float(float num) +{ + if (num < 0) + { kputchar('-'); num = -num; } @@ -47,73 +58,88 @@ void kprint_float(float num) { float frac_part = num - int_part; kprint_int(int_part); kputchar('.'); - for (int i = 0; i < 6; i++) { + for (int i = 0; i < 6; i++) + { frac_part *= 10.0f; } int fraction = (int)(frac_part + 0.5f); // Round to nearest kprint_int(fraction); } -void kprint_hex(uint64_t val) { - char *digits = "0123456789ABCDEF"; - char buffer[17]; // 64-bit hex is 16 chars +void kprint_hex(uint64_t val) +{ + char *digits = "0123456789ABCDEF"; + char buffer[17]; // 64-bit hex is 16 chars buffer[16] = '\0'; // Null-terminate the string - - // We process from right to left - for (int i = 15; i >= 0; i--) { - buffer[i] = digits[val & 0xF]; - val >>= 4; - } + + // We process from right to left + for (int i = 15; i >= 0; i--) + { + buffer[i] = digits[val & 0xF]; + val >>= 4; + } kprint("0x"); - kprint(buffer); + kprint(buffer); } -void knewline(void) { +void knewline(void) +{ kputchar('\n'); } -void kputs(const char *str) { +void kputs(const char *str) +{ kprint(str); knewline(); } -void kprintf(const char *format, ...) { +void kprintf(const char *format, ...) +{ va_list args; va_start(args, format); - for(char *p = format; *p != '\0'; p++) { - if (*p == '%') { + for (char *p = format; *p != '\0'; p++) + { + if (*p == '%') + { p++; - switch (*p) { - case 's': { - char *s = va_arg(args, char *); - kprint(s); - break; - } - case 'd': { - int d = va_arg(args, int); - kprint_int(d); - break; - } - case 'f': { - double f = va_arg(args, double); - kprint_float((float)f); - break; - } - case 'x': // Hex - case 'p': { // Pointer - uint64_t x = va_arg(args, uint64_t); - kprint_hex(x); - break; - } - case '%': - kputchar('%'); - break; - default: - kputchar('%'); - kputchar(*p); + switch (*p) + { + case 's': + { + char *s = va_arg(args, char *); + kprint(s); + break; } - } else { + case 'd': + { + int d = va_arg(args, int); + kprint_int(d); + break; + } + case 'f': + { + double f = va_arg(args, double); + kprint_float((float)f); + break; + } + case 'x': // Hex + case 'p': + { // Pointer + uint64_t x = va_arg(args, uint64_t); + kprint_hex(x); + break; + } + case '%': + kputchar('%'); + break; + default: + kputchar('%'); + kputchar(*p); + } + } + else + { kputchar(*p); } } diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index 5f90615..f5b2883 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -5,17 +5,12 @@ #include #include -void kmain() { - kprintf("Hello, from %s!" , "SquidgeOS"); +void kmain() +{ + kprintf("Hello, from %s!", "SquidgeOS"); kputs("-------------------"); knewline(); page_init(); - - //kprint("Stress testing memory...\n"); - //while(1) { - // void *p = page_alloc(); - //} - test_memory_integrity(); test_memory_alignment(); test_memory_stress(); diff --git a/src/kernel/memory.c b/src/kernel/memory.c index 996d9df..8f9f0f9 100644 --- a/src/kernel/memory.c +++ b/src/kernel/memory.c @@ -4,78 +4,91 @@ #include "memory.h" #include "panic.h" - -HeapHeader* heap_free_list; +HeapHeader *heap_free_list; extern uint8_t _heap_start[]; // named in the linker script -void page_init() { +void page_init() +{ kprint("Initialising page allocator.\n"); uintptr_t start = ((uintptr_t)_heap_start + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); uintptr_t end = 0x88000000; // Default QEMU RAM limit - for (uintptr_t addr = start; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) { + for (uintptr_t addr = start; addr + PAGE_SIZE <= end; addr += PAGE_SIZE) + { page_free((void *)addr); } } -void page_free(void *addr) { - if (addr == NULL) return; +void page_free(void *addr) +{ + if (addr == NULL) + return; struct Page *p = (struct Page *)addr; p->next = free_list; free_list = p; } -void *page_alloc() { - if (free_list == NULL) { +void *page_alloc() +{ + if (free_list == NULL) + { kpanic("No free pages!"); } struct Page *p = free_list; free_list = free_list->next; - //zero out the page - for (int i = 0; i < (PAGE_SIZE); i++) { + // zero out the page + for (int i = 0; i < (PAGE_SIZE); i++) + { ((uint8_t *)p)[i] = 0; } return (void *)p; } -void *kmalloc(size_t size) { - if (size == 0) return NULL; +void *kmalloc(size_t size) +{ + if (size == 0) + return NULL; // Align size to 8 bytes size = (size + 7) & ~7; - if (heap_free_list == NULL) { - HeapHeader* header = (HeapHeader *)page_alloc(); + if (heap_free_list == NULL) + { + HeapHeader *header = (HeapHeader *)page_alloc(); header->size = PAGE_SIZE - sizeof(HeapHeader); header->is_free = 1; header->next = NULL; header->prev = NULL; - + heap_free_list = header; } HeapHeader *current = heap_free_list; HeapHeader *prev = NULL; - while (current != NULL) { - if (current->is_free && current->size >= size) { + while (current != NULL) + { + if (current->is_free && current->size >= size) + { break; } prev = current; current = current->next; } - if(current == NULL) { + if (current == NULL) + { // No suitable block found, allocate a new page - HeapHeader* header = (HeapHeader *)page_alloc(); + HeapHeader *header = (HeapHeader *)page_alloc(); header->size = PAGE_SIZE - sizeof(HeapHeader); header->is_free = 1; header->next = heap_free_list; header->prev = NULL; - if(heap_free_list) { + if (heap_free_list) + { heap_free_list->prev = header; } heap_free_list = header; @@ -83,90 +96,112 @@ void *kmalloc(size_t size) { } // Now, current is a block that can be used - if (!current) { - return NULL; - } + if (!current) + { + return NULL; + } current->is_free = 0; // If the block is larger than needed, split it size_t min_split_size = sizeof(HeapHeader) + 16; - if (current->size >= size + min_split_size) { + if (current->size >= size + min_split_size) + { HeapHeader *new_header = (HeapHeader *)((uint8_t *)current + sizeof(HeapHeader) + size); // Safety check: if new_header address is wild, abort! - if ((uintptr_t)new_header < 0x80000000 || (uintptr_t)new_header > 0x88000000) { - kpanic("Splitting created invalid pointer!"); - } + if ((uintptr_t)new_header < 0x80000000 || (uintptr_t)new_header > 0x88000000) + { + kpanic("Splitting created invalid pointer!"); + } new_header->size = current->size - size - sizeof(HeapHeader); new_header->is_free = 1; new_header->next = current->next; new_header->prev = current; - if(current->next) { + if (current->next) + { current->next->prev = new_header; } current->size = size; current->next = new_header; } - return (void*)((char*)current + sizeof(HeapHeader)); + return (void *)((char *)current + sizeof(HeapHeader)); } -void kfree(void *ptr) { - if (ptr == NULL) return; +void kfree(void *ptr) +{ + if (ptr == NULL) + return; HeapHeader *header = (HeapHeader *)((uint8_t *)ptr - sizeof(HeapHeader)); - if(header->is_free) { + if (header->is_free) + { kpanic("Double free detected!"); } header->is_free = 1; - kcoalesce(header); + kcoalesce(header); } -void kcoalesce(HeapHeader *header) { - if(!header || !header->is_free) return; - //merge backward - while (header->prev && header->prev->is_free) { +void kcoalesce(HeapHeader *header) +{ + if (!header || !header->is_free) + return; + // merge backward + while (header->prev && header->prev->is_free) + { header = header->prev; } - //merge forward - while (header->next && header->next->is_free){ + // merge forward + while (header->next && header->next->is_free) + { uintptr_t current_end = (uintptr_t)header + sizeof(HeapHeader) + header->size; - if (current_end == (uintptr_t)header->next) { + if (current_end == (uintptr_t)header->next) + { header->size += sizeof(HeapHeader) + header->next->size; header->next = header->next->next; - if(header->next) { + if (header->next) + { header->next->prev = header; } - } else { + } + else + { break; } } } -void test_memory_integrity() { - kprint("Running Integrity Test...\n"); - uint64_t *a = (uint64_t*)kmalloc(16); - uint64_t *b = (uint64_t*)kmalloc(16); - - *a = 0x1122334455667788; - *b = 0x99AABBCCDDEEFF00; +void test_memory_integrity() +{ + kprint("Running Integrity Test...\n"); + uint64_t *a = (uint64_t *)kmalloc(16); + uint64_t *b = (uint64_t *)kmalloc(16); - if (*a == 0x1122334455667788) { - kprint("Integrity Pass!\n"); - } else { - kprint("CORRUPTION DETECTED!\n"); - } - kfree(a); - kfree(b); + *a = 0x1122334455667788; + *b = 0x99AABBCCDDEEFF00; + + if (*a == 0x1122334455667788) + { + kprint("Integrity Pass!\n"); + } + else + { + kprint("CORRUPTION DETECTED!\n"); + } + kfree(a); + kfree(b); } -void test_memory_alignment() { +void test_memory_alignment() +{ kprint("Running Alignment Test...\n"); - for (int i = 1; i <= 64; i++) { + for (int i = 1; i <= 64; i++) + { void *ptr = kmalloc(i); - if (((uintptr_t)ptr % 8) != 0) { + if (((uintptr_t)ptr % 8) != 0) + { kprint("Misaligned allocation detected!\n"); return; } @@ -175,32 +210,39 @@ void test_memory_alignment() { kprint("All allocations are properly aligned!\n"); } -void test_memory_stress() { - kprintf("Starting Stress Test...\n"); +void test_memory_stress() +{ + kprintf("Starting Stress Test...\n"); heap_stats(); - void *ptrs[100] = {0}; // Track allocated pointers - uint32_t seed = 0xACE2026; // Example seed + void *ptrs[100] = {0}; // Track allocated pointers + uint32_t seed = 0xACE2026; // Example seed - for (int i = 0; i < 1000; i++) { - // 1. Randomly allocate or free - int idx = (seed >> 16) % 50; - if (ptrs[idx] == NULL) { - size_t size = (seed % 256) + 1; - ptrs[idx] = kmalloc(size); - // Optional: fill with data to check integrity later - } else { - kfree(ptrs[idx]); - ptrs[idx] = NULL; - } - // Simple LCG to "randomize" seed - seed = (seed * 1103515245 + 12345) & 0x7fffffff; - } - kprintf("Stress Test Finished. Check heap_stats() for sanity.\n"); + for (int i = 0; i < 1000; i++) + { + // 1. Randomly allocate or free + int idx = (seed >> 16) % 50; + if (ptrs[idx] == NULL) + { + size_t size = (seed % 256) + 1; + ptrs[idx] = kmalloc(size); + // Optional: fill with data to check integrity later + } + else + { + kfree(ptrs[idx]); + ptrs[idx] = NULL; + } + // Simple LCG to "randomize" seed + seed = (seed * 1103515245 + 12345) & 0x7fffffff; + } + kprintf("Stress Test Finished. Check heap_stats() for sanity.\n"); kprintf("HeadHeader size: %d bytes\n", sizeof(HeapHeader)); - heap_stats(); + heap_stats(); kprintf("Cleaning up remaining allocations...\n"); - for (int i = 0; i < 100; i++) { - if (ptrs[i] != NULL) { + for (int i = 0; i < 100; i++) + { + if (ptrs[i] != NULL) + { kfree(ptrs[i]); ptrs[i] = NULL; } @@ -208,32 +250,37 @@ void test_memory_stress() { heap_stats(); } -void heap_stats() { - size_t free_size = 0; - size_t used_size = 0; - size_t free_blocks = 0; - size_t used_blocks = 0; +void heap_stats() +{ + size_t free_size = 0; + size_t used_size = 0; + size_t free_blocks = 0; + size_t used_blocks = 0; - HeapHeader *current = heap_free_list; + HeapHeader *current = heap_free_list; - while (current != NULL) { - if (current->is_free) { - free_size += current->size; - free_blocks++; - } else { - used_size += current->size; - used_blocks++; - } - current = current->next; - } + while (current != NULL) + { + if (current->is_free) + { + free_size += current->size; + free_blocks++; + } + else + { + used_size += current->size; + used_blocks++; + } + current = current->next; + } - kprint("--- Kernel Heap Stats ---\n"); + kprint("--- Kernel Heap Stats ---\n"); kprintf("Page Size: %d bytes", PAGE_SIZE); kprintf("HeapHeader size: %d bytes", sizeof(HeapHeader)); kprintf("Pages allocated: %d", (used_size + free_size + used_blocks * sizeof(HeapHeader) + free_blocks * sizeof(HeapHeader)) / PAGE_SIZE); - kprintf("Used: %x bytes in %d blocks",used_size, used_blocks); + kprintf("Used: %x bytes in %d blocks", used_size, used_blocks); kprintf("Used (with overhead): %x bytes", used_size + used_blocks * sizeof(HeapHeader)); kprintf("Free: %x bytes in %d blocks", free_size, free_blocks); - kprintf("Total metadata overhead: %d bytes", ((used_blocks + free_blocks) * sizeof(HeapHeader))); - kprint("-------------------------\n"); + kprintf("Total metadata overhead: %d bytes", ((used_blocks + free_blocks) * sizeof(HeapHeader))); + kprint("-------------------------\n"); } \ No newline at end of file diff --git a/src/kernel/memory.h b/src/kernel/memory.h index bc2ab34..8e7d64a 100644 --- a/src/kernel/memory.h +++ b/src/kernel/memory.h @@ -3,15 +3,17 @@ #define PAGE_SIZE 4096 -typedef struct Page { +typedef struct Page +{ struct Page *next; } Page; -typedef struct HeapHeader { +typedef struct HeapHeader +{ size_t size; int is_free; struct HeapHeader *next; - struct HeapHeader *prev; + struct HeapHeader *prev; } HeapHeader; static struct Page *free_list = NULL; diff --git a/src/kernel/panic.c b/src/kernel/panic.c index e524b8c..063d13f 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -4,14 +4,16 @@ #include #include "memory.h" -void kpanic(const char *reason){ +void kpanic(const char *reason) +{ kputs("\n!!! PANIC !!!\n"); - kputs(reason); + kputs(reason); kputs("\n!!! PANIC !!!\n"); - poweroff(); + poweroff(); } -void kpanic_force() { +void kpanic_force() +{ kprint("\n!!! FORCE PANIC !!!\n"); // 'ebreak' is the standard RISC-V way to trigger a debug trap. @@ -21,14 +23,16 @@ void kpanic_force() { poweroff(); kprint("Force panic falled. Power off failed. sleep until interupt. \n"); - while(1) { + while (1) + { __asm__ volatile("wfi"); } } -void handle_trap() { +void handle_trap() +{ kprint("\n!!! HARDWARE EXCEPTION DETECTED !!!\n"); - + // Read the 'mcause' register to see WHY we trapped unsigned long cause; __asm__ volatile("csrr %0, mcause" : "=r"(cause)); @@ -37,17 +41,34 @@ void handle_trap() { uintptr_t mtval; asm volatile("csrr %0, mtval" : "=r"(mtval)); - switch(cause) { - case 0: kprint("Reason: Instruction Address Misaligned\n"); break; - case 1: kprint("Reason: Instruction Access Fault\n"); break; - case 2: kprint("Reason: Illegal Instruction\n"); break; - case 3: kprint("Reason: Breakpoint (ebreak)\n"); break; - case 4: kprint("Reason: Load Address Misaligned\n"); break; - case 5: kprint("Reason: Load Access Fault\n"); break; - case 6: kprint("Reason: Store/AMO Address Misaligned\n"); break; - case 7: kprint("Reason: Store/AMO Access Fault\n"); break; - default: - kprintf("Reason: Unknown Exception Code %d\n", cause); + switch (cause) + { + case 0: + kprint("Reason: Instruction Address Misaligned\n"); + break; + case 1: + kprint("Reason: Instruction Access Fault\n"); + break; + case 2: + kprint("Reason: Illegal Instruction\n"); + break; + case 3: + kprint("Reason: Breakpoint (ebreak)\n"); + break; + case 4: + kprint("Reason: Load Address Misaligned\n"); + break; + case 5: + kprint("Reason: Load Access Fault\n"); + break; + case 6: + kprint("Reason: Store/AMO Address Misaligned\n"); + break; + case 7: + kprint("Reason: Store/AMO Access Fault\n"); + break; + default: + kprintf("Reason: Unknown Exception Code %d\n", cause); } kprintf("Faulting Address (if applicable): %x\n", mtval); diff --git a/src/kernel/panic.h b/src/kernel/panic.h index 0c087e4..007a16e 100644 --- a/src/kernel/panic.h +++ b/src/kernel/panic.h @@ -4,13 +4,14 @@ void kpanic(const char *reason); void kpanic_force(); -#define KASSERT(cond, msg) \ - if (!(cond)) { \ - kprint("ASSERTION FAILED: "); \ - kprint(__FILE__); \ - kprint(":"); \ +#define KASSERT(cond, msg) \ + if (!(cond)) \ + { \ + kprint("ASSERTION FAILED: "); \ + kprint(__FILE__); \ + kprint(":"); \ /* Note: Printing line numbers requires a custom itoa/printf */ \ - kpanic(msg); \ + kpanic(msg); \ } #endif \ No newline at end of file diff --git a/src/lib/string.c b/src/lib/string.c index 14f9a17..891a5d7 100644 --- a/src/lib/string.c +++ b/src/lib/string.c @@ -1,9 +1,11 @@ #include #include "string.h" -void *memset(void *s, int c, size_t n) { +void *memset(void *s, int c, size_t n) +{ unsigned char *p = s; - while (n--) { + while (n--) + { *p++ = (unsigned char)c; } return s; diff --git a/src/syscon/syscon.c b/src/syscon/syscon.c index bd8cb4a..c3a00ff 100644 --- a/src/syscon/syscon.c +++ b/src/syscon/syscon.c @@ -3,18 +3,20 @@ #include "syscon.h" #include "drivers/uart.h" -void poweroff(void) { +void poweroff(void) +{ knewline(); kputs("-------"); knewline(); - kputs("Poweroff requested"); + kputs("Poweroff requested"); *(volatile uint32_t *)SYSCON_ADDR = SYSCON_POWEROFF; } -void reboot(void) { +void reboot(void) +{ knewline(); kputs("-------"); knewline(); - kputs("Reboot requested"); + kputs("Reboot requested"); *(volatile uint32_t *)SYSCON_ADDR = SYSCON_REBOOT; } \ No newline at end of file diff --git a/src/syscon/syscon.h b/src/syscon/syscon.h index cda3319..32dd6a1 100644 --- a/src/syscon/syscon.h +++ b/src/syscon/syscon.h @@ -6,7 +6,7 @@ // Magic values for the Sifive Test device #define SYSCON_POWEROFF 0x5555 -#define SYSCON_REBOOT 0x7777 +#define SYSCON_REBOOT 0x7777 void poweroff(void); void reboot(void);