From patchwork Wed Dec 10 18:54:17 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 419820 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id BFADA14009B for ; Thu, 11 Dec 2014 05:55:20 +1100 (AEDT) Received: from localhost ([::1]:47372 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XymPu-0005ty-Ll for incoming@patchwork.ozlabs.org; Wed, 10 Dec 2014 13:55:18 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44960) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XymPB-0004hM-Mm for qemu-devel@nongnu.org; Wed, 10 Dec 2014 13:54:40 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XymP2-0003p6-8W for qemu-devel@nongnu.org; Wed, 10 Dec 2014 13:54:33 -0500 Received: from relay1.mentorg.com ([192.94.38.131]:61372) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XymP1-0003ox-P6 for qemu-devel@nongnu.org; Wed, 10 Dec 2014 13:54:24 -0500 Received: from nat-ies.mentorg.com ([192.94.31.2] helo=SVR-IES-FEM-01.mgc.mentorg.com) by relay1.mentorg.com with esmtp id 1XymP0-0004Wh-MG from Maciej_Rozycki@mentor.com ; Wed, 10 Dec 2014 10:54:23 -0800 Received: from localhost (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server (TLS) id 14.3.181.6; Wed, 10 Dec 2014 18:54:20 +0000 Date: Wed, 10 Dec 2014 18:54:17 +0000 From: "Maciej W. Rozycki" To: In-Reply-To: Message-ID: References: User-Agent: Alpine 1.10 (DEB 962 2008-03-14) MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: Windows NT kernel [generic] [fuzzy] X-Received-From: 192.94.38.131 Cc: Leon Alrae , Aurelien Jarno Subject: [Qemu-devel] [PATCH 3/3] target-mips: Set GDB register widths correctly X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org 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 --- 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