diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 8e523c02..40fc38d4 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -10,6 +10,7 @@ #include "exec/cpu_ldst.h" #include "arm_ldst.h" #include "fpu/softfloat.h" +#include "qemu/range.h" #ifndef CONFIG_USER_ONLY /* Cacheability and shareability attributes for a memory access */ @@ -8885,6 +8886,20 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, } if (address < base || address > base + rmask) { + /* + * Address not in this region. We must check whether the + * region covers addresses in the same page as our address. + * In that case we must not report a size that covers the + * whole page for a subsequent hit against a different MPU + * region or the background region, because it would result in + * incorrect TLB hits for subsequent accesses to addresses that + * are in this MPU region. + */ + if (ranges_overlap(base, rmask, + address & TARGET_PAGE_MASK, + TARGET_PAGE_SIZE)) { + *page_size = 1; + } continue; } @@ -9091,6 +9106,22 @@ static void v8m_security_lookup(CPUARMState *env, uint32_t address, sattrs->srvalid = true; sattrs->sregion = r; } + } else { + /* + * Address not in this region. We must check whether the + * region covers addresses in the same page as our address. + * In that case we must not report a size that covers the + * whole page for a subsequent hit against a different MPU + * region or the background region, because it would result + * in incorrect TLB hits for subsequent accesses to + * addresses that are in this MPU region. + */ + if (limit >= base && + ranges_overlap(base, limit - base + 1, + addr_page_base, + TARGET_PAGE_SIZE)) { + sattrs->subpage = true; + } } } } @@ -9158,6 +9189,21 @@ static bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address, } if (address < base || address > limit) { + /* + * Address not in this region. We must check whether the + * region covers addresses in the same page as our address. + * In that case we must not report a size that covers the + * whole page for a subsequent hit against a different MPU + * region or the background region, because it would result in + * incorrect TLB hits for subsequent accesses to addresses that + * are in this MPU region. + */ + if (limit >= base && + ranges_overlap(base, limit - base + 1, + addr_page_base, + TARGET_PAGE_SIZE)) { + *is_subpage = true; + } continue; }