]> git.ipfire.org Git - thirdparty/qemu.git/commitdiff
target/arm: Fix handling of setting SVE registers from gdb
authorVacha Bhavsar <vacha.bhavsar@oss.qualcomm.com>
Tue, 22 Jul 2025 17:37:36 +0000 (17:37 +0000)
committerPeter Maydell <peter.maydell@linaro.org>
Fri, 1 Aug 2025 15:48:50 +0000 (16:48 +0100)
The code to handle setting SVE registers via the gdbstub is broken:
 * it sets each pair of elements in the zregs[].d[] array in the
   wrong order for the most common (little endian) case: the least
   significant 64-bit value comes first
 * it makes no attempt to handle target_endian()
 * it does a simple copy out of the (target endian) gdbstub buffer
   into the (host endan) zregs data structure, which is wrong on
   big endian hosts

Fix all these problems:
 * use ldq_p() to read from the gdbstub buffer
 * check target_big_endian() to see if we need to handle the
   128-bit values the opposite way around

Cc: qemu-stable@nongnu.org
Signed-off-by: Vacha Bhavsar <vacha.bhavsar@oss.qualcomm.com>
Message-id: 20250722173736.2332529-3-vacha.bhavsar@oss.qualcomm.com
[PMM: adjusted commit message, fixed spacing]
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
target/arm/gdbstub64.c

index 4fce58d895ee9d82ae0c9418de804341de08c744..08e28585396816ab90d6d8e460ff8171892fe8da 100644 (file)
@@ -206,10 +206,17 @@ int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg)
     case 0 ... 31:
     {
         int vq, len = 0;
-        uint64_t *p = (uint64_t *) buf;
         for (vq = 0; vq < cpu->sve_max_vq; vq++) {
-            env->vfp.zregs[reg].d[vq * 2 + 1] = *p++;
-            env->vfp.zregs[reg].d[vq * 2] = *p++;
+            if (target_big_endian()) {
+                env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf);
+                buf += 8;
+                env->vfp.zregs[reg].d[vq * 2] = ldq_p(buf);
+            } else{
+                env->vfp.zregs[reg].d[vq * 2] = ldq_p(buf);
+                buf += 8;
+                env->vfp.zregs[reg].d[vq * 2 + 1] = ldq_p(buf);
+            }
+            buf += 8;
             len += 16;
         }
         return len;
@@ -224,9 +231,9 @@ int aarch64_gdb_set_sve_reg(CPUState *cs, uint8_t *buf, int reg)
     {
         int preg = reg - 34;
         int vq, len = 0;
-        uint64_t *p = (uint64_t *) buf;
         for (vq = 0; vq < cpu->sve_max_vq; vq = vq + 4) {
-            env->vfp.pregs[preg].p[vq / 4] = *p++;
+            env->vfp.pregs[preg].p[vq / 4] = ldq_p(buf);
+            buf += 8;
             len += 8;
         }
         return len;