From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13588 invoked by alias); 21 May 2012 15:44:31 -0000 Received: (qmail 13567 invoked by uid 22791); 21 May 2012 15:44:27 -0000 X-SWARE-Spam-Status: No, hits=-3.4 required=5.0 tests=AWL,BAYES_00,FROM_12LTRDOM,KHOP_RCVD_UNTRUST,RCVD_IN_HOSTKARMA_W,RCVD_IN_HOSTKARMA_WL,TW_EG X-Spam-Check-By: sourceware.org Received: from relay1.mentorg.com (HELO relay1.mentorg.com) (192.94.38.131) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 21 May 2012 15:44:11 +0000 Received: from svr-orw-fem-01.mgc.mentorg.com ([147.34.98.93]) by relay1.mentorg.com with esmtp id 1SWUmI-0007RM-9z from Maciej_Rozycki@mentor.com ; Mon, 21 May 2012 08:44:10 -0700 Received: from SVR-IES-FEM-01.mgc.mentorg.com ([137.202.0.104]) by svr-orw-fem-01.mgc.mentorg.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.4675); Mon, 21 May 2012 08:44:10 -0700 Received: from [172.30.0.105] (137.202.0.76) by SVR-IES-FEM-01.mgc.mentorg.com (137.202.0.104) with Microsoft SMTP Server id 14.1.289.1; Mon, 21 May 2012 16:44:07 +0100 Date: Mon, 21 May 2012 15:44:00 -0000 From: "Maciej W. Rozycki" To: CC: Eli Zaretskii Subject: [PATCH] MIPS/Linux: Signal frame support for DSP registers Message-ID: User-Agent: Alpine 1.10 (DEB 962 2008-03-14) MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2012-05/txt/msg00773.txt.bz2 Hello, Here's a change for signal frame handling that I realised after recent microMIPS considerations that is needed to complement MIPS/Linux DSP register support that I added not so long ago. There are no regressions in mips-linux-gnu test suite, but I believe signal frame handling is not really well covered there, not at least as far as MIPS DSP support is concerned. I have therefore used the following trivial program to make sure unwinding works correctly through a signal frame: $ cat dspmult.c #include #include static void segvaction (int signo, siginfo_t *info, void *context) { register unsigned long long acc0; register unsigned long long acc1; register unsigned long long acc2; register unsigned long long acc3; ucontext_t *uc = context; asm volatile ("multu %q0, %1, %2" : "=a" (acc0) : "r" (0xc0000011), "r" (2)); asm volatile ("multu %q0, %1, %2" : "=a" (acc1) : "r" (0xc0000011), "r" (4)); asm volatile ("multu %q0, %1, %2" : "=a" (acc2) : "r" (0xc0000011), "r" (8)); asm volatile ("multu %q0, %1, %2" : "=a" (acc3) : "r" (0xc0000011), "r" (16)); asm volatile ("wrdsp %0" : : "r" (0xaa55aa55)); asm volatile ("" : : "a" (acc0), "a" (acc1), "a" (acc2), "a" (acc3)); asm volatile ("teq $0, $0"); } int main (void) { struct sigaction act = { .sa_sigaction = segvaction, .sa_flags = SA_SIGINFO | SA_NODEFER, }; register unsigned long long acc0; register unsigned long long acc1; register unsigned long long acc2; register unsigned long long acc3; sigemptyset (&act.sa_mask); sigaction (SIGSEGV, &act, NULL); asm volatile ("mtc1 $0, $f0"); asm volatile ("multu %q0, %1, %2" : "=a" (acc0) : "r" (0x80000001), "r" (2)); asm volatile ("multu %q0, %1, %2" : "=a" (acc1) : "r" (0x80000001), "r" (4)); asm volatile ("multu %q0, %1, %2" : "=a" (acc2) : "r" (0x80000001), "r" (8)); asm volatile ("multu %q0, %1, %2" : "=a" (acc3) : "r" (0x80000001), "r" (16)); asm volatile ("wrdsp %0" : : "r" (0x55aa55aa)); asm volatile ("" : : "a" (acc0), "a" (acc1), "a" (acc2), "a" (acc3)); asm volatile ("lw $0, 0($0)"); return 0; } While accessing main's DSP registers from the context of segvaction correct original values are reported after my change has been applied, while before -- it's the current values that are. I have verified the values reported (as printed by "info registers") are consistent with the values in uc as well. While at it I realised this new feature really deserves a NEWS entry which I originally didn't think of and given that we haven't made a release with MIPS DSP support yet I would like to take this opportunity and fix this mistake. Eli, can you tell me if the NEWS entry is OK with you? Please note that I deliberately say "Linux" rather than "GNU/Linux" here as all the DSP support relies on a kernel feature; it does not rely on any C library or other userland feature whatsoever. Thanks. 2012-05-21 Maciej W. Rozycki gdb/ * NEWS: Add MIPS/Linux DSP support. * mips-linux-tdep.c: Document post-2.6.12 o32 sigcontext layout. (SIGCONTEXT_DSPCTL): New macro. (SIGCONTEXT_HI1, SIGCONTEXT_LO1): Likewise. (SIGCONTEXT_HI2, SIGCONTEXT_LO2): Likewise. (SIGCONTEXT_HI3, SIGCONTEXT_LO3): Likewise. (N64_SIGCONTEXT_HI1, N64_SIGCONTEXT_HI2): Likewise. (N64_SIGCONTEXT_HI3): Likewise. (N64_SIGCONTEXT_LO1, N64_SIGCONTEXT_LO2): Likewise. (N64_SIGCONTEXT_LO3): Likewise. (N64_SIGCONTEXT_DSPCTL): Likewise. (N64_SIGCONTEXT_FPCSR): Clarify definition. (mips_linux_o32_sigframe_init): Handle DSP registers. (mips_linux_n32n64_sigframe_init): Likewise. NB the way N64_SIGCONTEXT_FPCSR is defined and mips_linux_n32n64_sigframe_init implemented makes me suspect we get the value of the FP CSR wrong in the 64-bit case -- it's a 32-bit register and code elsewhere assumes it's 64-bit, so presumably will access the whole register slot rather than the right half of it. I'll have to check it. Maciej gdb-mips-dsp-sigtramp.diff Index: gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c =================================================================== --- gdb-fsf-trunk-quilt.orig/gdb/mips-linux-tdep.c 2012-05-20 16:26:05.000000000 +0100 +++ gdb-fsf-trunk-quilt/gdb/mips-linux-tdep.c 2012-05-20 16:26:10.845566830 +0100 @@ -940,6 +940,8 @@ static const struct tramp_frame micromip sigset_t sf_mask; }; + Pre-2.6.12 sigcontext: + struct sigcontext { unsigned int sc_regmask; [Unused] unsigned int sc_status; @@ -961,6 +963,30 @@ static const struct tramp_frame micromip unsigned long sc_sigset[4]; [kernel's sigset_t] }; + Post-2.6.12 sigcontext (SmartMIPS/DSP support added): + + struct sigcontext { + unsigned int sc_regmask; [Unused] + unsigned int sc_status; [Unused] + unsigned long long sc_pc; + unsigned long long sc_regs[32]; + unsigned long long sc_fpregs[32]; + unsigned int sc_acx; + unsigned int sc_fpc_csr; + unsigned int sc_fpc_eir; [Unused] + unsigned int sc_used_math; + unsigned int sc_dsp; + [Alignment hole of four bytes] + unsigned long long sc_mdhi; + unsigned long long sc_mdlo; + unsigned long sc_hi1; + unsigned long sc_lo1; + unsigned long sc_hi2; + unsigned long sc_lo2; + unsigned long sc_hi3; + unsigned long sc_lo3; + }; + The RT signal frames look like this: struct rt_sigframe { @@ -993,10 +1019,17 @@ static const struct tramp_frame micromip #define SIGCONTEXT_REGS (2 * 8) #define SIGCONTEXT_FPREGS (34 * 8) #define SIGCONTEXT_FPCSR (66 * 8 + 4) +#define SIGCONTEXT_DSPCTL (68 * 8 + 0) #define SIGCONTEXT_HI (69 * 8) #define SIGCONTEXT_LO (70 * 8) #define SIGCONTEXT_CAUSE (71 * 8 + 0) #define SIGCONTEXT_BADVADDR (71 * 8 + 4) +#define SIGCONTEXT_HI1 (71 * 8 + 0) +#define SIGCONTEXT_LO1 (71 * 8 + 4) +#define SIGCONTEXT_HI2 (72 * 8 + 0) +#define SIGCONTEXT_LO2 (72 * 8 + 4) +#define SIGCONTEXT_HI3 (73 * 8 + 0) +#define SIGCONTEXT_LO3 (73 * 8 + 4) #define SIGCONTEXT_REG_SIZE 8 @@ -1072,18 +1105,49 @@ mips_linux_o32_sigframe_init (const stru regs->fp_control_status + gdbarch_num_regs (gdbarch), sigcontext_base + SIGCONTEXT_FPCSR); + + if (regs->dspctl != -1) + trad_frame_set_reg_addr (this_cache, + regs->dspctl + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_DSPCTL); + trad_frame_set_reg_addr (this_cache, regs->hi + gdbarch_num_regs (gdbarch), regs_base + SIGCONTEXT_HI); trad_frame_set_reg_addr (this_cache, regs->lo + gdbarch_num_regs (gdbarch), regs_base + SIGCONTEXT_LO); - trad_frame_set_reg_addr (this_cache, - regs->cause + gdbarch_num_regs (gdbarch), - sigcontext_base + SIGCONTEXT_CAUSE); - trad_frame_set_reg_addr (this_cache, - regs->badvaddr + gdbarch_num_regs (gdbarch), - sigcontext_base + SIGCONTEXT_BADVADDR); + + if (regs->dspacc != -1) + { + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 0 + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_HI1); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 1 + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_LO1); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 2 + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_HI2); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 3 + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_LO2); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 4 + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_HI3); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 5 + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_LO3); + } + else + { + trad_frame_set_reg_addr (this_cache, + regs->cause + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_CAUSE); + trad_frame_set_reg_addr (this_cache, + regs->badvaddr + gdbarch_num_regs (gdbarch), + sigcontext_base + SIGCONTEXT_BADVADDR); + } /* Choice of the bottom of the sigframe is somewhat arbitrary. */ trad_frame_set_id (this_cache, frame_id_build (frame_sp, func)); @@ -1161,9 +1225,16 @@ mips_linux_o32_sigframe_init (const stru #define N64_SIGCONTEXT_REGS (0 * 8) #define N64_SIGCONTEXT_FPREGS (32 * 8) #define N64_SIGCONTEXT_HI (64 * 8) +#define N64_SIGCONTEXT_HI1 (65 * 8) +#define N64_SIGCONTEXT_HI2 (66 * 8) +#define N64_SIGCONTEXT_HI3 (67 * 8) #define N64_SIGCONTEXT_LO (68 * 8) +#define N64_SIGCONTEXT_LO1 (69 * 8) +#define N64_SIGCONTEXT_LO2 (70 * 8) +#define N64_SIGCONTEXT_LO3 (71 * 8) #define N64_SIGCONTEXT_PC (72 * 8) -#define N64_SIGCONTEXT_FPCSR (73 * 8) +#define N64_SIGCONTEXT_FPCSR (73 * 8 + 0) +#define N64_SIGCONTEXT_DSPCTL (74 * 8 + 0) #define N64_SIGCONTEXT_REG_SIZE 8 @@ -1213,6 +1284,7 @@ mips_linux_n32n64_sigframe_init (const s regs->fp_control_status + gdbarch_num_regs (gdbarch), sigcontext_base + N64_SIGCONTEXT_FPCSR); + trad_frame_set_reg_addr (this_cache, regs->hi + gdbarch_num_regs (gdbarch), sigcontext_base + N64_SIGCONTEXT_HI); @@ -1220,6 +1292,32 @@ mips_linux_n32n64_sigframe_init (const s regs->lo + gdbarch_num_regs (gdbarch), sigcontext_base + N64_SIGCONTEXT_LO); + if (regs->dspacc != -1) + { + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 0 + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_HI1); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 1 + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_LO1); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 2 + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_HI2); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 3 + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_LO2); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 4 + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_HI3); + trad_frame_set_reg_addr (this_cache, + regs->dspacc + 5 + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_LO3); + } + if (regs->dspctl != -1) + trad_frame_set_reg_addr (this_cache, + regs->dspctl + gdbarch_num_regs (gdbarch), + sigcontext_base + N64_SIGCONTEXT_DSPCTL); + /* Choice of the bottom of the sigframe is somewhat arbitrary. */ trad_frame_set_id (this_cache, frame_id_build (frame_sp, func)); } Index: gdb-fsf-trunk-quilt/gdb/NEWS =================================================================== --- gdb-fsf-trunk-quilt.orig/gdb/NEWS 2012-05-20 16:26:04.000000000 +0100 +++ gdb-fsf-trunk-quilt/gdb/NEWS 2012-05-20 16:29:02.275560354 +0100 @@ -3,6 +3,8 @@ *** Changes since GDB 7.4 +* GDB now supports access to MIPS DSP registers on Linux targets. + * GDB now supports debugging microMIPS binaries. * The "info os" command on GNU/Linux can now display information on