* patch: POSIX.1b signals for ppc
@ 2000-04-14 14:54 Giovanna Ambrosini
0 siblings, 0 replies; 7+ messages in thread
From: Giovanna Ambrosini @ 2000-04-14 14:54 UTC (permalink / raw)
To: cort, paulus, linuxppc-dev
Hello,
I added the support for calling a signal handler with three arguments:
signo, siginfo and the ucontext . Althogh it's been tested on a ppc850 platform,
I would like to ask you to test it on other ppc platforms.
diff -urN linux-2.3.99-pre5/arch/ppc/kernel/entry.S linux-2.3.99-pre5-ga/arch/ppc/kernel/entry.S
--- linux-2.3.99-pre5/arch/ppc/kernel/entry.S Mon Mar 6 16:52:14 2000
+++ linux-2.3.99-pre5-ga/arch/ppc/kernel/entry.S Fri Apr 14 10:37:22 2000
@@ -20,6 +20,10 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * 2000-04-10.
+ * Add sys_rt_sigreturn in DoSyscall Handler.
+ * Giovanna Ambrosini (ambrosini@lightning.ch).
*
*/
@@ -83,6 +87,8 @@
#endif /* SHOW_SYSCALLS */
cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
beq- 10f
+ cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */
+ beq- 16f
lwz r10,TASK_FLAGS(r2)
andi. r10,r10,PF_TRACESYS
bne- 50f
@@ -129,6 +135,12 @@
/* sys_sigreturn */
10: addi r3,r1,STACK_FRAME_OVERHEAD
bl sys_sigreturn
+ cmpi 0,r3,0 /* Check for restarted system call */
+ bge ret_from_except
+ b 20b
+/* sys_rt_sigreturn */
+16: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl sys_rt_sigreturn
cmpi 0,r3,0 /* Check for restarted system call */
bge ret_from_except
b 20b
diff -urN linux-2.3.99-pre5/arch/ppc/kernel/signal.c linux-2.3.99-pre5-ga/arch/ppc/kernel/signal.c
--- linux-2.3.99-pre5/arch/ppc/kernel/signal.c Tue Dec 14 15:40:29 1999
+++ linux-2.3.99-pre5-ga/arch/ppc/kernel/signal.c Fri Apr 14 14:25:11 2000
@@ -14,6 +14,16 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ *
+ * 2000-04-7.
+ * Define a real-time signal frame with siginfo and ucontext
+ * structures (setup_rt_frame()).
+ * Stuck up a real-time signal frame when setting the signal
+ * frame with SA_SIGINFO flags.
+ * Add sys_rt_sigreturn() to undo the signal stack.
+ *
+ * Giovanna Ambrosini (ambrosini@lightning.ch)
*/
#include <linux/sched.h>
@@ -121,13 +131,6 @@
}
-asmlinkage int sys_rt_sigreturn(unsigned long __unused)
-{
- printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n",
- current->comm,current->pid);
- do_exit(SIGSEGV);
-}
-
asmlinkage int
sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{
@@ -171,13 +174,11 @@
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
- * one or more sigcontext structs
+ * one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
- * XXX ultimately we will have to stack up a siginfo and ucontext
- * for each rt signal.
*/
struct sigregs {
elf_gregset_t gp_regs;
@@ -188,6 +189,15 @@
int abigap[56];
};
+struct rt_sigframe
+{
+ unsigned long _unused[2];
+ struct siginfo *pinfo;
+ void *puc;
+ struct siginfo info;
+ struct ucontext uc;
+};
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -255,6 +265,91 @@
do_exit(SIGSEGV);
}
+
+/*
+ * When we have rt signals to deliver, we set up on the
+ * user stack, going down from the original stack pointer:
+ * a sigregs struct
+ * one rt_sigframe struct (siginfo + ucontext)
+ * a gap of __SIGNAL_FRAMESIZE bytes
+ *
+ * Each of these things must be a multiple of 16 bytes in size.
+ *
+ */
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *rt_sf;
+ struct sigcontext_struct sigctx;
+ struct sigregs *sr;
+ int ret;
+ elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
+ sigset_t set;
+ stack_t st;
+ unsigned long prevsp;
+
+ rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
+ || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
+ || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ rt_sf++; /* Look at next rt_sigframe */
+ if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) {
+ /* Last stacked signal - restore registers -
+ * sigctx is initialized to point to the
+ * preamble frame (where registers are stored)
+ * see handle_signal()
+ */
+ sr = (struct sigregs *) sigctx.regs;
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);
+ if (copy_from_user(saved_regs, &sr->gp_regs,
+ sizeof(sr->gp_regs)))
+ goto badframe;
+ saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
+ | (saved_regs[PT_MSR] & MSR_USERCHANGE);
+ memcpy(regs, saved_regs, GP_REGS_SIZE);
+ if (copy_from_user(current->thread.fpr, &sr->fp_regs,
+ sizeof(sr->fp_regs)))
+ goto badframe;
+ /* This function sets back the stack flags into
+ the current task structure. */
+ sys_sigaltstack(&st, NULL);
+
+ ret = regs->result;
+ } else {
+ /* More signals to go */
+ /* Set up registers for next signal handler */
+ regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE;
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)))
+ goto badframe;
+ sr = (struct sigregs *) sigctx.regs;
+ regs->gpr[3] = ret = sigctx.signal;
+ /* Get the siginfo */
+ get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo);
+ /* Get the ucontext */
+ get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc);
+ regs->gpr[6] = (unsigned long) rt_sf;
+
+ regs->link = (unsigned long) &sr->tramp;
+ regs->nip = sigctx.handler;
+ if (get_user(prevsp, &sr->gp_regs[PT_R1])
+ || put_user(prevsp, (unsigned long *) regs->gpr[1]))
+ goto badframe;
+ }
+ return ret;
+
+badframe:
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
+
/*
* Set up a signal frame.
*/
@@ -297,6 +392,57 @@
do_exit(SIGSEGV);
}
+
+static void
+setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
+ signed long newsp)
+{
+ struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp;
+
+ /* Set up preamble frame */
+ if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto badframe;
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
+ || __copy_to_user(&frame->fp_regs, current->thread.fpr,
+ ELF_NFPREG * sizeof(double))
+ /* Set up to return from user space.
+ It calls the sc exception at offset 0x9999
+ for sys_rt_sigreturn().
+ */
+ || __put_user(0x38006666UL, &frame->tramp[0]) /* li r0,0x6666 */
+ || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */
+ goto badframe;
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[2]);
+
+ /* Retrieve rt_sigframe from stack and
+ set up registers for signal handler
+ */
+ newsp -= __SIGNAL_FRAMESIZE;
+ if (put_user(regs->gpr[1], (unsigned long *)newsp)
+ || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler)
+ || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal)
+ || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo)
+ || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc))
+ goto badframe;
+
+ regs->gpr[1] = newsp;
+ regs->gpr[6] = (unsigned long) rt_sf;
+ regs->link = (unsigned long) frame->tramp;
+
+ return;
+
+badframe:
+#if DEBUG_SIG
+ printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
+ regs, frame, newsp);
+#endif
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
/*
* OK, we're invoking a handler
*/
@@ -306,6 +452,7 @@
unsigned long *newspp, unsigned long frame)
{
struct sigcontext_struct *sc;
+ struct rt_sigframe *rt_sf;
if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND ||
@@ -313,20 +460,47 @@
!(ka->sa.sa_flags & SA_RESTART))))
regs->result = -EINTR;
- /* Put another sigcontext on the stack */
- *newspp -= sizeof(*sc);
- sc = (struct sigcontext_struct *) *newspp;
- if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
- goto badframe;
+ /* Set up Signal Frame */
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ /* Put a Real Time Context onto stack */
+ *newspp -= sizeof(*rt_sf);
+ rt_sf = (struct rt_sigframe *) *newspp;
+ if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
+ goto badframe;
- if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
- || __put_user(oldset->sig[0], &sc->oldmask)
+ if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler)
+ || __put_user(&rt_sf->info, &rt_sf->pinfo)
+ || __put_user(&rt_sf->uc, &rt_sf->puc)
+ /* Put the siginfo */
+ || __copy_to_user(&rt_sf->info, info, sizeof(*info))
+ /* Create the ucontext */
+ || __put_user(0, &rt_sf->uc.uc_flags)
+ || __put_user(0, &rt_sf->uc.uc_link)
+ || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+ || __put_user(sas_ss_flags(regs->gpr[1]),
+ &rt_sf->uc.uc_stack.ss_flags)
+ || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+ || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset))
+ /* mcontext.regs points to preamble register frame */
+ || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
+ || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
+ goto badframe;
+ } else {
+ /* Put another sigcontext on the stack */
+ *newspp -= sizeof(*sc);
+ sc = (struct sigcontext_struct *) *newspp;
+ if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
+ goto badframe;
+
+ if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
+ || __put_user(oldset->sig[0], &sc->oldmask)
#if _NSIG_WORDS > 1
- || __put_user(oldset->sig[1], &sc->_unused[3])
+ || __put_user(oldset->sig[1], &sc->_unused[3])
#endif
- || __put_user((struct pt_regs *)frame, &sc->regs)
- || __put_user(sig, &sc->signal))
- goto badframe;
+ || __put_user((struct pt_regs *)frame, &sc->regs)
+ || __put_user(sig, &sc->signal))
+ goto badframe;
+ }
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
@@ -482,7 +656,10 @@
if (newsp == frame)
return 0; /* no signals delivered */
- setup_frame(regs, (struct sigregs *) frame, newsp);
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(regs, (struct sigregs *) frame, newsp);
+ else
+ setup_frame(regs, (struct sigregs *) frame, newsp);
return 1;
}
diff -urN linux-2.3.99-pre5/include/asm-ppc/ucontext.h linux-2.3.99-pre5-ga/include/asm-ppc/ucontext.h
--- linux-2.3.99-pre5/include/asm-ppc/ucontext.h Tue Jan 13 00:18:13 1998
+++ linux-2.3.99-pre5-ga/include/asm-ppc/ucontext.h Fri Apr 14 10:30:41 2000
@@ -7,6 +7,7 @@
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ struct sigcontext_struct uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
};
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: patch: POSIX.1b signals for ppc
@ 2000-04-26 11:41 Kevin B. Hendricks
[not found] ` <3906F63F.7AD7A052@lightning.ch>
0 siblings, 1 reply; 7+ messages in thread
From: Kevin B. Hendricks @ 2000-04-26 11:41 UTC (permalink / raw)
To: ambrosini; +Cc: cort, paulus, linuxppc-dev
Hi Giovanna,
Thankyou!
I found your POSIX.1b signals patch for ppc that adds in sys_rt_sigreturn
and allows for signal handlers to get all 3 parameters (signo,siginfo, and
uc).
This patch is very important for the proper functioning of both green and
native threads of the JDK 1.3 that Blackdown is currently working on. (try
debugging code that uses SA_SIGINFO and ucontext as one of the
parameters...it will compile on powerpc with glibc 2.1.3 but the other
parameters passed to the signal handlers are just garbage which makes
debugging fun!).
Do you know its status?
Does it work on other ppc platforms outside of the ppc850?
Was it ever incorporated in part or whole into either Paul or Cort's
kernels (stable or development)?
If not, what if anything needs to be done to get the functionality of the
patch added into the ppc linux kernels?
If more work needs to be done to get this in the ppc kernels, please let me
know and I will try to help.
Thanks,
Kevin
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: patch: POSIX.1b signals for ppc
[not found] ` <3906F63F.7AD7A052@lightning.ch>
@ 2000-04-26 15:24 ` Kevin B. Hendricks
2000-04-26 17:11 ` Kevin B. Hendricks
0 siblings, 1 reply; 7+ messages in thread
From: Kevin B. Hendricks @ 2000-04-26 15:24 UTC (permalink / raw)
To: Giovanna Ambrosini; +Cc: linuxppc-dev
Hi Giovanna,
I need to keep using a stable kernel so I have attempted to backport your
POSIX.1b.patch back to Paul's latest 2.2.15pre19 kernel.
Here is the patch. It compiles cleanly but I have not attempted to boot
with it yet (but will soon).
If this works, I would like to get your changes into both Paul's stable and
devel trees as soon as possible. This functionality has been in the x86
kernel since at least the beginning of the 2.2 kernel series.
Thanks,
Kevin
--- arch/ppc/kernel/head.S.prev Wed Apr 26 10:38:24 2000
+++ arch/ppc/kernel/head.S Wed Apr 26 11:02:18 2000
@@ -23,6 +23,10 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * 2000-04-10.
+ * Add sys_rt_sigreturn in DoSyscall Handler.
+ * Giovanna Ambrosini (ambrosini@lightning.ch).
*
*/
@@ -2169,6 +2173,8 @@
#endif /* SHOW_SYSCALLS */
cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
beq- 10f
+ cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */
+ beq- 16f
lwz r10,TASK_FLAGS(r2)
andi. r10,r10,PF_TRACESYS
bne- 50f
@@ -2215,6 +2221,12 @@
/* sys_sigreturn */
10: addi r3,r1,STACK_FRAME_OVERHEAD
bl sys_sigreturn
+ cmpi 0,r3,0 /* Check for restarted system call */
+ bge int_return
+ b 20b
+/* sys_rt_sigreturn */
+16: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl sys_rt_sigreturn
cmpi 0,r3,0 /* Check for restarted system call */
bge int_return
b 20b
--- arch/ppc/kernel/signal.c.prev Wed Apr 26 10:38:39 2000
+++ arch/ppc/kernel/signal.c Wed Apr 26 10:56:47 2000
@@ -14,6 +14,16 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ *
+ * 2000-04-7.
+ * Define a real-time signal frame with siginfo and ucontext
+ * structures (setup_rt_frame()).
+ * Stuck up a real-time signal frame when setting the signal
+ * frame with SA_SIGINFO flags.
+ * Add sys_rt_sigreturn() to undo the signal stack.
+ *
+ * Giovanna Ambrosini (ambrosini@lightning.ch)
*/
#include <linux/sched.h>
@@ -121,13 +131,6 @@
}
-asmlinkage int sys_rt_sigreturn(unsigned long __unused)
-{
- printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n",
- current->comm,current->pid);
- do_exit(SIGSEGV);
-}
-
asmlinkage int
sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{
@@ -171,13 +174,11 @@
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
- * one or more sigcontext structs
+ * one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
- * XXX ultimately we will have to stack up a siginfo and ucontext
- * for each rt signal.
*/
struct sigregs {
elf_gregset_t gp_regs;
@@ -188,6 +189,15 @@
int abigap[56];
};
+struct rt_sigframe
+{
+ unsigned long _unused[2];
+ struct siginfo *pinfo;
+ void *puc;
+ struct siginfo info;
+ struct ucontext uc;
+};
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -259,6 +269,91 @@
do_exit(SIGSEGV);
}
+
+/*
+ * When we have rt signals to deliver, we set up on the
+ * user stack, going down from the original stack pointer:
+ * a sigregs struct
+ * one rt_sigframe struct (siginfo + ucontext)
+ * a gap of __SIGNAL_FRAMESIZE bytes
+ *
+ * Each of these things must be a multiple of 16 bytes in size.
+ *
+ */
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *rt_sf;
+ struct sigcontext_struct sigctx;
+ struct sigregs *sr;
+ int ret;
+ elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
+ sigset_t set;
+ stack_t st;
+ unsigned long prevsp;
+
+ rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
+ || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
+ || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ rt_sf++; /* Look at next rt_sigframe */
+ if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) {
+ /* Last stacked signal - restore registers -
+ * sigctx is initialized to point to the
+ * preamble frame (where registers are stored)
+ * see handle_signal()
+ */
+ sr = (struct sigregs *) sigctx.regs;
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);
+ if (copy_from_user(saved_regs, &sr->gp_regs,
+ sizeof(sr->gp_regs)))
+ goto badframe;
+ saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
+ | (saved_regs[PT_MSR] & MSR_USERCHANGE);
+ memcpy(regs, saved_regs, GP_REGS_SIZE);
+ if (copy_from_user(current->tss.fpr, &sr->fp_regs,
+ sizeof(sr->fp_regs)))
+ goto badframe;
+ /* This function sets back the stack flags into
+ the current task structure. */
+ sys_sigaltstack(&st, NULL);
+
+ ret = regs->result;
+ } else {
+ /* More signals to go */
+ /* Set up registers for next signal handler */
+ regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE;
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)))
+ goto badframe;
+ sr = (struct sigregs *) sigctx.regs;
+ regs->gpr[3] = ret = sigctx.signal;
+ /* Get the siginfo */
+ get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo);
+ /* Get the ucontext */
+ get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc);
+ regs->gpr[6] = (unsigned long) rt_sf;
+
+ regs->link = (unsigned long) &sr->tramp;
+ regs->nip = sigctx.handler;
+ if (get_user(prevsp, &sr->gp_regs[PT_R1])
+ || put_user(prevsp, (unsigned long *) regs->gpr[1]))
+ goto badframe;
+ }
+ return ret;
+
+badframe:
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
+
/*
* Set up a signal frame.
*/
@@ -305,6 +400,57 @@
do_exit(SIGSEGV);
}
+
+static void
+setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
+ signed long newsp)
+{
+ struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp;
+
+ /* Set up preamble frame */
+ if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto badframe;
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
+ || __copy_to_user(&frame->fp_regs, current->tss.fpr,
+ ELF_NFPREG * sizeof(double))
+ /* Set up to return from user space.
+ It calls the sc exception at offset 0x9999
+ for sys_rt_sigreturn().
+ */
+ || __put_user(0x38006666UL, &frame->tramp[0]) /* li r0,0x6666 */
+ || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */
+ goto badframe;
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[2]);
+
+ /* Retrieve rt_sigframe from stack and
+ set up registers for signal handler
+ */
+ newsp -= __SIGNAL_FRAMESIZE;
+ if (put_user(regs->gpr[1], (unsigned long *)newsp)
+ || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler)
+ || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal)
+ || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo)
+ || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc))
+ goto badframe;
+
+ regs->gpr[1] = newsp;
+ regs->gpr[6] = (unsigned long) rt_sf;
+ regs->link = (unsigned long) frame->tramp;
+
+ return;
+
+badframe:
+#if DEBUG_SIG
+ printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
+ regs, frame, newsp);
+#endif
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
/*
* OK, we're invoking a handler
*/
@@ -314,6 +460,7 @@
unsigned long *newspp, unsigned long frame)
{
struct sigcontext_struct *sc;
+ struct rt_sigframe *rt_sf;
if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND ||
@@ -321,20 +468,47 @@
!(ka->sa.sa_flags & SA_RESTART))))
regs->result = -EINTR;
- /* Put another sigcontext on the stack */
- *newspp -= sizeof(*sc);
- sc = (struct sigcontext_struct *) *newspp;
- if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
- goto badframe;
+ /* Set up Signal Frame */
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ /* Put a Real Time Context onto stack */
+ *newspp -= sizeof(*rt_sf);
+ rt_sf = (struct rt_sigframe *) *newspp;
+ if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
+ goto badframe;
+
+ if (__put_user((unsigned long) ka->sa.sa_handler,
&rt_sf->uc.uc_mcontext.handler)
+ || __put_user(&rt_sf->info, &rt_sf->pinfo)
+ || __put_user(&rt_sf->uc, &rt_sf->puc)
+ /* Put the siginfo */
+ || __copy_to_user(&rt_sf->info, info, sizeof(*info))
+ /* Create the ucontext */
+ || __put_user(0, &rt_sf->uc.uc_flags)
+ || __put_user(0, &rt_sf->uc.uc_link)
+ || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+ || __put_user(sas_ss_flags(regs->gpr[1]),
+ &rt_sf->uc.uc_stack.ss_flags)
+ || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+ || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset))
+ /* mcontext.regs points to preamble register frame */
+ || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
+ || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
+ goto badframe;
+ } else {
+ /* Put another sigcontext on the stack */
+ *newspp -= sizeof(*sc);
+ sc = (struct sigcontext_struct *) *newspp;
+ if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
+ goto badframe;
- if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
- || __put_user(oldset->sig[0], &sc->oldmask)
+ if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
+ || __put_user(oldset->sig[0], &sc->oldmask)
#if _NSIG_WORDS > 1
- || __put_user(oldset->sig[1], &sc->_unused[3])
+ || __put_user(oldset->sig[1], &sc->_unused[3])
#endif
- || __put_user((struct pt_regs *)frame, &sc->regs)
- || __put_user(sig, &sc->signal))
- goto badframe;
+ || __put_user((struct pt_regs *)frame, &sc->regs)
+ || __put_user(sig, &sc->signal))
+ goto badframe;
+ }
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
@@ -494,7 +668,10 @@
if (newsp == frame)
return 0; /* no signals delivered */
- setup_frame(regs, (struct sigregs *) frame, newsp);
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(regs, (struct sigregs *) frame, newsp);
+ else
+ setup_frame(regs, (struct sigregs *) frame, newsp);
return 1;
}
--- include/asm-ppc/ucontext.h.prev Wed Apr 26 10:39:24 2000
+++ include/asm-ppc/ucontext.h Wed Apr 26 10:39:36 2000
@@ -7,6 +7,7 @@
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ struct sigcontext_struct uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
};
--
Kevin B. Hendricks, Associate Professor of Operations and Information
Technology
Richard Ivey School of Business, University of Western Ontario
London, Ontario N6A-3K7 CANADA
khendricks@ivey.uwo.ca, (519) 661-3874, fax: 519-661-3959
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: patch: POSIX.1b signals for ppc
2000-04-26 15:24 ` Kevin B. Hendricks
@ 2000-04-26 17:11 ` Kevin B. Hendricks
2000-04-26 17:57 ` Kevin B. Hendricks
0 siblings, 1 reply; 7+ messages in thread
From: Kevin B. Hendricks @ 2000-04-26 17:11 UTC (permalink / raw)
To: Giovanna Ambrosini; +Cc: linuxppc-dev
Hi Giovanna,
> I need to keep using a stable kernel so I have attempted to backport your
> POSIX.1b.patch back to Paul's latest 2.2.15pre19 kernel.
>
> Here is the patch. It compiles cleanly but I have not attempted to boot
> with it yet (but will soon).
>
> If this works, I would like to get your changes into both Paul's stable and
> devel trees as soon as possible. This functionality has been in the x86
> kernel since at least the beginning of the 2.2 kernel series.
I have just finished running jdk 1.3 successfully using Paul's stable
2.2.15pre19 kernel (rsynced yesterday) and your posix signal patch backported
to the stable tree.
So far it seems to be working well with no real difficulties.
I will try to exercise the SA_SIGINFO info in some signal handlers to make sure
things are working okay.
I sure hope Paul and Cort add your patch in.
Thanks,
Kevin
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: patch: POSIX.1b signals for ppc
2000-04-26 17:11 ` Kevin B. Hendricks
@ 2000-04-26 17:57 ` Kevin B. Hendricks
0 siblings, 0 replies; 7+ messages in thread
From: Kevin B. Hendricks @ 2000-04-26 17:57 UTC (permalink / raw)
To: Giovanna Ambrosini; +Cc: linuxppc-dev
Hi Giovanna,
>I will try to exercise the SA_SIGINFO info in some signal handlers to make
>sure
>things are working okay.
Seems to be working fine! The additional debug info is a big help.
That only leaves the ucontext stuff to test yet which is what I really need
since it allows stack overflow checking to be done on an exception basis
(i.e when it occurs) and not before every and every access which should
speed up the jdk interpreter significantly.
Thanks,
Kevin
--
Kevin B. Hendricks, Associate Professor of Operations and Information
Technology
Richard Ivey School of Business, University of Western Ontario
London, Ontario N6A-3K7 CANADA
khendricks@ivey.uwo.ca, (519) 661-3874, fax: 519-661-3959
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
* patch: POSIX.1b signals for ppc
[not found] ` <20000516011302.N685@medea.fsmlabs.com>
@ 2000-05-19 15:06 ` Giovanna Ambrosini
0 siblings, 0 replies; 7+ messages in thread
From: Giovanna Ambrosini @ 2000-05-19 15:06 UTC (permalink / raw)
To: Cort Dougan; +Cc: linuxppc-dev
Hello Cort,
I prepared a new patch against the latest official kernel, as you asked me.
I tested it and worked fine.
Cort Dougan wrote:
>
> If you could send me the a patch against a more recent kernel in a few days
> I can merge it in. I'll be gone until the 22nd, though.
diff -urN linux-2.3.99-pre8/arch/ppc/kernel/entry.S linux-2.3.99-pre8-ga/arch/ppc/kernel/entry.S
--- linux-2.3.99-pre8/arch/ppc/kernel/entry.S Wed Feb 23 07:27:42 2000
+++ linux-2.3.99-pre8-ga/arch/ppc/kernel/entry.S Thu May 18 10:12:30 2000
@@ -20,6 +20,10 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * 2000-04-10.
+ * Add sys_rt_sigreturn in DoSyscall Handler.
+ * Giovanna Ambrosini (ambrosini@lightning.ch).
*
*/
@@ -83,6 +87,8 @@
#endif /* SHOW_SYSCALLS */
cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
beq- 10f
+ cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */
+ beq- 16f
lwz r10,TASK_FLAGS(r2)
andi. r10,r10,PF_TRACESYS
bne- 50f
@@ -129,6 +135,12 @@
/* sys_sigreturn */
10: addi r3,r1,STACK_FRAME_OVERHEAD
bl sys_sigreturn
+ cmpi 0,r3,0 /* Check for restarted system call */
+ bge ret_from_except
+ b 20b
+/* sys_rt_sigreturn */
+16: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl sys_rt_sigreturn
cmpi 0,r3,0 /* Check for restarted system call */
bge ret_from_except
b 20b
diff -urN linux-2.3.99-pre8/arch/ppc/kernel/signal.c linux-2.3.99-pre8-ga/arch/ppc/kernel/signal.c
--- linux-2.3.99-pre8/arch/ppc/kernel/signal.c Fri Nov 19 04:37:03 1999
+++ linux-2.3.99-pre8-ga/arch/ppc/kernel/signal.c Thu May 18 10:12:30 2000
@@ -14,6 +14,16 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ *
+ * 2000-04-7.
+ * Define a real-time signal frame with siginfo and ucontext
+ * structures (setup_rt_frame()).
+ * Stuck up a real-time signal frame when setting the signal
+ * frame with SA_SIGINFO flags.
+ * Add sys_rt_sigreturn() to undo the signal stack.
+ *
+ * Giovanna Ambrosini (ambrosini@lightning.ch)
*/
#include <linux/sched.h>
@@ -121,13 +131,6 @@
}
-asmlinkage int sys_rt_sigreturn(unsigned long __unused)
-{
- printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n",
- current->comm,current->pid);
- do_exit(SIGSEGV);
-}
-
asmlinkage int
sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{
@@ -171,13 +174,11 @@
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
- * one or more sigcontext structs
+ * one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
- * XXX ultimately we will have to stack up a siginfo and ucontext
- * for each rt signal.
*/
struct sigregs {
elf_gregset_t gp_regs;
@@ -188,6 +189,15 @@
int abigap[56];
};
+struct rt_sigframe
+{
+ unsigned long _unused[2];
+ struct siginfo *pinfo;
+ void *puc;
+ struct siginfo info;
+ struct ucontext uc;
+};
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -255,6 +265,91 @@
do_exit(SIGSEGV);
}
+
+/*
+ * When we have rt signals to deliver, we set up on the
+ * user stack, going down from the original stack pointer:
+ * a sigregs struct
+ * one rt_sigframe struct (siginfo + ucontext)
+ * a gap of __SIGNAL_FRAMESIZE bytes
+ *
+ * Each of these things must be a multiple of 16 bytes in size.
+ *
+ */
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *rt_sf;
+ struct sigcontext_struct sigctx;
+ struct sigregs *sr;
+ int ret;
+ elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
+ sigset_t set;
+ stack_t st;
+ unsigned long prevsp;
+
+ rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
+ || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
+ || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ rt_sf++; /* Look at next rt_sigframe */
+ if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) {
+ /* Last stacked signal - restore registers -
+ * sigctx is initialized to point to the
+ * preamble frame (where registers are stored)
+ * see handle_signal()
+ */
+ sr = (struct sigregs *) sigctx.regs;
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);
+ if (copy_from_user(saved_regs, &sr->gp_regs,
+ sizeof(sr->gp_regs)))
+ goto badframe;
+ saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
+ | (saved_regs[PT_MSR] & MSR_USERCHANGE);
+ memcpy(regs, saved_regs, GP_REGS_SIZE);
+ if (copy_from_user(current->thread.fpr, &sr->fp_regs,
+ sizeof(sr->fp_regs)))
+ goto badframe;
+ /* This function sets back the stack flags into
+ the current task structure. */
+ sys_sigaltstack(&st, NULL);
+
+ ret = regs->result;
+ } else {
+ /* More signals to go */
+ /* Set up registers for next signal handler */
+ regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE;
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)))
+ goto badframe;
+ sr = (struct sigregs *) sigctx.regs;
+ regs->gpr[3] = ret = sigctx.signal;
+ /* Get the siginfo */
+ get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo);
+ /* Get the ucontext */
+ get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc);
+ regs->gpr[6] = (unsigned long) rt_sf;
+
+ regs->link = (unsigned long) &sr->tramp;
+ regs->nip = sigctx.handler;
+ if (get_user(prevsp, &sr->gp_regs[PT_R1])
+ || put_user(prevsp, (unsigned long *) regs->gpr[1]))
+ goto badframe;
+ }
+ return ret;
+
+badframe:
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
+
/*
* Set up a signal frame.
*/
@@ -297,6 +392,57 @@
do_exit(SIGSEGV);
}
+
+static void
+setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
+ signed long newsp)
+{
+ struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp;
+
+ /* Set up preamble frame */
+ if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto badframe;
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
+ || __copy_to_user(&frame->fp_regs, current->thread.fpr,
+ ELF_NFPREG * sizeof(double))
+ /* Set up to return from user space.
+ It calls the sc exception at offset 0x9999
+ for sys_rt_sigreturn().
+ */
+ || __put_user(0x38006666UL, &frame->tramp[0]) /* li r0,0x6666 */
+ || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */
+ goto badframe;
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[2]);
+
+ /* Retrieve rt_sigframe from stack and
+ set up registers for signal handler
+ */
+ newsp -= __SIGNAL_FRAMESIZE;
+ if (put_user(regs->gpr[1], (unsigned long *)newsp)
+ || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler)
+ || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal)
+ || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo)
+ || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc))
+ goto badframe;
+
+ regs->gpr[1] = newsp;
+ regs->gpr[6] = (unsigned long) rt_sf;
+ regs->link = (unsigned long) frame->tramp;
+
+ return;
+
+badframe:
+#if DEBUG_SIG
+ printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
+ regs, frame, newsp);
+#endif
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
/*
* OK, we're invoking a handler
*/
@@ -306,6 +452,7 @@
unsigned long *newspp, unsigned long frame)
{
struct sigcontext_struct *sc;
+ struct rt_sigframe *rt_sf;
if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND ||
@@ -313,20 +460,47 @@
!(ka->sa.sa_flags & SA_RESTART))))
regs->result = -EINTR;
- /* Put another sigcontext on the stack */
- *newspp -= sizeof(*sc);
- sc = (struct sigcontext_struct *) *newspp;
- if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
- goto badframe;
+ /* Set up Signal Frame */
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ /* Put a Real Time Context onto stack */
+ *newspp -= sizeof(*rt_sf);
+ rt_sf = (struct rt_sigframe *) *newspp;
+ if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
+ goto badframe;
- if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
- || __put_user(oldset->sig[0], &sc->oldmask)
+ if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler)
+ || __put_user(&rt_sf->info, &rt_sf->pinfo)
+ || __put_user(&rt_sf->uc, &rt_sf->puc)
+ /* Put the siginfo */
+ || __copy_to_user(&rt_sf->info, info, sizeof(*info))
+ /* Create the ucontext */
+ || __put_user(0, &rt_sf->uc.uc_flags)
+ || __put_user(0, &rt_sf->uc.uc_link)
+ || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+ || __put_user(sas_ss_flags(regs->gpr[1]),
+ &rt_sf->uc.uc_stack.ss_flags)
+ || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+ || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset))
+ /* mcontext.regs points to preamble register frame */
+ || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
+ || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
+ goto badframe;
+ } else {
+ /* Put another sigcontext on the stack */
+ *newspp -= sizeof(*sc);
+ sc = (struct sigcontext_struct *) *newspp;
+ if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
+ goto badframe;
+
+ if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
+ || __put_user(oldset->sig[0], &sc->oldmask)
#if _NSIG_WORDS > 1
- || __put_user(oldset->sig[1], &sc->_unused[3])
+ || __put_user(oldset->sig[1], &sc->_unused[3])
#endif
- || __put_user((struct pt_regs *)frame, &sc->regs)
- || __put_user(sig, &sc->signal))
- goto badframe;
+ || __put_user((struct pt_regs *)frame, &sc->regs)
+ || __put_user(sig, &sc->signal))
+ goto badframe;
+ }
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
@@ -482,7 +656,10 @@
if (newsp == frame)
return 0; /* no signals delivered */
- setup_frame(regs, (struct sigregs *) frame, newsp);
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(regs, (struct sigregs *) frame, newsp);
+ else
+ setup_frame(regs, (struct sigregs *) frame, newsp);
return 1;
}
diff -urN linux-2.3.99-pre8/include/asm-ppc/ucontext.h linux-2.3.99-pre8-ga/include/asm-ppc/ucontext.h
--- linux-2.3.99-pre8/include/asm-ppc/ucontext.h Sun Nov 28 00:42:33 1999
+++ linux-2.3.99-pre8-ga/include/asm-ppc/ucontext.h Thu May 18 10:12:30 2000
@@ -7,6 +7,7 @@
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ struct sigcontext_struct uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
};
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
* patch: POSIX.1b signals for ppc..................
@ 2000-05-25 15:36 Giovanna Ambrosini
0 siblings, 0 replies; 7+ messages in thread
From: Giovanna Ambrosini @ 2000-05-25 15:36 UTC (permalink / raw)
To: cort; +Cc: linuxppc-dev
Hello Cort,
here is the POSIX.1b signals patch for ppc against your latest kernel tree (pre9).
It's been tested.
Thank you.
diff -urN linux-2.3.99-pre9/arch/ppc/kernel/entry.S linux-2.3.99-pre9-ga/arch/ppc/kernel/entry.S
--- linux-2.3.99-pre9/arch/ppc/kernel/entry.S Mon May 15 23:53:30 2000
+++ linux-2.3.99-pre9-ga/arch/ppc/kernel/entry.S Thu May 25 17:24:30 2000
@@ -20,6 +20,10 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ * 2000-04-10.
+ * Add sys_rt_sigreturn in DoSyscall Handler.
+ * Giovanna Ambrosini (ambrosini@lightning.ch).
*
*/
@@ -83,6 +87,8 @@
#endif /* SHOW_SYSCALLS */
cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */
beq- 10f
+ cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */
+ beq- 16f
lwz r10,TASK_FLAGS(r2)
andi. r10,r10,PF_TRACESYS
bne- 50f
@@ -129,6 +135,12 @@
/* sys_sigreturn */
10: addi r3,r1,STACK_FRAME_OVERHEAD
bl sys_sigreturn
+ cmpi 0,r3,0 /* Check for restarted system call */
+ bge ret_from_except
+ b 20b
+/* sys_rt_sigreturn */
+16: addi r3,r1,STACK_FRAME_OVERHEAD
+ bl sys_rt_sigreturn
cmpi 0,r3,0 /* Check for restarted system call */
bge ret_from_except
b 20b
diff -urN linux-2.3.99-pre9/arch/ppc/kernel/signal.c linux-2.3.99-pre9-ga/arch/ppc/kernel/signal.c
--- linux-2.3.99-pre9/arch/ppc/kernel/signal.c Fri Nov 19 04:37:03 1999
+++ linux-2.3.99-pre9-ga/arch/ppc/kernel/signal.c Thu May 25 17:24:30 2000
@@ -14,6 +14,16 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
+ *
+ *
+ * 2000-04-7.
+ * Define a real-time signal frame with siginfo and ucontext
+ * structures (setup_rt_frame()).
+ * Stuck up a real-time signal frame when setting the signal
+ * frame with SA_SIGINFO flags.
+ * Add sys_rt_sigreturn() to undo the signal stack.
+ *
+ * Giovanna Ambrosini (ambrosini@lightning.ch)
*/
#include <linux/sched.h>
@@ -121,13 +131,6 @@
}
-asmlinkage int sys_rt_sigreturn(unsigned long __unused)
-{
- printk("sys_rt_sigreturn(): %s/%d not yet implemented.\n",
- current->comm,current->pid);
- do_exit(SIGSEGV);
-}
-
asmlinkage int
sys_sigaltstack(const stack_t *uss, stack_t *uoss)
{
@@ -171,13 +174,11 @@
* When we have signals to deliver, we set up on the
* user stack, going down from the original stack pointer:
* a sigregs struct
- * one or more sigcontext structs
+ * one or more sigcontext structs with
* a gap of __SIGNAL_FRAMESIZE bytes
*
* Each of these things must be a multiple of 16 bytes in size.
*
- * XXX ultimately we will have to stack up a siginfo and ucontext
- * for each rt signal.
*/
struct sigregs {
elf_gregset_t gp_regs;
@@ -188,6 +189,15 @@
int abigap[56];
};
+struct rt_sigframe
+{
+ unsigned long _unused[2];
+ struct siginfo *pinfo;
+ void *puc;
+ struct siginfo info;
+ struct ucontext uc;
+};
+
/*
* Do a signal return; undo the signal stack.
*/
@@ -255,6 +265,91 @@
do_exit(SIGSEGV);
}
+
+/*
+ * When we have rt signals to deliver, we set up on the
+ * user stack, going down from the original stack pointer:
+ * a sigregs struct
+ * one rt_sigframe struct (siginfo + ucontext)
+ * a gap of __SIGNAL_FRAMESIZE bytes
+ *
+ * Each of these things must be a multiple of 16 bytes in size.
+ *
+ */
+asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
+{
+ struct rt_sigframe *rt_sf;
+ struct sigcontext_struct sigctx;
+ struct sigregs *sr;
+ int ret;
+ elf_gregset_t saved_regs; /* an array of ELF_NGREG unsigned longs */
+ sigset_t set;
+ stack_t st;
+ unsigned long prevsp;
+
+ rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE);
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx))
+ || copy_from_user(&set, &rt_sf->uc.uc_sigmask, sizeof(set))
+ || copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st)))
+ goto badframe;
+ sigdelsetmask(&set, ~_BLOCKABLE);
+ spin_lock_irq(¤t->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(¤t->sigmask_lock);
+
+ rt_sf++; /* Look at next rt_sigframe */
+ if (rt_sf == (struct rt_sigframe *)(sigctx.regs)) {
+ /* Last stacked signal - restore registers -
+ * sigctx is initialized to point to the
+ * preamble frame (where registers are stored)
+ * see handle_signal()
+ */
+ sr = (struct sigregs *) sigctx.regs;
+ if (regs->msr & MSR_FP )
+ giveup_fpu(current);
+ if (copy_from_user(saved_regs, &sr->gp_regs,
+ sizeof(sr->gp_regs)))
+ goto badframe;
+ saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
+ | (saved_regs[PT_MSR] & MSR_USERCHANGE);
+ memcpy(regs, saved_regs, GP_REGS_SIZE);
+ if (copy_from_user(current->thread.fpr, &sr->fp_regs,
+ sizeof(sr->fp_regs)))
+ goto badframe;
+ /* This function sets back the stack flags into
+ the current task structure. */
+ sys_sigaltstack(&st, NULL);
+
+ ret = regs->result;
+ } else {
+ /* More signals to go */
+ /* Set up registers for next signal handler */
+ regs->gpr[1] = (unsigned long)rt_sf - __SIGNAL_FRAMESIZE;
+ if (copy_from_user(&sigctx, &rt_sf->uc.uc_mcontext, sizeof(sigctx)))
+ goto badframe;
+ sr = (struct sigregs *) sigctx.regs;
+ regs->gpr[3] = ret = sigctx.signal;
+ /* Get the siginfo */
+ get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo);
+ /* Get the ucontext */
+ get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc);
+ regs->gpr[6] = (unsigned long) rt_sf;
+
+ regs->link = (unsigned long) &sr->tramp;
+ regs->nip = sigctx.handler;
+ if (get_user(prevsp, &sr->gp_regs[PT_R1])
+ || put_user(prevsp, (unsigned long *) regs->gpr[1]))
+ goto badframe;
+ }
+ return ret;
+
+badframe:
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
+
/*
* Set up a signal frame.
*/
@@ -297,6 +392,57 @@
do_exit(SIGSEGV);
}
+
+static void
+setup_rt_frame(struct pt_regs *regs, struct sigregs *frame,
+ signed long newsp)
+{
+ struct rt_sigframe *rt_sf = (struct rt_sigframe *) newsp;
+
+ /* Set up preamble frame */
+ if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
+ goto badframe;
+ if (regs->msr & MSR_FP)
+ giveup_fpu(current);
+ if (__copy_to_user(&frame->gp_regs, regs, GP_REGS_SIZE)
+ || __copy_to_user(&frame->fp_regs, current->thread.fpr,
+ ELF_NFPREG * sizeof(double))
+ /* Set up to return from user space.
+ It calls the sc exception at offset 0x9999
+ for sys_rt_sigreturn().
+ */
+ || __put_user(0x38006666UL, &frame->tramp[0]) /* li r0,0x6666 */
+ || __put_user(0x44000002UL, &frame->tramp[1])) /* sc */
+ goto badframe;
+ flush_icache_range((unsigned long) &frame->tramp[0],
+ (unsigned long) &frame->tramp[2]);
+
+ /* Retrieve rt_sigframe from stack and
+ set up registers for signal handler
+ */
+ newsp -= __SIGNAL_FRAMESIZE;
+ if (put_user(regs->gpr[1], (unsigned long *)newsp)
+ || get_user(regs->nip, &rt_sf->uc.uc_mcontext.handler)
+ || get_user(regs->gpr[3], &rt_sf->uc.uc_mcontext.signal)
+ || get_user(regs->gpr[4], (unsigned long *)&rt_sf->pinfo)
+ || get_user(regs->gpr[5], (unsigned long *)&rt_sf->puc))
+ goto badframe;
+
+ regs->gpr[1] = newsp;
+ regs->gpr[6] = (unsigned long) rt_sf;
+ regs->link = (unsigned long) frame->tramp;
+
+ return;
+
+badframe:
+#if DEBUG_SIG
+ printk("badframe in setup_rt_frame, regs=%p frame=%p newsp=%lx\n",
+ regs, frame, newsp);
+#endif
+ lock_kernel();
+ do_exit(SIGSEGV);
+}
+
/*
* OK, we're invoking a handler
*/
@@ -306,6 +452,7 @@
unsigned long *newspp, unsigned long frame)
{
struct sigcontext_struct *sc;
+ struct rt_sigframe *rt_sf;
if (regs->trap == 0x0C00 /* System Call! */
&& ((int)regs->result == -ERESTARTNOHAND ||
@@ -313,20 +460,47 @@
!(ka->sa.sa_flags & SA_RESTART))))
regs->result = -EINTR;
- /* Put another sigcontext on the stack */
- *newspp -= sizeof(*sc);
- sc = (struct sigcontext_struct *) *newspp;
- if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
- goto badframe;
+ /* Set up Signal Frame */
+ if (ka->sa.sa_flags & SA_SIGINFO) {
+ /* Put a Real Time Context onto stack */
+ *newspp -= sizeof(*rt_sf);
+ rt_sf = (struct rt_sigframe *) *newspp;
+ if (verify_area(VERIFY_WRITE, rt_sf, sizeof(*rt_sf)))
+ goto badframe;
- if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
- || __put_user(oldset->sig[0], &sc->oldmask)
+ if (__put_user((unsigned long) ka->sa.sa_handler, &rt_sf->uc.uc_mcontext.handler)
+ || __put_user(&rt_sf->info, &rt_sf->pinfo)
+ || __put_user(&rt_sf->uc, &rt_sf->puc)
+ /* Put the siginfo */
+ || __copy_to_user(&rt_sf->info, info, sizeof(*info))
+ /* Create the ucontext */
+ || __put_user(0, &rt_sf->uc.uc_flags)
+ || __put_user(0, &rt_sf->uc.uc_link)
+ || __put_user(current->sas_ss_sp, &rt_sf->uc.uc_stack.ss_sp)
+ || __put_user(sas_ss_flags(regs->gpr[1]),
+ &rt_sf->uc.uc_stack.ss_flags)
+ || __put_user(current->sas_ss_size, &rt_sf->uc.uc_stack.ss_size)
+ || __copy_to_user(&rt_sf->uc.uc_sigmask, oldset, sizeof(*oldset))
+ /* mcontext.regs points to preamble register frame */
+ || __put_user((struct pt_regs *)frame, &rt_sf->uc.uc_mcontext.regs)
+ || __put_user(sig, &rt_sf->uc.uc_mcontext.signal))
+ goto badframe;
+ } else {
+ /* Put another sigcontext on the stack */
+ *newspp -= sizeof(*sc);
+ sc = (struct sigcontext_struct *) *newspp;
+ if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
+ goto badframe;
+
+ if (__put_user((unsigned long) ka->sa.sa_handler, &sc->handler)
+ || __put_user(oldset->sig[0], &sc->oldmask)
#if _NSIG_WORDS > 1
- || __put_user(oldset->sig[1], &sc->_unused[3])
+ || __put_user(oldset->sig[1], &sc->_unused[3])
#endif
- || __put_user((struct pt_regs *)frame, &sc->regs)
- || __put_user(sig, &sc->signal))
- goto badframe;
+ || __put_user((struct pt_regs *)frame, &sc->regs)
+ || __put_user(sig, &sc->signal))
+ goto badframe;
+ }
if (ka->sa.sa_flags & SA_ONESHOT)
ka->sa.sa_handler = SIG_DFL;
@@ -482,7 +656,10 @@
if (newsp == frame)
return 0; /* no signals delivered */
- setup_frame(regs, (struct sigregs *) frame, newsp);
+ if (ka->sa.sa_flags & SA_SIGINFO)
+ setup_rt_frame(regs, (struct sigregs *) frame, newsp);
+ else
+ setup_frame(regs, (struct sigregs *) frame, newsp);
return 1;
}
diff -urN linux-2.3.99-pre9/include/asm-ppc/ucontext.h linux-2.3.99-pre9-ga/include/asm-ppc/ucontext.h
--- linux-2.3.99-pre9/include/asm-ppc/ucontext.h Sun Nov 28 00:42:33 1999
+++ linux-2.3.99-pre9-ga/include/asm-ppc/ucontext.h Thu May 25 17:24:30 2000
@@ -7,6 +7,7 @@
unsigned long uc_flags;
struct ucontext *uc_link;
stack_t uc_stack;
+ struct sigcontext_struct uc_mcontext;
sigset_t uc_sigmask; /* mask last for extensibility */
};
** Sent via the linuxppc-dev mail list. See http://lists.linuxppc.org/
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2000-05-25 15:36 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2000-04-26 11:41 patch: POSIX.1b signals for ppc Kevin B. Hendricks
[not found] ` <3906F63F.7AD7A052@lightning.ch>
2000-04-26 15:24 ` Kevin B. Hendricks
2000-04-26 17:11 ` Kevin B. Hendricks
2000-04-26 17:57 ` Kevin B. Hendricks
-- strict thread matches above, loose matches on Subject: below --
2000-05-25 15:36 Giovanna Ambrosini
[not found] <39070D1B.551092F8@lightning.ch>
[not found] ` <20000427180039.G21388@medea.fsmlabs.com>
[not found] ` <390936FF.2119A3BD@lightning.ch>
[not found] ` <20000516011302.N685@medea.fsmlabs.com>
2000-05-19 15:06 ` Giovanna Ambrosini
2000-04-14 14:54 Giovanna Ambrosini
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).