This source file includes following definitions.
- _sigpause_common
- do_sigpause
- do_sigsuspend
- do_sigreturn
- setup_frame
- do_signal
- sys_sigstack
1
2
3
4
5
6
7 #include <linux/sched.h>
8 #include <linux/kernel.h>
9 #include <linux/signal.h>
10 #include <linux/errno.h>
11 #include <linux/wait.h>
12 #include <linux/ptrace.h>
13 #include <linux/unistd.h>
14 #include <linux/mm.h>
15
16 #include <asm/segment.h>
17 #include <asm/bitops.h>
18 #include <asm/ptrace.h>
19
20 #define _S(nr) (1<<((nr)-1))
21
22 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
23
24 asmlinkage int sys_waitpid(pid_t pid, unsigned long *stat_addr, int options);
25 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs);
26
27
28
29
30
31 asmlinkage inline void _sigpause_common(unsigned int set, struct pt_regs *regs)
32 {
33 unsigned long mask;
34
35 mask = current->blocked;
36 current->blocked = set & _BLOCKABLE;
37
38
39
40
41
42
43 regs->pc = regs->npc;
44 regs->npc += 4;
45 regs->psr |= PSR_C;
46 regs->u_regs[UREG_I0] = EINTR;
47
48 while (1) {
49 current->state = TASK_INTERRUPTIBLE;
50 schedule();
51 if (do_signal(mask, regs))
52 return;
53 }
54 }
55
56 asmlinkage void do_sigpause(unsigned int set, struct pt_regs *regs)
57 {
58 _sigpause_common(set, regs);
59 }
60
61 asmlinkage void do_sigsuspend (struct pt_regs *regs)
62 {
63 unsigned long mask;
64 unsigned long set;
65
66 set = regs->u_regs [UREG_I0];
67 mask = current->blocked;
68 current->blocked = set & _BLOCKABLE;
69 regs->pc = regs->npc;
70 regs->npc += 4;
71 while (1) {
72 current->state = TASK_INTERRUPTIBLE;
73 schedule();
74 if (do_signal(mask,regs)){
75 regs->psr |= PSR_C;
76 regs->u_regs [UREG_I0] = EINTR;
77 return;
78 }
79 }
80 }
81
82 asmlinkage void do_sigreturn(struct pt_regs *regs)
83 {
84 struct sigcontext_struct *scptr =
85 (struct sigcontext_struct *) regs->u_regs[UREG_I0];
86
87 synchronize_user_stack();
88
89
90 if(verify_area(VERIFY_READ, scptr, sizeof(struct sigcontext_struct)) ||
91 ((((unsigned long) scptr)) & 0x3)) {
92 printk("%s [%d]: do_sigreturn, scptr is invalid at pc<%08lx> scptr<%p>\n",
93 current->comm, current->pid, regs->pc, scptr);
94 do_exit(SIGSEGV);
95 }
96
97 if((scptr->sigc_pc | scptr->sigc_npc) & 3)
98 return;
99
100 current->blocked = scptr->sigc_mask & _BLOCKABLE;
101 current->tss.sstk_info.cur_status = (scptr->sigc_onstack & 1);
102 regs->pc = scptr->sigc_pc;
103 regs->npc = scptr->sigc_npc;
104 regs->u_regs[UREG_FP] = scptr->sigc_sp;
105 regs->u_regs[UREG_I0] = scptr->sigc_o0;
106 regs->u_regs[UREG_G1] = scptr->sigc_g1;
107
108
109 regs->psr &= (~PSR_ICC);
110 regs->psr |= (scptr->sigc_psr & PSR_ICC);
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126 struct signal_sframe {
127 struct reg_window sig_window;
128 int sig_num;
129 int sig_code;
130 struct sigcontext_struct *sig_scptr;
131 int sig_address;
132 struct sigcontext_struct sig_context;
133 };
134
135 #define SF_ALIGNEDSZ (((sizeof(struct signal_sframe) + 7) & (~7)))
136
137 static inline void
138 setup_frame(struct sigaction *sa, struct sigcontext_struct **fp,
139 unsigned long pc, unsigned long npc, struct pt_regs *regs,
140 int signr, unsigned long oldmask)
141 {
142 struct signal_sframe *sframep;
143 struct sigcontext_struct *sc;
144 int window = 0;
145 int old_status = current->tss.sstk_info.cur_status;
146
147 synchronize_user_stack();
148 sframep = (struct signal_sframe *) *fp;
149 sframep = (struct signal_sframe *) (((unsigned long) sframep)-SF_ALIGNEDSZ);
150 sc = &sframep->sig_context;
151 if(verify_area(VERIFY_WRITE, sframep, sizeof(*sframep)) ||
152 (((unsigned long) sframep) & 7) ||
153 (((unsigned long) sframep) >= KERNBASE) ||
154 ((sparc_cpu_model == sun4 || sparc_cpu_model == sun4c) &&
155 ((unsigned long) sframep < 0xe0000000 && (unsigned long) sframep >= 0x20000000))) {
156 #if 0
157 printk("%s [%d]: User has trashed signal stack\n",
158 current->comm, current->pid);
159 printk("Sigstack ptr %p handler at pc<%08lx> for sig<%d>\n",
160 sframep, pc, signr);
161 #endif
162
163
164
165 current->sig->action[SIGILL-1].sa_handler = SIG_DFL;
166 current->blocked &= ~(1<<(SIGILL-1));
167 send_sig(SIGILL,current,1);
168 return;
169 }
170 *fp = (struct sigcontext_struct *) sframep;
171
172 sc->sigc_onstack = old_status;
173 sc->sigc_mask = oldmask;
174 sc->sigc_sp = regs->u_regs[UREG_FP];
175 sc->sigc_pc = pc;
176 sc->sigc_npc = npc;
177 sc->sigc_psr = regs->psr;
178 sc->sigc_g1 = regs->u_regs[UREG_G1];
179 sc->sigc_o0 = regs->u_regs[UREG_I0];
180 sc->sigc_oswins = current->tss.w_saved;
181 if(current->tss.w_saved)
182 for(window = 0; window < current->tss.w_saved; window++) {
183 sc->sigc_spbuf[window] =
184 (char *)current->tss.rwbuf_stkptrs[window];
185 memcpy(&sc->sigc_wbuf[window],
186 ¤t->tss.reg_window[window],
187 sizeof(struct reg_window));
188 }
189 else
190 memcpy(sframep, (char *)regs->u_regs[UREG_FP],
191 sizeof(struct reg_window));
192
193 current->tss.w_saved = 0;
194 sframep->sig_num = signr;
195 if(signr == SIGSEGV ||
196 signr == SIGILL ||
197 signr == SIGFPE ||
198 signr == SIGBUS ||
199 signr == SIGEMT) {
200 sframep->sig_code = current->tss.sig_desc;
201 sframep->sig_address = current->tss.sig_address;
202 } else {
203 sframep->sig_code = 0;
204 sframep->sig_address = 0;
205 }
206 sframep->sig_scptr = sc;
207 regs->u_regs[UREG_FP] = (unsigned long) *fp;
208 }
209
210
211
212
213
214
215
216
217
218
219
220 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
221 {
222 unsigned long mask = ~current->blocked;
223 unsigned long handler_signal = 0;
224 struct sigcontext_struct *frame = NULL;
225 unsigned long pc = 0;
226 unsigned long npc = 0;
227 unsigned long signr;
228 struct sigaction *sa;
229
230 while ((signr = current->signal & mask) != 0) {
231 signr = ffz(~signr);
232 clear_bit(signr, ¤t->signal);
233 sa = current->sig->action + signr;
234 signr++;
235 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
236 current->exit_code = signr;
237 current->state = TASK_STOPPED;
238 notify_parent(current);
239 schedule();
240 if (!(signr = current->exit_code))
241 continue;
242 current->exit_code = 0;
243 if (signr == SIGSTOP)
244 continue;
245 if (_S(signr) & current->blocked) {
246 current->signal |= _S(signr);
247 continue;
248 }
249 sa = current->sig->action + signr - 1;
250 }
251 if(sa->sa_handler == SIG_IGN) {
252 if(signr != SIGCHLD)
253 continue;
254 while(sys_waitpid(-1,NULL,WNOHANG) > 0);
255 continue;
256 }
257 if(sa->sa_handler == SIG_DFL) {
258 if(current->pid == 1)
259 continue;
260 switch(signr) {
261 case SIGCONT: case SIGCHLD: case SIGWINCH:
262 continue;
263
264 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
265 current->state = TASK_STOPPED;
266 current->exit_code = signr;
267 if(!(current->p_pptr->sig->action[SIGCHLD-1].sa_flags &
268 SA_NOCLDSTOP))
269 notify_parent(current);
270 schedule();
271 continue;
272
273 case SIGQUIT: case SIGILL: case SIGTRAP:
274 case SIGABRT: case SIGFPE: case SIGSEGV:
275 if(current->binfmt && current->binfmt->core_dump) {
276 if(current->binfmt->core_dump(signr, regs))
277 signr |= 0x80;
278 }
279
280 default:
281 current->signal |= _S(signr & 0x7f);
282 current->flags |= PF_SIGNALED;
283 do_exit(signr);
284 }
285 }
286
287 if(regs->psr & PSR_C) {
288 if(regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
289 (regs->u_regs[UREG_I0] == ERESTARTSYS && !(sa->sa_flags & SA_RESTART)))
290 regs->u_regs[UREG_I0] = EINTR;
291 }
292 handler_signal |= 1 << (signr - 1);
293 mask &= ~sa->sa_mask;
294 }
295 if((regs->psr & PSR_C) &&
296 (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
297 regs->u_regs[UREG_I0] == ERESTARTSYS ||
298 regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
299
300 regs->u_regs[UREG_I0] = regs->u_regs[UREG_G0];
301 regs->pc -= 4;
302 regs->npc -= 4;
303 }
304 if(!handler_signal)
305 return 0;
306 pc = regs->pc;
307 npc = regs->npc;
308 frame = (struct sigcontext_struct *) regs->u_regs[UREG_FP];
309 signr = 1;
310 sa = current->sig->action;
311 for(mask = 1; mask; sa++, signr++, mask += mask) {
312 if(mask > handler_signal)
313 break;
314 if(!(mask & handler_signal))
315 continue;
316 setup_frame(sa, &frame, pc, npc, regs, signr, oldmask);
317 pc = (unsigned long) sa->sa_handler;
318 npc = pc + 4;
319 if(sa->sa_flags & SA_ONESHOT)
320 sa->sa_handler = NULL;
321 current->blocked |= sa->sa_mask;
322 oldmask |= sa->sa_mask;
323 }
324 regs->pc = pc;
325 regs->npc = npc;
326 return 1;
327 }
328
329 asmlinkage int
330 sys_sigstack(struct sigstack *ssptr, struct sigstack *ossptr)
331 {
332
333 if(ossptr) {
334 if(verify_area(VERIFY_WRITE, ossptr, sizeof(struct sigstack)))
335 return -EFAULT;
336 memcpy(ossptr, ¤t->tss.sstk_info, sizeof(struct sigstack));
337 }
338
339
340 if(ssptr) {
341 if(verify_area(VERIFY_READ, ssptr, sizeof(struct sigstack)))
342 return -EFAULT;
343 memcpy(¤t->tss.sstk_info, ssptr, sizeof(struct sigstack));
344 }
345 return 0;
346 }