target/arm: Implement ESB instruction
Check for and defer any pending virtual SError. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220506180242.216785-17-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
3c29632feb
commit
13954587ea
@ -187,6 +187,7 @@ SMULTT .... 0001 0110 .... 0000 .... 1110 .... @rd0mn
|
|||||||
|
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
|
[
|
||||||
YIELD ---- 0011 0010 0000 1111 ---- 0000 0001
|
YIELD ---- 0011 0010 0000 1111 ---- 0000 0001
|
||||||
WFE ---- 0011 0010 0000 1111 ---- 0000 0010
|
WFE ---- 0011 0010 0000 1111 ---- 0000 0010
|
||||||
WFI ---- 0011 0010 0000 1111 ---- 0000 0011
|
WFI ---- 0011 0010 0000 1111 ---- 0000 0011
|
||||||
@ -195,6 +196,9 @@ SMULTT .... 0001 0110 .... 0000 .... 1110 .... @rd0mn
|
|||||||
# SEV ---- 0011 0010 0000 1111 ---- 0000 0100
|
# SEV ---- 0011 0010 0000 1111 ---- 0000 0100
|
||||||
# SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
|
# SEVL ---- 0011 0010 0000 1111 ---- 0000 0101
|
||||||
|
|
||||||
|
ESB ---- 0011 0010 0000 1111 ---- 0001 0000
|
||||||
|
]
|
||||||
|
|
||||||
# The canonical nop ends in 00000000, but the whole of the
|
# The canonical nop ends in 00000000, but the whole of the
|
||||||
# rest of the space executes as nop if otherwise unsupported.
|
# rest of the space executes as nop if otherwise unsupported.
|
||||||
NOP ---- 0011 0010 0000 1111 ---- ---- ----
|
NOP ---- 0011 0010 0000 1111 ---- ---- ----
|
||||||
|
@ -54,6 +54,7 @@ DEF_HELPER_1(wfe, void, env)
|
|||||||
DEF_HELPER_1(yield, void, env)
|
DEF_HELPER_1(yield, void, env)
|
||||||
DEF_HELPER_1(pre_hvc, void, env)
|
DEF_HELPER_1(pre_hvc, void, env)
|
||||||
DEF_HELPER_2(pre_smc, void, env, i32)
|
DEF_HELPER_2(pre_smc, void, env, i32)
|
||||||
|
DEF_HELPER_1(vesb, void, env)
|
||||||
|
|
||||||
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
|
DEF_HELPER_3(cpsr_write, void, env, i32, i32)
|
||||||
DEF_HELPER_2(cpsr_write_eret, void, env, i32)
|
DEF_HELPER_2(cpsr_write_eret, void, env, i32)
|
||||||
|
@ -960,3 +960,46 @@ void HELPER(probe_access)(CPUARMState *env, target_ulong ptr,
|
|||||||
access_type, mmu_idx, ra);
|
access_type, mmu_idx, ra);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function corresponds to AArch64.vESBOperation().
|
||||||
|
* Note that the AArch32 version is not functionally different.
|
||||||
|
*/
|
||||||
|
void HELPER(vesb)(CPUARMState *env)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* The EL2Enabled() check is done inside arm_hcr_el2_eff,
|
||||||
|
* and will return HCR_EL2.VSE == 0, so nothing happens.
|
||||||
|
*/
|
||||||
|
uint64_t hcr = arm_hcr_el2_eff(env);
|
||||||
|
bool enabled = !(hcr & HCR_TGE) && (hcr & HCR_AMO);
|
||||||
|
bool pending = enabled && (hcr & HCR_VSE);
|
||||||
|
bool masked = (env->daif & PSTATE_A);
|
||||||
|
|
||||||
|
/* If VSE pending and masked, defer the exception. */
|
||||||
|
if (pending && masked) {
|
||||||
|
uint32_t syndrome;
|
||||||
|
|
||||||
|
if (arm_el_is_aa64(env, 1)) {
|
||||||
|
/* Copy across IDS and ISS from VSESR. */
|
||||||
|
syndrome = env->cp15.vsesr_el2 & 0x1ffffff;
|
||||||
|
} else {
|
||||||
|
ARMMMUFaultInfo fi = { .type = ARMFault_AsyncExternal };
|
||||||
|
|
||||||
|
if (extended_addresses_enabled(env)) {
|
||||||
|
syndrome = arm_fi_to_lfsc(&fi);
|
||||||
|
} else {
|
||||||
|
syndrome = arm_fi_to_sfsc(&fi);
|
||||||
|
}
|
||||||
|
/* Copy across AET and ExT from VSESR. */
|
||||||
|
syndrome |= env->cp15.vsesr_el2 & 0xd000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set VDISR_EL2.A along with the syndrome. */
|
||||||
|
env->cp15.vdisr_el2 = syndrome | (1u << 31);
|
||||||
|
|
||||||
|
/* Clear pending virtual SError */
|
||||||
|
env->cp15.hcr_el2 &= ~HCR_VSE;
|
||||||
|
cpu_reset_interrupt(env_cpu(env), CPU_INTERRUPT_VSERR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -364,6 +364,7 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
|
|||||||
[
|
[
|
||||||
# Hints, and CPS
|
# Hints, and CPS
|
||||||
{
|
{
|
||||||
|
[
|
||||||
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
|
YIELD 1111 0011 1010 1111 1000 0000 0000 0001
|
||||||
WFE 1111 0011 1010 1111 1000 0000 0000 0010
|
WFE 1111 0011 1010 1111 1000 0000 0000 0010
|
||||||
WFI 1111 0011 1010 1111 1000 0000 0000 0011
|
WFI 1111 0011 1010 1111 1000 0000 0000 0011
|
||||||
@ -372,9 +373,8 @@ CLZ 1111 1010 1011 ---- 1111 .... 1000 .... @rdm
|
|||||||
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
|
# SEV 1111 0011 1010 1111 1000 0000 0000 0100
|
||||||
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
|
# SEVL 1111 0011 1010 1111 1000 0000 0000 0101
|
||||||
|
|
||||||
# For M-profile minimal-RAS ESB can be a NOP, which is the
|
ESB 1111 0011 1010 1111 1000 0000 0001 0000
|
||||||
# default behaviour since it is in the hint space.
|
]
|
||||||
# ESB 1111 0011 1010 1111 1000 0000 0001 0000
|
|
||||||
|
|
||||||
# The canonical nop ends in 0000 0000, but the whole rest
|
# The canonical nop ends in 0000 0000, but the whole rest
|
||||||
# of the space is "reserved hint, behaves as nop".
|
# of the space is "reserved hint, behaves as nop".
|
||||||
|
@ -1454,6 +1454,23 @@ static void handle_hint(DisasContext *s, uint32_t insn,
|
|||||||
gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 0b10000: /* ESB */
|
||||||
|
/* Without RAS, we must implement this as NOP. */
|
||||||
|
if (dc_isar_feature(aa64_ras, s)) {
|
||||||
|
/*
|
||||||
|
* QEMU does not have a source of physical SErrors,
|
||||||
|
* so we are only concerned with virtual SErrors.
|
||||||
|
* The pseudocode in the ARM for this case is
|
||||||
|
* if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
|
||||||
|
* AArch64.vESBOperation();
|
||||||
|
* Most of the condition can be evaluated at translation time.
|
||||||
|
* Test for EL2 present, and defer test for SEL2 to runtime.
|
||||||
|
*/
|
||||||
|
if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
|
||||||
|
gen_helper_vesb(cpu_env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 0b11000: /* PACIAZ */
|
case 0b11000: /* PACIAZ */
|
||||||
if (s->pauth_active) {
|
if (s->pauth_active) {
|
||||||
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
|
gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
|
||||||
|
@ -6239,6 +6239,29 @@ static bool trans_WFI(DisasContext *s, arg_WFI *a)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool trans_ESB(DisasContext *s, arg_ESB *a)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* For M-profile, minimal-RAS ESB can be a NOP.
|
||||||
|
* Without RAS, we must implement this as NOP.
|
||||||
|
*/
|
||||||
|
if (!arm_dc_feature(s, ARM_FEATURE_M) && dc_isar_feature(aa32_ras, s)) {
|
||||||
|
/*
|
||||||
|
* QEMU does not have a source of physical SErrors,
|
||||||
|
* so we are only concerned with virtual SErrors.
|
||||||
|
* The pseudocode in the ARM for this case is
|
||||||
|
* if PSTATE.EL IN {EL0, EL1} && EL2Enabled() then
|
||||||
|
* AArch32.vESBOperation();
|
||||||
|
* Most of the condition can be evaluated at translation time.
|
||||||
|
* Test for EL2 present, and defer test for SEL2 to runtime.
|
||||||
|
*/
|
||||||
|
if (s->current_el <= 1 && arm_dc_feature(s, ARM_FEATURE_EL2)) {
|
||||||
|
gen_helper_vesb(cpu_env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool trans_NOP(DisasContext *s, arg_NOP *a)
|
static bool trans_NOP(DisasContext *s, arg_NOP *a)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user