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
|
||||
|
||||
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
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include <kernel/memory.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -5,13 +5,11 @@
|
|||
#include <kernel/plic.h>
|
||||
#include <kernel/interrupts.h>
|
||||
#include <kernel/memory.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,43 +1,12 @@
|
|||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "timer.h"
|
||||
#include "plic.h"
|
||||
#include "interrupts.h"
|
||||
#include "drivers/uart.h"
|
||||
#include <kernel/interrupts.h>
|
||||
#include <kernel/plic.h>
|
||||
#include <kernel/timer.h>
|
||||
|
||||
_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;
|
||||
}
|
||||
|
|
@ -1,30 +1,8 @@
|
|||
#ifndef TIMER_H
|
||||
#define TIMER_H
|
||||
#include <stdint.h>
|
||||
#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
|
||||
|
|
@ -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
|
||||
Loading…
Add table
Add a link
Reference in a new issue