This source file includes following definitions.
- sys_sigsuspend
- sys_sigreturn
- setup_frame
- do_signal
1
2
3
4
5
6
7 #include <linux/sched.h>
8 #include <linux/mm.h>
9 #include <linux/kernel.h>
10 #include <linux/signal.h>
11 #include <linux/errno.h>
12 #include <linux/wait.h>
13 #include <linux/ptrace.h>
14 #include <linux/unistd.h>
15
16 #include <asm/segment.h>
17 #include <asm/cachectl.h>
18
19 #define _S(nr) (1<<((nr)-1))
20
21 #define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
22
23 asmlinkage int sys_waitpid(pid_t pid,unsigned long * stat_addr, int options);
24
25
26
27
28 asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, unsigned long set)
29 {
30 unsigned long mask;
31 struct pt_regs * regs = (struct pt_regs *) &restart;
32
33 mask = current->blocked;
34 current->blocked = set & _BLOCKABLE;
35 regs->reg2 = -EINTR;
36 while (1) {
37 current->state = TASK_INTERRUPTIBLE;
38 schedule();
39 if (do_signal(mask,regs))
40 return -EINTR;
41 }
42 }
43
44
45
46
47 asmlinkage int sys_sigreturn(unsigned long __unused)
48 {
49 struct sigcontext_struct context;
50 struct pt_regs * regs;
51
52 regs = (struct pt_regs *) &__unused;
53 if (verify_area(VERIFY_READ, (void *) regs->reg29, sizeof(context)))
54 goto badframe;
55 memcpy_fromfs(&context,(void *) regs->reg29, sizeof(context));
56 current->blocked = context.oldmask & _BLOCKABLE;
57 regs->reg1 = context.sc_at;
58 regs->reg2 = context.sc_v0;
59 regs->reg3 = context.sc_v1;
60 regs->reg4 = context.sc_a0;
61 regs->reg5 = context.sc_a1;
62 regs->reg6 = context.sc_a2;
63 regs->reg7 = context.sc_a3;
64 regs->reg8 = context.sc_t0;
65 regs->reg9 = context.sc_t1;
66 regs->reg10 = context.sc_t2;
67 regs->reg11 = context.sc_t3;
68 regs->reg12 = context.sc_t4;
69 regs->reg13 = context.sc_t5;
70 regs->reg14 = context.sc_t6;
71 regs->reg15 = context.sc_t7;
72 regs->reg16 = context.sc_s0;
73 regs->reg17 = context.sc_s1;
74 regs->reg18 = context.sc_s2;
75 regs->reg19 = context.sc_s3;
76 regs->reg20 = context.sc_s4;
77 regs->reg21 = context.sc_s5;
78 regs->reg22 = context.sc_s6;
79 regs->reg23 = context.sc_s7;
80 regs->reg24 = context.sc_t8;
81 regs->reg25 = context.sc_t9;
82
83
84
85 regs->reg28 = context.sc_gp;
86 regs->reg29 = context.sc_sp;
87 regs->reg30 = context.sc_fp;
88 regs->reg31 = context.sc_ra;
89 regs->cp0_epc = context.sc_epc;
90 regs->cp0_cause = context.sc_cause;
91
92
93
94
95 regs->orig_reg2 = -1;
96 return regs->orig_reg2;
97 badframe:
98 do_exit(SIGSEGV);
99 }
100
101
102
103
104 static void setup_frame(struct sigaction * sa, unsigned long ** fp,
105 unsigned long pc, struct pt_regs *regs,
106 int signr, unsigned long oldmask)
107 {
108 unsigned long * frame;
109
110 frame = *fp;
111 frame -= 32;
112 if (verify_area(VERIFY_WRITE,frame,21*4))
113 do_exit(SIGSEGV);
114
115
116
117 put_fs_long(regs->reg1 , frame );
118 put_fs_long(regs->reg2 , frame+ 1);
119 put_fs_long(regs->reg3 , frame+ 2);
120 put_fs_long(regs->reg4 , frame+ 3);
121 put_fs_long(regs->reg5 , frame+ 4);
122 put_fs_long(regs->reg6 , frame+ 5);
123 put_fs_long(regs->reg7 , frame+ 6);
124 put_fs_long(regs->reg8 , frame+ 7);
125 put_fs_long(regs->reg9 , frame+ 8);
126 put_fs_long(regs->reg10, frame+ 9);
127 put_fs_long(regs->reg11, frame+10);
128 put_fs_long(regs->reg12, frame+11);
129 put_fs_long(regs->reg13, frame+12);
130 put_fs_long(regs->reg14, frame+13);
131 put_fs_long(regs->reg15, frame+14);
132 put_fs_long(regs->reg16, frame+15);
133 put_fs_long(regs->reg17, frame+16);
134 put_fs_long(regs->reg18, frame+17);
135 put_fs_long(regs->reg19, frame+18);
136 put_fs_long(regs->reg20, frame+19);
137 put_fs_long(regs->reg21, frame+20);
138 put_fs_long(regs->reg22, frame+21);
139 put_fs_long(regs->reg23, frame+22);
140 put_fs_long(regs->reg24, frame+23);
141 put_fs_long(regs->reg25, frame+24);
142
143
144
145 put_fs_long(regs->reg28, frame+25);
146 put_fs_long(regs->reg29, frame+26);
147 put_fs_long(regs->reg30, frame+27);
148 put_fs_long(regs->reg31, frame+28);
149 put_fs_long(pc , frame+29);
150 put_fs_long(oldmask , frame+30);
151
152
153
154
155
156
157
158
159
160
161 put_fs_long(0x24010077, frame+31);
162 put_fs_long(0x000000c0, frame+32);
163 *fp = frame;
164
165
166
167 sys_cacheflush(frame, 32*4, BCACHE);
168 }
169
170
171
172
173
174
175
176
177
178
179 asmlinkage int do_signal(unsigned long oldmask, struct pt_regs * regs)
180 {
181 unsigned long mask = ~current->blocked;
182 unsigned long handler_signal = 0;
183 unsigned long *frame = NULL;
184 unsigned long pc = 0;
185 unsigned long signr;
186 struct sigaction * sa;
187
188 while ((signr = current->signal & mask)) {
189 __asm__(".set\tnoreorder\n\t"
190 ".set\tnoat\n\t"
191 "li\t%0,31\n"
192 "1:\tsllv\t$1,%1,%0\n\t"
193 "bgezl\t$1,1b\n\t"
194 "subu\t$8,1\n\t"
195 "subu\t%0,31\n\t"
196 "subu\t%0,$0,%0\n\t"
197 "li\t$1,1\n\t"
198 "sllv\t$1,$1,%0\n\t"
199 "nor\t$1,$0\n\t"
200 "xor\t%1,$1\n\t"
201 ".set\tat\n\t"
202 ".set\treorder"
203 :"=r" (signr),"=r" (current->signal)
204 :"0" (signr),"1" (current->signal)
205 :"$1");
206 sa = current->sigaction + signr;
207 signr++;
208 if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
209 current->exit_code = signr;
210 current->state = TASK_STOPPED;
211 notify_parent(current);
212 schedule();
213 if (!(signr = current->exit_code))
214 continue;
215 current->exit_code = 0;
216 if (signr == SIGSTOP)
217 continue;
218 if (_S(signr) & current->blocked) {
219 current->signal |= _S(signr);
220 continue;
221 }
222 sa = current->sigaction + signr - 1;
223 }
224 if (sa->sa_handler == SIG_IGN) {
225 if (signr != SIGCHLD)
226 continue;
227
228 while (sys_waitpid(-1,NULL,WNOHANG) > 0)
229 ;
230 continue;
231 }
232 if (sa->sa_handler == SIG_DFL) {
233 if (current->pid == 1)
234 continue;
235 switch (signr) {
236 case SIGCONT: case SIGCHLD: case SIGWINCH:
237 continue;
238
239 case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU:
240 if (current->flags & PF_PTRACED)
241 continue;
242 current->state = TASK_STOPPED;
243 current->exit_code = signr;
244 if (!(current->p_pptr->sigaction[SIGCHLD-1].sa_flags &
245 SA_NOCLDSTOP))
246 notify_parent(current);
247 schedule();
248 continue;
249
250 case SIGQUIT: case SIGILL: case SIGTRAP:
251 case SIGIOT: case SIGFPE: case SIGSEGV:
252 if (current->binfmt && current->binfmt->core_dump) {
253 if (current->binfmt->core_dump(signr, regs))
254 signr |= 0x80;
255 }
256
257 default:
258 current->signal |= _S(signr & 0x7f);
259 do_exit(signr);
260 }
261 }
262
263
264
265 if (regs->orig_reg2 >= 0) {
266 if (regs->reg2 == -ERESTARTNOHAND ||
267 (regs->reg2 == -ERESTARTSYS &&
268 !(sa->sa_flags & SA_RESTART)))
269 regs->reg2 = -EINTR;
270 }
271 handler_signal |= 1 << (signr-1);
272 mask &= ~sa->sa_mask;
273 }
274 if (regs->orig_reg2 >= 0 &&
275 (regs->reg2 == -ERESTARTNOHAND ||
276 regs->reg2 == -ERESTARTSYS ||
277 regs->reg2 == -ERESTARTNOINTR)) {
278 regs->reg2 = regs->orig_reg2;
279 regs->cp0_epc -= 4;
280 }
281 if (!handler_signal)
282 return 0;
283 pc = regs->cp0_epc;
284 frame = (unsigned long *) regs->reg29;
285 signr = 1;
286 sa = current->sigaction;
287 for (mask = 1 ; mask ; sa++,signr++,mask += mask) {
288 if (mask > handler_signal)
289 break;
290 if (!(mask & handler_signal))
291 continue;
292 setup_frame(sa,&frame,pc,regs,signr,oldmask);
293 pc = (unsigned long) sa->sa_handler;
294 if (sa->sa_flags & SA_ONESHOT)
295 sa->sa_handler = NULL;
296
297
298
299
300 __asm__(".set\tnoat\n\t"
301 "lwu\t$1,(%0)\n\t"
302 ".set\tat\n\t"
303 :
304 :"r" ((char *) pc)
305 :"$1");
306 current->blocked |= sa->sa_mask;
307 oldmask |= sa->sa_mask;
308 }
309 regs->reg29 = (unsigned long) frame;
310 regs->cp0_epc = pc;
311 return 1;
312 }