Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull siginfo updates from Eric Biederman: "This set of changes close the known issues with setting si_code to an invalid value, and with not fully initializing struct siginfo. There remains work to do on nds32, arc, unicore32, powerpc, arm, arm64, ia64 and x86 to get the code that generates siginfo into a simpler and more maintainable state. Most of that work involves refactoring the signal handling code and thus careful code review. Also not included is the work to shrink the in kernel version of struct siginfo. That depends on getting the number of places that directly manipulate struct siginfo under control, as it requires the introduction of struct kernel_siginfo for the in kernel things. Overall this set of changes looks like it is making good progress, and with a little luck I will be wrapping up the siginfo work next development cycle" * 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: (46 commits) signal/sh: Stop gcc warning about an impossible case in do_divide_error signal/mips: Report FPE_FLTUNK for undiagnosed floating point exceptions signal/um: More carefully relay signals in relay_signal. signal: Extend siginfo_layout with SIL_FAULT_{MCEERR|BNDERR|PKUERR} signal: Remove unncessary #ifdef SEGV_PKUERR in 32bit compat code signal/signalfd: Add support for SIGSYS signal/signalfd: Remove __put_user from signalfd_copyinfo signal/xtensa: Use force_sig_fault where appropriate signal/xtensa: Consistenly use SIGBUS in do_unaligned_user signal/um: Use force_sig_fault where appropriate signal/sparc: Use force_sig_fault where appropriate signal/sparc: Use send_sig_fault where appropriate signal/sh: Use force_sig_fault where appropriate signal/s390: Use force_sig_fault where appropriate signal/riscv: Replace do_trap_siginfo with force_sig_fault signal/riscv: Use force_sig_fault where appropriate signal/parisc: Use force_sig_fault where appropriate signal/parisc: Use force_sig_mceerr where appropriate signal/openrisc: Use force_sig_fault where appropriate signal/nios2: Use force_sig_fault where appropriate ...
This commit is contained in:
commit
93e95fa574
|
@ -7,18 +7,4 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* SIGTRAP si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define TRAP_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -871,8 +871,7 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
|
|||
send a signal. Old exceptions are not signaled. */
|
||||
fex = (exc >> IEEE_STATUS_TO_EXCSUM_SHIFT) & swcr;
|
||||
if (fex) {
|
||||
siginfo_t info;
|
||||
int si_code = 0;
|
||||
int si_code = FPE_FLTUNK;
|
||||
|
||||
if (fex & IEEE_TRAP_ENABLE_DNO) si_code = FPE_FLTUND;
|
||||
if (fex & IEEE_TRAP_ENABLE_INE) si_code = FPE_FLTRES;
|
||||
|
@ -881,11 +880,9 @@ SYSCALL_DEFINE5(osf_setsysinfo, unsigned long, op, void __user *, buffer,
|
|||
if (fex & IEEE_TRAP_ENABLE_DZE) si_code = FPE_FLTDIV;
|
||||
if (fex & IEEE_TRAP_ENABLE_INV) si_code = FPE_FLTINV;
|
||||
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = NULL; /* FIXME */
|
||||
send_sig_info(SIGFPE, &info, current);
|
||||
send_sig_fault(SIGFPE, si_code,
|
||||
(void __user *)NULL, /* FIXME */
|
||||
0, current);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -219,14 +219,8 @@ do_sigreturn(struct sigcontext __user *sc)
|
|||
|
||||
/* Send SIGTRAP if we're single-stepping: */
|
||||
if (ptrace_cancel_bpt (current)) {
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGTRAP, &info, current);
|
||||
send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc, 0,
|
||||
current);
|
||||
}
|
||||
return;
|
||||
|
||||
|
@ -253,14 +247,8 @@ do_rt_sigreturn(struct rt_sigframe __user *frame)
|
|||
|
||||
/* Send SIGTRAP if we're single-stepping: */
|
||||
if (ptrace_cancel_bpt (current)) {
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGTRAP, &info, current);
|
||||
send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *) regs->pc, 0,
|
||||
current);
|
||||
}
|
||||
return;
|
||||
|
||||
|
|
|
@ -213,7 +213,6 @@ do_entArith(unsigned long summary, unsigned long write_mask,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
long si_code = FPE_FLTINV;
|
||||
siginfo_t info;
|
||||
|
||||
if (summary & 1) {
|
||||
/* Software-completion summary bit is set, so try to
|
||||
|
@ -228,17 +227,12 @@ do_entArith(unsigned long summary, unsigned long write_mask,
|
|||
}
|
||||
die_if_kernel("Arithmetic fault", regs, 0, NULL);
|
||||
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
send_sig_info(SIGFPE, &info, current);
|
||||
send_sig_fault(SIGFPE, si_code, (void __user *) regs->pc, 0, current);
|
||||
}
|
||||
|
||||
asmlinkage void
|
||||
do_entIF(unsigned long type, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
int signo, code;
|
||||
|
||||
if ((regs->ps & ~IPL_MAX) == 0) {
|
||||
|
@ -270,31 +264,20 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
|
||||
switch (type) {
|
||||
case 0: /* breakpoint */
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_trapno = 0;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
|
||||
if (ptrace_cancel_bpt(current)) {
|
||||
regs->pc -= 4; /* make pc point to former bpt */
|
||||
}
|
||||
|
||||
send_sig_info(SIGTRAP, &info, current);
|
||||
send_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc, 0,
|
||||
current);
|
||||
return;
|
||||
|
||||
case 1: /* bugcheck */
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_FIXME;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGTRAP, &info, current);
|
||||
send_sig_fault(SIGTRAP, TRAP_UNK, (void __user *) regs->pc, 0,
|
||||
current);
|
||||
return;
|
||||
|
||||
case 2: /* gentrap */
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
info.si_trapno = regs->r16;
|
||||
switch ((long) regs->r16) {
|
||||
case GEN_INTOVF:
|
||||
signo = SIGFPE;
|
||||
|
@ -326,7 +309,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
break;
|
||||
case GEN_ROPRAND:
|
||||
signo = SIGFPE;
|
||||
code = FPE_FIXME;
|
||||
code = FPE_FLTUNK;
|
||||
break;
|
||||
|
||||
case GEN_DECOVF:
|
||||
|
@ -348,15 +331,12 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
case GEN_SUBRNG7:
|
||||
default:
|
||||
signo = SIGTRAP;
|
||||
code = TRAP_FIXME;
|
||||
code = TRAP_UNK;
|
||||
break;
|
||||
}
|
||||
|
||||
info.si_signo = signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
send_sig_info(signo, &info, current);
|
||||
send_sig_fault(signo, code, (void __user *) regs->pc, regs->r16,
|
||||
current);
|
||||
return;
|
||||
|
||||
case 4: /* opDEC */
|
||||
|
@ -380,11 +360,9 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
if (si_code == 0)
|
||||
return;
|
||||
if (si_code > 0) {
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
send_sig_info(SIGFPE, &info, current);
|
||||
send_sig_fault(SIGFPE, si_code,
|
||||
(void __user *) regs->pc, 0,
|
||||
current);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -409,11 +387,7 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
;
|
||||
}
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLOPC;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
send_sig_info(SIGILL, &info, current);
|
||||
send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0, current);
|
||||
}
|
||||
|
||||
/* There is an ifdef in the PALcode in MILO that enables a
|
||||
|
@ -426,15 +400,9 @@ do_entIF(unsigned long type, struct pt_regs *regs)
|
|||
asmlinkage void
|
||||
do_entDbg(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
die_if_kernel("Instruction fault", regs, 0, NULL);
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLOPC;
|
||||
info.si_addr = (void __user *) regs->pc;
|
||||
force_sig_info(SIGILL, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)regs->pc, 0, current);
|
||||
}
|
||||
|
||||
|
||||
|
@ -758,7 +726,7 @@ do_entUnaUser(void __user * va, unsigned long opcode,
|
|||
|
||||
unsigned long tmp1, tmp2, tmp3, tmp4;
|
||||
unsigned long fake_reg, *reg_addr = &fake_reg;
|
||||
siginfo_t info;
|
||||
int si_code;
|
||||
long error;
|
||||
|
||||
/* Check the UAC bits to decide what the user wants us to do
|
||||
|
@ -981,34 +949,27 @@ do_entUnaUser(void __user * va, unsigned long opcode,
|
|||
|
||||
give_sigsegv:
|
||||
regs->pc -= 4; /* make pc point to faulting insn */
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
|
||||
/* We need to replicate some of the logic in mm/fault.c,
|
||||
since we don't have access to the fault code in the
|
||||
exception handling return path. */
|
||||
if ((unsigned long)va >= TASK_SIZE)
|
||||
info.si_code = SEGV_ACCERR;
|
||||
si_code = SEGV_ACCERR;
|
||||
else {
|
||||
struct mm_struct *mm = current->mm;
|
||||
down_read(&mm->mmap_sem);
|
||||
if (find_vma(mm, (unsigned long)va))
|
||||
info.si_code = SEGV_ACCERR;
|
||||
si_code = SEGV_ACCERR;
|
||||
else
|
||||
info.si_code = SEGV_MAPERR;
|
||||
si_code = SEGV_MAPERR;
|
||||
up_read(&mm->mmap_sem);
|
||||
}
|
||||
info.si_addr = va;
|
||||
send_sig_info(SIGSEGV, &info, current);
|
||||
send_sig_fault(SIGSEGV, si_code, va, 0, current);
|
||||
return;
|
||||
|
||||
give_sigbus:
|
||||
regs->pc -= 4;
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = va;
|
||||
send_sig_info(SIGBUS, &info, current);
|
||||
send_sig_fault(SIGBUS, BUS_ADRALN, va, 0, current);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,6 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
|
|||
struct mm_struct *mm = current->mm;
|
||||
const struct exception_table_entry *fixup;
|
||||
int fault, si_code = SEGV_MAPERR;
|
||||
siginfo_t info;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
/* As of EV6, a load into $31/$f31 is a prefetch, and never faults
|
||||
|
@ -221,21 +220,13 @@ do_page_fault(unsigned long address, unsigned long mmcsr,
|
|||
up_read(&mm->mmap_sem);
|
||||
/* Send a sigbus, regardless of whether we were in kernel
|
||||
or user mode. */
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void __user *) address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *) address, 0, current);
|
||||
if (!user_mode(regs))
|
||||
goto no_context;
|
||||
return;
|
||||
|
||||
do_sigsegv:
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *) address;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *) address, 0, current);
|
||||
return;
|
||||
|
||||
#ifdef CONFIG_ALPHA_LARGE_VMALLOC
|
||||
|
|
|
@ -70,6 +70,8 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
|
|||
int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
clear_siginfo(&info);
|
||||
|
||||
/*
|
||||
* We fault-in kernel-space virtual memory on-demand. The
|
||||
* 'reference' page table is init_mm.pgd.
|
||||
|
|
|
@ -205,6 +205,7 @@ void ptrace_break(struct task_struct *tsk, struct pt_regs *regs)
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
|
|
|
@ -100,6 +100,7 @@ static void set_segfault(struct pt_regs *regs, unsigned long addr)
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
if (find_vma(current->mm, addr) == NULL)
|
||||
info.si_code = SEGV_MAPERR;
|
||||
|
|
|
@ -441,6 +441,7 @@ asmlinkage void do_undefinstr(struct pt_regs *regs)
|
|||
siginfo_t info;
|
||||
void __user *pc;
|
||||
|
||||
clear_siginfo(&info);
|
||||
pc = (void __user *)instruction_pointer(regs);
|
||||
|
||||
if (processor_mode(regs) == SVC_MODE) {
|
||||
|
@ -540,6 +541,7 @@ static int bad_syscall(int n, struct pt_regs *regs)
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
if ((current->personality & PER_MASK) != PER_LINUX) {
|
||||
send_sig(SIGSEGV, current, 1);
|
||||
return regs->ARM_r0;
|
||||
|
@ -607,6 +609,7 @@ asmlinkage int arm_syscall(int no, struct pt_regs *regs)
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
if ((no >> 16) != (__ARM_NR_BASE>> 16))
|
||||
return bad_syscall(no, regs);
|
||||
|
||||
|
@ -743,6 +746,8 @@ baddataabort(int code, unsigned long instr, struct pt_regs *regs)
|
|||
unsigned long addr = instruction_pointer(regs);
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
|
||||
#ifdef CONFIG_DEBUG_USER
|
||||
if (user_debug & UDBG_BADABORT) {
|
||||
pr_err("[%d] %s: bad data abort: code %d instr 0x%08lx\n",
|
||||
|
|
|
@ -950,6 +950,7 @@ do_alignment(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
if (ai_usermode & UM_SIGNAL) {
|
||||
siginfo_t si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_errno = 0;
|
||||
si.si_code = BUS_ADRALN;
|
||||
|
|
|
@ -163,6 +163,8 @@ __do_user_fault(struct task_struct *tsk, unsigned long addr,
|
|||
{
|
||||
struct siginfo si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
|
||||
#ifdef CONFIG_DEBUG_USER
|
||||
if (((user_debug & UDBG_SEGV) && (sig == SIGSEGV)) ||
|
||||
((user_debug & UDBG_BUS) && (sig == SIGBUS))) {
|
||||
|
@ -557,6 +559,7 @@ do_DataAbort(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
|
|||
inf->name, fsr, addr);
|
||||
show_pte(current->mm, addr);
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
@ -589,6 +592,7 @@ do_PrefetchAbort(unsigned long addr, unsigned int ifsr, struct pt_regs *regs)
|
|||
pr_alert("Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
|
||||
inf->name, ifsr, addr);
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
|
|
@ -218,8 +218,7 @@ static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_code = sicode;
|
||||
info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
|
||||
|
|
|
@ -882,7 +882,7 @@ asmlinkage void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
|
|||
si_code = FPE_FLTRES;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *)instruction_pointer(regs);
|
||||
|
|
|
@ -112,6 +112,7 @@ long compat_arm_syscall(struct pt_regs *regs)
|
|||
break;
|
||||
}
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLTRP;
|
||||
|
|
|
@ -635,6 +635,7 @@ asmlinkage void bad_el0_sync(struct pt_regs *regs, int reason, unsigned int esr)
|
|||
siginfo_t info;
|
||||
void __user *pc = (void __user *)instruction_pointer(regs);
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLOPC;
|
||||
|
|
|
@ -356,11 +356,12 @@ static void do_bad_area(unsigned long addr, unsigned int esr, struct pt_regs *re
|
|||
*/
|
||||
if (user_mode(regs)) {
|
||||
const struct fault_info *inf = esr_to_fault_info(esr);
|
||||
struct siginfo si = {
|
||||
.si_signo = inf->sig,
|
||||
.si_code = inf->code,
|
||||
.si_addr = (void __user *)addr,
|
||||
};
|
||||
struct siginfo si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = inf->sig;
|
||||
si.si_code = inf->code;
|
||||
si.si_addr = (void __user *)addr;
|
||||
|
||||
__do_user_fault(&si, esr);
|
||||
} else {
|
||||
|
@ -634,6 +635,7 @@ static int do_sea(unsigned long addr, unsigned int esr, struct pt_regs *regs)
|
|||
nmi_exit();
|
||||
}
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
@ -738,6 +740,7 @@ asmlinkage void __exception do_mem_abort(unsigned long addr, unsigned int esr,
|
|||
show_pte(addr);
|
||||
}
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
@ -780,6 +783,7 @@ asmlinkage void __exception do_sp_pc_abort(unsigned long addr,
|
|||
local_irq_enable();
|
||||
}
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
|
@ -823,7 +827,6 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
|
|||
struct pt_regs *regs)
|
||||
{
|
||||
const struct fault_info *inf = debug_fault_info + DBG_ESR_EVT(esr);
|
||||
struct siginfo info;
|
||||
int rv;
|
||||
|
||||
/*
|
||||
|
@ -839,6 +842,9 @@ asmlinkage int __exception do_debug_exception(unsigned long addr,
|
|||
if (!inf->fn(addr, esr, regs)) {
|
||||
rv = 1;
|
||||
} else {
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
|
|
@ -244,7 +244,6 @@ static struct exception_info eexcept_table[128] = {
|
|||
static void do_trap(struct exception_info *except_info, struct pt_regs *regs)
|
||||
{
|
||||
unsigned long addr = instruction_pointer(regs);
|
||||
siginfo_t info;
|
||||
|
||||
if (except_info->code != TRAP_BRKPT)
|
||||
pr_err("TRAP: %s PC[0x%lx] signo[%d] code[%d]\n",
|
||||
|
@ -253,12 +252,8 @@ static void do_trap(struct exception_info *except_info, struct pt_regs *regs)
|
|||
|
||||
die_if_kernel(except_info->kernel_str, regs, addr);
|
||||
|
||||
info.si_signo = except_info->signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = except_info->code;
|
||||
info.si_addr = (void __user *)addr;
|
||||
|
||||
force_sig_info(except_info->signo, &info, current);
|
||||
force_sig_fault(except_info->signo, except_info->code,
|
||||
(void __user *)addr, current);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -412,10 +412,6 @@ void do_trap0(struct pt_regs *regs)
|
|||
case TRAP_DEBUG:
|
||||
/* Trap0 0xdb is debug breakpoint */
|
||||
if (user_mode(regs)) {
|
||||
struct siginfo info;
|
||||
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
/*
|
||||
* Some architecures add some per-thread state
|
||||
* to distinguish between breakpoint traps and
|
||||
|
@ -423,9 +419,8 @@ void do_trap0(struct pt_regs *regs)
|
|||
* set the si_code value appropriately, or we
|
||||
* may want to use a different trap0 flavor.
|
||||
*/
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_addr = (void __user *) pt_elr(regs);
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_BRKPT,
|
||||
(void __user *) pt_elr(regs), current);
|
||||
} else {
|
||||
#ifdef CONFIG_KGDB
|
||||
kgdb_handle_exception(pt_cause(regs), SIGTRAP,
|
||||
|
|
|
@ -50,7 +50,7 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
|
|||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
siginfo_t info;
|
||||
int si_signo;
|
||||
int si_code = SEGV_MAPERR;
|
||||
int fault;
|
||||
const struct exception_table_entry *fixup;
|
||||
|
@ -140,28 +140,22 @@ void do_page_fault(unsigned long address, long cause, struct pt_regs *regs)
|
|||
* unable to fix up the page fault.
|
||||
*/
|
||||
if (fault & VM_FAULT_SIGBUS) {
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRERR;
|
||||
si_signo = SIGBUS;
|
||||
si_code = BUS_ADRERR;
|
||||
}
|
||||
/* Address is not in the memory map */
|
||||
else {
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_code = SEGV_ACCERR;
|
||||
si_signo = SIGSEGV;
|
||||
si_code = SEGV_ACCERR;
|
||||
}
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
force_sig_fault(si_signo, si_code, (void __user *)address, current);
|
||||
return;
|
||||
|
||||
bad_area:
|
||||
up_read(&mm->mmap_sem);
|
||||
|
||||
if (user_mode(regs)) {
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *)address, current);
|
||||
return;
|
||||
}
|
||||
/* Kernel-mode fault falls through */
|
||||
|
|
|
@ -27,11 +27,4 @@
|
|||
#define __ISR_VALID_BIT 0
|
||||
#define __ISR_VALID (1 << __ISR_VALID_BIT)
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
#endif /* _UAPI_ASM_IA64_SIGINFO_H */
|
||||
|
|
|
@ -62,6 +62,7 @@ ia64_emulate_brl (struct pt_regs *regs, unsigned long ar_ec)
|
|||
struct illegal_op_return rv;
|
||||
long tmp_taken, unimplemented_address;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
rv.fkt = (unsigned long) -1;
|
||||
|
||||
/*
|
||||
|
|
|
@ -153,6 +153,7 @@ ia64_rt_sigreturn (struct sigscratch *scr)
|
|||
return retval;
|
||||
|
||||
give_sigsegv:
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_errno = 0;
|
||||
si.si_code = SI_KERNEL;
|
||||
|
@ -236,6 +237,7 @@ force_sigsegv_info (int sig, void __user *addr)
|
|||
unsigned long flags;
|
||||
struct siginfo si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
if (sig == SIGSEGV) {
|
||||
/*
|
||||
* Acquiring siglock around the sa_handler-update is almost
|
||||
|
|
|
@ -104,6 +104,7 @@ __kprobes ia64_bad_break (unsigned long break_num, struct pt_regs *regs)
|
|||
int sig, code;
|
||||
|
||||
/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
|
||||
siginfo.si_imm = break_num;
|
||||
siginfo.si_flags = 0; /* clear __ISR_VALID */
|
||||
|
@ -293,7 +294,6 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
|
|||
{
|
||||
long exception, bundle[2];
|
||||
unsigned long fault_ip;
|
||||
struct siginfo siginfo;
|
||||
|
||||
fault_ip = regs->cr_iip;
|
||||
if (!fp_fault && (ia64_psr(regs)->ri == 0))
|
||||
|
@ -344,13 +344,16 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
|
|||
printk(KERN_ERR "handle_fpu_swa: fp_emulate() returned -1\n");
|
||||
return -1;
|
||||
} else {
|
||||
struct siginfo siginfo;
|
||||
|
||||
/* is next instruction a trap? */
|
||||
if (exception & 2) {
|
||||
ia64_increment_ip(regs);
|
||||
}
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = SIGFPE;
|
||||
siginfo.si_errno = 0;
|
||||
siginfo.si_code = FPE_FIXME; /* default code */
|
||||
siginfo.si_code = FPE_FLTUNK; /* default code */
|
||||
siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
|
||||
if (isr & 0x11) {
|
||||
siginfo.si_code = FPE_FLTINV;
|
||||
|
@ -372,9 +375,12 @@ handle_fpu_swa (int fp_fault, struct pt_regs *regs, unsigned long isr)
|
|||
return -1;
|
||||
} else if (exception != 0) {
|
||||
/* raise exception */
|
||||
struct siginfo siginfo;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = SIGFPE;
|
||||
siginfo.si_errno = 0;
|
||||
siginfo.si_code = FPE_FIXME; /* default code */
|
||||
siginfo.si_code = FPE_FLTUNK; /* default code */
|
||||
siginfo.si_addr = (void __user *) (regs->cr_iip + ia64_psr(regs)->ri);
|
||||
if (isr & 0x880) {
|
||||
siginfo.si_code = FPE_FLTOVF;
|
||||
|
@ -420,7 +426,7 @@ ia64_illegal_op_fault (unsigned long ec, long arg1, long arg2, long arg3,
|
|||
if (die_if_kernel(buf, ®s, 0))
|
||||
return rv;
|
||||
|
||||
memset(&si, 0, sizeof(si));
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = SIGILL;
|
||||
si.si_code = ILL_ILLOPC;
|
||||
si.si_addr = (void __user *) (regs.cr_iip + ia64_psr(®s)->ri);
|
||||
|
@ -434,7 +440,6 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
long arg7, struct pt_regs regs)
|
||||
{
|
||||
unsigned long code, error = isr, iip;
|
||||
struct siginfo siginfo;
|
||||
char buf[128];
|
||||
int result, sig;
|
||||
static const char *reason[] = {
|
||||
|
@ -485,6 +490,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
|
||||
case 26: /* NaT Consumption */
|
||||
if (user_mode(®s)) {
|
||||
struct siginfo siginfo;
|
||||
void __user *addr;
|
||||
|
||||
if (((isr >> 4) & 0xf) == 2) {
|
||||
|
@ -499,6 +505,7 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
addr = (void __user *) (regs.cr_iip
|
||||
+ ia64_psr(®s)->ri);
|
||||
}
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = sig;
|
||||
siginfo.si_code = code;
|
||||
siginfo.si_errno = 0;
|
||||
|
@ -515,6 +522,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
|
||||
case 31: /* Unsupported Data Reference */
|
||||
if (user_mode(®s)) {
|
||||
struct siginfo siginfo;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = SIGILL;
|
||||
siginfo.si_code = ILL_ILLOPN;
|
||||
siginfo.si_errno = 0;
|
||||
|
@ -531,6 +541,10 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
case 29: /* Debug */
|
||||
case 35: /* Taken Branch Trap */
|
||||
case 36: /* Single Step Trap */
|
||||
{
|
||||
struct siginfo siginfo;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
if (fsys_mode(current, ®s)) {
|
||||
extern char __kernel_syscall_via_break[];
|
||||
/*
|
||||
|
@ -578,11 +592,15 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
siginfo.si_isr = isr;
|
||||
force_sig_info(SIGTRAP, &siginfo, current);
|
||||
return;
|
||||
}
|
||||
|
||||
case 32: /* fp fault */
|
||||
case 33: /* fp trap */
|
||||
result = handle_fpu_swa((vector == 32) ? 1 : 0, ®s, isr);
|
||||
if ((result < 0) || (current->thread.flags & IA64_THREAD_FPEMU_SIGFPE)) {
|
||||
struct siginfo siginfo;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = SIGFPE;
|
||||
siginfo.si_errno = 0;
|
||||
siginfo.si_code = FPE_FLTINV;
|
||||
|
@ -616,6 +634,9 @@ ia64_fault (unsigned long vector, unsigned long isr, unsigned long ifa,
|
|||
} else {
|
||||
/* Unimplemented Instr. Address Trap */
|
||||
if (user_mode(®s)) {
|
||||
struct siginfo siginfo;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = SIGILL;
|
||||
siginfo.si_code = ILL_BADIADDR;
|
||||
siginfo.si_errno = 0;
|
||||
|
|
|
@ -1537,6 +1537,7 @@ ia64_handle_unaligned (unsigned long ifa, struct pt_regs *regs)
|
|||
/* NOT_REACHED */
|
||||
}
|
||||
force_sigbus:
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_errno = 0;
|
||||
si.si_code = BUS_ADRALN;
|
||||
|
|
|
@ -85,7 +85,6 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
|
|||
int signal = SIGSEGV, code = SEGV_MAPERR;
|
||||
struct vm_area_struct *vma, *prev_vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
struct siginfo si;
|
||||
unsigned long mask;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
@ -249,6 +248,9 @@ ia64_do_page_fault (unsigned long address, unsigned long isr, struct pt_regs *re
|
|||
return;
|
||||
}
|
||||
if (user_mode(regs)) {
|
||||
struct siginfo si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = signal;
|
||||
si.si_errno = 0;
|
||||
si.si_code = code;
|
||||
|
|
|
@ -1007,9 +1007,9 @@ void bad_super_trap (struct frame *fp)
|
|||
|
||||
asmlinkage void trap_c(struct frame *fp)
|
||||
{
|
||||
int sig;
|
||||
int sig, si_code;
|
||||
void __user *addr;
|
||||
int vector = (fp->ptregs.vector >> 2) & 0xff;
|
||||
siginfo_t info;
|
||||
|
||||
if (fp->ptregs.sr & PS_S) {
|
||||
if (vector == VEC_TRACE) {
|
||||
|
@ -1029,21 +1029,21 @@ asmlinkage void trap_c(struct frame *fp)
|
|||
/* send the appropriate signal to the user program */
|
||||
switch (vector) {
|
||||
case VEC_ADDRERR:
|
||||
info.si_code = BUS_ADRALN;
|
||||
si_code = BUS_ADRALN;
|
||||
sig = SIGBUS;
|
||||
break;
|
||||
case VEC_ILLEGAL:
|
||||
case VEC_LINE10:
|
||||
case VEC_LINE11:
|
||||
info.si_code = ILL_ILLOPC;
|
||||
si_code = ILL_ILLOPC;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case VEC_PRIV:
|
||||
info.si_code = ILL_PRVOPC;
|
||||
si_code = ILL_PRVOPC;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case VEC_COPROC:
|
||||
info.si_code = ILL_COPROC;
|
||||
si_code = ILL_COPROC;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case VEC_TRAP1:
|
||||
|
@ -1060,76 +1060,74 @@ asmlinkage void trap_c(struct frame *fp)
|
|||
case VEC_TRAP12:
|
||||
case VEC_TRAP13:
|
||||
case VEC_TRAP14:
|
||||
info.si_code = ILL_ILLTRP;
|
||||
si_code = ILL_ILLTRP;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
case VEC_FPBRUC:
|
||||
case VEC_FPOE:
|
||||
case VEC_FPNAN:
|
||||
info.si_code = FPE_FLTINV;
|
||||
si_code = FPE_FLTINV;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_FPIR:
|
||||
info.si_code = FPE_FLTRES;
|
||||
si_code = FPE_FLTRES;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_FPDIVZ:
|
||||
info.si_code = FPE_FLTDIV;
|
||||
si_code = FPE_FLTDIV;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_FPUNDER:
|
||||
info.si_code = FPE_FLTUND;
|
||||
si_code = FPE_FLTUND;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_FPOVER:
|
||||
info.si_code = FPE_FLTOVF;
|
||||
si_code = FPE_FLTOVF;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_ZERODIV:
|
||||
info.si_code = FPE_INTDIV;
|
||||
si_code = FPE_INTDIV;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_CHK:
|
||||
case VEC_TRAP:
|
||||
info.si_code = FPE_INTOVF;
|
||||
si_code = FPE_INTOVF;
|
||||
sig = SIGFPE;
|
||||
break;
|
||||
case VEC_TRACE: /* ptrace single step */
|
||||
info.si_code = TRAP_TRACE;
|
||||
si_code = TRAP_TRACE;
|
||||
sig = SIGTRAP;
|
||||
break;
|
||||
case VEC_TRAP15: /* breakpoint */
|
||||
info.si_code = TRAP_BRKPT;
|
||||
si_code = TRAP_BRKPT;
|
||||
sig = SIGTRAP;
|
||||
break;
|
||||
default:
|
||||
info.si_code = ILL_ILLOPC;
|
||||
si_code = ILL_ILLOPC;
|
||||
sig = SIGILL;
|
||||
break;
|
||||
}
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
switch (fp->ptregs.format) {
|
||||
default:
|
||||
info.si_addr = (void *) fp->ptregs.pc;
|
||||
addr = (void __user *) fp->ptregs.pc;
|
||||
break;
|
||||
case 2:
|
||||
info.si_addr = (void *) fp->un.fmt2.iaddr;
|
||||
addr = (void __user *) fp->un.fmt2.iaddr;
|
||||
break;
|
||||
case 7:
|
||||
info.si_addr = (void *) fp->un.fmt7.effaddr;
|
||||
addr = (void __user *) fp->un.fmt7.effaddr;
|
||||
break;
|
||||
case 9:
|
||||
info.si_addr = (void *) fp->un.fmt9.iaddr;
|
||||
addr = (void __user *) fp->un.fmt9.iaddr;
|
||||
break;
|
||||
case 10:
|
||||
info.si_addr = (void *) fp->un.fmta.daddr;
|
||||
addr = (void __user *) fp->un.fmta.daddr;
|
||||
break;
|
||||
case 11:
|
||||
info.si_addr = (void *) fp->un.fmtb.daddr;
|
||||
addr = (void __user*) fp->un.fmtb.daddr;
|
||||
break;
|
||||
}
|
||||
force_sig_info (sig, &info, current);
|
||||
force_sig_fault(sig, si_code, addr, current);
|
||||
}
|
||||
|
||||
void die_if_kernel (char *str, struct pt_regs *fp, int nr)
|
||||
|
@ -1161,12 +1159,6 @@ asmlinkage void fpsp040_die(void)
|
|||
#ifdef CONFIG_M68KFPU_EMU
|
||||
asmlinkage void fpemu_signal(int signal, int code, void *addr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = signal;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = addr;
|
||||
force_sig_info(signal, &info, current);
|
||||
force_sig_fault(signal, code, addr, current);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -21,35 +21,32 @@ extern void die_if_kernel(char *, struct pt_regs *, long);
|
|||
|
||||
int send_fault_sig(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t siginfo;
|
||||
int signo, si_code;
|
||||
void __user *addr;
|
||||
|
||||
clear_siginfo(&siginfo);
|
||||
siginfo.si_signo = current->thread.signo;
|
||||
siginfo.si_code = current->thread.code;
|
||||
siginfo.si_addr = (void *)current->thread.faddr;
|
||||
pr_debug("send_fault_sig: %p,%d,%d\n", siginfo.si_addr,
|
||||
siginfo.si_signo, siginfo.si_code);
|
||||
signo = current->thread.signo;
|
||||
si_code = current->thread.code;
|
||||
addr = (void __user *)current->thread.faddr;
|
||||
pr_debug("send_fault_sig: %p,%d,%d\n", addr, signo, si_code);
|
||||
|
||||
if (user_mode(regs)) {
|
||||
force_sig_info(siginfo.si_signo,
|
||||
&siginfo, current);
|
||||
force_sig_fault(signo, si_code, addr, current);
|
||||
} else {
|
||||
if (fixup_exception(regs))
|
||||
return -1;
|
||||
|
||||
//if (siginfo.si_signo == SIGBUS)
|
||||
// force_sig_info(siginfo.si_signo,
|
||||
// &siginfo, current);
|
||||
//if (signo == SIGBUS)
|
||||
// force_sig_fault(si_signo, si_code, addr, current);
|
||||
|
||||
/*
|
||||
* Oops. The kernel tried to access some bad page. We'll have to
|
||||
* terminate things with extreme prejudice.
|
||||
*/
|
||||
if ((unsigned long)siginfo.si_addr < PAGE_SIZE)
|
||||
if ((unsigned long)addr < PAGE_SIZE)
|
||||
pr_alert("Unable to handle kernel NULL pointer dereference");
|
||||
else
|
||||
pr_alert("Unable to handle kernel access");
|
||||
pr_cont(" at virtual address %p\n", siginfo.si_addr);
|
||||
pr_cont(" at virtual address %p\n", addr);
|
||||
die_if_kernel("Oops", regs, 0 /*error_code*/);
|
||||
do_exit(SIGKILL);
|
||||
}
|
||||
|
|
|
@ -60,16 +60,10 @@ asmlinkage void sw_exception(struct pt_regs *regs)
|
|||
|
||||
void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (kernel_mode(regs))
|
||||
die("Exception in kernel mode", regs, signr);
|
||||
|
||||
info.si_signo = signr;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = (void __user *) addr;
|
||||
force_sig_info(signr, &info, current);
|
||||
force_sig_fault(signr, code, (void __user *)addr, current);
|
||||
}
|
||||
|
||||
asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
|
||||
|
|
|
@ -88,7 +88,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
{
|
||||
struct vm_area_struct *vma;
|
||||
struct mm_struct *mm = current->mm;
|
||||
siginfo_t info;
|
||||
int code = SEGV_MAPERR;
|
||||
int is_write = error_code & ESR_S;
|
||||
int fault;
|
||||
|
@ -269,11 +268,6 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
/* User mode accesses cause a SIGSEGV */
|
||||
if (user_mode(regs)) {
|
||||
_exception(SIGSEGV, regs, code, address);
|
||||
/* info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = (void *) address;
|
||||
force_sig_info(SIGSEGV, &info, current);*/
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -295,11 +289,7 @@ void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
do_sigbus:
|
||||
up_read(&mm->mmap_sem);
|
||||
if (user_mode(regs)) {
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, current);
|
||||
return;
|
||||
}
|
||||
bad_page_fault(regs, address, SIGBUS);
|
||||
|
|
|
@ -699,17 +699,11 @@ static int simulate_sync(struct pt_regs *regs, unsigned int opcode)
|
|||
asmlinkage void do_ov(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state;
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_code = FPE_INTOVF;
|
||||
info.si_addr = (void __user *)regs->cp0_epc;
|
||||
|
||||
prev_state = exception_enter();
|
||||
die_if_kernel("Integer overflow", regs);
|
||||
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
force_sig_fault(SIGFPE, FPE_INTOVF, (void __user *)regs->cp0_epc, current);
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
||||
|
@ -722,32 +716,27 @@ asmlinkage void do_ov(struct pt_regs *regs)
|
|||
void force_fcr31_sig(unsigned long fcr31, void __user *fault_addr,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
struct siginfo si;
|
||||
|
||||
clear_siginfo(&si);
|
||||
si.si_addr = fault_addr;
|
||||
si.si_signo = SIGFPE;
|
||||
int si_code = FPE_FLTUNK;
|
||||
|
||||
if (fcr31 & FPU_CSR_INV_X)
|
||||
si.si_code = FPE_FLTINV;
|
||||
si_code = FPE_FLTINV;
|
||||
else if (fcr31 & FPU_CSR_DIV_X)
|
||||
si.si_code = FPE_FLTDIV;
|
||||
si_code = FPE_FLTDIV;
|
||||
else if (fcr31 & FPU_CSR_OVF_X)
|
||||
si.si_code = FPE_FLTOVF;
|
||||
si_code = FPE_FLTOVF;
|
||||
else if (fcr31 & FPU_CSR_UDF_X)
|
||||
si.si_code = FPE_FLTUND;
|
||||
si_code = FPE_FLTUND;
|
||||
else if (fcr31 & FPU_CSR_INE_X)
|
||||
si.si_code = FPE_FLTRES;
|
||||
si_code = FPE_FLTRES;
|
||||
|
||||
force_sig_info(SIGFPE, &si, tsk);
|
||||
force_sig_fault(SIGFPE, si_code, fault_addr, tsk);
|
||||
}
|
||||
|
||||
int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
|
||||
{
|
||||
struct siginfo si;
|
||||
int si_code;
|
||||
struct vm_area_struct *vma;
|
||||
|
||||
clear_siginfo(&si);
|
||||
switch (sig) {
|
||||
case 0:
|
||||
return 0;
|
||||
|
@ -757,23 +746,18 @@ int process_fpemu_return(int sig, void __user *fault_addr, unsigned long fcr31)
|
|||
return 1;
|
||||
|
||||
case SIGBUS:
|
||||
si.si_addr = fault_addr;
|
||||
si.si_signo = sig;
|
||||
si.si_code = BUS_ADRERR;
|
||||
force_sig_info(sig, &si, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, fault_addr, current);
|
||||
return 1;
|
||||
|
||||
case SIGSEGV:
|
||||
si.si_addr = fault_addr;
|
||||
si.si_signo = sig;
|
||||
down_read(¤t->mm->mmap_sem);
|
||||
vma = find_vma(current->mm, (unsigned long)fault_addr);
|
||||
if (vma && (vma->vm_start <= (unsigned long)fault_addr))
|
||||
si.si_code = SEGV_ACCERR;
|
||||
si_code = SEGV_ACCERR;
|
||||
else
|
||||
si.si_code = SEGV_MAPERR;
|
||||
si_code = SEGV_MAPERR;
|
||||
up_read(¤t->mm->mmap_sem);
|
||||
force_sig_info(sig, &si, current);
|
||||
force_sig_fault(SIGSEGV, si_code, fault_addr, current);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
|
@ -896,10 +880,8 @@ asmlinkage void do_fpe(struct pt_regs *regs, unsigned long fcr31)
|
|||
void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
|
||||
const char *str)
|
||||
{
|
||||
siginfo_t info;
|
||||
char b[40];
|
||||
|
||||
clear_siginfo(&info);
|
||||
#ifdef CONFIG_KGDB_LOW_LEVEL_TRAP
|
||||
if (kgdb_ll_trap(DIE_TRAP, str, regs, code, current->thread.trap_nr,
|
||||
SIGTRAP) == NOTIFY_STOP)
|
||||
|
@ -921,13 +903,9 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
|
|||
case BRK_DIVZERO:
|
||||
scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
|
||||
die_if_kernel(b, regs);
|
||||
if (code == BRK_DIVZERO)
|
||||
info.si_code = FPE_INTDIV;
|
||||
else
|
||||
info.si_code = FPE_INTOVF;
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_addr = (void __user *) regs->cp0_epc;
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
force_sig_fault(SIGFPE,
|
||||
code == BRK_DIVZERO ? FPE_INTDIV : FPE_INTOVF,
|
||||
(void __user *) regs->cp0_epc, current);
|
||||
break;
|
||||
case BRK_BUG:
|
||||
die_if_kernel("Kernel bug detected", regs);
|
||||
|
@ -952,9 +930,7 @@ void do_trap_or_bp(struct pt_regs *regs, unsigned int code, int si_code,
|
|||
scnprintf(b, sizeof(b), "%s instruction in kernel code", str);
|
||||
die_if_kernel(b, regs);
|
||||
if (si_code) {
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_code = si_code;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, si_code, NULL, current);
|
||||
} else {
|
||||
force_sig(SIGTRAP, current);
|
||||
}
|
||||
|
@ -1506,13 +1482,8 @@ asmlinkage void do_mdmx(struct pt_regs *regs)
|
|||
*/
|
||||
asmlinkage void do_watch(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
enum ctx_state prev_state;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
|
||||
prev_state = exception_enter();
|
||||
/*
|
||||
* Clear WP (bit 22) bit of cause register so we don't loop
|
||||
|
@ -1528,7 +1499,7 @@ asmlinkage void do_watch(struct pt_regs *regs)
|
|||
if (test_tsk_thread_flag(current, TIF_LOAD_WATCH)) {
|
||||
mips_read_watch_registers();
|
||||
local_irq_enable();
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_HWBKPT, NULL, current);
|
||||
} else {
|
||||
mips_clear_watch_registers();
|
||||
local_irq_enable();
|
||||
|
|
|
@ -42,7 +42,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
|||
struct task_struct *tsk = current;
|
||||
struct mm_struct *mm = tsk->mm;
|
||||
const int field = sizeof(unsigned long) * 2;
|
||||
siginfo_t info;
|
||||
int si_code;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
|
@ -63,7 +63,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
|||
return;
|
||||
#endif
|
||||
|
||||
info.si_code = SEGV_MAPERR;
|
||||
si_code = SEGV_MAPERR;
|
||||
|
||||
/*
|
||||
* We fault-in kernel-space virtual memory on-demand. The
|
||||
|
@ -112,7 +112,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
|||
* we can handle it..
|
||||
*/
|
||||
good_area:
|
||||
info.si_code = SEGV_ACCERR;
|
||||
si_code = SEGV_ACCERR;
|
||||
|
||||
if (write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
|
@ -223,11 +223,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
|||
pr_cont("\n");
|
||||
}
|
||||
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* info.si_code has been set above */
|
||||
info.si_addr = (void __user *) address;
|
||||
force_sig_info(SIGSEGV, &info, tsk);
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *)address, tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -283,11 +279,7 @@ static void __kprobes __do_page_fault(struct pt_regs *regs, unsigned long write,
|
|||
#endif
|
||||
current->thread.trap_nr = (regs->cp0_cause >> 2) & 0x1f;
|
||||
tsk->thread.cp0_badvaddr = address;
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void __user *) address;
|
||||
force_sig_info(SIGBUS, &info, tsk);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk);
|
||||
|
||||
return;
|
||||
#ifndef CONFIG_64BIT
|
||||
|
|
|
@ -222,19 +222,13 @@ void die_if_kernel(const char *str, struct pt_regs *regs, int err)
|
|||
|
||||
int bad_syscall(int n, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (current->personality != PER_LINUX) {
|
||||
send_sig(SIGSEGV, current, 1);
|
||||
return regs->uregs[0];
|
||||
}
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLTRP;
|
||||
info.si_addr = (void __user *)instruction_pointer(regs) - 4;
|
||||
|
||||
force_sig_info(SIGILL, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_ILLTRP,
|
||||
(void __user *)instruction_pointer(regs) - 4, current);
|
||||
die_if_kernel("Oops - bad syscall", regs, n);
|
||||
return regs->uregs[0];
|
||||
}
|
||||
|
@ -287,16 +281,11 @@ void __init early_trap_init(void)
|
|||
void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
|
||||
int error_code, int si_code)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
tsk->thread.trap_no = ENTRY_DEBUG_RELATED;
|
||||
tsk->thread.error_code = error_code;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *)instruction_pointer(regs);
|
||||
force_sig_info(SIGTRAP, &info, tsk);
|
||||
force_sig_fault(SIGTRAP, si_code,
|
||||
(void __user *)instruction_pointer(regs), tsk);
|
||||
}
|
||||
|
||||
void do_debug_trap(unsigned long entry, unsigned long addr,
|
||||
|
@ -318,29 +307,22 @@ void do_debug_trap(unsigned long entry, unsigned long addr,
|
|||
|
||||
void unhandled_interruption(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t si;
|
||||
pr_emerg("unhandled_interruption\n");
|
||||
show_regs(regs);
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGKILL);
|
||||
si.si_signo = SIGKILL;
|
||||
si.si_errno = 0;
|
||||
force_sig_info(SIGKILL, &si, current);
|
||||
force_sig(SIGKILL, current);
|
||||
}
|
||||
|
||||
void unhandled_exceptions(unsigned long entry, unsigned long addr,
|
||||
unsigned long type, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t si;
|
||||
pr_emerg("Unhandled Exception: entry: %lx addr:%lx itype:%lx\n", entry,
|
||||
addr, type);
|
||||
show_regs(regs);
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGKILL);
|
||||
si.si_signo = SIGKILL;
|
||||
si.si_errno = 0;
|
||||
si.si_addr = (void *)addr;
|
||||
force_sig_info(SIGKILL, &si, current);
|
||||
force_sig(SIGKILL, current);
|
||||
}
|
||||
|
||||
extern int do_page_fault(unsigned long entry, unsigned long addr,
|
||||
|
@ -363,14 +345,11 @@ void do_dispatch_tlb_misc(unsigned long entry, unsigned long addr,
|
|||
|
||||
void do_revinsn(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t si;
|
||||
pr_emerg("Reserved Instruction\n");
|
||||
show_regs(regs);
|
||||
if (!user_mode(regs))
|
||||
do_exit(SIGILL);
|
||||
si.si_signo = SIGILL;
|
||||
si.si_errno = 0;
|
||||
force_sig_info(SIGILL, &si, current);
|
||||
force_sig(SIGILL, current);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ALIGNMENT_TRAP
|
||||
|
|
|
@ -72,7 +72,7 @@ void do_page_fault(unsigned long entry, unsigned long addr,
|
|||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct *vma;
|
||||
siginfo_t info;
|
||||
int si_code;
|
||||
int fault;
|
||||
unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
@ -80,7 +80,7 @@ void do_page_fault(unsigned long entry, unsigned long addr,
|
|||
error_code = error_code & (ITYPE_mskINST | ITYPE_mskETYPE);
|
||||
tsk = current;
|
||||
mm = tsk->mm;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
si_code = SEGV_MAPERR;
|
||||
/*
|
||||
* We fault-in kernel-space virtual memory on-demand. The
|
||||
* 'reference' page table is init_mm.pgd.
|
||||
|
@ -161,7 +161,7 @@ void do_page_fault(unsigned long entry, unsigned long addr,
|
|||
*/
|
||||
|
||||
good_area:
|
||||
info.si_code = SEGV_ACCERR;
|
||||
si_code = SEGV_ACCERR;
|
||||
|
||||
/* first do some preliminary protection checks */
|
||||
if (entry == ENTRY_PTE_NOT_PRESENT) {
|
||||
|
@ -266,11 +266,7 @@ void do_page_fault(unsigned long entry, unsigned long addr,
|
|||
tsk->thread.address = addr;
|
||||
tsk->thread.error_code = error_code;
|
||||
tsk->thread.trap_no = entry;
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* info.si_code has been set above */
|
||||
info.si_addr = (void *)addr;
|
||||
force_sig_info(SIGSEGV, &info, tsk);
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *)addr, tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -339,11 +335,7 @@ void do_page_fault(unsigned long entry, unsigned long addr,
|
|||
tsk->thread.address = addr;
|
||||
tsk->thread.error_code = error_code;
|
||||
tsk->thread.trap_no = entry;
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void *)addr;
|
||||
force_sig_info(SIGBUS, &info, tsk);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)addr, tsk);
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
@ -26,13 +26,7 @@ static DEFINE_SPINLOCK(die_lock);
|
|||
|
||||
static void _send_sig(int signo, int code, unsigned long addr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = (void __user *) addr;
|
||||
force_sig_info(signo, &info, current);
|
||||
force_sig_fault(signo, code, (void __user *) addr, current);
|
||||
}
|
||||
|
||||
void die(const char *str, struct pt_regs *regs, long err)
|
||||
|
|
|
@ -250,27 +250,16 @@ void __init trap_init(void)
|
|||
|
||||
asmlinkage void do_trap(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
siginfo_t info;
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_code = TRAP_TRACE;
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_TRACE, (void __user *)address, current);
|
||||
|
||||
regs->pc += 4;
|
||||
}
|
||||
|
||||
asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
/* Send a SIGBUS */
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)address, current);
|
||||
} else {
|
||||
printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
|
||||
show_registers(regs);
|
||||
|
@ -281,15 +270,9 @@ asmlinkage void do_unaligned_access(struct pt_regs *regs, unsigned long address)
|
|||
|
||||
asmlinkage void do_bus_fault(struct pt_regs *regs, unsigned long address)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
/* Send a SIGBUS */
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, current);
|
||||
} else { /* Kernel mode */
|
||||
printk("KERNEL: Bus error (SIGBUS) 0x%.8lx\n", address);
|
||||
show_registers(regs);
|
||||
|
@ -464,7 +447,6 @@ static inline void simulate_swa(struct pt_regs *regs, unsigned long address,
|
|||
asmlinkage void do_illegal_instruction(struct pt_regs *regs,
|
||||
unsigned long address)
|
||||
{
|
||||
siginfo_t info;
|
||||
unsigned int op;
|
||||
unsigned int insn = *((unsigned int *)address);
|
||||
|
||||
|
@ -485,11 +467,7 @@ asmlinkage void do_illegal_instruction(struct pt_regs *regs,
|
|||
|
||||
if (user_mode(regs)) {
|
||||
/* Send a SIGILL */
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLOPC;
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)address, current);
|
||||
} else { /* Kernel mode */
|
||||
printk("KERNEL: Illegal instruction (SIGILL) 0x%.8lx\n",
|
||||
address);
|
||||
|
|
|
@ -52,7 +52,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
struct vm_area_struct *vma;
|
||||
siginfo_t info;
|
||||
int si_code;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
|
@ -97,7 +97,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
}
|
||||
|
||||
mm = tsk->mm;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
si_code = SEGV_MAPERR;
|
||||
|
||||
/*
|
||||
* If we're in an interrupt or have no user
|
||||
|
@ -139,7 +139,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
*/
|
||||
|
||||
good_area:
|
||||
info.si_code = SEGV_ACCERR;
|
||||
si_code = SEGV_ACCERR;
|
||||
|
||||
/* first do some preliminary protection checks */
|
||||
|
||||
|
@ -213,11 +213,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
/* User mode accesses just cause a SIGSEGV */
|
||||
|
||||
if (user_mode(regs)) {
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* info.si_code has been set above */
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGSEGV, &info, tsk);
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *)address, tsk);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -282,11 +278,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long address,
|
|||
* Send a sigbus, regardless of whether we were in kernel
|
||||
* or user mode.
|
||||
*/
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void *)address;
|
||||
force_sig_info(SIGBUS, &info, tsk);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address, tsk);
|
||||
|
||||
/* Kernel mode? Handle exceptions or die */
|
||||
if (!user_mode(regs))
|
||||
|
|
|
@ -76,8 +76,6 @@ void user_enable_single_step(struct task_struct *task)
|
|||
set_tsk_thread_flag(task, TIF_SINGLESTEP);
|
||||
|
||||
if (pa_psw(task)->n) {
|
||||
struct siginfo si;
|
||||
|
||||
/* Nullified, just crank over the queue. */
|
||||
task_regs(task)->iaoq[0] = task_regs(task)->iaoq[1];
|
||||
task_regs(task)->iasq[0] = task_regs(task)->iasq[1];
|
||||
|
@ -90,11 +88,9 @@ void user_enable_single_step(struct task_struct *task)
|
|||
ptrace_disable(task);
|
||||
/* Don't wake up the task, but let the
|
||||
parent know something happened. */
|
||||
si.si_code = TRAP_TRACE;
|
||||
si.si_addr = (void __user *) (task_regs(task)->iaoq[0] & ~3);
|
||||
si.si_signo = SIGTRAP;
|
||||
si.si_errno = 0;
|
||||
force_sig_info(SIGTRAP, &si, task);
|
||||
force_sig_fault(SIGTRAP, TRAP_TRACE,
|
||||
(void __user *) (task_regs(task)->iaoq[0] & ~3),
|
||||
task);
|
||||
/* notify_parent(task, SIGCHLD); */
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -297,13 +297,8 @@ void die_if_kernel(char *str, struct pt_regs *regs, long err)
|
|||
#define GDB_BREAK_INSN 0x10004
|
||||
static void handle_gdb_break(struct pt_regs *regs, int wot)
|
||||
{
|
||||
struct siginfo si;
|
||||
|
||||
si.si_signo = SIGTRAP;
|
||||
si.si_errno = 0;
|
||||
si.si_code = wot;
|
||||
si.si_addr = (void __user *) (regs->iaoq[0] & ~3);
|
||||
force_sig_info(SIGTRAP, &si, current);
|
||||
force_sig_fault(SIGTRAP, wot,
|
||||
(void __user *) (regs->iaoq[0] & ~3), current);
|
||||
}
|
||||
|
||||
static void handle_break(struct pt_regs *regs)
|
||||
|
@ -487,7 +482,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
{
|
||||
unsigned long fault_address = 0;
|
||||
unsigned long fault_space = 0;
|
||||
struct siginfo si;
|
||||
int si_code;
|
||||
|
||||
if (code == 1)
|
||||
pdc_console_restart(); /* switch back to pdc if HPMC */
|
||||
|
@ -571,7 +566,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
case 8:
|
||||
/* Illegal instruction trap */
|
||||
die_if_kernel("Illegal instruction", regs, code);
|
||||
si.si_code = ILL_ILLOPC;
|
||||
si_code = ILL_ILLOPC;
|
||||
goto give_sigill;
|
||||
|
||||
case 9:
|
||||
|
@ -582,7 +577,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
case 10:
|
||||
/* Privileged operation trap */
|
||||
die_if_kernel("Privileged operation", regs, code);
|
||||
si.si_code = ILL_PRVOPC;
|
||||
si_code = ILL_PRVOPC;
|
||||
goto give_sigill;
|
||||
|
||||
case 11:
|
||||
|
@ -605,20 +600,16 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
}
|
||||
|
||||
die_if_kernel("Privileged register usage", regs, code);
|
||||
si.si_code = ILL_PRVREG;
|
||||
si_code = ILL_PRVREG;
|
||||
give_sigill:
|
||||
si.si_signo = SIGILL;
|
||||
si.si_errno = 0;
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
force_sig_info(SIGILL, &si, current);
|
||||
force_sig_fault(SIGILL, si_code,
|
||||
(void __user *) regs->iaoq[0], current);
|
||||
return;
|
||||
|
||||
case 12:
|
||||
/* Overflow Trap, let the userland signal handler do the cleanup */
|
||||
si.si_signo = SIGFPE;
|
||||
si.si_code = FPE_INTOVF;
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
force_sig_info(SIGFPE, &si, current);
|
||||
force_sig_fault(SIGFPE, FPE_INTOVF,
|
||||
(void __user *) regs->iaoq[0], current);
|
||||
return;
|
||||
|
||||
case 13:
|
||||
|
@ -626,13 +617,11 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
The condition succeeds in an instruction which traps
|
||||
on condition */
|
||||
if(user_mode(regs)){
|
||||
si.si_signo = SIGFPE;
|
||||
/* Let userspace app figure it out from the insn pointed
|
||||
* to by si_addr.
|
||||
*/
|
||||
si.si_code = FPE_CONDTRAP;
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
force_sig_info(SIGFPE, &si, current);
|
||||
force_sig_fault(SIGFPE, FPE_CONDTRAP,
|
||||
(void __user *) regs->iaoq[0], current);
|
||||
return;
|
||||
}
|
||||
/* The kernel doesn't want to handle condition codes */
|
||||
|
@ -741,14 +730,10 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
return;
|
||||
|
||||
die_if_kernel("Protection id trap", regs, code);
|
||||
si.si_code = SEGV_MAPERR;
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_errno = 0;
|
||||
if (code == 7)
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
else
|
||||
si.si_addr = (void __user *) regs->ior;
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_MAPERR,
|
||||
(code == 7)?
|
||||
((void __user *) regs->iaoq[0]) :
|
||||
((void __user *) regs->ior), current);
|
||||
return;
|
||||
|
||||
case 28:
|
||||
|
@ -762,11 +747,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
"handle_interruption() pid=%d command='%s'\n",
|
||||
task_pid_nr(current), current->comm);
|
||||
/* SIGBUS, for lack of a better one. */
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_code = BUS_OBJERR;
|
||||
si.si_errno = 0;
|
||||
si.si_addr = (void __user *) regs->ior;
|
||||
force_sig_info(SIGBUS, &si, current);
|
||||
force_sig_fault(SIGBUS, BUS_OBJERR,
|
||||
(void __user *)regs->ior, current);
|
||||
return;
|
||||
}
|
||||
pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
|
||||
|
@ -781,11 +763,8 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
|
|||
"User fault %d on space 0x%08lx, pid=%d command='%s'\n",
|
||||
code, fault_space,
|
||||
task_pid_nr(current), current->comm);
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_errno = 0;
|
||||
si.si_code = SEGV_MAPERR;
|
||||
si.si_addr = (void __user *) regs->ior;
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_MAPERR,
|
||||
(void __user *)regs->ior, current);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -452,7 +452,6 @@ void handle_unaligned(struct pt_regs *regs)
|
|||
unsigned long newbase = R1(regs->iir)?regs->gr[R1(regs->iir)]:0;
|
||||
int modify = 0;
|
||||
int ret = ERR_NOTHANDLED;
|
||||
struct siginfo si;
|
||||
register int flop=0; /* true if this is a flop */
|
||||
|
||||
__inc_irq_stat(irq_unaligned_count);
|
||||
|
@ -690,21 +689,15 @@ void handle_unaligned(struct pt_regs *regs)
|
|||
|
||||
if (ret == ERR_PAGEFAULT)
|
||||
{
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_errno = 0;
|
||||
si.si_code = SEGV_MAPERR;
|
||||
si.si_addr = (void __user *)regs->ior;
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_MAPERR,
|
||||
(void __user *)regs->ior, current);
|
||||
}
|
||||
else
|
||||
{
|
||||
force_sigbus:
|
||||
/* couldn't handle it ... */
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_errno = 0;
|
||||
si.si_code = BUS_ADRALN;
|
||||
si.si_addr = (void __user *)regs->ior;
|
||||
force_sig_info(SIGBUS, &si, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN,
|
||||
(void __user *)regs->ior, current);
|
||||
}
|
||||
|
||||
return;
|
||||
|
|
|
@ -81,7 +81,6 @@ int
|
|||
handle_fpe(struct pt_regs *regs)
|
||||
{
|
||||
extern void printbinary(unsigned long x, int nbits);
|
||||
struct siginfo si;
|
||||
unsigned int orig_sw, sw;
|
||||
int signalcode;
|
||||
/* need an intermediate copy of float regs because FPU emulation
|
||||
|
@ -117,11 +116,8 @@ handle_fpe(struct pt_regs *regs)
|
|||
|
||||
memcpy(regs->fr, frcopy, sizeof regs->fr);
|
||||
if (signalcode != 0) {
|
||||
si.si_signo = signalcode >> 24;
|
||||
si.si_errno = 0;
|
||||
si.si_code = signalcode & 0xffffff;
|
||||
si.si_addr = (void __user *) regs->iaoq[0];
|
||||
force_sig_info(si.si_signo, &si, current);
|
||||
force_sig_fault(signalcode >> 24, signalcode & 0xffffff,
|
||||
(void __user *) regs->iaoq[0], current);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -353,23 +353,22 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
|
|||
up_read(&mm->mmap_sem);
|
||||
|
||||
if (user_mode(regs)) {
|
||||
struct siginfo si;
|
||||
unsigned int lsb = 0;
|
||||
int signo, si_code;
|
||||
|
||||
switch (code) {
|
||||
case 15: /* Data TLB miss fault/Data page fault */
|
||||
/* send SIGSEGV when outside of vma */
|
||||
if (!vma ||
|
||||
address < vma->vm_start || address >= vma->vm_end) {
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_code = SEGV_MAPERR;
|
||||
signo = SIGSEGV;
|
||||
si_code = SEGV_MAPERR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* send SIGSEGV for wrong permissions */
|
||||
if ((vma->vm_flags & acc_type) != acc_type) {
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_code = SEGV_ACCERR;
|
||||
signo = SIGSEGV;
|
||||
si_code = SEGV_ACCERR;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -377,43 +376,40 @@ void do_page_fault(struct pt_regs *regs, unsigned long code,
|
|||
/* fall through */
|
||||
case 17: /* NA data TLB miss / page fault */
|
||||
case 18: /* Unaligned access - PCXS only */
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_code = (code == 18) ? BUS_ADRALN : BUS_ADRERR;
|
||||
signo = SIGBUS;
|
||||
si_code = (code == 18) ? BUS_ADRALN : BUS_ADRERR;
|
||||
break;
|
||||
case 16: /* Non-access instruction TLB miss fault */
|
||||
case 26: /* PCXL: Data memory access rights trap */
|
||||
default:
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
|
||||
signo = SIGSEGV;
|
||||
si_code = (code == 26) ? SEGV_ACCERR : SEGV_MAPERR;
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_MEMORY_FAILURE
|
||||
if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) {
|
||||
unsigned int lsb = 0;
|
||||
printk(KERN_ERR
|
||||
"MCE: Killing %s:%d due to hardware memory corruption fault at %08lx\n",
|
||||
tsk->comm, tsk->pid, address);
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_code = BUS_MCEERR_AR;
|
||||
/*
|
||||
* Either small page or large page may be poisoned.
|
||||
* In other words, VM_FAULT_HWPOISON_LARGE and
|
||||
* VM_FAULT_HWPOISON are mutually exclusive.
|
||||
*/
|
||||
if (fault & VM_FAULT_HWPOISON_LARGE)
|
||||
lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
|
||||
else if (fault & VM_FAULT_HWPOISON)
|
||||
lsb = PAGE_SHIFT;
|
||||
|
||||
force_sig_mceerr(BUS_MCEERR_AR, (void __user *) address,
|
||||
lsb, current);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
show_signal_msg(regs, code, address, tsk, vma);
|
||||
|
||||
/*
|
||||
* Either small page or large page may be poisoned.
|
||||
* In other words, VM_FAULT_HWPOISON_LARGE and
|
||||
* VM_FAULT_HWPOISON are mutually exclusive.
|
||||
*/
|
||||
if (fault & VM_FAULT_HWPOISON_LARGE)
|
||||
lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault));
|
||||
else if (fault & VM_FAULT_HWPOISON)
|
||||
lsb = PAGE_SHIFT;
|
||||
else
|
||||
show_signal_msg(regs, code, address, tsk, vma);
|
||||
si.si_addr_lsb = lsb;
|
||||
|
||||
si.si_errno = 0;
|
||||
si.si_addr = (void __user *) address;
|
||||
force_sig_info(si.si_signo, &si, current);
|
||||
force_sig_fault(signo, si_code, (void __user *) address, current);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -15,19 +15,4 @@
|
|||
|
||||
#include <asm-generic/siginfo.h>
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* SIGTRAP si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define TRAP_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
|
||||
#endif /* _ASM_POWERPC_SIGINFO_H */
|
||||
|
|
|
@ -632,6 +632,7 @@ void do_break (struct pt_regs *regs, unsigned long address,
|
|||
hw_breakpoint_disable();
|
||||
|
||||
/* Deliver the signal to userspace */
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
|
|
|
@ -296,7 +296,6 @@ NOKPROBE_SYMBOL(die);
|
|||
void user_single_step_siginfo(struct task_struct *tsk,
|
||||
struct pt_regs *regs, siginfo_t *info)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->si_signo = SIGTRAP;
|
||||
info->si_code = TRAP_TRACE;
|
||||
info->si_addr = (void __user *)regs->nip;
|
||||
|
@ -334,7 +333,7 @@ void _exception_pkey(int signr, struct pt_regs *regs, int code,
|
|||
*/
|
||||
thread_pkey_regs_save(¤t->thread);
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = signr;
|
||||
info.si_code = code;
|
||||
info.si_addr = (void __user *) addr;
|
||||
|
@ -970,7 +969,7 @@ void unknown_exception(struct pt_regs *regs)
|
|||
printk("Bad trap at PC: %lx, SR: %lx, vector=%lx\n",
|
||||
regs->nip, regs->msr, regs->trap);
|
||||
|
||||
_exception(SIGTRAP, regs, TRAP_FIXME, 0);
|
||||
_exception(SIGTRAP, regs, TRAP_UNK, 0);
|
||||
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -992,7 +991,7 @@ void instruction_breakpoint_exception(struct pt_regs *regs)
|
|||
|
||||
void RunModeException(struct pt_regs *regs)
|
||||
{
|
||||
_exception(SIGTRAP, regs, TRAP_FIXME, 0);
|
||||
_exception(SIGTRAP, regs, TRAP_UNK, 0);
|
||||
}
|
||||
|
||||
void single_step_exception(struct pt_regs *regs)
|
||||
|
@ -1032,7 +1031,7 @@ static void emulate_single_step(struct pt_regs *regs)
|
|||
|
||||
static inline int __parse_fpscr(unsigned long fpscr)
|
||||
{
|
||||
int ret = FPE_FIXME;
|
||||
int ret = FPE_FLTUNK;
|
||||
|
||||
/* Invalid operation */
|
||||
if ((fpscr & FPSCR_VE) && (fpscr & FPSCR_VX))
|
||||
|
@ -1973,7 +1972,7 @@ void SPEFloatingPointException(struct pt_regs *regs)
|
|||
extern int do_spe_mathemu(struct pt_regs *regs);
|
||||
unsigned long spefscr;
|
||||
int fpexc_mode;
|
||||
int code = FPE_FIXME;
|
||||
int code = FPE_FLTUNK;
|
||||
int err;
|
||||
|
||||
flush_spe_to_thread(current);
|
||||
|
@ -2042,7 +2041,7 @@ void SPEFloatingPointRoundException(struct pt_regs *regs)
|
|||
printk(KERN_ERR "unrecognized spe instruction "
|
||||
"in %s at %lx\n", current->comm, regs->nip);
|
||||
} else {
|
||||
_exception(SIGFPE, regs, FPE_FIXME, regs->nip);
|
||||
_exception(SIGFPE, regs, FPE_FLTUNK, regs->nip);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -168,6 +168,7 @@ static int do_sigbus(struct pt_regs *regs, unsigned long address,
|
|||
return SIGBUS;
|
||||
|
||||
current->thread.trap_nr = BUS_ADRERR;
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
|
|
|
@ -44,7 +44,7 @@ static void spufs_handle_event(struct spu_context *ctx,
|
|||
return;
|
||||
}
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
clear_siginfo(&info);
|
||||
|
||||
switch (type) {
|
||||
case SPE_EVENT_INVALID_DMA:
|
||||
|
|
|
@ -63,18 +63,6 @@ void die(struct pt_regs *regs, const char *str)
|
|||
do_exit(SIGSEGV);
|
||||
}
|
||||
|
||||
static inline void do_trap_siginfo(int signo, int code,
|
||||
unsigned long addr, struct task_struct *tsk)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = code;
|
||||
info.si_addr = (void __user *)addr;
|
||||
force_sig_info(signo, &info, tsk);
|
||||
}
|
||||
|
||||
void do_trap(struct pt_regs *regs, int signo, int code,
|
||||
unsigned long addr, struct task_struct *tsk)
|
||||
{
|
||||
|
@ -87,7 +75,7 @@ void do_trap(struct pt_regs *regs, int signo, int code,
|
|||
show_regs(regs);
|
||||
}
|
||||
|
||||
do_trap_siginfo(signo, code, addr, tsk);
|
||||
force_sig_fault(signo, code, (void __user *)addr, tsk);
|
||||
}
|
||||
|
||||
static void do_trap_error(struct pt_regs *regs, int signo, int code,
|
||||
|
@ -149,7 +137,7 @@ asmlinkage void do_trap_break(struct pt_regs *regs)
|
|||
}
|
||||
#endif /* CONFIG_GENERIC_BUG */
|
||||
|
||||
do_trap_siginfo(SIGTRAP, TRAP_BRKPT, regs->sepc, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)(regs->sepc), current);
|
||||
regs->sepc += 0x4;
|
||||
}
|
||||
|
||||
|
|
|
@ -44,14 +44,8 @@ int is_valid_bugaddr(unsigned long addr)
|
|||
|
||||
void do_report_trap(struct pt_regs *regs, int si_signo, int si_code, char *str)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (user_mode(regs)) {
|
||||
info.si_signo = si_signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = get_trap_ip(regs);
|
||||
force_sig_info(si_signo, &info, current);
|
||||
force_sig_fault(si_signo, si_code, get_trap_ip(regs), current);
|
||||
report_user_fault(regs, si_signo, 0);
|
||||
} else {
|
||||
const struct exception_table_entry *fixup;
|
||||
|
@ -80,18 +74,12 @@ NOKPROBE_SYMBOL(do_trap);
|
|||
|
||||
void do_per_trap(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
|
||||
return;
|
||||
if (!current->ptrace)
|
||||
return;
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
info.si_addr =
|
||||
(void __force __user *) current->thread.per_event.address;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_HWBKPT,
|
||||
(void __force __user *) current->thread.per_event.address, current);
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_per_trap);
|
||||
|
||||
|
@ -165,7 +153,6 @@ void translation_exception(struct pt_regs *regs)
|
|||
|
||||
void illegal_op(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
__u8 opcode[6];
|
||||
__u16 __user *location;
|
||||
int is_uprobe_insn = 0;
|
||||
|
@ -177,13 +164,9 @@ void illegal_op(struct pt_regs *regs)
|
|||
if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
|
||||
return;
|
||||
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
|
||||
if (current->ptrace) {
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_addr = location;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
} else
|
||||
if (current->ptrace)
|
||||
force_sig_fault(SIGTRAP, TRAP_BRKPT, location, current);
|
||||
else
|
||||
signal = SIGILL;
|
||||
#ifdef CONFIG_UPROBES
|
||||
} else if (*((__u16 *) opcode) == UPROBE_SWBP_INSN) {
|
||||
|
|
|
@ -265,14 +265,10 @@ void report_user_fault(struct pt_regs *regs, long signr, int is_mm_fault)
|
|||
*/
|
||||
static noinline void do_sigsegv(struct pt_regs *regs, int si_code)
|
||||
{
|
||||
struct siginfo si;
|
||||
|
||||
report_user_fault(regs, SIGSEGV, 1);
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_errno = 0;
|
||||
si.si_code = si_code;
|
||||
si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
force_sig_fault(SIGSEGV, si_code,
|
||||
(void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK),
|
||||
current);
|
||||
}
|
||||
|
||||
static noinline void do_no_context(struct pt_regs *regs)
|
||||
|
@ -316,18 +312,13 @@ static noinline void do_low_address(struct pt_regs *regs)
|
|||
|
||||
static noinline void do_sigbus(struct pt_regs *regs)
|
||||
{
|
||||
struct task_struct *tsk = current;
|
||||
struct siginfo si;
|
||||
|
||||
/*
|
||||
* Send a sigbus, regardless of whether we were in kernel
|
||||
* or user mode.
|
||||
*/
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_errno = 0;
|
||||
si.si_code = BUS_ADRERR;
|
||||
si.si_addr = (void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK);
|
||||
force_sig_info(SIGBUS, &si, tsk);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR,
|
||||
(void __user *)(regs->int_parm_long & __FAIL_ADDR_MASK),
|
||||
current);
|
||||
}
|
||||
|
||||
static noinline int signal_return(struct pt_regs *regs)
|
||||
|
|
|
@ -347,13 +347,8 @@ static int __kprobes hw_breakpoint_handler(struct die_args *args)
|
|||
|
||||
/* Deliver the signal to userspace */
|
||||
if (!arch_check_bp_in_kernelspace(bp)) {
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = args->signr;
|
||||
info.si_errno = notifier_to_errno(rc);
|
||||
info.si_code = TRAP_HWBKPT;
|
||||
|
||||
force_sig_info(args->signr, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_HWBKPT,
|
||||
(void __user *)NULL, current);
|
||||
}
|
||||
|
||||
rcu_read_unlock();
|
||||
|
|
|
@ -477,7 +477,6 @@ asmlinkage void do_address_error(struct pt_regs *regs,
|
|||
{
|
||||
unsigned long error_code = 0;
|
||||
mm_segment_t oldfs;
|
||||
siginfo_t info;
|
||||
insn_size_t instruction;
|
||||
int tmp;
|
||||
|
||||
|
@ -537,11 +536,7 @@ asmlinkage void do_address_error(struct pt_regs *regs,
|
|||
"access (PC %lx PR %lx)\n", current->comm, regs->pc,
|
||||
regs->pr);
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *)address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, si_code, (void __user *)address, current);
|
||||
} else {
|
||||
inc_unaligned_kernel_access();
|
||||
|
||||
|
@ -598,19 +593,20 @@ int is_dsp_inst(struct pt_regs *regs)
|
|||
#ifdef CONFIG_CPU_SH2A
|
||||
asmlinkage void do_divide_error(unsigned long r4)
|
||||
{
|
||||
siginfo_t info;
|
||||
int code;
|
||||
|
||||
switch (r4) {
|
||||
case TRAP_DIVZERO_ERROR:
|
||||
info.si_code = FPE_INTDIV;
|
||||
code = FPE_INTDIV;
|
||||
break;
|
||||
case TRAP_DIVOVF_ERROR:
|
||||
info.si_code = FPE_INTOVF;
|
||||
code = FPE_INTOVF;
|
||||
break;
|
||||
default:
|
||||
/* Let gcc know unhandled cases don't make it past here */
|
||||
return;
|
||||
}
|
||||
|
||||
info.si_signo = SIGFPE;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
force_sig_fault(SIGFPE, code, NULL, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -507,7 +507,6 @@ static int ieee_fpe_handler(struct pt_regs *regs)
|
|||
unsigned short insn = *(unsigned short *)regs->pc;
|
||||
unsigned short finsn;
|
||||
unsigned long nextpc;
|
||||
siginfo_t info;
|
||||
int nib[4] = {
|
||||
(insn >> 12) & 0xf,
|
||||
(insn >> 8) & 0xf,
|
||||
|
@ -560,11 +559,8 @@ static int ieee_fpe_handler(struct pt_regs *regs)
|
|||
~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK);
|
||||
task_thread_info(tsk)->status |= TS_USEDFPU;
|
||||
} else {
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = FPE_FLTINV;
|
||||
info.si_addr = (void __user *)regs->pc;
|
||||
force_sig_info(SIGFPE, &info, tsk);
|
||||
force_sig_fault(SIGFPE, FPE_FLTINV,
|
||||
(void __user *)regs->pc, tsk);
|
||||
}
|
||||
|
||||
regs->pc = nextpc;
|
||||
|
|
|
@ -42,14 +42,7 @@ static void
|
|||
force_sig_info_fault(int si_signo, int si_code, unsigned long address,
|
||||
struct task_struct *tsk)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = si_signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
info.si_addr = (void __user *)address;
|
||||
|
||||
force_sig_info(si_signo, &info, tsk);
|
||||
force_sig_fault(si_signo, si_code, (void __user *)address, tsk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -17,13 +17,6 @@
|
|||
|
||||
#define SI_NOINFO 32767 /* no information in siginfo_t */
|
||||
|
||||
/*
|
||||
* SIGFPE si_codes
|
||||
*/
|
||||
#ifdef __KERNEL__
|
||||
#define FPE_FIXME 0 /* Broken dup of SI_USER */
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
/*
|
||||
* SIGEMT si_codes
|
||||
*/
|
||||
|
|
|
@ -518,14 +518,7 @@ void synchronize_user_stack(void)
|
|||
|
||||
static void stack_unaligned(unsigned long sp)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *) sp;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) sp, 0, current);
|
||||
}
|
||||
|
||||
void fault_in_user_windows(void)
|
||||
|
|
|
@ -147,17 +147,11 @@ SYSCALL_DEFINE0(nis_syscall)
|
|||
asmlinkage void
|
||||
sparc_breakpoint (struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
#ifdef DEBUG_SPARC_BREAKPOINT
|
||||
printk ("TRAP: Entering kernel PC=%x, nPC=%x\n", regs->pc, regs->npc);
|
||||
#endif
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_addr = (void __user *)regs->pc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->pc, 0, current);
|
||||
|
||||
#ifdef DEBUG_SPARC_BREAKPOINT
|
||||
printk ("TRAP: Returning to space: PC=%x nPC=%x\n", regs->pc, regs->npc);
|
||||
|
|
|
@ -502,7 +502,6 @@ SYSCALL_DEFINE0(nis_syscall)
|
|||
asmlinkage void sparc_breakpoint(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
|
@ -511,12 +510,7 @@ asmlinkage void sparc_breakpoint(struct pt_regs *regs)
|
|||
#ifdef DEBUG_SPARC_BREAKPOINT
|
||||
printk ("TRAP: Entering kernel PC=%lx, nPC=%lx\n", regs->tpc, regs->tnpc);
|
||||
#endif
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_errno = 0;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
force_sig_fault(SIGTRAP, TRAP_BRKPT, (void __user *)regs->tpc, 0, current);
|
||||
#ifdef DEBUG_SPARC_BREAKPOINT
|
||||
printk ("TRAP: Returning to space: PC=%lx nPC=%lx\n", regs->tpc, regs->tnpc);
|
||||
#endif
|
||||
|
|
|
@ -93,8 +93,6 @@ void __noreturn die_if_kernel(char *str, struct pt_regs *regs)
|
|||
|
||||
void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if(type < 0x80) {
|
||||
/* Sun OS's puke from bad traps, Linux survives! */
|
||||
printk("Unimplemented Sparc TRAP, type = %02lx\n", type);
|
||||
|
@ -104,19 +102,13 @@ void do_hw_interrupt(struct pt_regs *regs, unsigned long type)
|
|||
if(regs->psr & PSR_PS)
|
||||
die_if_kernel("Kernel bad trap", regs);
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLTRP;
|
||||
info.si_addr = (void __user *)regs->pc;
|
||||
info.si_trapno = type - 0x80;
|
||||
force_sig_info(SIGILL, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_ILLTRP,
|
||||
(void __user *)regs->pc, type - 0x80, current);
|
||||
}
|
||||
|
||||
void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if(psr & PSR_PS)
|
||||
die_if_kernel("Kernel illegal instruction", regs);
|
||||
#ifdef TRAP_DEBUG
|
||||
|
@ -124,27 +116,15 @@ void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned lon
|
|||
regs->pc, *(unsigned long *)regs->pc);
|
||||
#endif
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLOPC;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGILL, &info, current);
|
||||
send_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
void do_priv_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if(psr & PSR_PS)
|
||||
die_if_kernel("Penguin instruction from Penguin mode??!?!", regs);
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_PRVOPC;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGILL, &info, current);
|
||||
send_sig_fault(SIGILL, ILL_PRVOPC, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
/* XXX User may want to be allowed to do this. XXX */
|
||||
|
@ -152,8 +132,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 psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if(regs->psr & PSR_PS) {
|
||||
printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
|
||||
regs->u_regs[UREG_RETPC]);
|
||||
|
@ -165,12 +143,9 @@ void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned lon
|
|||
instruction_dump ((unsigned long *) regs->pc);
|
||||
printk ("do_MNA!\n");
|
||||
#endif
|
||||
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);
|
||||
send_sig_fault(SIGBUS, BUS_ADRALN,
|
||||
/* FIXME: Should dig out mna address */ (void *)0,
|
||||
0, current);
|
||||
}
|
||||
|
||||
static unsigned long init_fsr = 0x0UL;
|
||||
|
@ -226,9 +201,9 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
|||
unsigned long psr)
|
||||
{
|
||||
static int calls;
|
||||
siginfo_t info;
|
||||
unsigned long fsr;
|
||||
int ret = 0;
|
||||
int code;
|
||||
#ifndef CONFIG_SMP
|
||||
struct task_struct *fpt = last_task_used_math;
|
||||
#else
|
||||
|
@ -303,24 +278,20 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
|||
}
|
||||
|
||||
fsr = fpt->thread.fsr;
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
info.si_code = FPE_FIXME;
|
||||
code = FPE_FLTUNK;
|
||||
if ((fsr & 0x1c000) == (1 << 14)) {
|
||||
if (fsr & 0x10)
|
||||
info.si_code = FPE_FLTINV;
|
||||
code = FPE_FLTINV;
|
||||
else if (fsr & 0x08)
|
||||
info.si_code = FPE_FLTOVF;
|
||||
code = FPE_FLTOVF;
|
||||
else if (fsr & 0x04)
|
||||
info.si_code = FPE_FLTUND;
|
||||
code = FPE_FLTUND;
|
||||
else if (fsr & 0x02)
|
||||
info.si_code = FPE_FLTDIV;
|
||||
code = FPE_FLTDIV;
|
||||
else if (fsr & 0x01)
|
||||
info.si_code = FPE_FLTRES;
|
||||
code = FPE_FLTRES;
|
||||
}
|
||||
send_sig_info(SIGFPE, &info, fpt);
|
||||
send_sig_fault(SIGFPE, code, (void __user *)pc, 0, fpt);
|
||||
#ifndef CONFIG_SMP
|
||||
last_task_used_math = NULL;
|
||||
#endif
|
||||
|
@ -332,16 +303,9 @@ void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
|||
void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if(psr & PSR_PS)
|
||||
die_if_kernel("Penguin overflow trap from kernel mode", regs);
|
||||
info.si_signo = SIGEMT;
|
||||
info.si_errno = 0;
|
||||
info.si_code = EMT_TAGOVF;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGEMT, &info, current);
|
||||
send_sig_fault(SIGEMT, EMT_TAGOVF, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
|
@ -359,61 +323,33 @@ void handle_watchpoint(struct pt_regs *regs, unsigned long pc, unsigned long npc
|
|||
void handle_reg_access(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
#ifdef TRAP_DEBUG
|
||||
printk("Register Access Exception at PC %08lx NPC %08lx PSR %08lx\n",
|
||||
pc, npc, psr);
|
||||
#endif
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_OBJERR;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_OBJERR, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
void handle_cp_disabled(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_COPROC;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGILL, &info, current);
|
||||
send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
void handle_cp_exception(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
#ifdef TRAP_DEBUG
|
||||
printk("Co-Processor Exception at PC %08lx NPC %08lx PSR %08lx\n",
|
||||
pc, npc, psr);
|
||||
#endif
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_COPROC;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGILL, &info, current);
|
||||
send_sig_fault(SIGILL, ILL_COPROC, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
void handle_hw_divzero(struct pt_regs *regs, unsigned long pc, unsigned long npc,
|
||||
unsigned long psr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = FPE_INTDIV;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGFPE, &info, current);
|
||||
send_sig_fault(SIGFPE, FPE_INTDIV, (void __user *)pc, 0, current);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEBUG_BUGVERBOSE
|
||||
|
|
|
@ -87,7 +87,6 @@ static void dump_tl1_traplog(struct tl1_traplog *p)
|
|||
void bad_trap(struct pt_regs *regs, long lvl)
|
||||
{
|
||||
char buffer[36];
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "bad trap", regs,
|
||||
0, lvl, SIGTRAP) == NOTIFY_STOP)
|
||||
|
@ -107,12 +106,8 @@ void bad_trap(struct pt_regs *regs, long lvl)
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLTRP;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = lvl;
|
||||
force_sig_info(SIGILL, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_ILLTRP,
|
||||
(void __user *)regs->tpc, lvl, current);
|
||||
}
|
||||
|
||||
void bad_trap_tl1(struct pt_regs *regs, long lvl)
|
||||
|
@ -191,7 +186,6 @@ EXPORT_SYMBOL_GPL(unregister_dimm_printer);
|
|||
void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "instruction access exception", regs,
|
||||
0, 0x8, SIGTRAP) == NOTIFY_STOP)
|
||||
|
@ -206,12 +200,8 @@ void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, un
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_MAPERR,
|
||||
(void __user *)regs->tpc, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -230,7 +220,6 @@ void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsig
|
|||
{
|
||||
unsigned short type = (type_ctx >> 16);
|
||||
unsigned short ctx = (type_ctx & 0xffff);
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "instruction access exception", regs,
|
||||
0, 0x8, SIGTRAP) == NOTIFY_STOP)
|
||||
|
@ -247,12 +236,7 @@ void sun4v_insn_access_exception(struct pt_regs *regs, unsigned long addr, unsig
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void __user *) addr;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *) addr, 0, current);
|
||||
}
|
||||
|
||||
void sun4v_insn_access_exception_tl1(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
|
||||
|
@ -307,7 +291,6 @@ bool is_no_fault_exception(struct pt_regs *regs)
|
|||
void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "data access exception", regs,
|
||||
0, 0x30, SIGTRAP) == NOTIFY_STOP)
|
||||
|
@ -338,12 +321,7 @@ void spitfire_data_access_exception(struct pt_regs *regs, unsigned long sfsr, un
|
|||
if (is_no_fault_exception(regs))
|
||||
return;
|
||||
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
info.si_addr = (void __user *)sfar;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_MAPERR, (void __user *)sfar, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -559,8 +537,6 @@ static void spitfire_cee_log(unsigned long afsr, unsigned long afar, unsigned lo
|
|||
|
||||
static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned long udbh, unsigned long udbl, unsigned long tt, int tl1, struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
printk(KERN_WARNING "CPU[%d]: Uncorrectable Error AFSR[%lx] "
|
||||
"AFAR[%lx] UDBL[%lx] UDBH[%ld] TT[%lx] TL>1[%d]\n",
|
||||
smp_processor_id(), afsr, afar, udbl, udbh, tt, tl1);
|
||||
|
@ -595,12 +571,7 @@ static void spitfire_ue_log(unsigned long afsr, unsigned long afar, unsigned lon
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_OBJERR;
|
||||
info.si_addr = (void *)0;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_OBJERR, (void *)0, 0, current);
|
||||
}
|
||||
|
||||
void spitfire_access_error(struct pt_regs *regs, unsigned long status_encoded, unsigned long afar)
|
||||
|
@ -2190,7 +2161,6 @@ bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
|
|||
|
||||
if (attrs & SUN4V_ERR_ATTRS_MEMORY) {
|
||||
unsigned long addr = ent->err_raddr;
|
||||
siginfo_t info;
|
||||
|
||||
if (addr == ~(u64)0) {
|
||||
/* This seems highly unlikely to ever occur */
|
||||
|
@ -2211,21 +2181,13 @@ bool sun4v_nonresum_error_user_handled(struct pt_regs *regs,
|
|||
addr += PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
info.si_signo = SIGKILL;
|
||||
info.si_errno = 0;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
force_sig(SIGKILL, current);
|
||||
|
||||
return true;
|
||||
}
|
||||
if (attrs & SUN4V_ERR_ATTRS_PIO) {
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void __user *)sun4v_get_vaddr(regs);
|
||||
force_sig_info(info.si_signo, &info, current);
|
||||
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR,
|
||||
(void __user *)sun4v_get_vaddr(regs), 0, current);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2362,30 +2324,27 @@ static void do_fpe_common(struct pt_regs *regs)
|
|||
regs->tnpc += 4;
|
||||
} else {
|
||||
unsigned long fsr = current_thread_info()->xfsr[0];
|
||||
siginfo_t info;
|
||||
int code;
|
||||
|
||||
if (test_thread_flag(TIF_32BIT)) {
|
||||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = 0;
|
||||
info.si_code = FPE_FIXME;
|
||||
code = FPE_FLTUNK;
|
||||
if ((fsr & 0x1c000) == (1 << 14)) {
|
||||
if (fsr & 0x10)
|
||||
info.si_code = FPE_FLTINV;
|
||||
code = FPE_FLTINV;
|
||||
else if (fsr & 0x08)
|
||||
info.si_code = FPE_FLTOVF;
|
||||
code = FPE_FLTOVF;
|
||||
else if (fsr & 0x04)
|
||||
info.si_code = FPE_FLTUND;
|
||||
code = FPE_FLTUND;
|
||||
else if (fsr & 0x02)
|
||||
info.si_code = FPE_FLTDIV;
|
||||
code = FPE_FLTDIV;
|
||||
else if (fsr & 0x01)
|
||||
info.si_code = FPE_FLTRES;
|
||||
code = FPE_FLTRES;
|
||||
}
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
force_sig_fault(SIGFPE, code,
|
||||
(void __user *)regs->tpc, 0, current);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2428,7 +2387,6 @@ void do_fpother(struct pt_regs *regs)
|
|||
void do_tof(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "tagged arithmetic overflow", regs,
|
||||
0, 0x26, SIGEMT) == NOTIFY_STOP)
|
||||
|
@ -2440,12 +2398,8 @@ void do_tof(struct pt_regs *regs)
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGEMT;
|
||||
info.si_errno = 0;
|
||||
info.si_code = EMT_TAGOVF;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGEMT, &info, current);
|
||||
force_sig_fault(SIGEMT, EMT_TAGOVF,
|
||||
(void __user *)regs->tpc, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -2453,7 +2407,6 @@ void do_tof(struct pt_regs *regs)
|
|||
void do_div0(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "integer division by zero", regs,
|
||||
0, 0x28, SIGFPE) == NOTIFY_STOP)
|
||||
|
@ -2465,12 +2418,8 @@ void do_div0(struct pt_regs *regs)
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_code = FPE_INTDIV;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGFPE, &info, current);
|
||||
force_sig_fault(SIGFPE, FPE_INTDIV,
|
||||
(void __user *)regs->tpc, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -2632,7 +2581,6 @@ void do_illegal_instruction(struct pt_regs *regs)
|
|||
unsigned long pc = regs->tpc;
|
||||
unsigned long tstate = regs->tstate;
|
||||
u32 insn;
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "illegal instruction", regs,
|
||||
0, 0x10, SIGILL) == NOTIFY_STOP)
|
||||
|
@ -2666,12 +2614,7 @@ void do_illegal_instruction(struct pt_regs *regs)
|
|||
}
|
||||
}
|
||||
}
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_ILLOPC;
|
||||
info.si_addr = (void __user *)pc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGILL, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_ILLOPC, (void __user *)pc, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
@ -2679,7 +2622,6 @@ void do_illegal_instruction(struct pt_regs *regs)
|
|||
void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned long sfsr)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "memory address unaligned", regs,
|
||||
0, 0x34, SIGSEGV) == NOTIFY_STOP)
|
||||
|
@ -2692,20 +2634,13 @@ void mem_address_unaligned(struct pt_regs *regs, unsigned long sfar, unsigned lo
|
|||
if (is_no_fault_exception(regs))
|
||||
return;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *)sfar;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *)sfar, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
||||
void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_ctx)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "memory address unaligned", regs,
|
||||
0, 0x34, SIGSEGV) == NOTIFY_STOP)
|
||||
return;
|
||||
|
@ -2717,12 +2652,7 @@ void sun4v_do_mna(struct pt_regs *regs, unsigned long addr, unsigned long type_c
|
|||
if (is_no_fault_exception(regs))
|
||||
return;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *) addr;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void __user *) addr, 0, current);
|
||||
}
|
||||
|
||||
/* sun4v_mem_corrupt_detect_precise() - Handle precise exception on an ADI
|
||||
|
@ -2775,7 +2705,6 @@ void sun4v_mem_corrupt_detect_precise(struct pt_regs *regs, unsigned long addr,
|
|||
void do_privop(struct pt_regs *regs)
|
||||
{
|
||||
enum ctx_state prev_state = exception_enter();
|
||||
siginfo_t info;
|
||||
|
||||
if (notify_die(DIE_TRAP, "privileged operation", regs,
|
||||
0, 0x11, SIGILL) == NOTIFY_STOP)
|
||||
|
@ -2785,12 +2714,8 @@ void do_privop(struct pt_regs *regs)
|
|||
regs->tpc &= 0xffffffff;
|
||||
regs->tnpc &= 0xffffffff;
|
||||
}
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_PRVOPC;
|
||||
info.si_addr = (void __user *)regs->tpc;
|
||||
info.si_trapno = 0;
|
||||
force_sig_info(SIGILL, &info, current);
|
||||
force_sig_fault(SIGILL, ILL_PRVOPC,
|
||||
(void __user *)regs->tpc, 0, current);
|
||||
out:
|
||||
exception_exit(prev_state);
|
||||
}
|
||||
|
|
|
@ -311,14 +311,9 @@ static inline int ok_for_user(struct pt_regs *regs, unsigned int insn,
|
|||
|
||||
static void user_mna_trap_fault(struct pt_regs *regs, unsigned int insn)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void __user *)safe_compute_effective_address(regs, insn);
|
||||
info.si_trapno = 0;
|
||||
send_sig_info(SIGBUS, &info, current);
|
||||
send_sig_fault(SIGBUS, BUS_ADRALN,
|
||||
(void __user *)safe_compute_effective_address(regs, insn),
|
||||
0, current);
|
||||
}
|
||||
|
||||
asmlinkage void user_unaligned_trap(struct pt_regs *regs, unsigned int insn)
|
||||
|
|
|
@ -127,19 +127,11 @@ show_signal_msg(struct pt_regs *regs, int sig, int code,
|
|||
static void __do_fault_siginfo(int code, int sig, struct pt_regs *regs,
|
||||
unsigned long addr)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
info.si_signo = sig;
|
||||
info.si_code = code;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *) addr;
|
||||
info.si_trapno = 0;
|
||||
|
||||
if (unlikely(show_unhandled_signals))
|
||||
show_signal_msg(regs, sig, info.si_code,
|
||||
show_signal_msg(regs, sig, code,
|
||||
addr, current);
|
||||
|
||||
force_sig_info (sig, &info, current);
|
||||
force_sig_fault(sig, code, (void __user *) addr, 0, current);
|
||||
}
|
||||
|
||||
static unsigned long compute_si_addr(struct pt_regs *regs, int text_fault)
|
||||
|
|
|
@ -170,11 +170,7 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
|
|||
int fault_code)
|
||||
{
|
||||
unsigned long addr;
|
||||
siginfo_t info;
|
||||
|
||||
info.si_code = code;
|
||||
info.si_signo = sig;
|
||||
info.si_errno = 0;
|
||||
if (fault_code & FAULT_CODE_ITLB) {
|
||||
addr = regs->tpc;
|
||||
} else {
|
||||
|
@ -187,13 +183,11 @@ static void do_fault_siginfo(int code, int sig, struct pt_regs *regs,
|
|||
else
|
||||
addr = fault_addr;
|
||||
}
|
||||
info.si_addr = (void __user *) addr;
|
||||
info.si_trapno = 0;
|
||||
|
||||
if (unlikely(show_unhandled_signals))
|
||||
show_signal_msg(regs, sig, code, addr, current);
|
||||
|
||||
force_sig_info(sig, &info, current);
|
||||
force_sig_fault(sig, code, (void __user *) addr, 0, current);
|
||||
}
|
||||
|
||||
static unsigned int get_fault_insn(struct pt_regs *regs, unsigned int insn)
|
||||
|
|
|
@ -115,17 +115,10 @@ long arch_ptrace(struct task_struct *child, long request,
|
|||
static void send_sigtrap(struct task_struct *tsk, struct uml_pt_regs *regs,
|
||||
int error_code)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
info.si_signo = SIGTRAP;
|
||||
info.si_code = TRAP_BRKPT;
|
||||
|
||||
/* User-mode eip? */
|
||||
info.si_addr = UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL;
|
||||
|
||||
/* Send us the fake SIGTRAP */
|
||||
force_sig_info(SIGTRAP, &info, tsk);
|
||||
force_sig_fault(SIGTRAP, TRAP_BRKPT,
|
||||
/* User-mode eip? */
|
||||
UPT_IS_USER(regs) ? (void __user *) UPT_IP(regs) : NULL, tsk);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -162,13 +162,9 @@ static void show_segv_info(struct uml_pt_regs *regs)
|
|||
|
||||
static void bad_segv(struct faultinfo fi, unsigned long ip)
|
||||
{
|
||||
struct siginfo si;
|
||||
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_code = SEGV_ACCERR;
|
||||
si.si_addr = (void __user *) FAULT_ADDRESS(fi);
|
||||
current->thread.arch.faultinfo = fi;
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
force_sig_fault(SIGSEGV, SEGV_ACCERR, (void __user *) FAULT_ADDRESS(fi),
|
||||
current);
|
||||
}
|
||||
|
||||
void fatal_sigsegv(void)
|
||||
|
@ -214,8 +210,8 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
|
|||
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
|
||||
struct uml_pt_regs *regs)
|
||||
{
|
||||
struct siginfo si;
|
||||
jmp_buf *catcher;
|
||||
int si_code;
|
||||
int err;
|
||||
int is_write = FAULT_WRITE(fi);
|
||||
unsigned long address = FAULT_ADDRESS(fi);
|
||||
|
@ -239,7 +235,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
|
|||
|
||||
if (SEGV_IS_FIXABLE(&fi))
|
||||
err = handle_page_fault(address, ip, is_write, is_user,
|
||||
&si.si_code);
|
||||
&si_code);
|
||||
else {
|
||||
err = -EFAULT;
|
||||
/*
|
||||
|
@ -271,18 +267,14 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
|
|||
show_segv_info(regs);
|
||||
|
||||
if (err == -EACCES) {
|
||||
si.si_signo = SIGBUS;
|
||||
si.si_errno = 0;
|
||||
si.si_code = BUS_ADRERR;
|
||||
si.si_addr = (void __user *)address;
|
||||
current->thread.arch.faultinfo = fi;
|
||||
force_sig_info(SIGBUS, &si, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void __user *)address,
|
||||
current);
|
||||
} else {
|
||||
BUG_ON(err != -EFAULT);
|
||||
si.si_signo = SIGSEGV;
|
||||
si.si_addr = (void __user *) address;
|
||||
current->thread.arch.faultinfo = fi;
|
||||
force_sig_info(SIGSEGV, &si, current);
|
||||
force_sig_fault(SIGSEGV, si_code, (void __user *) address,
|
||||
current);
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -294,9 +286,7 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
|
|||
|
||||
void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
|
||||
{
|
||||
struct faultinfo *fi;
|
||||
struct siginfo clean_si;
|
||||
|
||||
int code, err;
|
||||
if (!UPT_IS_USER(regs)) {
|
||||
if (sig == SIGBUS)
|
||||
printk(KERN_ERR "Bus error - the host /dev/shm or /tmp "
|
||||
|
@ -306,29 +296,21 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
|
|||
|
||||
arch_examine_signal(sig, regs);
|
||||
|
||||
clear_siginfo(&clean_si);
|
||||
clean_si.si_signo = si->si_signo;
|
||||
clean_si.si_errno = si->si_errno;
|
||||
clean_si.si_code = si->si_code;
|
||||
switch (sig) {
|
||||
case SIGILL:
|
||||
case SIGFPE:
|
||||
case SIGSEGV:
|
||||
case SIGBUS:
|
||||
case SIGTRAP:
|
||||
fi = UPT_FAULTINFO(regs);
|
||||
clean_si.si_addr = (void __user *) FAULT_ADDRESS(*fi);
|
||||
/* Is the signal layout for the signal known?
|
||||
* Signal data must be scrubbed to prevent information leaks.
|
||||
*/
|
||||
code = si->si_code;
|
||||
err = si->si_errno;
|
||||
if ((err == 0) && (siginfo_layout(sig, code) == SIL_FAULT)) {
|
||||
struct faultinfo *fi = UPT_FAULTINFO(regs);
|
||||
current->thread.arch.faultinfo = *fi;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
clean_si.si_trapno = si->si_trapno;
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d)\n",
|
||||
sig, si->si_code);
|
||||
force_sig_fault(sig, code, (void __user *)FAULT_ADDRESS(*fi),
|
||||
current);
|
||||
} else {
|
||||
printk(KERN_ERR "Attempted to relay unknown signal %d (si_code = %d) with errno %d\n",
|
||||
sig, code, err);
|
||||
force_sig(sig, current);
|
||||
}
|
||||
|
||||
force_sig_info(sig, &clean_si, current);
|
||||
}
|
||||
|
||||
void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs)
|
||||
|
|
|
@ -52,14 +52,14 @@
|
|||
* Raise a SIGFPE for the current process.
|
||||
* sicode describes the signal being raised.
|
||||
*/
|
||||
void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
|
||||
void ucf64_raise_sigfpe(struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
clear_siginfo(&info);
|
||||
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_code = sicode;
|
||||
info.si_code = FPE_FLTUNK;
|
||||
info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
|
||||
|
||||
/*
|
||||
|
@ -94,7 +94,7 @@ void ucf64_exchandler(u32 inst, u32 fpexc, struct pt_regs *regs)
|
|||
pr_debug("UniCore-F64 FPSCR 0x%08x INST 0x%08x\n",
|
||||
cff(FPSCR), inst);
|
||||
|
||||
ucf64_raise_sigfpe(0, regs);
|
||||
ucf64_raise_sigfpe(regs);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,6 +125,7 @@ static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
|
|||
tsk->thread.address = addr;
|
||||
tsk->thread.error_code = fsr;
|
||||
tsk->thread.trap_no = 14;
|
||||
clear_siginfo(&si);
|
||||
si.si_signo = sig;
|
||||
si.si_errno = 0;
|
||||
si.si_code = code;
|
||||
|
@ -472,6 +473,7 @@ asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr,
|
|||
printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
|
||||
inf->name, fsr, addr);
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
@ -491,6 +493,7 @@ asmlinkage void do_PrefetchAbort(unsigned long addr,
|
|||
printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
|
||||
inf->name, ifsr, addr);
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = inf->sig;
|
||||
info.si_errno = 0;
|
||||
info.si_code = inf->code;
|
||||
|
|
|
@ -107,7 +107,7 @@ static bool write_ok_or_segv(unsigned long ptr, size_t size)
|
|||
thread->cr2 = ptr;
|
||||
thread->trap_nr = X86_TRAP_PF;
|
||||
|
||||
memset(&info, 0, sizeof(info));
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
|
|
|
@ -1377,7 +1377,6 @@ static void fill_sigtrap_info(struct task_struct *tsk,
|
|||
tsk->thread.trap_nr = X86_TRAP_DB;
|
||||
tsk->thread.error_code = error_code;
|
||||
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->si_signo = SIGTRAP;
|
||||
info->si_code = si_code;
|
||||
info->si_addr = user_mode(regs) ? (void __user *)regs->ip : NULL;
|
||||
|
@ -1395,6 +1394,7 @@ void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
|
|||
{
|
||||
struct siginfo info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
fill_sigtrap_info(tsk, regs, error_code, si_code, &info);
|
||||
/* Send us the fake SIGTRAP */
|
||||
force_sig_info(SIGTRAP, &info, tsk);
|
||||
|
|
|
@ -29,7 +29,7 @@ static inline void signal_compat_build_tests(void)
|
|||
BUILD_BUG_ON(NSIGFPE != 15);
|
||||
BUILD_BUG_ON(NSIGSEGV != 7);
|
||||
BUILD_BUG_ON(NSIGBUS != 5);
|
||||
BUILD_BUG_ON(NSIGTRAP != 4);
|
||||
BUILD_BUG_ON(NSIGTRAP != 5);
|
||||
BUILD_BUG_ON(NSIGCHLD != 6);
|
||||
BUILD_BUG_ON(NSIGSYS != 1);
|
||||
|
||||
|
|
|
@ -299,6 +299,7 @@ static void do_error_trap(struct pt_regs *regs, long error_code, char *str,
|
|||
if (notify_die(DIE_TRAP, str, regs, error_code, trapnr, signr) !=
|
||||
NOTIFY_STOP) {
|
||||
cond_local_irq_enable(regs);
|
||||
clear_siginfo(&info);
|
||||
do_trap(trapnr, signr, str, regs, error_code,
|
||||
fill_trap_info(regs, signr, trapnr, &info));
|
||||
}
|
||||
|
@ -854,6 +855,7 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr)
|
|||
|
||||
task->thread.trap_nr = trapnr;
|
||||
task->thread.error_code = error_code;
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGFPE;
|
||||
info.si_errno = 0;
|
||||
info.si_addr = (void __user *)uprobe_get_trap_addr(regs);
|
||||
|
@ -929,6 +931,7 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
|
|||
RCU_LOCKDEP_WARN(!rcu_is_watching(), "entry code didn't wake RCU");
|
||||
local_irq_enable();
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGILL;
|
||||
info.si_errno = 0;
|
||||
info.si_code = ILL_BADSTK;
|
||||
|
|
|
@ -278,6 +278,7 @@ static void force_sig_info_umip_fault(void __user *addr, struct pt_regs *regs)
|
|||
tsk->thread.error_code = X86_PF_USER | X86_PF_WRITE;
|
||||
tsk->thread.trap_nr = X86_TRAP_PF;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
info.si_code = SEGV_MAPERR;
|
||||
|
|
|
@ -3007,6 +3007,7 @@ static void kvm_send_hwpoison_signal(unsigned long address, struct task_struct *
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_MCEERR_AR;
|
||||
|
|
|
@ -209,6 +209,7 @@ force_sig_info_fault(int si_signo, int si_code, unsigned long address,
|
|||
unsigned lsb = 0;
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = si_signo;
|
||||
info.si_errno = 0;
|
||||
info.si_code = si_code;
|
||||
|
|
|
@ -323,8 +323,6 @@ do_illegal_instruction(struct pt_regs *regs)
|
|||
void
|
||||
do_unaligned_user (struct pt_regs *regs)
|
||||
{
|
||||
siginfo_t info;
|
||||
|
||||
__die_if_kernel("Unhandled unaligned exception in kernel",
|
||||
regs, SIGKILL);
|
||||
|
||||
|
@ -334,12 +332,7 @@ do_unaligned_user (struct pt_regs *regs)
|
|||
"(pid = %d, pc = %#010lx)\n",
|
||||
regs->excvaddr, current->comm,
|
||||
task_pid_nr(current), regs->pc);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRALN;
|
||||
info.si_addr = (void *) regs->excvaddr;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
|
||||
force_sig_fault(SIGBUS, BUS_ADRALN, (void *) regs->excvaddr, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -39,13 +39,13 @@ void do_page_fault(struct pt_regs *regs)
|
|||
struct mm_struct *mm = current->mm;
|
||||
unsigned int exccause = regs->exccause;
|
||||
unsigned int address = regs->excvaddr;
|
||||
siginfo_t info;
|
||||
int code;
|
||||
|
||||
int is_write, is_exec;
|
||||
int fault;
|
||||
unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
|
||||
|
||||
info.si_code = SEGV_MAPERR;
|
||||
code = SEGV_MAPERR;
|
||||
|
||||
/* We fault-in kernel-space virtual memory on-demand. The
|
||||
* 'reference' page table is init_mm.pgd.
|
||||
|
@ -91,7 +91,7 @@ void do_page_fault(struct pt_regs *regs)
|
|||
*/
|
||||
|
||||
good_area:
|
||||
info.si_code = SEGV_ACCERR;
|
||||
code = SEGV_ACCERR;
|
||||
|
||||
if (is_write) {
|
||||
if (!(vma->vm_flags & VM_WRITE))
|
||||
|
@ -157,11 +157,7 @@ void do_page_fault(struct pt_regs *regs)
|
|||
if (user_mode(regs)) {
|
||||
current->thread.bad_vaddr = address;
|
||||
current->thread.error_code = is_write;
|
||||
info.si_signo = SIGSEGV;
|
||||
info.si_errno = 0;
|
||||
/* info.si_code has been set above */
|
||||
info.si_addr = (void *) address;
|
||||
force_sig_info(SIGSEGV, &info, current);
|
||||
force_sig_fault(SIGSEGV, code, (void *) address, current);
|
||||
return;
|
||||
}
|
||||
bad_page_fault(regs, address, SIGSEGV);
|
||||
|
@ -186,11 +182,7 @@ void do_page_fault(struct pt_regs *regs)
|
|||
* or user mode.
|
||||
*/
|
||||
current->thread.bad_vaddr = address;
|
||||
info.si_code = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_ADRERR;
|
||||
info.si_addr = (void *) address;
|
||||
force_sig_info(SIGBUS, &info, current);
|
||||
force_sig_fault(SIGBUS, BUS_ADRERR, (void *) address, current);
|
||||
|
||||
/* Kernel mode? Handle exceptions or die */
|
||||
if (!user_mode(regs))
|
||||
|
|
|
@ -81,83 +81,86 @@ static __poll_t signalfd_poll(struct file *file, poll_table *wait)
|
|||
static int signalfd_copyinfo(struct signalfd_siginfo __user *uinfo,
|
||||
siginfo_t const *kinfo)
|
||||
{
|
||||
long err;
|
||||
struct signalfd_siginfo new;
|
||||
|
||||
BUILD_BUG_ON(sizeof(struct signalfd_siginfo) != 128);
|
||||
|
||||
/*
|
||||
* Unused members should be zero ...
|
||||
*/
|
||||
err = __clear_user(uinfo, sizeof(*uinfo));
|
||||
memset(&new, 0, sizeof(new));
|
||||
|
||||
/*
|
||||
* If you change siginfo_t structure, please be sure
|
||||
* this code is fixed accordingly.
|
||||
*/
|
||||
err |= __put_user(kinfo->si_signo, &uinfo->ssi_signo);
|
||||
err |= __put_user(kinfo->si_errno, &uinfo->ssi_errno);
|
||||
err |= __put_user(kinfo->si_code, &uinfo->ssi_code);
|
||||
new.ssi_signo = kinfo->si_signo;
|
||||
new.ssi_errno = kinfo->si_errno;
|
||||
new.ssi_code = kinfo->si_code;
|
||||
switch (siginfo_layout(kinfo->si_signo, kinfo->si_code)) {
|
||||
case SIL_KILL:
|
||||
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
|
||||
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
|
||||
new.ssi_pid = kinfo->si_pid;
|
||||
new.ssi_uid = kinfo->si_uid;
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
err |= __put_user(kinfo->si_tid, &uinfo->ssi_tid);
|
||||
err |= __put_user(kinfo->si_overrun, &uinfo->ssi_overrun);
|
||||
err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
|
||||
err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
|
||||
new.ssi_tid = kinfo->si_tid;
|
||||
new.ssi_overrun = kinfo->si_overrun;
|
||||
new.ssi_ptr = (long) kinfo->si_ptr;
|
||||
new.ssi_int = kinfo->si_int;
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(kinfo->si_band, &uinfo->ssi_band);
|
||||
err |= __put_user(kinfo->si_fd, &uinfo->ssi_fd);
|
||||
new.ssi_band = kinfo->si_band;
|
||||
new.ssi_fd = kinfo->si_fd;
|
||||
break;
|
||||
case SIL_FAULT_BNDERR:
|
||||
case SIL_FAULT_PKUERR:
|
||||
/*
|
||||
* Fall through to the SIL_FAULT case. Both SIL_FAULT_BNDERR
|
||||
* and SIL_FAULT_PKUERR are only generated by faults that
|
||||
* deliver them synchronously to userspace. In case someone
|
||||
* injects one of these signals and signalfd catches it treat
|
||||
* it as SIL_FAULT.
|
||||
*/
|
||||
case SIL_FAULT:
|
||||
err |= __put_user((long) kinfo->si_addr, &uinfo->ssi_addr);
|
||||
new.ssi_addr = (long) kinfo->si_addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
err |= __put_user(kinfo->si_trapno, &uinfo->ssi_trapno);
|
||||
new.ssi_trapno = kinfo->si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AO
|
||||
/*
|
||||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
if (kinfo->si_signo == SIGBUS &&
|
||||
kinfo->si_code == BUS_MCEERR_AO)
|
||||
err |= __put_user((short) kinfo->si_addr_lsb,
|
||||
&uinfo->ssi_addr_lsb);
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AR
|
||||
/*
|
||||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
if (kinfo->si_signo == SIGBUS &&
|
||||
kinfo->si_code == BUS_MCEERR_AR)
|
||||
err |= __put_user((short) kinfo->si_addr_lsb,
|
||||
&uinfo->ssi_addr_lsb);
|
||||
break;
|
||||
case SIL_FAULT_MCEERR:
|
||||
new.ssi_addr = (long) kinfo->si_addr;
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.ssi_trapno = kinfo->si_trapno;
|
||||
#endif
|
||||
new.ssi_addr_lsb = (short) kinfo->si_addr_lsb;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
|
||||
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
|
||||
err |= __put_user(kinfo->si_status, &uinfo->ssi_status);
|
||||
err |= __put_user(kinfo->si_utime, &uinfo->ssi_utime);
|
||||
err |= __put_user(kinfo->si_stime, &uinfo->ssi_stime);
|
||||
new.ssi_pid = kinfo->si_pid;
|
||||
new.ssi_uid = kinfo->si_uid;
|
||||
new.ssi_status = kinfo->si_status;
|
||||
new.ssi_utime = kinfo->si_utime;
|
||||
new.ssi_stime = kinfo->si_stime;
|
||||
break;
|
||||
case SIL_RT:
|
||||
default:
|
||||
/*
|
||||
* This case catches also the signals queued by sigqueue().
|
||||
*/
|
||||
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
|
||||
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
|
||||
err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
|
||||
err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
|
||||
new.ssi_pid = kinfo->si_pid;
|
||||
new.ssi_uid = kinfo->si_uid;
|
||||
new.ssi_ptr = (long) kinfo->si_ptr;
|
||||
new.ssi_int = kinfo->si_int;
|
||||
break;
|
||||
case SIL_SYS:
|
||||
new.ssi_call_addr = (long) kinfo->si_call_addr;
|
||||
new.ssi_syscall = kinfo->si_syscall;
|
||||
new.ssi_arch = kinfo->si_arch;
|
||||
break;
|
||||
}
|
||||
|
||||
return err ? -EFAULT: sizeof(*uinfo);
|
||||
if (copy_to_user(uinfo, &new, sizeof(struct signalfd_siginfo)))
|
||||
return -EFAULT;
|
||||
|
||||
return sizeof(*uinfo);
|
||||
}
|
||||
|
||||
static ssize_t signalfd_dequeue(struct signalfd_ctx *ctx, siginfo_t *info,
|
||||
|
|
|
@ -345,7 +345,6 @@ extern void user_single_step_siginfo(struct task_struct *tsk,
|
|||
static inline void user_single_step_siginfo(struct task_struct *tsk,
|
||||
struct pt_regs *regs, siginfo_t *info)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->si_signo = SIGTRAP;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -28,6 +28,9 @@ enum siginfo_layout {
|
|||
SIL_TIMER,
|
||||
SIL_POLL,
|
||||
SIL_FAULT,
|
||||
SIL_FAULT_MCEERR,
|
||||
SIL_FAULT_BNDERR,
|
||||
SIL_FAULT_PKUERR,
|
||||
SIL_CHLD,
|
||||
SIL_RT,
|
||||
SIL_SYS,
|
||||
|
|
|
@ -124,6 +124,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
|
|||
{
|
||||
if (step) {
|
||||
siginfo_t info;
|
||||
clear_siginfo(&info);
|
||||
user_single_step_siginfo(current, regs, &info);
|
||||
force_sig_info(SIGTRAP, &info, current);
|
||||
return;
|
||||
|
|
|
@ -249,7 +249,8 @@ typedef struct siginfo {
|
|||
#define TRAP_TRACE 2 /* process trace trap */
|
||||
#define TRAP_BRANCH 3 /* process taken branch trap */
|
||||
#define TRAP_HWBKPT 4 /* hardware breakpoint/watchpoint */
|
||||
#define NSIGTRAP 4
|
||||
#define TRAP_UNK 5 /* undiagnosed trap */
|
||||
#define NSIGTRAP 5
|
||||
|
||||
/*
|
||||
* There is an additional set of SIGTRAP si_codes used by ptrace
|
||||
|
|
|
@ -35,6 +35,10 @@ struct signalfd_siginfo {
|
|||
__u64 ssi_stime;
|
||||
__u64 ssi_addr;
|
||||
__u16 ssi_addr_lsb;
|
||||
__u16 __pad2;
|
||||
__s32 ssi_syscall;
|
||||
__u64 ssi_call_addr;
|
||||
__u32 ssi_arch;
|
||||
|
||||
/*
|
||||
* Pad strcture to 128 bytes. Remember to update the
|
||||
|
@ -45,7 +49,7 @@ struct signalfd_siginfo {
|
|||
* comes out of a read(2) and we really don't want to have
|
||||
* a compat on read(2).
|
||||
*/
|
||||
__u8 __pad[46];
|
||||
__u8 __pad[28];
|
||||
};
|
||||
|
||||
|
||||
|
|
181
kernel/signal.c
181
kernel/signal.c
|
@ -1539,7 +1539,6 @@ int send_sig_fault(int sig, int code, void __user *addr
|
|||
return send_sig_info(info.si_signo, &info, t);
|
||||
}
|
||||
|
||||
#if defined(BUS_MCEERR_AO) && defined(BUS_MCEERR_AR)
|
||||
int force_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *t)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
@ -1568,9 +1567,7 @@ int send_sig_mceerr(int code, void __user *addr, short lsb, struct task_struct *
|
|||
return send_sig_info(info.si_signo, &info, t);
|
||||
}
|
||||
EXPORT_SYMBOL(send_sig_mceerr);
|
||||
#endif
|
||||
|
||||
#ifdef SEGV_BNDERR
|
||||
int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
|
||||
{
|
||||
struct siginfo info;
|
||||
|
@ -1584,7 +1581,6 @@ int force_sig_bnderr(void __user *addr, void __user *lower, void __user *upper)
|
|||
info.si_upper = upper;
|
||||
return force_sig_info(info.si_signo, &info, current);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SEGV_PKUERR
|
||||
int force_sig_pkuerr(void __user *addr, u32 pkey)
|
||||
|
@ -2837,8 +2833,19 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
|
|||
[SIGPOLL] = { NSIGPOLL, SIL_POLL },
|
||||
[SIGSYS] = { NSIGSYS, SIL_SYS },
|
||||
};
|
||||
if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit))
|
||||
if ((sig < ARRAY_SIZE(filter)) && (si_code <= filter[sig].limit)) {
|
||||
layout = filter[sig].layout;
|
||||
/* Handle the exceptions */
|
||||
if ((sig == SIGBUS) &&
|
||||
(si_code >= BUS_MCEERR_AR) && (si_code <= BUS_MCEERR_AO))
|
||||
layout = SIL_FAULT_MCEERR;
|
||||
else if ((sig == SIGSEGV) && (si_code == SEGV_BNDERR))
|
||||
layout = SIL_FAULT_BNDERR;
|
||||
#ifdef SEGV_PKUERR
|
||||
else if ((sig == SIGSEGV) && (si_code == SEGV_PKUERR))
|
||||
layout = SIL_FAULT_PKUERR;
|
||||
#endif
|
||||
}
|
||||
else if (si_code <= NSIGPOLL)
|
||||
layout = SIL_POLL;
|
||||
} else {
|
||||
|
@ -2848,104 +2855,15 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
|
|||
layout = SIL_POLL;
|
||||
else if (si_code < 0)
|
||||
layout = SIL_RT;
|
||||
/* Tests to support buggy kernel ABIs */
|
||||
#ifdef TRAP_FIXME
|
||||
if ((sig == SIGTRAP) && (si_code == TRAP_FIXME))
|
||||
layout = SIL_FAULT;
|
||||
#endif
|
||||
#ifdef FPE_FIXME
|
||||
if ((sig == SIGFPE) && (si_code == FPE_FIXME))
|
||||
layout = SIL_FAULT;
|
||||
#endif
|
||||
}
|
||||
return layout;
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
|
||||
if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
|
||||
if (copy_to_user(to, from , sizeof(struct siginfo)))
|
||||
return -EFAULT;
|
||||
if (from->si_code < 0)
|
||||
return __copy_to_user(to, from, sizeof(siginfo_t))
|
||||
? -EFAULT : 0;
|
||||
/*
|
||||
* If you change siginfo_t structure, please be sure
|
||||
* this code is fixed accordingly.
|
||||
* Please remember to update the signalfd_copyinfo() function
|
||||
* inside fs/signalfd.c too, in case siginfo_t changes.
|
||||
* It should never copy any pad contained in the structure
|
||||
* to avoid security leaks, but must copy the generic
|
||||
* 3 ints plus the relevant union member.
|
||||
*/
|
||||
err = __put_user(from->si_signo, &to->si_signo);
|
||||
err |= __put_user(from->si_errno, &to->si_errno);
|
||||
err |= __put_user(from->si_code, &to->si_code);
|
||||
switch (siginfo_layout(from->si_signo, from->si_code)) {
|
||||
case SIL_KILL:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
break;
|
||||
case SIL_TIMER:
|
||||
/* Unreached SI_TIMER is negative */
|
||||
break;
|
||||
case SIL_POLL:
|
||||
err |= __put_user(from->si_band, &to->si_band);
|
||||
err |= __put_user(from->si_fd, &to->si_fd);
|
||||
break;
|
||||
case SIL_FAULT:
|
||||
err |= __put_user(from->si_addr, &to->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
err |= __put_user(from->si_trapno, &to->si_trapno);
|
||||
#endif
|
||||
#ifdef __ia64__
|
||||
err |= __put_user(from->si_imm, &to->si_imm);
|
||||
err |= __put_user(from->si_flags, &to->si_flags);
|
||||
err |= __put_user(from->si_isr, &to->si_isr);
|
||||
#endif
|
||||
/*
|
||||
* Other callers might not initialize the si_lsb field,
|
||||
* so check explicitly for the right codes here.
|
||||
*/
|
||||
#ifdef BUS_MCEERR_AR
|
||||
if (from->si_signo == SIGBUS && from->si_code == BUS_MCEERR_AR)
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AO
|
||||
if (from->si_signo == SIGBUS && from->si_code == BUS_MCEERR_AO)
|
||||
err |= __put_user(from->si_addr_lsb, &to->si_addr_lsb);
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
if (from->si_signo == SIGSEGV && from->si_code == SEGV_BNDERR) {
|
||||
err |= __put_user(from->si_lower, &to->si_lower);
|
||||
err |= __put_user(from->si_upper, &to->si_upper);
|
||||
}
|
||||
#endif
|
||||
#ifdef SEGV_PKUERR
|
||||
if (from->si_signo == SIGSEGV && from->si_code == SEGV_PKUERR)
|
||||
err |= __put_user(from->si_pkey, &to->si_pkey);
|
||||
#endif
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_status, &to->si_status);
|
||||
err |= __put_user(from->si_utime, &to->si_utime);
|
||||
err |= __put_user(from->si_stime, &to->si_stime);
|
||||
break;
|
||||
case SIL_RT:
|
||||
err |= __put_user(from->si_pid, &to->si_pid);
|
||||
err |= __put_user(from->si_uid, &to->si_uid);
|
||||
err |= __put_user(from->si_ptr, &to->si_ptr);
|
||||
break;
|
||||
case SIL_SYS:
|
||||
err |= __put_user(from->si_call_addr, &to->si_call_addr);
|
||||
err |= __put_user(from->si_syscall, &to->si_syscall);
|
||||
err |= __put_user(from->si_arch, &to->si_arch);
|
||||
break;
|
||||
}
|
||||
return err;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_COMPAT
|
||||
|
@ -2984,27 +2902,28 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
|
|||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AR
|
||||
if ((from->si_signo == SIGBUS) && (from->si_code == BUS_MCEERR_AR))
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_MCEERR:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AO
|
||||
if ((from->si_signo == SIGBUS) && (from->si_code == BUS_MCEERR_AO))
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
new.si_addr_lsb = from->si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_BNDERR:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
if ((from->si_signo == SIGSEGV) &&
|
||||
(from->si_code == SEGV_BNDERR)) {
|
||||
new.si_lower = ptr_to_compat(from->si_lower);
|
||||
new.si_upper = ptr_to_compat(from->si_upper);
|
||||
}
|
||||
new.si_lower = ptr_to_compat(from->si_lower);
|
||||
new.si_upper = ptr_to_compat(from->si_upper);
|
||||
break;
|
||||
case SIL_FAULT_PKUERR:
|
||||
new.si_addr = ptr_to_compat(from->si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
new.si_trapno = from->si_trapno;
|
||||
#endif
|
||||
#ifdef SEGV_PKUERR
|
||||
if ((from->si_signo == SIGSEGV) &&
|
||||
(from->si_code == SEGV_PKUERR))
|
||||
new.si_pkey = from->si_pkey;
|
||||
#endif
|
||||
|
||||
new.si_pkey = from->si_pkey;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
new.si_pid = from->si_pid;
|
||||
|
@ -3070,24 +2989,28 @@ int copy_siginfo_from_user32(struct siginfo *to,
|
|||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEERR_AR
|
||||
if ((from.si_signo == SIGBUS) && (from.si_code == BUS_MCEERR_AR))
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_MCEERR:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
#ifdef BUS_MCEER_AO
|
||||
if ((from.si_signo == SIGBUS) && (from.si_code == BUS_MCEERR_AO))
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
to->si_addr_lsb = from.si_addr_lsb;
|
||||
break;
|
||||
case SIL_FAULT_BNDERR:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
#ifdef SEGV_BNDERR
|
||||
if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_BNDERR)) {
|
||||
to->si_lower = compat_ptr(from.si_lower);
|
||||
to->si_upper = compat_ptr(from.si_upper);
|
||||
}
|
||||
#endif
|
||||
#ifdef SEGV_PKUERR
|
||||
if ((from.si_signo == SIGSEGV) && (from.si_code == SEGV_PKUERR))
|
||||
to->si_pkey = from.si_pkey;
|
||||
to->si_lower = compat_ptr(from.si_lower);
|
||||
to->si_upper = compat_ptr(from.si_upper);
|
||||
break;
|
||||
case SIL_FAULT_PKUERR:
|
||||
to->si_addr = compat_ptr(from.si_addr);
|
||||
#ifdef __ARCH_SI_TRAPNO
|
||||
to->si_trapno = from.si_trapno;
|
||||
#endif
|
||||
to->si_pkey = from.si_pkey;
|
||||
break;
|
||||
case SIL_CHLD:
|
||||
to->si_pid = from.si_pid;
|
||||
|
|
|
@ -1401,6 +1401,7 @@ static void kvm_send_hwpoison_signal(unsigned long address,
|
|||
{
|
||||
siginfo_t info;
|
||||
|
||||
clear_siginfo(&info);
|
||||
info.si_signo = SIGBUS;
|
||||
info.si_errno = 0;
|
||||
info.si_code = BUS_MCEERR_AR;
|
||||
|
|
Loading…
Reference in New Issue