target/arm: Update get_a64_user_mem_index for VHE

The EL2&0 translation regime is affected by Load Register (unpriv).

The code structure used here will facilitate later changes in this
area for implementing UAO and NV.

Backports commit cc28fc30e333dc2f20ebfde54444697e26cd8f6d from qemu
This commit is contained in:
Richard Henderson 2020-03-21 16:31:36 -04:00 committed by Lioncash
parent 76ca1cd732
commit 8f1201e392
4 changed files with 57 additions and 20 deletions

View file

@ -3096,10 +3096,10 @@ typedef ARMCPU ArchCPU;
* | | | TBFLAG_A32 | |
* | | +-----+----------+ TBFLAG_AM32 |
* | TBFLAG_ANY | |TBFLAG_M32| |
* | | +-------------------------|
* | | | TBFLAG_A64 |
* +--------------+-----------+-------------------------+
* 31 20 14 0
* | | +-+----------+--------------|
* | | | TBFLAG_A64 |
* +--------------+---------+---------------------------+
* 31 20 15 0
*
*/
FIELD(TBFLAG_ANY, AARCH64_STATE, 31, 1)
@ -3163,6 +3163,7 @@ FIELD(TBFLAG_A64, PAUTH_ACTIVE, 8, 1)
FIELD(TBFLAG_A64, BT, 9, 1)
FIELD(TBFLAG_A64, BTYPE, 10, 2)
FIELD(TBFLAG_A64, TBID, 12, 2)
FIELD(TBFLAG_A64, UNPRIV, 14, 1)
static inline bool bswap_code(bool sctlr_b)
{

View file

@ -11810,6 +11810,28 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
}
flags = FIELD_DP32(flags, TBFLAG_A64, BTYPE, env->btype);
}
/* Compute the condition for using AccType_UNPRIV for LDTR et al. */
/* TODO: ARMv8.2-UAO */
switch (mmu_idx) {
case ARMMMUIdx_E10_1:
case ARMMMUIdx_SE10_1:
/* TODO: ARMv8.3-NV */
flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
break;
case ARMMMUIdx_E20_2:
/* TODO: ARMv8.4-SecEL2 */
/*
* Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
* gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
*/
if (env->cp15.hcr_el2 & HCR_TGE) {
flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
}
break;
default:
break;
}
} else {
*pc = env->regs[15];
flags = FIELD_DP32(flags, TBFLAG_AM32, THUMB, env->thumb);

View file

@ -106,25 +106,36 @@ void a64_translate_init(struct uc_struct *uc)
offsetof(CPUARMState, exclusive_high), "exclusive_high");
}
static inline int get_a64_user_mem_index(DisasContext *s)
/*
* Return the core mmu_idx to use for A64 "unprivileged load/store" insns
*/
static int get_a64_user_mem_index(DisasContext *s)
{
/* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
* if EL1, access as if EL0; otherwise access at current EL
/*
* If AccType_UNPRIV is not used, the insn uses AccType_NORMAL,
* which is the usual mmu_idx for this cpu state.
*/
ARMMMUIdx useridx;
ARMMMUIdx useridx = s->mmu_idx;
switch (s->mmu_idx) {
case ARMMMUIdx_E10_1:
useridx = ARMMMUIdx_E10_0;
break;
case ARMMMUIdx_SE10_1:
useridx = ARMMMUIdx_SE10_0;
break;
case ARMMMUIdx_Stage2:
g_assert_not_reached();
default:
useridx = s->mmu_idx;
break;
if (s->unpriv) {
/*
* We have pre-computed the condition for AccType_UNPRIV.
* Therefore we should never get here with a mmu_idx for
* which we do not know the corresponding user mmu_idx.
*/
switch (useridx) {
case ARMMMUIdx_E10_1:
useridx = ARMMMUIdx_E10_0;
break;
case ARMMMUIdx_E20_2:
useridx = ARMMMUIdx_E20_0;
break;
case ARMMMUIdx_SE10_1:
useridx = ARMMMUIdx_SE10_0;
break;
default:
g_assert_not_reached();
}
}
return arm_to_core_mmu_idx(useridx);
}
@ -14509,6 +14520,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
dc->unpriv = FIELD_EX32(tb_flags, TBFLAG_A64, UNPRIV);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = arm_cpu->cp_regs;

View file

@ -72,6 +72,8 @@ typedef struct DisasContext {
* ie A64 LDX*, LDAX*, A32/T32 LDREX*, LDAEX*.
*/
bool is_ldex;
/* True if AccType_UNPRIV should be used for LDTR et al */
bool unpriv;
/* True if v8.3-PAuth is active. */
bool pauth_active;
/* Bottom two bits of XScale c15_cpar coprocessor access control reg */