* [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 11:46 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
` (12 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee, Philippe Mathieu-Daudé
Use a common predicate for querying stage1-ness.
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Rename from arm_mmu_idx_is_stage1 to arm_mmu_idx_is_stage1_of_2
---
target/arm/internals.h | 18 ++++++++++++++++++
target/arm/helper.c | 8 +++-----
2 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6d4a942bde..1f8ee5f573 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1034,6 +1034,24 @@ static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
#endif
+/**
+ * arm_mmu_idx_is_stage1_of_2:
+ * @mmu_idx: The ARMMMUIdx to test
+ *
+ * Return true if @mmu_idx is a NOTLB mmu_idx that is the
+ * first stage of a two stage regime.
+ */
+static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
+{
+ switch (mmu_idx) {
+ case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E1:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
* Parameters of a given virtual address, as extracted from the
* translation control register (TCR) for a given regime.
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 70b10428c5..852fd71dcc 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3261,8 +3261,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
bool take_exc = false;
if (fi.s1ptw && current_el == 1 && !arm_is_secure(env)
- && (mmu_idx == ARMMMUIdx_Stage1_E1 ||
- mmu_idx == ARMMMUIdx_Stage1_E0)) {
+ && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
/*
* Synchronous stage 2 fault on an access made as part of the
* translation table walk for AT S1E0* or AT S1E1* insn
@@ -9294,8 +9293,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
}
}
- if ((env->cp15.hcr_el2 & HCR_DC) &&
- (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
+ if ((env->cp15.hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
/* HCR.DC means SCTLR_EL1.M behaves as 0 */
return true;
}
@@ -9604,7 +9602,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
hwaddr addr, MemTxAttrs txattrs,
ARMMMUFaultInfo *fi)
{
- if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
+ if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
!regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
target_ulong s2size;
hwaddr s2pa;
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2
2020-02-02 1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
@ 2020-02-03 11:46 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 11:46 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, Philippe Mathieu-Daudé, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> Use a common predicate for querying stage1-ness.
>
> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> v2: Rename from arm_mmu_idx_is_stage1 to arm_mmu_idx_is_stage1_of_2
> ---
> target/arm/internals.h | 18 ++++++++++++++++++
> target/arm/helper.c | 8 +++-----
> 2 files changed, 21 insertions(+), 5 deletions(-)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 6d4a942bde..1f8ee5f573 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -1034,6 +1034,24 @@ static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
> ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
> #endif
>
> +/**
> + * arm_mmu_idx_is_stage1_of_2:
> + * @mmu_idx: The ARMMMUIdx to test
> + *
> + * Return true if @mmu_idx is a NOTLB mmu_idx that is the
> + * first stage of a two stage regime.
> + */
> +static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
> +{
> + switch (mmu_idx) {
> + case ARMMMUIdx_Stage1_E0:
> + case ARMMMUIdx_Stage1_E1:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> /*
> * Parameters of a given virtual address, as extracted from the
> * translation control register (TCR) for a given regime.
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 70b10428c5..852fd71dcc 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -3261,8 +3261,7 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
> bool take_exc = false;
>
> if (fi.s1ptw && current_el == 1 && !arm_is_secure(env)
> - && (mmu_idx == ARMMMUIdx_Stage1_E1 ||
> - mmu_idx == ARMMMUIdx_Stage1_E0)) {
> + && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
> /*
> * Synchronous stage 2 fault on an access made as part of the
> * translation table walk for AT S1E0* or AT S1E1* insn
> @@ -9294,8 +9293,7 @@ static inline bool regime_translation_disabled(CPUARMState *env,
> }
> }
>
> - if ((env->cp15.hcr_el2 & HCR_DC) &&
> - (mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1)) {
> + if ((env->cp15.hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
> /* HCR.DC means SCTLR_EL1.M behaves as 0 */
> return true;
> }
> @@ -9604,7 +9602,7 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
> hwaddr addr, MemTxAttrs txattrs,
> ARMMMUFaultInfo *fi)
> {
> - if ((mmu_idx == ARMMMUIdx_Stage1_E0 || mmu_idx == ARMMMUIdx_Stage1_E1) &&
> + if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
> !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
> target_ulong s2size;
> hwaddr s2pa;
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
2020-02-02 1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 11:54 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
` (11 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
To implement PAN, we will want to swap, for short periods
of time, to a different privileged mmu_idx. In addition,
we cannot do this with flushing alone, because the AT*
instructions have both PAN and PAN-less versions.
Add the ARMMMUIdx*_PAN constants where necessary next to
the corresponding ARMMMUIdx* constant.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu-param.h | 2 +-
target/arm/cpu.h | 33 ++++++++++++++-------
target/arm/internals.h | 9 ++++++
target/arm/helper.c | 60 +++++++++++++++++++++++++++++++-------
target/arm/translate-a64.c | 3 ++
target/arm/translate.c | 2 ++
6 files changed, 87 insertions(+), 22 deletions(-)
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 18ac562346..d593b60b28 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -29,6 +29,6 @@
# define TARGET_PAGE_BITS_MIN 10
#endif
-#define NB_MMU_MODES 9
+#define NB_MMU_MODES 12
#endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 0b3036c484..c63bceaaa5 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -2751,20 +2751,24 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
* 5. we want to be able to use the TLB for accesses done as part of a
* stage1 page table walk, rather than having to walk the stage2 page
* table over and over.
+ * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
+ * Never (PAN) bit within PSTATE.
*
* This gives us the following list of cases:
*
* NS EL0 EL1&0 stage 1+2 (aka NS PL0)
* NS EL1 EL1&0 stage 1+2 (aka NS PL1)
+ * NS EL1 EL1&0 stage 1+2 +PAN
* NS EL0 EL2&0
- * NS EL2 EL2&0
+ * NS EL2 EL2&0 +PAN
* NS EL2 (aka NS PL2)
* S EL0 EL1&0 (aka S PL0)
* S EL1 EL1&0 (not used if EL3 is 32 bit)
+ * S EL1 EL1&0 +PAN
* S EL3 (aka S PL1)
* NS EL1&0 stage 2
*
- * for a total of 9 different mmu_idx.
+ * for a total of 12 different mmu_idx.
*
* R profile CPUs have an MPU, but can use the same set of MMU indexes
* as A profile. They only need to distinguish NS EL0 and NS EL1 (and
@@ -2819,19 +2823,22 @@ typedef enum ARMMMUIdx {
/*
* A-profile.
*/
- ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
- ARMMMUIdx_E2 = 3 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2 = 4 | 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 = 5 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE3 = 7 | 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_Stage2 = 8 | ARM_MMU_IDX_A,
+ ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
/*
* These are not allocated TLBs and are used only for AT system
@@ -2839,6 +2846,7 @@ typedef enum ARMMMUIdx {
*/
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
/*
* M-profile.
@@ -2864,10 +2872,13 @@ typedef enum ARMMMUIdxBit {
TO_CORE_BIT(E10_0),
TO_CORE_BIT(E20_0),
TO_CORE_BIT(E10_1),
+ TO_CORE_BIT(E10_1_PAN),
TO_CORE_BIT(E2),
TO_CORE_BIT(E20_2),
+ TO_CORE_BIT(E20_2_PAN),
TO_CORE_BIT(SE10_0),
TO_CORE_BIT(SE10_1),
+ TO_CORE_BIT(SE10_1_PAN),
TO_CORE_BIT(SE3),
TO_CORE_BIT(Stage2),
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 1f8ee5f573..6be8b2d1a9 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -843,12 +843,16 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
return true;
default:
return false;
@@ -861,10 +865,13 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_E2:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_MPrivNegPri:
@@ -875,6 +882,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE3:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_MSPrivNegPri:
case ARMMMUIdx_MSUserNegPri:
case ARMMMUIdx_MSPriv:
@@ -1046,6 +1054,7 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
return true;
default:
return false;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 852fd71dcc..739d2d4cc5 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -671,6 +671,7 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
tlb_flush_by_mmuidx(cs,
ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_Stage2);
}
@@ -682,6 +683,7 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
tlb_flush_by_mmuidx_all_cpus_synced(cs,
ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_Stage2);
}
@@ -2700,6 +2702,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
switch (arm_mmu_idx(env)) {
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
return GTIMER_HYP;
default:
return GTIMER_PHYS;
@@ -2711,6 +2714,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
switch (arm_mmu_idx(env)) {
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
return GTIMER_HYPVIRT;
default:
return GTIMER_VIRT;
@@ -3337,7 +3341,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
if (arm_feature(env, ARM_FEATURE_EL2)) {
- if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
+ if (mmu_idx == ARMMMUIdx_E10_0 ||
+ mmu_idx == ARMMMUIdx_E10_1 ||
+ mmu_idx == ARMMMUIdx_E10_1_PAN) {
format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
} else {
format64 |= arm_current_el(env) == 2;
@@ -3797,7 +3803,9 @@ 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 | ARMMMUIdxBit_E20_0);
+ ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E20_0);
}
raw_write(env, ri, value);
}
@@ -3815,6 +3823,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
if (raw_read(env, ri) != value) {
tlb_flush_by_mmuidx(cs,
ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0 |
ARMMMUIdxBit_Stage2);
raw_write(env, ri, value);
@@ -4175,12 +4184,18 @@ static int vae1_tlbmask(CPUARMState *env)
{
/* Since we exclude secure first, we may read HCR_EL2 directly. */
if (arm_is_secure_below_el3(env)) {
- return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
+ return ARMMMUIdxBit_SE10_1 |
+ ARMMMUIdxBit_SE10_1_PAN |
+ ARMMMUIdxBit_SE10_0;
} else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
== (HCR_E2H | HCR_TGE)) {
- return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
+ return ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E20_0;
} else {
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
+ return ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0;
}
}
@@ -4214,18 +4229,28 @@ static int alle1_tlbmask(CPUARMState *env)
* stage 1 translations.
*/
if (arm_is_secure_below_el3(env)) {
- return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
+ return ARMMMUIdxBit_SE10_1 |
+ ARMMMUIdxBit_SE10_1_PAN |
+ ARMMMUIdxBit_SE10_0;
} else if (arm_feature(env, ARM_FEATURE_EL2)) {
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_Stage2;
+ return ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0 |
+ ARMMMUIdxBit_Stage2;
} else {
- return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
+ return ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0;
}
}
static int alle2_tlbmask(CPUARMState *env)
{
/* TODO: ARMv8.4-SecEL2 */
- return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | 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,
@@ -9215,6 +9240,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
switch (mmu_idx) {
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_E2:
return 2;
@@ -9223,10 +9249,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE10_0:
return arm_el_is_aa64(env, 3) ? 1 : 3;
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_MPrivNegPri:
case ARMMMUIdx_MUserNegPri:
case ARMMMUIdx_MPriv:
@@ -9342,6 +9371,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
return ARMMMUIdx_Stage1_E0;
case ARMMMUIdx_E10_1:
return ARMMMUIdx_Stage1_E1;
+ case ARMMMUIdx_E10_1_PAN:
+ return ARMMMUIdx_Stage1_E1_PAN;
default:
return mmu_idx;
}
@@ -9388,6 +9419,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
return false;
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
g_assert_not_reached();
}
}
@@ -11280,7 +11312,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
target_ulong *page_size,
ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
{
- if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
+ if (mmu_idx == ARMMMUIdx_E10_0 ||
+ mmu_idx == ARMMMUIdx_E10_1 ||
+ mmu_idx == ARMMMUIdx_E10_1_PAN) {
/* Call ourselves recursively to do the stage 1 and then stage 2
* translations.
*/
@@ -11807,10 +11841,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
case ARMMMUIdx_SE10_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:
return 2;
case ARMMMUIdx_SE3:
return 3;
@@ -12027,11 +12064,14 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
/* TODO: ARMv8.2-UAO */
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 */
flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
break;
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
/* TODO: ARMv8.4-SecEL2 */
/*
* Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 6e82486884..49631c2340 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -124,12 +124,15 @@ static int get_a64_user_mem_index(DisasContext *s)
*/
switch (useridx) {
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
useridx = ARMMMUIdx_E10_0;
break;
case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
useridx = ARMMMUIdx_E20_0;
break;
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
useridx = ARMMMUIdx_SE10_0;
break;
default:
diff --git a/target/arm/translate.c b/target/arm/translate.c
index e11a5871d0..d58c328e08 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -155,10 +155,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
case ARMMMUIdx_SE3:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
+ case ARMMMUIdx_SE10_1_PAN:
return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
case ARMMMUIdx_MUser:
case ARMMMUIdx_MPriv:
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled
2020-02-02 1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
@ 2020-02-03 11:54 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 11:54 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> To implement PAN, we will want to swap, for short periods
> of time, to a different privileged mmu_idx. In addition,
> we cannot do this with flushing alone, because the AT*
> instructions have both PAN and PAN-less versions.
>
> Add the ARMMMUIdx*_PAN constants where necessary next to
> the corresponding ARMMMUIdx* constant.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> target/arm/cpu-param.h | 2 +-
> target/arm/cpu.h | 33 ++++++++++++++-------
> target/arm/internals.h | 9 ++++++
> target/arm/helper.c | 60 +++++++++++++++++++++++++++++++-------
> target/arm/translate-a64.c | 3 ++
> target/arm/translate.c | 2 ++
> 6 files changed, 87 insertions(+), 22 deletions(-)
>
> diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
> index 18ac562346..d593b60b28 100644
> --- a/target/arm/cpu-param.h
> +++ b/target/arm/cpu-param.h
> @@ -29,6 +29,6 @@
> # define TARGET_PAGE_BITS_MIN 10
> #endif
>
> -#define NB_MMU_MODES 9
> +#define NB_MMU_MODES 12
>
> #endif
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 0b3036c484..c63bceaaa5 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -2751,20 +2751,24 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
> * 5. we want to be able to use the TLB for accesses done as part of a
> * stage1 page table walk, rather than having to walk the stage2 page
> * table over and over.
> + * 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
> + * Never (PAN) bit within PSTATE.
> *
> * This gives us the following list of cases:
> *
> * NS EL0 EL1&0 stage 1+2 (aka NS PL0)
> * NS EL1 EL1&0 stage 1+2 (aka NS PL1)
> + * NS EL1 EL1&0 stage 1+2 +PAN
> * NS EL0 EL2&0
> - * NS EL2 EL2&0
> + * NS EL2 EL2&0 +PAN
> * NS EL2 (aka NS PL2)
> * S EL0 EL1&0 (aka S PL0)
> * S EL1 EL1&0 (not used if EL3 is 32 bit)
> + * S EL1 EL1&0 +PAN
> * S EL3 (aka S PL1)
> * NS EL1&0 stage 2
> *
> - * for a total of 9 different mmu_idx.
> + * for a total of 12 different mmu_idx.
> *
> * R profile CPUs have an MPU, but can use the same set of MMU indexes
> * as A profile. They only need to distinguish NS EL0 and NS EL1 (and
> @@ -2819,19 +2823,22 @@ typedef enum ARMMMUIdx {
> /*
> * A-profile.
> */
> - ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
> - ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
>
> - ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
> + ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
>
> - ARMMMUIdx_E2 = 3 | ARM_MMU_IDX_A,
> - ARMMMUIdx_E20_2 = 4 | 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 = 5 | ARM_MMU_IDX_A,
> - ARMMMUIdx_SE10_1 = 6 | ARM_MMU_IDX_A,
> - ARMMMUIdx_SE3 = 7 | 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_Stage2 = 8 | ARM_MMU_IDX_A,
> + ARMMMUIdx_Stage2 = 11 | ARM_MMU_IDX_A,
>
> /*
> * These are not allocated TLBs and are used only for AT system
> @@ -2839,6 +2846,7 @@ typedef enum ARMMMUIdx {
> */
> ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
> ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
> + ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
>
> /*
> * M-profile.
> @@ -2864,10 +2872,13 @@ typedef enum ARMMMUIdxBit {
> TO_CORE_BIT(E10_0),
> TO_CORE_BIT(E20_0),
> TO_CORE_BIT(E10_1),
> + TO_CORE_BIT(E10_1_PAN),
> TO_CORE_BIT(E2),
> TO_CORE_BIT(E20_2),
> + TO_CORE_BIT(E20_2_PAN),
> TO_CORE_BIT(SE10_0),
> TO_CORE_BIT(SE10_1),
> + TO_CORE_BIT(SE10_1_PAN),
> TO_CORE_BIT(SE3),
> TO_CORE_BIT(Stage2),
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 1f8ee5f573..6be8b2d1a9 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -843,12 +843,16 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> case ARMMMUIdx_SE10_0:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> return true;
> default:
> return false;
> @@ -861,10 +865,13 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> case ARMMMUIdx_E2:
> case ARMMMUIdx_Stage2:
> case ARMMMUIdx_MPrivNegPri:
> @@ -875,6 +882,7 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
> case ARMMMUIdx_SE3:
> case ARMMMUIdx_SE10_0:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> case ARMMMUIdx_MSPrivNegPri:
> case ARMMMUIdx_MSUserNegPri:
> case ARMMMUIdx_MSPriv:
> @@ -1046,6 +1054,7 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> return true;
> default:
> return false;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 852fd71dcc..739d2d4cc5 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -671,6 +671,7 @@ static void tlbiall_nsnh_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
> tlb_flush_by_mmuidx(cs,
> ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> ARMMMUIdxBit_E10_0 |
> ARMMMUIdxBit_Stage2);
> }
> @@ -682,6 +683,7 @@ static void tlbiall_nsnh_is_write(CPUARMState *env, const ARMCPRegInfo *ri,
>
> tlb_flush_by_mmuidx_all_cpus_synced(cs,
> ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> ARMMMUIdxBit_E10_0 |
> ARMMMUIdxBit_Stage2);
> }
> @@ -2700,6 +2702,7 @@ static int gt_phys_redir_timeridx(CPUARMState *env)
> switch (arm_mmu_idx(env)) {
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> return GTIMER_HYP;
> default:
> return GTIMER_PHYS;
> @@ -2711,6 +2714,7 @@ static int gt_virt_redir_timeridx(CPUARMState *env)
> switch (arm_mmu_idx(env)) {
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> return GTIMER_HYPVIRT;
> default:
> return GTIMER_VIRT;
> @@ -3337,7 +3341,9 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
> format64 = arm_s1_regime_using_lpae_format(env, mmu_idx);
>
> if (arm_feature(env, ARM_FEATURE_EL2)) {
> - if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
> + if (mmu_idx == ARMMMUIdx_E10_0 ||
> + mmu_idx == ARMMMUIdx_E10_1 ||
> + mmu_idx == ARMMMUIdx_E10_1_PAN) {
> format64 |= env->cp15.hcr_el2 & (HCR_VM | HCR_DC);
> } else {
> format64 |= arm_current_el(env) == 2;
> @@ -3797,7 +3803,9 @@ 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 | ARMMMUIdxBit_E20_0);
> + ARMMMUIdxBit_E20_2 |
> + ARMMMUIdxBit_E20_2_PAN |
> + ARMMMUIdxBit_E20_0);
> }
> raw_write(env, ri, value);
> }
> @@ -3815,6 +3823,7 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
> if (raw_read(env, ri) != value) {
> tlb_flush_by_mmuidx(cs,
> ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> ARMMMUIdxBit_E10_0 |
> ARMMMUIdxBit_Stage2);
> raw_write(env, ri, value);
> @@ -4175,12 +4184,18 @@ static int vae1_tlbmask(CPUARMState *env)
> {
> /* Since we exclude secure first, we may read HCR_EL2 directly. */
> if (arm_is_secure_below_el3(env)) {
> - return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
> + return ARMMMUIdxBit_SE10_1 |
> + ARMMMUIdxBit_SE10_1_PAN |
> + ARMMMUIdxBit_SE10_0;
> } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
> == (HCR_E2H | HCR_TGE)) {
> - return ARMMMUIdxBit_E20_2 | ARMMMUIdxBit_E20_0;
> + return ARMMMUIdxBit_E20_2 |
> + ARMMMUIdxBit_E20_2_PAN |
> + ARMMMUIdxBit_E20_0;
> } else {
> - return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
> + return ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> + ARMMMUIdxBit_E10_0;
> }
> }
>
> @@ -4214,18 +4229,28 @@ static int alle1_tlbmask(CPUARMState *env)
> * stage 1 translations.
> */
> if (arm_is_secure_below_el3(env)) {
> - return ARMMMUIdxBit_SE10_1 | ARMMMUIdxBit_SE10_0;
> + return ARMMMUIdxBit_SE10_1 |
> + ARMMMUIdxBit_SE10_1_PAN |
> + ARMMMUIdxBit_SE10_0;
> } else if (arm_feature(env, ARM_FEATURE_EL2)) {
> - return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0 | ARMMMUIdxBit_Stage2;
> + return ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> + ARMMMUIdxBit_E10_0 |
> + ARMMMUIdxBit_Stage2;
> } else {
> - return ARMMMUIdxBit_E10_1 | ARMMMUIdxBit_E10_0;
> + return ARMMMUIdxBit_E10_1 |
> + ARMMMUIdxBit_E10_1_PAN |
> + ARMMMUIdxBit_E10_0;
> }
> }
>
> static int alle2_tlbmask(CPUARMState *env)
> {
> /* TODO: ARMv8.4-SecEL2 */
> - return ARMMMUIdxBit_E20_0 | ARMMMUIdxBit_E20_2 | 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,
> @@ -9215,6 +9240,7 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
> switch (mmu_idx) {
> case ARMMMUIdx_E20_0:
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> case ARMMMUIdx_Stage2:
> case ARMMMUIdx_E2:
> return 2;
> @@ -9223,10 +9249,13 @@ static uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
> case ARMMMUIdx_SE10_0:
> return arm_el_is_aa64(env, 3) ? 1 : 3;
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> case ARMMMUIdx_Stage1_E0:
> case ARMMMUIdx_Stage1_E1:
> + case ARMMMUIdx_Stage1_E1_PAN:
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> case ARMMMUIdx_MPrivNegPri:
> case ARMMMUIdx_MUserNegPri:
> case ARMMMUIdx_MPriv:
> @@ -9342,6 +9371,8 @@ static inline ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
> return ARMMMUIdx_Stage1_E0;
> case ARMMMUIdx_E10_1:
> return ARMMMUIdx_Stage1_E1;
> + case ARMMMUIdx_E10_1_PAN:
> + return ARMMMUIdx_Stage1_E1_PAN;
> default:
> return mmu_idx;
> }
> @@ -9388,6 +9419,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx)
> return false;
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> g_assert_not_reached();
> }
> }
> @@ -11280,7 +11312,9 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
> target_ulong *page_size,
> ARMMMUFaultInfo *fi, ARMCacheAttrs *cacheattrs)
> {
> - if (mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_E10_1) {
> + if (mmu_idx == ARMMMUIdx_E10_0 ||
> + mmu_idx == ARMMMUIdx_E10_1 ||
> + mmu_idx == ARMMMUIdx_E10_1_PAN) {
> /* Call ourselves recursively to do the stage 1 and then stage 2
> * translations.
> */
> @@ -11807,10 +11841,13 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
> case ARMMMUIdx_SE10_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:
> return 2;
> case ARMMMUIdx_SE3:
> return 3;
> @@ -12027,11 +12064,14 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
> /* TODO: ARMv8.2-UAO */
> 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 */
> flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
> break;
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> /* TODO: ARMv8.4-SecEL2 */
> /*
> * Note that E20_2 is gated by HCR_EL2.E2H == 1, but E20_0 is
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 6e82486884..49631c2340 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -124,12 +124,15 @@ static int get_a64_user_mem_index(DisasContext *s)
> */
> switch (useridx) {
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> useridx = ARMMMUIdx_E10_0;
> break;
> case ARMMMUIdx_E20_2:
> + case ARMMMUIdx_E20_2_PAN:
> useridx = ARMMMUIdx_E20_0;
> break;
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> useridx = ARMMMUIdx_SE10_0;
> break;
> default:
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index e11a5871d0..d58c328e08 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -155,10 +155,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
> case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
> case ARMMMUIdx_E10_0:
> case ARMMMUIdx_E10_1:
> + case ARMMMUIdx_E10_1_PAN:
> return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
> case ARMMMUIdx_SE3:
> case ARMMMUIdx_SE10_0:
> case ARMMMUIdx_SE10_1:
> + case ARMMMUIdx_SE10_1_PAN:
> return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
> case ARMMMUIdx_MUser:
> case ARMMMUIdx_MPriv:
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
2020-02-02 1:04 ` [PATCH v2 01/14] target/arm: Add arm_mmu_idx_is_stage1_of_2 Richard Henderson
2020-02-02 1:04 ` [PATCH v2 02/14] target/arm: Add mmu_idx for EL1 and EL2 w/ PAN enabled Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 12:24 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
` (10 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
Include definitions for all of the bits in ID_MMFR3.
We already have a definition for ID_AA64MMFR1.PAN.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c63bceaaa5..08b2f5d73e 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1727,6 +1727,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
FIELD(ID_ISAR6, SB, 12, 4)
FIELD(ID_ISAR6, SPECRES, 16, 4)
+FIELD(ID_MMFR3, CMAINTVA, 0, 4)
+FIELD(ID_MMFR3, CMAINTSW, 4, 4)
+FIELD(ID_MMFR3, BPMAINT, 8, 4)
+FIELD(ID_MMFR3, MAINTBCST, 12, 4)
+FIELD(ID_MMFR3, PAN, 16, 4)
+FIELD(ID_MMFR3, COHWALK, 20, 4)
+FIELD(ID_MMFR3, CMEMSZ, 24, 4)
+FIELD(ID_MMFR3, SUPERSEC, 28, 4)
+
FIELD(ID_MMFR4, SPECSEI, 0, 4)
FIELD(ID_MMFR4, AC2, 4, 4)
FIELD(ID_MMFR4, XNX, 8, 4)
@@ -3443,6 +3452,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
}
+static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
+}
+
+static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
+}
+
/*
* 64-bit feature tests via id registers.
*/
@@ -3602,6 +3621,16 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
}
+static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
+}
+
+static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
+}
+
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1
2020-02-02 1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
@ 2020-02-03 12:24 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 12:24 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> Include definitions for all of the bits in ID_MMFR3.
> We already have a definition for ID_AA64MMFR1.PAN.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> target/arm/cpu.h | 29 +++++++++++++++++++++++++++++
> 1 file changed, 29 insertions(+)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index c63bceaaa5..08b2f5d73e 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1727,6 +1727,15 @@ FIELD(ID_ISAR6, FHM, 8, 4)
> FIELD(ID_ISAR6, SB, 12, 4)
> FIELD(ID_ISAR6, SPECRES, 16, 4)
>
> +FIELD(ID_MMFR3, CMAINTVA, 0, 4)
> +FIELD(ID_MMFR3, CMAINTSW, 4, 4)
> +FIELD(ID_MMFR3, BPMAINT, 8, 4)
> +FIELD(ID_MMFR3, MAINTBCST, 12, 4)
> +FIELD(ID_MMFR3, PAN, 16, 4)
> +FIELD(ID_MMFR3, COHWALK, 20, 4)
> +FIELD(ID_MMFR3, CMEMSZ, 24, 4)
> +FIELD(ID_MMFR3, SUPERSEC, 28, 4)
> +
> FIELD(ID_MMFR4, SPECSEI, 0, 4)
> FIELD(ID_MMFR4, AC2, 4, 4)
> FIELD(ID_MMFR4, XNX, 8, 4)
> @@ -3443,6 +3452,16 @@ static inline bool isar_feature_aa32_vminmaxnm(const ARMISARegisters *id)
> return FIELD_EX64(id->mvfr2, MVFR2, FPMISC) >= 4;
> }
>
> +static inline bool isar_feature_aa32_pan(const ARMISARegisters *id)
> +{
> + return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) != 0;
> +}
> +
> +static inline bool isar_feature_aa32_ats1e1(const ARMISARegisters *id)
> +{
> + return FIELD_EX64(id->mvfr0, ID_MMFR3, PAN) >= 2;
> +}
> +
> /*
> * 64-bit feature tests via id registers.
> */
> @@ -3602,6 +3621,16 @@ static inline bool isar_feature_aa64_lor(const ARMISARegisters *id)
> return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, LO) != 0;
> }
>
> +static inline bool isar_feature_aa64_pan(const ARMISARegisters *id)
> +{
> + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) != 0;
> +}
> +
> +static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
> +{
> + return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
> +}
> +
> static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
> {
> return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (2 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 03/14] target/arm: Add isar_feature tests for PAN + ATS1E1 Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 12:25 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
` (9 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
For static const regdefs, file scope is preferred.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 57 +++++++++++++++++++++++----------------------
1 file changed, 29 insertions(+), 28 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 739d2d4cc5..795ef727d0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -6343,6 +6343,35 @@ static CPAccessResult access_lor_other(CPUARMState *env,
return access_lor_ns(env);
}
+/*
+ * A trivial implementation of ARMv8.1-LOR leaves all of these
+ * registers fixed at 0, which indicates that there are zero
+ * supported Limited Ordering regions.
+ */
+static const ARMCPRegInfo lor_reginfo[] = {
+ { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
+ .access = PL1_RW, .accessfn = access_lor_other,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
+ .access = PL1_R, .accessfn = access_lorid,
+ .type = ARM_CP_CONST, .resetvalue = 0 },
+ REGINFO_SENTINEL
+};
+
#ifdef TARGET_AARCH64
static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
bool isread)
@@ -7577,34 +7606,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
}
if (cpu_isar_feature(aa64_lor, cpu)) {
- /*
- * A trivial implementation of ARMv8.1-LOR leaves all of these
- * registers fixed at 0, which indicates that there are zero
- * supported Limited Ordering regions.
- */
- static const ARMCPRegInfo lor_reginfo[] = {
- { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
- .access = PL1_RW, .accessfn = access_lor_other,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
- .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
- .access = PL1_R, .accessfn = access_lorid,
- .type = ARM_CP_CONST, .resetvalue = 0 },
- REGINFO_SENTINEL
- };
define_arm_cp_regs(cpu, lor_reginfo);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope
2020-02-02 1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
@ 2020-02-03 12:25 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 12:25 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> For static const regdefs, file scope is preferred.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> target/arm/helper.c | 57 +++++++++++++++++++++++----------------------
> 1 file changed, 29 insertions(+), 28 deletions(-)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 739d2d4cc5..795ef727d0 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -6343,6 +6343,35 @@ static CPAccessResult access_lor_other(CPUARMState *env,
> return access_lor_ns(env);
> }
>
> +/*
> + * A trivial implementation of ARMv8.1-LOR leaves all of these
> + * registers fixed at 0, which indicates that there are zero
> + * supported Limited Ordering regions.
> + */
> +static const ARMCPRegInfo lor_reginfo[] = {
> + { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
> + .access = PL1_RW, .accessfn = access_lor_other,
> + .type = ARM_CP_CONST, .resetvalue = 0 },
> + { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
> + .access = PL1_RW, .accessfn = access_lor_other,
> + .type = ARM_CP_CONST, .resetvalue = 0 },
> + { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
> + .access = PL1_RW, .accessfn = access_lor_other,
> + .type = ARM_CP_CONST, .resetvalue = 0 },
> + { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
> + .access = PL1_RW, .accessfn = access_lor_other,
> + .type = ARM_CP_CONST, .resetvalue = 0 },
> + { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
> + .access = PL1_R, .accessfn = access_lorid,
> + .type = ARM_CP_CONST, .resetvalue = 0 },
> + REGINFO_SENTINEL
> +};
> +
> #ifdef TARGET_AARCH64
> static CPAccessResult access_pauth(CPUARMState *env, const ARMCPRegInfo *ri,
> bool isread)
> @@ -7577,34 +7606,6 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> }
>
> if (cpu_isar_feature(aa64_lor, cpu)) {
> - /*
> - * A trivial implementation of ARMv8.1-LOR leaves all of these
> - * registers fixed at 0, which indicates that there are zero
> - * supported Limited Ordering regions.
> - */
> - static const ARMCPRegInfo lor_reginfo[] = {
> - { .name = "LORSA_EL1", .state = ARM_CP_STATE_AA64,
> - .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 0,
> - .access = PL1_RW, .accessfn = access_lor_other,
> - .type = ARM_CP_CONST, .resetvalue = 0 },
> - { .name = "LOREA_EL1", .state = ARM_CP_STATE_AA64,
> - .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 1,
> - .access = PL1_RW, .accessfn = access_lor_other,
> - .type = ARM_CP_CONST, .resetvalue = 0 },
> - { .name = "LORN_EL1", .state = ARM_CP_STATE_AA64,
> - .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 2,
> - .access = PL1_RW, .accessfn = access_lor_other,
> - .type = ARM_CP_CONST, .resetvalue = 0 },
> - { .name = "LORC_EL1", .state = ARM_CP_STATE_AA64,
> - .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 3,
> - .access = PL1_RW, .accessfn = access_lor_other,
> - .type = ARM_CP_CONST, .resetvalue = 0 },
> - { .name = "LORID_EL1", .state = ARM_CP_STATE_AA64,
> - .opc0 = 3, .opc1 = 0, .crn = 10, .crm = 4, .opc2 = 7,
> - .access = PL1_R, .accessfn = access_lorid,
> - .type = ARM_CP_CONST, .resetvalue = 0 },
> - REGINFO_SENTINEL
> - };
> define_arm_cp_regs(cpu, lor_reginfo);
> }
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 05/14] target/arm: Update MSR access for PAN
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (3 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 04/14] target/arm: Move LOR regdefs to file scope Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 13:37 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
` (8 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
For aarch64, there's a dedicated msr (imm, reg) insn.
For aarch32, this is done via msr to cpsr; and writes
from el0 are ignored.
Since v8.0, the CPSR_RESERVED bits have been allocated.
We are not yet implementing ARMv8.0-SSBS or ARMv8.4-DIT,
so retain CPSR_RESERVED for now, so that the bits remain RES0.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Move regdef to file scope; merge patch for CPSR_RESERVED:
do not remove CPSR_SSBS from CPSR_RESERVED yet, mask PAN
from CPSR if feature not enabled (pmm).
---
target/arm/cpu.h | 11 +++++++++--
target/arm/helper-a64.c | 6 ++++++
target/arm/helper.c | 21 +++++++++++++++++++++
target/arm/op_helper.c | 9 ++++++++-
target/arm/translate-a64.c | 14 ++++++++++++++
target/arm/translate.c | 6 +++++-
6 files changed, 63 insertions(+), 4 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 08b2f5d73e..b11fdc3001 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1186,12 +1186,18 @@ void pmu_init(ARMCPU *cpu);
#define CPSR_IT_2_7 (0xfc00U)
#define CPSR_GE (0xfU << 16)
#define CPSR_IL (1U << 20)
-/* Note that the RESERVED bits include bit 21, which is PSTATE_SS in
+/*
+ * Note that the RESERVED bits include bit 21, which is PSTATE_SS in
* an AArch64 SPSR but RES0 in AArch32 SPSR and CPSR. In QEMU we use
* env->uncached_cpsr bit 21 to store PSTATE.SS when executing in AArch32,
* where it is live state but not accessible to the AArch32 code.
+ *
+ * TODO: With ARMv8.4-DIT, bit 21 is DIT in AArch32 (bit 24 for AArch64).
+ * We will need to move AArch32 SS somewhere else at that point.
+ * TODO: With ARMv8.0-SSBS, bit 23 is SSBS in AArch32 (bit 12 for AArch64).
*/
-#define CPSR_RESERVED (0x7U << 21)
+#define CPSR_RESERVED (5U << 21)
+#define CPSR_PAN (1U << 22)
#define CPSR_J (1U << 24)
#define CPSR_IT_0_1 (3U << 25)
#define CPSR_Q (1U << 27)
@@ -1258,6 +1264,7 @@ void pmu_init(ARMCPU *cpu);
#define PSTATE_BTYPE (3U << 10)
#define PSTATE_IL (1U << 20)
#define PSTATE_SS (1U << 21)
+#define PSTATE_PAN (1U << 22)
#define PSTATE_V (1U << 28)
#define PSTATE_C (1U << 29)
#define PSTATE_Z (1U << 30)
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index bf45f8a785..70d6407f80 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -1014,6 +1014,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
* will sort the register banks out for us, and we've already
* caught all the bad-mode cases in el_from_spsr().
*/
+ if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
+ spsr &= ~CPSR_PAN;
+ }
cpsr_write(env, spsr, ~0, CPSRWriteRaw);
if (!arm_singlestep_active(env)) {
env->uncached_cpsr &= ~PSTATE_SS;
@@ -1031,6 +1034,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
cur_el, new_el, env->regs[15]);
} else {
env->aarch64 = 1;
+ if (!cpu_isar_feature(aa64_pan, env_archcpu(env))) {
+ spsr &= ~PSTATE_PAN;
+ }
pstate_write(env, spsr);
if (!arm_singlestep_active(env)) {
env->pstate &= ~PSTATE_SS;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 795ef727d0..90a22921dc 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4163,6 +4163,24 @@ static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
env->daif = value & PSTATE_DAIF;
}
+static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pstate & PSTATE_PAN;
+}
+
+static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->pstate = (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN);
+}
+
+static const ARMCPRegInfo pan_reginfo = {
+ .name = "PAN", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 3,
+ .type = ARM_CP_NO_RAW, .access = PL1_RW,
+ .readfn = aa64_pan_read, .writefn = aa64_pan_write
+};
+
static CPAccessResult aa64_cacheop_access(CPUARMState *env,
const ARMCPRegInfo *ri,
bool isread)
@@ -7608,6 +7626,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (cpu_isar_feature(aa64_lor, cpu)) {
define_arm_cp_regs(cpu, lor_reginfo);
}
+ if (cpu_isar_feature(aa64_pan, cpu)) {
+ define_one_arm_cp_reg(cpu, &pan_reginfo);
+ }
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
define_arm_cp_regs(cpu, vhe_reginfo);
diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
index 27d16ad9ad..7ba578e826 100644
--- a/target/arm/op_helper.c
+++ b/target/arm/op_helper.c
@@ -400,11 +400,18 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
/* Write the CPSR for a 32-bit exception return */
void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
{
+ uint32_t mask;
+
qemu_mutex_lock_iothread();
arm_call_pre_el_change_hook(env_archcpu(env));
qemu_mutex_unlock_iothread();
- cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
+ mask = CPSR_ERET_MASK;
+ if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
+ mask &= ~CPSR_PAN;
+ }
+
+ cpsr_write(env, val, mask, CPSRWriteExceptionReturn);
/* Generated code has already stored the new PC value, but
* without masking out its low bits, because which bits need
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 49631c2340..d8ba240a15 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1602,6 +1602,20 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
s->base.is_jmp = DISAS_NEXT;
break;
+ case 0x04: /* PAN */
+ if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
+ goto do_unallocated;
+ }
+ if (crm & 1) {
+ set_pstate_bits(PSTATE_PAN);
+ } else {
+ clear_pstate_bits(PSTATE_PAN);
+ }
+ t1 = tcg_const_i32(s->current_el);
+ gen_helper_rebuild_hflags_a64(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
case 0x05: /* SPSel */
if (s->current_el == 0) {
goto do_unallocated;
diff --git a/target/arm/translate.c b/target/arm/translate.c
index d58c328e08..0b1f0e0fea 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -2760,13 +2760,17 @@ static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
mask &= ~CPSR_IT;
}
+ if (!dc_isar_feature(aa32_pan, s)) {
+ mask &= ~CPSR_PAN;
+ }
/* Mask out execution state and reserved bits. */
if (!spsr) {
mask &= ~(CPSR_EXEC | CPSR_RESERVED);
}
/* Mask out privileged bits. */
- if (IS_USER(s))
+ if (IS_USER(s)) {
mask &= CPSR_USER;
+ }
return mask;
}
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 05/14] target/arm: Update MSR access for PAN
2020-02-02 1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
@ 2020-02-03 13:37 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 13:37 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> For aarch64, there's a dedicated msr (imm, reg) insn.
> For aarch32, this is done via msr to cpsr; and writes
> from el0 are ignored.
>
> Since v8.0, the CPSR_RESERVED bits have been allocated.
> We are not yet implementing ARMv8.0-SSBS or ARMv8.4-DIT,
> so retain CPSR_RESERVED for now, so that the bits remain RES0.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> v2: Move regdef to file scope; merge patch for CPSR_RESERVED:
> do not remove CPSR_SSBS from CPSR_RESERVED yet, mask PAN
> from CPSR if feature not enabled (pmm).
> ---
> target/arm/cpu.h | 11 +++++++++--
> target/arm/helper-a64.c | 6 ++++++
> target/arm/helper.c | 21 +++++++++++++++++++++
> target/arm/op_helper.c | 9 ++++++++-
> target/arm/translate-a64.c | 14 ++++++++++++++
> target/arm/translate.c | 6 +++++-
> 6 files changed, 63 insertions(+), 4 deletions(-)
>
> diff --git a/target/arm/cpu.h b/target/arm/cpu.h
> index 08b2f5d73e..b11fdc3001 100644
> --- a/target/arm/cpu.h
> +++ b/target/arm/cpu.h
> @@ -1186,12 +1186,18 @@ void pmu_init(ARMCPU *cpu);
> #define CPSR_IT_2_7 (0xfc00U)
> #define CPSR_GE (0xfU << 16)
> #define CPSR_IL (1U << 20)
> -/* Note that the RESERVED bits include bit 21, which is PSTATE_SS in
> +/*
> + * Note that the RESERVED bits include bit 21, which is PSTATE_SS in
> * an AArch64 SPSR but RES0 in AArch32 SPSR and CPSR. In QEMU we use
> * env->uncached_cpsr bit 21 to store PSTATE.SS when executing in AArch32,
> * where it is live state but not accessible to the AArch32 code.
> + *
> + * TODO: With ARMv8.4-DIT, bit 21 is DIT in AArch32 (bit 24 for AArch64).
> + * We will need to move AArch32 SS somewhere else at that point.
> + * TODO: With ARMv8.0-SSBS, bit 23 is SSBS in AArch32 (bit 12 for AArch64).
> */
> -#define CPSR_RESERVED (0x7U << 21)
> +#define CPSR_RESERVED (5U << 21)
> +#define CPSR_PAN (1U << 22)
> #define CPSR_J (1U << 24)
> #define CPSR_IT_0_1 (3U << 25)
> #define CPSR_Q (1U << 27)
> @@ -1258,6 +1264,7 @@ void pmu_init(ARMCPU *cpu);
> #define PSTATE_BTYPE (3U << 10)
> #define PSTATE_IL (1U << 20)
> #define PSTATE_SS (1U << 21)
> +#define PSTATE_PAN (1U << 22)
> #define PSTATE_V (1U << 28)
> #define PSTATE_C (1U << 29)
> #define PSTATE_Z (1U << 30)
> diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
> index bf45f8a785..70d6407f80 100644
> --- a/target/arm/helper-a64.c
> +++ b/target/arm/helper-a64.c
> @@ -1014,6 +1014,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
> * will sort the register banks out for us, and we've already
> * caught all the bad-mode cases in el_from_spsr().
> */
> + if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
> + spsr &= ~CPSR_PAN;
> + }
> cpsr_write(env, spsr, ~0, CPSRWriteRaw);
> if (!arm_singlestep_active(env)) {
> env->uncached_cpsr &= ~PSTATE_SS;
> @@ -1031,6 +1034,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
> cur_el, new_el, env->regs[15]);
> } else {
> env->aarch64 = 1;
> + if (!cpu_isar_feature(aa64_pan, env_archcpu(env))) {
> + spsr &= ~PSTATE_PAN;
> + }
> pstate_write(env, spsr);
> if (!arm_singlestep_active(env)) {
> env->pstate &= ~PSTATE_SS;
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 795ef727d0..90a22921dc 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -4163,6 +4163,24 @@ static void aa64_daif_write(CPUARMState *env, const ARMCPRegInfo *ri,
> env->daif = value & PSTATE_DAIF;
> }
>
> +static uint64_t aa64_pan_read(CPUARMState *env, const ARMCPRegInfo *ri)
> +{
> + return env->pstate & PSTATE_PAN;
> +}
> +
> +static void aa64_pan_write(CPUARMState *env, const ARMCPRegInfo *ri,
> + uint64_t value)
> +{
> + env->pstate = (env->pstate & ~PSTATE_PAN) | (value & PSTATE_PAN);
> +}
> +
> +static const ARMCPRegInfo pan_reginfo = {
> + .name = "PAN", .state = ARM_CP_STATE_AA64,
> + .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 3,
> + .type = ARM_CP_NO_RAW, .access = PL1_RW,
> + .readfn = aa64_pan_read, .writefn = aa64_pan_write
> +};
> +
> static CPAccessResult aa64_cacheop_access(CPUARMState *env,
> const ARMCPRegInfo *ri,
> bool isread)
> @@ -7608,6 +7626,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
> if (cpu_isar_feature(aa64_lor, cpu)) {
> define_arm_cp_regs(cpu, lor_reginfo);
> }
> + if (cpu_isar_feature(aa64_pan, cpu)) {
> + define_one_arm_cp_reg(cpu, &pan_reginfo);
> + }
>
> if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
> define_arm_cp_regs(cpu, vhe_reginfo);
> diff --git a/target/arm/op_helper.c b/target/arm/op_helper.c
> index 27d16ad9ad..7ba578e826 100644
> --- a/target/arm/op_helper.c
> +++ b/target/arm/op_helper.c
> @@ -400,11 +400,18 @@ void HELPER(cpsr_write)(CPUARMState *env, uint32_t val, uint32_t mask)
> /* Write the CPSR for a 32-bit exception return */
> void HELPER(cpsr_write_eret)(CPUARMState *env, uint32_t val)
> {
> + uint32_t mask;
> +
> qemu_mutex_lock_iothread();
> arm_call_pre_el_change_hook(env_archcpu(env));
> qemu_mutex_unlock_iothread();
>
> - cpsr_write(env, val, CPSR_ERET_MASK, CPSRWriteExceptionReturn);
> + mask = CPSR_ERET_MASK;
> + if (!cpu_isar_feature(aa32_pan, env_archcpu(env))) {
> + mask &= ~CPSR_PAN;
> + }
> +
> + cpsr_write(env, val, mask, CPSRWriteExceptionReturn);
>
> /* Generated code has already stored the new PC value, but
> * without masking out its low bits, because which bits need
> diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
> index 49631c2340..d8ba240a15 100644
> --- a/target/arm/translate-a64.c
> +++ b/target/arm/translate-a64.c
> @@ -1602,6 +1602,20 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
> s->base.is_jmp = DISAS_NEXT;
> break;
>
> + case 0x04: /* PAN */
> + if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
> + goto do_unallocated;
> + }
> + if (crm & 1) {
> + set_pstate_bits(PSTATE_PAN);
> + } else {
> + clear_pstate_bits(PSTATE_PAN);
> + }
> + t1 = tcg_const_i32(s->current_el);
> + gen_helper_rebuild_hflags_a64(cpu_env, t1);
> + tcg_temp_free_i32(t1);
> + break;
> +
> case 0x05: /* SPSel */
> if (s->current_el == 0) {
> goto do_unallocated;
> diff --git a/target/arm/translate.c b/target/arm/translate.c
> index d58c328e08..0b1f0e0fea 100644
> --- a/target/arm/translate.c
> +++ b/target/arm/translate.c
> @@ -2760,13 +2760,17 @@ static uint32_t msr_mask(DisasContext *s, int flags, int spsr)
> if (!arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
> mask &= ~CPSR_IT;
> }
> + if (!dc_isar_feature(aa32_pan, s)) {
> + mask &= ~CPSR_PAN;
> + }
> /* Mask out execution state and reserved bits. */
> if (!spsr) {
> mask &= ~(CPSR_EXEC | CPSR_RESERVED);
> }
> /* Mask out privileged bits. */
> - if (IS_USER(s))
> + if (IS_USER(s)) {
> mask &= CPSR_USER;
> + }
> return mask;
> }
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el for PAN
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (4 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 05/14] target/arm: Update MSR access for PAN Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 13:38 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
` (7 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
Examine the PAN bit for EL1, EL2, and Secure EL1 to
determine if it applies.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 90a22921dc..638abe6af0 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -11904,13 +11904,22 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
return ARMMMUIdx_E10_0;
case 1:
if (arm_is_secure_below_el3(env)) {
+ if (env->pstate & PSTATE_PAN) {
+ return ARMMMUIdx_SE10_1_PAN;
+ }
return ARMMMUIdx_SE10_1;
}
+ if (env->pstate & PSTATE_PAN) {
+ return ARMMMUIdx_E10_1_PAN;
+ }
return ARMMMUIdx_E10_1;
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 (env->pstate & PSTATE_PAN) {
+ return ARMMMUIdx_E20_2_PAN;
+ }
return ARMMMUIdx_E20_2;
}
return ARMMMUIdx_E2;
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el for PAN
2020-02-02 1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
@ 2020-02-03 13:38 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 13:38 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> Examine the PAN bit for EL1, EL2, and Secure EL1 to
> determine if it applies.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> target/arm/helper.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 90a22921dc..638abe6af0 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -11904,13 +11904,22 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
> return ARMMMUIdx_E10_0;
> case 1:
> if (arm_is_secure_below_el3(env)) {
> + if (env->pstate & PSTATE_PAN) {
> + return ARMMMUIdx_SE10_1_PAN;
> + }
> return ARMMMUIdx_SE10_1;
> }
> + if (env->pstate & PSTATE_PAN) {
> + return ARMMMUIdx_E10_1_PAN;
> + }
> return ARMMMUIdx_E10_1;
> 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 (env->pstate & PSTATE_PAN) {
> + return ARMMMUIdx_E20_2_PAN;
> + }
> return ARMMMUIdx_E20_2;
> }
> return ARMMMUIdx_E2;
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (5 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 06/14] target/arm: Update arm_mmu_idx_el " Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-03 14:30 ` Alex Bennée
2020-02-02 1:04 ` [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry Richard Henderson
` (6 subsequent siblings)
13 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
If we have a PAN-enforcing mmu_idx, set prot == 0 if user_rw != 0.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/internals.h | 13 +++++++++++++
target/arm/helper.c | 3 +++
2 files changed, 16 insertions(+)
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 6be8b2d1a9..819de9037f 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -893,6 +893,19 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
}
}
+static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
+{
+ switch (mmu_idx) {
+ case ARMMMUIdx_Stage1_E1_PAN:
+ case ARMMMUIdx_E10_1_PAN:
+ case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_SE10_1_PAN:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* Return the FSR value for a debug exception (watchpoint, hardware
* breakpoint or BKPT insn) targeting the specified exception level.
*/
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 638abe6af0..18e4cbb63c 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -9578,6 +9578,9 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
if (is_user) {
prot_rw = user_rw;
} else {
+ if (user_rw && regime_is_pan(env, mmu_idx)) {
+ return 0;
+ }
prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
}
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot
2020-02-02 1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
@ 2020-02-03 14:30 ` Alex Bennée
0 siblings, 0 replies; 22+ messages in thread
From: Alex Bennée @ 2020-02-03 14:30 UTC (permalink / raw)
To: Richard Henderson; +Cc: peter.maydell, qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> If we have a PAN-enforcing mmu_idx, set prot == 0 if user_rw != 0.
>
> Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> ---
> target/arm/internals.h | 13 +++++++++++++
> target/arm/helper.c | 3 +++
> 2 files changed, 16 insertions(+)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index 6be8b2d1a9..819de9037f 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -893,6 +893,19 @@ static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
> }
> }
>
> +static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
> +{
> + switch (mmu_idx) {
> + case ARMMMUIdx_Stage1_E1_PAN:
> + case ARMMMUIdx_E10_1_PAN:
> + case ARMMMUIdx_E20_2_PAN:
> + case ARMMMUIdx_SE10_1_PAN:
> + return true;
> + default:
> + return false;
> + }
> +}
> +
> /* Return the FSR value for a debug exception (watchpoint, hardware
> * breakpoint or BKPT insn) targeting the specified exception level.
> */
> diff --git a/target/arm/helper.c b/target/arm/helper.c
> index 638abe6af0..18e4cbb63c 100644
> --- a/target/arm/helper.c
> +++ b/target/arm/helper.c
> @@ -9578,6 +9578,9 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
> if (is_user) {
> prot_rw = user_rw;
> } else {
> + if (user_rw && regime_is_pan(env, mmu_idx)) {
> + return 0;
> + }
> prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
> }
--
Alex Bennée
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (6 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 07/14] target/arm: Enforce PAN semantics in get_S1prot Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-02 1:04 ` [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers Richard Henderson
` (5 subsequent siblings)
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
The PAN bit is preserved, or set as per SCTLR_ELx.SPAN,
plus several other conditions listed in the ARM ARM.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Tidy preservation of CPSR_PAN in take_aarch32_exception (pmm).
---
target/arm/helper.c | 40 +++++++++++++++++++++++++++++++++++++---
1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 18e4cbb63c..4c0eb7e7d9 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8772,8 +8772,12 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
uint32_t mask, uint32_t offset,
uint32_t newpc)
{
+ int new_el;
+
/* Change the CPU state so as to actually take the exception. */
switch_mode(env, new_mode);
+ new_el = arm_current_el(env);
+
/*
* For exceptions taken to AArch32 we must clear the SS bit in both
* PSTATE and in the old-state value we save to SPSR_<mode>, so zero it now.
@@ -8786,7 +8790,7 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
/* Set new mode endianness */
env->uncached_cpsr &= ~CPSR_E;
- if (env->cp15.sctlr_el[arm_current_el(env)] & SCTLR_EE) {
+ if (env->cp15.sctlr_el[new_el] & SCTLR_EE) {
env->uncached_cpsr |= CPSR_E;
}
/* J and IL must always be cleared for exception entry */
@@ -8797,6 +8801,12 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode,
env->thumb = (env->cp15.sctlr_el[2] & SCTLR_TE) != 0;
env->elr_el[2] = env->regs[15];
} else {
+ /* CPSR.PAN is preserved unless target is EL1 and SCTLR.SPAN == 0. */
+ if (cpu_isar_feature(aa64_pan, env_archcpu(env))
+ && new_el == 1
+ && !(env->cp15.sctlr_el[1] & SCTLR_SPAN)) {
+ env->uncached_cpsr |= CPSR_PAN;
+ }
/*
* this is a lie, as there was no c1_sys on V4T/V5, but who cares
* and we should just guard the thumb mode on V4
@@ -9059,6 +9069,7 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
unsigned int new_el = env->exception.target_el;
target_ulong addr = env->cp15.vbar_el[new_el];
unsigned int new_mode = aarch64_pstate_mode(new_el, true);
+ unsigned int old_mode;
unsigned int cur_el = arm_current_el(env);
/*
@@ -9138,20 +9149,43 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
}
if (is_a64(env)) {
- env->banked_spsr[aarch64_banked_spsr_index(new_el)] = pstate_read(env);
+ old_mode = pstate_read(env);
aarch64_save_sp(env, arm_current_el(env));
env->elr_el[new_el] = env->pc;
} else {
- env->banked_spsr[aarch64_banked_spsr_index(new_el)] = cpsr_read(env);
+ old_mode = cpsr_read(env);
env->elr_el[new_el] = env->regs[15];
aarch64_sync_32_to_64(env);
env->condexec_bits = 0;
}
+ env->banked_spsr[aarch64_banked_spsr_index(new_el)] = old_mode;
+
qemu_log_mask(CPU_LOG_INT, "...with ELR 0x%" PRIx64 "\n",
env->elr_el[new_el]);
+ if (cpu_isar_feature(aa64_pan, cpu)) {
+ /* The value of PSTATE.PAN is normally preserved, except when ... */
+ new_mode |= old_mode & PSTATE_PAN;
+ switch (new_el) {
+ case 2:
+ /* ... the target is EL2 with HCR_EL2.{E2H,TGE} == '11' ... */
+ if ((arm_hcr_el2_eff(env) & (HCR_E2H | HCR_TGE))
+ != (HCR_E2H | HCR_TGE)) {
+ break;
+ }
+ /* fall through */
+ case 1:
+ /* ... the target is EL1 ... */
+ /* ... and SCTLR_ELx.SPAN == 0, then set to 1. */
+ if ((env->cp15.sctlr_el[new_el] & SCTLR_SPAN) == 0) {
+ new_mode |= PSTATE_PAN;
+ }
+ break;
+ }
+ }
+
pstate_write(env, PSTATE_DAIF | new_mode);
env->aarch64 = 1;
aarch64_restore_sp(env, new_el);
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (7 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 08/14] target/arm: Set PAN bit as required on exception entry Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-02 1:04 ` [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
` (4 subsequent siblings)
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
This is a minor enhancement over ARMv8.1-PAN.
The *_PAN mmu_idx are used with the existing do_ats_write.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Move regdefs to file scope (pmm).
---
target/arm/helper.c | 56 ++++++++++++++++++++++++++++++++++++++++-----
1 file changed, 50 insertions(+), 6 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 4c0eb7e7d9..e69cde801f 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -3409,16 +3409,21 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
switch (ri->opc2 & 6) {
case 0:
- /* stage 1 current state PL1: ATS1CPR, ATS1CPW */
+ /* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
switch (el) {
case 3:
mmu_idx = ARMMMUIdx_SE3;
break;
case 2:
- mmu_idx = ARMMMUIdx_Stage1_E1;
- break;
+ g_assert(!secure); /* TODO: ARMv8.4-SecEL2 */
+ /* fall through */
case 1:
- mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
+ mmu_idx = (secure ? ARMMMUIdx_SE10_1_PAN
+ : ARMMMUIdx_Stage1_E1_PAN);
+ } else {
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ }
break;
default:
g_assert_not_reached();
@@ -3487,8 +3492,13 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
switch (ri->opc2 & 6) {
case 0:
switch (ri->opc1) {
- case 0: /* AT S1E1R, AT S1E1W */
- mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
+ if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
+ mmu_idx = (secure ? ARMMMUIdx_SE10_1_PAN
+ : ARMMMUIdx_Stage1_E1_PAN);
+ } else {
+ mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_Stage1_E1;
+ }
break;
case 4: /* AT S1E2R, AT S1E2W */
mmu_idx = ARMMMUIdx_E2;
@@ -6692,6 +6702,32 @@ static const ARMCPRegInfo vhe_reginfo[] = {
REGINFO_SENTINEL
};
+#ifndef CONFIG_USER_ONLY
+static const ARMCPRegInfo ats1e1_reginfo[] = {
+ { .name = "AT_S1E1R", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write64 },
+ { .name = "AT_S1E1W", .state = ARM_CP_STATE_AA64,
+ .opc0 = 1, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write64 },
+ REGINFO_SENTINEL
+};
+
+static const ARMCPRegInfo ats1cp_reginfo[] = {
+ { .name = "ATS1CPRP",
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 0,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write },
+ { .name = "ATS1CPWP",
+ .cp = 15, .opc1 = 0, .crn = 7, .crm = 9, .opc2 = 1,
+ .access = PL1_W, .type = ARM_CP_NO_RAW | ARM_CP_RAISES_EXC,
+ .writefn = ats_write },
+ REGINFO_SENTINEL
+};
+#endif
+
void register_cp_regs_for_features(ARMCPU *cpu)
{
/* Register all the coprocessor registers based on feature bits */
@@ -7629,6 +7665,14 @@ void register_cp_regs_for_features(ARMCPU *cpu)
if (cpu_isar_feature(aa64_pan, cpu)) {
define_one_arm_cp_reg(cpu, &pan_reginfo);
}
+#ifndef CONFIG_USER_ONLY
+ if (cpu_isar_feature(aa64_ats1e1, cpu)) {
+ define_arm_cp_regs(cpu, ats1e1_reginfo);
+ }
+ if (cpu_isar_feature(aa32_ats1e1, cpu)) {
+ define_arm_cp_regs(cpu, ats1cp_reginfo);
+ }
+#endif
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
define_arm_cp_regs(cpu, vhe_reginfo);
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (8 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 09/14] target/arm: Implement ATS1E1 system registers Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-02 1:04 ` [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1 Richard Henderson
` (3 subsequent siblings)
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
This includes enablement of ARMv8.1-PAN.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.c | 4 ++++
target/arm/cpu64.c | 5 +++++
2 files changed, 9 insertions(+)
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index b0762a76c4..de733aceeb 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -2709,6 +2709,10 @@ static void arm_max_initfn(Object *obj)
t = FIELD_DP32(t, MVFR2, FPMISC, 4); /* FP MaxNum */
cpu->isar.mvfr2 = t;
+ t = cpu->id_mmfr3;
+ t = FIELD_DP32(t, ID_MMFR3, PAN, 2); /* ATS1E1 */
+ cpu->id_mmfr3 = t;
+
t = cpu->id_mmfr4;
t = FIELD_DP32(t, ID_MMFR4, HPDS, 1); /* AA32HPD */
cpu->id_mmfr4 = t;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index c80fb5fd43..57fbc5eade 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -673,6 +673,7 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
+ t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
cpu->isar.id_aa64mmfr1 = t;
/* Replicate the same data to the 32-bit id registers. */
@@ -693,6 +694,10 @@ static void aarch64_max_initfn(Object *obj)
u = FIELD_DP32(u, ID_ISAR6, SPECRES, 1);
cpu->isar.id_isar6 = u;
+ u = cpu->id_mmfr3;
+ u = FIELD_DP32(u, ID_MMFR3, PAN, 2); /* ATS1E1 */
+ cpu->id_mmfr3 = u;
+
/*
* FIXME: We do not yet support ARMv8.2-fp16 for AArch32 yet,
* so do not set MVFR1.FPHP. Strictly speaking this is not legal,
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (9 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 10/14] target/arm: Enable ARMv8.2-ATS1E1 in -cpu max Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-02 1:04 ` [PATCH v2 12/14] target/arm: Update MSR access to UAO Richard Henderson
` (2 subsequent siblings)
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
Add definitions for all of the fields, up to ARMv8.5.
Convert the existing RESERVED register to a full register.
Query KVM for the value of the register for the host.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu.h | 17 +++++++++++++++++
target/arm/helper.c | 4 ++--
target/arm/kvm64.c | 2 ++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index b11fdc3001..a6a8f74be8 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -871,6 +871,7 @@ struct ARMCPU {
uint64_t id_aa64pfr1;
uint64_t id_aa64mmfr0;
uint64_t id_aa64mmfr1;
+ uint64_t id_aa64mmfr2;
} isar;
uint32_t midr;
uint32_t revidr;
@@ -1816,6 +1817,22 @@ FIELD(ID_AA64MMFR1, PAN, 20, 4)
FIELD(ID_AA64MMFR1, SPECSEI, 24, 4)
FIELD(ID_AA64MMFR1, XNX, 28, 4)
+FIELD(ID_AA64MMFR2, CNP, 0, 4)
+FIELD(ID_AA64MMFR2, UAO, 4, 4)
+FIELD(ID_AA64MMFR2, LSM, 8, 4)
+FIELD(ID_AA64MMFR2, IESB, 12, 4)
+FIELD(ID_AA64MMFR2, VARANGE, 16, 4)
+FIELD(ID_AA64MMFR2, CCIDX, 20, 4)
+FIELD(ID_AA64MMFR2, NV, 24, 4)
+FIELD(ID_AA64MMFR2, ST, 28, 4)
+FIELD(ID_AA64MMFR2, AT, 32, 4)
+FIELD(ID_AA64MMFR2, IDS, 36, 4)
+FIELD(ID_AA64MMFR2, FWB, 40, 4)
+FIELD(ID_AA64MMFR2, TTL, 48, 4)
+FIELD(ID_AA64MMFR2, BBM, 52, 4)
+FIELD(ID_AA64MMFR2, EVT, 56, 4)
+FIELD(ID_AA64MMFR2, E0PD, 60, 4)
+
FIELD(ID_DFR0, COPDBG, 0, 4)
FIELD(ID_DFR0, COPSDBG, 4, 4)
FIELD(ID_DFR0, MMAPDBG, 8, 4)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index e69cde801f..a48f37dc05 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -7082,11 +7082,11 @@ void register_cp_regs_for_features(ARMCPU *cpu)
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
.resetvalue = cpu->isar.id_aa64mmfr1 },
- { .name = "ID_AA64MMFR2_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
+ { .name = "ID_AA64MMFR2_EL1", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 2,
.access = PL1_R, .type = ARM_CP_CONST,
.accessfn = access_aa64_tid3,
- .resetvalue = 0 },
+ .resetvalue = cpu->isar.id_aa64mmfr2 },
{ .name = "ID_AA64MMFR3_EL1_RESERVED", .state = ARM_CP_STATE_AA64,
.opc0 = 3, .opc1 = 0, .crn = 0, .crm = 7, .opc2 = 3,
.access = PL1_R, .type = ARM_CP_CONST,
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index fb21ab9e73..3bae9e4a66 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -549,6 +549,8 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
ARM64_SYS_REG(3, 0, 0, 7, 0));
err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr1,
ARM64_SYS_REG(3, 0, 0, 7, 1));
+ err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64mmfr2,
+ ARM64_SYS_REG(3, 0, 0, 7, 2));
/*
* Note that if AArch32 support is not present in the host,
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 12/14] target/arm: Update MSR access to UAO
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (10 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 11/14] target/arm: Add ID_AA64MMFR2_EL1 Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-02 1:04 ` [PATCH v2 13/14] target/arm: Implement UAO semantics Richard Henderson
2020-02-02 1:04 ` [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max Richard Henderson
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
v2: Move reginfo to file scope; avoid setting uao from spsr
when the feature is not enabled (pmm).
---
target/arm/cpu.h | 6 ++++++
target/arm/helper-a64.c | 3 +++
target/arm/helper.c | 21 +++++++++++++++++++++
target/arm/translate-a64.c | 14 ++++++++++++++
4 files changed, 44 insertions(+)
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index a6a8f74be8..a0ac70e0fb 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1266,6 +1266,7 @@ void pmu_init(ARMCPU *cpu);
#define PSTATE_IL (1U << 20)
#define PSTATE_SS (1U << 21)
#define PSTATE_PAN (1U << 22)
+#define PSTATE_UAO (1U << 23)
#define PSTATE_V (1U << 28)
#define PSTATE_C (1U << 29)
#define PSTATE_Z (1U << 30)
@@ -3655,6 +3656,11 @@ static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
}
+static inline bool isar_feature_aa64_uao(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, UAO) != 0;
+}
+
static inline bool isar_feature_aa64_bti(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, BT) != 0;
diff --git a/target/arm/helper-a64.c b/target/arm/helper-a64.c
index 70d6407f80..9dda94644f 100644
--- a/target/arm/helper-a64.c
+++ b/target/arm/helper-a64.c
@@ -1037,6 +1037,9 @@ void HELPER(exception_return)(CPUARMState *env, uint64_t new_pc)
if (!cpu_isar_feature(aa64_pan, env_archcpu(env))) {
spsr &= ~PSTATE_PAN;
}
+ if (!cpu_isar_feature(aa64_uao, env_archcpu(env))) {
+ spsr &= ~PSTATE_UAO;
+ }
pstate_write(env, spsr);
if (!arm_singlestep_active(env)) {
env->pstate &= ~PSTATE_SS;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a48f37dc05..d847b0f40b 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -4191,6 +4191,24 @@ static const ARMCPRegInfo pan_reginfo = {
.readfn = aa64_pan_read, .writefn = aa64_pan_write
};
+static uint64_t aa64_uao_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pstate & PSTATE_UAO;
+}
+
+static void aa64_uao_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->pstate = (env->pstate & ~PSTATE_UAO) | (value & PSTATE_UAO);
+}
+
+static const ARMCPRegInfo uao_reginfo = {
+ .name = "UAO", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .crn = 4, .crm = 2, .opc2 = 4,
+ .type = ARM_CP_NO_RAW, .access = PL1_RW,
+ .readfn = aa64_uao_read, .writefn = aa64_uao_write
+};
+
static CPAccessResult aa64_cacheop_access(CPUARMState *env,
const ARMCPRegInfo *ri,
bool isread)
@@ -7673,6 +7691,9 @@ void register_cp_regs_for_features(ARMCPU *cpu)
define_arm_cp_regs(cpu, ats1cp_reginfo);
}
#endif
+ if (cpu_isar_feature(aa64_uao, cpu)) {
+ define_one_arm_cp_reg(cpu, &uao_reginfo);
+ }
if (arm_feature(env, ARM_FEATURE_EL2) && cpu_isar_feature(aa64_vh, cpu)) {
define_arm_cp_regs(cpu, vhe_reginfo);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d8ba240a15..7c26c3bfeb 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1602,6 +1602,20 @@ static void handle_msr_i(DisasContext *s, uint32_t insn,
s->base.is_jmp = DISAS_NEXT;
break;
+ case 0x03: /* UAO */
+ if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
+ goto do_unallocated;
+ }
+ if (crm & 1) {
+ set_pstate_bits(PSTATE_UAO);
+ } else {
+ clear_pstate_bits(PSTATE_UAO);
+ }
+ t1 = tcg_const_i32(s->current_el);
+ gen_helper_rebuild_hflags_a64(cpu_env, t1);
+ tcg_temp_free_i32(t1);
+ break;
+
case 0x04: /* PAN */
if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
goto do_unallocated;
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 13/14] target/arm: Implement UAO semantics
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (11 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 12/14] target/arm: Update MSR access to UAO Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
2020-02-02 1:04 ` [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max Richard Henderson
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
We need only override the current condition under which
TBFLAG_A64.UNPRIV is set.
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/helper.c | 41 +++++++++++++++++++++--------------------
1 file changed, 21 insertions(+), 20 deletions(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index d847b0f40b..b24a6a6526 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -12194,28 +12194,29 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
}
/* Compute the condition for using AccType_UNPRIV for LDTR et al. */
- /* TODO: ARMv8.2-UAO */
- 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 */
- flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
- break;
- case ARMMMUIdx_E20_2:
- case ARMMMUIdx_E20_2_PAN:
- /* 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) {
+ if (!(env->pstate & PSTATE_UAO)) {
+ 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 */
flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
+ break;
+ case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
+ /* TODO: ARMv8.4-SecEL2 */
+ /*
+ * 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.
+ */
+ if (env->cp15.hcr_el2 & HCR_TGE) {
+ flags = FIELD_DP32(flags, TBFLAG_A64, UNPRIV, 1);
+ }
+ break;
+ default:
+ break;
}
- break;
- default:
- break;
}
return rebuild_hflags_common(env, fp_el, mmu_idx, flags);
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH v2 14/14] target/arm: Enable ARMv8.2-UAO in -cpu max
2020-02-02 1:04 [PATCH v2 00/14] target/arm: Implement PAN, ATS1E1, UAO Richard Henderson
` (12 preceding siblings ...)
2020-02-02 1:04 ` [PATCH v2 13/14] target/arm: Implement UAO semantics Richard Henderson
@ 2020-02-02 1:04 ` Richard Henderson
13 siblings, 0 replies; 22+ messages in thread
From: Richard Henderson @ 2020-02-02 1:04 UTC (permalink / raw)
To: qemu-devel; +Cc: peter.maydell, alex.bennee
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu64.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 57fbc5eade..1359564c55 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -676,6 +676,10 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* ATS1E1 */
cpu->isar.id_aa64mmfr1 = t;
+ t = cpu->isar.id_aa64mmfr2;
+ t = FIELD_DP64(t, ID_AA64MMFR2, UAO, 1);
+ cpu->isar.id_aa64mmfr2 = t;
+
/* Replicate the same data to the 32-bit id registers. */
u = cpu->isar.id_isar5;
u = FIELD_DP32(u, ID_ISAR5, AES, 2); /* AES + PMULL */
--
2.20.1
^ permalink raw reply related [flat|nested] 22+ messages in thread