mirror of https://github.com/xemu-project/xemu.git
target/arm: Implement HSTR.TJDBX
In v7A, the HSTR register has a TJDBX bit which traps NS EL0/EL1 access to the JOSCR and JMCR trivial Jazelle registers, and also BXJ. Implement these traps. In v8A this HSTR bit doesn't exist, so don't trap for v8A CPUs. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210816180305.20137-3-peter.maydell@linaro.org
This commit is contained in:
parent
cc7613bfaa
commit
8e228c9e4b
|
@ -1542,6 +1542,7 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
|
||||||
#define SCR_ATA (1U << 26)
|
#define SCR_ATA (1U << 26)
|
||||||
|
|
||||||
#define HSTR_TTEE (1 << 16)
|
#define HSTR_TTEE (1 << 16)
|
||||||
|
#define HSTR_TJDBX (1 << 17)
|
||||||
|
|
||||||
/* Return the current FPSCR value. */
|
/* Return the current FPSCR value. */
|
||||||
uint32_t vfp_get_fpscr(CPUARMState *env);
|
uint32_t vfp_get_fpscr(CPUARMState *env);
|
||||||
|
|
|
@ -7602,6 +7602,21 @@ static CPAccessResult access_jazelle(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||||
return CP_ACCESS_OK;
|
return CP_ACCESS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static CPAccessResult access_joscr_jmcr(CPUARMState *env,
|
||||||
|
const ARMCPRegInfo *ri, bool isread)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* HSTR.TJDBX traps JOSCR and JMCR accesses, but it exists only
|
||||||
|
* in v7A, not in v8A.
|
||||||
|
*/
|
||||||
|
if (!arm_feature(env, ARM_FEATURE_V8) &&
|
||||||
|
arm_current_el(env) < 2 && !arm_is_secure_below_el3(env) &&
|
||||||
|
(env->cp15.hstr_el2 & HSTR_TJDBX)) {
|
||||||
|
return CP_ACCESS_TRAP_EL2;
|
||||||
|
}
|
||||||
|
return CP_ACCESS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static const ARMCPRegInfo jazelle_regs[] = {
|
static const ARMCPRegInfo jazelle_regs[] = {
|
||||||
{ .name = "JIDR",
|
{ .name = "JIDR",
|
||||||
.cp = 14, .crn = 0, .crm = 0, .opc1 = 7, .opc2 = 0,
|
.cp = 14, .crn = 0, .crm = 0, .opc1 = 7, .opc2 = 0,
|
||||||
|
@ -7609,9 +7624,11 @@ static const ARMCPRegInfo jazelle_regs[] = {
|
||||||
.type = ARM_CP_CONST, .resetvalue = 0 },
|
.type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
{ .name = "JOSCR",
|
{ .name = "JOSCR",
|
||||||
.cp = 14, .crn = 1, .crm = 0, .opc1 = 7, .opc2 = 0,
|
.cp = 14, .crn = 1, .crm = 0, .opc1 = 7, .opc2 = 0,
|
||||||
|
.accessfn = access_joscr_jmcr,
|
||||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
{ .name = "JMCR",
|
{ .name = "JMCR",
|
||||||
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
|
.cp = 14, .crn = 2, .crm = 0, .opc1 = 7, .opc2 = 0,
|
||||||
|
.accessfn = access_joscr_jmcr,
|
||||||
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
.access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 },
|
||||||
REGINFO_SENTINEL
|
REGINFO_SENTINEL
|
||||||
};
|
};
|
||||||
|
|
|
@ -73,6 +73,8 @@ DEF_HELPER_2(v7m_vlldm, void, env, i32)
|
||||||
|
|
||||||
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
|
DEF_HELPER_2(v8m_stackcheck, void, env, i32)
|
||||||
|
|
||||||
|
DEF_HELPER_FLAGS_2(check_bxj_trap, TCG_CALL_NO_WG, void, env, i32)
|
||||||
|
|
||||||
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
|
DEF_HELPER_4(access_check_cp_reg, void, env, ptr, i32, i32)
|
||||||
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
|
DEF_HELPER_3(set_cp_reg, void, env, ptr, i32)
|
||||||
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
|
DEF_HELPER_2(get_cp_reg, i32, env, ptr)
|
||||||
|
|
|
@ -224,6 +224,22 @@ void HELPER(setend)(CPUARMState *env)
|
||||||
arm_rebuild_hflags(env);
|
arm_rebuild_hflags(env);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HELPER(check_bxj_trap)(CPUARMState *env, uint32_t rm)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Only called if in NS EL0 or EL1 for a BXJ for a v7A CPU;
|
||||||
|
* check if HSTR.TJDBX means we need to trap to EL2.
|
||||||
|
*/
|
||||||
|
if (env->cp15.hstr_el2 & HSTR_TJDBX) {
|
||||||
|
/*
|
||||||
|
* We know the condition code check passed, so take the IMPDEF
|
||||||
|
* choice to always report CV=1 COND 0xe
|
||||||
|
*/
|
||||||
|
uint32_t syn = syn_bxjtrap(1, 0xe, rm);
|
||||||
|
raise_exception_ra(env, EXCP_HYP_TRAP, syn, 2, GETPC());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
|
/* Function checks whether WFx (WFI/WFE) instructions are set up to be trapped.
|
||||||
* The function returns the target EL (1-3) if the instruction is to be trapped;
|
* The function returns the target EL (1-3) if the instruction is to be trapped;
|
||||||
|
|
|
@ -36,6 +36,7 @@ enum arm_exception_class {
|
||||||
EC_ADVSIMDFPACCESSTRAP = 0x07,
|
EC_ADVSIMDFPACCESSTRAP = 0x07,
|
||||||
EC_FPIDTRAP = 0x08,
|
EC_FPIDTRAP = 0x08,
|
||||||
EC_PACTRAP = 0x09,
|
EC_PACTRAP = 0x09,
|
||||||
|
EC_BXJTRAP = 0x0a,
|
||||||
EC_CP14RRTTRAP = 0x0c,
|
EC_CP14RRTTRAP = 0x0c,
|
||||||
EC_BTITRAP = 0x0d,
|
EC_BTITRAP = 0x0d,
|
||||||
EC_ILLEGALSTATE = 0x0e,
|
EC_ILLEGALSTATE = 0x0e,
|
||||||
|
@ -215,6 +216,12 @@ static inline uint32_t syn_btitrap(int btype)
|
||||||
return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
|
return (EC_BTITRAP << ARM_EL_EC_SHIFT) | btype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline uint32_t syn_bxjtrap(int cv, int cond, int rm)
|
||||||
|
{
|
||||||
|
return (EC_BXJTRAP << ARM_EL_EC_SHIFT) | ARM_EL_IL |
|
||||||
|
(cv << 24) | (cond << 20) | rm;
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
|
static inline uint32_t syn_insn_abort(int same_el, int ea, int s1ptw, int fsc)
|
||||||
{
|
{
|
||||||
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
|
return (EC_INSNABORT << ARM_EL_EC_SHIFT) | (same_el << ARM_EL_EC_SHIFT)
|
||||||
|
|
|
@ -6440,6 +6440,18 @@ static bool trans_BXJ(DisasContext *s, arg_BXJ *a)
|
||||||
if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
|
if (!ENABLE_ARCH_5J || arm_dc_feature(s, ARM_FEATURE_M)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* v7A allows BXJ to be trapped via HSTR.TJDBX. We don't waste a
|
||||||
|
* TBFLAGS bit on a basically-never-happens case, so call a helper
|
||||||
|
* function to check for the trap and raise the exception if needed
|
||||||
|
* (passing it the register number for the syndrome value).
|
||||||
|
* v8A doesn't have this HSTR bit.
|
||||||
|
*/
|
||||||
|
if (!arm_dc_feature(s, ARM_FEATURE_V8) &&
|
||||||
|
arm_dc_feature(s, ARM_FEATURE_EL2) &&
|
||||||
|
s->current_el < 2 && s->ns) {
|
||||||
|
gen_helper_check_bxj_trap(cpu_env, tcg_constant_i32(a->rm));
|
||||||
|
}
|
||||||
/* Trivial implementation equivalent to bx. */
|
/* Trivial implementation equivalent to bx. */
|
||||||
gen_bx(s, load_reg(s, a->rm));
|
gen_bx(s, load_reg(s, a->rm));
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue