qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 3/3] target-mips: Set GDB register widths correctly


From: Maciej W. Rozycki
Subject: [Qemu-devel] [PATCH 3/3] target-mips: Set GDB register widths correctly
Date: Wed, 10 Dec 2014 18:54:17 +0000
User-agent: Alpine 1.10 (DEB 962 2008-03-14)

Set register widths in the GDB stub as follows:

- for the system emulation mode -- to the native register size of the 
  processor selected, any MIPS I, MIPS II or MIPS32 (any revision) 
  processor will have 32-bit general purpose registers and any MIPS III, 
  MIPS IV or MIPS64 (again, any revision) will have 64-bit general 
  purpose registers,

- for the user emulation mode -- to the register size defined by the 
  ABI, that is the emulation of the o32 ABI will have 32-bit general 
  purpose registers and the emulation of the n32 and n64 ABIs will have 
  64-bit general purpose registers.

With the the user emulation mode, the o32 ABI and a 64-bit processor 
selected handle native 64-bit registers such that on reads they are 
truncated to low 32 bits only and on writes the 32-bit value stored is 
sign-extended from bit #31, which is how hardware instructions supported 
with the o32 ABI have been defined in the architecture.

Also correctly wrap the address space in the 32-bit o32 and n32 ABIs by 
sign-extending any addresses processed from bit #31, matching how the 
hardware operates in the user mode according to CP0.Status.UX == 0 and 
CP0.Status.PX == 0 (for o32) and CP0.Status.UX == 0 and CP0.Status.PX == 
1 (for n32).  This is also how GDB works operating on real processors in 
conjunction with JTAG hardware and associated debug-mode firmware across 
all execution modes.

As a side effect fix the case where registers are presented as 64-bit 
quantities while talking to a 32-bit processor.

