linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
* 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
* 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(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->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
[parent not found: <39070D1B.551092F8@lightning.ch>]
* 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(&current->sigmask_lock);
+ current->blocked = set;
+ recalc_sigpending(current);
+ spin_unlock_irq(&current->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

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