This source file includes following definitions.
- die_if_kernel
- do_entArith
- do_entIF
- do_entUna
- s_mem_to_reg
- s_reg_to_mem
- do_entUnaUser
- do_entSys
- trap_init
1
2
3
4
5
6
7
8
9
10
11 #include <linux/config.h>
12 #include <linux/mm.h>
13 #include <linux/sched.h>
14 #include <linux/tty.h>
15
16 #include <asm/gentrap.h>
17 #include <asm/segment.h>
18 #include <asm/unaligned.h>
19
20 void die_if_kernel(char * str, struct pt_regs * regs, long err)
21 {
22 long i;
23 unsigned long sp;
24 unsigned int * pc;
25
26 if (regs->ps & 8)
27 return;
28 printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
29 sp = (unsigned long) (regs+1);
30 printk("pc = [<%lx>] ps = %04lx\n", regs->pc, regs->ps);
31 printk("rp = [<%lx>] sp = %lx\n", regs->r26, sp);
32 printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
33 regs->r0, regs->r1, regs->r2, regs->r3);
34 printk("r8=%lx\n", regs->r8);
35 printk("r16=%lx r17=%lx r18=%lx r19=%lx\n",
36 regs->r16, regs->r17, regs->r18, regs->r19);
37 printk("r20=%lx r21=%lx r22=%lx r23=%lx\n",
38 regs->r20, regs->r21, regs->r22, regs->r23);
39 printk("r24=%lx r25=%lx r26=%lx r27=%lx\n",
40 regs->r24, regs->r25, regs->r26, regs->r27);
41 printk("r28=%lx r29=%lx r30=%lx\n",
42 regs->r28, regs->gp, sp);
43 printk("Code:");
44 pc = (unsigned int *) regs->pc;
45 for (i = -3; i < 6; i++)
46 printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
47 printk("\n");
48 do_exit(SIGSEGV);
49 }
50
51 asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
52 unsigned long a2, unsigned long a3,
53 unsigned long a4, unsigned long a5,
54 struct pt_regs regs)
55 {
56 if ((summary & 1)) {
57 extern long alpha_fp_emul_imprecise (struct pt_regs * regs,
58 unsigned long write_mask);
59
60
61
62
63 if (alpha_fp_emul_imprecise(®s, write_mask)) {
64 return;
65 }
66 }
67 printk("Arithmetic trap at %016lx: %02lx %016lx\n",
68 regs.pc, summary, write_mask);
69 die_if_kernel("Arithmetic fault", ®s, 0);
70 send_sig(SIGFPE, current, 1);
71 }
72
73 asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
74 unsigned long a3, unsigned long a4, unsigned long a5,
75 struct pt_regs regs)
76 {
77 extern int ptrace_cancel_bpt (struct task_struct *who);
78
79 die_if_kernel("Instruction fault", ®s, type);
80 switch (type) {
81 case 0:
82 if (ptrace_cancel_bpt(current)) {
83 regs.pc -= 4;
84 }
85 send_sig(SIGTRAP, current, 1);
86 break;
87
88 case 2:
89
90
91
92
93
94
95
96 switch ((long) regs.r16) {
97 case GEN_INTOVF: case GEN_INTDIV: case GEN_FLTOVF:
98 case GEN_FLTDIV: case GEN_FLTUND: case GEN_FLTINV:
99 case GEN_FLTINE:
100 send_sig(SIGFPE, current, 1);
101 break;
102
103 case GEN_DECOVF:
104 case GEN_DECDIV:
105 case GEN_DECINV:
106 case GEN_ROPRAND:
107 case GEN_ASSERTERR:
108 case GEN_NULPTRERR:
109 case GEN_STKOVF:
110 case GEN_STRLENERR:
111 case GEN_SUBSTRERR:
112 case GEN_RANGERR:
113 case GEN_SUBRNG:
114 case GEN_SUBRNG1:
115 case GEN_SUBRNG2:
116 case GEN_SUBRNG3:
117 case GEN_SUBRNG4:
118 case GEN_SUBRNG5:
119 case GEN_SUBRNG6:
120 case GEN_SUBRNG7:
121 send_sig(SIGILL, current, 1);
122 break;
123 }
124 break;
125
126 case 1:
127 case 3:
128 send_sig(SIGILL, current, 1);
129 break;
130
131 case 4:
132 #ifdef CONFIG_ALPHA_NEED_ROUNDING_EMULATION
133 {
134 extern long alpha_fp_emul (unsigned long pc);
135 unsigned int opcode;
136
137
138 opcode = get_user((__u32*)(regs.pc - 4)) >> 26;
139 if (opcode == 0x16) {
140
141
142
143
144 if (!alpha_fp_emul(regs.pc - 4))
145 send_sig(SIGFPE, current, 1);
146 break;
147 }
148 }
149 #endif
150 send_sig(SIGILL, current, 1);
151 break;
152
153 default:
154 panic("do_entIF: unexpected instruction-fault type");
155 }
156 }
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171 struct allregs {
172 unsigned long regs[32];
173 unsigned long ps, pc, gp, a0, a1, a2;
174 };
175
176 struct unaligned_stat {
177 unsigned long count, va, pc;
178 } unaligned[2];
179
180 asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
181 unsigned long a3, unsigned long a4, unsigned long a5,
182 struct allregs regs)
183 {
184 static int cnt = 0;
185 static long last_time = 0;
186
187 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
188 cnt = 0;
189 }
190 if (++cnt < 5) {
191 printk("kernel: unaligned trap at %016lx: %p %lx %ld\n",
192 regs.pc - 4, va, opcode, reg);
193 }
194 last_time = jiffies;
195
196 ++unaligned[0].count;
197 unaligned[0].va = (unsigned long) va - 4;
198 unaligned[0].pc = regs.pc;
199
200
201 if (reg >= 16 && reg <= 18)
202 reg += 19;
203 switch (opcode) {
204 case 0x28:
205 *(reg+regs.regs) = (int) ldl_u(va);
206 return;
207 case 0x29:
208 *(reg+regs.regs) = ldq_u(va);
209 return;
210 case 0x2c:
211 stl_u(*(reg+regs.regs), va);
212 return;
213 case 0x2d:
214 stq_u(*(reg+regs.regs), va);
215 return;
216 }
217 printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
218 regs.pc, va, opcode, reg);
219 do_exit(SIGSEGV);
220 }
221
222
223
224
225
226
227
228 static inline unsigned long s_mem_to_reg (unsigned long s_mem)
229 {
230 unsigned long frac = (s_mem >> 0) & 0x7fffff;
231 unsigned long sign = (s_mem >> 31) & 0x1;
232 unsigned long exp_msb = (s_mem >> 30) & 0x1;
233 unsigned long exp_low = (s_mem >> 23) & 0x7f;
234 unsigned long exp;
235
236 exp = (exp_msb << 10) | exp_low;
237 if (exp_msb) {
238 if (exp_low == 0x7f) {
239 exp = 0x3ff;
240 }
241 } else {
242 if (exp_low == 0x00) {
243 exp = 0x000;
244 } else {
245 exp |= (0x7 << 8);
246 }
247 }
248 return (sign << 63) | (exp << 52) | (frac << 29);
249 }
250
251
252
253
254
255 static inline unsigned long s_reg_to_mem (unsigned long s_reg)
256 {
257 return ((s_reg >> 62) << 30) | ((s_reg << 5) >> 34);
258 }
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279 asmlinkage void do_entUnaUser(void * va, unsigned long opcode, unsigned long reg,
280 unsigned long * frame)
281 {
282 long dir, size;
283 unsigned long *reg_addr, *pc_addr, usp, zero = 0;
284 static int cnt = 0;
285 static long last_time = 0;
286 extern void alpha_write_fp_reg (unsigned long reg, unsigned long val);
287 extern unsigned long alpha_read_fp_reg (unsigned long reg);
288
289 pc_addr = frame + 7 + 20 + 1;
290
291 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
292 cnt = 0;
293 }
294 if (++cnt < 5) {
295 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
296 current->comm, current->pid,
297 *pc_addr - 4, va, opcode, reg);
298 }
299 last_time = jiffies;
300
301 ++unaligned[1].count;
302 unaligned[1].va = (unsigned long) va - 4;
303 unaligned[1].pc = *pc_addr;
304
305 dir = VERIFY_READ;
306 if (opcode & 0x4) {
307
308 dir = VERIFY_WRITE;
309 }
310 size = 4;
311 if (opcode & 0x1) {
312
313 size = 8;
314 }
315 if (verify_area(dir, va, size)) {
316 *pc_addr -= 4;
317 send_sig(SIGSEGV, current, 1);
318 return;
319 }
320
321 reg_addr = frame;
322 if (opcode >= 0x28) {
323
324 if (reg < 9) {
325 reg_addr += 7 + reg;
326 } else if (reg < 16) {
327 reg_addr += (reg - 9);
328 } else if (reg < 19) {
329 reg_addr += 7 + 20 + 3 + (reg - 16);
330 } else if (reg < 29) {
331 reg_addr += 7 + 9 + (reg - 19);
332 } else {
333 switch (reg) {
334 case 29:
335 reg_addr += 7 + 20 + 2;
336 break;
337 case 30:
338 usp = rdusp();
339 reg_addr = &usp;
340 break;
341 case 31:
342 reg_addr = &zero;
343 break;
344 }
345 }
346 }
347
348 switch (opcode) {
349 case 0x22:
350 alpha_write_fp_reg(reg, s_mem_to_reg(ldl_u(va)));
351 break;
352 case 0x26:
353 alpha_write_fp_reg(reg, s_reg_to_mem(ldl_u(va)));
354 break;
355
356 case 0x23: alpha_write_fp_reg(reg, ldq_u(va)); break;
357 case 0x27: stq_u(alpha_read_fp_reg(reg), va); break;
358
359 case 0x28: *reg_addr = (int) ldl_u(va); break;
360 case 0x29: *reg_addr = ldq_u(va); break;
361 case 0x2c: stl_u(*reg_addr, va); break;
362 case 0x2d: stq_u(*reg_addr, va); break;
363 default:
364 *pc_addr -= 4;
365 send_sig(SIGBUS, current, 1);
366 return;
367 }
368
369 if (opcode >= 0x28 && reg == 30 && dir == VERIFY_WRITE) {
370 wrusp(usp);
371 }
372 }
373
374
375
376
377
378
379
380
381
382
383
384
385 asmlinkage long do_entSys(unsigned long a0, unsigned long a1, unsigned long a2,
386 unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs)
387 {
388 if (regs.r0 != 112)
389 printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
390 return -1;
391 }
392
393 extern asmlinkage void entMM(void);
394 extern asmlinkage void entIF(void);
395 extern asmlinkage void entArith(void);
396 extern asmlinkage void entUna(void);
397 extern asmlinkage void entSys(void);
398
399 void trap_init(void)
400 {
401 unsigned long gptr;
402
403
404
405
406 __asm__("br %0,___tmp\n"
407 "___tmp:\tldgp %0,0(%0)"
408 : "=r" (gptr));
409 wrkgp(gptr);
410
411 wrent(entArith, 1);
412 wrent(entMM, 2);
413 wrent(entIF, 3);
414 wrent(entUna, 4);
415 wrent(entSys, 5);
416 }