target-arm: Infrastucture changes to enable handling of tagged address loading into PC

When capturing the current CPU state for the TB, extract the TBI0 and TBI1
values from the correct TCR for the current EL and then add them to the TB
flags field.

Then, at the start of code generation for the block, copy the TBI fields
into the DisasContext structure.

Backports commit 86fb3fa4ed5873b021a362ea26a021f4aeab1bb4 from qemu
This commit is contained in:
Thomas Hanson 2018-02-26 07:58:04 -05:00 committed by Lioncash
parent be6e25bcc7
commit 2af4ca54e9
No known key found for this signature in database
GPG key ID: 4E3C3CC1031BA9C7
9 changed files with 113 additions and 2 deletions

View file

@ -3157,6 +3157,8 @@
#define arm64_reg_reset arm64_reg_reset_aarch64
#define arm64_reg_write arm64_reg_write_aarch64
#define arm64_release arm64_release_aarch64
#define arm_regime_tbi0 arm_regime_tbi0_aarch64
#define arm_regime_tbi1 arm_regime_tbi1_aarch64
#define arm_register_el_change_hook arm_register_el_change_hook_aarch64
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64
#define helper_cls32 helper_cls32_aarch64

View file

@ -3157,6 +3157,8 @@
#define arm64_reg_reset arm64_reg_reset_aarch64eb
#define arm64_reg_write arm64_reg_write_aarch64eb
#define arm64_release arm64_release_aarch64eb
#define arm_regime_tbi0 arm_regime_tbi0_aarch64eb
#define arm_regime_tbi1 arm_regime_tbi1_aarch64eb
#define arm_register_el_change_hook arm_register_el_change_hook_aarch64eb
#define gen_a64_set_pc_im gen_a64_set_pc_im_aarch64eb
#define helper_cls32 helper_cls32_aarch64eb

View file

@ -3151,5 +3151,7 @@
#define xscale_cp_reginfo xscale_cp_reginfo_arm
#define xscale_cpar_write xscale_cpar_write_arm
#define ARM_REGS_STORAGE_SIZE ARM_REGS_STORAGE_SIZE_arm
#define arm_regime_tbi0 arm_regime_tbi0_arm
#define arm_regime_tbi1 arm_regime_tbi1_arm
#define arm_register_el_change_hook arm_register_el_change_hook_arm
#endif

View file

@ -3151,5 +3151,7 @@
#define xscale_cp_reginfo xscale_cp_reginfo_armeb
#define xscale_cpar_write xscale_cpar_write_armeb
#define ARM_REGS_STORAGE_SIZE ARM_REGS_STORAGE_SIZE_armeb
#define arm_regime_tbi0 arm_regime_tbi0_armeb
#define arm_regime_tbi1 arm_regime_tbi1_armeb
#define arm_register_el_change_hook arm_register_el_change_hook_armeb
#endif

View file

