mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-06 01:03:55 -06:00
target/arm: Fold secure and non-secure a-profile mmu indexes
For a-profile aarch64, which does not bank system registers, it takes quite a lot of code to switch between security states. In the process, registers such as TCR_EL{1,2} must be swapped, which in itself requires the flushing of softmmu tlbs. Therefore it doesn't buy us anything to separate tlbs by security state. Retain the distinction between Stage2 and Stage2_S. This will be important as we implement FEAT_RME, and do not wish to add a third set of mmu indexes for Realm state. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20221001162318.153420-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
7aee3cb956
commit
d902ae7558
7 changed files with 85 additions and 203 deletions
|
@ -1754,6 +1754,7 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
/* Begin with base v8.0 state. */
|
||||
uint64_t valid_mask = 0x3fff;
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
uint64_t changed;
|
||||
|
||||
/*
|
||||
* Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always
|
||||
|
@ -1816,7 +1817,22 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
|
||||
/* Clear all-context RES0 bits. */
|
||||
value &= valid_mask;
|
||||
raw_write(env, ri, value);
|
||||
changed = env->cp15.scr_el3 ^ value;
|
||||
env->cp15.scr_el3 = value;
|
||||
|
||||
/*
|
||||
* If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then
|
||||
* we must invalidate all TLBs below EL3.
|
||||
*/
|
||||
if (changed & SCR_NS) {
|
||||
tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 |
|
||||
ARMMMUIdxBit_E20_0 |
|
||||
ARMMMUIdxBit_E10_1 |
|
||||
ARMMMUIdxBit_E20_2 |
|
||||
ARMMMUIdxBit_E10_1_PAN |
|
||||
ARMMMUIdxBit_E20_2_PAN |
|
||||
ARMMMUIdxBit_E2));
|
||||
}
|
||||
}
|
||||
|
||||
static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
|
||||
|
@ -2647,9 +2663,6 @@ 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;
|
||||
|
@ -2662,9 +2675,6 @@ 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;
|
||||
|
@ -3372,7 +3382,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
/* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
|
||||
switch (el) {
|
||||
case 3:
|
||||
mmu_idx = ARMMMUIdx_SE3;
|
||||
mmu_idx = ARMMMUIdx_E3;
|
||||
secure = true;
|
||||
break;
|
||||
case 2:
|
||||
|
@ -3380,10 +3390,9 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
/* fall through */
|
||||
case 1:
|
||||
if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
|
||||
mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN
|
||||
: ARMMMUIdx_Stage1_E1_PAN);
|
||||
mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
|
||||
} else {
|
||||
mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1;
|
||||
mmu_idx = ARMMMUIdx_Stage1_E1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -3394,7 +3403,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
/* stage 1 current state PL0: ATS1CUR, ATS1CUW */
|
||||
switch (el) {
|
||||
case 3:
|
||||
mmu_idx = ARMMMUIdx_SE10_0;
|
||||
mmu_idx = ARMMMUIdx_E10_0;
|
||||
secure = true;
|
||||
break;
|
||||
case 2:
|
||||
|
@ -3402,7 +3411,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
|
|||
mmu_idx = ARMMMUIdx_Stage1_E0;
|
||||
break;
|
||||
case 1:
|
||||
mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0;
|
||||
mmu_idx = ARMMMUIdx_Stage1_E0;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
|
@ -3471,17 +3480,16 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
switch (ri->opc1) {
|
||||
case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
|
||||
if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
|
||||
mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN
|
||||
: ARMMMUIdx_Stage1_E1_PAN);
|
||||
mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
|
||||
} else {
|
||||
mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1;
|
||||
mmu_idx = ARMMMUIdx_Stage1_E1;
|
||||
}
|
||||
break;
|
||||
case 4: /* AT S1E2R, AT S1E2W */
|
||||
mmu_idx = secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2;
|
||||
mmu_idx = ARMMMUIdx_E2;
|
||||
break;
|
||||
case 6: /* AT S1E3R, AT S1E3W */
|
||||
mmu_idx = ARMMMUIdx_SE3;
|
||||
mmu_idx = ARMMMUIdx_E3;
|
||||
secure = true;
|
||||
break;
|
||||
default:
|
||||
|
@ -3489,13 +3497,13 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
}
|
||||
break;
|
||||
case 2: /* AT S1E0R, AT S1E0W */
|
||||
mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0;
|
||||
mmu_idx = ARMMMUIdx_Stage1_E0;
|
||||
break;
|
||||
case 4: /* AT S12E1R, AT S12E1W */
|
||||
mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1;
|
||||
mmu_idx = ARMMMUIdx_E10_1;
|
||||
break;
|
||||
case 6: /* AT S12E0R, AT S12E0W */
|
||||
mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_E10_0;
|
||||
mmu_idx = ARMMMUIdx_E10_0;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
|
@ -3765,11 +3773,6 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
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;
|
||||
}
|
||||
|
||||
tlb_flush_by_mmuidx(env_cpu(env), mask);
|
||||
}
|
||||
raw_write(env, ri, value);
|
||||
|
@ -3789,11 +3792,6 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
uint16_t mask = ARMMMUIdxBit_E10_1 |
|
||||
ARMMMUIdxBit_E10_1_PAN |
|
||||
ARMMMUIdxBit_E10_0;
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
mask >>= ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
tlb_flush_by_mmuidx(cs, mask);
|
||||
raw_write(env, ri, value);
|
||||
}
|
||||
|
@ -4264,11 +4262,6 @@ static int vae1_tlbmask(CPUARMState *env)
|
|||
ARMMMUIdxBit_E10_1_PAN |
|
||||
ARMMMUIdxBit_E10_0;
|
||||
}
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
mask >>= ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
|
@ -4295,10 +4288,6 @@ static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
|
|||
mmu_idx = ARMMMUIdx_E10_0;
|
||||
}
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
mmu_idx &= ~ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
return tlbbits_for_regime(env, mmu_idx, addr);
|
||||
}
|
||||
|
||||
|
@ -4331,30 +4320,17 @@ static int alle1_tlbmask(CPUARMState *env)
|
|||
* stage 2 translations, whereas most other scopes only invalidate
|
||||
* stage 1 translations.
|
||||
*/
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
return ARMMMUIdxBit_SE10_1 |
|
||||
ARMMMUIdxBit_SE10_1_PAN |
|
||||
ARMMMUIdxBit_SE10_0;
|
||||
} else {
|
||||
return ARMMMUIdxBit_E10_1 |
|
||||
ARMMMUIdxBit_E10_1_PAN |
|
||||
ARMMMUIdxBit_E10_0;
|
||||
}
|
||||
return (ARMMMUIdxBit_E10_1 |
|
||||
ARMMMUIdxBit_E10_1_PAN |
|
||||
ARMMMUIdxBit_E10_0);
|
||||
}
|
||||
|
||||
static int e2_tlbmask(CPUARMState *env)
|
||||
{
|
||||
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;
|
||||
}
|
||||
return (ARMMMUIdxBit_E20_0 |
|
||||
ARMMMUIdxBit_E20_2 |
|
||||
ARMMMUIdxBit_E20_2_PAN |
|
||||
ARMMMUIdxBit_E2);
|
||||
}
|
||||
|
||||
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
@ -4381,7 +4357,7 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
ARMCPU *cpu = env_archcpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_SE3);
|
||||
tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3);
|
||||
}
|
||||
|
||||
static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
@ -4407,7 +4383,7 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
|
||||
tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_SE3);
|
||||
tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3);
|
||||
}
|
||||
|
||||
static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
@ -4435,7 +4411,7 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
CPUState *cs = CPU(cpu);
|
||||
uint64_t pageaddr = sextract64(value << 12, 0, 56);
|
||||
|
||||
tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_SE3);
|
||||
tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3);
|
||||
}
|
||||
|
||||
static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
@ -4474,12 +4450,10 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
{
|
||||
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_SE2 : ARMMMUIdx_E2,
|
||||
pageaddr);
|
||||
int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
|
||||
|
||||
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
|
||||
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
|
||||
ARMMMUIdxBit_E2, bits);
|
||||
}
|
||||
|
||||
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
||||
|
@ -4487,10 +4461,10 @@ static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
|
|||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
uint64_t pageaddr = sextract64(value << 12, 0, 56);
|
||||
int bits = tlbbits_for_regime(env, ARMMMUIdx_SE3, pageaddr);
|
||||
int bits = tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr);
|
||||
|
||||
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
|
||||
ARMMMUIdxBit_SE3, bits);
|
||||
ARMMMUIdxBit_E3, bits);
|
||||
}
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
|
@ -4596,8 +4570,7 @@ static void tlbi_aa64_rvae1is_write(CPUARMState *env,
|
|||
|
||||
static int vae2_tlbmask(CPUARMState *env)
|
||||
{
|
||||
return (arm_is_secure_below_el3(env)
|
||||
? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2);
|
||||
return ARMMMUIdxBit_E2;
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae2_write(CPUARMState *env,
|
||||
|
@ -4643,8 +4616,7 @@ static void tlbi_aa64_rvae3_write(CPUARMState *env,
|
|||
* flush-last-level-only.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, ARMMMUIdxBit_SE3,
|
||||
tlb_force_broadcast(env));
|
||||
do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env));
|
||||
}
|
||||
|
||||
static void tlbi_aa64_rvae3is_write(CPUARMState *env,
|
||||
|
@ -4658,7 +4630,7 @@ static void tlbi_aa64_rvae3is_write(CPUARMState *env,
|
|||
* flush-last-level-only or inner/outer specific flushes.
|
||||
*/
|
||||
|
||||
do_rvae_write(env, value, ARMMMUIdxBit_SE3, true);
|
||||
do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -10271,8 +10243,7 @@ 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 || mmu_idx == ARMMMUIdx_SE20_0)
|
||||
? 2 : 1;
|
||||
el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
|
||||
}
|
||||
return env->cp15.sctlr_el[el];
|
||||
}
|
||||
|
@ -10816,22 +10787,15 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
|
|||
switch (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:
|
||||
case ARMMMUIdx_SE10_1:
|
||||
case ARMMMUIdx_SE10_1_PAN:
|
||||
return 1;
|
||||
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:
|
||||
case ARMMMUIdx_E3:
|
||||
return 3;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
|
@ -10884,15 +10848,11 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
|
|||
}
|
||||
break;
|
||||
case 3:
|
||||
return ARMMMUIdx_SE3;
|
||||
return ARMMMUIdx_E3;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if (arm_is_secure_below_el3(env)) {
|
||||
idx &= ~ARM_MMU_IDX_A_NS;
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
|
@ -11095,15 +11055,11 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
|
|||
switch (mmu_idx) {
|
||||
case ARMMMUIdx_E10_1:
|
||||
case ARMMMUIdx_E10_1_PAN:
|
||||
case ARMMMUIdx_SE10_1:
|
||||
case ARMMMUIdx_SE10_1_PAN:
|
||||
/* TODO: ARMv8.3-NV */
|
||||
DP_TBFLAG_A64(flags, UNPRIV, 1);
|
||||
break;
|
||||
case ARMMMUIdx_E20_2:
|
||||
case ARMMMUIdx_E20_2_PAN:
|
||||
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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue