Implement the hypervisor context (hcontext) register described in "The RISC-V Debug Specification" Version 1.0. The hcontext CSR is accessible from H and M mode, gated by the Smstateen HSCONTXT bit. Writes are masked to the width mandated by the RV32/RV64 xlen.
Signed-off-by: Arseniy Semenov <[email protected]> --- This series adds emulation support for the hypervisor context (hcontext) register, as specified in "The RISC-V Debug Specification" Version 1.0. The hcontext CSR (0x6a8) is a read/write register accessible from H and M mode, whose value is derived from the mcontext register. Accesses are gated behind the Smstateen HSCONTXT enable bit and writes are masked to the xlen-dependent width defined by the spec. No behaviour change occurs when the H extension is not enabled. --- target/riscv/cpu_bits.h | 1 + target/riscv/tcg/csr.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 3579789a1f..bfa10afca8 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -456,6 +456,7 @@ #define CSR_MNSTATUS 0x744 /* Debug/Trace Registers (shared with Debug Mode) */ +#define CSR_HCONTEXT 0x6a8 #define CSR_TSELECT 0x7a0 #define CSR_TDATA1 0x7a1 #define CSR_TDATA2 0x7a2 diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index 063590f56a..db1c8e58f4 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -814,6 +814,16 @@ static RISCVException debug(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } +static RISCVException hmode_debug(CPURISCVState *env, int csrno) +{ + if (riscv_has_ext(env, RVH) && + (riscv_cpu_cfg(env)->debug || riscv_cpu_cfg(env)->ext_sdtrig)) { + return RISCV_EXCP_NONE; + } + + return RISCV_EXCP_ILLEGAL_INST; +} + static RISCVException rnmi(CPURISCVState *env, int csrno) { RISCVCPU *cpu = env_archcpu(env); @@ -5703,6 +5713,40 @@ static RISCVException write_mcontext(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static RISCVException read_hcontext(CPURISCVState *env, int csrno, + target_ulong *val) +{ + RISCVException ret; + + ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSCONTXT); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + *val = env->mcontext; + + return RISCV_EXCP_NONE; +} + +static RISCVException write_hcontext(CPURISCVState *env, int csrno, + target_ulong val, uintptr_t ra) +{ + RISCVException ret; + + ret = smstateen_acc_ok(env, 0, SMSTATEEN0_HSCONTXT); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false; + + target_ulong mask = rv32 ? MCONTEXT32_HCONTEXT : MCONTEXT64_HCONTEXT; + + env->mcontext = val & mask; + + return RISCV_EXCP_NONE; +} + static RISCVException read_mnscratch(CPURISCVState *env, int csrno, target_ulong *val) { @@ -6620,6 +6664,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_TDATA3] = { "tdata3", debug, read_tdata, write_tdata }, [CSR_TINFO] = { "tinfo", debug, read_tinfo, write_ignore }, [CSR_MCONTEXT] = { "mcontext", debug, read_mcontext, write_mcontext }, + [CSR_HCONTEXT] = { "hcontext", hmode_debug, + read_hcontext, write_hcontext }, #if !defined(CONFIG_USER_ONLY) [CSR_DCSR] = { "dcsr", sdext, read_dcsr, write_dcsr }, [CSR_DPC] = { "dpc", sdext, read_dpc, write_dpc }, --- base-commit: a19f59a72d96056d9a8f48cf6c77f5787491e414 change-id: 20261019-hcontext-e8e8f54989a4 Best regards, -- Arseniy Semenov <[email protected]>
