* [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