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