Define CSR STATUS bits, std functions on exception

master
vhaudiquet 1 year ago
parent cf8a1de199
commit 2d33e50074
  1. 36
      src/cpu/csr.h
  2. 18
      src/cpu/exception.c
  3. 7
      src/cpu/rv32cpu.c

@ -61,4 +61,40 @@
/* Machine Memory Protection */ /* Machine Memory Protection */
#define CSR_PMPCFG0 0x3A0 #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 #endif

@ -16,10 +16,10 @@ __attribute__((noreturn)) void exception_trigger(rv32_cpu_t* cpu, uint32_t scaus
// Exceptions cannot be disabled // Exceptions cannot be disabled
// Unset SIE (interrupt enable) bit // 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 // 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) if(gdbstub && scause == SCAUSE_BREAKPOINT)
{ {
cpu->sim_ticks_left = 0; 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 // Save previous interrupt enable in xSTATUS.xPIE
if(cpu->csr[CSR_SSTATUS] & 0b10U) if(csr_read(cpu, CSR_SSTATUS) & STATUS_SIE)
cpu->csr[CSR_SSTATUS] |= 0x80; 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 // Set previous privilege mode in xSTATUS.xPP
// TODO : Allow user mode exceptions (by not setting this) // 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 // Set privilege mode for exception handling, checking for delegation
// TODO // TODO
// Set xTVAL, exception-specific information related to xCAUSE // 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 // 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 // Set PC to xTVEC : exception handling code
// xTVEC: [Base(30bits) Mode(2 bits)], address 4-byte aligned in base // xTVEC: [Base(30bits) Mode(2 bits)], address 4-byte aligned in base
// Exceptions are not vectored (we can safely ignore mode) // 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 // Unlock cpu mutex, cpu_loop will lock it just after
pthread_mutex_unlock(&cpu->mutex); pthread_mutex_unlock(&cpu->mutex);

@ -529,15 +529,14 @@ static void cpu_execute(rv32_cpu_t* cpu, instruction_t* instruction)
case IMM_SRET: case IMM_SRET:
// SRET: Return from supervisor interrupt // SRET: Return from supervisor interrupt
// Restore Interrupt Enable from Previous Interrupt Enable // Restore Interrupt Enable from Previous Interrupt Enable
uint32_t sstatus = csr_read(cpu, CSR_SSTATUS); if(csr_read(cpu, CSR_SSTATUS) & STATUS_SPIE)
if(sstatus & 0x80) csr_write(cpu, CSR_SSTATUS, csr_read(cpu, CSR_SSTATUS) | STATUS_SIE);
csr_write(cpu, CSR_SSTATUS, sstatus | 0b10);
// Restore privilege mode from Previous Privilege // Restore privilege mode from Previous Privilege
// TODO // TODO
// Set Previous Interrupt Enable to 1 // 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 // Set Previous Privilege to 0
// TODO // TODO

Loading…
Cancel
Save