This source file includes following definitions.
- syscall_trace_entry
- syscall_trace_exit
- 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/signal.h>
14
15 #include <asm/delay.h>
16 #include <asm/system.h>
17 #include <asm/ptrace.h>
18 #include <asm/oplib.h>
19 #include <asm/page.h>
20 #include <asm/pgtable.h>
21 #include <asm/mp.h>
22 #include <asm/kdebug.h>
23 #include <asm/unistd.h>
24
25 struct trap_trace_entry {
26 unsigned long pc;
27 unsigned long type;
28 };
29
30 int trap_curbuf = 0;
31 struct trap_trace_entry trapbuf[1024];
32
33 void syscall_trace_entry(struct pt_regs *regs)
34 {
35 printk("%s[%d]: ", current->comm, current->pid);
36 printk("scall<%d> (could be %d)\n", (int) regs->u_regs[UREG_G1],
37 (int) regs->u_regs[UREG_I0]);
38 }
39
40 void syscall_trace_exit(struct pt_regs *regs)
41 {
42 }
43
44 void die_if_kernel(char *str, struct pt_regs *regs)
45 {
46 unsigned long i;
47 unsigned long *pc;
48
49 if(regs->psr & PSR_PS)
50 do_exit(SIGKILL);
51 printk("%s(%d): %s\n", current->comm, current->pid, str);
52 show_regs(regs);
53 printk("Instruction DUMP:");
54 pc = (unsigned long *) regs->pc;
55 for(i = -3; i < 6; i++)
56 printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
57 printk("\n");
58 do_exit(SIGSEGV);
59 }
60
61 void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
62 {
63 if(type < 0x80) {
64
65 printk("Unimplemented Sparc TRAP, type = %02lx\n", type);
66 panic("Whee... Hello Mr. Penguin");
67 }
68 current->tss.sig_desc = SUBSIG_BADTRAP(type - 0x80);
69 current->tss.sig_address = pc;
70 send_sig(SIGILL, current, 1);
71 }
72
73 void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
74 unsigned long psr)
75 {
76 if(psr & PSR_PS)
77 die_if_kernel("Kernel illegal instruction", regs);
78 current->tss.sig_address = pc;
79 current->tss.sig_desc = SUBSIG_ILLINST;
80 send_sig(SIGILL, current, 1);
81 }
82
83 void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
84 unsigned long psr)
85 {
86 if(psr & PSR_PS)
87 die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
88 current->tss.sig_address = pc;
89 current->tss.sig_desc = SUBSIG_PRIVINST;
90 send_sig(SIGILL, current, 1);
91 }
92
93
94
95 void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
96 unsigned long psr)
97 {
98 if(regs->psr & PSR_PS)
99 die_if_kernel("Kernel MNA access", regs);
100 current->tss.sig_address = pc;
101 current->tss.sig_desc = SUBSIG_PRIVINST;
102 send_sig(SIGBUS, current, 1);
103 }
104
105 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
106 void *fpqueue, unsigned long *fpqdepth);
107 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
108
109 static unsigned long init_fsr = 0x0UL;
110 static unsigned long init_fregs[32] __attribute__ ((aligned (8))) =
111 { ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
112 ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
113 ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
114 ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL };
115
116 void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
117 unsigned long psr)
118 {
119
120 if(psr & PSR_PS)
121 die_if_kernel("Kernel gets Penguin-FPU disabled trap", regs);
122
123 put_psr(get_psr() | PSR_EF);
124 regs->psr |= PSR_EF;
125 if(last_task_used_math == current)
126 return;
127 if(last_task_used_math) {
128
129 struct task_struct *fptask = last_task_used_math;
130 fpsave(&fptask->tss.float_regs[0], &fptask->tss.fsr,
131 &fptask->tss.fpqueue[0], &fptask->tss.fpqdepth);
132 }
133 last_task_used_math = current;
134 if(current->used_math) {
135 fpload(¤t->tss.float_regs[0], ¤t->tss.fsr);
136 } else {
137
138 fpload(&init_fregs[0], &init_fsr);
139 current->used_math = 1;
140 }
141 }
142
143 static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
144 static unsigned long fake_fsr;
145 static unsigned long fake_queue[32] __attribute__ ((aligned (8)));
146 static unsigned long fake_depth;
147
148 void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
149 unsigned long psr)
150 {
151 static calls = 0;
152 struct task_struct *fpt = last_task_used_math;
153
154 put_psr(get_psr() | PSR_EF);
155
156
157
158
159 if(!fpt) {
160 fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth);
161 regs->psr &= ~PSR_EF;
162 return;
163 }
164 fpsave(&fpt->tss.float_regs[0], &fpt->tss.fsr,
165 &fpt->tss.fpqueue[0], &fpt->tss.fpqdepth);
166 last_task_used_math->tss.sig_address = pc;
167 last_task_used_math->tss.sig_desc = SUBSIG_FPERROR;
168 if(psr & PSR_PS) {
169
170
171
172 printk("WARNING: FPU exception from kernel mode. at pc=%08lx\n",
173 regs->pc);
174 regs->pc = regs->npc;
175 regs->npc += 4;
176 calls++;
177 if(calls > 2)
178 die_if_kernel("Too many Penguin-FPU traps from kernel mode",
179 regs);
180 return;
181 }
182 send_sig(SIGFPE, last_task_used_math, 1);
183 last_task_used_math = NULL;
184 regs->psr &= ~PSR_EF;
185 if(calls > 0)
186 calls=0;
187 }
188
189 void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
190 unsigned long psr)
191 {
192 if(psr & PSR_PS)
193 die_if_kernel("Penguin overflow trap from kernel mode", regs);
194 current->tss.sig_address = pc;
195 current->tss.sig_desc = SUBSIG_TAG;
196 send_sig(SIGEMT, current, 1);
197 }
198
199 void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
200 unsigned long psr)
201 {
202 printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n",
203 pc, npc, psr);
204 if(psr & PSR_PS)
205 panic("Tell me what a watchpoint trap is, and I'll then deal "
206 "with such a beast...");
207 }
208
209 void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
210 unsigned long psr)
211 {
212 printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
213 pc, npc, psr);
214 send_sig(SIGILL, current, 1);
215 }
216
217 void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
218 unsigned long psr)
219 {
220 send_sig(SIGILL, current, 1);
221 }
222
223 void handle_bad_flush(struct pt_regs *regs, unsigned long pc, unsigned long npc,
224 unsigned long psr)
225 {
226 printk("Unimplemented FLUSH Exception at PC %08lx NPC %08lx PSR %08lx\n",
227 pc, npc, psr);
228 send_sig(SIGILL, current, 1);
229 }
230
231 void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
232 unsigned long psr)
233 {
234 printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
235 pc, npc, psr);
236 send_sig(SIGILL, current, 1);
237 }
238
239 void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
240 unsigned long psr)
241 {
242 printk("Divide By Zero Exception at PC %08lx NPC %08lx PSR %08lx\n",
243 pc, npc, psr);
244 send_sig(SIGILL, current, 1);
245 }
246
247
248
249
250
251 extern void sparc_cpu_startup(void);
252
253 extern int linux_num_cpus;
254 extern pgd_t **srmmu_context_table;
255
256 int linux_smp_still_initting;
257 unsigned int thiscpus_tbr;
258 int thiscpus_mid;
259
260 void trap_init(void)
261 {
262 struct linux_prom_registers ctx_reg;
263 int i;
264
265 if(linux_num_cpus == 1) {
266 printk("trap_init: Uniprocessor detected.\n");
267 return;
268 }
269 if(sparc_cpu_model != sun4m) {
270 prom_printf("trap_init: Multiprocessor on a non-sun4m! Aieee...\n");
271 prom_printf("trap_init: Cannot continue, bailing out.\n");
272 prom_halt();
273 }
274
275 prom_printf("trap_init: Multiprocessor detected, initiating CPU-startup. cpus=%d\n",
276 linux_num_cpus);
277 linux_smp_still_initting = 1;
278 ctx_reg.which_io = 0x0;
279 ctx_reg.phys_addr = (char *) (((unsigned long) srmmu_context_table) - PAGE_OFFSET);
280 ctx_reg.reg_size = 0x0;
281
282
283
284
285 for(i=0; i<linux_num_cpus; i++) {
286 if((linux_cpus[i].mid & (~8)) != 0x0) {
287 static int cpuid = 0;
288 cpuid = (linux_cpus[i].mid & (~8));
289 percpu_table[cpuid].cpu_is_alive = 0;
290 thiscpus_mid = linux_cpus[i].mid;
291 thiscpus_tbr = (unsigned int)
292 percpu_table[cpuid].trap_table;
293 prom_startcpu(linux_cpus[i].prom_node, &ctx_reg, 0x0,
294 (char *) sparc_cpu_startup);
295 prom_printf("Waiting for cpu %d to start up...\n", i);
296 while(percpu_table[cpuid].cpu_is_alive == 0) {
297 static int counter = 0;
298 counter++;
299 if(counter>200)
300 break;
301 __delay(200000);
302 }
303 }
304 }
305
306 linux_smp_still_initting = 1;
307 }