On 2026/9/16 下午4:50, SignKirigami wrote:
On 2026年8月31日星期一 中国标准时间 10:56:26,Bibo Mao wrote:

On 2026/8/26 下午6:30, SignKirigami wrote:
Add host and guest system-state banks, LVZ exception and MMU indices,
CPU and translation state, and helpers for selecting a VM-level CSR bank.

Read host ERA and BADV explicitly when generating ELF core notes so the
result does not depend on the currently selected guest state.

Signed-off-by: SignKirigami <[email protected]>
Signed-off-by: Hengyu Yu <[email protected]>
---
   target/loongarch/arch_dump.c |  6 ++--
   target/loongarch/cpu.c       |  4 +--
   target/loongarch/cpu.h       | 64 ++++++++++++++++++++++++++++++++++--
   target/loongarch/translate.h |  2 ++
   4 files changed, 68 insertions(+), 8 deletions(-)

diff --git a/target/loongarch/arch_dump.c b/target/loongarch/arch_dump.c
index 9d84faef96..711b23257b 100644
--- a/target/loongarch/arch_dump.c
+++ b/target/loongarch/arch_dump.c
@@ -116,7 +116,7 @@ int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, 
CPUState *cs,
   {
       struct loongarch_note note;
       CPULoongArchState *env = &LOONGARCH_CPU(cs)->env;
-    CPUSysState *sys = env_sys(env);
+    CPUSysState *host = get_sys(env, LOONGARCH_VM_LEVEL_HOST);
       int ret, i;
yes, it need similar modification with loongarch_cpu_write_elf64_note().
can we keep local variable sys unchanged so that the change is smaller?
I think it may be more clear if using host for host mode, guest for guest mode, 
and sys
for current mode in use.
If you insist on this, please use two patches:
1. One patch is to replace env_sys(env) with get_sys(env, LOONGARCH_VM_LEVEL_HOST), and variable name sys keep unchanged; 2. The other patch is to change variable name sys with host, and note that there is no function change.

If so, it is easy to review.

Regards
Bibo Mao

Regards
SignKirigami

BTW I do not know which name is better between LOONGARCH_VM_LEVEL_HOST
and LOONGARCH_VM_LEVEL0. Such as in KVM mode, it is to dump CSR
resisters of guest VM; however in TCG mode, it is for host.
loongarch_note_init(&note, s, "CORE", 5, NT_PRSTATUS,
@@ -127,8 +127,8 @@ int loongarch_cpu_write_elf64_note(WriteCoreDumpFunction f, 
CPUState *cs,
       for (i = 0; i < 32; ++i) {
           note.prstatus.pr_reg.gpr[i] = cpu_to_dump64(s, env->gpr[i]);
       }
-    note.prstatus.pr_reg.csr_era  = cpu_to_dump64(s, sys->CSR_ERA);
-    note.prstatus.pr_reg.csr_badv = cpu_to_dump64(s, sys->CSR_BADV);
+    note.prstatus.pr_reg.csr_era  = cpu_to_dump64(s, host->CSR_ERA);
+    note.prstatus.pr_reg.csr_badv = cpu_to_dump64(s, host->CSR_BADV);
       ret = f(&note, LOONGARCH_PRSTATUS_NOTE_SIZE, s);
       if (ret < 0) {
           return -1;
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fb03424ffa..2f7692dc93 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -282,7 +282,7 @@ static void loongarch_la464_initfn(Object *obj)
       uint32_t data = 0, field;
       int i;
- set_sys_state(env, &env->sys_states[0]);
+    set_sys(env, LOONGARCH_VM_LEVEL_HOST);
       for (i = 0; i < 21; i++) {
           env->cpucfg[i] = 0x0;
       }
@@ -412,7 +412,7 @@ static void loongarch_la132_initfn(Object *obj)
       uint32_t data = 0;
       int i;
- set_sys_state(env, &env->sys_states[0]);
+    set_sys(env, LOONGARCH_VM_LEVEL_HOST);
       for (i = 0; i < 21; i++) {
           env->cpucfg[i] = 0x0;
       }
I still think that it need split to smaller version, such as
    1. get_sys()/set_sys() and its user.
    2. mmu_idx change for new added LVZ
    3. others

diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ad30c73167..be982b7695 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -20,6 +20,8 @@
   #include "cpu-csr.h"
   #include "cpu-qom.h"
+#define CPU_INTERRUPT_GUEST CPU_INTERRUPT_TGT_EXT_0
+
   #define FCSR0_M1    0x1f         /* FCSR1 mask, Enables */
   #define FCSR0_M2    0x1f1f0000   /* FCSR2 mask, Cause and Flags */
   #define FCSR0_M3    0x300        /* FCSR3 mask, Round Mode */
@@ -93,6 +95,10 @@ FIELD(FCSR0, CAUSE, 24, 5)
   #define  EXCCODE_WPEM                EXCODE(19, 1)
   #define  EXCCODE_BTD                 EXCODE(20, 0)
   #define  EXCCODE_BTE                 EXCODE(21, 0)
+#define  EXCCODE_GSPR                EXCODE(22, 0)
+#define  EXCCODE_HVC                 EXCODE(23, 0)
+#define  EXCCODE_GCSC                EXCODE(24, 0)
+#define  EXCCODE_GCHC                EXCODE(25, 0)
The exception for LVZ is added however not used, it had better be added
in patch where it is actually used.
   #define  EXCCODE_DBP                 EXCODE(26, 0) /* Reserved subcode used 
for debug */
/* cpucfg[0] bits */
@@ -255,6 +261,7 @@ FIELD(TLB_MISC, E, 0, 1)
   FIELD(TLB_MISC, ASID, 1, 10)
   FIELD(TLB_MISC, VPPN, 13, 35)
   FIELD(TLB_MISC, PS, 48, 6)
+FIELD(TLB_MISC, GID, 54, 8)
/*Msg interrupt registers */
   #define N_MSGIS                4
@@ -314,6 +321,10 @@ typedef struct  LoongArchBT {
       uint32_t ftop;
   } lbt_t;
+#define LOONGARCH_VM_LEVEL_HOST 0
+#define LOONGARCH_VM_LEVEL_GUEST     1
+#define LOONGARCH_VM_LEVELS          2
+
   #define CPU_VENDOR_LOONGSON   "Loongson"
   #define CPU_MODEL_3A5000      "3A5000"
   #define CPU_MODEL_1C101       "1C101"
@@ -375,10 +386,18 @@ typedef struct CPUSysState {
       uint64_t CSR_DBG;
       uint64_t CSR_DERA;
       uint64_t CSR_DSAVE;
+    uint64_t CSR_GSTAT;
+    uint64_t CSR_GCFG;
+    uint64_t CSR_GINTC;
+    uint64_t CSR_GCNTC;
+    uint64_t CSR_GTLBC;
I think this patch can move to patch 1.

       /* Msg interrupt registers */
       uint64_t CSR_MSGIS[N_MSGIS];
       uint64_t CSR_MSGIR;
       uint64_t CSR_MSGIE;
+#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
+    LoongArchTLB tlb[LOONGARCH_TLB_MAX];
+#endif
It can be deleted in this patch.

   } CPUSysState;
typedef struct CPUArchState {
@@ -394,7 +413,7 @@ typedef struct CPUArchState {
       uint32_t pv_features;
       uint64_t vendor_id;
       uint64_t cpu_id;
-    CPUSysState sys_states[1];
+    CPUSysState sys_states[LOONGARCH_VM_LEVELS];
struct {
           uint64_t guest_addr;
@@ -419,6 +438,7 @@ typedef struct CPUArchState {
       uint32_t mp_state;
   #endif
       CPUSysState *sys_state;
+    bool vm_exit;
   } CPULoongArchState;
typedef struct LoongArchCPUTopo {
@@ -438,8 +458,10 @@ struct ArchCPU {
CPULoongArchState env;
       QEMUTimer timer;
+    QEMUTimer guest_timer;
       uint32_t  phy_id;
       OnOffAuto lbt;
+    OnOffAuto lvz;
       OnOffAuto pmu;
       OnOffAuto ptw;
       OnOffAuto lsx;
@@ -484,15 +506,44 @@ struct LoongArchCPUClass {
   #define MMU_KERNEL_IDX   MMU_PLV_KERNEL
   #define MMU_USER_IDX     MMU_PLV_USER
   #define MMU_DA_IDX       4
+#define MMU_GUEST_IDX    5
+#define MMU_GUEST_DA_IDX 9
+
+static inline bool is_guest_mmu_idx(int mmu_idx)
+{
+    return mmu_idx >= MMU_GUEST_IDX;
+}
+
+static inline int mmu_idx_to_plv(int mmu_idx)
+{
+    if (mmu_idx == MMU_DA_IDX || mmu_idx == MMU_GUEST_DA_IDX) {
+        return 0;
+    }
+    if (is_guest_mmu_idx(mmu_idx)) {
+        return mmu_idx - MMU_GUEST_IDX;
+    }
+    return mmu_idx;
+}
static inline CPUSysState *env_sys(CPULoongArchState *env)
   {
       return env->sys_state;
   }
-static inline void set_sys_state(CPULoongArchState *env, CPUSysState *sys)
+static inline CPUSysState *get_sys(CPULoongArchState *env, int vm_level)
+{
+    return &env->sys_states[vm_level];
+}
+
+static inline void set_sys(CPULoongArchState *env, int vm_level)
   {
-    env->sys_state = sys;
+    env->sys_state = get_sys(env, vm_level);
+}
+
+static inline int env_vm_level(CPULoongArchState *env)
+{
+    return env_sys(env) == get_sys(env, LOONGARCH_VM_LEVEL_GUEST) ?
+           LOONGARCH_VM_LEVEL_GUEST : LOONGARCH_VM_LEVEL_HOST;
   }
static inline bool is_la64(CPULoongArchState *env)
@@ -530,6 +581,13 @@ static inline void set_pc(CPULoongArchState *env, uint64_t 
value)
   #define HW_FLAGS_CRMD_PG    R_CSR_CRMD_PG_MASK   /* 0x10 */
   #define HW_FLAGS_VA32       0x20
   #define HW_FLAGS_EUEN_ASXE  0x40
+#define HW_FLAGS_GUEST_MODE 0x80
+
+bool has_lvz_capability(CPULoongArchState *env);
+bool will_return_to_guest(CPULoongArchState *env);
+uint8_t get_gid(CPULoongArchState *env);
+uint8_t get_tgid(CPULoongArchState *env);
+void trigger_vm_exit(CPULoongArchState *env);
There is only function declaration, no function implementation and
called. I think it can be removed in this patch.

In general it requires that every single patch can pass to compile and work.

Regards
Bibo Mao
#define CPU_RESOLVING_TYPE TYPE_LOONGARCH_CPU diff --git a/target/loongarch/translate.h b/target/loongarch/translate.h
index 8aa8325dc6..257c3bbddd 100644
--- a/target/loongarch/translate.h
+++ b/target/loongarch/translate.h
@@ -24,6 +24,7 @@
   #define avail_FP(C)     (FIELD_EX32((C)->cpucfg2, CPUCFG2, FP))
   #define avail_FP_SP(C)  (FIELD_EX32((C)->cpucfg2, CPUCFG2, FP_SP))
   #define avail_FP_DP(C)  (FIELD_EX32((C)->cpucfg2, CPUCFG2, FP_DP))
+#define avail_LVZ(C)    (FIELD_EX32((C)->cpucfg2, CPUCFG2, LVZ))
   #define avail_LSPW(C)   (FIELD_EX32((C)->cpucfg2, CPUCFG2, LSPW))
   #define avail_LAM(C)    (FIELD_EX32((C)->cpucfg2, CPUCFG2, LAM))
   #define avail_LAM_BH(C) (FIELD_EX32((C)->cpucfg2, CPUCFG2, LAM_BH))
@@ -66,6 +67,7 @@ typedef struct DisasContext {
       TCGv zero;
       bool la64; /* LoongArch64 mode */
       bool va32; /* 32-bit virtual address */
+    bool guest_mode;
       uint32_t cpucfg1;
       uint32_t cpucfg2;
       uint32_t cpucfg3;









Reply via email to