mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-03 17:05:47 +00:00
target/arm: add MMU stage 1 for Secure EL2
This adds the MMU indices for EL2 stage 1 in secure state. To keep code contained, which is largelly identical between secure and non-secure modes, the MMU indices are reassigned. The new assignments provide a systematic pattern with a non-secure bit. Backports b6ad6062f1e55bd5b9407ce89e55e3a08b83827c
This commit is contained in:
parent
fbdcef3ca5
commit
edd5f021e6
|
@ -2928,6 +2928,9 @@ bool write_cpustate_to_list(ARMCPU *cpu);
|
|||
#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
|
||||
#define ARM_MMU_IDX_M 0x40 /* M profile */
|
||||
|
||||
/* Meanings of the bits for A profile mmu idx values */
|
||||
#define ARM_MMU_IDX_A_NS 0x8
|
||||
|
||||
/* Meanings of the bits for M profile mmu idx values */
|
||||
#define ARM_MMU_IDX_M_PRIV 0x1
|
||||
#define ARM_MMU_IDX_M_NEGPRI 0x2
|
||||
|
@ -2941,20 +2944,22 @@ typedef enum ARMMMUIdx {
|
|||
/*
|
||||
* A-profile.
|
||||
*/
|
||||
ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE10_0 = 0 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE20_0 = 1 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE10_1 = 2 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE20_2 = 3 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE10_1_PAN = 4 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE20_2_PAN = 5 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE2 = 6 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A,
|
||||
|
||||
ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
|
||||
|
||||
ARMMMUIdx_E2 = 4 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_E20_2 = 5 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_E20_2_PAN = 6 | ARM_MMU_IDX_A,
|
||||
|
||||
ARMMMUIdx_SE10_0 = 7 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE10_1 = 8 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A,
|
||||
ARMMMUIdx_E10_0 = ARMMMUIdx_SE10_0 | ARM_MMU_IDX_A_NS,
|
||||
ARMMMUIdx_E20_0 = ARMMMUIdx_SE20_0 | ARM_MMU_IDX_A_NS,
|
||||
ARMMMUIdx_E10_1 = ARMMMUIdx_SE10_1 | ARM_MMU_IDX_A_NS,
|
||||
ARMMMUIdx_E20_2 = ARMMMUIdx_SE20_2 | ARM_MMU_IDX_A_NS,
|
||||
ARMMMUIdx_E10_1_PAN = ARMMMUIdx_SE10_1_PAN | ARM_MMU_IDX_A_NS,
|
||||
ARMMMUIdx_E20_2_PAN = ARMMMUIdx_SE20_2_PAN | ARM_MMU_IDX_A_NS,
|
||||
ARMMMUIdx_E2 = ARMMMUIdx_SE2 | ARM_MMU_IDX_A_NS,
|
||||
|
||||
/*
|
||||
* These are not allocated TLBs and are used only for AT system
|
||||
|
@ -3001,8 +3006,12 @@ typedef enum ARMMMUIdxBit {
|
|||
TO_CORE_BIT(E20_2),
|
||||
TO_CORE_BIT(E20_2_PAN),
|
||||
TO_CORE_BIT(SE10_0),
|
||||
TO_CORE_BIT(SE20_0),
|
||||
TO_CORE_BIT(SE10_1),
|
||||
TO_CORE_BIT(SE20_2),
|
||||
TO_CORE_BIT(SE10_1_PAN),
|
||||
TO_CORE_BIT(SE20_2_PAN),
|
||||
TO_CORE_BIT(SE2),
|
||||
TO_CORE_BIT(SE3),
|
||||
|
||||
TO_CORE_BIT(MUser),
|
||||
|
|
|
@ -2563,6 +2563,9 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
|
|||
case ARMMMUIdx_E20_0:
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
case ARMMMUIdx_SE20_0:
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
return GTIMER_HYP;
|
||||
default:
|
||||
return GTIMER_PHYS;
|
||||
|
@ -2575,6 +2578,9 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
|
|||
case ARMMMUIdx_E20_0:
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
case ARMMMUIdx_SE20_0:
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
return GTIMER_HYPVIRT;
|
||||
default:
|
||||
return GTIMER_VIRT;
|
||||
|
@ -3269,7 +3275,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
mmu_idx = ARMMMUIdx_SE3;
|
||||
break;
|
||||
case 2:
|
||||
g_assert(!secure); /* TODO: ARMv8.4-SecEL2 */
|
||||
g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */
|
||||
/* fall through */
|
||||
case 1:
|
||||
if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
|
||||
|
@ -3365,7 +3371,7 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
}
|
||||
break;
|
||||
case 4: /* AT S1E2R, AT S1E2W */
|
||||
mmu_idx = ARMMMUIdx_E2;
|
||||
mmu_idx = secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2;
|
||||
break;
|
||||
case 6: /* AT S1E3R, AT S1E3W */
|
||||
mmu_idx = ARMMMUIdx_SE3;
|
||||
|
@ -3680,10 +3686,15 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
*/
|
||||
if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
|
||||
(arm_hcr_el2_eff(env) & HCR_E2H)) {
|
||||
tlb_flush_by_mmuidx(env_cpu(env),
|
||||
ARMMMUIdxBit_E20_2 |
|
||||
uint16_t mask = ARMMMUIdxBit_E20_2 |
|
||||
ARMMMUIdxBit_E20_2_PAN |
|
||||
ARMMMUIdxBit_E20_0);
|
||||
ARMMMUIdxBit_E20_0;
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
mask >>= ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
tlb_flush_by_mmuidx(env_cpu(env), mask);
|
||||
}
|
||||
raw_write(env, ri, value);
|
||||
}
|
||||
|
@ -4134,9 +4145,15 @@ static int vae1_tlbmask(CPUARMState *env)
|
|||
uint64_t hcr = arm_hcr_el2_eff(env);
|
||||
|
||||
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
|
||||
return ARMMMUIdxBit_E20_2 |
|
||||
uint16_t mask = ARMMMUIdxBit_E20_2 |
|
||||
ARMMMUIdxBit_E20_2_PAN |
|
||||
ARMMMUIdxBit_E20_0;
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
mask >>= ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
return mask;
|
||||
} else if (arm_is_secure_below_el3(env)) {
|
||||
return ARMMMUIdxBit_SE10_1 |
|
||||
ARMMMUIdxBit_SE10_1_PAN |
|
||||
|
@ -4195,11 +4212,17 @@ static int alle1_tlbmask(CPUARMState *env)
|
|||
|
||||
static int e2_tlbmask(CPUARMState *env)
|
||||
{
|
||||
/* TODO: ARMv8.4-SecEL2 */
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
return ARMMMUIdxBit_SE20_0 |
|
||||
ARMMMUIdxBit_SE20_2 |
|
||||
ARMMMUIdxBit_SE20_2_PAN |
|
||||
ARMMMUIdxBit_SE2;
|
||||
} else {
|
||||
return ARMMMUIdxBit_E20_0 |
|
||||
ARMMMUIdxBit_E20_2 |
|
||||
ARMMMUIdxBit_E20_2_PAN |
|
||||
ARMMMUIdxBit_E2;
|
||||
}
|
||||
}
|
||||
|
||||
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
@ -4332,9 +4355,12 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
#if 0
|
||||
CPUState *cs = env_cpu(env);
|
||||
uint64_t pageaddr = sextract64(value << 12, 0, 56);
|
||||
bool secure = arm_is_secure_below_el3(env);
|
||||
int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2;
|
||||
int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2,
|
||||
pageaddr);
|
||||
|
||||
tlb_flush_page_by_mmuidx_all_cpus_synced(cs, pageaddr,
|
||||
ARMMMUIdxBit_E2);
|
||||
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -9669,7 +9695,8 @@ uint64_t arm_sctlr(CPUARMState *env, int el)
|
|||
/* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */
|
||||
if (el == 0) {
|
||||
ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
|
||||
el = (mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1);
|
||||
el = (mmu_idx == ARMMMUIdx_E20_0 || mmu_idx == ARMMMUIdx_SE20_0)
|
||||
? 2 : 1;
|
||||
}
|
||||
return env->cp15.sctlr_el[el];
|
||||
}
|
||||
|
@ -9802,6 +9829,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||
switch (mmu_idx) {
|
||||
case ARMMMUIdx_SE10_0:
|
||||
case ARMMMUIdx_E20_0:
|
||||
case ARMMMUIdx_SE20_0:
|
||||
case ARMMMUIdx_Stage1_E0:
|
||||
case ARMMMUIdx_MUser:
|
||||
case ARMMMUIdx_MSUser:
|
||||
|
@ -12369,6 +12397,7 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
|
|||
case ARMMMUIdx_E10_0:
|
||||
case ARMMMUIdx_E20_0:
|
||||
case ARMMMUIdx_SE10_0:
|
||||
case ARMMMUIdx_SE20_0:
|
||||
return 0;
|
||||
case ARMMMUIdx_E10_1:
|
||||
case ARMMMUIdx_E10_1_PAN:
|
||||
|
@ -12378,6 +12407,9 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
|
|||
case ARMMMUIdx_E2:
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
case ARMMMUIdx_SE2:
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
return 2;
|
||||
case ARMMMUIdx_SE3:
|
||||
return 3;
|
||||
|
@ -12397,6 +12429,9 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate)
|
|||
|
||||
ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
|
||||
{
|
||||
ARMMMUIdx idx;
|
||||
uint64_t hcr;
|
||||
|
||||
if (arm_feature(env, ARM_FEATURE_M)) {
|
||||
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
|
||||
}
|
||||
|
@ -12404,40 +12439,43 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
|
|||
/* See ARM pseudo-function ELIsInHost. */
|
||||
switch (el) {
|
||||
case 0:
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
return ARMMMUIdx_SE10_0;
|
||||
hcr = arm_hcr_el2_eff(env);
|
||||
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
|
||||
idx = ARMMMUIdx_E20_0;
|
||||
} else {
|
||||
idx = ARMMMUIdx_E10_0;
|
||||
}
|
||||
if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)
|
||||
&& arm_el_is_aa64(env, 2)) {
|
||||
return ARMMMUIdx_E20_0;
|
||||
}
|
||||
return ARMMMUIdx_E10_0;
|
||||
break;
|
||||
case 1:
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
if (env->pstate & PSTATE_PAN) {
|
||||
return ARMMMUIdx_SE10_1_PAN;
|
||||
idx = ARMMMUIdx_E10_1_PAN;
|
||||
} else {
|
||||
idx = ARMMMUIdx_E10_1;
|
||||
}
|
||||
return ARMMMUIdx_SE10_1;
|
||||
}
|
||||
if (env->pstate & PSTATE_PAN) {
|
||||
return ARMMMUIdx_E10_1_PAN;
|
||||
}
|
||||
return ARMMMUIdx_E10_1;
|
||||
break;
|
||||
case 2:
|
||||
/* TODO: ARMv8.4-SecEL2 */
|
||||
/* Note that TGE does not apply at EL2. */
|
||||
if ((env->cp15.hcr_el2 & HCR_E2H) && arm_el_is_aa64(env, 2)) {
|
||||
if (arm_hcr_el2_eff(env) & HCR_E2H) {
|
||||
if (env->pstate & PSTATE_PAN) {
|
||||
return ARMMMUIdx_E20_2_PAN;
|
||||
idx = ARMMMUIdx_E20_2_PAN;
|
||||
} else {
|
||||
idx = ARMMMUIdx_E20_2;
|
||||
}
|
||||
return ARMMMUIdx_E20_2;
|
||||
} else {
|
||||
idx = ARMMMUIdx_E2;
|
||||
}
|
||||
return ARMMMUIdx_E2;
|
||||
break;
|
||||
case 3:
|
||||
return ARMMMUIdx_SE3;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
idx &= ~ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
ARMMMUIdx arm_mmu_idx(CPUARMState *env)
|
||||
|
@ -12534,7 +12572,8 @@ void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc,
|
|||
break;
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
/* TODO: ARMv8.4-SecEL2 */
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
/*
|
||||
* Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
|
||||
* gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.
|
||||
|
|
|
@ -862,6 +862,9 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
|
|||
case ARMMMUIdx_SE10_0:
|
||||
case ARMMMUIdx_SE10_1:
|
||||
case ARMMMUIdx_SE10_1_PAN:
|
||||
case ARMMMUIdx_SE20_0:
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -892,6 +895,10 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||
case ARMMMUIdx_SE10_0:
|
||||
case ARMMMUIdx_SE10_1:
|
||||
case ARMMMUIdx_SE10_1_PAN:
|
||||
case ARMMMUIdx_SE20_0:
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
case ARMMMUIdx_SE2:
|
||||
case ARMMMUIdx_MSPrivNegPri:
|
||||
case ARMMMUIdx_MSUserNegPri:
|
||||
case ARMMMUIdx_MSPriv:
|
||||
|
@ -909,6 +916,7 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||
case ARMMMUIdx_E10_1_PAN:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
case ARMMMUIdx_SE10_1_PAN:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
|
@ -919,10 +927,14 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
|
|||
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||
{
|
||||
switch (mmu_idx) {
|
||||
case ARMMMUIdx_SE20_0:
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
case ARMMMUIdx_E20_0:
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
case ARMMMUIdx_Stage2:
|
||||
case ARMMMUIdx_SE2:
|
||||
case ARMMMUIdx_E2:
|
||||
return 2;
|
||||
case ARMMMUIdx_SE3:
|
||||
|
|
|
@ -119,6 +119,10 @@ static int get_a64_user_mem_index(DisasContext *s)
|
|||
case ARMMMUIdx_SE10_1_PAN:
|
||||
useridx = ARMMMUIdx_SE10_0;
|
||||
break;
|
||||
case ARMMMUIdx_SE20_2:
|
||||
case ARMMMUIdx_SE20_2_PAN:
|
||||
useridx = ARMMMUIdx_SE20_0;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue