diff options
author | Vacha Bhavsar <vacha.bhavsar@oss.qualcomm.com> | 2025-07-22 17:37:35 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2025-08-01 16:48:50 +0100 |
commit | 35cca0f95ff5345f54c11d116efc8940a0dab8aa (patch) | |
tree | ee67dc642d622781603dc183196aa808db43d6fe | |
parent | 4f2b82f60431e4792ecfd86a4d6b824248ee4c21 (diff) | |
download | qemu-35cca0f95ff5345f54c11d116efc8940a0dab8aa.zip qemu-35cca0f95ff5345f54c11d116efc8940a0dab8aa.tar.gz qemu-35cca0f95ff5345f54c11d116efc8940a0dab8aa.tar.bz2 |
target/arm: Fix big-endian handling of NEON gdb remote debugging
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>
-rw-r--r-- | target/arm/gdbstub64.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/target/arm/gdbstub64.c b/target/arm/gdbstub64.c index 64ee9b3..4fce58d 100644 --- a/target/arm/gdbstub64.c +++ b/target/arm/gdbstub64.c @@ -115,8 +115,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_big_endian() (which is + * only true for us for aarch64_be-linux-user). + */ + if (target_big_endian()) { + 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: |