Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/microblaze/kernel/signal.c
10817 views
1
/*
2
* Signal handling
3
*
4
* Copyright (C) 2008-2009 Michal Simek <[email protected]>
5
* Copyright (C) 2008-2009 PetaLogix
6
* Copyright (C) 2003,2004 John Williams <[email protected]>
7
* Copyright (C) 2001 NEC Corporation
8
* Copyright (C) 2001 Miles Bader <[email protected]>
9
* Copyright (C) 1999,2000 Niibe Yutaka & Kaz Kojima
10
* Copyright (C) 1991,1992 Linus Torvalds
11
*
12
* 1997-11-28 Modified for POSIX.1b signals by Richard Henderson
13
*
14
* This file was was derived from the sh version, arch/sh/kernel/signal.c
15
*
16
* This file is subject to the terms and conditions of the GNU General
17
* Public License. See the file COPYING in the main directory of this
18
* archive for more details.
19
*/
20
21
#include <linux/sched.h>
22
#include <linux/mm.h>
23
#include <linux/smp.h>
24
#include <linux/kernel.h>
25
#include <linux/signal.h>
26
#include <linux/errno.h>
27
#include <linux/wait.h>
28
#include <linux/ptrace.h>
29
#include <linux/unistd.h>
30
#include <linux/stddef.h>
31
#include <linux/personality.h>
32
#include <linux/percpu.h>
33
#include <linux/linkage.h>
34
#include <asm/entry.h>
35
#include <asm/ucontext.h>
36
#include <linux/uaccess.h>
37
#include <asm/pgtable.h>
38
#include <asm/pgalloc.h>
39
#include <linux/syscalls.h>
40
#include <asm/cacheflush.h>
41
#include <asm/syscalls.h>
42
43
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
44
45
asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_sycall);
46
47
asmlinkage long
48
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
49
struct pt_regs *regs)
50
{
51
return do_sigaltstack(uss, uoss, regs->r1);
52
}
53
54
/*
55
* Do a signal return; undo the signal stack.
56
*/
57
struct sigframe {
58
struct sigcontext sc;
59
unsigned long extramask[_NSIG_WORDS-1];
60
unsigned long tramp[2]; /* signal trampoline */
61
};
62
63
struct rt_sigframe {
64
struct siginfo info;
65
struct ucontext uc;
66
unsigned long tramp[2]; /* signal trampoline */
67
};
68
69
static int restore_sigcontext(struct pt_regs *regs,
70
struct sigcontext __user *sc, int *rval_p)
71
{
72
unsigned int err = 0;
73
74
#define COPY(x) {err |= __get_user(regs->x, &sc->regs.x); }
75
COPY(r0);
76
COPY(r1);
77
COPY(r2); COPY(r3); COPY(r4); COPY(r5);
78
COPY(r6); COPY(r7); COPY(r8); COPY(r9);
79
COPY(r10); COPY(r11); COPY(r12); COPY(r13);
80
COPY(r14); COPY(r15); COPY(r16); COPY(r17);
81
COPY(r18); COPY(r19); COPY(r20); COPY(r21);
82
COPY(r22); COPY(r23); COPY(r24); COPY(r25);
83
COPY(r26); COPY(r27); COPY(r28); COPY(r29);
84
COPY(r30); COPY(r31);
85
COPY(pc); COPY(ear); COPY(esr); COPY(fsr);
86
#undef COPY
87
88
*rval_p = regs->r3;
89
90
return err;
91
}
92
93
asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
94
{
95
struct rt_sigframe __user *frame =
96
(struct rt_sigframe __user *)(regs->r1);
97
98
sigset_t set;
99
int rval;
100
101
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
102
goto badframe;
103
104
if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
105
goto badframe;
106
107
sigdelsetmask(&set, ~_BLOCKABLE);
108
spin_lock_irq(&current->sighand->siglock);
109
current->blocked = set;
110
recalc_sigpending();
111
spin_unlock_irq(&current->sighand->siglock);
112
113
if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
114
goto badframe;
115
116
/* It is more difficult to avoid calling this function than to
117
call it and ignore errors. */
118
if (do_sigaltstack(&frame->uc.uc_stack, NULL, regs->r1))
119
goto badframe;
120
121
return rval;
122
123
badframe:
124
force_sig(SIGSEGV, current);
125
return 0;
126
}
127
128
/*
129
* Set up a signal frame.
130
*/
131
132
static int
133
setup_sigcontext(struct sigcontext __user *sc, struct pt_regs *regs,
134
unsigned long mask)
135
{
136
int err = 0;
137
138
#define COPY(x) {err |= __put_user(regs->x, &sc->regs.x); }
139
COPY(r0);
140
COPY(r1);
141
COPY(r2); COPY(r3); COPY(r4); COPY(r5);
142
COPY(r6); COPY(r7); COPY(r8); COPY(r9);
143
COPY(r10); COPY(r11); COPY(r12); COPY(r13);
144
COPY(r14); COPY(r15); COPY(r16); COPY(r17);
145
COPY(r18); COPY(r19); COPY(r20); COPY(r21);
146
COPY(r22); COPY(r23); COPY(r24); COPY(r25);
147
COPY(r26); COPY(r27); COPY(r28); COPY(r29);
148
COPY(r30); COPY(r31);
149
COPY(pc); COPY(ear); COPY(esr); COPY(fsr);
150
#undef COPY
151
152
err |= __put_user(mask, &sc->oldmask);
153
154
return err;
155
}
156
157
/*
158
* Determine which stack to use..
159
*/
160
static inline void __user *
161
get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
162
{
163
/* Default to using normal stack */
164
unsigned long sp = regs->r1;
165
166
if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && !on_sig_stack(sp))
167
sp = current->sas_ss_sp + current->sas_ss_size;
168
169
return (void __user *)((sp - frame_size) & -8UL);
170
}
171
172
static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
173
sigset_t *set, struct pt_regs *regs)
174
{
175
struct rt_sigframe __user *frame;
176
int err = 0;
177
int signal;
178
unsigned long address = 0;
179
#ifdef CONFIG_MMU
180
pmd_t *pmdp;
181
pte_t *ptep;
182
#endif
183
184
frame = get_sigframe(ka, regs, sizeof(*frame));
185
186
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
187
goto give_sigsegv;
188
189
signal = current_thread_info()->exec_domain
190
&& current_thread_info()->exec_domain->signal_invmap
191
&& sig < 32
192
? current_thread_info()->exec_domain->signal_invmap[sig]
193
: sig;
194
195
if (info)
196
err |= copy_siginfo_to_user(&frame->info, info);
197
198
/* Create the ucontext. */
199
err |= __put_user(0, &frame->uc.uc_flags);
200
err |= __put_user(NULL, &frame->uc.uc_link);
201
err |= __put_user((void __user *)current->sas_ss_sp,
202
&frame->uc.uc_stack.ss_sp);
203
err |= __put_user(sas_ss_flags(regs->r1),
204
&frame->uc.uc_stack.ss_flags);
205
err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
206
err |= setup_sigcontext(&frame->uc.uc_mcontext,
207
regs, set->sig[0]);
208
err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
209
210
/* Set up to return from userspace. If provided, use a stub
211
already in userspace. */
212
/* minus 8 is offset to cater for "rtsd r15,8" */
213
/* addi r12, r0, __NR_sigreturn */
214
err |= __put_user(0x31800000 | __NR_rt_sigreturn ,
215
frame->tramp + 0);
216
/* brki r14, 0x8 */
217
err |= __put_user(0xb9cc0008, frame->tramp + 1);
218
219
/* Return from sighandler will jump to the tramp.
220
Negative 8 offset because return is rtsd r15, 8 */
221
regs->r15 = ((unsigned long)frame->tramp)-8;
222
223
address = ((unsigned long)frame->tramp);
224
#ifdef CONFIG_MMU
225
pmdp = pmd_offset(pud_offset(
226
pgd_offset(current->mm, address),
227
address), address);
228
229
preempt_disable();
230
ptep = pte_offset_map(pmdp, address);
231
if (pte_present(*ptep)) {
232
address = (unsigned long) page_address(pte_page(*ptep));
233
/* MS: I need add offset in page */
234
address += ((unsigned long)frame->tramp) & ~PAGE_MASK;
235
/* MS address is virtual */
236
address = virt_to_phys(address);
237
invalidate_icache_range(address, address + 8);
238
flush_dcache_range(address, address + 8);
239
}
240
pte_unmap(ptep);
241
preempt_enable();
242
#else
243
flush_icache_range(address, address + 8);
244
flush_dcache_range(address, address + 8);
245
#endif
246
if (err)
247
goto give_sigsegv;
248
249
/* Set up registers for signal handler */
250
regs->r1 = (unsigned long) frame;
251
252
/* Signal handler args: */
253
regs->r5 = signal; /* arg 0: signum */
254
regs->r6 = (unsigned long) &frame->info; /* arg 1: siginfo */
255
regs->r7 = (unsigned long) &frame->uc; /* arg2: ucontext */
256
/* Offset to handle microblaze rtid r14, 0 */
257
regs->pc = (unsigned long)ka->sa.sa_handler;
258
259
set_fs(USER_DS);
260
261
/* the tracer may want to single-step inside the handler */
262
if (test_thread_flag(TIF_SINGLESTEP))
263
ptrace_notify(SIGTRAP);
264
265
#ifdef DEBUG_SIG
266
printk(KERN_INFO "SIG deliver (%s:%d): sp=%p pc=%08lx\n",
267
current->comm, current->pid, frame, regs->pc);
268
#endif
269
270
return;
271
272
give_sigsegv:
273
if (sig == SIGSEGV)
274
ka->sa.sa_handler = SIG_DFL;
275
force_sig(SIGSEGV, current);
276
}
277
278
/* Handle restarting system calls */
279
static inline void
280
handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
281
{
282
switch (regs->r3) {
283
case -ERESTART_RESTARTBLOCK:
284
case -ERESTARTNOHAND:
285
if (!has_handler)
286
goto do_restart;
287
regs->r3 = -EINTR;
288
break;
289
case -ERESTARTSYS:
290
if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
291
regs->r3 = -EINTR;
292
break;
293
}
294
/* fallthrough */
295
case -ERESTARTNOINTR:
296
do_restart:
297
/* offset of 4 bytes to re-execute trap (brki) instruction */
298
#ifndef CONFIG_MMU
299
regs->pc -= 4;
300
#else
301
/* offset of 8 bytes required = 4 for rtbd
302
offset, plus 4 for size of
303
"brki r14,8"
304
instruction. */
305
regs->pc -= 8;
306
#endif
307
break;
308
}
309
}
310
311
/*
312
* OK, we're invoking a handler
313
*/
314
315
static int
316
handle_signal(unsigned long sig, struct k_sigaction *ka,
317
siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
318
{
319
/* Set up the stack frame */
320
if (ka->sa.sa_flags & SA_SIGINFO)
321
setup_rt_frame(sig, ka, info, oldset, regs);
322
else
323
setup_rt_frame(sig, ka, NULL, oldset, regs);
324
325
if (ka->sa.sa_flags & SA_ONESHOT)
326
ka->sa.sa_handler = SIG_DFL;
327
328
if (!(ka->sa.sa_flags & SA_NODEFER)) {
329
spin_lock_irq(&current->sighand->siglock);
330
sigorsets(&current->blocked,
331
&current->blocked, &ka->sa.sa_mask);
332
sigaddset(&current->blocked, sig);
333
recalc_sigpending();
334
spin_unlock_irq(&current->sighand->siglock);
335
}
336
return 1;
337
}
338
339
/*
340
* Note that 'init' is a special process: it doesn't get signals it doesn't
341
* want to handle. Thus you cannot kill init even with a SIGKILL even by
342
* mistake.
343
*
344
* Note that we go through the signals twice: once to check the signals that
345
* the kernel can handle, and then we build all the user-level signal handling
346
* stack-frames in one go after that.
347
*/
348
int do_signal(struct pt_regs *regs, sigset_t *oldset, int in_syscall)
349
{
350
siginfo_t info;
351
int signr;
352
struct k_sigaction ka;
353
#ifdef DEBUG_SIG
354
printk(KERN_INFO "do signal: %p %p %d\n", regs, oldset, in_syscall);
355
printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
356
regs->r12, current_thread_info()->flags);
357
#endif
358
/*
359
* We want the common case to go fast, which
360
* is why we may in certain cases get here from
361
* kernel mode. Just return without doing anything
362
* if so.
363
*/
364
if (kernel_mode(regs))
365
return 1;
366
367
if (current_thread_info()->status & TS_RESTORE_SIGMASK)
368
oldset = &current->saved_sigmask;
369
else
370
oldset = &current->blocked;
371
372
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
373
if (signr > 0) {
374
/* Whee! Actually deliver the signal. */
375
if (in_syscall)
376
handle_restart(regs, &ka, 1);
377
if (handle_signal(signr, &ka, &info, oldset, regs)) {
378
/*
379
* A signal was successfully delivered; the saved
380
* sigmask will have been stored in the signal frame,
381
* and will be restored by sigreturn, so we can simply
382
* clear the TS_RESTORE_SIGMASK flag.
383
*/
384
current_thread_info()->status &=
385
~TS_RESTORE_SIGMASK;
386
}
387
return 1;
388
}
389
390
if (in_syscall)
391
handle_restart(regs, NULL, 0);
392
393
/*
394
* If there's no signal to deliver, we just put the saved sigmask
395
* back.
396
*/
397
if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
398
current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
399
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
400
}
401
402
/* Did we come from a system call? */
403
return 0;
404
}
405
406