1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * arch/sparc/kernel/traps.c
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright 1995, 2008 David S. Miller (davem@davemloft.net)
6*4882a593Smuzhiyun * Copyright 2000 Jakub Jelinek (jakub@redhat.com)
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun
9*4882a593Smuzhiyun /*
10*4882a593Smuzhiyun * I hate traps on the sparc, grrr...
11*4882a593Smuzhiyun */
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/sched/mm.h>
14*4882a593Smuzhiyun #include <linux/sched/debug.h>
15*4882a593Smuzhiyun #include <linux/mm_types.h>
16*4882a593Smuzhiyun #include <linux/kernel.h>
17*4882a593Smuzhiyun #include <linux/signal.h>
18*4882a593Smuzhiyun #include <linux/smp.h>
19*4882a593Smuzhiyun #include <linux/kdebug.h>
20*4882a593Smuzhiyun #include <linux/export.h>
21*4882a593Smuzhiyun #include <linux/pgtable.h>
22*4882a593Smuzhiyun
23*4882a593Smuzhiyun #include <asm/delay.h>
24*4882a593Smuzhiyun #include <asm/ptrace.h>
25*4882a593Smuzhiyun #include <asm/oplib.h>
26*4882a593Smuzhiyun #include <asm/page.h>
27*4882a593Smuzhiyun #include <asm/unistd.h>
28*4882a593Smuzhiyun #include <asm/traps.h>
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include "entry.h"
31*4882a593Smuzhiyun #include "kernel.h"
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun /* #define TRAP_DEBUG */
34*4882a593Smuzhiyun
instruction_dump(unsigned long * pc)35*4882a593Smuzhiyun static void instruction_dump(unsigned long *pc)
36*4882a593Smuzhiyun {
37*4882a593Smuzhiyun int i;
38*4882a593Smuzhiyun
39*4882a593Smuzhiyun if((((unsigned long) pc) & 3))
40*4882a593Smuzhiyun return;
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun for(i = -3; i < 6; i++)
43*4882a593Smuzhiyun printk("%c%08lx%c",i?' ':'<',pc[i],i?' ':'>');
44*4882a593Smuzhiyun printk("\n");
45*4882a593Smuzhiyun }
46*4882a593Smuzhiyun
47*4882a593Smuzhiyun #define __SAVE __asm__ __volatile__("save %sp, -0x40, %sp\n\t")
48*4882a593Smuzhiyun #define __RESTORE __asm__ __volatile__("restore %g0, %g0, %g0\n\t")
49*4882a593Smuzhiyun
die_if_kernel(char * str,struct pt_regs * regs)50*4882a593Smuzhiyun void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
51*4882a593Smuzhiyun {
52*4882a593Smuzhiyun static int die_counter;
53*4882a593Smuzhiyun int count = 0;
54*4882a593Smuzhiyun
55*4882a593Smuzhiyun /* Amuse the user. */
56*4882a593Smuzhiyun printk(
57*4882a593Smuzhiyun " \\|/ ____ \\|/\n"
58*4882a593Smuzhiyun " \"@'/ ,. \\`@\"\n"
59*4882a593Smuzhiyun " /_| \\__/ |_\\\n"
60*4882a593Smuzhiyun " \\__U_/\n");
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun printk("%s(%d): %s [#%d]\n", current->comm, task_pid_nr(current), str, ++die_counter);
63*4882a593Smuzhiyun show_regs(regs);
64*4882a593Smuzhiyun add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun __SAVE; __SAVE; __SAVE; __SAVE;
67*4882a593Smuzhiyun __SAVE; __SAVE; __SAVE; __SAVE;
68*4882a593Smuzhiyun __RESTORE; __RESTORE; __RESTORE; __RESTORE;
69*4882a593Smuzhiyun __RESTORE; __RESTORE; __RESTORE; __RESTORE;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun struct reg_window32 *rw = (struct reg_window32 *)regs->u_regs[UREG_FP];
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun /* Stop the back trace when we hit userland or we
75*4882a593Smuzhiyun * find some badly aligned kernel stack. Set an upper
76*4882a593Smuzhiyun * bound in case our stack is trashed and we loop.
77*4882a593Smuzhiyun */
78*4882a593Smuzhiyun while(rw &&
79*4882a593Smuzhiyun count++ < 30 &&
80*4882a593Smuzhiyun (((unsigned long) rw) >= PAGE_OFFSET) &&
81*4882a593Smuzhiyun !(((unsigned long) rw) & 0x7)) {
82*4882a593Smuzhiyun printk("Caller[%08lx]: %pS\n", rw->ins[7],
83*4882a593Smuzhiyun (void *) rw->ins[7]);
84*4882a593Smuzhiyun rw = (struct reg_window32 *)rw->ins[6];
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun }
87*4882a593Smuzhiyun printk("Instruction DUMP:");
88*4882a593Smuzhiyun instruction_dump ((unsigned long *) regs->pc);
89*4882a593Smuzhiyun if(regs->psr & PSR_PS)
90*4882a593Smuzhiyun do_exit(SIGKILL);
91*4882a593Smuzhiyun do_exit(SIGSEGV);
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun
do_hw_interrupt(struct pt_regs * regs,unsigned long type)94*4882a593Smuzhiyun void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun if(type < 0x80) {
97*4882a593Smuzhiyun /* Sun OS's puke from bad traps, Linux survives! */
98*4882a593Smuzhiyun printk("Unimplemented Sparc TRAP, type = %02lx\n", type);
99*4882a593Smuzhiyun die_if_kernel("Whee... Hello Mr. Penguin", regs);
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun if(regs->psr & PSR_PS)
103*4882a593Smuzhiyun die_if_kernel("Kernel bad trap", regs);
104*4882a593Smuzhiyun
105*4882a593Smuzhiyun force_sig_fault(SIGILL, ILL_ILLTRP,
106*4882a593Smuzhiyun (void __user *)regs->pc, type - 0x80);
107*4882a593Smuzhiyun }
108*4882a593Smuzhiyun
do_illegal_instruction(struct pt_regs * regs,unsigned long pc,unsigned long npc,unsigned long psr)109*4882a593Smuzhiyun void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
110*4882a593Smuzhiyun unsigned long psr)
111*4882a593Smuzhiyun {
112*4882a593Smuzhiyun if(psr & PSR_PS)
113*4882a593Smuzhiyun die_if_kernel("Kernel illegal instruction", regs);
114*4882a593Smuzhiyun #ifdef TRAP_DEBUG
115*4882a593Smuzhiyun printk("Ill instr. at pc=%08lx instruction is %08lx\n",
116*4882a593Smuzhiyun regs->pc, *(unsigned long *)regs->pc);
117*4882a593Smuzhiyun #endif
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc, 0, current);
120*4882a593Smuzhiyun }
121*4882a593Smuzhiyun
do_priv_instruction(struct pt_regs * regs,unsigned long pc,unsigned long npc,unsigned long psr)122*4882a593Smuzhiyun void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
123*4882a593Smuzhiyun unsigned long psr)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun if(psr & PSR_PS)
126*4882a593Smuzhiyun die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
127*4882a593Smuzhiyun send_sig_fault(SIGILL, ILL_PRVOPC, (void __user *)pc, 0, current);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun /* XXX User may want to be allowed to do this. XXX */
131*4882a593Smuzhiyun
do_memaccess_unaligned(struct pt_regs * regs,unsigned long pc,unsigned long npc,unsigned long psr)132*4882a593Smuzhiyun void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
133*4882a593Smuzhiyun unsigned long psr)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun if(regs->psr & PSR_PS) {
136*4882a593Smuzhiyun printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
137*4882a593Smuzhiyun regs->u_regs[UREG_RETPC]);
138*4882a593Smuzhiyun die_if_kernel("BOGUS", regs);
139*4882a593Smuzhiyun /* die_if_kernel("Kernel MNA access", regs); */
140*4882a593Smuzhiyun }
141*4882a593Smuzhiyun #if 0
142*4882a593Smuzhiyun show_regs (regs);
143*4882a593Smuzhiyun instruction_dump ((unsigned long *) regs->pc);
144*4882a593Smuzhiyun printk ("do_MNA!\n");
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun send_sig_fault(SIGBUS, BUS_ADRALN,
147*4882a593Smuzhiyun /* FIXME: Should dig out mna address */ (void *)0,
148*4882a593Smuzhiyun 0, current);
149*4882a593Smuzhiyun }
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun static unsigned long init_fsr = 0x0UL;
152*4882a593Smuzhiyun static unsigned long init_fregs[32] __attribute__ ((aligned (8))) =
153*4882a593Smuzhiyun { ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
154*4882a593Smuzhiyun ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
155*4882a593Smuzhiyun ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL,
156*4882a593Smuzhiyun ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL, ~0UL };
157*4882a593Smuzhiyun
do_fpd_trap(struct pt_regs * regs,unsigned long pc,unsigned long npc,unsigned long psr)158*4882a593Smuzhiyun void do_fpd_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
159*4882a593Smuzhiyun unsigned long psr)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun /* Sanity check... */
162*4882a593Smuzhiyun if(psr & PSR_PS)
163*4882a593Smuzhiyun die_if_kernel("Kernel gets FloatingPenguinUnit disabled trap", regs);
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun put_psr(get_psr() | PSR_EF); /* Allow FPU ops. */
166*4882a593Smuzhiyun regs->psr |= PSR_EF;
167*4882a593Smuzhiyun #ifndef CONFIG_SMP
168*4882a593Smuzhiyun if(last_task_used_math == current)
169*4882a593Smuzhiyun return;
170*4882a593Smuzhiyun if(last_task_used_math) {
171*4882a593Smuzhiyun /* Other processes fpu state, save away */
172*4882a593Smuzhiyun struct task_struct *fptask = last_task_used_math;
173*4882a593Smuzhiyun fpsave(&fptask->thread.float_regs[0], &fptask->thread.fsr,
174*4882a593Smuzhiyun &fptask->thread.fpqueue[0], &fptask->thread.fpqdepth);
175*4882a593Smuzhiyun }
176*4882a593Smuzhiyun last_task_used_math = current;
177*4882a593Smuzhiyun if(used_math()) {
178*4882a593Smuzhiyun fpload(¤t->thread.float_regs[0], ¤t->thread.fsr);
179*4882a593Smuzhiyun } else {
180*4882a593Smuzhiyun /* Set initial sane state. */
181*4882a593Smuzhiyun fpload(&init_fregs[0], &init_fsr);
182*4882a593Smuzhiyun set_used_math();
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun #else
185*4882a593Smuzhiyun if(!used_math()) {
186*4882a593Smuzhiyun fpload(&init_fregs[0], &init_fsr);
187*4882a593Smuzhiyun set_used_math();
188*4882a593Smuzhiyun } else {
189*4882a593Smuzhiyun fpload(¤t->thread.float_regs[0], ¤t->thread.fsr);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun set_thread_flag(TIF_USEDFPU);
192*4882a593Smuzhiyun #endif
193*4882a593Smuzhiyun }
194*4882a593Smuzhiyun
195*4882a593Smuzhiyun static unsigned long fake_regs[32] __attribute__ ((aligned (8)));
196*4882a593Smuzhiyun static unsigned long fake_fsr;
197*4882a593Smuzhiyun static unsigned long fake_queue[32] __attribute__ ((aligned (8)));
198*4882a593Smuzhiyun static unsigned long fake_depth;
199*4882a593Smuzhiyun
do_fpe_trap(struct pt_regs * regs,unsigned long pc,unsigned long npc,unsigned long psr)200*4882a593Smuzhiyun void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
201*4882a593Smuzhiyun unsigned long psr)
202*4882a593Smuzhiyun {
203*4882a593Smuzhiyun static int calls;
204*4882a593Smuzhiyun unsigned long fsr;
205*4882a593Smuzhiyun int ret = 0;
206*4882a593Smuzhiyun int code;
207*4882a593Smuzhiyun #ifndef CONFIG_SMP
208*4882a593Smuzhiyun struct task_struct *fpt = last_task_used_math;
209*4882a593Smuzhiyun #else
210*4882a593Smuzhiyun struct task_struct *fpt = current;
211*4882a593Smuzhiyun #endif
212*4882a593Smuzhiyun put_psr(get_psr() | PSR_EF);
213*4882a593Smuzhiyun /* If nobody owns the fpu right now, just clear the
214*4882a593Smuzhiyun * error into our fake static buffer and hope it don't
215*4882a593Smuzhiyun * happen again. Thank you crashme...
216*4882a593Smuzhiyun */
217*4882a593Smuzhiyun #ifndef CONFIG_SMP
218*4882a593Smuzhiyun if(!fpt) {
219*4882a593Smuzhiyun #else
220*4882a593Smuzhiyun if (!test_tsk_thread_flag(fpt, TIF_USEDFPU)) {
221*4882a593Smuzhiyun #endif
222*4882a593Smuzhiyun fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth);
223*4882a593Smuzhiyun regs->psr &= ~PSR_EF;
224*4882a593Smuzhiyun return;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun fpsave(&fpt->thread.float_regs[0], &fpt->thread.fsr,
227*4882a593Smuzhiyun &fpt->thread.fpqueue[0], &fpt->thread.fpqdepth);
228*4882a593Smuzhiyun #ifdef DEBUG_FPU
229*4882a593Smuzhiyun printk("Hmm, FP exception, fsr was %016lx\n", fpt->thread.fsr);
230*4882a593Smuzhiyun #endif
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun switch ((fpt->thread.fsr & 0x1c000)) {
233*4882a593Smuzhiyun /* switch on the contents of the ftt [floating point trap type] field */
234*4882a593Smuzhiyun #ifdef DEBUG_FPU
235*4882a593Smuzhiyun case (1 << 14):
236*4882a593Smuzhiyun printk("IEEE_754_exception\n");
237*4882a593Smuzhiyun break;
238*4882a593Smuzhiyun #endif
239*4882a593Smuzhiyun case (2 << 14): /* unfinished_FPop (underflow & co) */
240*4882a593Smuzhiyun case (3 << 14): /* unimplemented_FPop (quad stuff, maybe sqrt) */
241*4882a593Smuzhiyun ret = do_mathemu(regs, fpt);
242*4882a593Smuzhiyun break;
243*4882a593Smuzhiyun #ifdef DEBUG_FPU
244*4882a593Smuzhiyun case (4 << 14):
245*4882a593Smuzhiyun printk("sequence_error (OS bug...)\n");
246*4882a593Smuzhiyun break;
247*4882a593Smuzhiyun case (5 << 14):
248*4882a593Smuzhiyun printk("hardware_error (uhoh!)\n");
249*4882a593Smuzhiyun break;
250*4882a593Smuzhiyun case (6 << 14):
251*4882a593Smuzhiyun printk("invalid_fp_register (user error)\n");
252*4882a593Smuzhiyun break;
253*4882a593Smuzhiyun #endif /* DEBUG_FPU */
254*4882a593Smuzhiyun }
255*4882a593Smuzhiyun /* If we successfully emulated the FPop, we pretend the trap never happened :-> */
256*4882a593Smuzhiyun if (ret) {
257*4882a593Smuzhiyun fpload(¤t->thread.float_regs[0], ¤t->thread.fsr);
258*4882a593Smuzhiyun return;
259*4882a593Smuzhiyun }
260*4882a593Smuzhiyun /* nope, better SIGFPE the offending process... */
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun #ifdef CONFIG_SMP
263*4882a593Smuzhiyun clear_tsk_thread_flag(fpt, TIF_USEDFPU);
264*4882a593Smuzhiyun #endif
265*4882a593Smuzhiyun if(psr & PSR_PS) {
266*4882a593Smuzhiyun /* The first fsr store/load we tried trapped,
267*4882a593Smuzhiyun * the second one will not (we hope).
268*4882a593Smuzhiyun */
269*4882a593Smuzhiyun printk("WARNING: FPU exception from kernel mode. at pc=%08lx\n",
270*4882a593Smuzhiyun regs->pc);
271*4882a593Smuzhiyun regs->pc = regs->npc;
272*4882a593Smuzhiyun regs->npc += 4;
273*4882a593Smuzhiyun calls++;
274*4882a593Smuzhiyun if(calls > 2)
275*4882a593Smuzhiyun die_if_kernel("Too many Penguin-FPU traps from kernel mode",
276*4882a593Smuzhiyun regs);
277*4882a593Smuzhiyun return;
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun fsr = fpt->thread.fsr;
281*4882a593Smuzhiyun code = FPE_FLTUNK;
282*4882a593Smuzhiyun if ((fsr & 0x1c000) == (1 << 14)) {
283*4882a593Smuzhiyun if (fsr & 0x10)
284*4882a593Smuzhiyun code = FPE_FLTINV;
285*4882a593Smuzhiyun else if (fsr & 0x08)
286*4882a593Smuzhiyun code = FPE_FLTOVF;
287*4882a593Smuzhiyun else if (fsr & 0x04)
288*4882a593Smuzhiyun code = FPE_FLTUND;
289*4882a593Smuzhiyun else if (fsr & 0x02)
290*4882a593Smuzhiyun code = FPE_FLTDIV;
291*4882a593Smuzhiyun else if (fsr & 0x01)
292*4882a593Smuzhiyun code = FPE_FLTRES;
293*4882a593Smuzhiyun }
294*4882a593Smuzhiyun send_sig_fault(SIGFPE, code, (void __user *)pc, 0, fpt);
295*4882a593Smuzhiyun #ifndef CONFIG_SMP
296*4882a593Smuzhiyun last_task_used_math = NULL;
297*4882a593Smuzhiyun #endif
298*4882a593Smuzhiyun regs->psr &= ~PSR_EF;
299*4882a593Smuzhiyun if(calls > 0)
300*4882a593Smuzhiyun calls=0;
301*4882a593Smuzhiyun }
302*4882a593Smuzhiyun
303*4882a593Smuzhiyun void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
304*4882a593Smuzhiyun unsigned long psr)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun if(psr & PSR_PS)
307*4882a593Smuzhiyun die_if_kernel("Penguin overflow trap from kernel mode", regs);
308*4882a593Smuzhiyun send_sig_fault(SIGEMT, EMT_TAGOVF, (void __user *)pc, 0, current);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
312*4882a593Smuzhiyun unsigned long psr)
313*4882a593Smuzhiyun {
314*4882a593Smuzhiyun #ifdef TRAP_DEBUG
315*4882a593Smuzhiyun printk("Watchpoint detected at PC %08lx NPC %08lx PSR %08lx\n",
316*4882a593Smuzhiyun pc, npc, psr);
317*4882a593Smuzhiyun #endif
318*4882a593Smuzhiyun if(psr & PSR_PS)
319*4882a593Smuzhiyun panic("Tell me what a watchpoint trap is, and I'll then deal "
320*4882a593Smuzhiyun "with such a beast...");
321*4882a593Smuzhiyun }
322*4882a593Smuzhiyun
323*4882a593Smuzhiyun void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
324*4882a593Smuzhiyun unsigned long psr)
325*4882a593Smuzhiyun {
326*4882a593Smuzhiyun #ifdef TRAP_DEBUG
327*4882a593Smuzhiyun printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
328*4882a593Smuzhiyun pc, npc, psr);
329*4882a593Smuzhiyun #endif
330*4882a593Smuzhiyun force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)pc, 0);
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
334*4882a593Smuzhiyun unsigned long psr)
335*4882a593Smuzhiyun {
336*4882a593Smuzhiyun send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, 0, current);
337*4882a593Smuzhiyun }
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
340*4882a593Smuzhiyun unsigned long psr)
341*4882a593Smuzhiyun {
342*4882a593Smuzhiyun #ifdef TRAP_DEBUG
343*4882a593Smuzhiyun printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
344*4882a593Smuzhiyun pc, npc, psr);
345*4882a593Smuzhiyun #endif
346*4882a593Smuzhiyun send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, 0, current);
347*4882a593Smuzhiyun }
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
350*4882a593Smuzhiyun unsigned long psr)
351*4882a593Smuzhiyun {
352*4882a593Smuzhiyun send_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)pc, 0, current);
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun
355*4882a593Smuzhiyun #ifdef CONFIG_DEBUG_BUGVERBOSE
356*4882a593Smuzhiyun void do_BUG(const char *file, int line)
357*4882a593Smuzhiyun {
358*4882a593Smuzhiyun // bust_spinlocks(1); XXX Not in our original BUG()
359*4882a593Smuzhiyun printk("kernel BUG at %s:%d!\n", file, line);
360*4882a593Smuzhiyun }
361*4882a593Smuzhiyun EXPORT_SYMBOL(do_BUG);
362*4882a593Smuzhiyun #endif
363*4882a593Smuzhiyun
364*4882a593Smuzhiyun /* Since we have our mappings set up, on multiprocessors we can spin them
365*4882a593Smuzhiyun * up here so that timer interrupts work during initialization.
366*4882a593Smuzhiyun */
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun void trap_init(void)
369*4882a593Smuzhiyun {
370*4882a593Smuzhiyun extern void thread_info_offsets_are_bolixed_pete(void);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /* Force linker to barf if mismatched */
373*4882a593Smuzhiyun if (TI_UWINMASK != offsetof(struct thread_info, uwinmask) ||
374*4882a593Smuzhiyun TI_TASK != offsetof(struct thread_info, task) ||
375*4882a593Smuzhiyun TI_FLAGS != offsetof(struct thread_info, flags) ||
376*4882a593Smuzhiyun TI_CPU != offsetof(struct thread_info, cpu) ||
377*4882a593Smuzhiyun TI_PREEMPT != offsetof(struct thread_info, preempt_count) ||
378*4882a593Smuzhiyun TI_SOFTIRQ != offsetof(struct thread_info, softirq_count) ||
379*4882a593Smuzhiyun TI_HARDIRQ != offsetof(struct thread_info, hardirq_count) ||
380*4882a593Smuzhiyun TI_KSP != offsetof(struct thread_info, ksp) ||
381*4882a593Smuzhiyun TI_KPC != offsetof(struct thread_info, kpc) ||
382*4882a593Smuzhiyun TI_KPSR != offsetof(struct thread_info, kpsr) ||
383*4882a593Smuzhiyun TI_KWIM != offsetof(struct thread_info, kwim) ||
384*4882a593Smuzhiyun TI_REG_WINDOW != offsetof(struct thread_info, reg_window) ||
385*4882a593Smuzhiyun TI_RWIN_SPTRS != offsetof(struct thread_info, rwbuf_stkptrs) ||
386*4882a593Smuzhiyun TI_W_SAVED != offsetof(struct thread_info, w_saved))
387*4882a593Smuzhiyun thread_info_offsets_are_bolixed_pete();
388*4882a593Smuzhiyun
389*4882a593Smuzhiyun /* Attach to the address space of init_task. */
390*4882a593Smuzhiyun mmgrab(&init_mm);
391*4882a593Smuzhiyun current->active_mm = &init_mm;
392*4882a593Smuzhiyun
393*4882a593Smuzhiyun /* NOTE: Other cpus have this done as they are started
394*4882a593Smuzhiyun * up on SMP.
395*4882a593Smuzhiyun */
396*4882a593Smuzhiyun }
397