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]>


Reply via email to