From c43ed4a2e36c30a6248893a19388f5d8748df218 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 3 Sep 2024 13:20:46 -0400 Subject: [PATCH 1/4] Use upstream 'name' field for CSR names This should fix the use of CSR names in the GDB stub. --- target/riscv/cpu.h | 1 - target/riscv/csr.c | 16 ++++++++-------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 71ea82f7e2..a38dd5d2f9 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -814,7 +814,6 @@ typedef struct { riscv_csr_write_fn write; riscv_csr_op_fn op; riscv_csr_log_update_fn log_update; - const char *csr_name; } riscv_csr_operations; /* CSR function table constants */ diff --git a/target/riscv/csr.c b/target/riscv/csr.c index aee5be5824..ec31bf2d9e 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1560,7 +1560,7 @@ static void log_changed_csr_fn(CPURISCVState *env, int csrno, target_ulong value) { if (qemu_log_instr_enabled(env)) { - qemu_log_instr_reg(env, csr_ops[csrno].csr_name, value); + qemu_log_instr_reg(env, csr_ops[csrno].name, value); } } #else @@ -1568,18 +1568,18 @@ static void log_changed_csr_fn(CPURISCVState *env, int csrno, #endif /* Define csr_ops entry for read-only CSR register */ -#define CSR_OP_FN_R(pred, readfn, name) \ +#define CSR_OP_FN_R(pred, readfn, csr_name) \ {.predicate=pred, .read=readfn, .write=NULL, .op=NULL, \ - .log_update=NULL, .csr_name=name} + .log_update=NULL, .name=csr_name} /* Shorthand for functions following the read_ pattern */ #define CSR_OP_R(pred, name) \ CSR_OP_FN_R(pred, glue(read_, name), stringify(name)) /* Internal - use CSR_OP_FN_RW, CSR_OP_RW and CSR_OP_NOLOG_RW */ -#define _CSR_OP_FN_RW(pred, readfn, writefn, logfn, name) \ +#define _CSR_OP_FN_RW(pred, readfn, writefn, logfn, csr_name) \ {.predicate=pred, .read=readfn, .write=writefn, \ - .op=NULL, .log_update=logfn, .csr_name=name} + .op=NULL, .log_update=logfn, .name=csr_name} /* Define csr_ops entry for read-write CSR register */ #define CSR_OP_FN_RW(pred, readfn, writefn, name) \ @@ -1599,10 +1599,10 @@ static void log_changed_csr_fn(CPURISCVState *env, int csrno, NULL, stringify(name)) /* Define csr_ops entry for read-modify-write CSR register */ -#define CSR_OP_RMW(pred, name) \ +#define CSR_OP_RMW(pred, csr_name) \ {.predicate=pred, .read=NULL, .write=NULL, \ - .op=glue(rmw_, name), .log_update=log_changed_csr_fn, \ - .csr_name=stringify(name)} + .op=glue(rmw_, csr_name), .log_update=log_changed_csr_fn, \ + .name=stringify(csr_name)} /* Control and Status Register function table */ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { From 685ea15ee0a276c7c5f58bcda278ba2c5735cbd8 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 3 Sep 2024 13:36:29 -0400 Subject: [PATCH 2/4] riscv: Use all lower-case for SCR names in struct CPURISCVState This matches the style for all other RISC-V registers including CSRs and avoids a weird collision with STDC which zlib defines as an alias of __STDC__. --- target/cheri-common/cheri-translate-utils.h | 2 +- target/riscv/cheri-archspecific-early.h | 8 +-- target/riscv/cheri-archspecific.h | 4 +- target/riscv/cpu.c | 54 ++++++++++----------- target/riscv/cpu.h | 44 ++++++++--------- target/riscv/cpu_helper.c | 36 +++++++------- target/riscv/csr.c | 24 ++++----- target/riscv/gdbstub.c | 4 +- target/riscv/helper_utils.h | 2 +- target/riscv/machine.c | 18 +++---- target/riscv/op_helper.c | 12 ++--- target/riscv/op_helper_cheri.c | 46 +++++++++--------- target/riscv/translate.c | 4 +- 13 files changed, 129 insertions(+), 129 deletions(-) diff --git a/target/cheri-common/cheri-translate-utils.h b/target/cheri-common/cheri-translate-utils.h index 7d1f9f9619..5d03f8d97b 100644 --- a/target/cheri-common/cheri-translate-utils.h +++ b/target/cheri-common/cheri-translate-utils.h @@ -128,7 +128,7 @@ TCGv_i64 cpu_reg(DisasContext *s, int reg); #elif defined(TARGET_RISCV) -#define DDC_ENV_OFFSET offsetof(CPUArchState, DDC) +#define DDC_ENV_OFFSET offsetof(CPUArchState, ddc) #define target_get_gpr_global(ctx, reg) (assert(0), (TCGv)NULL) #define target_get_gpr(ctx, t, reg) gen_get_gpr((TCGv)t, reg) static inline void _gen_set_gpr(DisasContext *ctx, int reg_num_dst, TCGv t, diff --git a/target/riscv/cheri-archspecific-early.h b/target/riscv/cheri-archspecific-early.h index b8b5e73c8e..f7fbc7f803 100644 --- a/target/riscv/cheri-archspecific-early.h +++ b/target/riscv/cheri-archspecific-early.h @@ -117,14 +117,14 @@ enum CheriSCR { #define CINVOKE_DATA_REGNUM 31 static inline const cap_register_t *cheri_get_ddc(CPURISCVState *env) { - cheri_debug_assert(env->DDC.cr_extra == CREG_FULLY_DECOMPRESSED); - return &env->DDC; + cheri_debug_assert(env->ddc.cr_extra == CREG_FULLY_DECOMPRESSED); + return &env->ddc; } static inline const cap_register_t *_cheri_get_pcc_unchecked(CPURISCVState *env) { - cheri_debug_assert(env->PCC.cr_extra == CREG_FULLY_DECOMPRESSED); - return &env->PCC; + cheri_debug_assert(env->pcc.cr_extra == CREG_FULLY_DECOMPRESSED); + return &env->pcc; } static inline GPCapRegs *cheri_get_gpcrs(CPUArchState *env) { diff --git a/target/riscv/cheri-archspecific.h b/target/riscv/cheri-archspecific.h index bdb8b2881d..37d9354886 100644 --- a/target/riscv/cheri-archspecific.h +++ b/target/riscv/cheri-archspecific.h @@ -119,8 +119,8 @@ static inline void update_next_pcc_for_tcg(CPUArchState *env, uint32_t cjalr_flags) { assert_valid_jump_target(target); - // On return to TCG we will jump there immediately, so update env->PCC now. - env->PCC = *target; + // On return to TCG we will jump there immediately, so update env->pcc now. + env->pcc = *target; #ifdef CONFIG_DEBUG_TCG env->_pc_is_current = true; // PCC.cursor is up-to-date again. #endif diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 98d54ba317..0eb49f00c9 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -288,7 +288,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) #endif qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", PC_ADDR(env)); #ifdef TARGET_CHERI - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc (offset) ", GET_SPECIAL_REG_ARCH(env, pc, PCC)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc (offset) ", GET_SPECIAL_REG_ARCH(env, pc, pcc)); #endif #ifndef CONFIG_USER_ONLY qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid); @@ -312,15 +312,15 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags) if (riscv_has_ext(env, RVH)) { qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg); } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", GET_SPECIAL_REG_ARCH(env, mtvec, MTCC)); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec ", GET_SPECIAL_REG_ARCH(env, stvec, STCC)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", GET_SPECIAL_REG_ARCH(env, mtvec, mtcc)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec ", GET_SPECIAL_REG_ARCH(env, stvec, stcc)); if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec ", GET_SPECIAL_REG_ARCH(env, vstvec, VSTCC)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec ", GET_SPECIAL_REG_ARCH(env, vstvec, vstcc)); } - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", GET_SPECIAL_REG_ARCH(env, mepc, MEPCC)); - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc ", GET_SPECIAL_REG_ARCH(env, sepc, SEPCC)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", GET_SPECIAL_REG_ARCH(env, mepc, mepcc)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc ", GET_SPECIAL_REG_ARCH(env, sepc, sepcc)); if (riscv_has_ext(env, RVH)) { - qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc ", GET_SPECIAL_REG_ARCH(env, vsepc, VSEPCC)); + qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc ", GET_SPECIAL_REG_ARCH(env, vsepc, vsepcc)); } qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause ", env->mcause); qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause ", env->scause); @@ -358,7 +358,7 @@ static void riscv_cpu_set_pc(CPUState *cs, vaddr value) RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; #ifdef TARGET_CHERI - cheri_update_pcc(&env->PCC, value, /*can_be_unrepresentable=*/true); + cheri_update_pcc(&env->pcc, value, /*can_be_unrepresentable=*/true); #else env->pc = value; #endif @@ -397,11 +397,11 @@ void restore_state_to_opc(CPURISCVState *env, TranslationBlock *tb, target_ulong *data) { #ifdef TARGET_CHERI - assert(cap_is_in_bounds(&env->PCC, data[0], 1)); - if (unlikely(env->PCC._cr_cursor != data[0])) { + assert(cap_is_in_bounds(&env->pcc, data[0], 1)); + if (unlikely(env->pcc._cr_cursor != data[0])) { qemu_log_instr_or_mask_msg(env, CPU_LOG_INT, "%s: Updating pc from TB: " TARGET_FMT_lx " -> " TARGET_FMT_lx "\n", - __func__, (target_ulong)env->PCC._cr_cursor, data[0]); + __func__, (target_ulong)env->pcc._cr_cursor, data[0]); } #endif riscv_update_pc(env, data[0], /*can_be_unrepresentable=*/false); @@ -522,7 +522,7 @@ void rvfi_dii_communicate(CPUState* cs, CPURISCVState* env, bool was_trap) { static bool rvfi_dii_started = false; static unsigned rvfi_dii_version = 1; // Single-step completed -> update PC in the trace buffer - env->rvfi_dii_trace.PC.rvfi_pc_wdata = GET_SPECIAL_REG_ARCH(env, pc, PCC); + env->rvfi_dii_trace.PC.rvfi_pc_wdata = GET_SPECIAL_REG_ARCH(env, pc, pcc); env->rvfi_dii_trace.INST.rvfi_order++; // TestRIG expects a zero $pc after a trap: @@ -658,7 +658,7 @@ void rvfi_dii_communicate(CPUState* cs, CPURISCVState* env, bool was_trap) { tb_flush(cs); // flush TCG state env->rvfi_dii_injected_insn = cmd_buf.rvfi_dii_insn; env->rvfi_dii_have_injected_insn = true; - env->rvfi_dii_trace.PC.rvfi_pc_rdata = GET_SPECIAL_REG_ARCH(env, pc, PCC); + env->rvfi_dii_trace.PC.rvfi_pc_rdata = GET_SPECIAL_REG_ARCH(env, pc, pcc); env->rvfi_dii_trace.INST.rvfi_mode = env->priv; env->rvfi_dii_trace.INST.rvfi_ixl = get_field(env->misa, MISA_MXL); resume_all_vcpus(); @@ -736,23 +736,23 @@ static void riscv_cpu_reset(DeviceState *dev) /* * See Table 5.2: Special Capability Registers (SCRs) in the CHERI ISA spec */ - set_max_perms_capability(&env->PCC, env->resetvec); - set_max_perms_capability(&env->DDC, 0); + set_max_perms_capability(&env->pcc, env->resetvec); + set_max_perms_capability(&env->ddc, 0); // User mode trap handling: - set_max_perms_capability(&env->UTCC, 0); - null_capability(&env->UTDC); - null_capability(&env->UScratchC); - set_max_perms_capability(&env->UEPCC, 0); + set_max_perms_capability(&env->utcc, 0); + null_capability(&env->utdc); + null_capability(&env->uscratchc); + set_max_perms_capability(&env->uepcc, 0); // Supervisor mode trap handling - set_max_perms_capability(&env->STCC, 0); - null_capability(&env->STDC); - null_capability(&env->SScratchC); - set_max_perms_capability(&env->SEPCC, 0); + set_max_perms_capability(&env->stcc, 0); + null_capability(&env->stdc); + null_capability(&env->sscratchc); + set_max_perms_capability(&env->sepcc, 0); // Machine mode trap handling - set_max_perms_capability(&env->MTCC, 0); - null_capability(&env->MTDC); - null_capability(&env->MScratchC); - set_max_perms_capability(&env->MEPCC, 0); + set_max_perms_capability(&env->mtcc, 0); + null_capability(&env->mtdc); + null_capability(&env->mscratchc); + set_max_perms_capability(&env->mepcc, 0); #endif /* TARGET_CHERI */ #ifdef CONFIG_DEBUG_TCG env->_pc_is_current = true; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index a38dd5d2f9..1f790b0a49 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -136,8 +136,8 @@ struct CPURISCVState { target_ulong vtype; #ifdef TARGET_CHERI - cap_register_t PCC; // SCR 0 Program counter cap. (PCC) TODO: implement this properly - cap_register_t DDC; // SCR 1 Default data cap. (DDC) + cap_register_t pcc; // SCR 0 Program counter cap. (PCC) TODO: implement this properly + cap_register_t ddc; // SCR 1 Default data cap. (DDC) #else target_ulong pc; #endif @@ -200,17 +200,17 @@ struct CPURISCVState { #ifdef TARGET_CHERI // XXX: not implemented properly - cap_register_t UTCC; // SCR 4 User trap code cap. (UTCC) - cap_register_t UTDC; // SCR 5 User trap data cap. (UTDC) - cap_register_t UScratchC; // SCR 6 User scratch cap. (UScratchC) - cap_register_t UEPCC; // SCR 7 User exception PC cap. (UEPCC) + cap_register_t utcc; // SCR 4 User trap code cap. (UTCC) + cap_register_t utdc; // SCR 5 User trap data cap. (UTDC) + cap_register_t uscratchc; // SCR 6 User scratch cap. (UScratchC) + cap_register_t uepcc; // SCR 7 User exception PC cap. (UEPCC) #endif #ifdef TARGET_CHERI - cap_register_t STCC; // SCR 12 Supervisor trap code cap. (STCC) - cap_register_t STDC; // SCR 13 Supervisor trap data cap. (STDC) - cap_register_t SScratchC; // SCR 14 Supervisor scratch cap. (SScratchC) - cap_register_t SEPCC; // SCR 15 Supervisor exception PC cap. (SEPCC) + cap_register_t stcc; // SCR 12 Supervisor trap code cap. (STCC) + cap_register_t stdc; // SCR 13 Supervisor trap data cap. (STDC) + cap_register_t sscratchc; // SCR 14 Supervisor scratch cap. (SScratchC) + cap_register_t sepcc; // SCR 15 Supervisor exception PC cap. (SEPCC) #else target_ulong stvec; target_ulong sepc; @@ -218,10 +218,10 @@ struct CPURISCVState { target_ulong scause; #ifdef TARGET_CHERI - cap_register_t MTCC; // SCR 28 Machine trap code cap. (MTCC) - cap_register_t MTDC; // SCR 29 Machine trap data cap. (MTDC) - cap_register_t MScratchC; // SCR 30 Machine scratch cap. (MScratchC) - cap_register_t MEPCC; // SCR 31 Machine exception PC cap. (MEPCC) + cap_register_t mtcc; // SCR 28 Machine trap code cap. (MTCC) + cap_register_t mtdc; // SCR 29 Machine trap data cap. (MTDC) + cap_register_t mscratchc; // SCR 30 Machine scratch cap. (MScratchC) + cap_register_t mepcc; // SCR 31 Machine exception PC cap. (MEPCC) #else target_ulong mtvec; target_ulong mepc; @@ -241,10 +241,10 @@ struct CPURISCVState { /* Virtual CSRs */ #ifdef TARGET_CHERI - cap_register_t VSTCC; - cap_register_t VSTDC; - cap_register_t VSScratchC; - cap_register_t VSEPCC; + cap_register_t vstcc; + cap_register_t vstdc; + cap_register_t vsscratchc; + cap_register_t vsepcc; #else target_ulong vstvec; target_ulong vsepc; @@ -264,8 +264,8 @@ struct CPURISCVState { /* HS Backup CSRs */ #ifdef TARGET_CHERI - cap_register_t STCC_HS; - cap_register_t SEPCC_HS; + cap_register_t stcc_hs; + cap_register_t sepcc_hs; #else target_ulong stvec_hs; target_ulong sepc_hs; @@ -372,7 +372,7 @@ static inline bool pc_is_current(CPURISCVState *env) // that shouldn't really matter. static inline target_ulong cpu_get_recent_pc(CPURISCVState *env) { #ifdef TARGET_CHERI - return env->PCC._cr_cursor; + return env->pcc._cr_cursor; #else return env->pc; #endif @@ -712,7 +712,7 @@ riscv_cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc, uint32_t flags = 0; *pc = PC_ADDR(env); // We want the full virtual address here (no offset) #ifdef TARGET_CHERI - cheri_cpu_get_tb_cpu_state(&env->PCC, &env->DDC, cs_base, cs_top, + cheri_cpu_get_tb_cpu_state(&env->pcc, &env->ddc, cs_base, cs_top, cheri_flags); #else *cs_base = 0; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index edec70f249..0452e294dd 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -156,8 +156,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env, bool hs_mode_trap) riscv_log_instr_csr_changed(env, CSR_VSSTATUS); /* mstatus may be modified again by do_interrupt */ - COPY_SPECIAL_REG(env, vstvec, VSTCC, stvec, STCC); - COPY_SPECIAL_REG(env, stvec, STCC, stvec_hs, STCC_HS); + COPY_SPECIAL_REG(env, vstvec, vstcc, stvec, stcc); + COPY_SPECIAL_REG(env, stvec, stcc, stvec_hs, stcc_hs); LOG_SPECIAL_REG(env, CSR_VSTVEC, CheriSCR_BSTCC); LOG_SPECIAL_REG(env, CSR_STVEC, CheriSCR_STCC); @@ -166,8 +166,8 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env, bool hs_mode_trap) riscv_log_instr_csr_changed(env, CSR_VSSCRATCH); riscv_log_instr_csr_changed(env, CSR_SSCRATCH); - COPY_SPECIAL_REG(env, vsepc, VSEPCC, sepc, SEPCC); - COPY_SPECIAL_REG(env, sepc, SEPCC, sepc_hs, SEPCC_HS); + COPY_SPECIAL_REG(env, vsepc, vsepcc, sepc, sepcc); + COPY_SPECIAL_REG(env, sepc, sepcc, sepc_hs, sepcc_hs); LOG_SPECIAL_REG(env, CSR_VSEPC, CheriSCR_BSEPCC); LOG_SPECIAL_REG(env, CSR_SEPC, CheriSCR_SEPCC); @@ -201,16 +201,16 @@ void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env, bool hs_mode_trap) env->mstatus &= ~mstatus_mask; env->mstatus |= env->vsstatus; - COPY_SPECIAL_REG(env, stvec_hs, STCC_HS, stvec, STCC); - COPY_SPECIAL_REG(env, stvec, STCC, vstvec, VSTCC); + COPY_SPECIAL_REG(env, stvec_hs, stcc_hs, stvec, stcc); + COPY_SPECIAL_REG(env, stvec, stcc, vstvec, vstcc); LOG_SPECIAL_REG(env, CSR_STVEC, CheriSCR_STCC); env->sscratch_hs = env->sscratch; env->sscratch = env->vsscratch; riscv_log_instr_csr_changed(env, CSR_SSCRATCH); - COPY_SPECIAL_REG(env, sepc_hs, SEPCC_HS, sepc, SEPCC); - COPY_SPECIAL_REG(env, sepc, SEPCC, vsepc, VSEPCC); + COPY_SPECIAL_REG(env, sepc_hs, sepcc_hs, sepc, sepcc); + COPY_SPECIAL_REG(env, sepc, sepcc, vsepc, vsepcc); LOG_SPECIAL_REG(env, CSR_SEPC, CheriSCR_SEPCC); env->scause_hs = env->scause; @@ -1233,8 +1233,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, /* TODO(am2419): do we log PCC as a changed register? */ #define riscv_update_pc_for_exc_handler(env, src_cap, new_pc) \ do { \ - cheri_update_pcc_for_exc_handler(&env->PCC, src_cap, new_pc); \ - qemu_log_instr_dbg_cap(env, "PCC", &env->PCC); \ + cheri_update_pcc_for_exc_handler(&env->pcc, src_cap, new_pc); \ + qemu_log_instr_dbg_cap(env, "PCC", &env->pcc); \ } while (false) #else /* @@ -1410,7 +1410,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 1)); riscv_log_instr_csr_changed(env, CSR_SCAUSE); - COPY_SPECIAL_REG(env, sepc, SEPCC, pc, PCC); + COPY_SPECIAL_REG(env, sepc, sepcc, pc, pcc); LOG_SPECIAL_REG(env, CSR_SEPC, CheriSCR_SEPCC); env->sbadaddr = tval; @@ -1418,10 +1418,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->htval = htval; riscv_log_instr_csr_changed(env, CSR_HTVAL); - target_ulong stvec = GET_SPECIAL_REG_ADDR(env, stvec, STCC); + target_ulong stvec = GET_SPECIAL_REG_ADDR(env, stvec, stcc); target_ulong new_pc = (stvec >> 2 << 2) + ((async && (stvec & 3) == 1) ? cause * 4 : 0); - riscv_update_pc_for_exc_handler(env, &env->STCC, new_pc); + riscv_update_pc_for_exc_handler(env, &env->stcc, new_pc); riscv_cpu_set_mode(env, PRV_S); } else { /* handle the trap in M-mode */ @@ -1451,7 +1451,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->mcause = cause | ~(((target_ulong)-1) >> async); riscv_log_instr_csr_changed(env, CSR_MCAUSE); - COPY_SPECIAL_REG(env, mepc, MEPCC, pc, PCC); + COPY_SPECIAL_REG(env, mepc, mepcc, pc, pcc); LOG_SPECIAL_REG(env, CSR_MEPC, CheriSCR_MEPCC); env->mbadaddr = tval; @@ -1459,10 +1459,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->mtval2 = mtval2; riscv_log_instr_csr_changed(env, CSR_MTVAL2); - target_ulong mtvec = GET_SPECIAL_REG_ADDR(env, mtvec, MTCC); + target_ulong mtvec = GET_SPECIAL_REG_ADDR(env, mtvec, mtcc); target_ulong new_pc = (mtvec >> 2 << 2) + ((async && (mtvec & 3) == 1) ? cause * 4 : 0); - riscv_update_pc_for_exc_handler(env, &env->MTCC, new_pc); + riscv_update_pc_for_exc_handler(env, &env->mtcc, new_pc); riscv_cpu_set_mode(env, PRV_M); } @@ -1470,10 +1470,10 @@ void riscv_cpu_do_interrupt(CPUState *cs) if (qemu_log_instr_enabled(env)) { if (async) { qemu_log_instr_interrupt(env, cause, - GET_SPECIAL_REG_ADDR(env, pc, PCC)); + GET_SPECIAL_REG_ADDR(env, pc, pcc)); } else { qemu_log_instr_exception(env, cause, - GET_SPECIAL_REG_ADDR(env, pc, PCC), tval); + GET_SPECIAL_REG_ADDR(env, pc, pcc), tval); } } #endif diff --git a/target/riscv/csr.c b/target/riscv/csr.c index ec31bf2d9e..eedd44c290 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -673,7 +673,7 @@ static int write_mie(CPURISCVState *env, int csrno, target_ulong val) static int read_mtvec(CPURISCVState *env, int csrno, target_ulong *val) { - *val = GET_SPECIAL_REG_ARCH(env, mtvec, MTCC); + *val = GET_SPECIAL_REG_ARCH(env, mtvec, mtcc); return 0; } @@ -681,7 +681,7 @@ static int write_mtvec(CPURISCVState *env, int csrno, target_ulong val) { /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ if ((val & 3) < 2) { - SET_SPECIAL_REG(env, mtvec, MTCC, val); + SET_SPECIAL_REG(env, mtvec, mtcc, val); } else { qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: reserved mode not supported\n"); } @@ -735,7 +735,7 @@ static int write_mscratch(CPURISCVState *env, int csrno, target_ulong val) static int read_mepc(CPURISCVState *env, int csrno, target_ulong *val) { - *val = GET_SPECIAL_REG_ARCH(env, mepc, MEPCC); + *val = GET_SPECIAL_REG_ARCH(env, mepc, mepcc); // RISC-V privileged spec 3.1.15 Machine Exception Program Counter (mepc): // "The low bit of mepc (mepc[0]) is always zero. [...] Whenever IALIGN=32, // mepc[1] is masked on reads so that it appears to be 0." @@ -745,7 +745,7 @@ static int read_mepc(CPURISCVState *env, int csrno, target_ulong *val) static int write_mepc(CPURISCVState *env, int csrno, target_ulong val) { - SET_SPECIAL_REG(env, mepc, MEPCC, val); + SET_SPECIAL_REG(env, mepc, mepcc, val); return 0; } @@ -849,7 +849,7 @@ static int write_sie(CPURISCVState *env, int csrno, target_ulong val) static int read_stvec(CPURISCVState *env, int csrno, target_ulong *val) { - *val = GET_SPECIAL_REG_ARCH(env, stvec, STCC); + *val = GET_SPECIAL_REG_ARCH(env, stvec, stcc); return 0; } @@ -857,7 +857,7 @@ static int write_stvec(CPURISCVState *env, int csrno, target_ulong val) { /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ if ((val & 3) < 2) { - SET_SPECIAL_REG(env, stvec, STCC, val); + SET_SPECIAL_REG(env, stvec, stcc, val); } else { qemu_log_mask(LOG_UNIMP, "CSR_STVEC: reserved mode not supported\n"); } @@ -891,7 +891,7 @@ static int write_sscratch(CPURISCVState *env, int csrno, target_ulong val) static int read_sepc(CPURISCVState *env, int csrno, target_ulong *val) { - *val = GET_SPECIAL_REG_ARCH(env, sepc, SEPCC); + *val = GET_SPECIAL_REG_ARCH(env, sepc, sepcc); // RISC-V privileged spec 4.1.7 Supervisor Exception Program Counter (sepc) // "The low bit of sepc (sepc[0]) is always zero. [...] Whenever IALIGN=32, // sepc[1] is masked on reads so that it appears to be 0." @@ -901,7 +901,7 @@ static int read_sepc(CPURISCVState *env, int csrno, target_ulong *val) static int write_sepc(CPURISCVState *env, int csrno, target_ulong val) { - SET_SPECIAL_REG(env, sepc, SEPCC, val); + SET_SPECIAL_REG(env, sepc, sepcc, val); return 0; } @@ -1208,13 +1208,13 @@ static int write_vsstatus(CPURISCVState *env, int csrno, target_ulong val) static int read_vstvec(CPURISCVState *env, int csrno, target_ulong *val) { - *val = GET_SPECIAL_REG_ARCH(env, vstvec, VSTCC); + *val = GET_SPECIAL_REG_ARCH(env, vstvec, vstcc); return 0; } static int write_vstvec(CPURISCVState *env, int csrno, target_ulong val) { - SET_SPECIAL_REG(env, vstvec, VSTCC, val); + SET_SPECIAL_REG(env, vstvec, vstcc, val); return 0; } @@ -1232,13 +1232,13 @@ static int write_vsscratch(CPURISCVState *env, int csrno, target_ulong val) static int read_vsepc(CPURISCVState *env, int csrno, target_ulong *val) { - *val = GET_SPECIAL_REG_ARCH(env, vsepc, VSEPCC); + *val = GET_SPECIAL_REG_ARCH(env, vsepc, vsepcc); return 0; } static int write_vsepc(CPURISCVState *env, int csrno, target_ulong val) { - SET_SPECIAL_REG(env, vsepc, VSEPCC, val); + SET_SPECIAL_REG(env, vsepc, vsepcc, val); return 0; } diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index 358ac023fb..fd100980fd 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -33,7 +33,7 @@ int riscv_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) if (n < 32) { return gdb_get_regl(mem_buf, gpr_int_value(env, n)); } else if (n == 32) { - return gdb_get_regl(mem_buf, GET_SPECIAL_REG_ARCH(env, pc, PCC)); + return gdb_get_regl(mem_buf, GET_SPECIAL_REG_ARCH(env, pc, pcc)); } return 0; } @@ -51,7 +51,7 @@ int riscv_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) return sizeof(target_ulong); } else if (n == 32) { /* TODO(am2419): arguably we don't want to log changes from gdb */ - SET_SPECIAL_REG(env, pc, PCC, ldtul_p(mem_buf)); + SET_SPECIAL_REG(env, pc, pcc, ldtul_p(mem_buf)); return sizeof(target_ulong); } return 0; diff --git a/target/riscv/helper_utils.h b/target/riscv/helper_utils.h index da704ec269..345e5d094a 100644 --- a/target/riscv/helper_utils.h +++ b/target/riscv/helper_utils.h @@ -67,7 +67,7 @@ static inline void riscv_update_pc(CPURISCVState *env, target_ulong pc_addr, bool can_be_unrepresentable) { #ifdef TARGET_CHERI - cheri_update_pcc(&env->PCC, pc_addr, can_be_unrepresentable); + cheri_update_pcc(&env->pcc, pc_addr, can_be_unrepresentable); #else env->pc = pc_addr; #endif diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 796c6d77fa..5d12eaf7f5 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -116,9 +116,9 @@ static const VMStateDescription vmstate_hyper = { VMSTATE_UINT64(env.htimedelta, RISCVCPU), VMSTATE_UINT64(env.vsstatus, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.vstvec, env.VSTCC, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.vstvec, env.vstcc, RISCVCPU), VMSTATE_UINTTL(env.vsscratch, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.vsepc, env.VSEPCC, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.vsepc, env.vsepcc, RISCVCPU), VMSTATE_UINTTL(env.vscause, RISCVCPU), VMSTATE_UINTTL(env.vstval, RISCVCPU), VMSTATE_UINTTL(env.vsatp, RISCVCPU), @@ -126,9 +126,9 @@ static const VMStateDescription vmstate_hyper = { VMSTATE_UINTTL(env.mtval2, RISCVCPU), VMSTATE_UINTTL(env.mtinst, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.stvec_hs, env.STCC_HS, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.stvec_hs, env.stcc_hs, RISCVCPU), VMSTATE_UINTTL(env.sscratch_hs, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.sepc_hs, env.SEPCC_HS, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.sepc_hs, env.sepcc_hs, RISCVCPU), VMSTATE_UINTTL(env.scause_hs, RISCVCPU), VMSTATE_UINTTL(env.stval_hs, RISCVCPU), VMSTATE_UINTTL(env.satp_hs, RISCVCPU), @@ -150,7 +150,7 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32), #endif VMSTATE_UINT64_ARRAY(env.fpr, RISCVCPU, 32), - VMSTATE_UINTTL_OR_CAP(env.pc, env.PCC, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.pc, env.pcc, RISCVCPU), VMSTATE_UINTTL(env.load_res, RISCVCPU), VMSTATE_UINTTL(env.load_val, RISCVCPU), VMSTATE_UINTTL(env.frm, RISCVCPU), @@ -175,11 +175,11 @@ const VMStateDescription vmstate_riscv_cpu = { VMSTATE_UINTTL(env.sbadaddr, RISCVCPU), VMSTATE_UINTTL(env.mbadaddr, RISCVCPU), VMSTATE_UINTTL(env.medeleg, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.stvec, env.STCC, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.sepc, env.SEPCC, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.stvec, env.stcc, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.sepc, env.sepcc, RISCVCPU), VMSTATE_UINTTL(env.scause, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.mtvec, env.MTCC, RISCVCPU), - VMSTATE_UINTTL_OR_CAP(env.mepc, env.MEPCC, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.mtvec, env.mtcc, RISCVCPU), + VMSTATE_UINTTL_OR_CAP(env.mepc, env.mepcc, RISCVCPU), VMSTATE_UINTTL(env.mcause, RISCVCPU), VMSTATE_UINTTL(env.mtval, RISCVCPU), VMSTATE_UINTTL(env.scounteren, RISCVCPU), diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 3bee75e515..15b4065733 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -119,7 +119,7 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) } #endif - target_ulong retpc = GET_SPECIAL_REG_ADDR(env, sepc, SEPCC); + target_ulong retpc = GET_SPECIAL_REG_ADDR(env, sepc, sepcc); // We have to clear the low bit of the address since that is defined as zero // in the privileged spec. The cheri_update_pcc_for_exc_return() check below // will de-tag pcc if this would result changing the address for sealed caps. @@ -174,9 +174,9 @@ target_ulong helper_sret(CPURISCVState *env, target_ulong cpu_pc_deb) riscv_cpu_set_mode(env, prev_priv); #ifdef TARGET_CHERI - cheri_update_pcc_for_exc_return(&env->PCC, &env->SEPCC, retpc); + cheri_update_pcc_for_exc_return(&env->pcc, &env->sepcc, retpc); /* TODO(am2419): do we log PCC as a changed register? */ - qemu_log_instr_dbg_cap(env, "PCC", &env->PCC); + qemu_log_instr_dbg_cap(env, "PCC", &env->pcc); #endif return retpc; } @@ -193,7 +193,7 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) } #endif - target_ulong retpc = GET_SPECIAL_REG_ADDR(env, mepc, MEPCC); + target_ulong retpc = GET_SPECIAL_REG_ADDR(env, mepc, mepcc); // We have to clear the low bit of the address since that is defined as zero // in the privileged spec. The cheri_update_pcc_for_exc_return() check below // will de-tag pcc if this would result changing the address for sealed caps. @@ -235,9 +235,9 @@ target_ulong helper_mret(CPURISCVState *env, target_ulong cpu_pc_deb) #endif #ifdef TARGET_CHERI - cheri_update_pcc_for_exc_return(&env->PCC, &env->MEPCC, retpc); + cheri_update_pcc_for_exc_return(&env->pcc, &env->mepcc, retpc); /* TODO(am2419): do we log PCC as a changed register? */ - qemu_log_instr_dbg_cap(env, "PCC", &env->PCC); + qemu_log_instr_dbg_cap(env, "PCC", &env->pcc); #endif return retpc; } diff --git a/target/riscv/op_helper_cheri.c b/target/riscv/op_helper_cheri.c index a1ed682746..4343437af5 100644 --- a/target/riscv/op_helper_cheri.c +++ b/target/riscv/op_helper_cheri.c @@ -116,28 +116,28 @@ struct SCRInfo { static inline cap_register_t *get_scr(CPUArchState *env, uint32_t index) { switch (index) { - case CheriSCR_PCC: return &env->PCC; - case CheriSCR_DDC: return &env->DDC; - - case CheriSCR_UTCC: return &env->UTCC; - case CheriSCR_UTDC: return &env->UTDC; - case CheriSCR_UScratchC: return &env->UScratchC; - case CheriSCR_UEPCC: return &env->UEPCC; - - case CheriSCR_STCC: return &env->STCC; - case CheriSCR_STDC: return &env->STDC; - case CheriSCR_SScratchC: return &env->SScratchC; - case CheriSCR_SEPCC: return &env->SEPCC; - - case CheriSCR_MTCC: return &env->MTCC; - case CheriSCR_MTDC: return &env->MTDC; - case CheriSCR_MScratchC: return &env->MScratchC; - case CheriSCR_MEPCC: return &env->MEPCC; - - case CheriSCR_BSTCC: return &env->VSTCC; - case CheriSCR_BSTDC: return &env->VSTDC; - case CheriSCR_BSScratchC: return &env->VSScratchC; - case CheriSCR_BSEPCC: return &env->VSEPCC; + case CheriSCR_PCC: return &env->pcc; + case CheriSCR_DDC: return &env->ddc; + + case CheriSCR_UTCC: return &env->utcc; + case CheriSCR_UTDC: return &env->utdc; + case CheriSCR_UScratchC: return &env->uscratchc; + case CheriSCR_UEPCC: return &env->uepcc; + + case CheriSCR_STCC: return &env->stcc; + case CheriSCR_STDC: return &env->stdc; + case CheriSCR_SScratchC: return &env->sscratchc; + case CheriSCR_SEPCC: return &env->sepcc; + + case CheriSCR_MTCC: return &env->mtcc; + case CheriSCR_MTDC: return &env->mtdc; + case CheriSCR_MScratchC: return &env->mscratchc; + case CheriSCR_MEPCC: return &env->mepcc; + + case CheriSCR_BSTCC: return &env->vstcc; + case CheriSCR_BSTDC: return &env->vstdc; + case CheriSCR_BSScratchC: return &env->vsscratchc; + case CheriSCR_BSEPCC: return &env->vsepcc; default: assert(false && "Should have raised an invalid inst trap!"); } } @@ -155,7 +155,7 @@ void HELPER(cspecialrw)(CPUArchState *env, uint32_t cd, uint32_t cs, uint32_t index) { uintptr_t _host_return_address = GETPC(); - // Ensure that env->PCC.cursor is correct: + // Ensure that env->pcc.cursor is correct: cpu_restore_state(env_cpu(env), _host_return_address, false); assert(index <= 31 && "Bug in translator?"); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 3322893781..d7065bf1c0 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1104,10 +1104,10 @@ void riscv_translate_init(void) #ifdef TARGET_CHERI cpu_pc = tcg_global_mem_new(cpu_env, - offsetof(CPURISCVState, PCC._cr_cursor), "pc"); + offsetof(CPURISCVState, pcc._cr_cursor), "pc"); /// XXXAR: We currently interpose using DDC.cursor and not DDC.base! ddc_interposition = tcg_global_mem_new( - cpu_env, offsetof(CPURISCVState, DDC._cr_cursor), "ddc_interpose"); + cpu_env, offsetof(CPURISCVState, ddc._cr_cursor), "ddc_interpose"); #else cpu_pc = tcg_global_mem_new(cpu_env, offsetof(CPURISCVState, pc), "pc"); #endif From 0585ad6d23fea70b46b22a24e033a31b00ecfcb4 Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 3 Sep 2024 14:08:22 -0400 Subject: [PATCH 3/4] riscv: Rename get_csr to riscv_get_csr and move to cpu.h --- target/riscv/cpu.h | 31 +++++++++++++++++++++++++++++++ target/riscv/op_helper_cheri.c | 34 +++------------------------------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 1f790b0a49..8fb3be1613 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -827,6 +827,37 @@ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops); void riscv_set_csr_ops(int csrno, riscv_csr_operations *ops); +#ifdef TARGET_CHERI +static inline cap_register_t *riscv_get_scr(CPUArchState *env, uint32_t index) +{ + switch (index) { + case CheriSCR_PCC: return &env->pcc; + case CheriSCR_DDC: return &env->ddc; + + case CheriSCR_UTCC: return &env->utcc; + case CheriSCR_UTDC: return &env->utdc; + case CheriSCR_UScratchC: return &env->uscratchc; + case CheriSCR_UEPCC: return &env->uepcc; + + case CheriSCR_STCC: return &env->stcc; + case CheriSCR_STDC: return &env->stdc; + case CheriSCR_SScratchC: return &env->sscratchc; + case CheriSCR_SEPCC: return &env->sepcc; + + case CheriSCR_MTCC: return &env->mtcc; + case CheriSCR_MTDC: return &env->mtdc; + case CheriSCR_MScratchC: return &env->mscratchc; + case CheriSCR_MEPCC: return &env->mepcc; + + case CheriSCR_BSTCC: return &env->vstcc; + case CheriSCR_BSTDC: return &env->vstdc; + case CheriSCR_BSScratchC: return &env->vsscratchc; + case CheriSCR_BSEPCC: return &env->vsepcc; + default: assert(false && "Should have raised an invalid inst trap!"); + } +} +#endif + void riscv_cpu_register_gdb_regs_for_features(CPUState *cs); #endif /* RISCV_CPU_H */ diff --git a/target/riscv/op_helper_cheri.c b/target/riscv/op_helper_cheri.c index 4343437af5..c00816793b 100644 --- a/target/riscv/op_helper_cheri.c +++ b/target/riscv/op_helper_cheri.c @@ -113,40 +113,12 @@ struct SCRInfo { [CheriSCR_BSEPCC] = {.r = true, .w = true, .access = H_ASR, .name= "BSTCC"}, }; -static inline cap_register_t *get_scr(CPUArchState *env, uint32_t index) -{ - switch (index) { - case CheriSCR_PCC: return &env->pcc; - case CheriSCR_DDC: return &env->ddc; - - case CheriSCR_UTCC: return &env->utcc; - case CheriSCR_UTDC: return &env->utdc; - case CheriSCR_UScratchC: return &env->uscratchc; - case CheriSCR_UEPCC: return &env->uepcc; - - case CheriSCR_STCC: return &env->stcc; - case CheriSCR_STDC: return &env->stdc; - case CheriSCR_SScratchC: return &env->sscratchc; - case CheriSCR_SEPCC: return &env->sepcc; - - case CheriSCR_MTCC: return &env->mtcc; - case CheriSCR_MTDC: return &env->mtdc; - case CheriSCR_MScratchC: return &env->mscratchc; - case CheriSCR_MEPCC: return &env->mepcc; - - case CheriSCR_BSTCC: return &env->vstcc; - case CheriSCR_BSTDC: return &env->vstdc; - case CheriSCR_BSScratchC: return &env->vsscratchc; - case CheriSCR_BSEPCC: return &env->vsepcc; - default: assert(false && "Should have raised an invalid inst trap!"); - } -} - #ifdef CONFIG_TCG_LOG_INSTR void riscv_log_instr_scr_changed(CPURISCVState *env, int scrno) { if (qemu_log_instr_enabled(env)) { - qemu_log_instr_cap(env, scr_info[scrno].name, get_scr(env, scrno)); + qemu_log_instr_cap(env, scr_info[scrno].name, + riscv_get_scr(env, scrno)); } } #endif @@ -171,7 +143,7 @@ void HELPER(cspecialrw)(CPUArchState *env, uint32_t cd, uint32_t cs, if (scr_min_priv(mode) > env->priv) { raise_cheri_exception(env, CapEx_AccessSystemRegsViolation, 32 + index); } - cap_register_t *scr = get_scr(env, index); + cap_register_t *scr = riscv_get_scr(env, index); // Make a copy of the write value in case cd == cs cap_register_t new_val = *get_readonly_capreg(env, cs); if (cd != 0) { From a164216f1739ab6439b63c1b1a63783559582d1f Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 3 Sep 2024 11:46:47 -0400 Subject: [PATCH 4/4] gdb: Expose CHERI SCRs via the GDB stub This does not expose PCC and DDC in the new SCRs register group since those are already in the general purpose CHERI group. --- target/riscv/cpu.c | 5 +++ target/riscv/cpu.h | 3 ++ target/riscv/gdbstub.c | 73 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0eb49f00c9..6987fb16ea 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -999,6 +999,11 @@ static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname) if (strcmp(xmlname, "riscv-csr.xml") == 0) { return cpu->dyn_csr_xml; } +#ifdef TARGET_CHERI + if (strcmp(xmlname, "riscv-scr.xml") == 0) { + return cpu->dyn_scr_xml; + } +#endif return NULL; } diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 8fb3be1613..fc2db7c164 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -410,6 +410,9 @@ struct RISCVCPU { CPURISCVState env; char *dyn_csr_xml; +#ifdef TARGET_CHERI + char *dyn_scr_xml; +#endif /* Configuration Settings */ struct { diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c index fd100980fd..924b1b9a97 100644 --- a/target/riscv/gdbstub.c +++ b/target/riscv/gdbstub.c @@ -228,6 +228,74 @@ static int riscv_gen_dynamic_csr_xml(CPUState *cs, int base_reg) return CSR_TABLE_SIZE; } +#if defined(TARGET_CHERI) +static struct SCR { + int index; + const char *name; + bool code; +} scrs[] = { + { .index = CheriSCR_UTCC, .name = "utcc", .code = true }, + { .index = CheriSCR_UTDC, .name = "utdc"}, + { .index = CheriSCR_UScratchC, .name = "uscratchc"}, + { .index = CheriSCR_UEPCC, .name = "uepcc", .code = true }, + + { .index = CheriSCR_STCC, .name = "stcc", .code = true }, + { .index = CheriSCR_STDC, .name = "stdc"}, + { .index = CheriSCR_SScratchC, .name = "sscratchc"}, + { .index = CheriSCR_SEPCC, .name = "sepcc", .code = true }, + + { .index = CheriSCR_MTCC, .name = "mtcc", .code = true }, + { .index = CheriSCR_MTDC, .name = "mtdc"}, + { .index = CheriSCR_MScratchC, .name = "mscratchc"}, + { .index = CheriSCR_MEPCC, .name = "mepcc", .code = true }, +}; + +static int riscv_gdb_get_scr(CPURISCVState *env, GByteArray *buf, int n) +{ + if (n < ARRAY_SIZE(scrs)) { + cap_register_t *scr = riscv_get_scr(env, scrs[n].index); + return gdb_get_capreg(buf, scr); + } + return 0; +} + +static int riscv_gdb_set_scr(CPURISCVState *env, uint8_t *mem_buf, int n) +{ + /* All CHERI registers are read-only currently. */ + if (n < ARRAY_SIZE(scrs)) { + return CHERI_CAP_SIZE + 1; + } + return 0; +} + +static int riscv_gen_dynamic_scr_xml(CPUState *cs, int base_reg) +{ + RISCVCPU *cpu = RISCV_CPU(cs); + CPURISCVState *env = &cpu->env; + GString *s = g_string_new(NULL); + int bitsize = riscv_cpu_is_32bit(env) ? 64 : 128; + int i; + + g_string_printf(s, ""); + g_string_append_printf(s, ""); + g_string_append_printf(s, ""); + + for (i = 0; i < ARRAY_SIZE(scrs); i++) { + g_string_append_printf(s, "", base_reg + i); + } + + g_string_append_printf(s, ""); + + cpu->dyn_scr_xml = g_string_free(s, false); + return ARRAY_SIZE(scrs); +} +#endif + void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); @@ -261,4 +329,9 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs) gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr, riscv_gen_dynamic_csr_xml(cs, cs->gdb_num_regs), "riscv-csr.xml", 0); +#if defined(TARGET_CHERI) + gdb_register_coprocessor(cs, riscv_gdb_get_scr, riscv_gdb_set_scr, + riscv_gen_dynamic_scr_xml(cs, cs->gdb_num_regs), + "riscv-scr.xml", 0); +#endif }