Commit 6ee20a4c88 for qemu.org
commit 6ee20a4c88e10520b9e3eb09b2bc8cc73d42750b
Author: Xianglai Li <lixianglai@loongson.cn>
Date: Mon Sep 7 11:00:04 2026 +0800
target/loongarch: clear the registers when cpu is reset
Use virt-manager to start a virtual machine, and then use the following
command to manually trigger the crash of the virtual machine:
echo c > /proc/sysrq-trigger
After the VM is abnormal, the ESTAT register has a certain probability of
remaining interrupted. Then the VM is forced to restart and the VM is
suspended in the interrupt handling function during startup.
In order to clear the remaining interrupt information in the ESTAT
register, we performed this operation during the reset process, while also
checking and optimizing the status of other CSR registers.
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 84a130956d..18d73ebc1b 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -623,6 +623,13 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
lacc->parent_phases.hold(obj, type);
}
+ /*
+ * Workaround for edk2-stable202408, CSR PGD register is set only if
+ * its value is equal to zero for boot cpu, it causes reboot issue.
+ */
+ memset(env, 0, offsetof(CPULoongArchState, end_reset_fields));
+ memset(sys, 0, offsetof(CPUSysState, end_reset_fields));
+
#ifdef CONFIG_TCG
env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
@@ -637,47 +644,11 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
R_TLBENTRY_32_PPN_MASK;
}
#endif
- env->fcsr0 = 0x0;
- int n;
- /* Set csr registers value after reset, see the manual 6.4. */
- sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PLV, 0);
- sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, IE, 0);
sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1);
- sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, PG, 0);
- sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DATF, 0);
- sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DATM, 0);
-
- sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, FPE, 0);
- sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, SXE, 0);
- sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, ASXE, 0);
- sys->CSR_EUEN = FIELD_DP64(sys->CSR_EUEN, CSR_EUEN, BTE, 0);
-
- sys->CSR_MISC = 0;
-
- sys->CSR_ECFG = FIELD_DP64(sys->CSR_ECFG, CSR_ECFG, VS, 0);
- sys->CSR_ECFG = FIELD_DP64(sys->CSR_ECFG, CSR_ECFG, LIE, 0);
-
- sys->CSR_ESTAT = sys->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
- sys->CSR_RVACFG = FIELD_DP64(sys->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
sys->CSR_CPUID = cs->cpu_index;
- sys->CSR_TCFG = FIELD_DP64(sys->CSR_TCFG, CSR_TCFG, EN, 0);
- sys->CSR_LLBCTL = FIELD_DP64(sys->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
- sys->CSR_TLBRERA = FIELD_DP64(sys->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
- sys->CSR_MERRCTL = FIELD_DP64(sys->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
sys->CSR_TID = cs->cpu_index;
- /*
- * Workaround for edk2-stable202408, CSR PGD register is set only if
- * its value is equal to zero for boot cpu, it causes reboot issue.
- *
- * Here clear CSR registers relative with TLB.
- */
- sys->CSR_PGDH = 0;
- sys->CSR_PGDL = 0;
- sys->CSR_PWCH = 0;
- sys->CSR_EENTRY = 0;
- sys->CSR_TLBRENTRY = 0;
- sys->CSR_MERRENTRY = 0;
+
/* set CSR_PWCL.PTBASE and CSR_STLBPS.PS bits from CSR_PRCFG2 */
if (sys->CSR_PRCFG2 == 0) {
sys->CSR_PRCFG2 = 0x3fffff000;
@@ -685,18 +656,9 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
tlb_ps = ctz32(sys->CSR_PRCFG2);
sys->CSR_STLBPS = FIELD_DP64(sys->CSR_STLBPS, CSR_STLBPS, PS, tlb_ps);
sys->CSR_PWCL = FIELD_DP64(sys->CSR_PWCL, CSR_PWCL, PTBASE, tlb_ps);
- for (n = 0; n < 4; n++) {
- sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV0, 0);
- sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV1, 0);
- sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV2, 0);
- sys->CSR_DMW[n] = FIELD_DP64(sys->CSR_DMW[n], CSR_DMW, PLV3, 0);
- }
#ifndef CONFIG_USER_ONLY
env->pc = 0x1c000000;
-#ifdef CONFIG_TCG
- memset(env->tlb, 0, sizeof(env->tlb));
-#endif
if (kvm_enabled()) {
kvm_arch_reset_vcpu(cs);
}
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index 97db3b453f..d83dcef6f8 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -334,7 +334,6 @@ typedef struct CPUSysState {
uint64_t CSR_TLBEHI;
uint64_t CSR_TLBELO0;
uint64_t CSR_TLBELO1;
- uint64_t CSR_ASID;
uint64_t CSR_PGDL;
uint64_t CSR_PGDH;
uint64_t CSR_PGD;
@@ -343,9 +342,6 @@ typedef struct CPUSysState {
uint64_t CSR_STLBPS;
uint64_t CSR_RVACFG;
uint64_t CSR_CPUID;
- uint64_t CSR_PRCFG1;
- uint64_t CSR_PRCFG2;
- uint64_t CSR_PRCFG3;
uint64_t CSR_SAVE[16];
uint64_t CSR_TID;
uint64_t CSR_TCFG;
@@ -380,6 +376,14 @@ typedef struct CPUSysState {
uint64_t CSR_MSGIS[N_MSGIS];
uint64_t CSR_MSGIR;
uint64_t CSR_MSGIE;
+
+ /* Fields up to this point are cleared by a CPU reset */
+ struct {} end_reset_fields;
+
+ uint64_t CSR_ASID;
+ uint64_t CSR_PRCFG1;
+ uint64_t CSR_PRCFG2;
+ uint64_t CSR_PRCFG3;
} CPUSysState;
typedef struct CPUArchState {
@@ -391,16 +395,9 @@ typedef struct CPUArchState {
uint32_t fcsr0;
lbt_t lbt;
- uint32_t cpucfg[21];
- uint32_t pv_features;
- uint64_t vendor_id;
- uint64_t cpu_id;
- CPUSysState sys_states[1];
-
struct {
uint64_t guest_addr;
} stealtime;
- uint32_t perf_event_num;
#ifdef CONFIG_TCG
float_status fp_status;
@@ -410,12 +407,23 @@ typedef struct CPUArchState {
uint64_t llval_high; /* For 128-bit atomic SC.Q */
uint64_t llbit_scq; /* Potential LL.D+LD.D+SC.Q sequence in effect */
uint64_t hw_pte_mask; /* Mask of architecturally-defined (hardware) PTE bits. */
-#endif
+
#ifndef CONFIG_USER_ONLY
-#ifdef CONFIG_TCG
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
+#endif
#endif
+ /* Fields up to this point are cleared by a CPU reset */
+ struct {} end_reset_fields;
+
+ CPUSysState sys_states[1];
+ uint32_t cpucfg[21];
+ uint32_t pv_features;
+ uint64_t vendor_id;
+ uint64_t cpu_id;
+ uint32_t perf_event_num;
+
+#ifndef CONFIG_USER_ONLY
AddressSpace *address_space_iocsr;
uint32_t mp_state;
#endif