From daf423db3b6afd90ecdd776dbc32c0b57cc78edb Mon Sep 17 00:00:00 2001 From: Simon Horman Date: Wed, 30 Jul 2008 10:29:39 +1000 Subject: kdump: sh: parse elfcorehdr command line argument A quick cut and paste from other architectures to allow SH to parse the elfcorehdr command line argument which is required for both is_kdump_kernel() and vmcore to function. (the former is as yet unused on SH). Tested compilation only Signed-off-by: Simon Horman Signed-off-by: Paul Mundt --- arch/sh/kernel/setup.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/setup.c b/arch/sh/kernel/setup.c index 6339d0c95715..a35207655e7b 100644 --- a/arch/sh/kernel/setup.c +++ b/arch/sh/kernel/setup.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -286,6 +287,25 @@ static void __init setup_memory(void) extern void __init setup_memory(void); #endif +/* + * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by + * is_kdump_kernel() to determine if we are booting after a panic. Hence + * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE. + */ +#ifdef CONFIG_CRASH_DUMP +/* elfcorehdr= specifies the location of elf core header + * stored by the crashed kernel. + */ +static int __init parse_elfcorehdr(char *arg) +{ + if (!arg) + return -EINVAL; + elfcorehdr_addr = memparse(arg, &arg); + return 0; +} +early_param("elfcorehdr", parse_elfcorehdr); +#endif + void __init setup_arch(char **cmdline_p) { enable_mmu(); -- cgit v1.2.3 From cec3fd3e2a7cacf37e2bd6d9fa915337245cc563 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 30 Jul 2008 13:11:26 +0900 Subject: sh: Tidy up the _TIF work masks, and fix syscall trace bug on singlestep. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh5/entry.S | 2 +- arch/sh/kernel/entry-common.S | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index ca08e7f26a3a..bba331d5ef74 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -1300,7 +1300,7 @@ syscall_allowed: getcon KCR0, r2 ld.l r2, TI_FLAGS, r4 - movi (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT), r6 + movi _TIF_WORK_SYSCALL_MASK, r6 and r6, r4, r6 beq/l r6, ZERO, tr0 diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 5e0dd1933847..a34417c8ee0a 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -202,7 +202,7 @@ work_resched: syscall_exit_work: ! r0: current_thread_info->flags ! r8: current_thread_info - tst #_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | _TIF_SYSCALL_AUDIT, r0 + tst #_TIF_WORK_SYSCALL_MASK, r0 bt/s work_pending tst #_TIF_NEED_RESCHED, r0 #ifdef CONFIG_TRACE_IRQFLAGS @@ -351,7 +351,7 @@ ENTRY(system_call) ! get_current_thread_info r8, r10 mov.l @(TI_FLAGS,r8), r8 - mov #(_TIF_SYSCALL_TRACE | _TIF_SYSCALL_AUDIT), r10 + mov #_TIF_WORK_SYSCALL_MASK, r10 tst r10, r8 bf syscall_trace_entry ! -- cgit v1.2.3 From c4637d475170ca0d99973efd07df727012db6cd1 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 30 Jul 2008 15:30:52 +0900 Subject: sh: seccomp support. This hooks up the seccomp thread flag and associated callback from the syscall tracer. Signed-off-by: Paul Mundt --- arch/sh/kernel/ptrace_32.c | 3 +++ arch/sh/kernel/ptrace_64.c | 3 +++ 2 files changed, 6 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 2bc72def5cf8..e9bd4b2aa9c2 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -276,6 +277,8 @@ asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) { struct task_struct *tsk = current; + secure_computing(regs->regs[0]); + if (unlikely(current->audit_context) && entryexit) audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), regs->regs[0]); diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index d453c47dc522..7d8776260953 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -277,6 +278,8 @@ asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) { struct task_struct *tsk = current; + secure_computing(regs->regs[9]); + if (unlikely(current->audit_context) && entryexit) audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), regs->regs[9]); -- cgit v1.2.3 From c459dbf294b4a3d70490a468a7ca3907fb2c2f57 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 30 Jul 2008 19:09:31 +0900 Subject: sh: ptrace single stepping cleanups. This converts the single stepping done by sh/sh64 ptrace implementations to use the generic user_enable/disable_single_step(), and subsequently rips out a lot of ptrace request cases that are now handled generically. Signed-off-by: Paul Mundt --- arch/sh/kernel/ptrace_32.c | 93 +++++++++------------------------------------- arch/sh/kernel/ptrace_64.c | 77 ++++++-------------------------------- 2 files changed, 30 insertions(+), 140 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index e9bd4b2aa9c2..ff66f97c564d 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -58,7 +58,23 @@ static inline int put_stack_long(struct task_struct *task, int offset, return 0; } -static void ptrace_disable_singlestep(struct task_struct *child) +void user_enable_single_step(struct task_struct *child) +{ + struct pt_regs *regs = task_pt_regs(child); + long pc; + + pc = get_stack_long(child, (long)®s->pc); + + /* Next scheduling will set up UBC */ + if (child->thread.ubc_pc == 0) + ubc_usercnt += 1; + + child->thread.ubc_pc = pc; + + set_tsk_thread_flag(child, TIF_SINGLESTEP); +} + +void user_disable_single_step(struct task_struct *child) { clear_tsk_thread_flag(child, TIF_SINGLESTEP); @@ -82,7 +98,7 @@ static void ptrace_disable_singlestep(struct task_struct *child) */ void ptrace_disable(struct task_struct *child) { - ptrace_disable_singlestep(child); + user_disable_single_step(child); } long arch_ptrace(struct task_struct *child, long request, long addr, long data) @@ -91,12 +107,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int ret; switch (request) { - /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { unsigned long tmp; @@ -126,12 +136,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ ret = -EIO; if ((addr & 3) || addr < 0 || @@ -152,67 +156,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - ret = -EIO; - if (!valid_signal(data)) - break; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - - ptrace_disable_singlestep(child); - - child->exit_code = data; - wake_up_process(child); - ret = 0; - break; - } - -/* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: { - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - ptrace_disable_singlestep(child); - child->exit_code = SIGKILL; - wake_up_process(child); - break; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - long pc; - struct pt_regs *regs = NULL; - - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - - pc = get_stack_long(child, (long)®s->pc); - - /* Next scheduling will set up UBC */ - if (child->thread.ubc_pc == 0) - ubc_usercnt += 1; - child->thread.ubc_pc = pc; - - set_tsk_thread_flag(child, TIF_SINGLESTEP); - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - break; - } - #ifdef CONFIG_SH_DSP case PTRACE_GETDSPREGS: { unsigned long dp; diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 7d8776260953..108f3962e39a 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -121,18 +121,23 @@ put_fpu_long(struct task_struct *task, unsigned long addr, unsigned long data) return 0; } +void user_enable_single_step(struct task_struct *child) +{ + struct pt_regs *regs = child->thread.uregs; + + regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ +} + +void user_disable_single_step(struct task_struct *child) +{ + regs->sr &= ~SR_SSTEP; +} long arch_ptrace(struct task_struct *child, long request, long addr, long data) { int ret; switch (request) { - /* when I and D space are separate, these will need to be fixed. */ - case PTRACE_PEEKTEXT: /* read word at location addr. */ - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - /* read the word at location addr in the USER area. */ case PTRACE_PEEKUSR: { unsigned long tmp; @@ -155,12 +160,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } - /* when I and D space are separate, this will have to be fixed. */ - case PTRACE_POKETEXT: /* write the word at location addr. */ - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - case PTRACE_POKEUSR: /* write the word at location addr in the USER area. We must disallow any changes to certain SR bits or u_fpvalid, since @@ -192,58 +191,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) } break; - case PTRACE_SYSCALL: /* continue and stop at next (return from) syscall */ - case PTRACE_CONT: { /* restart after signal. */ - ret = -EIO; - if (!valid_signal(data)) - break; - if (request == PTRACE_SYSCALL) - set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - else - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - child->exit_code = data; - wake_up_process(child); - ret = 0; - break; - } - -/* - * make the child exit. Best I can do is send it a sigkill. - * perhaps it should be put in the status that it wants to - * exit. - */ - case PTRACE_KILL: { - ret = 0; - if (child->exit_state == EXIT_ZOMBIE) /* already dead */ - break; - child->exit_code = SIGKILL; - wake_up_process(child); - break; - } - - case PTRACE_SINGLESTEP: { /* set the trap flag. */ - struct pt_regs *regs; - - ret = -EIO; - if (!valid_signal(data)) - break; - clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); - if ((child->ptrace & PT_DTRACE) == 0) { - /* Spurious delayed TF traps may occur */ - child->ptrace |= PT_DTRACE; - } - - regs = child->thread.uregs; - - regs->sr |= SR_SSTEP; /* auto-resetting upon exception */ - - child->exit_code = data; - /* give it a chance to run. */ - wake_up_process(child); - ret = 0; - break; - } - default: ret = ptrace_request(child, request, addr, data); break; @@ -341,5 +288,5 @@ asmlinkage void do_software_break_point(unsigned long long vec, */ void ptrace_disable(struct task_struct *child) { - /* nothing to do.. */ + user_disable_single_step(child); } -- cgit v1.2.3 From ab99c733ae73cce31f2a2434f7099564e5a73d95 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 30 Jul 2008 19:55:30 +0900 Subject: sh: Make syscall tracer use tracehook notifiers, add TIF_NOTIFY_RESUME. This follows the changes in commits: 7d6d637dac2050f30a1b57b0a3dc5de4a10616ba 4f72c4279eab1e5f3ed1ac4e55d4527617582392 on powerpc. Adding in TIF_NOTIFY_RESUME, and cleaning up the syscall tracing to be more generic. This is an incremental step to turning on tracehook, as well as unifying more of the ptrace and signal code across the 32/64 split. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh5/entry.S | 17 +++-- arch/sh/kernel/entry-common.S | 12 ++- arch/sh/kernel/ptrace_32.c | 54 +++++++------- arch/sh/kernel/ptrace_64.c | 50 ++++++------- arch/sh/kernel/signal_32.c | 22 ++++-- arch/sh/kernel/signal_64.c | 166 ++++++++++++++++++++++------------------- 6 files changed, 167 insertions(+), 154 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh5/entry.S b/arch/sh/kernel/cpu/sh5/entry.S index bba331d5ef74..04c7da968146 100644 --- a/arch/sh/kernel/cpu/sh5/entry.S +++ b/arch/sh/kernel/cpu/sh5/entry.S @@ -987,11 +987,11 @@ work_resched: work_notifysig: gettr tr1, LINK - movi do_signal, r6 + movi do_notify_resume, r6 ptabs r6, tr0 or SP, ZERO, r2 - or ZERO, ZERO, r3 - blink tr0, LINK /* Call do_signal(regs, 0), return here */ + or r7, ZERO, r3 + blink tr0, LINK /* Call do_notify_resume(regs, current_thread_info->flags), return here */ restore_all: /* Do prefetches */ @@ -1305,13 +1305,15 @@ syscall_allowed: beq/l r6, ZERO, tr0 /* Trace it by calling syscall_trace before and after */ - movi syscall_trace, r4 + movi do_syscall_trace_enter, r4 or SP, ZERO, r2 - or ZERO, ZERO, r3 ptabs r4, tr0 blink tr0, LINK - /* Reload syscall number as r5 is trashed by syscall_trace */ + /* Save the retval */ + st.q SP, FRAME_R(2), r2 + + /* Reload syscall number as r5 is trashed by do_syscall_trace_enter */ ld.q SP, FRAME_S(FSYSCALL_ID), r5 andi r5, 0x1ff, r5 @@ -1343,9 +1345,8 @@ syscall_ret_trace: /* We get back here only if under trace */ st.q SP, FRAME_R(9), r2 /* Save return value */ - movi syscall_trace, LINK + movi do_syscall_trace_leave, LINK or SP, ZERO, r2 - movi 1, r3 ptabs LINK, tr0 blink tr0, LINK diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index a34417c8ee0a..0bc17def55a7 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S @@ -211,10 +211,8 @@ syscall_exit_work: nop #endif sti - ! XXX setup arguments... mov r15, r4 - mov #1, r5 - mov.l 4f, r0 ! do_syscall_trace + mov.l 8f, r0 ! do_syscall_trace_leave jsr @r0 nop bra resume_userspace @@ -223,12 +221,11 @@ syscall_exit_work: .align 2 syscall_trace_entry: ! Yes it is traced. - ! XXX setup arguments... mov r15, r4 - mov #0, r5 - mov.l 4f, r11 ! Call do_syscall_trace which notifies + mov.l 7f, r11 ! Call do_syscall_trace_enter which notifies jsr @r11 ! superior (will chomp R[0-7]) nop + mov.l r0, @(OFF_R0,r15) ! Save return value ! Reload R0-R4 from kernel stack, where the ! parent may have modified them using ! ptrace(POKEUSR). (Note that R0-R2 are @@ -389,8 +386,9 @@ syscall_exit: #endif 2: .long NR_syscalls 3: .long sys_call_table -4: .long do_syscall_trace #ifdef CONFIG_TRACE_IRQFLAGS 5: .long trace_hardirqs_on 6: .long trace_hardirqs_off #endif +7: .long do_syscall_trace_enter +8: .long do_syscall_trace_leave diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index ff66f97c564d..f48769b23bd6 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -216,41 +217,38 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } -asmlinkage void do_syscall_trace(struct pt_regs *regs, int entryexit) +asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) { - struct task_struct *tsk = current; + long ret = 0; secure_computing(regs->regs[0]); - if (unlikely(current->audit_context) && entryexit) - audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), - regs->regs[0]); - - if (!test_thread_flag(TIF_SYSCALL_TRACE) && - !test_thread_flag(TIF_SINGLESTEP)) - goto out; - if (!(tsk->ptrace & PT_PTRACED)) - goto out; - - /* the 0x80 provides a way for the tracing parent to distinguish - between a syscall stop and SIGTRAP delivery */ - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && - !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (tsk->exit_code) { - send_sig(tsk->exit_code, tsk, 1); - tsk->exit_code = 0; - } + if (test_thread_flag(TIF_SYSCALL_TRACE) && + tracehook_report_syscall_entry(regs)) + /* + * Tracing decided this syscall should not happen. + * We'll return a bogus call number to get an ENOSYS + * error, but leave the original number in regs->regs[0]. + */ + ret = -1L; -out: - if (unlikely(current->audit_context) && !entryexit) + if (unlikely(current->audit_context)) audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); + return ret ?: regs->regs[0]; +} + +asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) +{ + int step; + + if (unlikely(current->audit_context)) + audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), + regs->regs[0]); + + step = test_thread_flag(TIF_SINGLESTEP); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); } diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 108f3962e39a..236d8bef9ccd 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -221,40 +222,37 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) return sys_ptrace(request, pid, addr, data); } -asmlinkage void syscall_trace(struct pt_regs *regs, int entryexit) +asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs) { - struct task_struct *tsk = current; + long long ret = 0; secure_computing(regs->regs[9]); - if (unlikely(current->audit_context) && entryexit) - audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), - regs->regs[9]); - - if (!test_thread_flag(TIF_SYSCALL_TRACE) && - !test_thread_flag(TIF_SINGLESTEP)) - goto out; - if (!(tsk->ptrace & PT_PTRACED)) - goto out; - - ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) && - !test_thread_flag(TIF_SINGLESTEP) ? 0x80 : 0)); - - /* - * this isn't the same as continuing with a signal, but it will do - * for normal use. strace only continues with a signal if the - * stopping signal is not SIGTRAP. -brl - */ - if (tsk->exit_code) { - send_sig(tsk->exit_code, tsk, 1); - tsk->exit_code = 0; - } + if (test_thread_flag(TIF_SYSCALL_TRACE) && + tracehook_report_syscall_entry(regs)) + /* + * Tracing decided this syscall should not happen. + * We'll return a bogus call number to get an ENOSYS + * error, but leave the original number in regs->regs[0]. + */ + ret = -1LL; -out: - if (unlikely(current->audit_context) && !entryexit) + if (unlikely(current->audit_context)) audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1], regs->regs[2], regs->regs[3], regs->regs[4], regs->regs[5]); + + return ret ?: regs->regs[9]; +} + +asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) +{ + if (unlikely(current->audit_context)) + audit_syscall_exit(AUDITSC_RESULT(regs->regs[9]), + regs->regs[9]); + + if (test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, 0); } /* Called with interrupts disabled */ diff --git a/arch/sh/kernel/signal_32.c b/arch/sh/kernel/signal_32.c index 4bbbde895a53..51689d29ad45 100644 --- a/arch/sh/kernel/signal_32.c +++ b/arch/sh/kernel/signal_32.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -507,14 +508,13 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info, switch (regs->regs[0]) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: + no_system_call_restart: regs->regs[0] = -EINTR; break; case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->regs[0] = -EINTR; - break; - } + if (!(ka->sa.sa_flags & SA_RESTART)) + goto no_system_call_restart; /* fallthrough */ case -ERESTARTNOINTR: regs->regs[0] = save_r0; @@ -589,12 +589,15 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) * clear the TIF_RESTORE_SIGMASK flag */ if (test_thread_flag(TIF_RESTORE_SIGMASK)) clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, regs, + test_thread_flag(TIF_SINGLESTEP)); } return; } - no_signal: +no_signal: /* Did we come from a system call? */ if (regs->tra >= 0) { /* Restart the system call - no handlers present */ @@ -618,9 +621,14 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0) } asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0, - __u32 thread_info_flags) + unsigned long thread_info_flags) { /* deal with pending signal delivery */ - if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK)) + if (thread_info_flags & _TIF_SIGPENDING) do_signal(regs, save_r0); + + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); + } } diff --git a/arch/sh/kernel/signal_64.c b/arch/sh/kernel/signal_64.c index 552eb810cd85..1d62dfef77f1 100644 --- a/arch/sh/kernel/signal_64.c +++ b/arch/sh/kernel/signal_64.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -42,7 +43,84 @@ #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) -asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); +/* + * Note that 'init' is a special process: it doesn't get signals it doesn't + * want to handle. Thus you cannot kill init even with a SIGKILL even by + * mistake. + * + * Note that we go through the signals twice: once to check the signals that + * the kernel can handle, and then we build all the user-level signal handling + * stack-frames in one go after that. + */ +static int do_signal(struct pt_regs *regs, sigset_t *oldset) +{ + siginfo_t info; + int signr; + struct k_sigaction ka; + + /* + * We want the common case to go fast, which + * is why we may in certain cases get here from + * kernel mode. Just return without doing anything + * if so. + */ + if (!user_mode(regs)) + return 1; + + if (try_to_freeze()) + goto no_signal; + + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else if (!oldset) + oldset = ¤t->blocked; + + signr = get_signal_to_deliver(&info, &ka, regs, 0); + + if (signr > 0) { + /* Whee! Actually deliver the signal. */ + handle_signal(signr, &info, &ka, oldset, regs); + + /* + * If a signal was successfully delivered, the saved sigmask + * is in its frame, and we can clear the TIF_RESTORE_SIGMASK + * flag. + */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); + + tracehook_signal_handler(signr, &info, &ka, regs, 0); + return 1; + } + +no_signal: + /* Did we come from a system call? */ + if (regs->syscall_nr >= 0) { + /* Restart the system call - no handlers present */ + switch (regs->regs[REG_RET]) { + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: + /* Decode Syscall # */ + regs->regs[REG_RET] = regs->syscall_nr; + regs->pc -= 4; + break; + + case -ERESTART_RESTARTBLOCK: + regs->regs[REG_RET] = __NR_restart_syscall; + regs->pc -= 4; + break; + } + } + + /* No signal to deliver -- put the saved sigmask back */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } + + return 0; +} /* * Atomically swap in the new signal mask, and wait for a signal. @@ -643,14 +721,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, switch (regs->regs[REG_RET]) { case -ERESTART_RESTARTBLOCK: case -ERESTARTNOHAND: + no_system_call_restart: regs->regs[REG_RET] = -EINTR; break; case -ERESTARTSYS: - if (!(ka->sa.sa_flags & SA_RESTART)) { - regs->regs[REG_RET] = -EINTR; - break; - } + if (!(ka->sa.sa_flags & SA_RESTART)) + goto no_system_call_restart; /* fallthrough */ case -ERESTARTNOINTR: /* Decode syscall # */ @@ -673,80 +750,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, spin_unlock_irq(¤t->sighand->siglock); } -/* - * Note that 'init' is a special process: it doesn't get signals it doesn't - * want to handle. Thus you cannot kill init even with a SIGKILL even by - * mistake. - * - * Note that we go through the signals twice: once to check the signals that - * the kernel can handle, and then we build all the user-level signal handling - * stack-frames in one go after that. - */ -int do_signal(struct pt_regs *regs, sigset_t *oldset) +asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags) { - siginfo_t info; - int signr; - struct k_sigaction ka; - - /* - * We want the common case to go fast, which - * is why we may in certain cases get here from - * kernel mode. Just return without doing anything - * if so. - */ - if (!user_mode(regs)) - return 1; - - if (try_to_freeze()) - goto no_signal; - - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else if (!oldset) - oldset = ¤t->blocked; - - signr = get_signal_to_deliver(&info, &ka, regs, 0); - - if (signr > 0) { - /* Whee! Actually deliver the signal. */ - handle_signal(signr, &info, &ka, oldset, regs); + if (thread_info_flags & _TIF_SIGPENDING) + do_signal(regs, 0); - /* - * If a signal was successfully delivered, the saved sigmask - * is in its frame, and we can clear the TIF_RESTORE_SIGMASK - * flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - - return 1; + if (thread_info_flags & _TIF_NOTIFY_RESUME) { + clear_thread_flag(TIF_NOTIFY_RESUME); + tracehook_notify_resume(regs); } - -no_signal: - /* Did we come from a system call? */ - if (regs->syscall_nr >= 0) { - /* Restart the system call - no handlers present */ - switch (regs->regs[REG_RET]) { - case -ERESTARTNOHAND: - case -ERESTARTSYS: - case -ERESTARTNOINTR: - /* Decode Syscall # */ - regs->regs[REG_RET] = regs->syscall_nr; - regs->pc -= 4; - break; - - case -ERESTART_RESTARTBLOCK: - regs->regs[REG_RET] = __NR_restart_syscall; - regs->pc -= 4; - break; - } - } - - /* No signal to deliver -- put the saved sigmask back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); - } - - return 0; } -- cgit v1.2.3 From 9e5e21170e4de269cd5b9d53ac9d60d220e3be63 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Wed, 30 Jul 2008 20:05:35 +0900 Subject: sh: Fix up the audit arch endian specification. Presently this was always being set to AUDIT_ARCH_SH, which assumes big endian. Fix this up so that the architecture actually reflects what we're running on. Signed-off-by: Paul Mundt --- arch/sh/kernel/ptrace_32.c | 13 ++++++++++++- arch/sh/kernel/ptrace_64.c | 16 +++++++++++++++- 2 files changed, 27 insertions(+), 2 deletions(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index f48769b23bd6..035cb300d3dc 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c @@ -217,6 +217,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return ret; } +static inline int audit_arch(void) +{ + int arch = EM_SH; + +#ifdef CONFIG_CPU_LITTLE_ENDIAN + arch |= __AUDIT_ARCH_LE; +#endif + + return arch; +} + asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) { long ret = 0; @@ -233,7 +244,7 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) ret = -1L; if (unlikely(current->audit_context)) - audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[3], + audit_syscall_entry(audit_arch(), regs->regs[3], regs->regs[4], regs->regs[5], regs->regs[6], regs->regs[7]); diff --git a/arch/sh/kernel/ptrace_64.c b/arch/sh/kernel/ptrace_64.c index 236d8bef9ccd..5922edd416db 100644 --- a/arch/sh/kernel/ptrace_64.c +++ b/arch/sh/kernel/ptrace_64.c @@ -222,6 +222,20 @@ asmlinkage int sh64_ptrace(long request, long pid, long addr, long data) return sys_ptrace(request, pid, addr, data); } +static inline int audit_arch(void) +{ + int arch = EM_SH; + +#ifdef CONFIG_64BIT + arch |= __AUDIT_ARCH_64BIT; +#endif +#ifdef CONFIG_CPU_LITTLE_ENDIAN + arch |= __AUDIT_ARCH_LE; +#endif + + return arch; +} + asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs) { long long ret = 0; @@ -238,7 +252,7 @@ asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs) ret = -1LL; if (unlikely(current->audit_context)) - audit_syscall_entry(AUDIT_ARCH_SH, regs->regs[1], + audit_syscall_entry(audit_arch(), regs->regs[1], regs->regs[2], regs->regs[3], regs->regs[4], regs->regs[5]); -- cgit v1.2.3 From 6a9545bd95e88d61df942b9087cb59b8c7a6dc56 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 4 Aug 2008 12:51:06 +0900 Subject: sh: Fix up broken kerneldoc comments. These were completely unparseable, so fix them up. Signed-off-by: Paul Mundt --- arch/sh/kernel/cpu/sh4/sq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c index dcdf959a3d44..8a8a993f55ea 100644 --- a/arch/sh/kernel/cpu/sh4/sq.c +++ b/arch/sh/kernel/cpu/sh4/sq.c @@ -199,7 +199,7 @@ EXPORT_SYMBOL(sq_remap); /** * sq_unmap - Unmap a Store Queue allocation - * @map: Pre-allocated Store Queue mapping. + * @vaddr: Pre-allocated Store Queue mapping. * * Unmaps the store queue allocation @map that was previously created by * sq_remap(). Also frees up the pte that was previously inserted into -- cgit v1.2.3 From 3108cf061228c2c2951006c80fb6fe832000adda Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 4 Aug 2008 13:32:04 +0900 Subject: sh: Fix up __bug_table handling in module loader. We should be calling in to the lib/bug.c module helpers, fix that up. Signed-off-by: Paul Mundt --- arch/sh/kernel/module.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index 5482e65375a9..6ba2b79b826b 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -145,9 +146,10 @@ int module_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs, struct module *me) { - return 0; + return module_bug_finalize(hdr, sechdrs, me); } void module_arch_cleanup(struct module *mod) { + module_bug_cleanup(mod); } -- cgit v1.2.3 From 4b59c97325371d51275bdb50523fa98a301615b0 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 4 Aug 2008 13:34:29 +0900 Subject: sh: module_alloc() should be using vmalloc_exec(). SH-X2 extended mode TLB allows for toggling of the exec bit, so make sure we are using the right protection bits for module space there also. Signed-off-by: Paul Mundt --- arch/sh/kernel/module.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index 6ba2b79b826b..c43081039dd5 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c @@ -37,7 +37,8 @@ void *module_alloc(unsigned long size) { if (size == 0) return NULL; - return vmalloc(size); + + return vmalloc_exec(size); } -- cgit v1.2.3 From c3b4adfa65bae300a143188491e285556ca80fff Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 4 Aug 2008 13:42:49 +0900 Subject: sh: Save NUMA node data in vmcore for crash dumps. Presently the NUMA node data isn't saved on kexec. This implements a simple arch_crash_save_vmcoreinfo() for saving off the relevant data. Signed-off-by: Paul Mundt --- arch/sh/kernel/machine_kexec.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/sh/kernel') diff --git a/arch/sh/kernel/machine_kexec.c b/arch/sh/kernel/machine_kexec.c index ec1eadce4aaa..4703dff174d5 100644 --- a/arch/sh/kernel/machine_kexec.c +++ b/arch/sh/kernel/machine_kexec.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -104,3 +105,10 @@ void machine_kexec(struct kimage *image) (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg); } +void arch_crash_save_vmcoreinfo(void) +{ +#ifdef CONFIG_NUMA + VMCOREINFO_SYMBOL(node_data); + VMCOREINFO_LENGTH(node_data, MAX_NUMNODES); +#endif +} -- cgit v1.2.3