We had only been reporting the stage2 page size. This causes
problems if stage1 is using a larger page size (16k, 2M, etc),
but stage2 is using a smaller page size, because cputlb does
not set large_page_{addr,mask} properly.
Fix by using the max of the two page sizes.
Reported-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
Hi Mark, I think this will fix the issue that you mentioned on Monday.
It certainly appears to fit the bill vs the described symptoms.
This is based on my ptw.c rewrite, full tree at
https://gitlab.com/rth7680/qemu/-/tree/tgt-arm-rme
Based-on: 20220822152741.1617527-1-richard.henderson@linaro.org
("[PATCH v2 00/66] target/arm: Implement FEAT_HAFDBS")
r~
---
target/arm/ptw.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index c81c51f60c..510939fc89 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -2509,7 +2509,7 @@ static bool get_phys_addr_twostage(CPUARMState *env,
target_ulong address,
ARMMMUFaultInfo *fi)
{
hwaddr ipa;
- int s1_prot;
+ int s1_prot, s1_lgpgsz;
bool ret;
bool ipa_secure;
ARMCacheAttrs cacheattrs1;
@@ -2550,6 +2550,7 @@ static bool get_phys_addr_twostage(CPUARMState *env,
target_ulong address,
* prot and cacheattrs later.
*/
s1_prot = result->f.prot;
+ s1_lgpgsz = result->f.lg_page_size;
cacheattrs1 = result->cacheattrs;
memset(result, 0, sizeof(*result));
@@ -2565,6 +2566,14 @@ static bool get_phys_addr_twostage(CPUARMState *env, target_ulong address,
return ret;
}
+ /*
+ * Use the maximum of the S1 & S2 page size, so that invalidation
+ * of pages > TARGET_PAGE_SIZE works correctly.
+ */
+ if (result->f.lg_page_size < s1_lgpgsz) {
+ result->f.lg_page_size = s1_lgpgsz;
+ }
+
/* Combine the S1 and S2 cache attributes. */
hcr = arm_hcr_el2_eff_secstate(env, is_secure);
if (hcr & HCR_DC) {