[RFC PATCH 05/18] target/arm: Probe second page earlier in allocation_tag_mem_internal
Richard Henderson <[email protected]>
| Newsgroups | org.nongnu.qemu-riscv,org.nongnu.qemu-arm,org.nongnu.qemu-devel |
|---|---|
| Message-ID | <[email protected]> |
Translation faults have priority over everything else in this function. We were failing to trap for the second page entirely in the user-only case, and when tag access is disabled on the first page for the system case. Signed-off-by: Richard Henderson <[email protected]> --- target/arm/tcg/mte_helper.c | 55 ++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c index 31bf58c937..399bca30c9 100644 --- a/target/arm/tcg/mte_helper.c +++ b/target/arm/tcg/mte_helper.c @@ -130,6 +130,13 @@ allocation_tag_mem_internal(CPUARMState *env, int ptr_mmu_idx, g_assert_not_reached(); } } + if (atm_kind == ATM_NORMAL) { + int in_page = -(ptr | TARGET_PAGE_MASK); + if (unlikely(ptr_size > in_page)) { + probe_access(env, ptr + in_page, ptr_size - in_page, + ptr_access, MMU_USER_IDX, ra); + } + } /* Require both MAP_ANON and PROT_MTE for the page. */ if ((flags & PAGE_ANON) && (flags & PAGE_MTE)) { @@ -148,6 +155,7 @@ allocation_tag_mem_internal(CPUARMState *env, int ptr_mmu_idx, MemoryRegion *mr; ARMASIdx tag_asi; AddressSpace *tag_as; + uint8_t pte_attrs; /* * Probe the first byte of the virtual address. This raises an @@ -161,9 +169,32 @@ allocation_tag_mem_internal(CPUARMState *env, int ptr_mmu_idx, assert(atm_kind == ATM_PROBE_PAGES); goto fini; } + + /* + * Remember these across the second lookup below, + * which may invalidate this pointer via tlb resize. + */ + ptr_paddr = full->phys_addr | (ptr & ~TARGET_PAGE_MASK); + pte_attrs = full->extra.arm.pte_attrs; ret.attrs = full->attrs; - switch (full->extra.arm.pte_attrs) { + /* + * The Normal memory access can extend to the next page. E.g. a single + * 8-byte access to the last byte of a page will check only the last + * tag on the first page. + * Any page access exception has priority over tag check exception. + */ + if (atm_kind == ATM_NORMAL) { + int in_page = -(ptr | TARGET_PAGE_MASK); + if (unlikely(ptr_size > in_page)) { + void *discard_mem; + ret.flags |= probe_access_full(env, ptr + in_page, 0, ptr_access, + ptr_mmu_idx, false, + &discard_mem, &full, ra); + } + } + + switch (pte_attrs) { case 0xf0: /* Tagged */ break; @@ -193,28 +224,8 @@ allocation_tag_mem_internal(CPUARMState *env, int ptr_mmu_idx, goto fini; } - /* - * Remember this across the second lookup below, - * which may invalidate this pointer via tlb resize. - */ - ptr_paddr = full->phys_addr | (ptr & ~TARGET_PAGE_MASK); - - /* - * The Normal memory access can extend to the next page. E.g. a single - * 8-byte access to the last byte of a page will check only the last - * tag on the first page. - * Any page access exception has priority over tag check exception. - */ + /* Any debug exception has priority over a tag check exception. */ if (atm_kind == ATM_NORMAL) { - int in_page = -(ptr | TARGET_PAGE_MASK); - if (unlikely(ptr_size > in_page)) { - void *discard_mem; - ret.flags |= probe_access_full(env, ptr + in_page, 0, ptr_access, - ptr_mmu_idx, false, - &discard_mem, &full, ra); - } - - /* Any debug exception has priority over a tag check exception. */ if (unlikely(ret.flags & TLB_WATCHPOINT)) { int wp = ptr_access == MMU_DATA_LOAD ? BP_MEM_READ : BP_MEM_WRITE; cpu_check_watchpoint(env_cpu(env), ptr, ptr_size, -- 2.43.0