patch-2.4.14 linux/arch/ppc/kernel/traps.c
Next file: linux/arch/ppc/kernel/walnut_setup.c
Previous file: linux/arch/ppc/kernel/syscalls.c
Back to the patch index
Back to the overall index
- Lines: 73
- Date:
Fri Nov 2 17:43:54 2001
- Orig file:
v2.4.13/linux/arch/ppc/kernel/traps.c
- Orig date:
Tue Oct 9 17:06:51 2001
diff -u --recursive --new-file v2.4.13/linux/arch/ppc/kernel/traps.c linux/arch/ppc/kernel/traps.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.traps.c 1.19 08/24/01 20:07:37 paulus
+ * BK Id: SCCS/s.traps.c 1.22 10/11/01 10:33:09 paulus
*/
/*
* linux/arch/ppc/kernel/traps.c
@@ -108,6 +108,7 @@
#ifdef CONFIG_ALL_PPC
unsigned long fixup;
#endif /* CONFIG_ALL_PPC */
+ unsigned long msr = regs->msr;
if (user_mode(regs)) {
_exception(SIGSEGV, regs);
@@ -132,31 +133,47 @@
* Check if the NIP corresponds to the address of a sync
* instruction for which there is an entry in the exception
* table.
+ * Note that the 601 only takes a machine check on TEA
+ * (transfer error ack) signal assertion, and does not
+ * set of the top 16 bits of SRR1.
+ * -- paulus.
*/
- if (regs->msr & (0x80000 | 0x40000)
+ if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
&& (fixup = search_exception_table(regs->nip)) != 0) {
/*
- * Check that it's a sync instruction.
+ * Check that it's a sync instruction, or somewhere
+ * in the twi; isync; nop sequence that inb/inw/inl uses.
* As the address is in the exception table
* we should be able to read the instr there.
+ * For the debug message, we look at the preceding
+ * load or store.
*/
- if (*(unsigned int *)regs->nip == 0x7c0004ac) {
- unsigned int lsi = ((unsigned int *)regs->nip)[-1];
- int rb = (lsi >> 11) & 0x1f;
- printk(KERN_DEBUG "%s bad port %lx at %lx\n",
- (lsi & 0x100)? "OUT to": "IN from",
- regs->gpr[rb] - _IO_BASE, regs->nip);
+ unsigned int *nip = (unsigned int *)regs->nip;
+ if (*nip == 0x60000000) /* nop */
+ nip -= 2;
+ else if (*nip == 0x4c00012c) /* isync */
+ --nip;
+ if (*nip == 0x7c0004ac || (*nip >> 26) == 3) {
+ /* sync or twi */
+ unsigned int rb;
+
+ --nip;
+ rb = (*nip >> 11) & 0x1f;
+ printk(KERN_DEBUG "%s bad port %lx at %p\n",
+ (*nip & 0x100)? "OUT to": "IN from",
+ regs->gpr[rb] - _IO_BASE, nip);
regs->nip = fixup;
return;
}
}
#endif /* CONFIG_ALL_PPC */
printk("Machine check in kernel mode.\n");
- printk("Caused by (from SRR1=%lx): ", regs->msr);
- switch (regs->msr & 0xF0000) {
+ printk("Caused by (from SRR1=%lx): ", msr);
+ switch (msr & 0xF0000) {
case 0x80000:
printk("Machine check signal\n");
break;
+ case 0: /* for 601 */
case 0x40000:
printk("Transfer error ack signal\n");
break;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)