On 2026/7/10 下午5:00, SignKirigami wrote:
Add the guest CSR lookup table and get_gcsr() helper, mark guest
read-only registers and guest sensitive privileged resources, and store
host and guest CSRInfo offsets relative to CPULoongArchState so CSR
access generation can select the host or guest table directly.

Signed-off-by: SignKirigami <[email protected]>
Signed-off-by: Hengyu Yu <[email protected]>
---
  target/loongarch/cpu.c                        |   2 +-
  target/loongarch/csr.c                        | 124 +++++++++++++++++-
  target/loongarch/csr.h                        |  12 +-
  .../tcg/insn_trans/trans_extra.c.inc          |   2 +-
  .../tcg/insn_trans/trans_privileged.c.inc     |  16 +--
  5 files changed, 133 insertions(+), 23 deletions(-)

diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fb03424ffa..492b17e136 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -783,7 +783,7 @@ static void loongarch_cpu_dump_csr(CPUState *cs, FILE *f)
              qemu_fprintf(f, " CSR%03d:", col);
          }
- addr = (void *)env + get_csr_offset(csr_info, 0);
+        addr = (void *)env + csr_info->offset;
          qemu_fprintf(f, " %s ", csr_info->name);
          len = strlen(csr_info->name);
          for (; len < 6; len++) {
diff --git a/target/loongarch/csr.c b/target/loongarch/csr.c
index 309b826ca9..ed9d25edf2 100644
--- a/target/loongarch/csr.c
+++ b/target/loongarch/csr.c
@@ -9,19 +9,34 @@
  #define CSR_OFF_FUNCS(NAME, FL, RD, WR)                    \
      [LOONGARCH_CSR_##NAME] = {                             \
          .name   = (stringify(NAME)),                       \
-        .offset = CSR_OFFSET(CSR_##NAME),                  \
+        .offset = CSR_OFFSET(CSR_##NAME, 0),               \
          .flags = FL, .readfn = RD, .writefn = WR           \
      }
#define CSR_OFF_ARRAY(NAME, N) \
      [LOONGARCH_CSR_##NAME(N)] = {                             \
          .name   = (stringify(NAME##N)),                       \
-        .offset = CSR_OFFSET(CSR_##NAME[N]),                  \
-        .flags = CSRFL_BASIC, .readfn = NULL, .writefn = NULL           \
+        .offset = CSR_OFFSET(CSR_##NAME[N], 0),               \
+        .flags = CSRFL_BASIC, .readfn = NULL, .writefn = NULL \
      }
#define CSR_OFF_FLAGS(NAME, FL) CSR_OFF_FUNCS(NAME, FL, NULL, NULL)
  #define CSR_OFF(NAME)             CSR_OFF_FLAGS(NAME, CSRFL_BASIC)
+#define GCSR_OFF_FUNCS(NAME, FL, RD, WR)                  \
+    [LOONGARCH_CSR_##NAME] = {                            \
+        .name   = (stringify(GCSR_##NAME)),               \
+        .offset = CSR_OFFSET(CSR_##NAME, 1),              \
+        .flags = FL, .readfn = RD, .writefn = WR          \
+    }
+#define GCSR_OFF_ARRAY(NAME, N)                               \
+    [LOONGARCH_CSR_##NAME(N)] = {                             \
+        .name   = (stringify(GCSR_##NAME##N)),                \
+        .offset = CSR_OFFSET(CSR_##NAME[N], 1),               \
+        .flags = CSRFL_BASIC, .readfn = NULL, .writefn = NULL \
+    }
+#define GCSR_OFF_FLAGS(NAME, FL) GCSR_OFF_FUNCS(NAME, FL, NULL, NULL)
+#define GCSR_OFF(NAME) GCSR_OFF_FLAGS(NAME, CSRFL_BASIC)
+#define GCSR_GSPR(NAME) GCSR_OFF_FLAGS(NAME, CSRFL_GSPR)
static CSRInfo csr_info[] = {
      CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
@@ -35,6 +50,8 @@ static CSRInfo csr_info[] = {
      CSR_OFF_FLAGS(BADI, CSRFL_READONLY),
      CSR_OFF(EENTRY),
      CSR_OFF(TLBIDX),
+    CSR_OFF(GTLBC),
+    CSR_OFF(TRGP),
      CSR_OFF(TLBEHI),
      CSR_OFF(TLBELO0),
      CSR_OFF(TLBELO1),
@@ -71,6 +88,10 @@ static CSRInfo csr_info[] = {
      CSR_OFF_FLAGS(TVAL, CSRFL_READONLY | CSRFL_IO),
      CSR_OFF(CNTC),
      CSR_OFF_FLAGS(TICLR, CSRFL_IO),
+    CSR_OFF(GSTAT),
+    CSR_OFF(GCFG),
+    CSR_OFF_FLAGS(GINTC, CSRFL_IO),
+    CSR_OFF(GCNTC),
      CSR_OFF(LLBCTL),
      CSR_OFF(IMPCTL1),
      CSR_OFF(IMPCTL2),
@@ -135,6 +156,87 @@ static CSRInfo csr_info[] = {
      CSR_OFF(MSGIR),
  };
+static CSRInfo gcsr_info[] = {
+    GCSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
+    GCSR_OFF(PRMD),
+    GCSR_OFF_FLAGS(EUEN, CSRFL_EXITTB),
+    GCSR_OFF_FLAGS(MISC, CSRFL_GUEST_READONLY),
+    GCSR_OFF(ECFG),
+    GCSR_OFF_FLAGS(ESTAT, CSRFL_EXITTB),
+    GCSR_OFF(ERA),
+    GCSR_OFF(BADV),
+    GCSR_OFF_FLAGS(BADI, CSRFL_GUEST_READONLY),
+    GCSR_OFF(EENTRY),
+    GCSR_OFF(TLBIDX),
+    GCSR_GSPR(GTLBC),
+    GCSR_GSPR(TRGP),
+    GCSR_OFF(TLBEHI),
+    GCSR_OFF(TLBELO0),
+    GCSR_OFF(TLBELO1),
+    GCSR_OFF_FLAGS(ASID, CSRFL_EXITTB),
+    GCSR_OFF(PGDL),
+    GCSR_OFF(PGDH),
+    GCSR_OFF_FLAGS(PGD, CSRFL_GUEST_READONLY),
+    GCSR_OFF(PWCL),
+    GCSR_OFF(PWCH),
+    GCSR_OFF(STLBPS),
+    GCSR_OFF(RVACFG),
+    GCSR_OFF_FLAGS(CPUID, CSRFL_GUEST_READONLY),
+    GCSR_OFF_FLAGS(PRCFG1, CSRFL_GUEST_READONLY),
+    GCSR_OFF_FLAGS(PRCFG2, CSRFL_GUEST_READONLY),
+    GCSR_OFF_FLAGS(PRCFG3, CSRFL_GUEST_READONLY),
+    GCSR_OFF_ARRAY(SAVE, 0),
+    GCSR_OFF_ARRAY(SAVE, 1),
+    GCSR_OFF_ARRAY(SAVE, 2),
+    GCSR_OFF_ARRAY(SAVE, 3),
+    GCSR_OFF_ARRAY(SAVE, 4),
+    GCSR_OFF_ARRAY(SAVE, 5),
+    GCSR_OFF_ARRAY(SAVE, 6),
+    GCSR_OFF_ARRAY(SAVE, 7),
+    GCSR_OFF_ARRAY(SAVE, 8),
+    GCSR_OFF_ARRAY(SAVE, 9),
+    GCSR_OFF_ARRAY(SAVE, 10),
+    GCSR_OFF_ARRAY(SAVE, 11),
+    GCSR_OFF_ARRAY(SAVE, 12),
+    GCSR_OFF_ARRAY(SAVE, 13),
+    GCSR_OFF_ARRAY(SAVE, 14),
+    GCSR_OFF_ARRAY(SAVE, 15),
+    GCSR_OFF(TID),
+    GCSR_OFF_FLAGS(TCFG, CSRFL_IO),
+    GCSR_OFF_FLAGS(TVAL, CSRFL_GUEST_READONLY | CSRFL_IO),
+    GCSR_OFF(CNTC),
+    GCSR_OFF_FLAGS(TICLR, CSRFL_IO),
+    GCSR_GSPR(GSTAT),
+    GCSR_GSPR(GCFG),
+    GCSR_GSPR(GINTC),
+    GCSR_GSPR(GCNTC),
+    GCSR_OFF(LLBCTL),
+    GCSR_GSPR(IMPCTL1),
+    GCSR_GSPR(IMPCTL2),
+    GCSR_OFF(TLBRENTRY),
+    GCSR_OFF(TLBRBADV),
+    GCSR_OFF(TLBRERA),
+    GCSR_OFF(TLBRSAVE),
+    GCSR_OFF(TLBRELO0),
+    GCSR_OFF(TLBRELO1),
+    GCSR_OFF(TLBREHI),
+    GCSR_OFF(TLBRPRMD),
+    GCSR_GSPR(MERRCTL),
+    GCSR_GSPR(MERRINFO1),
+    GCSR_GSPR(MERRINFO2),
+    GCSR_GSPR(MERRENTRY),
+    GCSR_GSPR(MERRERA),
+    GCSR_GSPR(MERRSAVE),
+    GCSR_GSPR(CTAG),
+    GCSR_OFF_ARRAY(DMW, 0),
+    GCSR_OFF_ARRAY(DMW, 1),
+    GCSR_OFF_ARRAY(DMW, 2),
+    GCSR_OFF_ARRAY(DMW, 3),
+    GCSR_GSPR(DBG),
+    GCSR_GSPR(DERA),
+    GCSR_GSPR(DSAVE),
+};
+
  CSRInfo *get_csr(unsigned int csr_num)
  {
      CSRInfo *csr;
@@ -151,6 +253,22 @@ CSRInfo *get_csr(unsigned int csr_num)
      return csr;
  }
+CSRInfo *get_gcsr(unsigned int csr_num)
+{
+    CSRInfo *csr;
+
+    if (csr_num >= ARRAY_SIZE(gcsr_info)) {
+        return NULL;
+    }
+
+    csr = &gcsr_info[csr_num];
+    if (csr->flags == 0) {
+        return NULL;
+    }
+
+    return csr;
+}
+
  bool set_csr_flag(unsigned int csr_num, int flag)
  {
      CSRInfo *csr;
diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h
index c2b6b882bc..c39230f30c 100644
--- a/target/loongarch/csr.h
+++ b/target/loongarch/csr.h
@@ -8,10 +8,9 @@
#include "cpu-csr.h" -#define CSR_OFFSET(id) offsetof(CPUSysState, id)
-#define CPU_CSR_OFFSET(id, vm_level)                                     \
+#define CSR_OFFSET(id, vm_level)                                     \
                      (offsetof(CPULoongArchState, sys_states[vm_level])   \
-                             + CSR_OFFSET(id))
+                    + offsetof(CPUSysState, id))
typedef void (*GenCSRFunc)(void);
  enum {
@@ -20,6 +19,8 @@ enum {
      CSRFL_IO       = (1 << 2),
      CSRFL_UNUSED   = (1 << 3),
      CSRFL_BASIC    = (1 << 4),
+    CSRFL_GUEST_READONLY = (1 << 5),
+    CSRFL_GSPR     = (1 << 6),
  };
typedef struct {
@@ -31,9 +32,6 @@ typedef struct {
  } CSRInfo;
CSRInfo *get_csr(unsigned int csr_num);
+CSRInfo *get_gcsr(unsigned int csr_num);
  bool set_csr_flag(unsigned int csr_num, int flag);
-static inline unsigned int get_csr_offset(const CSRInfo *csr, int vm_level)
-{
-    return csr->offset + offsetof(CPULoongArchState, sys_states[vm_level]);
-}
  #endif /* TARGET_LOONGARCH_CSR_H */
diff --git a/target/loongarch/tcg/insn_trans/trans_extra.c.inc 
b/target/loongarch/tcg/insn_trans/trans_extra.c.inc
index 655dce329e..5a404632f5 100644
--- a/target/loongarch/tcg/insn_trans/trans_extra.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_extra.c.inc
@@ -55,7 +55,7 @@ static bool gen_rdtime(DisasContext *ctx, arg_rr *a,
          tcg_gen_sextract_tl(dst1, dst1, high ? 32 : 0, 32);
      }
- offset = CPU_CSR_OFFSET(CSR_TID, 0);
+    offset = CSR_OFFSET(CSR_TID, 0);
      tcg_gen_ld_i64(dst2, tcg_env, offset);
return true;
diff --git a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc 
b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
index 6728ce5ec9..2094d182ac 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -106,7 +106,6 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a)
      TCGv dest;
      const CSRInfo *csr;
      GenCSRRead readfn;
-    tcg_target_long offset;
if (check_plv(ctx)) {
          return false;
@@ -122,8 +121,7 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a)
          if (readfn) {
              readfn(dest, tcg_env);
          } else {
-            offset = get_csr_offset(csr, 0);
-            tcg_gen_ld_tl(dest, tcg_env, offset);
+            tcg_gen_ld_tl(dest, tcg_env, csr->offset);
          }
how about something like this:
    offset = get_csr_offset(csr, ctx->guest_mode == true);

      }
      gen_set_gpr(a->rd, dest, EXT_NONE);
@@ -135,7 +133,6 @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a)
      TCGv dest, src1;
      const CSRInfo *csr;
      GenCSRWrite writefn;
-    tcg_target_long offset;
if (check_plv(ctx)) {
          return false;
@@ -157,9 +154,8 @@ static bool trans_csrwr(DisasContext *ctx, arg_csrwr *a)
          writefn(dest, tcg_env, src1);
      } else {
          dest = tcg_temp_new();
-        offset = get_csr_offset(csr, 0);
-        tcg_gen_ld_tl(dest, tcg_env, offset);
-        tcg_gen_st_tl(src1, tcg_env, offset);
+        tcg_gen_ld_tl(dest, tcg_env, csr->offset);
+        tcg_gen_st_tl(src1, tcg_env, csr->offset);
Ditto, offset = get_csr_offset(csr, ctx->guest_mode == true);
      }
      gen_set_gpr(a->rd, dest, EXT_NONE);
      return true;
@@ -170,7 +166,6 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
      TCGv src1, mask, oldv, newv, temp;
      const CSRInfo *csr;
      GenCSRWrite writefn;
-    tcg_target_long offset;
if (check_plv(ctx)) {
          return false;
@@ -196,8 +191,7 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
      newv = tcg_temp_new();
      temp = tcg_temp_new();
- offset = get_csr_offset(csr, 0);
Ditto, offset = get_csr_offset(csr, ctx->guest_mode == true);

Regards
Bibo Mao
-    tcg_gen_ld_tl(oldv, tcg_env, offset);
+    tcg_gen_ld_tl(oldv, tcg_env, csr->offset);
      tcg_gen_and_tl(newv, src1, mask);
      tcg_gen_andc_tl(temp, oldv, mask);
      tcg_gen_or_tl(newv, newv, temp);
@@ -206,7 +200,7 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
      if (writefn) {
          writefn(oldv, tcg_env, newv);
      } else {
-        tcg_gen_st_tl(newv, tcg_env, offset);
+        tcg_gen_st_tl(newv, tcg_env, csr->offset);
      }
      gen_set_gpr(a->rd, oldv, EXT_NONE);
      return true;



Reply via email to