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