Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] MIPS/Linux: Signal frame support for DSP registers
@ 2012-05-21 15:44 Maciej W. Rozycki
  2012-05-21 16:31 ` Eli Zaretskii
  0 siblings, 1 reply; 4+ messages in thread
From: Maciej W. Rozycki @ 2012-05-21 15:44 UTC (permalink / raw)
  To: gdb-patches; +Cc: Eli Zaretskii

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 <signal.h>
#include <stddef.h>

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  <macro@codesourcery.com>

	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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] MIPS/Linux: Signal frame support for DSP registers
  2012-05-21 15:44 [PATCH] MIPS/Linux: Signal frame support for DSP registers Maciej W. Rozycki
@ 2012-05-21 16:31 ` Eli Zaretskii
  2012-05-21 17:10   ` Maciej W. Rozycki
  0 siblings, 1 reply; 4+ messages in thread
From: Eli Zaretskii @ 2012-05-21 16:31 UTC (permalink / raw)
  To: Maciej W. Rozycki; +Cc: gdb-patches

> Date: Mon, 21 May 2012 16:43:58 +0100
> From: "Maciej W. Rozycki" <macro@codesourcery.com>
> CC: Eli Zaretskii <eliz@gnu.org>
> 
>  Eli, can you tell me if the NEWS entry is OK with you?

Yes, thanks.

> 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.

Hmm... since you mention that, I looked into configure.tgt and saw
that we are inconsistent here: some targets are described as running
"GNU/Linux", others just "Linux".  Personally, I think "GNU/Linux" is
the more correct in this case (you refer to a target system), but it's
not my call.


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] MIPS/Linux: Signal frame support for DSP registers
  2012-05-21 16:31 ` Eli Zaretskii
@ 2012-05-21 17:10   ` Maciej W. Rozycki
  2012-05-22 17:17     ` Maciej W. Rozycki
  0 siblings, 1 reply; 4+ messages in thread
From: Maciej W. Rozycki @ 2012-05-21 17:10 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: gdb-patches

On Mon, 21 May 2012, Eli Zaretskii wrote:

> >  Eli, can you tell me if the NEWS entry is OK with you?
> 
> Yes, thanks.

 Great!  I'll push the change then.

> > 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.
> 
> Hmm... since you mention that, I looked into configure.tgt and saw
> that we are inconsistent here: some targets are described as running
> "GNU/Linux", others just "Linux".  Personally, I think "GNU/Linux" is
> the more correct in this case (you refer to a target system), but it's
> not my call.

 After some thinking I've concluded it's an interesting question actually.  
Some target properties are libc-specific, for example the system library 
is free to map any magic numbers used for kernel syscalls however it likes 
(things like fcntl flags or whatever) and the library calls may not 
identity map to syscalls, so these will be libc- rather than 
kernel-specific.

 Here I don't think the system library can do anything, the signal frame 
and the associated bits are arranged by the kernel directly and the layout 
of struct ucontext_t is cast in stone.  One can stuff a hypothetical BSD C 
library on top of the Linux kernel and our MIPS DSP support will work with 
that unchanged.

 A less hypothetical case is an embedded app running on Linux without libc 
and I believe such stuff actually exists (and GDB can debug it provided 
that they have a remote stub of some sort available).

 Thanks for your notes.

  Maciej


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH] MIPS/Linux: Signal frame support for DSP registers
  2012-05-21 17:10   ` Maciej W. Rozycki
@ 2012-05-22 17:17     ` Maciej W. Rozycki
  0 siblings, 0 replies; 4+ messages in thread
From: Maciej W. Rozycki @ 2012-05-22 17:17 UTC (permalink / raw)
  To: gdb-patches; +Cc: Eli Zaretskii

On Mon, 21 May 2012, Maciej W. Rozycki wrote:

> > >  Eli, can you tell me if the NEWS entry is OK with you?
> > 
> > Yes, thanks.
> 
>  Great!  I'll push the change then.

 So this is now in; I'll see how I can wire the manual test case quoted 
into the gdb.arch testsuite sometime, it would be good to have actually 
(like the MIPS16 case this needs some care in checking toolchain and 
target support for the feature).

  Maciej


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2012-05-22 17:17 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-05-21 15:44 [PATCH] MIPS/Linux: Signal frame support for DSP registers Maciej W. Rozycki
2012-05-21 16:31 ` Eli Zaretskii
2012-05-21 17:10   ` Maciej W. Rozycki
2012-05-22 17:17     ` Maciej W. Rozycki

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox