aboutsummaryrefslogtreecommitdiffstats
path: root/arch/openrisc/kernel/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/openrisc/kernel/signal.c')
-rw-r--r--arch/openrisc/kernel/signal.c233
1 files changed, 116 insertions, 117 deletions
diff --git a/arch/openrisc/kernel/signal.c b/arch/openrisc/kernel/signal.c
index ae167f7e081a..66775bc07a8e 100644
--- a/arch/openrisc/kernel/signal.c
+++ b/arch/openrisc/kernel/signal.c
@@ -28,24 +28,24 @@
28#include <linux/tracehook.h> 28#include <linux/tracehook.h>
29 29
30#include <asm/processor.h> 30#include <asm/processor.h>
31#include <asm/syscall.h>
31#include <asm/ucontext.h> 32#include <asm/ucontext.h>
32#include <asm/uaccess.h> 33#include <asm/uaccess.h>
33 34
34#define DEBUG_SIG 0 35#define DEBUG_SIG 0
35 36
36struct rt_sigframe { 37struct rt_sigframe {
37 struct siginfo *pinfo;
38 void *puc;
39 struct siginfo info; 38 struct siginfo info;
40 struct ucontext uc; 39 struct ucontext uc;
41 unsigned char retcode[16]; /* trampoline code */ 40 unsigned char retcode[16]; /* trampoline code */
42}; 41};
43 42
44static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc) 43static int restore_sigcontext(struct pt_regs *regs,
44 struct sigcontext __user *sc)
45{ 45{
46 unsigned int err = 0; 46 int err = 0;
47 47
48 /* Alwys make any pending restarted system call return -EINTR */ 48 /* Always make any pending restarted system calls return -EINTR */
49 current_thread_info()->restart_block.fn = do_no_restart_syscall; 49 current_thread_info()->restart_block.fn = do_no_restart_syscall;
50 50
51 /* 51 /*
@@ -53,25 +53,21 @@ static int restore_sigcontext(struct pt_regs *regs, struct sigcontext *sc)
53 * (sc is already checked for VERIFY_READ since the sigframe was 53 * (sc is already checked for VERIFY_READ since the sigframe was
54 * checked in sys_sigreturn previously) 54 * checked in sys_sigreturn previously)
55 */ 55 */
56 if (__copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long))) 56 err |= __copy_from_user(regs, sc->regs.gpr, 32 * sizeof(unsigned long));
57 goto badframe; 57 err |= __copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long));
58 if (__copy_from_user(&regs->pc, &sc->regs.pc, sizeof(unsigned long))) 58 err |= __copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long));
59 goto badframe;
60 if (__copy_from_user(&regs->sr, &sc->regs.sr, sizeof(unsigned long)))
61 goto badframe;
62 59
63 /* make sure the SM-bit is cleared so user-mode cannot fool us */ 60 /* make sure the SM-bit is cleared so user-mode cannot fool us */
64 regs->sr &= ~SPR_SR_SM; 61 regs->sr &= ~SPR_SR_SM;
65 62
63 regs->orig_gpr11 = -1; /* Avoid syscall restart checks */
64
66 /* TODO: the other ports use regs->orig_XX to disable syscall checks 65 /* TODO: the other ports use regs->orig_XX to disable syscall checks
67 * after this completes, but we don't use that mechanism. maybe we can 66 * after this completes, but we don't use that mechanism. maybe we can
68 * use it now ? 67 * use it now ?
69 */ 68 */
70 69
71 return err; 70 return err;
72
73badframe:
74 return 1;
75} 71}
76 72
77asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs) 73asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
@@ -111,21 +107,18 @@ badframe:
111 * Set up a signal frame. 107 * Set up a signal frame.
112 */ 108 */
113 109
114static int setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs, 110static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
115 unsigned long mask)
116{ 111{
117 int err = 0; 112 int err = 0;
118 113
119 /* copy the regs */ 114 /* copy the regs */
120 115 /* There should be no need to save callee-saved registers here...
116 * ...but we save them anyway. Revisit this
117 */
121 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long)); 118 err |= __copy_to_user(sc->regs.gpr, regs, 32 * sizeof(unsigned long));
122 err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long)); 119 err |= __copy_to_user(&sc->regs.pc, &regs->pc, sizeof(unsigned long));
123 err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long)); 120 err |= __copy_to_user(&sc->regs.sr, &regs->sr, sizeof(unsigned long));
124 121
125 /* then some other stuff */
126
127 err |= __put_user(mask, &sc->oldmask);
128
129 return err; 122 return err;
130} 123}
131 124
@@ -173,55 +166,53 @@ static inline void __user *get_sigframe(struct k_sigaction *ka,
173 * trampoline which performs the syscall sigreturn, or a provided 166 * trampoline which performs the syscall sigreturn, or a provided
174 * user-mode trampoline. 167 * user-mode trampoline.
175 */ 168 */
176static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, 169static int setup_rt_frame(struct ksignal *ksig, sigset_t *set,
177 sigset_t *set, struct pt_regs *regs) 170 struct pt_regs *regs)
178{ 171{
179 struct rt_sigframe *frame; 172 struct rt_sigframe *frame;
180 unsigned long return_ip; 173 unsigned long return_ip;
181 int err = 0; 174 int err = 0;
182 175
183 frame = get_sigframe(ka, regs, sizeof(*frame)); 176 frame = get_sigframe(&ksig->ka, regs, sizeof(*frame));
184 177
185 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame))) 178 if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
186 goto give_sigsegv; 179 return -EFAULT;
187 180
188 err |= __put_user(&frame->info, &frame->pinfo); 181 /* Create siginfo. */
189 err |= __put_user(&frame->uc, &frame->puc); 182 if (ksig->ka.sa.sa_flags & SA_SIGINFO)
183 err |= copy_siginfo_to_user(&frame->info, &ksig->info);
190 184
191 if (ka->sa.sa_flags & SA_SIGINFO) 185 /* Create the ucontext. */
192 err |= copy_siginfo_to_user(&frame->info, info);
193 if (err)
194 goto give_sigsegv;
195
196 /* Clear all the bits of the ucontext we don't use. */
197 err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));
198 err |= __put_user(0, &frame->uc.uc_flags); 186 err |= __put_user(0, &frame->uc.uc_flags);
199 err |= __put_user(NULL, &frame->uc.uc_link); 187 err |= __put_user(NULL, &frame->uc.uc_link);
200 err |= __save_altstack(&frame->uc.uc_stack, regs->sp); 188 err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
201 err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, set->sig[0]); 189 err |= setup_sigcontext(regs, &frame->uc.uc_mcontext);
202 190
203 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set)); 191 err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
204 192
205 if (err) 193 if (err)
206 goto give_sigsegv; 194 return -EFAULT;
207 195
208 /* trampoline - the desired return ip is the retcode itself */ 196 /* trampoline - the desired return ip is the retcode itself */
209 return_ip = (unsigned long)&frame->retcode; 197 return_ip = (unsigned long)&frame->retcode;
210 /* This is l.ori r11,r0,__NR_sigreturn, l.sys 1 */ 198 /* This is:
211 err |= __put_user(0xa960, (short *)(frame->retcode + 0)); 199 l.ori r11,r0,__NR_sigreturn
212 err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2)); 200 l.sys 1
201 */
202 err |= __put_user(0xa960, (short *)(frame->retcode + 0));
203 err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode + 2));
213 err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4)); 204 err |= __put_user(0x20000001, (unsigned long *)(frame->retcode + 4));
214 err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8)); 205 err |= __put_user(0x15000000, (unsigned long *)(frame->retcode + 8));
215 206
216 if (err) 207 if (err)
217 goto give_sigsegv; 208 return -EFAULT;
218 209
219 /* TODO what is the current->exec_domain stuff and invmap ? */ 210 /* TODO what is the current->exec_domain stuff and invmap ? */
220 211
221 /* Set up registers for signal handler */ 212 /* Set up registers for signal handler */
222 regs->pc = (unsigned long)ka->sa.sa_handler; /* what we enter NOW */ 213 regs->pc = (unsigned long)ksig->ka.sa.sa_handler; /* what we enter NOW */
223 regs->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */ 214 regs->gpr[9] = (unsigned long)return_ip; /* what we enter LATER */
224 regs->gpr[3] = (unsigned long)sig; /* arg 1: signo */ 215 regs->gpr[3] = (unsigned long)ksig->sig; /* arg 1: signo */
225 regs->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */ 216 regs->gpr[4] = (unsigned long)&frame->info; /* arg 2: (siginfo_t*) */
226 regs->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */ 217 regs->gpr[5] = (unsigned long)&frame->uc; /* arg 3: ucontext */
227 218
@@ -229,25 +220,16 @@ static int setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
229 regs->sp = (unsigned long)frame; 220 regs->sp = (unsigned long)frame;
230 221
231 return 0; 222 return 0;
232
233give_sigsegv:
234 force_sigsegv(sig, current);
235 return -EFAULT;
236} 223}
237 224
238static inline void 225static inline void
239handle_signal(unsigned long sig, 226handle_signal(struct ksignal *ksig, struct pt_regs *regs)
240 siginfo_t *info, struct k_sigaction *ka,
241 struct pt_regs *regs)
242{ 227{
243 int ret; 228 int ret;
244 229
245 ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs); 230 ret = setup_rt_frame(ksig, sigmask_to_save(), regs);
246 if (ret)
247 return;
248 231
249 signal_delivered(sig, info, ka, regs, 232 signal_setup_done(ret, ksig, test_thread_flag(TIF_SINGLESTEP));
250 test_thread_flag(TIF_SINGLESTEP));
251} 233}
252 234
253/* 235/*
@@ -262,82 +244,99 @@ handle_signal(unsigned long sig,
262 * mode below. 244 * mode below.
263 */ 245 */
264 246
265void do_signal(struct pt_regs *regs) 247int do_signal(struct pt_regs *regs, int syscall)
266{ 248{
267 siginfo_t info; 249 struct ksignal ksig;
268 int signr; 250 unsigned long continue_addr = 0;
269 struct k_sigaction ka; 251 unsigned long restart_addr = 0;
270 252 unsigned long retval = 0;
271 /* 253 int restart = 0;
272 * We want the common case to go fast, which 254
273 * is why we may in certain cases get here from 255 if (syscall) {
274 * kernel mode. Just return without doing anything 256 continue_addr = regs->pc;
275 * if so. 257 restart_addr = continue_addr - 4;
276 */ 258 retval = regs->gpr[11];
277 if (!user_mode(regs)) 259
278 return; 260 /*
279 261 * Setup syscall restart here so that a debugger will
280 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 262 * see the already changed PC.
281 263 */
282 /* If we are coming out of a syscall then we need 264 switch (retval) {
283 * to check if the syscall was interrupted and wants to be
284 * restarted after handling the signal. If so, the original
285 * syscall number is put back into r11 and the PC rewound to
286 * point at the l.sys instruction that resulted in the
287 * original syscall. Syscall results other than the four
288 * below mean that the syscall executed to completion and no
289 * restart is necessary.
290 */
291 if (regs->orig_gpr11) {
292 int restart = 0;
293
294 switch (regs->gpr[11]) {
295 case -ERESTART_RESTARTBLOCK: 265 case -ERESTART_RESTARTBLOCK:
266 restart = -2;
267 /* Fall through */
296 case -ERESTARTNOHAND: 268 case -ERESTARTNOHAND:
297 /* Restart if there is no signal handler */
298 restart = (signr <= 0);
299 break;
300 case -ERESTARTSYS: 269 case -ERESTARTSYS:
301 /* Restart if there no signal handler or
302 * SA_RESTART flag is set */
303 restart = (signr <= 0 || (ka.sa.sa_flags & SA_RESTART));
304 break;
305 case -ERESTARTNOINTR: 270 case -ERESTARTNOINTR:
306 /* Always restart */ 271 restart++;
307 restart = 1; 272 regs->gpr[11] = regs->orig_gpr11;
273 regs->pc = restart_addr;
308 break; 274 break;
309 } 275 }
310
311 if (restart) {
312 if (regs->gpr[11] == -ERESTART_RESTARTBLOCK)
313 regs->gpr[11] = __NR_restart_syscall;
314 else
315 regs->gpr[11] = regs->orig_gpr11;
316 regs->pc -= 4;
317 } else {
318 regs->gpr[11] = -EINTR;
319 }
320 } 276 }
321 277
322 if (signr <= 0) { 278 /*
323 /* no signal to deliver so we just put the saved sigmask 279 * Get the signal to deliver. During the call to get_signal the
324 * back */ 280 * debugger may change all our registers so we may need to revert
281 * the decision to restart the syscall; specifically, if the PC is
282 * changed, don't restart the syscall.
283 */
284 if (get_signal(&ksig)) {
285 if (unlikely(restart) && regs->pc == restart_addr) {
286 if (retval == -ERESTARTNOHAND ||
287 retval == -ERESTART_RESTARTBLOCK
288 || (retval == -ERESTARTSYS
289 && !(ksig.ka.sa.sa_flags & SA_RESTART))) {
290 /* No automatic restart */
291 regs->gpr[11] = -EINTR;
292 regs->pc = continue_addr;
293 }
294 }
295 handle_signal(&ksig, regs);
296 } else {
297 /* no handler */
325 restore_saved_sigmask(); 298 restore_saved_sigmask();
326 } else { /* signr > 0 */ 299 /*
327 /* Whee! Actually deliver the signal. */ 300 * Restore pt_regs PC as syscall restart will be handled by
328 handle_signal(signr, &info, &ka, regs); 301 * kernel without return to userspace
302 */
303 if (unlikely(restart) && regs->pc == restart_addr) {
304 regs->pc = continue_addr;
305 return restart;
306 }
329 } 307 }
330 308
331 return; 309 return 0;
332} 310}
333 311
334asmlinkage void do_notify_resume(struct pt_regs *regs) 312asmlinkage int
313do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
335{ 314{
336 if (current_thread_info()->flags & _TIF_SIGPENDING) 315 do {
337 do_signal(regs); 316 if (likely(thread_flags & _TIF_NEED_RESCHED)) {
338 317 schedule();
339 if (current_thread_info()->flags & _TIF_NOTIFY_RESUME) { 318 } else {
340 clear_thread_flag(TIF_NOTIFY_RESUME); 319 if (unlikely(!user_mode(regs)))
341 tracehook_notify_resume(regs); 320 return 0;
342 } 321 local_irq_enable();
322 if (thread_flags & _TIF_SIGPENDING) {
323 int restart = do_signal(regs, syscall);
324 if (unlikely(restart)) {
325 /*
326 * Restart without handlers.
327 * Deal with it without leaving
328 * the kernel space.
329 */
330 return restart;
331 }
332 syscall = 0;
333 } else {
334 clear_thread_flag(TIF_NOTIFY_RESUME);
335 tracehook_notify_resume(regs);
336 }
337 }
338 local_irq_disable();
339 thread_flags = current_thread_info()->flags;
340 } while (thread_flags & _TIF_WORK_MASK);
341 return 0;
343} 342}