This source file includes following definitions.
- syscall_trace_entry
- syscall_trace_exit
- sun4m_nmi
- die_if_kernel
- do_hw_interrupt
- do_illegal_instruction
- do_priv_instruction
- do_memaccess_unaligned
- do_fpd_trap
- do_fpe_trap
- handle_tag_overflow
- handle_watchpoint
- handle_reg_access
- handle_cp_disabled
- handle_bad_flush
- handle_cp_exception
- handle_hw_divzero
- trap_init
1
2
3
4
5
6
7
8
9
10
11 #include <linux/sched.h>
12 #include <linux/kernel.h>
13 #include <linux/config.h>
14 #include <linux/signal.h>
15
16 #include <asm/delay.h>
17 #include <asm/system.h>
18 #include <asm/ptrace.h>
19 #include <asm/oplib.h>
20 #include <asm/page.h>
21 #include <asm/pgtable.h>
22 #include <asm/kdebug.h>
23 #include <asm/unistd.h>
24 #include <asm/traps.h>
25 #include <asm/smp.h>
26
27
28
29 struct trap_trace_entry {
30 unsigned long pc;
31 unsigned long type;
32 };
33
34 int trap_curbuf = 0;
35 struct trap_trace_entry trapbuf[1024];
36
37 void syscall_trace_entry(struct pt_regs *regs)
38 {
39 printk("%s[%d]: ", current->comm, current->pid);
40 printk("scall<%d> (could be %d)\n", (int) regs->u_regs[UREG_G1],
41 (int) regs->u_regs[UREG_I0]);
42 }
43
44 void syscall_trace_exit(struct pt_regs *regs)
45 {
46 }
47
48 void sun4m_nmi(struct pt_regs *regs)
49 {
50 unsigned long afsr, afar;
51
52 printk("Aieee: sun4m NMI received!\n");
53
54 __asm__ __volatile__("mov 0x500, %%g1\n\t"
55 "lda [%%g1] 0x4, %0\n\t"
56 "mov 0x600, %%g1\n\t"
57 "lda [%%g1] 0x4, %1\n\t" :
58 "=r" (afsr), "=r" (afar));
59 printk("afsr=%08lx afar=%08lx\n", afsr, afar);
60 printk("you lose buddy boy...\n");
61 show_regs(regs);
62 prom_halt();
63 }
64
65 void die_if_kernel(char *str, struct pt_regs *regs)
66 {
67 unsigned long i;
68 unsigned long *pc;
69
70
71 printk(
72 " \\|/ ____ \\|/\n"
73 " \"@'/ ,. \\`@\"\n"
74 " /_| \\__/ |_\\\n"
75 " \\__U_/\n");
76
77 printk("%s(%d): %s\n", current->comm, current->pid, str);
78 show_regs(regs);
79 #if CONFIG_AP1000
80 ap_panic();
81 #endif
82 printk("Instruction DUMP:");
83 pc = (unsigned long *) regs->pc;
84 for(i = -3; i < 6; i++)
85 printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
86 printk("\n");
87 if(regs->psr & PSR_PS)
88 do_exit(SIGKILL);
89 do_exit(SIGSEGV);
90 }
91
92 void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
93 {
94 if(type < 0x80) {
95
96 printk("Unimplemented Sparc TRAP, type = %02lx\n", type);
97 die_if_kernel("Whee... Hello Mr. Penguin", current->tss.kregs);
98 }
99 if(type == SP_TRAP_SBPT) {
100 send_sig(SIGTRAP, current, 1);
101 return;
102 }
103 current->tss.sig_desc = SUBSIG_BADTRAP(type - 0x80);
104 current->tss.sig_address = pc;
105 send_sig(SIGILL, current, 1);
106 }
107
108 void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
109 unsigned long psr)
110 {
111 if(psr & PSR_PS)
112 die_if_kernel("Kernel illegal instruction", regs);
113 #ifdef TRAP_DEBUG
114 printk("Ill instr. at pc=%08lx instruction is %08lx\n",
115 regs->pc, *(unsigned long *)regs->pc);
116 #endif
117 current->tss.sig_address = pc;
118 current->tss.sig_desc = SUBSIG_ILLINST;
119 send_sig(SIGILL, current, 1);
120 }
121
122 void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
123 unsigned long psr)
124 {
125 if(psr & PSR_PS)
126 die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
127 current->tss.sig_address = pc;
128 current->tss.sig_desc = SUBSIG_PRIVINST;
129 send_sig(SIGILL, current, 1);
130 }
131
132
133
134 void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
135 unsigned long psr)
136 {
137 if(regs->psr & PSR_PS) {
138 printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
139 regs->u_regs[UREG_RETPC]);
140 die_if_kernel("BOGUS", regs);
141
142 }
143 current->tss.sig_address = pc;
144 current->tss.sig_desc = SUBSIG_PRIVINST;
145 send_sig(SIGBUS, current, 1);
146 }
147
148 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
149 void *fpqueue, unsigned long *fpqdepth);
150 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
151
152 static unsigned long init_fsr = 0x0UL;
153 static unsigned long init_fregs[32] __attribute__ ((aligned (8))) =
154 { ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
155 ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
156 ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
157 ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL };
158
159 void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
160 unsigned long psr)
161 {
162
163 if(psr & PSR_PS)
164 die_if_kernel("Kernel gets FloatingPenguinUnit disabled trap", regs);
165
166 put_psr(get_psr() | PSR_EF);
167 regs->psr |= PSR_EF;
168 #ifndef __SMP__
169 if(last_task_used_math == current)
170 return;
171 if(last_task_used_math) {
172
173 struct task_struct *fptask = last_task_used_math;
174 fpsave(&fptask->tss.float_regs[0], &fptask->tss.fsr,
175 &fptask->tss.fpqueue[0], &fptask->tss.fpqdepth);
176 }
177 last_task_used_math = current;
178 if(current->used_math) {
179 fpload(¤t->tss.float_regs[0], ¤t->tss.fsr);
180 } else {
181
182 fpload(&init_fregs[0], &init_fsr);
183 current->used_math = 1;
184 }
185 #else
186 if(!current->used_math) {
187 fpload(&init_fregs[0], &init_fsr);
188 current->used_math = 1;
189 } else {
190 fpload(¤t->tss.float_regs[0], ¤t->tss.fsr);
191 }
192 current->flags |= PF_USEDFPU;
193 #endif
194 }
195
196 static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
197 static unsigned long fake_fsr;
198 static unsigned long fake_queue[32] __attribute__ ((aligned (8)));
199 static unsigned long fake_depth;
200
201 void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
202 unsigned long psr)
203 {
204 static calls = 0;
205 #ifndef __SMP__
206 struct task_struct *fpt = last_task_used_math;
207 #else
208 struct task_struct *fpt = current;
209 #endif
210
211 put_psr(get_psr() | PSR_EF);
212
213
214
215
216 #ifndef __SMP__
217 if(!fpt) {
218 #else
219 if(!(fpt->flags & PF_USEDFPU)) {
220 #endif
221 fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth);
222 regs->psr &= ~PSR_EF;
223 return;
224 }
225 fpsave(&fpt->tss.float_regs[0], &fpt->tss.fsr,
226 &fpt->tss.fpqueue[0], &fpt->tss.fpqdepth);
227 fpt->tss.sig_address = pc;
228 fpt->tss.sig_desc = SUBSIG_FPERROR;
229 #ifdef __SMP__
230 fpt->flags &= ~PF_USEDFPU;
231 #endif
232 if(psr & PSR_PS) {
233
234
235
236 printk("WARNING: FPU exception from kernel mode. at pc=%08lx\n",
237 regs->pc);
238 regs->pc = regs->npc;
239 regs->npc += 4;
240 calls++;
241 if(calls > 2)
242 die_if_kernel("Too many Penguin-FPU traps from kernel mode",
243 regs);
244 return;
245 }
246 send_sig(SIGFPE, fpt, 1);
247 #ifndef __SMP__
248 last_task_used_math = NULL;
249 #endif
250 regs->psr &= ~PSR_EF;
251 if(calls > 0)
252 calls=0;
253 }
254
255 void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
256 unsigned long psr)
257 {
258 if(psr & PSR_PS)
259 die_if_kernel("Penguin overflow trap from kernel mode", regs);
260 current->tss.sig_address = pc;
261 current->tss.sig_desc = SUBSIG_TAG;
262 send_sig(SIGEMT, current, 1);
263 }
264
265 void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
266 unsigned long psr)
267 {
268 #ifdef TRAP_DEBUG
269 printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n",
270 pc, npc, psr);
271 #endif
272 if(psr & PSR_PS)
273 panic("Tell me what a watchpoint trap is, and I'll then deal "
274 "with such a beast...");
275 }
276
277 void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
278 unsigned long psr)
279 {
280 #ifdef TRAP_DEBUG
281 printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
282 pc, npc, psr);
283 #endif
284 send_sig(SIGILL, current, 1);
285 }
286
287 void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
288 unsigned long psr)
289 {
290 send_sig(SIGILL, current, 1);
291 }
292
293 void handle_bad_flush(struct pt_regs *regs, unsigned long pc, unsigned long npc,
294 unsigned long psr)
295 {
296 #ifdef TRAP_DEBUG
297 printk("Unimplemented FLUSH Exception at PC %08lx NPC %08lx PSR %08lx\n",
298 pc, npc, psr);
299 #endif
300 printk("INSTRUCTION=%08lx\n", *((unsigned long *) regs->pc));
301 send_sig(SIGILL, current, 1);
302 }
303
304 void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
305 unsigned long psr)
306 {
307 #ifdef TRAP_DEBUG
308 printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
309 pc, npc, psr);
310 #endif
311 send_sig(SIGILL, current, 1);
312 }
313
314 void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
315 unsigned long psr)
316 {
317 send_sig(SIGILL, current, 1);
318 }
319
320
321
322
323
324 extern void sparc_cpu_startup(void);
325
326 extern int linux_num_cpus;
327 extern ctxd_t *srmmu_ctx_table_phys;
328
329 int linux_smp_still_initting;
330 unsigned int thiscpus_tbr;
331 int thiscpus_mid;
332
333 void trap_init(void)
334 {
335 }