diff mbox series

[v1,14/19] target/arm: Check alignment in helper_mte_check

Message ID 20230216030854.1212208-15-richard.henderson@linaro.org
State New
Headers show
Series target/arm: Implement FEAT_LSE2 | expand

Commit Message

Richard Henderson Feb. 16, 2023, 3:08 a.m. UTC
Fixes a bug in that with SCTLR.A set, we should raise any
alignment fault before raising any MTE check fault.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/internals.h     |  3 ++-
 target/arm/mte_helper.c    | 18 ++++++++++++++++++
 target/arm/translate-a64.c |  2 ++
 3 files changed, 22 insertions(+), 1 deletion(-)

Comments

Peter Maydell Feb. 23, 2023, 4:28 p.m. UTC | #1
On Thu, 16 Feb 2023 at 03:11, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Fixes a bug in that with SCTLR.A set, we should raise any
> alignment fault before raising any MTE check fault.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  target/arm/internals.h     |  3 ++-
>  target/arm/mte_helper.c    | 18 ++++++++++++++++++
>  target/arm/translate-a64.c |  2 ++
>  3 files changed, 22 insertions(+), 1 deletion(-)
>
> diff --git a/target/arm/internals.h b/target/arm/internals.h
> index e1e018da46..fa264e368c 100644
> --- a/target/arm/internals.h
> +++ b/target/arm/internals.h
> @@ -1222,7 +1222,8 @@ FIELD(MTEDESC, MIDX,  0, 4)
>  FIELD(MTEDESC, TBI,   4, 2)
>  FIELD(MTEDESC, TCMA,  6, 2)
>  FIELD(MTEDESC, WRITE, 8, 1)
> -FIELD(MTEDESC, SIZEM1, 9, SIMD_DATA_BITS - 9)  /* size - 1 */
> +FIELD(MTEDESC, ALIGN, 9, 3)
> +FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12)  /* size - 1 */
>
>  bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
>  uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
> diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
> index 98bcf59c22..e50bb4ea13 100644
> --- a/target/arm/mte_helper.c
> +++ b/target/arm/mte_helper.c
> @@ -784,6 +784,24 @@ uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra)
>
>  uint64_t HELPER(mte_check)(CPUARMState *env, uint32_t desc, uint64_t ptr)
>  {
> +    /*
> +     * In the Arm ARM pseudocode, the alignment check happens at the top
> +     * of Mem[], while the MTE check happens later in AArch64.MemSingle[].
> +     * Thus the alignment check has priority.
> +     * When the mte check is disabled, tcg performs the alignment check
> +     * during the code generated for the memory access.
> +     */

Also described in the text: the I_ZFGJP priority table lists
MTE faults at priority 33, basically lower than anything else
except an external abort.

Looking at the code, is this really the only case here where
we were mis-prioritizing tag check faults? Have we already
checked things like "no page table entry" and all the other
cases that can cause data aborts at this point?

thanks
-- PMM
Richard Henderson Feb. 23, 2023, 4:38 p.m. UTC | #2
On 2/23/23 06:28, Peter Maydell wrote:
> Also described in the text: the I_ZFGJP priority table lists
> MTE faults at priority 33, basically lower than anything else
> except an external abort.
> 
> Looking at the code, is this really the only case here where
> we were mis-prioritizing tag check faults? Have we already
> checked things like "no page table entry" and all the other
> cases that can cause data aborts at this point?

Well, yes, we do the page table lookup in allocation_tag_mem(), while fetching the tag 
memory against which the check is performed.

If there's another mis-prioritization, I don't know about it.


r~
Peter Maydell Feb. 23, 2023, 4:54 p.m. UTC | #3
On Thu, 16 Feb 2023 at 03:11, Richard Henderson
<richard.henderson@linaro.org> wrote:
>
> Fixes a bug in that with SCTLR.A set, we should raise any
> alignment fault before raising any MTE check fault.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

thanks
-- PMM
diff mbox series

Patch

diff --git a/target/arm/internals.h b/target/arm/internals.h
index e1e018da46..fa264e368c 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1222,7 +1222,8 @@  FIELD(MTEDESC, MIDX,  0, 4)
 FIELD(MTEDESC, TBI,   4, 2)
 FIELD(MTEDESC, TCMA,  6, 2)
 FIELD(MTEDESC, WRITE, 8, 1)
-FIELD(MTEDESC, SIZEM1, 9, SIMD_DATA_BITS - 9)  /* size - 1 */
+FIELD(MTEDESC, ALIGN, 9, 3)
+FIELD(MTEDESC, SIZEM1, 12, SIMD_DATA_BITS - 12)  /* size - 1 */
 
 bool mte_probe(CPUARMState *env, uint32_t desc, uint64_t ptr);
 uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra);
diff --git a/target/arm/mte_helper.c b/target/arm/mte_helper.c
index 98bcf59c22..e50bb4ea13 100644
--- a/target/arm/mte_helper.c
+++ b/target/arm/mte_helper.c
@@ -784,6 +784,24 @@  uint64_t mte_check(CPUARMState *env, uint32_t desc, uint64_t ptr, uintptr_t ra)
 
 uint64_t HELPER(mte_check)(CPUARMState *env, uint32_t desc, uint64_t ptr)
 {
+    /*
+     * In the Arm ARM pseudocode, the alignment check happens at the top
+     * of Mem[], while the MTE check happens later in AArch64.MemSingle[].
+     * Thus the alignment check has priority.
+     * When the mte check is disabled, tcg performs the alignment check
+     * during the code generated for the memory access.
+     */
+    unsigned align = FIELD_EX32(desc, MTEDESC, ALIGN);
+    if (unlikely(align)) {
+        align = (1u << align) - 1;
+        if (unlikely(ptr & align)) {
+            int idx = FIELD_EX32(desc, MTEDESC, MIDX);
+            bool w = FIELD_EX32(desc, MTEDESC, WRITE);
+            MMUAccessType type = w ? MMU_DATA_STORE : MMU_DATA_LOAD;
+            arm_cpu_do_unaligned_access(env_cpu(env), ptr, type, idx, GETPC());
+        }
+    }
+
     return mte_check(env, desc, ptr, GETPC());
 }
 
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 1117a1cc41..caeb91efa5 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -267,6 +267,7 @@  static TCGv_i64 gen_mte_check1_mmuidx(DisasContext *s, TCGv_i64 addr,
         desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
         desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
         desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
+        desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(memop));
         desc = FIELD_DP32(desc, MTEDESC, SIZEM1, memop_size(memop) - 1);
 
         ret = new_tmp_a64(s);
@@ -298,6 +299,7 @@  TCGv_i64 gen_mte_checkN(DisasContext *s, TCGv_i64 addr, bool is_write,
         desc = FIELD_DP32(desc, MTEDESC, TBI, s->tbid);
         desc = FIELD_DP32(desc, MTEDESC, TCMA, s->tcma);
         desc = FIELD_DP32(desc, MTEDESC, WRITE, is_write);
+        desc = FIELD_DP32(desc, MTEDESC, ALIGN, get_alignment_bits(single_mop));
         desc = FIELD_DP32(desc, MTEDESC, SIZEM1, total_size - 1);
 
         ret = new_tmp_a64(s);