From 2d33e50074135b9a64d298aa677b0c307b726171 Mon Sep 17 00:00:00 2001 From: vhaudiquet Date: Tue, 24 Oct 2023 00:19:10 +0200 Subject: [PATCH] Define CSR STATUS bits, std functions on exception --- src/cpu/csr.h | 36 ++++++++++++++++++++++++++++++++++++ src/cpu/exception.c | 18 ++++++++++-------- src/cpu/rv32cpu.c | 7 +++---- 3 files changed, 49 insertions(+), 12 deletions(-) diff --git a/src/cpu/csr.h b/src/cpu/csr.h index 317398d..df1f3a5 100644 --- a/src/cpu/csr.h +++ b/src/cpu/csr.h @@ -61,4 +61,40 @@ /* Machine Memory Protection */ #define CSR_PMPCFG0 0x3A0 +// CSR STATUS +// SIE: Supervisor Interrupt Enable +#define STATUS_SIE 0x2 +// MIE: Machine Interrupt Enable +#define STATUS_MIE 0x8 +// SPIE: Supervisor Previous Interrupt Enable +#define STATUS_SPIE 0x20 +// MPIE: Machine Previous Interrupt Enable +#define STATUS_MPIE 0x80 +// UBE : User Big Endian (always 0 for us, we are little endian) +#define STATUS_UBE 0x40 +// SPP : Supervisor Previous Privilege +#define STATUS_SPP 0x100 +// VS (2bits) : for extensions +#define STATUS_VS 0x600 +// MPP (2bits) : Machine Previous Privilege +#define STATUS_MPP 0x1800 +// FS (2bits) : for extensions +#define STATUS_FS 0x6000 +// XS (2bits) : for extensions +#define STATUS_XS 0x18000 +// MPRV : Modify PRiVilege +#define STATUS_MPRV 0x20000 +// SUM : permit Supervisor User Memory access +#define STATUS_SUM 0x40000 +// MXR : Make eXecutable Readable +#define STATUS_MXR 0x80000 +// TVM : Trap Virtual Memory (virtualization support) +#define STATUS_TVM 0x100000 +// TW : Timeout Wait (virtualization support) +#define STATUS_TW 0x200000 +// TSR : Trap SRET (virtualization support) +#define STATUS_TSR 0x400000 +// SD : for extensions +#define STATUS_SD 0x80000000 + #endif diff --git a/src/cpu/exception.c b/src/cpu/exception.c index 9d0677f..f2db177 100644 --- a/src/cpu/exception.c +++ b/src/cpu/exception.c @@ -16,10 +16,10 @@ __attribute__((noreturn)) void exception_trigger(rv32_cpu_t* cpu, uint32_t scaus // Exceptions cannot be disabled // Unset SIE (interrupt enable) bit - cpu->csr[CSR_SSTATUS] &= ~0b10U; + csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) & (~STATUS_SIE)); // Set xCAUSE : exception cause, with interrupt bit set to null - cpu->csr[CSR_SCAUSE] = scause; + csr_write(cpu, CSR_SCAUSE, scause); if(gdbstub && scause == SCAUSE_BREAKPOINT) { cpu->sim_ticks_left = 0; @@ -31,26 +31,28 @@ __attribute__((noreturn)) void exception_trigger(rv32_cpu_t* cpu, uint32_t scaus } // Save previous interrupt enable in xSTATUS.xPIE - if(cpu->csr[CSR_SSTATUS] & 0b10U) - cpu->csr[CSR_SSTATUS] |= 0x80; + if(csr_read(cpu, CSR_SSTATUS) & STATUS_SIE) + csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SPIE); + else + csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) & (~STATUS_SPIE)); // Set previous privilege mode in xSTATUS.xPP // TODO : Allow user mode exceptions (by not setting this) - cpu->csr[CSR_SSTATUS] |= 0x100; + csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SPP); // Set privilege mode for exception handling, checking for delegation // TODO // Set xTVAL, exception-specific information related to xCAUSE - cpu->csr[CSR_STVAL] = tval; + csr_write(cpu, CSR_STVAL, tval); // Set SEPC to instruction that caused exception - cpu->csr[CSR_SEPC] = cpu->pc; + csr_write(cpu, CSR_SEPC, cpu->pc); // Set PC to xTVEC : exception handling code // xTVEC: [Base(30bits) Mode(2 bits)], address 4-byte aligned in base // Exceptions are not vectored (we can safely ignore mode) - cpu->pc = cpu->csr[CSR_STVEC] & 0xFFFFFFFC; + cpu->pc = csr_read(cpu, CSR_STVEC) & 0xFFFFFFFC; // Unlock cpu mutex, cpu_loop will lock it just after pthread_mutex_unlock(&cpu->mutex); diff --git a/src/cpu/rv32cpu.c b/src/cpu/rv32cpu.c index 0a3226c..a28c51a 100644 --- a/src/cpu/rv32cpu.c +++ b/src/cpu/rv32cpu.c @@ -529,15 +529,14 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction) case IMM_SRET: // SRET: Return from supervisor interrupt // Restore Interrupt Enable from Previous Interrupt Enable - uint32_t sstatus = csr_read(cpu, CSR_SSTATUS); - if(sstatus & 0x80) - csr_write(cpu, CSR_SSTATUS, sstatus | 0b10); + if(csr_read(cpu, CSR_SSTATUS) & STATUS_SPIE) + csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SIE); // Restore privilege mode from Previous Privilege // TODO // Set Previous Interrupt Enable to 1 - csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | 0x80); + csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SPIE); // Set Previous Privilege to 0 // TODO