Commit da172f56 authored by Anton Blanchard's avatar Anton Blanchard

ppc64: more signal32 updates from Stephen Rothwell

parent 4014ca71
...@@ -112,43 +112,37 @@ struct rt_sigframe_32 { ...@@ -112,43 +112,37 @@ struct rt_sigframe_32 {
}; };
extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr,
int options, struct rusage * ru);
/*
* Start of nonRT signal support
*
* sigset_t is 32 bits for non-rt signals
*
* System Calls
* sigaction sys32_sigaction
* sigpending sys32_sigpending
* sigprocmask sys32_sigprocmask
* sigreturn sys32_sigreturn
*
* Note sigsuspend has no special 32 bit routine - uses the 64 bit routine
*
* Other routines
* setup_frame32
*/
extern asmlinkage long sys_wait4(pid_t pid,unsigned int * stat_addr, int options, struct rusage * ru); asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act,
struct old_sigaction32 *oact)
/****************************************************************************/
/* Start of nonRT signal support */
/* */
/* sigset_t is 32 bits for non-rt signals */
/* */
/* System Calls */
/* sigaction sys32_sigaction */
/* sigpending sys32_sigpending */
/* sigprocmask sys32_sigprocmask */
/* sigreturn sys32_sigreturn */
/* */
/* Note sigsuspend has no special 32 bit routine - uses the 64 bit routine */
/* */
/* Other routines */
/* setup_frame32 */
/* */
/****************************************************************************/
asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact)
{ {
struct k_sigaction new_ka, old_ka; struct k_sigaction new_ka, old_ka;
int ret; int ret;
if (sig < 0) if (sig < 0)
{
sig = -sig; sig = -sig;
}
if (act) if (act) {
{
old_sigset_t32 mask; old_sigset_t32 mask;
ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler); ret = get_user((long)new_ka.sa.sa_handler, &act->sa_handler);
...@@ -157,14 +151,11 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old ...@@ -157,14 +151,11 @@ asmlinkage long sys32_sigaction(int sig, struct old_sigaction32 *act, struct old
ret |= __get_user(mask, &act->sa_mask); ret |= __get_user(mask, &act->sa_mask);
if (ret) if (ret)
return ret; return ret;
siginitset(&new_ka.sa.sa_mask, mask); siginitset(&new_ka.sa.sa_mask, mask);
} }
ret = do_sigaction(sig, (act? &new_ka: NULL), (oact? &old_ka: NULL)); ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
if (!ret && oact)
{
ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler); ret = put_user((long)old_ka.sa.sa_handler, &oact->sa_handler);
ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer); ret |= __put_user((long)old_ka.sa.sa_restorer, &oact->sa_restorer);
ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags); ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
...@@ -184,19 +175,20 @@ asmlinkage long sys32_sigpending(old_sigset_t32 *set) ...@@ -184,19 +175,20 @@ asmlinkage long sys32_sigpending(old_sigset_t32 *set)
old_sigset_t s; old_sigset_t s;
int ret; int ret;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS); set_fs(KERNEL_DS);
ret = sys_sigpending(&s); ret = sys_sigpending(&s);
set_fs (old_fs); set_fs(old_fs);
if (put_user (s, set)) return -EFAULT; if (put_user(s, set))
return -EFAULT;
return ret; return ret;
} }
extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t *oset); extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set,
old_sigset_t *oset);
/* /*
* Note: it is necessary to treat how as an unsigned int, with the * Note: it is necessary to treat how as an unsigned int, with the
...@@ -205,19 +197,22 @@ extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t ...@@ -205,19 +197,22 @@ extern asmlinkage long sys_sigprocmask(int how, old_sigset_t *set, old_sigset_t
* of a signed int (msr in 32-bit mode) and the register representation * of a signed int (msr in 32-bit mode) and the register representation
* of a signed int (msr in 64-bit mode) is performed. * of a signed int (msr in 64-bit mode) is performed.
*/ */
asmlinkage long sys32_sigprocmask(u32 how, old_sigset_t32 *set, old_sigset_t32 *oset) asmlinkage long sys32_sigprocmask(u32 how, old_sigset_t32 *set,
old_sigset_t32 *oset)
{ {
old_sigset_t s; old_sigset_t s;
int ret; int ret;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
if (set && get_user (s, set)) return -EFAULT; if (set && get_user(s, set))
set_fs (KERNEL_DS); return -EFAULT;
set_fs(KERNEL_DS);
ret = sys_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL); ret = sys_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL);
set_fs (old_fs); set_fs(old_fs);
if (ret) return ret; if (ret)
if (oset && put_user (s, oset)) return -EFAULT; return ret;
if (oset && put_user (s, oset))
return -EFAULT;
return 0; return 0;
} }
...@@ -267,24 +262,26 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -267,24 +262,26 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
sr = (struct sigregs32*)(u64)sigctx.regs; sr = (struct sigregs32*)(u64)sigctx.regs;
if (regs->msr & MSR_FP ) if (regs->msr & MSR_FP )
giveup_fpu(current); giveup_fpu(current);
/* copy the 32 bit register values off the user stack */ /*
/* into the 32 bit register area */ * copy the 32 bit register values off the user stack
if (copy_from_user(saved_regs, &sr->gp_regs,sizeof(sr->gp_regs))) * into the 32 bit register area
*/
if (copy_from_user(saved_regs, &sr->gp_regs,
sizeof(sr->gp_regs)))
goto badframe; goto badframe;
/**********************************************************************/ /*
/* The saved reg structure in the frame is an elf_grepset_t32, it is */ * The saved reg structure in the frame is an elf_grepset_t32,
/* a 32 bit register save of the registers in the pt_regs structure */ * it is a 32 bit register save of the registers in the
/* that was stored on the kernel stack during the system call */ * pt_regs structure that was stored on the kernel stack
/* when the system call was interrupted for the signal. Only 32 bits*/ * during the system call when the system call was interrupted
/* are saved because the sigcontext contains a pointer to the regs */ * for the signal. Only 32 bits are saved because the
/* and the sig context address is passed as a pointer to the signal */ * sigcontext contains a pointer to the regs and the sig
/* handler. */ * context address is passed as a pointer to the signal
/* */ * handler.
/* The entries in the elf_grepset have the same index as the elements */ *
/* in the pt_regs structure. */ * The entries in the elf_grepset have the same index as the
/* */ * elements in the pt_regs structure.
/**********************************************************************/ */
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE); | (saved_regs[PT_MSR] & MSR_USERCHANGE);
regs->gpr[0] = (u64)(saved_regs[0]) & 0xFFFFFFFF; regs->gpr[0] = (u64)(saved_regs[0]) & 0xFFFFFFFF;
...@@ -328,8 +325,10 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -328,8 +325,10 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/* restore the non gpr registers */ /* restore the non gpr registers */
/****************************************************/ /****************************************************/
regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF;
/* Insure that the interrupt mode is 64 bit, during 32 bit execution. /*
* (This is necessary because we only saved lower 32 bits of msr.) * Insure that the interrupt mode is 64 bit, during 32 bit
* execution. (This is necessary because we only saved
* lower 32 bits of msr.)
*/ */
regs->msr = regs->msr | MSR_ISF; /* When this thread is interrupted it should run in 64 bit mode. */ regs->msr = regs->msr | MSR_ISF; /* When this thread is interrupted it should run in 64 bit mode. */
...@@ -353,6 +352,7 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -353,6 +352,7 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
goto badframe; goto badframe;
ret = regs->result; ret = regs->result;
return ret; return ret;
badframe: badframe:
...@@ -362,11 +362,11 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -362,11 +362,11 @@ long sys32_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/* /*
* Set up a signal frame. * Set up a signal frame.
*/ */
static void static void setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
unsigned int newsp) unsigned int newsp)
{ {
struct sigcontext32_struct *sc = (struct sigcontext32_struct *)(u64)newsp; struct sigcontext32_struct *sc =
(struct sigcontext32_struct *)(u64)newsp;
if (verify_area(VERIFY_WRITE, frame, sizeof(*frame))) if (verify_area(VERIFY_WRITE, frame, sizeof(*frame)))
goto badframe; goto badframe;
...@@ -477,6 +477,7 @@ setup_frame32(struct pt_regs *regs, struct sigregs32 *frame, ...@@ -477,6 +477,7 @@ setup_frame32(struct pt_regs *regs, struct sigregs32 *frame,
return; return;
badframe: badframe:
udbg_printf("setup_frame32 - badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); PPCDBG_ENTER_DEBUGGER();
#if DEBUG_SIG #if DEBUG_SIG
printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n", printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp); regs, frame, newsp);
...@@ -526,13 +527,13 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -526,13 +527,13 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/* Adjust the inputted reg1 to point to the first rt signal frame */ /* Adjust the inputted reg1 to point to the first rt signal frame */
rt_stack_frame = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32); rt_stack_frame = (struct rt_sigframe_32 *)(regs->gpr[1] + __SIGNAL_FRAMESIZE32);
/* Copy the information from the user stack */ /* Copy the information from the user stack */
if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext,sizeof(sigctx)) if (copy_from_user(&sigctx, &rt_stack_frame->uc.uc_mcontext,
|| copy_from_user(&signal_set, &rt_stack_frame->uc.uc_sigmask,sizeof(signal_set)) sizeof(sigctx))
|| copy_from_user(&stack,&rt_stack_frame->uc.uc_stack,sizeof(stack))) || copy_from_user(&signal_set, &rt_stack_frame->uc.uc_sigmask,
{ sizeof(signal_set))
/* unable to copy from user storage */ || copy_from_user(&stack,&rt_stack_frame->uc.uc_stack,
sizeof(stack)))
goto badframe; goto badframe;
}
/* /*
* Unblock the signal that was processed * Unblock the signal that was processed
...@@ -554,27 +555,22 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -554,27 +555,22 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
signalregs = (struct sigregs32 *) (u64)sigctx.regs; signalregs = (struct sigregs32 *) (u64)sigctx.regs;
/* If currently owning the floating point - give them up */ /* If currently owning the floating point - give them up */
if (regs->msr & MSR_FP) if (regs->msr & MSR_FP)
{
giveup_fpu(current); giveup_fpu(current);
} if (copy_from_user(saved_regs, &signalregs->gp_regs,
if (copy_from_user(saved_regs,&signalregs->gp_regs,sizeof(signalregs->gp_regs))) sizeof(signalregs->gp_regs)))
{
goto badframe; goto badframe;
} /*
/**********************************************************************/ * The saved reg structure in the frame is an elf_grepset_t32,
/* The saved reg structure in the frame is an elf_grepset_t32, it is */ * it is a 32 bit register save of the registers in the
/* a 32 bit register save of the registers in the pt_regs structure */ * pt_regs structure that was stored on the kernel stack
/* that was stored on the kernel stack during the system call */ * during the system call when the system call was interrupted
/* when the system call was interrupted for the signal. Only 32 bits*/ * for the signal. Only 32 bits are saved because the
/* are saved because the sigcontext contains a pointer to the regs */ * sigcontext contains a pointer to the regs and the sig
/* and the sig context address is passed as a pointer to the signal */ * context address is passed as a pointer to the signal handler
/* handler. */ *
/* */ * The entries in the elf_grepset have the same index as
/* The entries in the elf_grepset have the same index as the elements */ * the elements in the pt_regs structure.
/* in the pt_regs structure. */ */
/* */
/**********************************************************************/
saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE) saved_regs[PT_MSR] = (regs->msr & ~MSR_USERCHANGE)
| (saved_regs[PT_MSR] & MSR_USERCHANGE); | (saved_regs[PT_MSR] & MSR_USERCHANGE);
regs->gpr[0] = (u64)(saved_regs[0]) & 0xFFFFFFFF; regs->gpr[0] = (u64)(saved_regs[0]) & 0xFFFFFFFF;
...@@ -618,7 +614,6 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -618,7 +614,6 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
/* restore the non gpr registers */ /* restore the non gpr registers */
/****************************************************/ /****************************************************/
regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF; regs->msr = (u64)(saved_regs[PT_MSR]) & 0xFFFFFFFF;
regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF; regs->nip = (u64)(saved_regs[PT_NIP]) & 0xFFFFFFFF;
regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF; regs->orig_gpr3 = (u64)(saved_regs[PT_ORIG_R3]) & 0xFFFFFFFF;
regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF; regs->ctr = (u64)(saved_regs[PT_CTR]) & 0xFFFFFFFF;
...@@ -626,16 +621,15 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -626,16 +621,15 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF; regs->xer = (u64)(saved_regs[PT_XER]) & 0xFFFFFFFF;
regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF; regs->ccr = (u64)(saved_regs[PT_CCR]) & 0xFFFFFFFF;
/* regs->softe is left unchanged (like MSR.EE) */ /* regs->softe is left unchanged (like MSR.EE) */
/******************************************************/ /*
/* the DAR and the DSISR are only relevant during a */ * the DAR and the DSISR are only relevant during a
/* data or instruction storage interrupt. The value */ * data or instruction storage interrupt. The value
/* will be set to zero. */ * will be set to zero.
/******************************************************/ */
regs->dar = 0; regs->dar = 0;
regs->dsisr = 0; regs->dsisr = 0;
regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF; regs->result = (u64)(saved_regs[PT_RESULT]) & 0xFFFFFFFF;
ret = regs->result; ret = regs->result;
return ret; return ret;
badframe: badframe:
...@@ -644,7 +638,8 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5, ...@@ -644,7 +638,8 @@ long sys32_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, struct sigaction32 *oact, size_t sigsetsize) asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act,
struct sigaction32 *oact, size_t sigsetsize)
{ {
struct k_sigaction new_ka, old_ka; struct k_sigaction new_ka, old_ka;
int ret; int ret;
...@@ -698,8 +693,8 @@ asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, struc ...@@ -698,8 +693,8 @@ asmlinkage long sys32_rt_sigaction(int sig, const struct sigaction32 *act, struc
} }
extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset, extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set,
size_t sigsetsize); sigset_t *oset, size_t sigsetsize);
/* /*
* Note: it is necessary to treat how as an unsigned int, with the * Note: it is necessary to treat how as an unsigned int, with the
...@@ -708,7 +703,8 @@ extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset ...@@ -708,7 +703,8 @@ extern asmlinkage long sys_rt_sigprocmask(int how, sigset_t *set, sigset_t *oset
* of a signed int (msr in 32-bit mode) and the register representation * of a signed int (msr in 32-bit mode) and the register representation
* of a signed int (msr in 64-bit mode) is performed. * of a signed int (msr in 64-bit mode) is performed.
*/ */
asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset, size_t sigsetsize) asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set,
sigset32_t *oset, size_t sigsetsize)
{ {
sigset_t s; sigset_t s;
sigset32_t s32; sigset32_t s32;
...@@ -727,11 +723,12 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset, ...@@ -727,11 +723,12 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset,
} }
} }
set_fs (KERNEL_DS); set_fs(KERNEL_DS);
ret = sys_rt_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL, ret = sys_rt_sigprocmask((int)how, set ? &s : NULL, oset ? &s : NULL,
sigsetsize); sigsetsize);
set_fs (old_fs); set_fs(old_fs);
if (ret) return ret; if (ret)
return ret;
if (oset) { if (oset) {
switch (_NSIG_WORDS) { switch (_NSIG_WORDS) {
case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
...@@ -749,17 +746,17 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset, ...@@ -749,17 +746,17 @@ asmlinkage long sys32_rt_sigprocmask(u32 how, sigset32_t *set, sigset32_t *oset,
extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize); extern asmlinkage long sys_rt_sigpending(sigset_t *set, size_t sigsetsize);
asmlinkage long sys32_rt_sigpending(sigset32_t *set,
asmlinkage long sys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsetsize) __kernel_size_t32 sigsetsize)
{ {
sigset_t s; sigset_t s;
sigset32_t s32; sigset32_t s32;
int ret; int ret;
mm_segment_t old_fs = get_fs(); mm_segment_t old_fs = get_fs();
set_fs (KERNEL_DS); set_fs(KERNEL_DS);
ret = sys_rt_sigpending(&s, sigsetsize); ret = sys_rt_sigpending(&s, sigsetsize);
set_fs (old_fs); set_fs(old_fs);
if (!ret) { if (!ret) {
switch (_NSIG_WORDS) { switch (_NSIG_WORDS) {
case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3]; case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];
...@@ -774,9 +771,7 @@ asmlinkage long sys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsets ...@@ -774,9 +771,7 @@ asmlinkage long sys32_rt_sigpending(sigset32_t *set, __kernel_size_t32 sigsets
} }
siginfo_t32 *siginfo64to32(siginfo_t32 *d, siginfo_t *s)
siginfo_t32 *
siginfo64to32(siginfo_t32 *d, siginfo_t *s)
{ {
memset (d, 0, sizeof(siginfo_t32)); memset (d, 0, sizeof(siginfo_t32));
d->si_signo = s->si_signo; d->si_signo = s->si_signo;
...@@ -787,39 +782,40 @@ siginfo64to32(siginfo_t32 *d, siginfo_t *s) ...@@ -787,39 +782,40 @@ siginfo64to32(siginfo_t32 *d, siginfo_t *s)
d->si_pid = s->si_pid; d->si_pid = s->si_pid;
d->si_uid = s->si_uid; d->si_uid = s->si_uid;
d->si_int = s->si_int; d->si_int = s->si_int;
} else switch (s->si_signo) { } else {
/* XXX: What about POSIX1.b timers */ switch (s->si_signo) {
case SIGCHLD: /* XXX: What about POSIX1.b timers */
d->si_pid = s->si_pid; case SIGCHLD:
d->si_status = s->si_status; d->si_pid = s->si_pid;
d->si_utime = s->si_utime; d->si_status = s->si_status;
d->si_stime = s->si_stime; d->si_utime = s->si_utime;
break; d->si_stime = s->si_stime;
case SIGSEGV: break;
case SIGBUS: case SIGSEGV:
case SIGFPE: case SIGBUS:
case SIGILL: case SIGFPE:
d->si_addr = (long)(s->si_addr); case SIGILL:
break; d->si_addr = (long)(s->si_addr);
case SIGPOLL: break;
d->si_band = s->si_band; case SIGPOLL:
d->si_fd = s->si_fd; d->si_band = s->si_band;
break; d->si_fd = s->si_fd;
default: break;
d->si_pid = s->si_pid; default:
d->si_uid = s->si_uid; d->si_pid = s->si_pid;
break; d->si_uid = s->si_uid;
break;
}
} }
return d; return d;
} }
extern asmlinkage long extern asmlinkage long sys_rt_sigtimedwait(const sigset_t *uthese,
sys_rt_sigtimedwait(const sigset_t *uthese, siginfo_t *uinfo, siginfo_t *uinfo, const struct timespec *uts,
const struct timespec *uts, size_t sigsetsize); size_t sigsetsize);
asmlinkage long asmlinkage long sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts, __kernel_size_t32 sigsetsize)
struct timespec32 *uts, __kernel_size_t32 sigsetsize)
{ {
sigset_t s; sigset_t s;
sigset32_t s32; sigset32_t s32;
...@@ -829,7 +825,7 @@ sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, ...@@ -829,7 +825,7 @@ sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
siginfo_t info; siginfo_t info;
siginfo_t32 info32; siginfo_t32 info32;
if (copy_from_user (&s32, uthese, sizeof(sigset32_t))) if (copy_from_user(&s32, uthese, sizeof(sigset32_t)))
return -EFAULT; return -EFAULT;
switch (_NSIG_WORDS) { switch (_NSIG_WORDS) {
case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
...@@ -838,20 +834,18 @@ sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, ...@@ -838,20 +834,18 @@ sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
} }
if (uts) { if (uts) {
ret = get_user (t.tv_sec, &uts->tv_sec); ret = get_user(t.tv_sec, &uts->tv_sec);
ret |= __get_user (t.tv_nsec, &uts->tv_nsec); ret |= __get_user(t.tv_nsec, &uts->tv_nsec);
if (ret) if (ret)
return -EFAULT; return -EFAULT;
} }
set_fs (KERNEL_DS); set_fs(KERNEL_DS);
if (uts) if (uts)
{
ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize); ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);
} else { else
ret = sys_rt_sigtimedwait(&s, &info, (struct timespec *)uts, sigsetsize); ret = sys_rt_sigtimedwait(&s, &info, (struct timespec *)uts,
} sigsetsize);
set_fs(old_fs);
set_fs (old_fs);
if (ret >= 0 && uinfo) { if (ret >= 0 && uinfo) {
if (copy_to_user (uinfo, siginfo64to32(&info32, &info), if (copy_to_user (uinfo, siginfo64to32(&info32, &info),
sizeof(siginfo_t32))) sizeof(siginfo_t32)))
...@@ -862,8 +856,7 @@ sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo, ...@@ -862,8 +856,7 @@ sys32_rt_sigtimedwait(sigset32_t *uthese, siginfo_t32 *uinfo,
siginfo_t * siginfo_t * siginfo32to64(siginfo_t *d, siginfo_t32 *s)
siginfo32to64(siginfo_t *d, siginfo_t32 *s)
{ {
d->si_signo = s->si_signo; d->si_signo = s->si_signo;
d->si_errno = s->si_errno; d->si_errno = s->si_errno;
...@@ -872,29 +865,30 @@ siginfo32to64(siginfo_t *d, siginfo_t32 *s) ...@@ -872,29 +865,30 @@ siginfo32to64(siginfo_t *d, siginfo_t32 *s)
d->si_pid = s->si_pid; d->si_pid = s->si_pid;
d->si_uid = s->si_uid; d->si_uid = s->si_uid;
d->si_int = s->si_int; d->si_int = s->si_int;
} else {
} else switch (s->si_signo) { switch (s->si_signo) {
/* XXX: What about POSIX1.b timers */ /* XXX: What about POSIX1.b timers */
case SIGCHLD: case SIGCHLD:
d->si_pid = s->si_pid; d->si_pid = s->si_pid;
d->si_status = s->si_status; d->si_status = s->si_status;
d->si_utime = s->si_utime; d->si_utime = s->si_utime;
d->si_stime = s->si_stime; d->si_stime = s->si_stime;
break; break;
case SIGSEGV: case SIGSEGV:
case SIGBUS: case SIGBUS:
case SIGFPE: case SIGFPE:
case SIGILL: case SIGILL:
d->si_addr = (void *)A(s->si_addr); d->si_addr = (void *)A(s->si_addr);
break; break;
case SIGPOLL: case SIGPOLL:
d->si_band = s->si_band; d->si_band = s->si_band;
d->si_fd = s->si_fd; d->si_fd = s->si_fd;
break; break;
default: default:
d->si_pid = s->si_pid; d->si_pid = s->si_pid;
d->si_uid = s->si_uid; d->si_uid = s->si_uid;
break; break;
}
} }
return d; return d;
} }
...@@ -928,8 +922,10 @@ asmlinkage long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo) ...@@ -928,8 +922,10 @@ asmlinkage long sys32_rt_sigqueueinfo(u32 pid, u32 sig, siginfo_t32 *uinfo)
} }
int do_signal(sigset_t *oldset, struct pt_regs *regs); extern int do_signal(sigset_t *oldset, struct pt_regs *regs);
int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, int p4, int p6, int p7, struct pt_regs *regs)
int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3,
int p4, int p6, int p7, struct pt_regs *regs)
{ {
sigset_t saveset, newset; sigset_t saveset, newset;
sigset32_t s32; sigset32_t s32;
...@@ -941,13 +937,15 @@ int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, int p4, ...@@ -941,13 +937,15 @@ int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, int p4,
if (copy_from_user(&s32, unewset, sizeof(s32))) if (copy_from_user(&s32, unewset, sizeof(s32)))
return -EFAULT; return -EFAULT;
/* Swap the 2 words of the 64-bit sigset_t (they are stored in the "wrong" endian in 32-bit user storage). */ /*
switch (_NSIG_WORDS) * Swap the 2 words of the 64-bit sigset_t (they are stored
{ * in the "wrong" endian in 32-bit user storage).
case 4: newset.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); */
case 3: newset.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); switch (_NSIG_WORDS) {
case 2: newset.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); case 4: newset.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);
case 1: newset.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); case 3: newset.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);
case 2: newset.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);
case 1: newset.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);
} }
sigdelsetmask(&newset, ~_BLOCKABLE); sigdelsetmask(&newset, ~_BLOCKABLE);
...@@ -971,11 +969,10 @@ int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, int p4, ...@@ -971,11 +969,10 @@ int sys32_rt_sigsuspend(sigset32_t* unewset, size_t sigsetsize, int p3, int p4,
/* /*
* Set up a rt signal frame. * Set up a rt signal frame.
*/ */
static void static void setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame,
setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame,
unsigned int newsp) unsigned int newsp)
{ {
unsigned int copyreg4,copyreg5; unsigned int copyreg4, copyreg5;
struct rt_sigframe_32 * rt_sf = (struct rt_sigframe_32 *) (u64)newsp; struct rt_sigframe_32 * rt_sf = (struct rt_sigframe_32 *) (u64)newsp;
...@@ -1089,6 +1086,7 @@ setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame, ...@@ -1089,6 +1086,7 @@ setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame,
return; return;
badframe: badframe:
udbg_printf("setup_frame32 - badframe in setup_frame, regs=%p frame=%p newsp=%lx\n", regs, frame, newsp); PPCDBG_ENTER_DEBUGGER();
#if DEBUG_SIG #if DEBUG_SIG
printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n", printk("badframe in setup_frame32, regs=%p frame=%p newsp=%lx\n",
regs, frame, newsp); regs, frame, newsp);
...@@ -1100,9 +1098,9 @@ setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame, ...@@ -1100,9 +1098,9 @@ setup_rt_frame32(struct pt_regs *regs, struct sigregs32 *frame,
/* /*
* OK, we're invoking a handler * OK, we're invoking a handler
*/ */
static void static void handle_signal32(unsigned long sig, siginfo_t *info,
handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, sigset_t *oldset, struct pt_regs * regs, unsigned int *newspp,
struct pt_regs * regs, unsigned int *newspp, unsigned int frame) unsigned int frame)
{ {
struct sigcontext32_struct *sc; struct sigcontext32_struct *sc;
struct rt_sigframe_32 *rt_stack_frame; struct rt_sigframe_32 *rt_stack_frame;
...@@ -1115,39 +1113,44 @@ handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -1115,39 +1113,44 @@ handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
!(ka->sa.sa_flags & SA_RESTART)))) !(ka->sa.sa_flags & SA_RESTART))))
regs->result = -EINTR; regs->result = -EINTR;
/* Set up the signal frame */ /*
/* Determine if an real time frame - siginfo required */ * Set up the signal frame
if (ka->sa.sa_flags & SA_SIGINFO) * Determine if an real time frame - siginfo required
{ */
if (ka->sa.sa_flags & SA_SIGINFO) {
siginfo64to32(&siginfo32bit,info); siginfo64to32(&siginfo32bit,info);
*newspp -= sizeof(*rt_stack_frame); *newspp -= sizeof(*rt_stack_frame);
rt_stack_frame = (struct rt_sigframe_32 *) (u64)(*newspp) ; rt_stack_frame = (struct rt_sigframe_32 *)(u64)(*newspp);
if (verify_area(VERIFY_WRITE, rt_stack_frame, sizeof(*rt_stack_frame))) if (verify_area(VERIFY_WRITE, rt_stack_frame,
{ sizeof(*rt_stack_frame)))
goto badframe; goto badframe;
} if (__put_user((u32)(u64)ka->sa.sa_handler,
if (__put_user((u32)(u64)ka->sa.sa_handler, &rt_stack_frame->uc.uc_mcontext.handler) &rt_stack_frame->uc.uc_mcontext.handler)
|| __put_user((u32)(u64)&rt_stack_frame->info, &rt_stack_frame->pinfo) || __put_user((u32)(u64)&rt_stack_frame->info,
|| __put_user((u32)(u64)&rt_stack_frame->uc, &rt_stack_frame->puc) &rt_stack_frame->pinfo)
|| __put_user((u32)(u64)&rt_stack_frame->uc,
&rt_stack_frame->puc)
/* put the siginfo on the user stack */ /* put the siginfo on the user stack */
|| __copy_to_user(&rt_stack_frame->info,&siginfo32bit,sizeof(siginfo32bit)) || __copy_to_user(&rt_stack_frame->info, &siginfo32bit,
sizeof(siginfo32bit))
/* set the ucontext on the user stack */ /* set the ucontext on the user stack */
|| __put_user(0,&rt_stack_frame->uc.uc_flags) || __put_user(0, &rt_stack_frame->uc.uc_flags)
|| __put_user(0,&rt_stack_frame->uc.uc_link) || __put_user(0, &rt_stack_frame->uc.uc_link)
|| __put_user(current->sas_ss_sp, &rt_stack_frame->uc.uc_stack.ss_sp) || __put_user(current->sas_ss_sp,
&rt_stack_frame->uc.uc_stack.ss_sp)
|| __put_user(sas_ss_flags(regs->gpr[1]), || __put_user(sas_ss_flags(regs->gpr[1]),
&rt_stack_frame->uc.uc_stack.ss_flags) &rt_stack_frame->uc.uc_stack.ss_flags)
|| __put_user(current->sas_ss_size, &rt_stack_frame->uc.uc_stack.ss_size) || __put_user(current->sas_ss_size,
|| __copy_to_user(&rt_stack_frame->uc.uc_sigmask, oldset,sizeof(*oldset)) &rt_stack_frame->uc.uc_stack.ss_size)
|| __copy_to_user(&rt_stack_frame->uc.uc_sigmask,
oldset, sizeof(*oldset))
/* point the mcontext.regs to the pramble register frame */ /* point the mcontext.regs to the pramble register frame */
|| __put_user(frame, &rt_stack_frame->uc.uc_mcontext.regs) || __put_user(frame, &rt_stack_frame->uc.uc_mcontext.regs)
|| __put_user(sig,&rt_stack_frame->uc.uc_mcontext.signal)) || __put_user(sig,&rt_stack_frame->uc.uc_mcontext.signal))
{
goto badframe; goto badframe;
}
} else { } else {
/* Put a sigcontext on the stack */ /* Put another sigcontext on the stack */
*newspp -= sizeof(*sc); *newspp -= sizeof(*sc);
sc = (struct sigcontext32_struct *)(u64)*newspp; sc = (struct sigcontext32_struct *)(u64)*newspp;
if (verify_area(VERIFY_WRITE, sc, sizeof(*sc))) if (verify_area(VERIFY_WRITE, sc, sizeof(*sc)))
...@@ -1194,8 +1197,8 @@ handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset, ...@@ -1194,8 +1197,8 @@ handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
* sigaltatck sys32_sigaltstack * sigaltatck sys32_sigaltstack
*/ */
asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, int p4, int p6, asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3,
int p7, struct pt_regs *regs) int p4, int p6, int p7, struct pt_regs *regs)
{ {
stack_t uss, uoss; stack_t uss, uoss;
int ret; int ret;
...@@ -1208,20 +1211,29 @@ asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, int p4, int ...@@ -1208,20 +1211,29 @@ asmlinkage int sys32_sigaltstack(u32 newstack, u32 oldstack, int p3, int p4, int
*/ */
sp = regs->gpr[1]; sp = regs->gpr[1];
/* Put new stack info in local 64 bit stack struct */ /* Put new stack info in local 64 bit stack struct */
if (newstack && (get_user((long)uss.ss_sp, &((stack_32_t *)(long)newstack)->ss_sp) || if (newstack &&
__get_user(uss.ss_flags, &((stack_32_t *)(long)newstack)->ss_flags) || (get_user((long)uss.ss_sp,
__get_user(uss.ss_size, &((stack_32_t *)(long)newstack)->ss_size))) &((stack_32_t *)(long)newstack)->ss_sp) ||
__get_user(uss.ss_flags,
&((stack_32_t *)(long)newstack)->ss_flags) ||
__get_user(uss.ss_size,
&((stack_32_t *)(long)newstack)->ss_size)))
return -EFAULT; return -EFAULT;
old_fs = get_fs(); old_fs = get_fs();
set_fs(KERNEL_DS); set_fs(KERNEL_DS);
ret = do_sigaltstack(newstack ? &uss : NULL, oldstack ? &uoss : NULL, sp); ret = do_sigaltstack(newstack ? &uss : NULL, oldstack ? &uoss : NULL,
sp);
set_fs(old_fs); set_fs(old_fs);
/* Copy the stack information to the user output buffer */ /* Copy the stack information to the user output buffer */
if (!ret && oldstack && (put_user((long)uoss.ss_sp, &((stack_32_t *)(long)oldstack)->ss_sp) || if (!ret && oldstack &&
__put_user(uoss.ss_flags, &((stack_32_t *)(long)oldstack)->ss_flags) || (put_user((long)uoss.ss_sp,
__put_user(uoss.ss_size, &((stack_32_t *)(long)oldstack)->ss_size))) &((stack_32_t *)(long)oldstack)->ss_sp) ||
__put_user(uoss.ss_flags,
&((stack_32_t *)(long)oldstack)->ss_flags) ||
__put_user(uoss.ss_size,
&((stack_32_t *)(long)oldstack)->ss_size)))
return -EFAULT; return -EFAULT;
return ret; return ret;
} }
...@@ -1259,8 +1271,8 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1259,8 +1271,8 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
if (signr > 0) { if (signr > 0) {
ka = &current->sig->action[signr-1]; ka = &current->sig->action[signr-1];
if ( (ka->sa.sa_flags & SA_ONSTACK) if ((ka->sa.sa_flags & SA_ONSTACK) &&
&& (! on_sig_stack(regs->gpr[1]))) (!on_sig_stack(regs->gpr[1])))
newsp = (current->sas_ss_sp + current->sas_ss_size); newsp = (current->sas_ss_sp + current->sas_ss_size);
else else
newsp = regs->gpr[1]; newsp = regs->gpr[1];
...@@ -1282,7 +1294,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs) ...@@ -1282,7 +1294,7 @@ int do_signal32(sigset_t *oldset, struct pt_regs *regs)
return 0; /* no signals delivered */ return 0; /* no signals delivered */
/* Invoke correct stack setup routine */ /* Invoke correct stack setup routine */
if (ka->sa.sa_flags & SA_SIGINFO) if (ka->sa.sa_flags & SA_SIGINFO)
setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp); setup_rt_frame32(regs, (struct sigregs32*)(u64)frame, newsp);
else else
setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp); setup_frame32(regs, (struct sigregs32*)(u64)frame, newsp);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment