From: <ai...@us...> - 2003-09-16 12:34:21
|
Update of /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel In directory sc8-pr-cvs1:/tmp/cvs-serv16019 Modified Files: signal.c Log Message: DA: this is better than what was there already - still not tested, I'd say there is still some work left to do Index: signal.c =================================================================== RCS file: /cvsroot/linux-vax/kernel-2.4/arch/vax/kernel/signal.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- signal.c 16 Feb 2003 23:28:02 -0000 1.11 +++ signal.c 16 Sep 2003 12:34:15 -0000 1.12 @@ -32,7 +32,7 @@ #include <asm/ucontext.h> #include <asm/uaccess.h> -#undef DEBUG_SIG +#undef DEBUG_SIG /* FIXME: Check this & fixup other regs, like r0 */ #define RESTART_VAX_SYSCALL(regs) { (regs)->pc -= 4; } @@ -188,12 +188,10 @@ /* FIXME: this dont work ... */ struct rt_sigframe { - char *pretcode; - struct siginfo *pinfo; - void *puc; + int sig; struct siginfo info; struct ucontext uc; - unsigned char retcode[8]; /* trampoline code */ + unsigned char retcode[20]; /* trampoline code */ }; @@ -526,17 +524,14 @@ sigset_t *set, struct pt_regs * regs) { struct rt_sigframe *frame; - unsigned long return_ip; int err = 0; - machine_halt(); + // machine_halt(); frame = get_sigframe(ka, regs, sizeof(*frame)); if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) goto give_sigsegv; - err |= __put_user(&frame->info, &frame->pinfo); - err |= __put_user(&frame->uc, &frame->puc); err |= copy_siginfo_to_user(&frame->info, info); if (err) goto give_sigsegv; @@ -553,17 +548,54 @@ /* Set up to return from userspace. If provided, use a stub already in userspace. */ + + /* Set up to return from userspace. If provided, use a stub + already in userspace. */ + + /* We do this differently to other ports. Each function has a two byte RSM. + * (due to the calling convention). Each sighandler will expect to be + * CALLS'd and will RET from that. So we cant just muck about with PC's on the + * stack like the i386. So we use the trampoline code on the stack a bit more. + * The easiest way to skip around all this is to calls the signal + * handler, and then either calls the restorer, or chmk to sys_sigreturn */ + + /* CALLS $1, */ + err |= __put_user(0xfb, (char *)(frame->retcode+0)); + err |= __put_user(0x01, (char *)(frame->retcode+1)); + /* (absolute address)*/ + err |= __put_user(0x9f, (char *)(frame->retcode+2)); + /* sighandler */ + err |= __put_user(((unsigned long) ka->sa.sa_handler), (unsigned long *)(frame->retcode + 3)); + if (ka->sa.sa_flags & SA_RESTORER) { - return_ip = (unsigned long)ka->sa.sa_restorer; + /* CALLS $0,*/ + err |= __put_user(0xfb, (char *)(frame->retcode+7)); + err |= __put_user(0x00, (char *)(frame->retcode+8)); + /* (absolute address)*/ + err |= __put_user(0x9f, (char *)(frame->retcode+9)); + /* restorer */ + err |= __put_user(((unsigned long) ka->sa.sa_restorer), (unsigned long *)(frame->retcode + 10)); + /* plus a halt */ + err |= __put_user(0x00, (char *)(frame->retcode+14)); } else { - /* trampoline - the desired return ip is the retcode itself */ - return_ip = (unsigned long)&frame->retcode; - /* TODO: check byteorder */ - err |= __put_user(0xbc8f, (short *)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2)); + /* perform a syscall to sys_sigreturn. First set up the + * argument list to avoid confusing it */ + + /* pushl $0x0 */ + err |= __put_user(0xdd, (char *)(frame->retcode+7)); + err |= __put_user(0x00, (char *)(frame->retcode+8)); + /* movl sp, ap */ + err |= __put_user(0xd0, (char *)(frame->retcode+9)); + err |= __put_user(0x5e, (char *)(frame->retcode+10)); + err |= __put_user(0x5c, (char *)(frame->retcode+11)); + /* chmk __NR_sigreturn; */ + err |= __put_user(0xbc, (char *)(frame->retcode+12)); + err |= __put_user(0x8f, (char *)(frame->retcode+13)); + err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+14)); + /* plus a halt */ + err |= __put_user(0x00, (char *)(frame->retcode+16)); } - err |= __put_user(return_ip, &frame->pretcode); if (err) goto give_sigsegv; @@ -572,7 +604,9 @@ /* Set up registers for signal handler */ regs->pc = (unsigned long) ka->sa.sa_handler; /* what we enter NOW */ - regs->sp = (unsigned int)frame; /* what we enter LATER */ + regs->fp = regs->sp; + regs->sp = (unsigned int)frame; /* what we enter LATER */ + __mtpr(frame, PR_USP); return; @@ -657,7 +691,7 @@ return 1; /* FIXME: */ - canrestart=0; + canrestart=regs->r0; #ifdef DEBUG_SIG printk("do_signal: pid %d,canrestart %d, current->sigpending %d,current->blocked %d ", current->pid,canrestart,current->sigpending,current->blocked); #endif |