Signed-off-by: Maciej W. Rozycki <address@hidden>
---
qemu-mips-regsize.diff
Index: qemu-git-trunk/gdbstub.c
===================================================================
--- qemu-git-trunk.orig/gdbstub.c       2014-12-05 18:38:40.847529339 +0000
+++ qemu-git-trunk/gdbstub.c    2014-12-05 18:41:00.358928442 +0000
@@ -789,7 +789,7 @@ static int gdb_handle_packet(GDBState *s
         break;
     case 'c':
         if (*p != '\0') {
-            addr = strtoull(p, (char **)&p, 16);
+            addr = target_address(s->c_cpu, strtoull(p, (char **)&p, 16));
             gdb_set_cpu_pc(s, addr);
         }
         s->signal = 0;
@@ -875,7 +875,7 @@ static int gdb_handle_packet(GDBState *s
         break;
     case 's':
         if (*p != '\0') {
-            addr = strtoull(p, (char **)&p, 16);
+            addr = target_address(s->c_cpu, strtoull(p, (char **)&p, 16));
             gdb_set_cpu_pc(s, addr);
         }
         cpu_single_step(s->c_cpu, sstep_flags);
@@ -930,7 +930,7 @@ static int gdb_handle_packet(GDBState *s
         put_packet(s, "OK");
         break;
     case 'm':
-        addr = strtoull(p, (char **)&p, 16);
+        addr = target_address(s->g_cpu, strtoull(p, (char **)&p, 16));
         if (*p == ',')
             p++;
         len = strtoull(p, NULL, 16);
@@ -942,7 +942,7 @@ static int gdb_handle_packet(GDBState *s
         }
         break;
     case 'M':
-        addr = strtoull(p, (char **)&p, 16);
+        addr = target_address(s->g_cpu, strtoull(p, (char **)&p, 16));
         if (*p == ',')
             p++;
         len = strtoull(p, (char **)&p, 16);
@@ -987,7 +987,7 @@ static int gdb_handle_packet(GDBState *s
         type = strtoul(p, (char **)&p, 16);
         if (*p == ',')
             p++;
-        addr = strtoull(p, (char **)&p, 16);
+        addr = target_address(s->g_cpu, strtoull(p, (char **)&p, 16));
         if (*p == ',')
             p++;
         len = strtoull(p, (char **)&p, 16);
Index: qemu-git-trunk/target-alpha/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-alpha/cpu.h      2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-alpha/cpu.h   2014-12-05 18:41:00.358928442 +0000
@@ -500,4 +500,7 @@ static inline void cpu_get_tb_cpu_state(
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /* !defined (__CPU_ALPHA_H__) */
Index: qemu-git-trunk/target-arm/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-arm/cpu.h        2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-arm/cpu.h     2014-12-05 18:41:00.358928442 +0000
@@ -1539,4 +1539,7 @@ enum {
     QEMU_PSCI_CONDUIT_HVC = 2,
 };
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-cris/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-cris/cpu.h       2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-cris/cpu.h    2014-12-05 18:41:00.358928442 +0000
@@ -277,4 +277,7 @@ void cris_cpu_list(FILE *f, fprintf_func
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-i386/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-i386/cpu.h       2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-i386/cpu.h    2014-12-05 18:41:00.358928442 +0000
@@ -1378,4 +1378,7 @@ void enable_compat_apic_id_mode(void);
 #define APIC_DEFAULT_ADDRESS 0xfee00000
 #define APIC_SPACE_SIZE      0x100000
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /* CPU_I386_H */
Index: qemu-git-trunk/target-lm32/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-lm32/cpu.h       2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-lm32/cpu.h    2014-12-05 18:41:00.358928442 +0000
@@ -248,4 +248,7 @@ static inline void cpu_get_tb_cpu_state(
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-m68k/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-m68k/cpu.h       2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-m68k/cpu.h    2014-12-05 18:41:00.358928442 +0000
@@ -254,4 +254,7 @@ static inline void cpu_get_tb_cpu_state(
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-microblaze/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-microblaze/cpu.h 2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-microblaze/cpu.h      2014-12-05 18:41:00.358928442 
+0000
@@ -364,4 +364,7 @@ void mb_cpu_unassigned_access(CPUState *
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-mips/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-mips/cpu.h       2014-12-05 18:40:55.358929758 
+0000
+++ qemu-git-trunk/target-mips/cpu.h    2014-12-05 18:41:00.358928442 +0000
@@ -1008,4 +1008,38 @@ static inline void cpu_mips_store_cause(
 }
 #endif
 
+/* Macros below used by gdbstub.  */
+#define target_address(cs, addr) mips_address(&MIPS_CPU(cs)->env, (addr))
+
+/* System emulation always uses the processor's native register size;
+   any processor that supports at least MIPS III instructions has 64-bit
+   registers.  User emulation uses the ABI register size.  */
+#ifndef CONFIG_USER_ONLY
+# define mips64_p(env) (((env)->insn_flags & ISA_MIPS3) != 0)
+# define mips_address(env, addr)                                        \
+    (mips64_p(env) ? (addr) : ((int64_t)(int32_t)(addr)))
+# define mips_get_reg(env, buf, val)                                    \
+    (mips64_p(env) ? gdb_get_reg64((buf), (val)) : gdb_get_reg32((buf), (val)))
+# define mips_set_reg(env, buf)                                         \
+    (mips64_p(env) ? ldq_p(buf) : ((int64_t)(int32_t)ldl_p(buf)))
+# define mips_regsize(env) (4 << mips64_p(env))
+#elif defined(TARGET_ABI_MIPSN64)
+# define mips_address(env, addr) (addr)
+# define mips_get_reg(env, buf, val) gdb_get_reg64((buf), (val))
+# define mips_set_reg(env, buf) ldq_p(buf)
+# define mips_regsize(env) 8
+#elif defined(TARGET_ABI_MIPSN32)
+# define mips_address(env, addr) ((int64_t)(int32_t)(addr))
+# define mips_get_reg(env, buf, val) gdb_get_reg64((buf), (val))
+# define mips_set_reg(env, buf) ldq_p(buf)
+# define mips_regsize(env) 8
+#elif defined(TARGET_ABI_MIPSO32)
+# define mips_address(env, addr) ((int64_t)(int32_t)(addr))
+# define mips_get_reg(env, buf, val) gdb_get_reg32((buf), (val))
+# define mips_set_reg(env, buf) (((int64_t)(int32_t)ldl_p(buf)))
+# define mips_regsize(env) 4
+#else
+# error Unsupported user-mode MIPS ABI
+#endif
+
 #endif /* !defined (__MIPS_CPU_H__) */
Index: qemu-git-trunk/target-mips/gdbstub.c
===================================================================
--- qemu-git-trunk.orig/target-mips/gdbstub.c   2014-12-05 18:40:52.857534413 
+0000
+++ qemu-git-trunk/target-mips/gdbstub.c        2014-12-05 18:41:00.358928442 
+0000
@@ -21,54 +21,56 @@
 #include "qemu-common.h"
 #include "exec/gdbstub.h"
 
+#include "cpu.h"
+
 int mips_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
 {
     MIPSCPU *cpu = MIPS_CPU(cs);
     CPUMIPSState *env = &cpu->env;
 
     if (n < 32) {
-        return gdb_get_regl(mem_buf, env->active_tc.gpr[n]);
+        return mips_get_reg(env, mem_buf, env->active_tc.gpr[n]);
     }
     if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
         switch (n) {
         case 70:
-            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr31);
+            return mips_get_reg(env, mem_buf, (int32_t)env->active_fpu.fcr31);
         case 71:
-            return gdb_get_regl(mem_buf, (int32_t)env->active_fpu.fcr0);
+            return mips_get_reg(env, mem_buf, (int32_t)env->active_fpu.fcr0);
         default:
             if (env->CP0_Status & (1 << CP0St_FR)) {
-                return gdb_get_regl(mem_buf,
+                return mips_get_reg(env, mem_buf,
                     env->active_fpu.fpr[n - 38].d);
             } else {
-                return gdb_get_regl(mem_buf,
+                return mips_get_reg(env, mem_buf,
                     env->active_fpu.fpr[n - 38].w[FP_ENDIAN_IDX]);
             }
         }
     }
     switch (n) {
     case 32:
-        return gdb_get_regl(mem_buf, (int32_t)env->CP0_Status);
+        return mips_get_reg(env, mem_buf, (int32_t)env->CP0_Status);
     case 33:
-        return gdb_get_regl(mem_buf, env->active_tc.LO[0]);
+        return mips_get_reg(env, mem_buf, env->active_tc.LO[0]);
     case 34:
-        return gdb_get_regl(mem_buf, env->active_tc.HI[0]);
+        return mips_get_reg(env, mem_buf, env->active_tc.HI[0]);
     case 35:
-        return gdb_get_regl(mem_buf, env->CP0_BadVAddr);
+        return mips_get_reg(env, mem_buf, env->CP0_BadVAddr);
     case 36:
-        return gdb_get_regl(mem_buf, (int32_t)env->CP0_Cause);
+        return mips_get_reg(env, mem_buf, (int32_t)env->CP0_Cause);
     case 37:
-        return gdb_get_regl(mem_buf, env->active_tc.PC |
-                                     !!(env->hflags & MIPS_HFLAG_M16));
+        return mips_get_reg(env, mem_buf, env->active_tc.PC |
+                                          !!(env->hflags & MIPS_HFLAG_M16));
     case 72:
-        return gdb_get_regl(mem_buf, 0); /* fp */
+        return mips_get_reg(env, mem_buf, 0); /* fp */
     case 89:
-        return gdb_get_regl(mem_buf, (int32_t)env->CP0_PRid);
+        return mips_get_reg(env, mem_buf, (int32_t)env->CP0_PRid);
     default:
         if (n > 89) {
             return 0;
         }
         /* 16 embedded regs.  */
-        return gdb_get_regl(mem_buf, 0);
+        return mips_get_reg(env, mem_buf, 0);
     }
 
     return 0;
@@ -80,11 +82,11 @@ int mips_cpu_gdb_write_register(CPUState
     CPUMIPSState *env = &cpu->env;
     target_ulong tmp;
 
-    tmp = ldtul_p(mem_buf);
+    tmp = mips_set_reg(env, mem_buf);
 
     if (n < 32) {
         env->active_tc.gpr[n] = tmp;
-        return sizeof(target_ulong);
+        return mips_regsize(env);
     }
     if (env->CP0_Config1 & (1 << CP0C1_FP) && n >= 38 && n < 72) {
         switch (n) {
@@ -106,7 +108,7 @@ int mips_cpu_gdb_write_register(CPUState
             }
             break;
         }
-        return sizeof(target_ulong);
+        return mips_regsize(env);
     }
     switch (n) {
     case 32:
@@ -146,5 +148,5 @@ int mips_cpu_gdb_write_register(CPUState
         break;
     }
 
-    return sizeof(target_ulong);
+    return mips_regsize(env);
 }
Index: qemu-git-trunk/target-moxie/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-moxie/cpu.h      2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-moxie/cpu.h   2014-12-05 18:41:00.358928442 +0000
@@ -155,4 +155,7 @@ static inline void cpu_get_tb_cpu_state(
 int moxie_cpu_handle_mmu_fault(CPUState *cpu, vaddr address,
                                int rw, int mmu_idx);
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /* _CPU_MOXIE_H */
Index: qemu-git-trunk/target-openrisc/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-openrisc/cpu.h   2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-openrisc/cpu.h        2014-12-05 18:41:00.358928442 
+0000
@@ -427,4 +427,7 @@ static inline target_ulong cpu_get_pc(CP
     return env->pc;
 }
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /* CPU_OPENRISC_H */
Index: qemu-git-trunk/target-ppc/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-ppc/cpu.h        2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-ppc/cpu.h     2014-12-05 18:41:00.358928442 +0000
@@ -2310,4 +2310,7 @@ int ppc_get_vcpu_dt_id(PowerPCCPU *cpu);
  */
 PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id);
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /* !defined (__CPU_PPC_H__) */
Index: qemu-git-trunk/target-s390x/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-s390x/cpu.h      2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-s390x/cpu.h   2014-12-05 18:41:00.858923584 +0000
@@ -1149,4 +1149,7 @@ static inline int s390_assign_subch_ioev
     }
 }
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-sh4/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-sh4/cpu.h        2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-sh4/cpu.h     2014-12-05 18:41:00.858923584 +0000
@@ -354,4 +354,7 @@ static inline void cpu_get_tb_cpu_state(
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif                         /* _CPU_SH4_H */
Index: qemu-git-trunk/target-sparc/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-sparc/cpu.h      2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-sparc/cpu.h   2014-12-05 18:41:00.858923584 +0000
@@ -753,4 +753,7 @@ static inline bool tb_am_enabled(int tb_
 
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif
Index: qemu-git-trunk/target-tricore/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-tricore/cpu.h    2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-tricore/cpu.h 2014-12-05 18:41:00.858923584 +0000
@@ -400,4 +400,7 @@ static inline void cpu_pc_from_tb(CPUTri
     env->PC = tb->pc;
 }
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /*__TRICORE_CPU_H__ */
Index: qemu-git-trunk/target-unicore32/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-unicore32/cpu.h  2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-unicore32/cpu.h       2014-12-05 18:41:00.858923584 
+0000
@@ -159,4 +159,7 @@ int uc32_cpu_handle_mmu_fault(CPUState *
 void uc32_translate_init(void);
 void switch_mode(CPUUniCore32State *, int);
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif /* QEMU_UNICORE32_CPU_H */
Index: qemu-git-trunk/target-xtensa/cpu.h
===================================================================
--- qemu-git-trunk.orig/target-xtensa/cpu.h     2014-12-05 18:38:40.847529339 
+0000
+++ qemu-git-trunk/target-xtensa/cpu.h  2014-12-05 18:41:00.858923584 +0000
@@ -533,4 +533,7 @@ static inline void cpu_get_tb_cpu_state(
 #include "exec/cpu-all.h"
 #include "exec/exec-all.h"
 
+/* Used by gdbstub.  */
+#define target_address(cs, addr) (addr)
+
 #endif



reply via email to

[Prev in Thread] Current Thread [Next in Thread]