diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2022-10-24 15:18:51 +1000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2022-10-27 11:34:31 +0100 |
commit | c8d6c286ab4bff1c5ff511f3e834fb2a713d65d2 (patch) | |
tree | 5d419aef59422a08a3cbf84284cb21db4c0b3cdd /target/arm | |
parent | 65c123fdf577413a7d910e6b07c10e79d118041f (diff) | |
download | qemu-c8d6c286ab4bff1c5ff511f3e834fb2a713d65d2.zip qemu-c8d6c286ab4bff1c5ff511f3e834fb2a713d65d2.tar.gz qemu-c8d6c286ab4bff1c5ff511f3e834fb2a713d65d2.tar.bz2 |
target/arm: Use the max page size in a 2-stage ptw
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 <maz@kernel.org>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20221024051851.3074715-15-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm')
-rw-r--r-- | target/arm/ptw.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/target/arm/ptw.c b/target/arm/ptw.c index a1f4ae6..58a7bbd 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -2571,7 +2571,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, ARMMMUFaultInfo *fi) { hwaddr ipa; - int s1_prot; + int s1_prot, s1_lgpgsz; bool is_secure = ptw->in_secure; bool ret, ipa_secure, s2walk_secure; ARMCacheAttrs cacheattrs1; @@ -2607,6 +2607,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, * Save the stage1 results so that we may merge prot and cacheattrs later. */ s1_prot = result->f.prot; + s1_lgpgsz = result->f.lg_page_size; cacheattrs1 = result->cacheattrs; memset(result, 0, sizeof(*result)); @@ -2621,6 +2622,14 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw, 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) { |