target/loongarch/cpu-csr.h | 7 +++++++ target/loongarch/cpu.c | 41 +++++++++++++++++--------------------- target/loongarch/cpu.h | 22 +++++++++++--------- 3 files changed, 38 insertions(+), 32 deletions(-)
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 carried out the operation and checked the status of other
registers during the reset process:
Set the CSR_CRMD, CSR_ESTAT, CSR_MSGIS and CSR_PERFCTRL registers to the
reset state when the CPU is reset.
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
---
Cc: Alex Bennée <alex.bennee@linaro.org>
Cc: Bibo Mao <maobibo@loongson.cn>
Cc: Song Gao <gaosong@loongson.cn>
changelog:
V1->V2:
1.Add a description of the issues related to this patch
2.Replace the macro definition MAX_PERF_EVENTS with the variable
perf_event_num as the condition for the for loop.
3.Rebase against the latest codebase.
4.Refer to the usage of end_reset_fields on ARM and other architectures,
and modify the current implementation accordingly.
Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
---
target/loongarch/cpu-csr.h | 7 +++++++
target/loongarch/cpu.c | 41 +++++++++++++++++---------------------
target/loongarch/cpu.h | 22 +++++++++++---------
3 files changed, 38 insertions(+), 32 deletions(-)
diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
index d860417af2..d936af8e57 100644
--- a/target/loongarch/cpu-csr.h
+++ b/target/loongarch/cpu-csr.h
@@ -211,6 +211,13 @@ FIELD(CSR_DMW_64, VSEG, 60, 4)
#define LOONGARCH_CSR_PERFCTRL(N) (0x200 + 2 * N)
#define LOONGARCH_CSR_PERFCNTR(N) (0x201 + 2 * N)
+FIELD(CSR_PERFCTRL, EV, 0, 10)
+FIELD(CSR_PERFCTRL, PLV0, 16, 1)
+FIELD(CSR_PERFCTRL, PLV1, 17, 1)
+FIELD(CSR_PERFCTRL, PLV2, 18, 1)
+FIELD(CSR_PERFCTRL, PLV3, 19, 1)
+FIELD(CSR_PERFCTRL, PMIE, 20, 1)
+
/* Debug CSRs */
#define LOONGARCH_CSR_DBG 0x500 /* debug config */
FIELD(CSR_DBG, DST, 0, 1)
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index fb03424ffa..aa6ecd9da2 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -623,44 +623,39 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
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);
+ memset(sys, 0, offsetof(CPUSysState, end_reset_fields));
- 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);
+ /* Set csr registers value after reset, see the manual 6.4. */
+ sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1);
- 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;
+
+ sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DST, 0);
+ for (n = 0; n < env->perf_event_num; n++) {
+ sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
+ PLV0, 0);
+ sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
+ PLV1, 0);
+ sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
+ PLV2, 0);
+ sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
+ PLV3, 0);
+ sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
+ PMIE, 0);
+ }
+
/*
* 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;
diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
index ad30c73167..2576239b31 100644
--- a/target/loongarch/cpu.h
+++ b/target/loongarch/cpu.h
@@ -325,22 +325,30 @@ typedef struct CPUSysState {
uint64_t CSR_MISC;
uint64_t CSR_ECFG;
uint64_t CSR_ESTAT;
+ uint64_t CSR_PGDL;
+ uint64_t CSR_PGDH;
+ uint64_t CSR_EENTRY;
+ uint64_t CSR_PWCH;
+ uint64_t CSR_RVACFG;
+ uint64_t CSR_TLBRENTRY;
+ uint64_t CSR_MERRENTRY;
+ /* Msg interrupt registers */
+ uint64_t CSR_MSGIS[N_MSGIS];
+
+ /* Fields up to this point are cleared by a CPU reset */
+ struct {} end_reset_fields;
+
uint64_t CSR_ERA;
uint64_t CSR_BADV;
uint64_t CSR_BADI;
- uint64_t CSR_EENTRY;
uint64_t CSR_TLBIDX;
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;
uint64_t CSR_PWCL;
- uint64_t CSR_PWCH;
uint64_t CSR_STLBPS;
- uint64_t CSR_RVACFG;
uint64_t CSR_CPUID;
uint64_t CSR_PRCFG1;
uint64_t CSR_PRCFG2;
@@ -354,7 +362,6 @@ typedef struct CPUSysState {
uint64_t CSR_LLBCTL;
uint64_t CSR_IMPCTL1;
uint64_t CSR_IMPCTL2;
- uint64_t CSR_TLBRENTRY;
uint64_t CSR_TLBRBADV;
uint64_t CSR_TLBRERA;
uint64_t CSR_TLBRSAVE;
@@ -365,7 +372,6 @@ typedef struct CPUSysState {
uint64_t CSR_MERRCTL;
uint64_t CSR_MERRINFO1;
uint64_t CSR_MERRINFO2;
- uint64_t CSR_MERRENTRY;
uint64_t CSR_MERRERA;
uint64_t CSR_MERRSAVE;
uint64_t CSR_CTAG;
@@ -375,8 +381,6 @@ typedef struct CPUSysState {
uint64_t CSR_DBG;
uint64_t CSR_DERA;
uint64_t CSR_DSAVE;
- /* Msg interrupt registers */
- uint64_t CSR_MSGIS[N_MSGIS];
uint64_t CSR_MSGIR;
uint64_t CSR_MSGIE;
} CPUSysState;
--
2.39.1
Hi,
On 16/6/26 11:25, Xianglai Li wrote:
> 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 carried out the operation and checked the status of other
> registers during the reset process:
>
> Set the CSR_CRMD, CSR_ESTAT, CSR_MSGIS and CSR_PERFCTRL registers to the
> reset state when the CPU is reset.
>
> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
> ---
> Cc: Alex Bennée <alex.bennee@linaro.org>
> Cc: Bibo Mao <maobibo@loongson.cn>
> Cc: Song Gao <gaosong@loongson.cn>
>
> changelog:
> V1->V2:
> 1.Add a description of the issues related to this patch
> 2.Replace the macro definition MAX_PERF_EVENTS with the variable
> perf_event_num as the condition for the for loop.
> 3.Rebase against the latest codebase.
> 4.Refer to the usage of end_reset_fields on ARM and other architectures,
> and modify the current implementation accordingly.
>
> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
> ---
> target/loongarch/cpu-csr.h | 7 +++++++
> target/loongarch/cpu.c | 41 +++++++++++++++++---------------------
> target/loongarch/cpu.h | 22 +++++++++++---------
> 3 files changed, 38 insertions(+), 32 deletions(-)
>
> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
> index d860417af2..d936af8e57 100644
> --- a/target/loongarch/cpu-csr.h
> +++ b/target/loongarch/cpu-csr.h
> @@ -211,6 +211,13 @@ FIELD(CSR_DMW_64, VSEG, 60, 4)
> #define LOONGARCH_CSR_PERFCTRL(N) (0x200 + 2 * N)
> #define LOONGARCH_CSR_PERFCNTR(N) (0x201 + 2 * N)
>
> +FIELD(CSR_PERFCTRL, EV, 0, 10)
> +FIELD(CSR_PERFCTRL, PLV0, 16, 1)
> +FIELD(CSR_PERFCTRL, PLV1, 17, 1)
> +FIELD(CSR_PERFCTRL, PLV2, 18, 1)
> +FIELD(CSR_PERFCTRL, PLV3, 19, 1)
> +FIELD(CSR_PERFCTRL, PMIE, 20, 1)
> +
> /* Debug CSRs */
> #define LOONGARCH_CSR_DBG 0x500 /* debug config */
> FIELD(CSR_DBG, DST, 0, 1)
> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
> index fb03424ffa..aa6ecd9da2 100644
> --- a/target/loongarch/cpu.c
> +++ b/target/loongarch/cpu.c
> @@ -623,44 +623,39 @@ static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
> 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);
> + memset(sys, 0, offsetof(CPUSysState, end_reset_fields));
>
> - 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);
> + /* Set csr registers value after reset, see the manual 6.4. */
> + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1);
>
> - 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;
> +
> + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DST, 0);
> + for (n = 0; n < env->perf_event_num; n++) {
> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
> + PLV0, 0);
> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
> + PLV1, 0);
> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
> + PLV2, 0);
> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
> + PLV3, 0);
> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n], CSR_PERFCTRL,
> + PMIE, 0);
> + }
> +
> /*
> * Workaround for edk2-stable202408, CSR PGD register is set only if
> * its value is equal to zero for boot cpu, it causes reboot issue.
Is this comment still accurate?
> *
> * 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;
> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
> index ad30c73167..2576239b31 100644
> --- a/target/loongarch/cpu.h
> +++ b/target/loongarch/cpu.h
> @@ -325,22 +325,30 @@ typedef struct CPUSysState {
> uint64_t CSR_MISC;
> uint64_t CSR_ECFG;
> uint64_t CSR_ESTAT;
> + uint64_t CSR_PGDL;
> + uint64_t CSR_PGDH;
> + uint64_t CSR_EENTRY;
> + uint64_t CSR_PWCH;
> + uint64_t CSR_RVACFG;
> + uint64_t CSR_TLBRENTRY;
> + uint64_t CSR_MERRENTRY;
> + /* Msg interrupt registers */
> + uint64_t CSR_MSGIS[N_MSGIS];
> +
> + /* Fields up to this point are cleared by a CPU reset */
> + struct {} end_reset_fields;
> +
> uint64_t CSR_ERA;
> uint64_t CSR_BADV;
> uint64_t CSR_BADI;
> - uint64_t CSR_EENTRY;
> uint64_t CSR_TLBIDX;
> 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;
> uint64_t CSR_PWCL;
> - uint64_t CSR_PWCH;
> uint64_t CSR_STLBPS;
> - uint64_t CSR_RVACFG;
> uint64_t CSR_CPUID;
> uint64_t CSR_PRCFG1;
> uint64_t CSR_PRCFG2;
> @@ -354,7 +362,6 @@ typedef struct CPUSysState {
> uint64_t CSR_LLBCTL;
> uint64_t CSR_IMPCTL1;
> uint64_t CSR_IMPCTL2;
> - uint64_t CSR_TLBRENTRY;
> uint64_t CSR_TLBRBADV;
> uint64_t CSR_TLBRERA;
> uint64_t CSR_TLBRSAVE;
> @@ -365,7 +372,6 @@ typedef struct CPUSysState {
> uint64_t CSR_MERRCTL;
> uint64_t CSR_MERRINFO1;
> uint64_t CSR_MERRINFO2;
> - uint64_t CSR_MERRENTRY;
> uint64_t CSR_MERRERA;
> uint64_t CSR_MERRSAVE;
> uint64_t CSR_CTAG;
> @@ -375,8 +381,6 @@ typedef struct CPUSysState {
> uint64_t CSR_DBG;
> uint64_t CSR_DERA;
> uint64_t CSR_DSAVE;
> - /* Msg interrupt registers */
> - uint64_t CSR_MSGIS[N_MSGIS];
> uint64_t CSR_MSGIR;
> uint64_t CSR_MSGIE;
> } CPUSysState;
Hi Philippe Mathieu-Daudé:
> Hi,
>
> On 16/6/26 11:25, Xianglai Li wrote:
>> 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 carried out the operation and checked the status of other
>> registers during the reset process:
>>
>> Set the CSR_CRMD, CSR_ESTAT, CSR_MSGIS and CSR_PERFCTRL registers to the
>> reset state when the CPU is reset.
>>
>> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
>> ---
>> Cc: Alex Bennée <alex.bennee@linaro.org>
>> Cc: Bibo Mao <maobibo@loongson.cn>
>> Cc: Song Gao <gaosong@loongson.cn>
>>
>> changelog:
>> V1->V2:
>> 1.Add a description of the issues related to this patch
>> 2.Replace the macro definition MAX_PERF_EVENTS with the variable
>> perf_event_num as the condition for the for loop.
>> 3.Rebase against the latest codebase.
>> 4.Refer to the usage of end_reset_fields on ARM and other architectures,
>> and modify the current implementation accordingly.
>>
>> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
>> ---
>> target/loongarch/cpu-csr.h | 7 +++++++
>> target/loongarch/cpu.c | 41 +++++++++++++++++---------------------
>> target/loongarch/cpu.h | 22 +++++++++++---------
>> 3 files changed, 38 insertions(+), 32 deletions(-)
>>
>> diff --git a/target/loongarch/cpu-csr.h b/target/loongarch/cpu-csr.h
>> index d860417af2..d936af8e57 100644
>> --- a/target/loongarch/cpu-csr.h
>> +++ b/target/loongarch/cpu-csr.h
>> @@ -211,6 +211,13 @@ FIELD(CSR_DMW_64, VSEG, 60, 4)
>> #define LOONGARCH_CSR_PERFCTRL(N) (0x200 + 2 * N)
>> #define LOONGARCH_CSR_PERFCNTR(N) (0x201 + 2 * N)
>> +FIELD(CSR_PERFCTRL, EV, 0, 10)
>> +FIELD(CSR_PERFCTRL, PLV0, 16, 1)
>> +FIELD(CSR_PERFCTRL, PLV1, 17, 1)
>> +FIELD(CSR_PERFCTRL, PLV2, 18, 1)
>> +FIELD(CSR_PERFCTRL, PLV3, 19, 1)
>> +FIELD(CSR_PERFCTRL, PMIE, 20, 1)
>> +
>> /* Debug CSRs */
>> #define LOONGARCH_CSR_DBG 0x500 /* debug config */
>> FIELD(CSR_DBG, DST, 0, 1)
>> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
>> index fb03424ffa..aa6ecd9da2 100644
>> --- a/target/loongarch/cpu.c
>> +++ b/target/loongarch/cpu.c
>> @@ -623,44 +623,39 @@ static void loongarch_cpu_reset_hold(Object
>> *obj, ResetType type)
>> 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);
>> + memset(sys, 0, offsetof(CPUSysState, end_reset_fields));
>> - 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);
>> + /* Set csr registers value after reset, see the manual 6.4. */
>> + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1);
>> - 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;
>> +
>> + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DST, 0);
>> + for (n = 0; n < env->perf_event_num; n++) {
>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>> CSR_PERFCTRL,
>> + PLV0, 0);
>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>> CSR_PERFCTRL,
>> + PLV1, 0);
>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>> CSR_PERFCTRL,
>> + PLV2, 0);
>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>> CSR_PERFCTRL,
>> + PLV3, 0);
>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>> CSR_PERFCTRL,
>> + PMIE, 0);
>> + }
>> +
>> /*
>> * Workaround for edk2-stable202408, CSR PGD register is set
>> only if
>> * its value is equal to zero for boot cpu, it causes reboot
>> issue.
>
> Is this comment still accurate?
>
Yes, the comment is outdated. We should move it before memset(sys, 0,
offsetof(CPUSysState, end_reset_fields)), like this:
/*
* 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(sys, 0, offsetof(CPUSysState, end_reset_fields));
>> *
>> * Here clear CSR registers relative with TLB.
Let's just delete this comment in the next version — the related note is
no longer needed.
Thanks!
Xianglai.
>> */
>> - 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;
>> diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h
>> index ad30c73167..2576239b31 100644
>> --- a/target/loongarch/cpu.h
>> +++ b/target/loongarch/cpu.h
>> @@ -325,22 +325,30 @@ typedef struct CPUSysState {
>> uint64_t CSR_MISC;
>> uint64_t CSR_ECFG;
>> uint64_t CSR_ESTAT;
>> + uint64_t CSR_PGDL;
>> + uint64_t CSR_PGDH;
>> + uint64_t CSR_EENTRY;
>> + uint64_t CSR_PWCH;
>> + uint64_t CSR_RVACFG;
>> + uint64_t CSR_TLBRENTRY;
>> + uint64_t CSR_MERRENTRY;
>> + /* Msg interrupt registers */
>> + uint64_t CSR_MSGIS[N_MSGIS];
>> +
>> + /* Fields up to this point are cleared by a CPU reset */
>> + struct {} end_reset_fields;
>> +
>> uint64_t CSR_ERA;
>> uint64_t CSR_BADV;
>> uint64_t CSR_BADI;
>> - uint64_t CSR_EENTRY;
>> uint64_t CSR_TLBIDX;
>> 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;
>> uint64_t CSR_PWCL;
>> - uint64_t CSR_PWCH;
>> uint64_t CSR_STLBPS;
>> - uint64_t CSR_RVACFG;
>> uint64_t CSR_CPUID;
>> uint64_t CSR_PRCFG1;
>> uint64_t CSR_PRCFG2;
>> @@ -354,7 +362,6 @@ typedef struct CPUSysState {
>> uint64_t CSR_LLBCTL;
>> uint64_t CSR_IMPCTL1;
>> uint64_t CSR_IMPCTL2;
>> - uint64_t CSR_TLBRENTRY;
>> uint64_t CSR_TLBRBADV;
>> uint64_t CSR_TLBRERA;
>> uint64_t CSR_TLBRSAVE;
>> @@ -365,7 +372,6 @@ typedef struct CPUSysState {
>> uint64_t CSR_MERRCTL;
>> uint64_t CSR_MERRINFO1;
>> uint64_t CSR_MERRINFO2;
>> - uint64_t CSR_MERRENTRY;
>> uint64_t CSR_MERRERA;
>> uint64_t CSR_MERRSAVE;
>> uint64_t CSR_CTAG;
>> @@ -375,8 +381,6 @@ typedef struct CPUSysState {
>> uint64_t CSR_DBG;
>> uint64_t CSR_DERA;
>> uint64_t CSR_DSAVE;
>> - /* Msg interrupt registers */
>> - uint64_t CSR_MSGIS[N_MSGIS];
>> uint64_t CSR_MSGIR;
>> uint64_t CSR_MSGIE;
>> } CPUSysState;
On 16/6/26 14:20, lixianglai wrote:
> Hi Philippe Mathieu-Daudé:
>> Hi,
>>
>> On 16/6/26 11:25, Xianglai Li wrote:
>>> 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 carried out the operation and checked the status of other
>>> registers during the reset process:
>>>
>>> Set the CSR_CRMD, CSR_ESTAT, CSR_MSGIS and CSR_PERFCTRL registers to the
>>> reset state when the CPU is reset.
>>>
>>> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
>>> ---
>>> Cc: Alex Bennée <alex.bennee@linaro.org>
>>> Cc: Bibo Mao <maobibo@loongson.cn>
>>> Cc: Song Gao <gaosong@loongson.cn>
>>>
>>> changelog:
>>> V1->V2:
>>> 1.Add a description of the issues related to this patch
>>> 2.Replace the macro definition MAX_PERF_EVENTS with the variable
>>> perf_event_num as the condition for the for loop.
>>> 3.Rebase against the latest codebase.
>>> 4.Refer to the usage of end_reset_fields on ARM and other architectures,
>>> and modify the current implementation accordingly.
>>>
>>> Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
>>> ---
>>> target/loongarch/cpu-csr.h | 7 +++++++
>>> target/loongarch/cpu.c | 41 +++++++++++++++++---------------------
>>> target/loongarch/cpu.h | 22 +++++++++++---------
>>> 3 files changed, 38 insertions(+), 32 deletions(-)
>>> diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
>>> index fb03424ffa..aa6ecd9da2 100644
>>> --- a/target/loongarch/cpu.c
>>> +++ b/target/loongarch/cpu.c
>>> @@ -623,44 +623,39 @@ static void loongarch_cpu_reset_hold(Object
>>> *obj, ResetType type)
>>> 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);
>>> + memset(sys, 0, offsetof(CPUSysState, end_reset_fields));
>>> - 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);
>>> + /* Set csr registers value after reset, see the manual 6.4. */
>>> + sys->CSR_CRMD = FIELD_DP64(sys->CSR_CRMD, CSR_CRMD, DA, 1);
>>> - 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;
>>> +
>>> + sys->CSR_DBG = FIELD_DP64(sys->CSR_DBG, CSR_DBG, DST, 0);
>>> + for (n = 0; n < env->perf_event_num; n++) {
>>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>>> CSR_PERFCTRL,
>>> + PLV0, 0);
>>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>>> CSR_PERFCTRL,
>>> + PLV1, 0);
>>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>>> CSR_PERFCTRL,
>>> + PLV2, 0);
>>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>>> CSR_PERFCTRL,
>>> + PLV3, 0);
>>> + sys->CSR_PERFCTRL[n] = FIELD_DP64(sys->CSR_PERFCTRL[n],
>>> CSR_PERFCTRL,
>>> + PMIE, 0);
>>> + }
>>> +
>>> /*
>>> * Workaround for edk2-stable202408, CSR PGD register is set
>>> only if
>>> * its value is equal to zero for boot cpu, it causes reboot
>>> issue.
>>
>> Is this comment still accurate?
>>
> Yes, the comment is outdated. We should move it before memset(sys, 0,
> offsetof(CPUSysState, end_reset_fields)), like this:
>
> /*
> * 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(sys, 0, offsetof(CPUSysState, end_reset_fields));
OK, then add on v3:
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
>
>>> *
>>> * Here clear CSR registers relative with TLB.
> Let's just delete this comment in the next version — the related note is
> no longer needed.
>
> Thanks!
> Xianglai.
© 2016 - 2026 Red Hat, Inc.