/*
* Iinux/arch/i386/traps.c
*
* Copyright (С) 1991, 1992 Linus Torvalds
*
* Поддержка Pentium III FXSR, SSE
* Gareth Hughes , May 2000
*/
void die(const char * str, struct pt_regs * regs, long err)
{
console_verbose();
spin_lock_irq(&die_lock);
printk("%s: %041x\n", str, err & Oxffff);
show_registers(regs) ;
spin_unlock_irq(&die_lock);
do_exit(SIGSEGV);
}
static inline void die_if_kernel (const char * str, struct pt_regs * regs, long err)
{
if (! regs->eflags & VM_MASK) && !(3 & regs->xcs) )
die {str, regs, err);
}
static inline unsigned long get_cr2 {void)
{
unsigned long address;
/* получить адрес */
__asm _ ("movl %%cr2, %0": "=r" (address));
return address;
}
static void inline do_trap(int trapnr, int signr, char *str, int vm86,
struct pt_regs * regs, long error_code, siginfo_t *info)
{
if (vm86 && regs->eflags & VM__MASK)
goto vm86_trap;
if (!(regs->xcs & 3) ) goto kernel_trap;
trap_signal: {
struct task_struct *tsk = current;
tsk->thread.error_code = error_code;
tsk->thread. trap_no = trapnr;
if (info)
force_sig_info (signr, info, tsk);
else
force_sig (signr, tsk);
return;
}
kernel trap: {
unsigned long fixup = search_exception_table (regs->eip);
if (fixup)
regs->eip = fixup;
else
die(str, regs, error__code};
return;
}
vm86_trap: {
int ret = handle_vm86_trap((struct kernel_vm86_regs *) regs,
error_code, trapnr);
if (ret) goto trap_signal;
return;
}
}
#define DO_ERROR(trapnr, signr, str, name) \
asmlinkage void do_##name (struct pt_regs * regs, long error_code) \
{ \
do_trap (trapnr, signr, str, 0, regs, error_code, NULL); \
}
#define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
siginfo_t info; \
info.si_signo = signr; \
info.si_errno =0; \
info.si_code = sicode; \
info.si_addr = (void *}siaddr; \
do_trap(trapnr, signr, str, 0, regs, error_code, &info} ; \
}
#define DO_VM86_ERROR(trapnr, signr, str, name) \
asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
{ \
do_trap(trapnr, signr, str, 1, regs, error_code, NULL); \
}
#define DO_VM86_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
asmlinkage void do_##name (struct pt_regs * regs, long error_code) \
{ \
siginfo_t info; \
info.si_signo = signr; \
info.si_errno = 0; \
info.si_code = sicode; \
info.si_addr = (void *)siaddr; \
do_trap(trapnr, signr, str, 1, regs, error_code, &info) ; \
}
DO_VM86_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip)
DO_VM86_ERROR( 3, SIGTRAP, "int3", int3)
DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow)
DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds)
DO_ERROR_INFO ( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
DO_VM86_ERROR ( 7, SIGSEGV, "device not available", device_not_available)
DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segrnent_overrun)
DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr2 ())
|