On 2026/8/26 下午6:30, SignKirigami wrote:
Add LVZ host and guest CSR access metadata to the existing CSR table. Keep
one shared register description and calculate the host or guest bank
offset at translation time instead of duplicating CSRInfo entries.
Mark guest read-only, sensitive and unavailable CSRs for later LVZ
instruction translation.
Signed-off-by: SignKirigami <[email protected]>
Signed-off-by: Hengyu Yu <[email protected]>
---
target/loongarch/cpu.c | 3 +-
target/loongarch/csr.c | 108 +++++++++---------
target/loongarch/csr.h | 2 +
.../tcg/insn_trans/trans_extra.c.inc | 2 +-
.../tcg/insn_trans/trans_privileged.c.inc | 6 +-
5 files changed, 65 insertions(+), 56 deletions(-)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 2f7692dc93..0f6a211949 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -783,7 +783,8 @@ 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 + get_csr_offset(csr_info,
+ LOONGARCH_VM_LEVEL_HOST);
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..fa018a4582 100644
--- a/target/loongarch/csr.c
+++ b/target/loongarch/csr.c
@@ -13,15 +13,16 @@
.flags = FL, .readfn = RD, .writefn = WR \
}
-#define CSR_OFF_ARRAY(NAME, N) \
+#define CSR_OFF_ARRAY_FLAGS(NAME, N, FL) \
[LOONGARCH_CSR_##NAME(N)] = { \
.name = (stringify(NAME##N)), \
.offset = CSR_OFFSET(CSR_##NAME[N]), \
- .flags = CSRFL_BASIC, .readfn = NULL, .writefn = NULL \
+ .flags = FL \
}
#define CSR_OFF_FLAGS(NAME, FL) CSR_OFF_FUNCS(NAME, FL, NULL, NULL)
#define CSR_OFF(NAME) CSR_OFF_FLAGS(NAME, CSRFL_BASIC)
+#define CSR_OFF_ARRAY(NAME, N) CSR_OFF_ARRAY_FLAGS(NAME, N, CSRFL_BASIC)
static CSRInfo csr_info[] = {
CSR_OFF_FLAGS(CRMD, CSRFL_EXITTB),
@@ -35,6 +36,7 @@ static CSRInfo csr_info[] = {
CSR_OFF_FLAGS(BADI, CSRFL_READONLY),
CSR_OFF(EENTRY),
CSR_OFF(TLBIDX),
+ CSR_OFF_FLAGS(GTLBC, CSRFL_GSPR),
CSR_OFF(TLBEHI),
CSR_OFF(TLBELO0),
CSR_OFF(TLBELO1),
@@ -71,9 +73,13 @@ static CSRInfo csr_info[] = {
CSR_OFF_FLAGS(TVAL, CSRFL_READONLY | CSRFL_IO),
CSR_OFF(CNTC),
CSR_OFF_FLAGS(TICLR, CSRFL_IO),
Should previous CSR_OFF_FLAGS(GTLBC, CSRFL_GSPR) be moved to here? since
all these registers relative with LVZ.
+ CSR_OFF_FLAGS(GSTAT, CSRFL_GSPR),
+ CSR_OFF_FLAGS(GCFG, CSRFL_GSPR),
+ CSR_OFF_FLAGS(GINTC, CSRFL_IO | CSRFL_GSPR),
+ CSR_OFF_FLAGS(GCNTC, CSRFL_GSPR),
CSR_OFF(LLBCTL),
- CSR_OFF(IMPCTL1),
- CSR_OFF(IMPCTL2),
+ CSR_OFF_FLAGS(IMPCTL1, CSRFL_GSPR),
+ CSR_OFF_FLAGS(IMPCTL2, CSRFL_GSPR),
It change the old flags, previous its flag is CSRFL_BASIC, and not it is
replaced with CSRFL_GSPR. How about CSRFL_BASIC | CSRFL_GSPR and keep
old flag still on?
CSR_OFF(TLBRENTRY),
CSR_OFF(TLBRBADV),
CSR_OFF(TLBRERA),
@@ -82,57 +88,57 @@ static CSRInfo csr_info[] = {
CSR_OFF(TLBRELO1),
CSR_OFF(TLBREHI),
CSR_OFF(TLBRPRMD),
- CSR_OFF(MERRCTL),
- CSR_OFF(MERRINFO1),
- CSR_OFF(MERRINFO2),
- CSR_OFF(MERRENTRY),
- CSR_OFF(MERRERA),
- CSR_OFF(MERRSAVE),
- CSR_OFF(CTAG),
+ CSR_OFF_FLAGS(MERRCTL, CSRFL_GSPR),
+ CSR_OFF_FLAGS(MERRINFO1, CSRFL_GSPR),
+ CSR_OFF_FLAGS(MERRINFO2, CSRFL_GSPR),
+ CSR_OFF_FLAGS(MERRENTRY, CSRFL_GSPR),
+ CSR_OFF_FLAGS(MERRERA, CSRFL_GSPR),
+ CSR_OFF_FLAGS(MERRSAVE, CSRFL_GSPR),
+ CSR_OFF_FLAGS(CTAG, CSRFL_GSPR),
CSR_OFF_ARRAY(DMW, 0),
CSR_OFF_ARRAY(DMW, 1),
CSR_OFF_ARRAY(DMW, 2),
CSR_OFF_ARRAY(DMW, 3),
- CSR_OFF_ARRAY(PERFCTRL, 0),
- CSR_OFF_ARRAY(PERFCNTR, 0),
- CSR_OFF_ARRAY(PERFCTRL, 1),
- CSR_OFF_ARRAY(PERFCNTR, 1),
- CSR_OFF_ARRAY(PERFCTRL, 2),
- CSR_OFF_ARRAY(PERFCNTR, 2),
- CSR_OFF_ARRAY(PERFCTRL, 3),
- CSR_OFF_ARRAY(PERFCNTR, 3),
- CSR_OFF_ARRAY(PERFCTRL, 4),
- CSR_OFF_ARRAY(PERFCNTR, 4),
- CSR_OFF_ARRAY(PERFCTRL, 5),
- CSR_OFF_ARRAY(PERFCNTR, 5),
- CSR_OFF_ARRAY(PERFCTRL, 6),
- CSR_OFF_ARRAY(PERFCNTR, 6),
- CSR_OFF_ARRAY(PERFCTRL, 7),
- CSR_OFF_ARRAY(PERFCNTR, 7),
- CSR_OFF_ARRAY(PERFCTRL, 8),
- CSR_OFF_ARRAY(PERFCNTR, 8),
- CSR_OFF_ARRAY(PERFCTRL, 9),
- CSR_OFF_ARRAY(PERFCNTR, 9),
- CSR_OFF_ARRAY(PERFCTRL, 10),
- CSR_OFF_ARRAY(PERFCNTR, 10),
- CSR_OFF_ARRAY(PERFCTRL, 11),
- CSR_OFF_ARRAY(PERFCNTR, 11),
- CSR_OFF_ARRAY(PERFCTRL, 12),
- CSR_OFF_ARRAY(PERFCNTR, 12),
- CSR_OFF_ARRAY(PERFCTRL, 13),
- CSR_OFF_ARRAY(PERFCNTR, 13),
- CSR_OFF_ARRAY(PERFCTRL, 14),
- CSR_OFF_ARRAY(PERFCNTR, 14),
- CSR_OFF_ARRAY(PERFCTRL, 15),
- CSR_OFF_ARRAY(PERFCNTR, 15),
- CSR_OFF(DBG),
- CSR_OFF(DERA),
- CSR_OFF(DSAVE),
- CSR_OFF_ARRAY(MSGIS, 0),
- CSR_OFF_ARRAY(MSGIS, 1),
- CSR_OFF_ARRAY(MSGIS, 2),
- CSR_OFF_ARRAY(MSGIS, 3),
- CSR_OFF(MSGIR),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 0, CSRFL_GUEST_INVALID),
what is different between flag CSRFL_GSPR and CSRFL_GUEST_INVALID?
With CSR register access instruction, on host value zero is return if it
is not implemented. On guest mode, I think that there should be GSPR
exception and trap to host and let hypervisor to handle this if it is
not implemented. There is no much meaning to return zero and does not
trap to host.
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 0, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 1, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 1, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 2, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 2, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 3, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 3, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 4, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 4, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 5, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 5, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 6, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 6, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 7, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 7, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 8, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 8, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 9, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 9, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 10, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 10, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 11, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 11, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 12, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 12, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 13, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 13, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 14, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 14, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCTRL, 15, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(PERFCNTR, 15, CSRFL_GUEST_INVALID),
+ CSR_OFF_FLAGS(DBG, CSRFL_GSPR),
+ CSR_OFF_FLAGS(DERA, CSRFL_GSPR),
+ CSR_OFF_FLAGS(DSAVE, CSRFL_GSPR),
+ CSR_OFF_ARRAY_FLAGS(MSGIS, 0, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(MSGIS, 1, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(MSGIS, 2, CSRFL_GUEST_INVALID),
+ CSR_OFF_ARRAY_FLAGS(MSGIS, 3, CSRFL_GUEST_INVALID),
+ CSR_OFF_FLAGS(MSGIR, CSRFL_GUEST_INVALID),
};
CSRInfo *get_csr(unsigned int csr_num)
diff --git a/target/loongarch/csr.h b/target/loongarch/csr.h
index c2b6b882bc..647695e248 100644
--- a/target/loongarch/csr.h
+++ b/target/loongarch/csr.h
@@ -20,6 +20,8 @@ enum {
CSRFL_IO = (1 << 2),
CSRFL_UNUSED = (1 << 3),
CSRFL_BASIC = (1 << 4),
+ CSRFL_GSPR = (1 << 5),
+ CSRFL_GUEST_INVALID = (1 << 6),
};
typedef struct {
diff --git a/target/loongarch/tcg/insn_trans/trans_extra.c.inc
b/target/loongarch/tcg/insn_trans/trans_extra.c.inc
index 655dce329e..e69384497f 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 = CPU_CSR_OFFSET(CSR_TID, LOONGARCH_VM_LEVEL_HOST);
This should be another small patch.
Regards
Bibo Mao
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..bcfc977990 100644
--- a/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
+++ b/target/loongarch/tcg/insn_trans/trans_privileged.c.inc
@@ -122,7 +122,7 @@ static bool trans_csrrd(DisasContext *ctx, arg_csrrd *a)
if (readfn) {
readfn(dest, tcg_env);
} else {
- offset = get_csr_offset(csr, 0);
+ offset = get_csr_offset(csr, LOONGARCH_VM_LEVEL_HOST);
tcg_gen_ld_tl(dest, tcg_env, offset);
}
}
@@ -157,7 +157,7 @@ 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);
+ offset = get_csr_offset(csr, LOONGARCH_VM_LEVEL_HOST);
tcg_gen_ld_tl(dest, tcg_env, offset);
tcg_gen_st_tl(src1, tcg_env, offset);
}
@@ -196,7 +196,7 @@ static bool trans_csrxchg(DisasContext *ctx, arg_csrxchg *a)
newv = tcg_temp_new();
temp = tcg_temp_new();
- offset = get_csr_offset(csr, 0);
+ offset = get_csr_offset(csr, LOONGARCH_VM_LEVEL_HOST);
tcg_gen_ld_tl(oldv, tcg_env, offset);
tcg_gen_and_tl(newv, src1, mask);
tcg_gen_andc_tl(temp, oldv, mask);