@ -3437,6 +3437,61 @@ static CPAccessResult access_nv1(CPUARMState *env, const ARMCPRegInfo *ri,
return CP_ACCESS_OK ;
}
static CPAccessResult access_nv1_or_exlock_el1 ( CPUARMState * env ,
const ARMCPRegInfo * ri ,
bool isread )
{
if ( arm_current_el ( env ) = = 1 ) {
uint64_t nvx = arm_hcr_el2_nvx_eff ( env ) ;
if ( ! isread & &
( env - > pstate & PSTATE_EXLOCK ) & &
( env - > cp15 . gcscr_el [ 1 ] & GCSCR_EXLOCKEN ) & &
! ( nvx & HCR_NV1 ) ) {
return CP_ACCESS_EXLOCK ;
}
return access_nv1_with_nvx ( nvx ) ;
}
/*
* At EL2 , since VHE redirection is done at translation time ,
* el_is_in_host is always false here , so EXLOCK does not apply .
*/
return CP_ACCESS_OK ;
}
static CPAccessResult access_exlock_el2 ( CPUARMState * env ,
const ARMCPRegInfo * ri , bool isread )
{
int el = arm_current_el ( env ) ;
if ( el = = 3 ) {
return CP_ACCESS_OK ;
}
/*
* Access to the EL2 register from EL1 means NV is set , and
* EXLOCK has priority over an NV1 trap to EL2 .
*/
if ( ! isread & &
( env - > pstate & PSTATE_EXLOCK ) & &
( env - > cp15 . gcscr_el [ el ] & GCSCR_EXLOCKEN ) ) {
return CP_ACCESS_EXLOCK ;
}
return CP_ACCESS_OK ;
}
static CPAccessResult access_exlock_el3 ( CPUARMState * env ,
const ARMCPRegInfo * ri , bool isread )
{
if ( ! isread & &
( env - > pstate & PSTATE_EXLOCK ) & &
( env - > cp15 . gcscr_el [ 3 ] & GCSCR_EXLOCKEN ) ) {
return CP_ACCESS_EXLOCK ;
}
return CP_ACCESS_OK ;
}
# ifdef CONFIG_USER_ONLY
/*
* ` IC IVAU ` is handled to improve compatibility with JITs that dual - map their
@ -3608,7 +3663,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ . name = " ELR_EL1 " , . state = ARM_CP_STATE_AA64 ,
. type = ARM_CP_ALIAS ,
. opc0 = 3 , . opc1 = 0 , . crn = 4 , . crm = 0 , . opc2 = 1 ,
. access = PL1_RW , . accessfn = access_nv1 ,
. access = PL1_RW , . accessfn = access_nv1_or_exlock_el1 ,
. nv2_redirect_offset = 0x230 | NV2_REDIR_NV1 ,
. vhe_redir_to_el2 = ENCODE_AA64_CP_REG ( 3 , 4 , 4 , 0 , 1 ) ,
. vhe_redir_to_el01 = ENCODE_AA64_CP_REG ( 3 , 5 , 4 , 0 , 1 ) ,
@ -3616,7 +3671,7 @@ static const ARMCPRegInfo v8_cp_reginfo[] = {
{ . name = " SPSR_EL1 " , . state = ARM_CP_STATE_AA64 ,
. type = ARM_CP_ALIAS ,
. opc0 = 3 , . opc1 = 0 , . crn = 4 , . crm = 0 , . opc2 = 0 ,
. access = PL1_RW , . accessfn = access_nv1 ,
. access = PL1_RW , . accessfn = access_nv1_or_exlock_el1 ,
. nv2_redirect_offset = 0x160 | NV2_REDIR_NV1 ,
. vhe_redir_to_el2 = ENCODE_AA64_CP_REG ( 3 , 4 , 4 , 0 , 0 ) ,
. vhe_redir_to_el01 = ENCODE_AA64_CP_REG ( 3 , 5 , 4 , 0 , 0 ) ,
@ -4100,7 +4155,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
{ . name = " ELR_EL2 " , . state = ARM_CP_STATE_AA64 ,
. type = ARM_CP_ALIAS | ARM_CP_NV2_REDIRECT ,
. opc0 = 3 , . opc1 = 4 , . crn = 4 , . crm = 0 , . opc2 = 1 ,
. access = PL2_RW ,
. access = PL2_RW , . accessfn = access_exlock_el2 ,
. fieldoffset = offsetof ( CPUARMState , elr_el [ 2 ] ) } ,
{ . name = " ESR_EL2 " , . state = ARM_CP_STATE_BOTH ,
. type = ARM_CP_NV2_REDIRECT ,
@ -4118,7 +4173,7 @@ static const ARMCPRegInfo el2_cp_reginfo[] = {
{ . name = " SPSR_EL2 " , . state = ARM_CP_STATE_AA64 ,
. type = ARM_CP_ALIAS | ARM_CP_NV2_REDIRECT ,
. opc0 = 3 , . opc1 = 4 , . crn = 4 , . crm = 0 , . opc2 = 0 ,
. access = PL2_RW ,
. access = PL2_RW , . accessfn = access_exlock_el2 ,
. fieldoffset = offsetof ( CPUARMState , banked_spsr [ BANK_HYP ] ) } ,
{ . name = " VBAR_EL2 " , . state = ARM_CP_STATE_BOTH ,
. opc0 = 3 , . opc1 = 4 , . crn = 12 , . crm = 0 , . opc2 = 0 ,
@ -4400,7 +4455,7 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
{ . name = " ELR_EL3 " , . state = ARM_CP_STATE_AA64 ,
. type = ARM_CP_ALIAS ,
. opc0 = 3 , . opc1 = 6 , . crn = 4 , . crm = 0 , . opc2 = 1 ,
. access = PL3_RW ,
. access = PL3_RW , . accessfn = access_exlock_el3 ,
. fieldoffset = offsetof ( CPUARMState , elr_el [ 3 ] ) } ,
{ . name = " ESR_EL3 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 6 , . crn = 5 , . crm = 2 , . opc2 = 0 ,
@ -4411,7 +4466,7 @@ static const ARMCPRegInfo el3_cp_reginfo[] = {
{ . name = " SPSR_EL3 " , . state = ARM_CP_STATE_AA64 ,
. type = ARM_CP_ALIAS ,
. opc0 = 3 , . opc1 = 6 , . crn = 4 , . crm = 0 , . opc2 = 0 ,
. access = PL3_RW ,
. access = PL3_RW , . accessfn = access_exlock_el3 ,
. fieldoffset = offsetof ( CPUARMState , banked_spsr [ BANK_MON ] ) } ,
{ . name = " VBAR_EL3 " , . state = ARM_CP_STATE_AA64 ,
. opc0 = 3 , . opc1 = 6 , . crn = 12 , . crm = 0 , . opc2 = 0 ,