]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
target/arm: Fix big-endian handling of NEON gdb remote debugging
authorVacha Bhavsar <vacha.bhavsar@oss.qualcomm.com>
Tue, 22 Jul 2025 17:37:35 +0000 (17:37 +0000)
committerMichael Tokarev <mjt@tls.msk.ru>
Wed, 6 Aug 2025 07:02:36 +0000 (10:02 +0300)
In the code for allowing the gdbstub to set the value of an AArch64
FP/SIMD register, we weren't accounting for target_big_endian()
being true. This meant that for aarch64_be-linux-user we would
set the two halves of the FP register the wrong way around.
The much more common case of a little-endian guest is not affected;
nor are big-endian hosts.

Correct the handling of this case.

Cc: qemu-stable@nongnu.org
Signed-off-by: Vacha Bhavsar <vacha.bhavsar@oss.qualcomm.com>
Message-id: 20250722173736.2332529-2-vacha.bhavsar@oss.qualcomm.com
[PMM: added comment, expanded commit message, fixed missing space]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
(cherry picked from commit 35cca0f95ff5345f54c11d116efc8940a0dab8aa)
(Mjt: s/target_big_endian/target_words_bigendian/ due to missing
 v10.0.0-277-gb939b8e42a "exec: Rename target_words_bigendian() -> target_big_endian()")
Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
target/arm/gdbstub64.c

index 1a4dbec567983f1e5d624c7e69224f35288e7000..d4d808a49bbe21907696ffcd88a73aae63c10936 100644 (file)
@@ -111,8 +111,22 @@ int aarch64_gdb_set_fpu_reg(CPUState *cs, uint8_t *buf, int reg)
         /* 128 bit FP register */
         {
             uint64_t *q = aa64_vfp_qreg(env, reg);
-            q[0] = ldq_le_p(buf);
-            q[1] = ldq_le_p(buf + 8);
+
+            /*
+             * On the wire these are target-endian 128 bit values.
+             * In the CPU state these are host-order uint64_t values
+             * with the least-significant one first. This means they're
+             * the other way around for target_words_bigendian() (which is
+             * only true for us for aarch64_be-linux-user).
+             */
+            if (target_words_bigendian()) {
+                q[1] = ldq_p(buf);
+                q[0] = ldq_p(buf + 8);
+            } else{
+                q[0] = ldq_p(buf);
+                q[1] = ldq_p(buf + 8);
+            }
+
             return 16;
         }
     case 32: