This source file includes following definitions.
- die_if_kernel
- do_entArith
- do_entIF
- do_entUna
- do_entUnaUser
- do_entSys
- trap_init
1
2
3
4
5
6
7
8
9
10
11 #include <linux/mm.h>
12 #include <linux/sched.h>
13 #include <linux/tty.h>
14
15 #include <asm/unaligned.h>
16
17 void die_if_kernel(char * str, struct pt_regs * regs, long err)
18 {
19 long i;
20 unsigned long sp;
21 unsigned int * pc;
22
23 if (regs->ps & 8)
24 return;
25 printk("%s(%d): %s %ld\n", current->comm, current->pid, str, err);
26 sp = (unsigned long) (regs+1);
27 printk("pc = %lx ps = %04lx\n", regs->pc, regs->ps);
28 printk("rp = %lx sp = %lx\n", regs->r26, sp);
29 printk("r0=%lx r1=%lx r2=%lx r3=%lx\n",
30 regs->r0, regs->r1, regs->r2, regs->r3);
31 printk("r8=%lx\n", regs->r8);
32 printk("r16=%lx r17=%lx r18=%lx r19=%lx\n",
33 regs->r16, regs->r17, regs->r18, regs->r19);
34 printk("r20=%lx r21=%lx r22=%lx r23=%lx\n",
35 regs->r20, regs->r21, regs->r22, regs->r23);
36 printk("r24=%lx r25=%lx r26=%lx r27=%lx\n",
37 regs->r24, regs->r25, regs->r26, regs->r27);
38 printk("r28=%lx r29=%lx r30=%lx\n",
39 regs->r28, regs->gp, sp);
40 printk("Code:");
41 pc = (unsigned int *) regs->pc;
42 for (i = -3; i < 6; i++)
43 printk("%c%08x%c",i?' ':'<',pc[i],i?' ':'>');
44 printk("\n");
45 do_exit(SIGSEGV);
46 }
47
48 asmlinkage void do_entArith(unsigned long summary, unsigned long write_mask,
49 unsigned long a2, unsigned long a3, unsigned long a4, unsigned long a5,
50 struct pt_regs regs)
51 {
52 printk("Arithmetic trap: %02lx %016lx\n", summary, write_mask);
53 die_if_kernel("Arithmetic fault", ®s, 0);
54 send_sig(SIGFPE, current, 1);
55 }
56
57 asmlinkage void do_entIF(unsigned long type, unsigned long a1, unsigned long a2,
58 unsigned long a3, unsigned long a4, unsigned long a5,
59 struct pt_regs regs)
60 {
61 extern int ptrace_cancel_bpt (struct task_struct *who);
62
63 die_if_kernel("Instruction fault", ®s, type);
64 switch (type) {
65 case 0:
66 if (ptrace_cancel_bpt(current)) {
67 regs.pc -= 4;
68 }
69 send_sig(SIGTRAP, current, 1);
70 break;
71
72 case 1:
73 case 2:
74 case 3:
75 case 4:
76 send_sig(SIGILL, current, 1);
77 break;
78
79 default:
80 panic("do_entIF: unexpected instruction-fault type");
81 }
82 }
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 struct allregs {
98 unsigned long regs[32];
99 unsigned long ps, pc, gp, a0, a1, a2;
100 };
101
102 struct unaligned_stat {
103 unsigned long count, va, pc;
104 } unaligned[2];
105
106 asmlinkage void do_entUna(void * va, unsigned long opcode, unsigned long reg,
107 unsigned long a3, unsigned long a4, unsigned long a5,
108 struct allregs regs)
109 {
110 static int cnt = 0;
111 static long last_time = 0;
112
113 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
114 cnt = 0;
115 }
116 if (++cnt < 5) {
117 printk("kernel: unaligned trap at %016lx: %p %lx %ld\n",
118 regs.pc - 4, va, opcode, reg);
119 }
120 last_time = jiffies;
121
122 ++unaligned[0].count;
123 unaligned[0].va = (unsigned long) va - 4;
124 unaligned[0].pc = regs.pc;
125
126
127 if (reg >= 16 && reg <= 18)
128 reg += 19;
129 switch (opcode) {
130 case 0x28:
131 *(reg+regs.regs) = (int) ldl_u(va);
132 return;
133 case 0x29:
134 *(reg+regs.regs) = ldq_u(va);
135 return;
136 case 0x2c:
137 stl_u(*(reg+regs.regs), va);
138 return;
139 case 0x2d:
140 stq_u(*(reg+regs.regs), va);
141 return;
142 }
143 printk("Bad unaligned kernel access at %016lx: %p %lx %ld\n",
144 regs.pc, va, opcode, reg);
145 do_exit(SIGSEGV);
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163 asmlinkage void do_entUnaUser(void * va, unsigned long opcode, unsigned long reg,
164 unsigned long * frame)
165 {
166 long dir, size;
167 unsigned long *reg_addr, *pc_addr, usp, zero = 0;
168 static int cnt = 0;
169 static long last_time = 0;
170
171 pc_addr = frame + 7 + 20 + 1;
172
173 if (cnt >= 5 && jiffies - last_time > 5*HZ) {
174 cnt = 0;
175 }
176 if (++cnt < 5) {
177 printk("%s(%d): unaligned trap at %016lx: %p %lx %ld\n",
178 current->comm, current->pid,
179 *pc_addr - 4, va, opcode, reg);
180 }
181 last_time = jiffies;
182
183 ++unaligned[1].count;
184 unaligned[1].va = (unsigned long) va - 4;
185 unaligned[1].pc = *pc_addr;
186
187 dir = VERIFY_READ;
188 if (opcode > 0x29) {
189
190 dir = VERIFY_WRITE;
191 }
192 size = 4;
193 if (opcode & 1) {
194
195 size = 8;
196 }
197 if (verify_area(dir, va, size)) {
198 *pc_addr -= 4;
199 send_sig(SIGSEGV, current, 1);
200 return;
201 }
202
203 reg_addr = frame;
204 if (reg < 9) {
205 reg_addr += 7 + reg;
206 } else if (reg < 16) {
207 reg_addr += (reg - 9);
208 } else if (reg < 19) {
209 reg_addr += 7 + 20 + 3 + (reg - 16);
210 } else if (reg < 29) {
211 reg_addr += 7 + 9 + (reg - 19);
212 } else {
213 switch (reg) {
214 case 29:
215 reg_addr += 7 + 20 + 2;
216 break;
217 case 30:
218 usp = rdusp();
219 reg_addr = &usp;
220 break;
221 case 31:
222 reg_addr = &zero;
223 break;
224 }
225 }
226
227 switch (opcode) {
228 case 0x28: *reg_addr = (int) ldl_u(va); break;
229 case 0x29: *reg_addr = ldq_u(va); break;
230 case 0x2c: stl_u(*reg_addr, va); break;
231 case 0x2d: stq_u(*reg_addr, va); break;
232 default:
233 *pc_addr -= 4;
234 send_sig(SIGBUS, current, 1);
235 return;
236 }
237
238 if (reg == 30 && dir == VERIFY_WRITE) {
239 wrusp(usp);
240 }
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254 asmlinkage long do_entSys(unsigned long a0, unsigned long a1, unsigned long a2,
255 unsigned long a3, unsigned long a4, unsigned long a5, struct pt_regs regs)
256 {
257 if (regs.r0 != 112)
258 printk("<sc %ld(%lx,%lx,%lx)>", regs.r0, a0, a1, a2);
259 return -1;
260 }
261
262 extern asmlinkage void entMM(void);
263 extern asmlinkage void entIF(void);
264 extern asmlinkage void entArith(void);
265 extern asmlinkage void entUna(void);
266 extern asmlinkage void entSys(void);
267
268 void trap_init(void)
269 {
270 unsigned long gptr;
271
272
273
274
275 __asm__("br %0,___tmp\n"
276 "___tmp:\tldgp %0,0(%0)"
277 : "=r" (gptr));
278 wrkgp(gptr);
279
280 wrent(entArith, 1);
281 wrent(entMM, 2);
282 wrent(entIF, 3);
283 wrent(entUna, 4);
284 wrent(entSys, 5);
285 }