Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/score/kernel/signal.c
10817 views
1
/*
2
* arch/score/kernel/signal.c
3
*
4
* Score Processor version.
5
*
6
* Copyright (C) 2009 Sunplus Core Technology Co., Ltd.
7
* Chen Liqin <[email protected]>
8
* Lennox Wu <[email protected]>
9
*
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
14
*
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
19
*
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, see the file COPYING, or write
22
* to the Free Software Foundation, Inc.,
23
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24
*/
25
26
#include <linux/errno.h>
27
#include <linux/signal.h>
28
#include <linux/ptrace.h>
29
#include <linux/unistd.h>
30
#include <linux/uaccess.h>
31
32
#include <asm/cacheflush.h>
33
#include <asm/syscalls.h>
34
#include <asm/ucontext.h>
35
36
#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
37
38
struct rt_sigframe {
39
u32 rs_ass[4]; /* argument save space */
40
u32 rs_code[2]; /* signal trampoline */
41
struct siginfo rs_info;
42
struct ucontext rs_uc;
43
};
44
45
static int setup_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
46
{
47
int err = 0;
48
unsigned long reg;
49
50
reg = regs->cp0_epc; err |= __put_user(reg, &sc->sc_pc);
51
err |= __put_user(regs->cp0_psr, &sc->sc_psr);
52
err |= __put_user(regs->cp0_condition, &sc->sc_condition);
53
54
55
#define save_gp_reg(i) { \
56
reg = regs->regs[i]; \
57
err |= __put_user(reg, &sc->sc_regs[i]); \
58
} while (0)
59
save_gp_reg(0); save_gp_reg(1); save_gp_reg(2);
60
save_gp_reg(3); save_gp_reg(4); save_gp_reg(5);
61
save_gp_reg(6); save_gp_reg(7); save_gp_reg(8);
62
save_gp_reg(9); save_gp_reg(10); save_gp_reg(11);
63
save_gp_reg(12); save_gp_reg(13); save_gp_reg(14);
64
save_gp_reg(15); save_gp_reg(16); save_gp_reg(17);
65
save_gp_reg(18); save_gp_reg(19); save_gp_reg(20);
66
save_gp_reg(21); save_gp_reg(22); save_gp_reg(23);
67
save_gp_reg(24); save_gp_reg(25); save_gp_reg(26);
68
save_gp_reg(27); save_gp_reg(28); save_gp_reg(29);
69
#undef save_gp_reg
70
71
reg = regs->ceh; err |= __put_user(reg, &sc->sc_mdceh);
72
reg = regs->cel; err |= __put_user(reg, &sc->sc_mdcel);
73
err |= __put_user(regs->cp0_ecr, &sc->sc_ecr);
74
err |= __put_user(regs->cp0_ema, &sc->sc_ema);
75
76
return err;
77
}
78
79
static int restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
80
{
81
int err = 0;
82
u32 reg;
83
84
err |= __get_user(regs->cp0_epc, &sc->sc_pc);
85
err |= __get_user(regs->cp0_condition, &sc->sc_condition);
86
87
err |= __get_user(reg, &sc->sc_mdceh);
88
regs->ceh = (int) reg;
89
err |= __get_user(reg, &sc->sc_mdcel);
90
regs->cel = (int) reg;
91
92
err |= __get_user(reg, &sc->sc_psr);
93
regs->cp0_psr = (int) reg;
94
err |= __get_user(reg, &sc->sc_ecr);
95
regs->cp0_ecr = (int) reg;
96
err |= __get_user(reg, &sc->sc_ema);
97
regs->cp0_ema = (int) reg;
98
99
#define restore_gp_reg(i) do { \
100
err |= __get_user(reg, &sc->sc_regs[i]); \
101
regs->regs[i] = reg; \
102
} while (0)
103
restore_gp_reg(0); restore_gp_reg(1); restore_gp_reg(2);
104
restore_gp_reg(3); restore_gp_reg(4); restore_gp_reg(5);
105
restore_gp_reg(6); restore_gp_reg(7); restore_gp_reg(8);
106
restore_gp_reg(9); restore_gp_reg(10); restore_gp_reg(11);
107
restore_gp_reg(12); restore_gp_reg(13); restore_gp_reg(14);
108
restore_gp_reg(15); restore_gp_reg(16); restore_gp_reg(17);
109
restore_gp_reg(18); restore_gp_reg(19); restore_gp_reg(20);
110
restore_gp_reg(21); restore_gp_reg(22); restore_gp_reg(23);
111
restore_gp_reg(24); restore_gp_reg(25); restore_gp_reg(26);
112
restore_gp_reg(27); restore_gp_reg(28); restore_gp_reg(29);
113
#undef restore_gp_reg
114
115
return err;
116
}
117
118
/*
119
* Determine which stack to use..
120
*/
121
static void __user *get_sigframe(struct k_sigaction *ka,
122
struct pt_regs *regs, size_t frame_size)
123
{
124
unsigned long sp;
125
126
/* Default to using normal stack */
127
sp = regs->regs[0];
128
sp -= 32;
129
130
/* This is the X/Open sanctioned signal stack switching. */
131
if ((ka->sa.sa_flags & SA_ONSTACK) && (!on_sig_stack(sp)))
132
sp = current->sas_ss_sp + current->sas_ss_size;
133
134
return (void __user*)((sp - frame_size) & ~7);
135
}
136
137
asmlinkage long
138
score_sigaltstack(struct pt_regs *regs)
139
{
140
const stack_t __user *uss = (const stack_t __user *) regs->regs[4];
141
stack_t __user *uoss = (stack_t __user *) regs->regs[5];
142
unsigned long usp = regs->regs[0];
143
144
return do_sigaltstack(uss, uoss, usp);
145
}
146
147
asmlinkage long
148
score_rt_sigreturn(struct pt_regs *regs)
149
{
150
struct rt_sigframe __user *frame;
151
sigset_t set;
152
stack_t st;
153
int sig;
154
155
frame = (struct rt_sigframe __user *) regs->regs[0];
156
if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
157
goto badframe;
158
if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
159
goto badframe;
160
161
sigdelsetmask(&set, ~_BLOCKABLE);
162
spin_lock_irq(&current->sighand->siglock);
163
current->blocked = set;
164
recalc_sigpending();
165
spin_unlock_irq(&current->sighand->siglock);
166
167
sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
168
if (sig < 0)
169
goto badframe;
170
else if (sig)
171
force_sig(sig, current);
172
173
if (__copy_from_user(&st, &frame->rs_uc.uc_stack, sizeof(st)))
174
goto badframe;
175
176
/* It is more difficult to avoid calling this function than to
177
call it and ignore errors. */
178
do_sigaltstack((stack_t __user *)&st, NULL, regs->regs[0]);
179
180
__asm__ __volatile__(
181
"mv\tr0, %0\n\t"
182
"la\tr8, syscall_exit\n\t"
183
"br\tr8\n\t"
184
: : "r" (regs) : "r8");
185
186
badframe:
187
force_sig(SIGSEGV, current);
188
189
return 0;
190
}
191
192
static int setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
193
int signr, sigset_t *set, siginfo_t *info)
194
{
195
struct rt_sigframe __user *frame;
196
int err = 0;
197
198
frame = get_sigframe(ka, regs, sizeof(*frame));
199
if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
200
goto give_sigsegv;
201
202
/*
203
* Set up the return code ...
204
*
205
* li v0, __NR_rt_sigreturn
206
* syscall
207
*/
208
err |= __put_user(0x87788000 + __NR_rt_sigreturn*2,
209
frame->rs_code + 0);
210
err |= __put_user(0x80008002, frame->rs_code + 1);
211
flush_cache_sigtramp((unsigned long) frame->rs_code);
212
213
err |= copy_siginfo_to_user(&frame->rs_info, info);
214
err |= __put_user(0, &frame->rs_uc.uc_flags);
215
err |= __put_user(NULL, &frame->rs_uc.uc_link);
216
err |= __put_user((void __user *)current->sas_ss_sp,
217
&frame->rs_uc.uc_stack.ss_sp);
218
err |= __put_user(sas_ss_flags(regs->regs[0]),
219
&frame->rs_uc.uc_stack.ss_flags);
220
err |= __put_user(current->sas_ss_size,
221
&frame->rs_uc.uc_stack.ss_size);
222
err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
223
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
224
225
if (err)
226
goto give_sigsegv;
227
228
regs->regs[0] = (unsigned long) frame;
229
regs->regs[3] = (unsigned long) frame->rs_code;
230
regs->regs[4] = signr;
231
regs->regs[5] = (unsigned long) &frame->rs_info;
232
regs->regs[6] = (unsigned long) &frame->rs_uc;
233
regs->regs[29] = (unsigned long) ka->sa.sa_handler;
234
regs->cp0_epc = (unsigned long) ka->sa.sa_handler;
235
236
return 0;
237
238
give_sigsegv:
239
if (signr == SIGSEGV)
240
ka->sa.sa_handler = SIG_DFL;
241
force_sig(SIGSEGV, current);
242
return -EFAULT;
243
}
244
245
static int handle_signal(unsigned long sig, siginfo_t *info,
246
struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
247
{
248
int ret;
249
250
if (regs->is_syscall) {
251
switch (regs->regs[4]) {
252
case ERESTART_RESTARTBLOCK:
253
case ERESTARTNOHAND:
254
regs->regs[4] = EINTR;
255
break;
256
case ERESTARTSYS:
257
if (!(ka->sa.sa_flags & SA_RESTART)) {
258
regs->regs[4] = EINTR;
259
break;
260
}
261
case ERESTARTNOINTR:
262
regs->regs[4] = regs->orig_r4;
263
regs->regs[7] = regs->orig_r7;
264
regs->cp0_epc -= 8;
265
}
266
267
regs->is_syscall = 0;
268
}
269
270
/*
271
* Set up the stack frame
272
*/
273
ret = setup_rt_frame(ka, regs, sig, oldset, info);
274
275
spin_lock_irq(&current->sighand->siglock);
276
sigorsets(&current->blocked, &current->blocked, &ka->sa.sa_mask);
277
if (!(ka->sa.sa_flags & SA_NODEFER))
278
sigaddset(&current->blocked, sig);
279
recalc_sigpending();
280
spin_unlock_irq(&current->sighand->siglock);
281
282
return ret;
283
}
284
285
static void do_signal(struct pt_regs *regs)
286
{
287
struct k_sigaction ka;
288
sigset_t *oldset;
289
siginfo_t info;
290
int signr;
291
292
/*
293
* We want the common case to go fast, which is why we may in certain
294
* cases get here from kernel mode. Just return without doing anything
295
* if so.
296
*/
297
if (!user_mode(regs))
298
return;
299
300
if (test_thread_flag(TIF_RESTORE_SIGMASK))
301
oldset = &current->saved_sigmask;
302
else
303
oldset = &current->blocked;
304
305
signr = get_signal_to_deliver(&info, &ka, regs, NULL);
306
if (signr > 0) {
307
/* Actually deliver the signal. */
308
if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
309
/*
310
* A signal was successfully delivered; the saved
311
* sigmask will have been stored in the signal frame,
312
* and will be restored by sigreturn, so we can simply
313
* clear the TIF_RESTORE_SIGMASK flag.
314
*/
315
if (test_thread_flag(TIF_RESTORE_SIGMASK))
316
clear_thread_flag(TIF_RESTORE_SIGMASK);
317
}
318
319
return;
320
}
321
322
if (regs->is_syscall) {
323
if (regs->regs[4] == ERESTARTNOHAND ||
324
regs->regs[4] == ERESTARTSYS ||
325
regs->regs[4] == ERESTARTNOINTR) {
326
regs->regs[4] = regs->orig_r4;
327
regs->regs[7] = regs->orig_r7;
328
regs->cp0_epc -= 8;
329
}
330
331
if (regs->regs[4] == ERESTART_RESTARTBLOCK) {
332
regs->regs[27] = __NR_restart_syscall;
333
regs->regs[4] = regs->orig_r4;
334
regs->regs[7] = regs->orig_r7;
335
regs->cp0_epc -= 8;
336
}
337
338
regs->is_syscall = 0; /* Don't deal with this again. */
339
}
340
341
/*
342
* If there's no signal to deliver, we just put the saved sigmask
343
* back
344
*/
345
if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
346
clear_thread_flag(TIF_RESTORE_SIGMASK);
347
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
348
}
349
}
350
351
/*
352
* notification of userspace execution resumption
353
* - triggered by the TIF_WORK_MASK flags
354
*/
355
asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
356
__u32 thread_info_flags)
357
{
358
/* deal with pending signal delivery */
359
if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
360
do_signal(regs);
361
}
362
363