Commit 1f8aa4b6af for qemu.org
commit 1f8aa4b6af88e2df4792b9a22782a6b0435b864e
Author: Richard Henderson <richard.henderson@linaro.org>
Date: Mon Jul 20 19:05:30 2026 +0100
target/arm: Fix testing of raw mtx value
MTX is always a pair of bits, one for each half of the address space.
Testing it like a boolean is incorrect.
Introduce raw_mte_check, a mirror of the similar mte_check function
that applies when MTX is passed in MTEDESC.
Fixes: 8912ceced815 ("target/arm: load on canonical tag loads ext bits")
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20260717161430.37264-1-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/target/arm/tcg/mte_helper.c b/target/arm/tcg/mte_helper.c
index dca4ef5a94..ad4ad5b4cc 100644
--- a/target/arm/tcg/mte_helper.c
+++ b/target/arm/tcg/mte_helper.c
@@ -317,6 +317,12 @@ int load_tag1(uint64_t ptr, uint8_t *mem)
return extract32(*mem, ofs, 4);
}
+/* Like mtx_check, but simple mtx bit pair instead of MTEDESC. */
+static bool raw_mtx_check(unsigned mtx, unsigned bit55)
+{
+ return (mtx >> bit55) & 1;
+}
+
uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt, uint32_t mtx)
{
int mmu_idx = arm_env_mmu_index(env);
@@ -330,9 +336,11 @@ uint64_t HELPER(ldg)(CPUARMState *env, uint64_t ptr, uint64_t xt, uint32_t mtx)
/* Load if page supports tags. */
if (mem) {
rtag = load_tag1(ptr, mem);
- } else if (mtx) {
- uint64_t bit55 = extract64(ptr, 55, 1);
- rtag = 0xF * bit55;
+ } else {
+ bool bit55 = extract64(ptr, 55, 1);
+ if (raw_mtx_check(mtx, bit55)) {
+ rtag = 0xF * bit55;
+ }
}
return address_with_allocation_tag(xt, rtag);
@@ -387,7 +395,7 @@ static inline void do_stg(CPUARMState *env, uint64_t ptr, uint64_t xt,
/* Store if page supports tags. */
if (mem) {
store1(ptr, mem, allocation_tag_from_addr(xt));
- } else if (mtx) {
+ } else if (raw_mtx_check(mtx, extract64(ptr, 55, 1))) {
canonical_tag_write_fail(env, ptr, ra);
}
}
@@ -420,6 +428,7 @@ static inline void do_st2g(CPUARMState *env, uint64_t ptr, uint64_t xt,
uint8_t *mem1, *mem2;
check_tag_aligned(env, ptr, ra);
+ mtx = raw_mtx_check(mtx, extract64(ptr, 55, 1));
/*
* Trap if accessing an invalid page(s).
@@ -504,8 +513,8 @@ uint64_t HELPER(ldgm)(CPUARMState *env, uint64_t ptr, uint32_t mtx)
/* The tag is squashed to zero if the page does not support tags. */
if (!tag_mem) {
/* Load canonical value if mtx is set (untagged memory region) */
- if (mtx) {
- bool bit55 = extract64(ptr, 55, 1);
+ bool bit55 = extract64(ptr, 55, 1);
+ if (raw_mtx_check(mtx, bit55)) {
ret = extract64(-bit55, 0, 1 << gm_bs);
shift = extract64(ptr, LOG2_TAG_GRANULE, 4) * 4;
return ret << shift;
@@ -573,7 +582,7 @@ void HELPER(stgm)(CPUARMState *env, uint64_t ptr, uint64_t val, uint32_t mtx)
*/
if (!tag_mem) {
/* Storing tags to canonically tagged region: fault. */
- if (mtx) {
+ if (raw_mtx_check(mtx, extract64(ptr, 55, 1))) {
canonical_tag_write_fail(env, ptr, ra);
}
return;
@@ -630,7 +639,7 @@ void HELPER(stzgm_tags)(CPUARMState *env, uint64_t ptr, uint64_t val,
if (mem) {
int tag_pair = (val & 0xf) * 0x11;
memset(mem, tag_pair, tag_bytes);
- } else if (mtx) {
+ } else if (raw_mtx_check(mtx, extract64(ptr, 55, 1))) {
canonical_tag_write_fail(env, ptr, ra);
}
}