diff --git a/src/boot/traps.S b/src/boot/traps.S index ed84028..9c2f024 100644 --- a/src/boot/traps.S +++ b/src/boot/traps.S @@ -4,10 +4,10 @@ .global trap_entry trap_entry: - # Allocate stack space for GPRs (256 bytes) + FPU registers (512 bytes) - addi sp, sp, -768 # Total: 256 (GPRs) + 512 (FPU) + # Create space on the stack for 32 registers (32 * 8 = 256 bytes) + addi sp, sp, -256 - # --- Save GPRs --- + # Save all General Purpose Registers (GPRs) sd ra, 0(sp) sd gp, 8(sp) sd tp, 16(sp) @@ -39,112 +39,19 @@ trap_entry: sd t5, 224(sp) sd t6, 232(sp) - # --- Save mepc/mcause/mstatus --- + # Save mepc to the stack (using offset 240) csrr t0, mepc sd t0, 240(sp) - csrr t0, mcause - sd t0, 248(sp) - csrr t0, mstatus - sd t0, 256(sp) - # --- Check FPU Status (mstatus.FS) --- - csrr t1, mstatus - li t2, 0x6000 - and t1, t1, t2 - bnez t1, save_fpu - - # If no FPU, skip to handler - j call_handler - -save_fpu: - # Save FPU registers (f0-f31) starting at offset 256 - fsd f0, 256(sp) - fsd f1, 264(sp) - fsd f2, 272(sp) - fsd f3, 280(sp) - fsd f4, 288(sp) - fsd f5, 296(sp) - fsd f6, 304(sp) - fsd f7, 312(sp) - fsd f8, 320(sp) - fsd f9, 328(sp) - fsd f10, 336(sp) - fsd f11, 344(sp) - fsd f12, 352(sp) - fsd f13, 360(sp) - fsd f14, 368(sp) - fsd f15, 376(sp) - fsd f16, 384(sp) - fsd f17, 392(sp) - fsd f18, 400(sp) - fsd f19, 408(sp) - fsd f20, 416(sp) - fsd f21, 424(sp) - fsd f22, 432(sp) - fsd f23, 440(sp) - fsd f24, 448(sp) - fsd f25, 456(sp) - fsd f26, 464(sp) - fsd f27, 472(sp) - fsd f28, 480(sp) - fsd f29, 488(sp) - fsd f30, 496(sp) - fsd f31, 504(sp) - -call_handler: - # Pass stack pointer to C handler - mv a0, sp + # Call trap handler + mv a0, sp # put the stack pointer to the first arg call handle_trap - # --- Restore mepc --- + # restore mepc ld t0, 240(sp) csrw mepc, t0 - # --- Restore FPU (if it was saved) --- - csrr t1, mstatus - li t2, 0x6000 - and t1, t1, t2 - bnez t1, restore_fpu - - j restore_gpr - -restore_fpu: - # Restore FPU registers - fld f0, 256(sp) - fld f1, 264(sp) - fld f2, 272(sp) - fld f3, 280(sp) - fld f4, 288(sp) - fld f5, 296(sp) - fld f6, 304(sp) - fld f7, 312(sp) - fld f8, 320(sp) - fld f9, 328(sp) - fld f10, 336(sp) - fld f11, 344(sp) - fld f12, 352(sp) - fld f13, 360(sp) - fld f14, 368(sp) - fld f15, 376(sp) - fld f16, 384(sp) - fld f17, 392(sp) - fld f18, 400(sp) - fld f19, 408(sp) - fld f20, 416(sp) - fld f21, 424(sp) - fld f22, 432(sp) - fld f23, 440(sp) - fld f24, 448(sp) - fld f25, 456(sp) - fld f26, 464(sp) - fld f27, 472(sp) - fld f28, 480(sp) - fld f29, 488(sp) - fld f30, 496(sp) - fld f31, 504(sp) - -restore_gpr: - # Restore GPRs + # Restore all GPRs ld ra, 0(sp) ld gp, 8(sp) ld tp, 16(sp) @@ -176,6 +83,8 @@ restore_gpr: ld t5, 224(sp) ld t6, 232(sp) - # Restore stack pointer - addi sp, sp, 768 + # Shrink the stack back + addi sp, sp, 256 + + # Return from Machine-mode trap mret \ No newline at end of file diff --git a/src/drivers/uart.c b/src/drivers/uart.c index df5d4fd..a2c216a 100644 --- a/src/drivers/uart.c +++ b/src/drivers/uart.c @@ -137,8 +137,7 @@ void kprintf_internal(const char *format, va_list args) if (*p == '%') { p++; - if (*p == '\0') - break; + if(*p == '\0') break; switch (*p) { case 'c': @@ -150,8 +149,7 @@ void kprintf_internal(const char *format, va_list args) case 's': { char *s = va_arg(args, char *); - if (!s) - s = "(null)"; + if (!s) s = "(null)"; kprint(s); break; } @@ -161,12 +159,12 @@ void kprintf_internal(const char *format, va_list args) kprint_int(d); break; } - case 'u': - { + case 'u': + { unsigned int u = va_arg(args, unsigned int); kprint_int((int)u); break; - } + } case 'f': { double f = va_arg(args, double); @@ -176,11 +174,11 @@ void kprintf_internal(const char *format, va_list args) case 'x': // Hex case 'p': // Pointer { -#if UINTPTR_MAX == 0xffffffffULL - unsigned int x = va_arg(args, unsigned int); -#else - uint64_t x = va_arg(args, uint64_t); -#endif + #if UINTPTR_MAX == 0xffffffffULL + unsigned int x = va_arg(args, unsigned int); + #else + uint64_t x = va_arg(args, uint64_t); + #endif kprint_hex(x); break; } diff --git a/src/kernel/interrupts.c b/src/kernel/interrupts.c index c700b19..ac14bb2 100644 --- a/src/kernel/interrupts.c +++ b/src/kernel/interrupts.c @@ -8,7 +8,6 @@ #include #include - void interrupt_init() { kprint("Initialising Interrupts..."); @@ -23,17 +22,6 @@ void interrupt_init() mie_val |= (1 << MIE_BIT_MEIE) | (1 << MIE_BIT_MTIE); asm volatile("csrw mie, %0" ::"r"(mie_val)); kputs("OK"); - - uint32_t mie, sie, mstatus; - asm volatile ("csrr %0, mie" : "=r"(mie)); - asm volatile ("csrr %0, sie" : "=r"(sie)); - asm volatile ("csrr %0, mstatus" : "=r"(mstatus)); - kprintf("mie: 0x%X, sie: 0x%X, mstatus: 0x%X\n", mie, sie, mstatus); - - // Enable timer and global interrupts - asm volatile ("csrs mie, %0" : : "r"(mie | (1 << 7) | (1 << 3))); // Enable timer and global - asm volatile ("csrs sie, %0" : : "r"(sie | (1 << 7) | (1 << 3))); // Enable timer and global - asm volatile ("csrs mstatus, %0" : : "r"(mstatus | (1 << 3))); // Set MIE bit } void kpanic(const char *reason, ...) @@ -67,11 +55,15 @@ void kpanic_force() void handle_trap(trap_frame_t *registers) { + // Read the 'mcause' register to see WHY we trapped + unsigned long cause; + __asm__ volatile("csrr %0, mcause" : "=r"(cause)); + // Check if the top bit is 1 (Interrupt) or 0 (Exception) // For 64-bit RISC-V, the bit is 63 - int is_interrupt = (registers->mcause >> 63) & 1; + int is_interrupt = (cause >> 63) & 1; - unsigned long code = registers->mcause & 0xfff; + unsigned long code = cause & 0xfff; if (is_interrupt) { @@ -86,7 +78,7 @@ void handle_trap(trap_frame_t *registers) kprintf("\n[EXCEPTION] Code: %d | Instruction: %x | Fault Address: %x\n", code, registers->mepc, mtval); - switch (registers->mcause) + switch (cause) { case 0: kpanic("Reason: Instruction Address Misaligned\n"); @@ -113,7 +105,7 @@ void handle_trap(trap_frame_t *registers) kpanic("Reason: Store/AMO Access Fault\n"); break; default: - kpanic("Reason: Unknown Exception Code %d\n", registers->mcause); + kpanic("Reason: Unknown Exception Code %d\n", cause); break; } } @@ -124,7 +116,8 @@ void handle_interrupt(unsigned long code) switch (code) { case 7: - timer_tick(); + timer_handle_interrupt(); + break; case 11: volatile uint32_t *claim_reg = (uint32_t *)PLIC_CLAIM(0); diff --git a/src/kernel/interrupts.h b/src/kernel/interrupts.h index 8d108fb..0bd683d 100644 --- a/src/kernel/interrupts.h +++ b/src/kernel/interrupts.h @@ -3,8 +3,6 @@ #define MSTATUS 0x300 #define MIE 0x304 -#define MCAUSE 0x342 -#define MEPC 0x341 #define MSTATUS_BIT_MIE 3 #define MIE_BIT_MTIE 7 #define MIE_BIT_MEIE 11 @@ -58,10 +56,8 @@ typedef struct { uint64_t t5; // x30 uint64_t t6; // x31 - // Control and Status Register state (Saved in traps.S) - uint64_t mepc; // offset 240 - uint64_t mcause; // offset 248 - uint64_t mstatus; // offset 256 + // Control and Status Register state + uint64_t mepc; // offset 240 (Saved in traps.S) } trap_frame_t; void interrupt_init(); diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index da2a669..1d935c3 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -5,13 +5,11 @@ #include #include #include -#include void kmain() { zero_bss(); plic_init(); - timer_init(); uart_init(); page_init(); interrupt_init(); @@ -19,12 +17,4 @@ void kmain() kprintf("Hello, from %s!", "SquidgeOS"); kputs("----------------------"); knewline(); - while (1) { - uint64_t ticks = timer_get_ms(); - kputchar('T'); - kputchar(':'); // Print "T:1234" every second - kprint_int(ticks); - knewline(); - delay_ms(1000); - } } diff --git a/src/kernel/plic.c b/src/kernel/plic.c index f482fa8..5a14838 100644 --- a/src/kernel/plic.c +++ b/src/kernel/plic.c @@ -13,13 +13,7 @@ void plic_init() // This is a bitmask, so we shift 1 by the IRQ number. *PLIC_ENABLE(hart) = (1 << UART_IRQ); - // Set priority for CLINT timer interrupt (IRQ 7) - *PLIC_PRIORITY(TIMER_IRQ) = 1; // Lowest priority - - // Enable CLINT timer interrupt for Hart 0 - *PLIC_ENABLE(hart) |= (1 << TIMER_IRQ); - // 3. Set the priority threshold for Hart 0 // We set this to 0 so that ANY interrupt with priority > 0 gets through. *PLIC_THRESHOLD(hart) = 0; -} +} \ No newline at end of file diff --git a/src/kernel/plic.h b/src/kernel/plic.h index cca2c60..9235164 100644 --- a/src/kernel/plic.h +++ b/src/kernel/plic.h @@ -16,7 +16,6 @@ #define PLIC_CLAIM(hart) ((volatile uint32_t *)(PLIC_BASE + 0x200004 + (hart) * 0x1000)) #define UART_IRQ 10 -#define TIMER_IRQ 7 void plic_init(); diff --git a/src/kernel/timer.c b/src/kernel/timer.c index 03320da..530c6fd 100644 --- a/src/kernel/timer.c +++ b/src/kernel/timer.c @@ -1,43 +1,12 @@ #include -#include -#include "timer.h" -#include "plic.h" -#include "interrupts.h" -#include "drivers/uart.h" +#include +#include +#include -_Atomic uint64_t sys_ticks = 0; -const uint64_t tick_delta = TICKS_PER_MS; +void timer_handle_interrupt() +{ + static volatile uint64_t *mtime = (uint64_t *)CLINT_MTIME; + static volatile uint64_t *mtimecmp = (uint64_t *)CLINT_MTIMECMP(0); -void timer_init() { - timer_tick(); -} - -void timer_tick() { - static volatile uint64_t *mtime = (uint64_t *)CLINT_MTIME; - static volatile uint64_t *mtimecmp = (uint64_t *)CLINT_MTIMECMP(0); - uint64_t current_mtime = *mtime; - uint64_t new_mtimecmp = current_mtime + tick_delta; - *mtimecmp = new_mtimecmp; - //kprintf("Set mtimecmp: %u (mtime: %u, delta: %u)\n", new_mtimecmp, current_mtime, tick_delta); - sys_ticks++; -} - -// Get current time in milliseconds -uint64_t timer_get_ms() { - return sys_ticks; -} - -// Delay for 'ms' milliseconds (blocking) -void delay_ms(uint64_t ms) { - if (ms == 0) return; - uint64_t end = sys_ticks + ms; - while (sys_ticks < end) { - asm volatile("wfi"); - } -} - -// Sleep for 'ms' milliseconds (non-blocking, if possible) -// For now, just call delay_ms (can be improved later) -void sleep_ms(uint64_t ms) { - delay_ms(ms); + *mtimecmp = *mtime + TIMER_FREQ; } \ No newline at end of file diff --git a/src/kernel/timer.h b/src/kernel/timer.h index 089010f..3b6f452 100644 --- a/src/kernel/timer.h +++ b/src/kernel/timer.h @@ -1,30 +1,8 @@ -#ifndef TIMER_H -#define TIMER_H -#include +#ifndef KTIMER_H +#define KTIMER_H -/* Define your clock frequency here based on your hardware */ -/* Example: 12.5 MHz for QEMU virt machine */ -#define CLOCK_FREQ_HZ 12500000 +#define TIMER_FREQ 100000 -/* Calculate ticks per millisecond */ -#define TICKS_PER_MS (CLOCK_FREQ_HZ / 1000) - -extern _Atomic uint64_t sys_ticks; -extern const uint64_t tick_delta; - -// Initialize timer (1ms ticks) -void timer_init(); - -// Increment the system tick counter -void timer_tick(); - -// Get current time in milliseconds -uint64_t timer_get_ms(); - -// Delay for 'ms' milliseconds (blocking) -void delay_ms(uint64_t ms); - -// Sleep for 'ms' milliseconds (non-blocking, if possible) -void sleep_ms(uint64_t ms); +void timer_handle_interrupt(); #endif \ No newline at end of file diff --git a/src/lib/string.h b/src/lib/string.h index 5ad4eee..78ae169 100644 --- a/src/lib/string.h +++ b/src/lib/string.h @@ -2,8 +2,5 @@ #define STRING_H void *memset(void *s, int c, size_t n); -void *memcpy(void *dest, const void *src, size_t n); -int strcmp(const char *str1, const char *str2); -size_t strlen(const char *s); #endif \ No newline at end of file