--- arch/ppc/kernel/signal.c.old 2003-08-28 15:30:37.000000000 -0500 +++ arch/ppc/kernel/signal.c 2003-09-09 21:13:38.000000000 -0500 @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include #include @@ -40,6 +42,8 @@ #define GP_REGS_SIZE MIN(sizeof(elf_gregset_t), sizeof(struct pt_regs)) +int ppc_use_old_sigret = 1; + extern void syscall_direct_return(struct pt_regs *regs); int do_signal(sigset_t *oldset, struct pt_regs *regs); @@ -383,8 +387,15 @@ /* Save user registers on the stack */ frame = &rt_sf->uc.uc_mcontext; - if (save_user_regs(regs, frame, 0x6666, 0)) - goto badframe; + if (ppc_use_old_sigret) { + /* We use 0x6666 for a rt signal frame, the entry code will + map it to __NR_rt_sigreturn. */ + if (save_user_regs(regs, frame, 0x6666, 0)) + goto badframe; + } else { + if (save_user_regs(regs, frame, __NR_rt_sigreturn, 0)) + goto badframe; + } if (put_user(regs->gpr[1], (unsigned long *)newsp)) goto badframe; @@ -461,15 +472,13 @@ return 0; } -int sys_rt_sigreturn(struct pt_regs *regs) +int rt_sigreturn(struct ucontext *uc, struct pt_regs *regs) { - struct rt_sigframe *rt_sf; stack_t st; - rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE + 16); - if (verify_area(VERIFY_READ, rt_sf, sizeof(struct rt_sigframe))) + if (verify_area(VERIFY_READ, uc, sizeof(struct ucontext))) goto bad; - if (do_setcontext(&rt_sf->uc, regs, 0)) + if (do_setcontext(uc, regs, 0)) goto bad; /* @@ -479,7 +488,7 @@ * always done it up until now so it is probably better not to * change it. -- paulus */ - if (__copy_from_user(&st, &rt_sf->uc.uc_stack, sizeof(st))) + if (__copy_from_user(&st, &uc->uc_stack, sizeof(st))) goto bad; do_sigaltstack(&st, NULL, regs->gpr[1]); @@ -489,6 +498,61 @@ do_exit(SIGSEGV); } +int sys_rt_sigreturn(struct pt_regs *regs) +{ + struct rt_sigframe *rt_sf; + + rt_sf = (struct rt_sigframe *)(regs->gpr[1] + __SIGNAL_FRAMESIZE + 16); + return rt_sigreturn(&rt_sf->uc, regs); +} + +int sys_dbg_sigreturn(struct ucontext *uc, int ndbg, struct sig_dbg_op *dbg, + struct pt_regs *regs) +{ + struct sig_dbg_op op; + int i; + + for (i=0; imsr |= MSR_DE; + current->thread.dbcr0 |= (DBCR0_IDM | DBCR0_IC); + } else { + regs->msr &= ~MSR_DE; + current->thread.dbcr0 &= ~(DBCR0_IDM | DBCR0_IC); + regs->msr &= ~MSR_SE; + } +#else + if (op.dbg_value) + regs->msr |= MSR_SE; + else + regs->msr &= ~MSR_SE; +#endif + break; + + case SIG_DBG_BRANCH_TRACING: +#if defined(CONFIG_4xx) + return -EINVAL; +#else + if (op.dbg_value) + regs->msr |= MSR_BE; + else + regs->msr &= ~MSR_BE; +#endif + break; + + default: + return -EINVAL; + } + } + + return rt_sigreturn(uc, regs); +} + /* * OK, we're invoking a handler */ @@ -525,8 +589,15 @@ || __put_user(sig, &sc->signal)) goto badframe; - if (save_user_regs(regs, &frame->mctx, 0x7777, 0)) - goto badframe; + if (ppc_use_old_sigret) { + /* We use 0x7777 for a normal signal frame, the entry code will + map it to __NR_sigreturn. */ + if (save_user_regs(regs, &frame->mctx, 0x7777, 0)) + goto badframe; + } else { + if (save_user_regs(regs, &frame->mctx, __NR_sigreturn, 0)) + goto badframe; + } if (put_user(regs->gpr[1], (unsigned long *)newsp)) goto badframe; @@ -747,3 +818,23 @@ return 1; } +#define PPC_CPU_DEFHANDLER_SIGTYPE 1 +static struct ctl_table ppc_table[] = { + {PPC_CPU_DEFHANDLER_SIGTYPE, "sigtype", &ppc_use_old_sigret, + sizeof(int), 0644, NULL, &proc_dointvec_minmax}, + {0} +}; + +static struct ctl_table ppc_root_table[] = { + {CTL_CPU, "ppc", NULL, 0, 0555, ppc_table}, + {0} +}; + +static int __init +ppc_register_sysctl(void) +{ + register_sysctl_table(ppc_root_table, 1); + return 0; +} + +__initcall(ppc_register_sysctl); --- arch/ppc/kernel/traps.c.old 2003-08-28 15:42:26.000000000 -0500 +++ arch/ppc/kernel/traps.c 2003-09-05 09:15:47.000000000 -0500 @@ -396,7 +396,7 @@ void SingleStepException(struct pt_regs *regs) { - regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ + regs->msr &= ~(MSR_SE | MSR_BE); /* Turn off 'trace' bits */ if (debugger_sstep(regs)) return; _exception(SIGTRAP, regs, TRAP_TRACE, 0); --- arch/ppc/kernel/entry.S.old 2003-08-31 04:39:10.000000000 -0500 +++ arch/ppc/kernel/entry.S 2003-09-09 20:21:41.000000000 -0500 @@ -28,6 +28,7 @@ #include #include #include +#include #include "ppc_defs.h" #undef SHOW_SYSCALLS @@ -80,27 +81,24 @@ lwz r8,GPR8(r1) 1: #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_PTRACE(r2) andi. r10,r10,PT_TRACESYS bne- 50f cmpli 0,r0,NR_syscalls bge- 66f +syscall_1: lis r10,sys_call_table@h ori r10,r10,sys_call_table@l slwi r0,r0,2 lwzx r10,r10,r0 /* Fetch system call handler [ptr] */ cmpi 0,r10,0 - beq- 66f + beq- 16f mtlr r10 addi r9,r1,STACK_FRAME_OVERHEAD blrl /* Call handler */ .globl ret_from_syscall_1 ret_from_syscall_1: -20: stw r3,RESULT(r1) /* Save result */ + stw r3,RESULT(r1) /* Save result */ #ifdef SHOW_SYSCALLS #ifdef SHOW_SYSCALLS_TASK cmp 0,r2,r31 @@ -125,20 +123,17 @@ stw r10,_CCR(r1) 30: stw r3,GPR3(r1) /* Update return value */ b ret_from_except -66: li r3,ENOSYS + +66: cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */ + bne- 10f + li r0,__NR_sigreturn + b syscall_1 +10: cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */ + bne- 16f + li r0,__NR_rt_sigreturn + b syscall_1 +16: li r3,ENOSYS b 22b -/* 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 /* Traced system call support */ 50: bl syscall_trace lwz r0,GPR0(r1) /* Restore original registers */ @@ -151,12 +146,13 @@ lwz r9,GPR9(r1) cmpli 0,r0,NR_syscalls bge- 66f +syscall_2: lis r10,sys_call_table@h ori r10,r10,sys_call_table@l slwi r0,r0,2 lwzx r10,r10,r0 /* Fetch system call handler [ptr] */ cmpi 0,r10,0 - beq- 66f + beq- 16f mtlr r10 addi r9,r1,STACK_FRAME_OVERHEAD blrl /* Call handler */ @@ -176,7 +172,15 @@ 60: stw r3,GPR3(r1) /* Update return value */ bl syscall_trace b ret_from_except -66: li r3,ENOSYS +66: cmpi 0,r0,0x7777 /* Special case for 'sys_sigreturn' */ + bne- 10f + li r0,__NR_sigreturn + b syscall_2 +10: cmpi 0,r0,0x6666 /* Special case for 'sys_rt_sigreturn' */ + bne- 16f + li r0,__NR_rt_sigreturn + b syscall_2 +16: li r3,ENOSYS b 52b #ifdef SHOW_SYSCALLS 7: .string "syscall %d(%x, %x, %x, %x, %x, " --- arch/ppc/kernel/misc.S.old 2003-08-31 04:39:09.000000000 -0500 +++ arch/ppc/kernel/misc.S 2003-09-09 21:41:58.000000000 -0500 @@ -1034,6 +1034,37 @@ _GLOBAL(__main) blr +_sys_sigreturn: + addi r3,r1,STACK_FRAME_OVERHEAD + mflr r30 + bl sys_sigreturn + cmpi 0,r3,0 /* Check for restarted system call */ + bge ret_from_except + mtlr r30 + blr + +_sys_rt_sigreturn: + addi r3,r1,STACK_FRAME_OVERHEAD + mflr r30 + bl sys_rt_sigreturn + cmpi 0,r3,0 /* Check for restarted system call */ + bge ret_from_except + mtlr r30 + blr + +/* + * This handles the special case of the debug sigreturn call, which needs + * the registers in order to do its job. + */ +_sys_dbg_sigreturn: + addi r6,r1,STACK_FRAME_OVERHEAD + mflr r30 + bl sys_dbg_sigreturn + cmpi 0,r3,0 /* Check for restarted system call */ + bge ret_from_except + mtlr r30 + blr + #define SYSCALL(name) \ _GLOBAL(name) \ li r0,__NR_##name; \ @@ -1183,7 +1214,7 @@ .long sys_sysinfo .long sys_ipc .long sys_fsync - .long sys_sigreturn + .long _sys_sigreturn .long sys_clone /* 120 */ .long sys_setdomainname .long sys_newuname @@ -1236,7 +1267,7 @@ .long sys_setresgid .long sys_getresgid /* 170 */ .long sys_prctl - .long sys_rt_sigreturn + .long _sys_rt_sigreturn .long sys_rt_sigaction .long sys_rt_sigprocmask .long sys_rt_sigpending /* 175 */ @@ -1314,6 +1345,11 @@ .long sys_ni_syscall /* reserved for sys_clock_getres */ .long sys_ni_syscall /* reserved for sys_clock_nanosleep */ .long sys_swapcontext + .long sys_ni_syscall /* 250 reserved for sys_tgkill */ + .long sys_ni_syscall /* reserved for sys_utimes */ + .long sys_ni_syscall /* reserved for sys_statfs64 */ + .long sys_ni_syscall /* reserved for sys_fstatfs64 */ + .long _sys_dbg_sigreturn .rept NR_syscalls-(.-sys_call_table)/4 .long sys_ni_syscall --- include/asm-ppc/signal.h.old 2003-09-09 11:29:59.000000000 -0500 +++ include/asm-ppc/signal.h 2003-09-09 13:29:49.000000000 -0500 @@ -152,4 +152,23 @@ #include #endif /* __KERNEL__ */ +/* + * These are parameters to dbg_sigreturn syscall. They enable or + * disable certain debugging things that can be done from signal + * handlers. The dbg_sigreturn syscall *must* be called from a + * SA_SIGINFO signal so the ucontext can be passed to it. It takes an + * array of struct sig_dbg_op, which has the debug operations to + * perform before returning from the signal. + */ +struct sig_dbg_op { + int dbg_type; + unsigned long dbg_value; +}; + +/* Enable or disable single-stepping. The value sets the state. */ +#define SIG_DBG_SINGLE_STEPPING 1 + +/* Enable or disable branch tracing. The value sets the state. */ +#define SIG_DBG_BRANCH_TRACING 2 + #endif --- include/asm-ppc/unistd.h.old 2003-08-31 04:41:10.000000000 -0500 +++ include/asm-ppc/unistd.h 2003-09-09 21:44:04.000000000 -0500 @@ -237,7 +237,33 @@ #define __NR_io_getevents 229 #define __NR_io_submit 230 #define __NR_io_cancel 231 +#define __NR_set_tid_address 232 +#define __NR_fadvise64 233 +#define __NR_exit_group 234 +#define __NR_lookup_dcookie 235 +#define __NR_epoll_create 236 +#define __NR_epoll_ctl 237 +#define __NR_epoll_wait 238 +#define __NR_remap_file_pages 239 +#define __NR_timer_create 240 +#define __NR_timer_settime 241 +#define __NR_timer_gettime 242 +#define __NR_timer_getoverrun 243 +#define __NR_timer_delete 244 +#define __NR_clock_settime 245 +#define __NR_clock_gettime 246 +#define __NR_clock_getres 247 +#define __NR_clock_nanosleep 248 #endif +#define __NR_swapcontext 249 +#if 0 +#define __NR_tgkill 250 +#define __NR__utimes 251 +#define __NR_statfs64 252 +#define __NR_fstatfs64 253 +#endif +#define __NR_dbg_sigreturn 254 + #define __NR(n) #n