summaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/traps.c
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
committerRalf Baechle <ralf@linux-mips.org>1997-09-12 01:29:55 +0000
commit545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch)
treee9ce4bc598d06374bda906f18365984bf22a526a /arch/sparc64/kernel/traps.c
parent4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff)
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'arch/sparc64/kernel/traps.c')
-rw-r--r--arch/sparc64/kernel/traps.c62
1 files changed, 50 insertions, 12 deletions
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c
index ac3e79958..1ffd43730 100644
--- a/arch/sparc64/kernel/traps.c
+++ b/arch/sparc64/kernel/traps.c
@@ -1,4 +1,4 @@
-/* $Id: traps.c,v 1.29 1997/07/05 09:52:38 davem Exp $
+/* $Id: traps.c,v 1.31 1997/08/11 14:35:33 davem Exp $
* arch/sparc64/kernel/traps.c
*
* Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu)
@@ -25,6 +25,7 @@
#include <asm/unistd.h>
#include <asm/uaccess.h>
#include <asm/fpumacro.h>
+#include <asm/lsu.h>
/* #define SYSCALL_TRACING */
/* #define VERBOSE_SYSCALL_TRACING */
@@ -194,8 +195,55 @@ void data_access_exception (struct pt_regs *regs)
send_sig(SIGSEGV, current, 1);
}
+#ifdef CONFIG_PCI
+/* This is really pathetic... */
+/* #define DEBUG_PCI_POKES */
+extern volatile int pci_poke_in_progress;
+extern volatile int pci_poke_faulted;
+#endif
+
void do_dae(struct pt_regs *regs)
{
+#ifdef CONFIG_PCI
+#ifdef DEBUG_PCI_POKES
+ prom_printf(" (POKE ");
+#endif
+ if(pci_poke_in_progress) {
+ unsigned long va;
+#ifdef DEBUG_PCI_POKES
+ prom_printf("tpc[%016lx] tnpc[%016lx] ",
+ regs->tpc, regs->tnpc);
+#endif
+ pci_poke_faulted = 1;
+ regs->tnpc = regs->tpc + 4;
+
+
+#ifdef DEBUG_PCI_POKES
+ prom_printf("PCI) ");
+ /* prom_halt(); */
+#endif
+ /* Re-enable I/D caches, Ultra turned them off. */
+ for(va = 0; va < (PAGE_SIZE << 1); va += 32) {
+ spitfire_put_icache_tag(va, 0x0);
+ spitfire_put_dcache_tag(va, 0x0);
+ }
+ __asm__ __volatile__("flush %%g6\n\t"
+ "membar #Sync\n\t"
+ "stxa %0, [%%g0] %1\n\t"
+ "membar #Sync"
+ : /* no outputs */
+ : "r" (LSU_CONTROL_IC | LSU_CONTROL_DC |
+ LSU_CONTROL_IM | LSU_CONTROL_DM),
+ "i" (ASI_LSU_CONTROL)
+ : "memory");
+ return;
+ }
+#ifdef DEBUG_PCI_POKES
+ prom_printf("USER) ");
+ prom_printf("tpc[%016lx] tnpc[%016lx]\n");
+ prom_halt();
+#endif
+#endif
send_sig(SIGSEGV, current, 1);
}
@@ -215,11 +263,9 @@ void do_fpe_common(struct pt_regs *regs)
regs->tpc = regs->tnpc;
regs->tnpc += 4;
} else {
- lock_kernel();
current->tss.sig_address = regs->tpc;
current->tss.sig_desc = SUBSIG_FPERROR;
send_sig(SIGFPE, current, 1);
- unlock_kernel();
}
}
@@ -288,6 +334,7 @@ void die_if_kernel(char *str, struct pt_regs *regs)
}
printk("Instruction DUMP:");
instruction_dump ((unsigned int *) regs->tpc);
+ lock_kernel(); /* Or else! */
if(regs->tstate & TSTATE_PRIV)
do_exit(SIGKILL);
do_exit(SIGSEGV);
@@ -298,13 +345,11 @@ void do_illegal_instruction(struct pt_regs *regs)
unsigned long pc = regs->tpc;
unsigned long tstate = regs->tstate;
- lock_kernel();
if(tstate & TSTATE_PRIV)
die_if_kernel("Kernel illegal instruction", regs);
current->tss.sig_address = pc;
current->tss.sig_desc = SUBSIG_ILLINST;
send_sig(SIGILL, current, 1);
- unlock_kernel();
}
void mem_address_unaligned(struct pt_regs *regs)
@@ -333,19 +378,16 @@ void do_privact(struct pt_regs *regs)
current->tss.sig_address = regs->tpc;
current->tss.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGILL, current, 1);
- unlock_kernel();
}
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long tstate)
{
- lock_kernel();
if(tstate & TSTATE_PRIV)
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
current->tss.sig_address = pc;
current->tss.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGILL, current, 1);
- unlock_kernel();
}
/* XXX User may want to be allowed to do this. XXX */
@@ -353,7 +395,6 @@ void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long n
void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long tstate)
{
- lock_kernel();
if(regs->tstate & TSTATE_PRIV) {
printk("KERNEL MNA at pc %016lx npc %016lx called by %016lx\n", pc, npc,
regs->u_regs[UREG_RETPC]);
@@ -363,15 +404,12 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon
current->tss.sig_address = pc;
current->tss.sig_desc = SUBSIG_PRIVINST;
send_sig(SIGBUS, current, 1);
- unlock_kernel();
}
void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
- lock_kernel();
send_sig(SIGILL, current, 1);
- unlock_kernel();
}
/* Trap level 1 stuff or other traps we should never see... */