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