patch-2.3.41 linux/arch/sparc/kernel/traps.c
Next file: linux/arch/sparc/kernel/unaligned.c
Previous file: linux/arch/sparc/kernel/time.c
Back to the patch index
Back to the overall index
- Lines: 260
- Date:
Fri Jan 21 18:22:54 2000
- Orig file:
v2.3.40/linux/arch/sparc/kernel/traps.c
- Orig date:
Tue Aug 31 17:29:13 1999
diff -u --recursive --new-file v2.3.40/linux/arch/sparc/kernel/traps.c linux/arch/sparc/kernel/traps.c
@@ -1,7 +1,8 @@
-/* $Id: traps.c,v 1.60 1999/08/14 03:51:31 anton Exp $
+/* $Id: traps.c,v 1.61 2000/01/21 11:38:41 jj Exp $
* arch/sparc/kernel/traps.c
*
* Copyright 1995 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright 2000 Jakub Jelinek (jakub@redhat.com)
*/
/*
@@ -128,6 +129,8 @@
void do_hw_interrupt(unsigned long type, unsigned long psr, unsigned long pc)
{
+ siginfo_t info;
+
lock_kernel();
if(type < 0x80) {
/* Sun OS's puke from bad traps, Linux survives! */
@@ -135,22 +138,23 @@
die_if_kernel("Whee... Hello Mr. Penguin", current->thread.kregs);
}
- if(type == SP_TRAP_SBPT) {
- send_sig(SIGTRAP, current, 1);
- } else {
- if(psr & PSR_PS)
- die_if_kernel("Kernel bad trap", current->thread.kregs);
+ if(psr & PSR_PS)
+ die_if_kernel("Kernel bad trap", current->thread.kregs);
- current->thread.sig_desc = SUBSIG_BADTRAP(type - 0x80);
- current->thread.sig_address = pc;
- send_sig(SIGILL, current, 1);
- }
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLTRP;
+ info.si_addr = (void *)pc;
+ info.si_trapno = type - 0x80;
+ force_sig_info(SIGILL, &info, current);
unlock_kernel();
}
void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(psr & PSR_PS)
die_if_kernel("Kernel illegal instruction", regs);
@@ -163,9 +167,12 @@
if (!do_user_muldiv (regs, pc))
goto out;
}
- current->thread.sig_address = pc;
- current->thread.sig_desc = SUBSIG_ILLINST;
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_ILLOPC;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGILL, &info, current);
out:
unlock_kernel();
}
@@ -173,12 +180,17 @@
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(psr & PSR_PS)
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
- current->thread.sig_address = pc;
- current->thread.sig_desc = SUBSIG_PRIVINST;
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_PRVOPC;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGILL, &info, current);
unlock_kernel();
}
@@ -187,6 +199,8 @@
void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(regs->psr & PSR_PS) {
printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
@@ -194,14 +208,17 @@
die_if_kernel("BOGUS", regs);
/* die_if_kernel("Kernel MNA access", regs); */
}
- current->thread.sig_address = pc;
- current->thread.sig_desc = SUBSIG_PRIVINST;
#if 0
show_regs (regs);
instruction_dump ((unsigned long *) regs->pc);
printk ("do_MNA!\n");
#endif
- send_sig(SIGBUS, current, 1);
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRALN;
+ info.si_addr = /* FIXME: Should dig out mna address */ (void *)0;
+ info.si_trapno = 0;
+ send_sig_info(SIGBUS, &info, current);
unlock_kernel();
}
@@ -269,6 +286,8 @@
unsigned long psr)
{
static int calls = 0;
+ siginfo_t info;
+ unsigned long fsr;
int ret = 0;
#ifndef __SMP__
struct task_struct *fpt = last_task_used_math;
@@ -326,8 +345,6 @@
}
/* nope, better SIGFPE the offending process... */
- fpt->thread.sig_address = pc;
- fpt->thread.sig_desc = SUBSIG_FPERROR; /* as good as any */
#ifdef __SMP__
fpt->flags &= ~PF_USEDFPU;
#endif
@@ -345,7 +362,26 @@
regs);
goto out;
}
- send_sig(SIGFPE, fpt, 1);
+
+ fsr = fpt->thread.fsr;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ info.si_code = __SI_FAULT;
+ if ((fsr & 0x1c000) == (1 << 14)) {
+ if (fsr & 0x10)
+ info.si_code = FPE_FLTINV;
+ else if (fsr & 0x08)
+ info.si_code = FPE_FLTOVF;
+ else if (fsr & 0x04)
+ info.si_code = FPE_FLTUND;
+ else if (fsr & 0x02)
+ info.si_code = FPE_FLTDIV;
+ else if (fsr & 0x01)
+ info.si_code = FPE_FLTRES;
+ }
+ send_sig_info(SIGFPE, &info, fpt);
#ifndef __SMP__
last_task_used_math = NULL;
#endif
@@ -359,12 +395,17 @@
void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
if(psr & PSR_PS)
die_if_kernel("Penguin overflow trap from kernel mode", regs);
- current->thread.sig_address = pc;
- current->thread.sig_desc = SUBSIG_TAG; /* as good as any */
- send_sig(SIGEMT, current, 1);
+ info.si_signo = SIGEMT;
+ info.si_errno = 0;
+ info.si_code = EMT_TAGOVF;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGEMT, &info, current);
unlock_kernel();
}
@@ -385,40 +426,69 @@
void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
#ifdef TRAP_DEBUG
printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
pc, npc, psr);
#endif
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_OBJERR;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ force_sig_info(SIGBUS, &info, current);
unlock_kernel();
}
void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGILL, &info, current);
unlock_kernel();
}
void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
#ifdef TRAP_DEBUG
printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
pc, npc, psr);
#endif
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGILL;
+ info.si_errno = 0;
+ info.si_code = ILL_COPROC;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGILL, &info, current);
unlock_kernel();
}
void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
unsigned long psr)
{
+ siginfo_t info;
+
lock_kernel();
- send_sig(SIGILL, current, 1);
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = FPE_INTDIV;
+ info.si_addr = (void *)pc;
+ info.si_trapno = 0;
+ send_sig_info(SIGFPE, &info, current);
+
unlock_kernel();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)