Root/
1 | /* |
2 | * Copyright (C) 2004-2006 Atmel Corporation |
3 | * |
4 | * Based on linux/arch/sh/kernel/signal.c |
5 | * Copyright (C) 1999, 2000 Niibe Yutaka & Kaz Kojima |
6 | * Copyright (C) 1991, 1992 Linus Torvalds |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as |
10 | * published by the Free Software Foundation. |
11 | */ |
12 | |
13 | #include <linux/sched.h> |
14 | #include <linux/mm.h> |
15 | #include <linux/errno.h> |
16 | #include <linux/ptrace.h> |
17 | #include <linux/unistd.h> |
18 | #include <linux/tracehook.h> |
19 | |
20 | #include <asm/uaccess.h> |
21 | #include <asm/ucontext.h> |
22 | #include <asm/syscalls.h> |
23 | |
24 | struct rt_sigframe |
25 | { |
26 | struct siginfo info; |
27 | struct ucontext uc; |
28 | unsigned long retcode; |
29 | }; |
30 | |
31 | static int |
32 | restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc) |
33 | { |
34 | int err = 0; |
35 | |
36 | #define COPY(x) err |= __get_user(regs->x, &sc->x) |
37 | COPY(sr); |
38 | COPY(pc); |
39 | COPY(lr); |
40 | COPY(sp); |
41 | COPY(r12); |
42 | COPY(r11); |
43 | COPY(r10); |
44 | COPY(r9); |
45 | COPY(r8); |
46 | COPY(r7); |
47 | COPY(r6); |
48 | COPY(r5); |
49 | COPY(r4); |
50 | COPY(r3); |
51 | COPY(r2); |
52 | COPY(r1); |
53 | COPY(r0); |
54 | #undef COPY |
55 | |
56 | /* |
57 | * Don't allow anyone to pretend they're running in supervisor |
58 | * mode or something... |
59 | */ |
60 | err |= !valid_user_regs(regs); |
61 | |
62 | return err; |
63 | } |
64 | |
65 | |
66 | asmlinkage int sys_rt_sigreturn(struct pt_regs *regs) |
67 | { |
68 | struct rt_sigframe __user *frame; |
69 | sigset_t set; |
70 | |
71 | /* Always make any pending restarted system calls return -EINTR */ |
72 | current_thread_info()->restart_block.fn = do_no_restart_syscall; |
73 | |
74 | frame = (struct rt_sigframe __user *)regs->sp; |
75 | pr_debug("SIG return: frame = %p\n", frame); |
76 | |
77 | if (!access_ok(VERIFY_READ, frame, sizeof(*frame))) |
78 | goto badframe; |
79 | |
80 | if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set))) |
81 | goto badframe; |
82 | |
83 | set_current_blocked(&set); |
84 | |
85 | if (restore_sigcontext(regs, &frame->uc.uc_mcontext)) |
86 | goto badframe; |
87 | |
88 | if (restore_altstack(&frame->uc.uc_stack)) |
89 | goto badframe; |
90 | |
91 | pr_debug("Context restored: pc = %08lx, lr = %08lx, sp = %08lx\n", |
92 | regs->pc, regs->lr, regs->sp); |
93 | |
94 | return regs->r12; |
95 | |
96 | badframe: |
97 | force_sig(SIGSEGV, current); |
98 | return 0; |
99 | } |
100 | |
101 | static int |
102 | setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs) |
103 | { |
104 | int err = 0; |
105 | |
106 | #define COPY(x) err |= __put_user(regs->x, &sc->x) |
107 | COPY(sr); |
108 | COPY(pc); |
109 | COPY(lr); |
110 | COPY(sp); |
111 | COPY(r12); |
112 | COPY(r11); |
113 | COPY(r10); |
114 | COPY(r9); |
115 | COPY(r8); |
116 | COPY(r7); |
117 | COPY(r6); |
118 | COPY(r5); |
119 | COPY(r4); |
120 | COPY(r3); |
121 | COPY(r2); |
122 | COPY(r1); |
123 | COPY(r0); |
124 | #undef COPY |
125 | |
126 | return err; |
127 | } |
128 | |
129 | static inline void __user * |
130 | get_sigframe(struct ksignal *ksig, struct pt_regs *regs, int framesize) |
131 | { |
132 | unsigned long sp = sigsp(regs->sp, ksig); |
133 | |
134 | return (void __user *)((sp - framesize) & ~3); |
135 | } |
136 | |
137 | static int |
138 | setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs) |
139 | { |
140 | struct rt_sigframe __user *frame; |
141 | int err = 0; |
142 | |
143 | frame = get_sigframe(ksig, regs, sizeof(*frame)); |
144 | err = -EFAULT; |
145 | if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame))) |
146 | goto out; |
147 | |
148 | /* |
149 | * Set up the return code: |
150 | * |
151 | * mov r8, __NR_rt_sigreturn |
152 | * scall |
153 | * |
154 | * Note: This will blow up since we're using a non-executable |
155 | * stack. Better use SA_RESTORER. |
156 | */ |
157 | #if __NR_rt_sigreturn > 127 |
158 | # error __NR_rt_sigreturn must be < 127 to fit in a short mov |
159 | #endif |
160 | err = __put_user(0x3008d733 | (__NR_rt_sigreturn << 20), |
161 | &frame->retcode); |
162 | |
163 | err |= copy_siginfo_to_user(&frame->info, &ksig->info); |
164 | |
165 | /* Set up the ucontext */ |
166 | err |= __put_user(0, &frame->uc.uc_flags); |
167 | err |= __put_user(NULL, &frame->uc.uc_link); |
168 | err |= __save_altstack(&frame->uc.uc_stack, regs->sp); |
169 | err |= setup_sigcontext(&frame->uc.uc_mcontext, regs); |
170 | err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); |
171 | |
172 | if (err) |
173 | goto out; |
174 | |
175 | regs->r12 = ksig->sig; |
176 | regs->r11 = (unsigned long) &frame->info; |
177 | regs->r10 = (unsigned long) &frame->uc; |
178 | regs->sp = (unsigned long) frame; |
179 | if (ksig->ka.sa.sa_flags & SA_RESTORER) |
180 | regs->lr = (unsigned long)ksig->ka.sa.sa_restorer; |
181 | else { |
182 | printk(KERN_NOTICE "[%s:%d] did not set SA_RESTORER\n", |
183 | current->comm, current->pid); |
184 | regs->lr = (unsigned long) &frame->retcode; |
185 | } |
186 | |
187 | pr_debug("SIG deliver [%s:%d]: sig=%d sp=0x%lx pc=0x%lx->0x%p lr=0x%lx\n", |
188 | current->comm, current->pid, ksig->sig, regs->sp, |
189 | regs->pc, ksig->ka.sa.sa_handler, regs->lr); |
190 | |
191 | regs->pc = (unsigned long)ksig->ka.sa.sa_handler; |
192 | |
193 | out: |
194 | return err; |
195 | } |
196 | |
197 | static inline void setup_syscall_restart(struct pt_regs *regs) |
198 | { |
199 | if (regs->r12 == -ERESTART_RESTARTBLOCK) |
200 | regs->r8 = __NR_restart_syscall; |
201 | else |
202 | regs->r12 = regs->r12_orig; |
203 | regs->pc -= 2; |
204 | } |
205 | |
206 | static inline void |
207 | handle_signal(struct ksignal *ksig, struct pt_regs *regs, int syscall) |
208 | { |
209 | int ret; |
210 | |
211 | /* |
212 | * Set up the stack frame |
213 | */ |
214 | ret = setup_rt_frame(ksig, sigmask_to_save(), regs); |
215 | |
216 | /* |
217 | * Check that the resulting registers are sane |
218 | */ |
219 | ret |= !valid_user_regs(regs); |
220 | |
221 | /* |
222 | * Block the signal if we were successful. |
223 | */ |
224 | signal_setup_done(ret, ksig, 0); |
225 | } |
226 | |
227 | /* |
228 | * Note that 'init' is a special process: it doesn't get signals it |
229 | * doesn't want to handle. Thus you cannot kill init even with a |
230 | * SIGKILL even by mistake. |
231 | */ |
232 | static void do_signal(struct pt_regs *regs, int syscall) |
233 | { |
234 | struct ksignal ksig; |
235 | |
236 | /* |
237 | * We want the common case to go fast, which is why we may in |
238 | * certain cases get here from kernel mode. Just return |
239 | * without doing anything if so. |
240 | */ |
241 | if (!user_mode(regs)) |
242 | return; |
243 | |
244 | get_signal(&ksig); |
245 | if (syscall) { |
246 | switch (regs->r12) { |
247 | case -ERESTART_RESTARTBLOCK: |
248 | case -ERESTARTNOHAND: |
249 | if (ksig.sig > 0) { |
250 | regs->r12 = -EINTR; |
251 | break; |
252 | } |
253 | /* fall through */ |
254 | case -ERESTARTSYS: |
255 | if (ksig.sig > 0 && !(ksig.ka.sa.sa_flags & SA_RESTART)) { |
256 | regs->r12 = -EINTR; |
257 | break; |
258 | } |
259 | /* fall through */ |
260 | case -ERESTARTNOINTR: |
261 | setup_syscall_restart(regs); |
262 | } |
263 | } |
264 | |
265 | if (!ksig.sig) { |
266 | /* No signal to deliver -- put the saved sigmask back */ |
267 | restore_saved_sigmask(); |
268 | return; |
269 | } |
270 | |
271 | handle_signal(&ksig, regs, syscall); |
272 | } |
273 | |
274 | asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti) |
275 | { |
276 | int syscall = 0; |
277 | |
278 | if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR) |
279 | syscall = 1; |
280 | |
281 | if (ti->flags & _TIF_SIGPENDING) |
282 | do_signal(regs, syscall); |
283 | |
284 | if (ti->flags & _TIF_NOTIFY_RESUME) { |
285 | clear_thread_flag(TIF_NOTIFY_RESUME); |
286 | tracehook_notify_resume(regs); |
287 | } |
288 | } |
289 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9