@ -3160,6 +3160,8 @@ symbols = (
arm_symbols = (
'ARM_REGS_STORAGE_SIZE',
'arm_regime_tbi0',
'arm_regime_tbi1',
'arm_register_el_change_hook',
)
@ -3171,6 +3173,8 @@ aarch64_symbols = (
'arm64_reg_reset',
'arm64_reg_write',
'arm64_release',
'arm_regime_tbi0',
'arm_regime_tbi1',
'arm_register_el_change_hook',
'gen_a64_set_pc_im',
'helper_cls32',

View file

@ -2157,7 +2157,11 @@ static inline bool arm_singlestep_active(CPUARMState *env)
#define ARM_TBFLAG_BE_DATA_SHIFT 20
#define ARM_TBFLAG_BE_DATA_MASK (1 << ARM_TBFLAG_BE_DATA_SHIFT)
/* Bit usage when in AArch64 state: currently we have no A64 specific bits */
/* Bit usage when in AArch64 state */
#define ARM_TBFLAG_TBI0_SHIFT 0 /* TBI0 for EL0/1 or TBI for EL2/3 */
#define ARM_TBFLAG_TBI0_MASK (0x1ull << ARM_TBFLAG_TBI0_SHIFT)
#define ARM_TBFLAG_TBI1_SHIFT 1 /* TBI1 for EL0/1 */
#define ARM_TBFLAG_TBI1_MASK (0x1ull << ARM_TBFLAG_TBI1_SHIFT)
/* some convenience accessor macros */
#define ARM_TBFLAG_AARCH64_STATE(F) \
@ -2188,6 +2192,10 @@ static inline bool arm_singlestep_active(CPUARMState *env)
(((F) & ARM_TBFLAG_NS_MASK) >> ARM_TBFLAG_NS_SHIFT)
#define ARM_TBFLAG_BE_DATA(F) \
(((F) & ARM_TBFLAG_BE_DATA_MASK) >> ARM_TBFLAG_BE_DATA_SHIFT)
#define ARM_TBFLAG_TBI0(F) \
(((F) & ARM_TBFLAG_TBI0_MASK) >> ARM_TBFLAG_TBI0_SHIFT)
#define ARM_TBFLAG_TBI1(F) \
(((F) & ARM_TBFLAG_TBI1_MASK) >> ARM_TBFLAG_TBI1_SHIFT)
static inline bool bswap_code(bool sctlr_b)
{
@ -2321,12 +2329,52 @@ static inline bool arm_cpu_data_is_big_endian(CPUARMState *env)
return (env->cp15.sctlr_el[cur_el] & SCTLR_EE) != 0;
}
#ifndef CONFIG_USER_ONLY
/**
* arm_regime_tbi0:
* @env: CPUARMState
* @mmu_idx: MMU index indicating required translation regime
*
* Extracts the TBI0 value from the appropriate TCR for the current EL
*
* Returns: the TBI0 value.
*/
uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx);
/**
* arm_regime_tbi1:
* @env: CPUARMState
* @mmu_idx: MMU index indicating required translation regime
*
* Extracts the TBI1 value from the appropriate TCR for the current EL
*
* Returns: the TBI1 value.
*/
uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx);
#else
/* We can't handle tagged addresses properly in user-only mode */
static inline uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx)
{
return 0;
}
static inline uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
{
return 0;
}
#endif
static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *flags)
{
ARMMMUIdx mmu_idx = cpu_mmu_index(env, false);
if (is_a64(env)) {
*pc = env->pc;
*flags = ARM_TBFLAG_AARCH64_STATE_MASK;
/* Get control bits for tagged addresses */
*flags |= (arm_regime_tbi0(env, mmu_idx) << ARM_TBFLAG_TBI0_SHIFT);
*flags |= (arm_regime_tbi1(env, mmu_idx) << ARM_TBFLAG_TBI1_SHIFT);
} else {
*pc = env->regs[15];
*flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT)
@ -2345,7 +2393,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
<< ARM_TBFLAG_XSCALE_CPAR_SHIFT);
}
*flags |= (cpu_mmu_index(env, false) << ARM_TBFLAG_MMUIDX_SHIFT);
*flags |= (mmu_idx << ARM_TBFLAG_MMUIDX_SHIFT);
/* The SS_ACTIVE and PSTATE_SS bits correspond to the state machine
* states defined in the ARM ARM for software singlestep:
* SS_ACTIVE PSTATE.SS State

View file

@ -5969,6 +5969,52 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
}
/* Returns TBI0 value for current regime el */
uint32_t arm_regime_tbi0(CPUARMState *env, ARMMMUIdx mmu_idx)
{
TCR *tcr;
uint32_t el;
/* For EL0 and EL1, TBI is controlled by stage 1's TCR, so convert
* a stage 1+2 mmu index into the appropriate stage 1 mmu index.
*/
if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
mmu_idx += ARMMMUIdx_S1NSE0;
}
tcr = regime_tcr(env, mmu_idx);
el = regime_el(env, mmu_idx);
if (el > 1) {
return extract64(tcr->raw_tcr, 20, 1);
} else {
return extract64(tcr->raw_tcr, 37, 1);
}
}
/* Returns TBI1 value for current regime el */
uint32_t arm_regime_tbi1(CPUARMState *env, ARMMMUIdx mmu_idx)
{
TCR *tcr;
uint32_t el;
/* For EL0 and EL1, TBI is controlled by stage 1's TCR, so convert
* a stage 1+2 mmu index into the appropriate stage 1 mmu index.
*/
if (mmu_idx == ARMMMUIdx_S12NSE0 || mmu_idx == ARMMMUIdx_S12NSE1) {
mmu_idx += ARMMMUIdx_S1NSE0;
}
tcr = regime_tcr(env, mmu_idx);
el = regime_el(env, mmu_idx);
if (el > 1) {
return 0;
} else {
return extract64(tcr->raw_tcr, 38, 1);
}
}
/* Return the TTBR associated with this translation regime */
static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx,
int ttbrn)

View file

@ -11393,6 +11393,8 @@ void gen_intermediate_code_a64(ARMCPU *cpu, TranslationBlock *tb)
dc->condexec_mask = 0;
dc->condexec_cond = 0;
dc->mmu_idx = ARM_TBFLAG_MMUIDX(tb->flags);
dc->tbi0 = ARM_TBFLAG_TBI0(tb->flags);
dc->tbi1 = ARM_TBFLAG_TBI1(tb->flags);
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
#if !defined(CONFIG_USER_ONLY)
dc->user = (dc->current_el == 0);

View file

@ -22,6 +22,8 @@ typedef struct DisasContext {
int user;
#endif
ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
bool tbi0; /* TBI0 for EL0/1 or TBI for EL2/3 */
bool tbi1; /* TBI1 for EL0/1, not used for EL2/3 */
bool ns; /* Use non-secure CPREG bank on access */
int fp_excp_el; /* FP exception EL or 0 if enabled */
/* Flag indicating that exceptions from secure mode are routed to EL3. */