Perform the atomic update for hardware management of the dirty bit.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/cpu64.c | 2 +-
target/arm/ptw.c | 20 ++++++++++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index fe1369fe96..0732796559 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -1165,7 +1165,7 @@ static void aarch64_max_initfn(Object *obj)
cpu->isar.id_aa64mmfr0 = t;
t = cpu->isar.id_aa64mmfr1;
- t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 1); /* FEAT_HAFDBS, AF only */
+ t = FIELD_DP64(t, ID_AA64MMFR1, HAFDBS, 2); /* FEAT_HAFDBS */
t = FIELD_DP64(t, ID_AA64MMFR1, VMIDBITS, 2); /* FEAT_VMID16 */
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 82b6ab029e..0dbbb7d4d4 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -1484,10 +1484,30 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
ap = extract32(attrs, 6, 2);
if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
+ if (param.hd
+ && extract64(attrs, 51, 1) /* DBM */
+ && access_type == MMU_DATA_STORE) {
+ /*
+ * Pre-emptively set S2AP[1], so that we compute EXEC properly.
+ * C.f. AArch64.S2ApplyOutputPerms, which does the same thing.
+ */
+ ap |= 2;
+ new_descriptor |= 1ull << 7;
+ }
ns = mmu_idx == ARMMMUIdx_Stage2;
xn = extract64(attrs, 54, 2);
result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
} else {
+ if (param.hd
+ && extract64(attrs, 51, 1) /* DBM */
+ && access_type == MMU_DATA_STORE) {
+ /*
+ * Pre-emptively clear AP[2], so that we compute EXEC properly.
+ * C.f. AArch64.S1ApplyOutputPerms, which does the same thing.
+ */
+ ap &= ~2;
+ new_descriptor &= ~(1ull << 7);
+ }
ns = extract32(attrs, 5, 1);
xn = extract64(attrs, 54, 1);
pxn = extract64(attrs, 53, 1);
--
2.34.1