mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-03 15:53:54 -06:00
target/arm: Handle FEAT_NV2 redirection of SPSR_EL2, ELR_EL2, ESR_EL2, FAR_EL2
Under FEAT_NV2, when HCR_EL2.{NV,NV2} == 0b11 at EL1, accesses to the registers SPSR_EL2, ELR_EL2, ESR_EL2, FAR_EL2 and TFSR_EL2 (which would UNDEF without FEAT_NV or FEAT_NV2) should instead access the equivalent EL1 registers SPSR_EL1, ELR_EL1, ESR_EL1, FAR_EL1 and TFSR_EL1. Because there are only five registers involved and the encoding for the EL1 register is identical to that of the EL2 register except that opc1 is 0, we handle this by finding the EL1 register in the hash table and using it instead. Note that traps that apply to direct accesses to the EL1 register, such as active fine-grained traps or other trap bits, do not trigger when it is accessed via the EL2 encoding in this way. However, some traps that are defined by the EL2 register may apply. We therefore call the EL2 register's accessfn first. The only one of the five which has such traps is TFSR_EL2: make sure its accessfn correctly handles both FEAT_NV (where we trap to EL2 without checking ATA bits) and FEAT_NV2 (where we check ATA bits and then redirect to TFSR_EL1). (We don't need the NV1 tbflag bit until the next patch, but we introduce it here to avoid putting the NV, NV1, NV2 bits in an odd order.) Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Tested-by: Miguel Luis <miguel.luis@oracle.com>
This commit is contained in:
parent
ef8a4a8816
commit
c35da11df4
6 changed files with 58 additions and 5 deletions
|
@ -6135,14 +6135,16 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
|
|||
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 7,
|
||||
.access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||
{ .name = "ELR_EL2", .state = ARM_CP_STATE_AA64,
|
||||
.type = ARM_CP_ALIAS,
|
||||
.type = ARM_CP_ALIAS | ARM_CP_NV2_REDIRECT,
|
||||
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 1,
|
||||
.access = PL2_RW,
|
||||
.fieldoffset = offsetof(CPUARMState, elr_el[2]) },
|
||||
{ .name = "ESR_EL2", .state = ARM_CP_STATE_BOTH,
|
||||
.type = ARM_CP_NV2_REDIRECT,
|
||||
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 2, .opc2 = 0,
|
||||
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.esr_el[2]) },
|
||||
{ .name = "FAR_EL2", .state = ARM_CP_STATE_BOTH,
|
||||
.type = ARM_CP_NV2_REDIRECT,
|
||||
.opc0 = 3, .opc1 = 4, .crn = 6, .crm = 0, .opc2 = 0,
|
||||
.access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.far_el[2]) },
|
||||
{ .name = "HIFAR", .state = ARM_CP_STATE_AA32,
|
||||
|
@ -6151,7 +6153,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
|
|||
.access = PL2_RW,
|
||||
.fieldoffset = offsetofhigh32(CPUARMState, cp15.far_el[2]) },
|
||||
{ .name = "SPSR_EL2", .state = ARM_CP_STATE_AA64,
|
||||
.type = ARM_CP_ALIAS,
|
||||
.type = ARM_CP_ALIAS | ARM_CP_NV2_REDIRECT,
|
||||
.opc0 = 3, .opc1 = 4, .crn = 4, .crm = 0, .opc2 = 0,
|
||||
.access = PL2_RW,
|
||||
.fieldoffset = offsetof(CPUARMState, banked_spsr[BANK_HYP]) },
|
||||
|
@ -7876,11 +7878,13 @@ static CPAccessResult access_tfsr_el2(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
/*
|
||||
* TFSR_EL2: similar to generic access_mte(), but we need to
|
||||
* account for FEAT_NV. At EL1 this must be a FEAT_NV access;
|
||||
* we will trap to EL2 and the HCR/SCR traps do not apply.
|
||||
* if NV2 is enabled then we will redirect this to TFSR_EL1
|
||||
* after doing the HCR and SCR ATA traps; otherwise this will
|
||||
* be a trap to EL2 and the HCR/SCR traps do not apply.
|
||||
*/
|
||||
int el = arm_current_el(env);
|
||||
|
||||
if (el == 1) {
|
||||
if (el == 1 && (arm_hcr_el2_eff(env) & HCR_NV2)) {
|
||||
return CP_ACCESS_OK;
|
||||
}
|
||||
if (el < 2 && arm_is_el2_enabled(env)) {
|
||||
|
@ -7917,6 +7921,7 @@ static const ARMCPRegInfo mte_reginfo[] = {
|
|||
.access = PL1_RW, .accessfn = access_tfsr_el1,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[1]) },
|
||||
{ .name = "TFSR_EL2", .state = ARM_CP_STATE_AA64,
|
||||
.type = ARM_CP_NV2_REDIRECT,
|
||||
.opc0 = 3, .opc1 = 4, .crn = 5, .crm = 6, .opc2 = 0,
|
||||
.access = PL2_RW, .accessfn = access_tfsr_el2,
|
||||
.fieldoffset = offsetof(CPUARMState, cp15.tfsr_el[2]) },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue