File: /usr/src/linux/arch/ppc/kernel/traps.c

1     /*
2      * BK Id: SCCS/s.traps.c 1.19 08/24/01 20:07:37 paulus
3      */
4     /*
5      *  linux/arch/ppc/kernel/traps.c
6      *
7      *  Copyright (C) 1995-1996  Gary Thomas (gdt@linuxppc.org)
8      *
9      *  This program is free software; you can redistribute it and/or
10      *  modify it under the terms of the GNU General Public License
11      *  as published by the Free Software Foundation; either version
12      *  2 of the License, or (at your option) any later version.
13      *
14      *  Modified by Cort Dougan (cort@cs.nmt.edu)
15      *  and Paul Mackerras (paulus@cs.anu.edu.au)
16      */
17     
18     /*
19      * This file handles the architecture-dependent parts of hardware exceptions
20      */
21     
22     #include <linux/errno.h>
23     #include <linux/sched.h>
24     #include <linux/kernel.h>
25     #include <linux/mm.h>
26     #include <linux/stddef.h>
27     #include <linux/unistd.h>
28     #include <linux/ptrace.h>
29     #include <linux/slab.h>
30     #include <linux/user.h>
31     #include <linux/a.out.h>
32     #include <linux/interrupt.h>
33     #include <linux/config.h>
34     #include <linux/init.h>
35     
36     #include <asm/pgtable.h>
37     #include <asm/uaccess.h>
38     #include <asm/system.h>
39     #include <asm/io.h>
40     #include <asm/processor.h>
41     
42     extern int fix_alignment(struct pt_regs *);
43     extern void bad_page_fault(struct pt_regs *, unsigned long, int sig);
44     
45     #ifdef CONFIG_XMON
46     extern void xmon(struct pt_regs *regs);
47     extern int xmon_bpt(struct pt_regs *regs);
48     extern int xmon_sstep(struct pt_regs *regs);
49     extern int xmon_iabr_match(struct pt_regs *regs);
50     extern int xmon_dabr_match(struct pt_regs *regs);
51     extern void (*xmon_fault_handler)(struct pt_regs *regs);
52     #endif
53     
54     #ifdef CONFIG_XMON
55     void (*debugger)(struct pt_regs *regs) = xmon;
56     int (*debugger_bpt)(struct pt_regs *regs) = xmon_bpt;
57     int (*debugger_sstep)(struct pt_regs *regs) = xmon_sstep;
58     int (*debugger_iabr_match)(struct pt_regs *regs) = xmon_iabr_match;
59     int (*debugger_dabr_match)(struct pt_regs *regs) = xmon_dabr_match;
60     void (*debugger_fault_handler)(struct pt_regs *regs);
61     #else
62     #ifdef CONFIG_KGDB
63     void (*debugger)(struct pt_regs *regs);
64     int (*debugger_bpt)(struct pt_regs *regs);
65     int (*debugger_sstep)(struct pt_regs *regs);
66     int (*debugger_iabr_match)(struct pt_regs *regs);
67     int (*debugger_dabr_match)(struct pt_regs *regs);
68     void (*debugger_fault_handler)(struct pt_regs *regs);
69     #endif
70     #endif
71     
72     /*
73      * Trap & Exception support
74      */
75     
76     
77     spinlock_t oops_lock = SPIN_LOCK_UNLOCKED;
78     
79     void die(const char * str, struct pt_regs * fp, long err)
80     {
81     	console_verbose();
82     	spin_lock_irq(&oops_lock);
83     	printk("Oops: %s, sig: %ld\n", str, err);
84     	show_regs(fp);
85     	spin_unlock_irq(&oops_lock);
86     	/* do_exit() should take care of panic'ing from an interrupt
87     	 * context so we don't handle it here
88     	 */
89     	do_exit(err);
90     }
91     
92     void
93     _exception(int signr, struct pt_regs *regs)
94     {
95     	if (!user_mode(regs))
96     	{
97     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
98     		debugger(regs);
99     #endif
100     		die("Exception in kernel mode", regs, signr);
101     	}
102     	force_sig(signr, current);
103     }
104     
105     void
106     MachineCheckException(struct pt_regs *regs)
107     {
108     #ifdef CONFIG_ALL_PPC
109     	unsigned long fixup;
110     #endif /* CONFIG_ALL_PPC */
111     
112     	if (user_mode(regs)) {
113     		_exception(SIGSEGV, regs);	
114     		return;
115     	}
116     
117     #if defined(CONFIG_8xx) && defined(CONFIG_PCI)
118     	/* the qspan pci read routines can cause machine checks -- Cort */
119     	bad_page_fault(regs, regs->dar, SIGBUS);
120     	return;
121     #endif
122     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
123     	if (debugger_fault_handler) {
124     		debugger_fault_handler(regs);
125     		return;
126     	}
127     #endif
128     
129     #ifdef CONFIG_ALL_PPC
130     	/*
131     	 * I/O accesses can cause machine checks on powermacs.
132     	 * Check if the NIP corresponds to the address of a sync
133     	 * instruction for which there is an entry in the exception
134     	 * table.
135     	 */
136     	if (regs->msr & (0x80000 | 0x40000)
137     	    && (fixup = search_exception_table(regs->nip)) != 0) {
138     		/*
139     		 * Check that it's a sync instruction.
140     		 * As the address is in the exception table
141     		 * we should be able to read the instr there.
142     		 */
143     		if (*(unsigned int *)regs->nip == 0x7c0004ac) {
144     			unsigned int lsi = ((unsigned int *)regs->nip)[-1];
145     			int rb = (lsi >> 11) & 0x1f;
146     			printk(KERN_DEBUG "%s bad port %lx at %lx\n",
147     			       (lsi & 0x100)? "OUT to": "IN from",
148     			       regs->gpr[rb] - _IO_BASE, regs->nip);
149     			regs->nip = fixup;
150     			return;
151     		}
152     	}
153     #endif /* CONFIG_ALL_PPC */
154     	printk("Machine check in kernel mode.\n");
155     	printk("Caused by (from SRR1=%lx): ", regs->msr);
156     	switch (regs->msr & 0xF0000) {
157     	case 0x80000:
158     		printk("Machine check signal\n");
159     		break;
160     	case 0x40000:
161     		printk("Transfer error ack signal\n");
162     		break;
163     	case 0x20000:
164     		printk("Data parity error signal\n");
165     		break;
166     	case 0x10000:
167     		printk("Address parity error signal\n");
168     		break;
169     	default:
170     		printk("Unknown values in msr\n");
171     	}
172     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
173     	debugger(regs);
174     #endif
175     	die("machine check", regs, SIGBUS);
176     }
177     
178     void
179     SMIException(struct pt_regs *regs)
180     {
181     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
182     	{
183     		debugger(regs);
184     		return;
185     	}
186     #endif
187     	show_regs(regs);
188     	panic("System Management Interrupt");
189     }
190     
191     void
192     UnknownException(struct pt_regs *regs)
193     {
194     	printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
195     	       regs->nip, regs->msr, regs->trap);
196     	_exception(SIGTRAP, regs);	
197     }
198     
199     void
200     InstructionBreakpoint(struct pt_regs *regs)
201     {
202     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
203     	if (debugger_iabr_match(regs))
204     		return;
205     #endif
206     	_exception(SIGTRAP, regs);
207     }
208     
209     void
210     RunModeException(struct pt_regs *regs)
211     {
212     	_exception(SIGTRAP, regs);	
213     }
214     
215     /* Illegal instruction emulation support.  Originally written to
216      * provide the PVR to user applications using the mfspr rd, PVR.
217      * Return non-zero if we can't emulate, or EFAULT if the associated
218      * memory access caused an access fault.  Return zero on success.
219      *
220      * There are a couple of ways to do this, either "decode" the instruction
221      * or directly match lots of bits.  In this case, matching lots of
222      * bits is faster and easier.
223      *
224      */
225     #define INST_MFSPR_PVR		0x7c1f42a6
226     #define INST_MFSPR_PVR_MASK	0xfc1fffff
227     
228     static int
229     emulate_instruction(struct pt_regs *regs)
230     {
231     	uint    instword;
232     	uint    rd;
233     	uint    retval;
234     
235     	retval = EINVAL;
236     
237     	if (!user_mode(regs))
238     		return retval;
239     
240     	if (get_user(instword, (uint *)(regs->nip)))
241     		return -EFAULT;
242     
243     	/* Emulate the mfspr rD, PVR.
244     	 */
245     	if ((instword & INST_MFSPR_PVR_MASK) == INST_MFSPR_PVR) {
246     		rd = (instword >> 21) & 0x1f;
247     		regs->gpr[rd] = mfspr(PVR);
248     		retval = 0;
249     	}
250     	if (retval == 0)
251     		regs->nip += 4;
252     	return(retval);
253     }
254     
255     void
256     ProgramCheckException(struct pt_regs *regs)
257     {
258     #if defined(CONFIG_4xx)
259     	unsigned int esr = mfspr(SPRN_ESR);
260     
261     	if (esr & ESR_PTR) {
262     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
263     		if (debugger_bpt(regs))
264     			return;
265     #endif
266     		_exception(SIGTRAP, regs);
267     	} else {
268     		_exception(SIGILL, regs);
269     	}
270     #else
271     	if (regs->msr & 0x100000) {
272     		/* IEEE FP exception */
273     		_exception(SIGFPE, regs);
274     	} else if (regs->msr & 0x20000) {
275     		/* trap exception */
276     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
277     		if (debugger_bpt(regs))
278     			return;
279     #endif
280     		_exception(SIGTRAP, regs);
281     	} else {
282     		/* Try to emulate it if we should. */
283     		int errcode;
284     		if ((errcode = emulate_instruction(regs))) {
285     			if (errcode == -EFAULT)
286     				_exception(SIGBUS, regs);
287     			else
288     				_exception(SIGILL, regs);
289     		}
290     	}
291     #endif
292     }
293     
294     void
295     SingleStepException(struct pt_regs *regs)
296     {
297     	regs->msr &= ~MSR_SE;  /* Turn off 'trace' bit */
298     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
299     	if (debugger_sstep(regs))
300     		return;
301     #endif
302     	_exception(SIGTRAP, regs);	
303     }
304     
305     void
306     AlignmentException(struct pt_regs *regs)
307     {
308     	int fixed;
309     
310     	fixed = fix_alignment(regs);
311     	if (fixed == 1) {
312     		regs->nip += 4;	/* skip over emulated instruction */
313     		return;
314     	}
315     	if (fixed == -EFAULT) {
316     		/* fixed == -EFAULT means the operand address was bad */
317     		if (user_mode(regs))
318     			force_sig(SIGSEGV, current);
319     		else
320     			bad_page_fault(regs, regs->dar, SIGSEGV);
321     		return;
322     	}
323     	_exception(SIGBUS, regs);	
324     }
325     
326     void
327     StackOverflow(struct pt_regs *regs)
328     {
329     	printk(KERN_CRIT "Kernel stack overflow in process %p, r1=%lx\n",
330     	       current, regs->gpr[1]);
331     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
332     	debugger(regs);
333     #endif
334     	show_regs(regs);
335     	panic("kernel stack overflow");
336     }
337     
338     void
339     trace_syscall(struct pt_regs *regs)
340     {
341     	printk("Task: %p(%d), PC: %08lX/%08lX, Syscall: %3ld, Result: %s%ld\n",
342     	       current, current->pid, regs->nip, regs->link, regs->gpr[0],
343     	       regs->ccr&0x10000000?"Error=":"", regs->gpr[3]);
344     }
345     
346     #ifdef CONFIG_8xx
347     void
348     SoftwareEmulation(struct pt_regs *regs)
349     {
350     	extern int do_mathemu(struct pt_regs *);
351     	int errcode;
352     
353     	if (!user_mode(regs)) {
354     #if defined(CONFIG_XMON) || defined(CONFIG_KGDB)
355     		debugger(regs);
356     #endif
357     		die("Kernel Mode Software FPU Emulation", regs, SIGFPE);
358     	}
359     
360     #ifdef CONFIG_MATH_EMULATION
361     	if ((errcode = do_mathemu(regs))) {
362     #else
363     	if ((errcode = Soft_emulate_8xx(regs))) {
364     #endif
365     		if (errcode > 0)
366     			_exception(SIGFPE, regs);
367     		else if (errcode == -EFAULT)
368     			_exception(SIGSEGV, regs);
369     		else
370     			_exception(SIGILL, regs);
371     	}
372     }
373     #endif
374     
375     #if !defined(CONFIG_TAU_INT)
376     void
377     TAUException(struct pt_regs *regs)
378     {
379     	printk("TAU trap at PC: %lx, SR: %lx, vector=%lx\n",
380     	       regs->nip, regs->msr, regs->trap);
381     }
382     #endif /* CONFIG_INT_TAU */
383     
384     void __init trap_init(void)
385     {
386     }
387