aboutsummaryrefslogtreecommitdiff
path: root/target/arm
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2024-03-01 10:41:09 -1000
committerPeter Maydell <peter.maydell@linaro.org>2024-03-05 13:22:56 +0000
commit59754f85ed35cbd5f4bf2663ca2136c78d5b2413 (patch)
tree1bd9d1eb57eadc718ae8e247727419098fd453d5 /target/arm
parent49fa457ca5abc8c46910ec777e2c510b428a1648 (diff)
target/arm: Do memory type alignment check when translation disabled
If translation is disabled, the default memory type is Device, which requires alignment checking. This is more optimally done early via the MemOp given to the TCG memory operation. Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org> Reported-by: Idan Horowitz <idan.horowitz@gmail.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20240301204110.656742-6-richard.henderson@linaro.org Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1204 Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm')
-rw-r--r--target/arm/tcg/hflags.c34
1 files changed, 32 insertions, 2 deletions
diff --git a/target/arm/tcg/hflags.c b/target/arm/tcg/hflags.c
index 8e5d35d922..5da1b0fc1d 100644
--- a/target/arm/tcg/hflags.c
+++ b/target/arm/tcg/hflags.c
@@ -26,6 +26,35 @@ static inline bool fgt_svc(CPUARMState *env, int el)
FIELD_EX64(env->cp15.fgt_exec[FGTREG_HFGITR], HFGITR_EL2, SVC_EL1);
}
+/* Return true if memory alignment should be enforced. */
+static bool aprofile_require_alignment(CPUARMState *env, int el, uint64_t sctlr)
+{
+#ifdef CONFIG_USER_ONLY
+ return false;
+#else
+ /* Check the alignment enable bit. */
+ if (sctlr & SCTLR_A) {
+ return true;
+ }
+
+ /*
+ * If translation is disabled, then the default memory type is
+ * Device(-nGnRnE) instead of Normal, which requires that alignment
+ * be enforced. Since this affects all ram, it is most efficient
+ * to handle this during translation.
+ */
+ if (sctlr & SCTLR_M) {
+ /* Translation enabled: memory type in PTE via MAIR_ELx. */
+ return false;
+ }
+ if (el < 2 && (arm_hcr_el2_eff(env) & (HCR_DC | HCR_VM))) {
+ /* Stage 2 translation enabled: memory type in PTE. */
+ return false;
+ }
+ return true;
+#endif
+}
+
static CPUARMTBFlags rebuild_hflags_common(CPUARMState *env, int fp_el,
ARMMMUIdx mmu_idx,
CPUARMTBFlags flags)
@@ -121,8 +150,9 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
{
CPUARMTBFlags flags = {};
int el = arm_current_el(env);
+ uint64_t sctlr = arm_sctlr(env, el);
- if (arm_sctlr(env, el) & SCTLR_A) {
+ if (aprofile_require_alignment(env, el, sctlr)) {
DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
}
@@ -223,7 +253,7 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
sctlr = regime_sctlr(env, stage1);
- if (sctlr & SCTLR_A) {
+ if (aprofile_require_alignment(env, el, sctlr)) {
DP_TBFLAG_ANY(flags, ALIGN_MEM, 1);
}