Compare commits
1 commit
main
...
feature/ti
| Author | SHA1 | Date | |
|---|---|---|---|
| 537dde170b |
10 changed files with 47 additions and 224 deletions
115
src/boot/traps.S
115
src/boot/traps.S
|
|
@ -4,10 +4,10 @@
|
||||||
.global trap_entry
|
.global trap_entry
|
||||||
|
|
||||||
trap_entry:
|
trap_entry:
|
||||||
# Allocate stack space for GPRs (256 bytes) + FPU registers (512 bytes)
|
# Create space on the stack for 32 registers (32 * 8 = 256 bytes)
|
||||||
addi sp, sp, -768 # Total: 256 (GPRs) + 512 (FPU)
|
addi sp, sp, -256
|
||||||
|
|
||||||
# --- Save GPRs ---
|
# Save all General Purpose Registers (GPRs)
|
||||||
sd ra, 0(sp)
|
sd ra, 0(sp)
|
||||||
sd gp, 8(sp)
|
sd gp, 8(sp)
|
||||||
sd tp, 16(sp)
|
sd tp, 16(sp)
|
||||||
|
|
@ -39,112 +39,19 @@ trap_entry:
|
||||||
sd t5, 224(sp)
|
sd t5, 224(sp)
|
||||||
sd t6, 232(sp)
|
sd t6, 232(sp)
|
||||||
|
|
||||||
# --- Save mepc/mcause/mstatus ---
|
# Save mepc to the stack (using offset 240)
|
||||||
csrr t0, mepc
|
csrr t0, mepc
|
||||||
sd t0, 240(sp)
|
sd t0, 240(sp)
|
||||||
csrr t0, mcause
|
|
||||||
sd t0, 248(sp)
|
|
||||||
csrr t0, mstatus
|
|
||||||
sd t0, 256(sp)
|
|
||||||
|
|
||||||
# --- Check FPU Status (mstatus.FS) ---
|
# Call trap handler
|
||||||
csrr t1, mstatus
|
mv a0, sp # put the stack pointer to the first arg
|
||||||
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 handle_trap
|
call handle_trap
|
||||||
|
|
||||||
# --- Restore mepc ---
|
# restore mepc
|
||||||
ld t0, 240(sp)
|
ld t0, 240(sp)
|
||||||
csrw mepc, t0
|
csrw mepc, t0
|
||||||
|
|
||||||
# --- Restore FPU (if it was saved) ---
|
# Restore all GPRs
|
||||||
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
|
|
||||||
ld ra, 0(sp)
|
ld ra, 0(sp)
|
||||||
ld gp, 8(sp)
|
ld gp, 8(sp)
|
||||||
ld tp, 16(sp)
|
ld tp, 16(sp)
|
||||||
|
|
@ -176,6 +83,8 @@ restore_gpr:
|
||||||
ld t5, 224(sp)
|
ld t5, 224(sp)
|
||||||
ld t6, 232(sp)
|
ld t6, 232(sp)
|
||||||
|
|
||||||
# Restore stack pointer
|
# Shrink the stack back
|
||||||
addi sp, sp, 768
|
addi sp, sp, 256
|
||||||
|
|
||||||
|
# Return from Machine-mode trap
|
||||||
mret
|
mret
|
||||||
|
|
@ -137,8 +137,7 @@ void kprintf_internal(const char *format, va_list args)
|
||||||
if (*p == '%')
|
if (*p == '%')
|
||||||
{
|
{
|
||||||
p++;
|
p++;
|
||||||
if (*p == '\0')
|
if(*p == '\0') break;
|
||||||
break;
|
|
||||||
switch (*p)
|
switch (*p)
|
||||||
{
|
{
|
||||||
case 'c':
|
case 'c':
|
||||||
|
|
@ -150,8 +149,7 @@ void kprintf_internal(const char *format, va_list args)
|
||||||
case 's':
|
case 's':
|
||||||
{
|
{
|
||||||
char *s = va_arg(args, char *);
|
char *s = va_arg(args, char *);
|
||||||
if (!s)
|
if (!s) s = "(null)";
|
||||||
s = "(null)";
|
|
||||||
kprint(s);
|
kprint(s);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -161,12 +159,12 @@ void kprintf_internal(const char *format, va_list args)
|
||||||
kprint_int(d);
|
kprint_int(d);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'u':
|
case 'u':
|
||||||
{
|
{
|
||||||
unsigned int u = va_arg(args, unsigned int);
|
unsigned int u = va_arg(args, unsigned int);
|
||||||
kprint_int((int)u);
|
kprint_int((int)u);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'f':
|
case 'f':
|
||||||
{
|
{
|
||||||
double f = va_arg(args, double);
|
double f = va_arg(args, double);
|
||||||
|
|
@ -176,11 +174,11 @@ void kprintf_internal(const char *format, va_list args)
|
||||||
case 'x': // Hex
|
case 'x': // Hex
|
||||||
case 'p': // Pointer
|
case 'p': // Pointer
|
||||||
{
|
{
|
||||||
#if UINTPTR_MAX == 0xffffffffULL
|
#if UINTPTR_MAX == 0xffffffffULL
|
||||||
unsigned int x = va_arg(args, unsigned int);
|
unsigned int x = va_arg(args, unsigned int);
|
||||||
#else
|
#else
|
||||||
uint64_t x = va_arg(args, uint64_t);
|
uint64_t x = va_arg(args, uint64_t);
|
||||||
#endif
|
#endif
|
||||||
kprint_hex(x);
|
kprint_hex(x);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
#include <kernel/memory.h>
|
#include <kernel/memory.h>
|
||||||
#include <kernel/timer.h>
|
#include <kernel/timer.h>
|
||||||
|
|
||||||
|
|
||||||
void interrupt_init()
|
void interrupt_init()
|
||||||
{
|
{
|
||||||
kprint("Initialising Interrupts...");
|
kprint("Initialising Interrupts...");
|
||||||
|
|
@ -23,17 +22,6 @@ void interrupt_init()
|
||||||
mie_val |= (1 << MIE_BIT_MEIE) | (1 << MIE_BIT_MTIE);
|
mie_val |= (1 << MIE_BIT_MEIE) | (1 << MIE_BIT_MTIE);
|
||||||
asm volatile("csrw mie, %0" ::"r"(mie_val));
|
asm volatile("csrw mie, %0" ::"r"(mie_val));
|
||||||
kputs("OK");
|
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, ...)
|
void kpanic(const char *reason, ...)
|
||||||
|
|
@ -67,11 +55,15 @@ void kpanic_force()
|
||||||
|
|
||||||
void handle_trap(trap_frame_t *registers)
|
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)
|
// Check if the top bit is 1 (Interrupt) or 0 (Exception)
|
||||||
// For 64-bit RISC-V, the bit is 63
|
// 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)
|
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);
|
kprintf("\n[EXCEPTION] Code: %d | Instruction: %x | Fault Address: %x\n", code, registers->mepc, mtval);
|
||||||
|
|
||||||
switch (registers->mcause)
|
switch (cause)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
kpanic("Reason: Instruction Address Misaligned\n");
|
kpanic("Reason: Instruction Address Misaligned\n");
|
||||||
|
|
@ -113,7 +105,7 @@ void handle_trap(trap_frame_t *registers)
|
||||||
kpanic("Reason: Store/AMO Access Fault\n");
|
kpanic("Reason: Store/AMO Access Fault\n");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
kpanic("Reason: Unknown Exception Code %d\n", registers->mcause);
|
kpanic("Reason: Unknown Exception Code %d\n", cause);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -124,7 +116,8 @@ void handle_interrupt(unsigned long code)
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
case 7:
|
case 7:
|
||||||
timer_tick();
|
timer_handle_interrupt();
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 11:
|
case 11:
|
||||||
volatile uint32_t *claim_reg = (uint32_t *)PLIC_CLAIM(0);
|
volatile uint32_t *claim_reg = (uint32_t *)PLIC_CLAIM(0);
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#define MSTATUS 0x300
|
#define MSTATUS 0x300
|
||||||
#define MIE 0x304
|
#define MIE 0x304
|
||||||
#define MCAUSE 0x342
|
|
||||||
#define MEPC 0x341
|
|
||||||
#define MSTATUS_BIT_MIE 3
|
#define MSTATUS_BIT_MIE 3
|
||||||
#define MIE_BIT_MTIE 7
|
#define MIE_BIT_MTIE 7
|
||||||
#define MIE_BIT_MEIE 11
|
#define MIE_BIT_MEIE 11
|
||||||
|
|
@ -58,10 +56,8 @@ typedef struct {
|
||||||
uint64_t t5; // x30
|
uint64_t t5; // x30
|
||||||
uint64_t t6; // x31
|
uint64_t t6; // x31
|
||||||
|
|
||||||
// Control and Status Register state (Saved in traps.S)
|
// Control and Status Register state
|
||||||
uint64_t mepc; // offset 240
|
uint64_t mepc; // offset 240 (Saved in traps.S)
|
||||||
uint64_t mcause; // offset 248
|
|
||||||
uint64_t mstatus; // offset 256
|
|
||||||
} trap_frame_t;
|
} trap_frame_t;
|
||||||
|
|
||||||
void interrupt_init();
|
void interrupt_init();
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,11 @@
|
||||||
#include <kernel/plic.h>
|
#include <kernel/plic.h>
|
||||||
#include <kernel/interrupts.h>
|
#include <kernel/interrupts.h>
|
||||||
#include <kernel/memory.h>
|
#include <kernel/memory.h>
|
||||||
#include <kernel/timer.h>
|
|
||||||
|
|
||||||
void kmain()
|
void kmain()
|
||||||
{
|
{
|
||||||
zero_bss();
|
zero_bss();
|
||||||
plic_init();
|
plic_init();
|
||||||
timer_init();
|
|
||||||
uart_init();
|
uart_init();
|
||||||
page_init();
|
page_init();
|
||||||
interrupt_init();
|
interrupt_init();
|
||||||
|
|
@ -19,12 +17,4 @@ void kmain()
|
||||||
kprintf("Hello, from %s!", "SquidgeOS");
|
kprintf("Hello, from %s!", "SquidgeOS");
|
||||||
kputs("----------------------");
|
kputs("----------------------");
|
||||||
knewline();
|
knewline();
|
||||||
while (1) {
|
|
||||||
uint64_t ticks = timer_get_ms();
|
|
||||||
kputchar('T');
|
|
||||||
kputchar(':'); // Print "T:1234" every second
|
|
||||||
kprint_int(ticks);
|
|
||||||
knewline();
|
|
||||||
delay_ms(1000);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,6 @@ void plic_init()
|
||||||
// This is a bitmask, so we shift 1 by the IRQ number.
|
// This is a bitmask, so we shift 1 by the IRQ number.
|
||||||
*PLIC_ENABLE(hart) = (1 << UART_IRQ);
|
*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
|
// 3. Set the priority threshold for Hart 0
|
||||||
// We set this to 0 so that ANY interrupt with priority > 0 gets through.
|
// We set this to 0 so that ANY interrupt with priority > 0 gets through.
|
||||||
*PLIC_THRESHOLD(hart) = 0;
|
*PLIC_THRESHOLD(hart) = 0;
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
#define PLIC_CLAIM(hart) ((volatile uint32_t *)(PLIC_BASE + 0x200004 + (hart) * 0x1000))
|
#define PLIC_CLAIM(hart) ((volatile uint32_t *)(PLIC_BASE + 0x200004 + (hart) * 0x1000))
|
||||||
|
|
||||||
#define UART_IRQ 10
|
#define UART_IRQ 10
|
||||||
#define TIMER_IRQ 7
|
|
||||||
|
|
||||||
void plic_init();
|
void plic_init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,12 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <kernel/interrupts.h>
|
||||||
#include "timer.h"
|
#include <kernel/plic.h>
|
||||||
#include "plic.h"
|
#include <kernel/timer.h>
|
||||||
#include "interrupts.h"
|
|
||||||
#include "drivers/uart.h"
|
|
||||||
|
|
||||||
_Atomic uint64_t sys_ticks = 0;
|
void timer_handle_interrupt()
|
||||||
const uint64_t tick_delta = TICKS_PER_MS;
|
{
|
||||||
|
static volatile uint64_t *mtime = (uint64_t *)CLINT_MTIME;
|
||||||
|
static volatile uint64_t *mtimecmp = (uint64_t *)CLINT_MTIMECMP(0);
|
||||||
|
|
||||||
void timer_init() {
|
*mtimecmp = *mtime + TIMER_FREQ;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,30 +1,8 @@
|
||||||
#ifndef TIMER_H
|
#ifndef KTIMER_H
|
||||||
#define TIMER_H
|
#define KTIMER_H
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
/* Define your clock frequency here based on your hardware */
|
#define TIMER_FREQ 100000
|
||||||
/* Example: 12.5 MHz for QEMU virt machine */
|
|
||||||
#define CLOCK_FREQ_HZ 12500000
|
|
||||||
|
|
||||||
/* Calculate ticks per millisecond */
|
void timer_handle_interrupt();
|
||||||
#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);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -2,8 +2,5 @@
|
||||||
#define STRING_H
|
#define STRING_H
|
||||||
|
|
||||||
void *memset(void *s, int c, size_t n);
|
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
|
#endif
|
||||||
Loading…
Add table
Add a link
Reference in a new issue