From c8d4acbf0edd6e9bb2de8b74cc577ef1acb25d29 Mon Sep 17 00:00:00 2001 From: Yen-Fu Chen Date: Sat, 7 Oct 2023 13:31:29 +0800 Subject: [PATCH] Handle csr mstatus and misa correctly In the privileged arch-test, we need to set the extensions we used in the Machine ISA Register and set the Machine Status Register to privileged mode when we invoke the exception handler --- src/emulate.c | 61 ++++++++++++++++++++++++--------------------- src/riscv.c | 12 ++++++++- src/riscv.h | 12 +++++++++ src/rv32_template.c | 1 + 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/emulate.c b/src/emulate.c index 8001a929..001bbd87 100644 --- a/src/emulate.c +++ b/src/emulate.c @@ -58,35 +58,38 @@ static void rv_exception_default_handler(riscv_t *rv) rv->PC = rv->csr_mepc; /* mret */ } -#define EXCEPTION_HANDLER_IMPL(type, code) \ - static void rv_except_##type(riscv_t *rv, uint32_t mtval) \ - { \ - /* mtvec (Machine Trap-Vector Base Address Register) \ - * mtvec[MXLEN-1:2]: vector base address \ - * mtvec[1:0] : vector mode \ - */ \ - const uint32_t base = rv->csr_mtvec & ~0x3; \ - const uint32_t mode = rv->csr_mtvec & 0x3; \ - /* mepc (Machine Exception Program Counter) \ - * mtval (Machine Trap Value Register) \ - * mcause (Machine Cause Register): store exception code \ - */ \ - rv->csr_mepc = rv->PC; \ - rv->csr_mtval = mtval; \ - rv->csr_mcause = code; \ - if (!rv->csr_mtvec) { /* in case CSR is not configured */ \ - rv_exception_default_handler(rv); \ - return; \ - } \ - switch (mode) { \ - case 0: /* DIRECT: All exceptions set PC to base */ \ - rv->PC = base; \ - break; \ - /* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ \ - case 1: \ - rv->PC = base + 4 * code; \ - break; \ - } \ +#define EXCEPTION_HANDLER_IMPL(type, code) \ + static void rv_except_##type(riscv_t *rv, uint32_t mtval) \ + { \ + /* mtvec (Machine Trap-Vector Base Address Register) \ + * mtvec[MXLEN-1:2]: vector base address \ + * mtvec[1:0] : vector mode \ + */ \ + const uint32_t base = rv->csr_mtvec & ~0x3; \ + const uint32_t mode = rv->csr_mtvec & 0x3; \ + /* mepc (Machine Exception Program Counter) \ + * mtval (Machine Trap Value Register) \ + * mcause (Machine Cause Register): store exception code \ + * mstatus (Machine Status Register): keep track of and controls the \ + * hart’s current operating state \ + */ \ + rv->csr_mepc = rv->PC; \ + rv->csr_mtval = mtval; \ + rv->csr_mcause = code; \ + rv->csr_mstatus = MSTATUS_MPP; /* set privilege mode */ \ + if (!rv->csr_mtvec) { /* in case CSR is not configured */ \ + rv_exception_default_handler(rv); \ + return; \ + } \ + switch (mode) { \ + case 0: /* DIRECT: All exceptions set PC to base */ \ + rv->PC = base; \ + break; \ + /* VECTORED: Asynchronous interrupts set PC to base + 4 * code */ \ + case 1: \ + rv->PC = base + 4 * code; \ + break; \ + } \ } /* RISC-V exception handlers */ diff --git a/src/riscv.c b/src/riscv.c index 97f51c81..c3d60a87 100644 --- a/src/riscv.c +++ b/src/riscv.c @@ -254,8 +254,18 @@ void rv_reset(riscv_t *rv, riscv_word_t pc, int argc, char **args) rv->csr_mtvec = 0; rv->csr_cycle = 0; rv->csr_mstatus = 0; - + rv->csr_misa |= MISA_SUPER | MISA_USER | MISA_I; +#if RV32_HAS(EXT_A) + rv->csr_misa |= MISA_A; +#endif +#if RV32_HAS(EXT_C) + rv->csr_misa |= MISA_C; +#endif +#if RV32_HAS(EXT_M) + rv->csr_misa |= MISA_M; +#endif #if RV32_HAS(EXT_F) + rv->csr_misa |= MISA_F; /* reset float registers */ memset(rv->F, 0, sizeof(float) * N_RV_REGS); rv->csr_fcsr = 0; diff --git a/src/riscv.h b/src/riscv.h index 992751cf..100c4dd3 100644 --- a/src/riscv.h +++ b/src/riscv.h @@ -67,6 +67,18 @@ enum { }; /* clang-format on */ +#define MISA_SUPER (1 << ('S' - 'A')) +#define MISA_USER (1 << ('U' - 'A')) +#define MISA_I (1 << ('I' - 'A')) +#define MISA_M (1 << ('M' - 'A')) +#define MISA_A (1 << ('A' - 'A')) +#define MISA_F (1 << ('F' - 'A')) +#define MISA_C (1 << ('C' - 'A')) +#define MSTATUS_MPIE_SHIFT 7 +#define MSTATUS_MPP_SHIFT 11 +#define MSTATUS_MPIE (1 << MSTATUS_MPIE_SHIFT) +#define MSTATUS_MPP (3 << MSTATUS_MPP_SHIFT) + /* forward declaration for internal structure */ typedef struct riscv_internal riscv_t; typedef void *riscv_user_t; diff --git a/src/rv32_template.c b/src/rv32_template.c index 7f5a14b1..fddcbb74 100644 --- a/src/rv32_template.c +++ b/src/rv32_template.c @@ -285,6 +285,7 @@ RVOP(hret, { /* MRET: return from traps in U-mode */ RVOP(mret, { + rv->csr_mstatus = MSTATUS_MPIE; rv->PC = rv->csr_mepc; return true; })