⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 traps.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Architecture-specific trap handling. * * Copyright (C) 1998-2000 Hewlett-Packard Co * Copyright (C) 1998-2000 David Mosberger-Tang <davidm@hpl.hp.com> * * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE */#define FPSWA_DEBUG	1/* * The fpu_fault() handler needs to be able to access and update all * floating point registers.  Those saved in pt_regs can be accessed * through that structure, but those not saved, will be accessed * directly.  To make this work, we need to ensure that the compiler * does not end up using a preserved floating point register on its * own.  The following achieves this by declaring preserved registers * that are not marked as "fixed" as global register variables. */register double f2 asm ("f2"); register double f3 asm ("f3");register double f4 asm ("f4"); register double f5 asm ("f5");register long f16 asm ("f16"); register long f17 asm ("f17");register long f18 asm ("f18"); register long f19 asm ("f19");register long f20 asm ("f20"); register long f21 asm ("f21");register long f22 asm ("f22"); register long f23 asm ("f23");register double f24 asm ("f24"); register double f25 asm ("f25");register double f26 asm ("f26"); register double f27 asm ("f27");register double f28 asm ("f28"); register double f29 asm ("f29");register double f30 asm ("f30"); register double f31 asm ("f31");#include <linux/config.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/sched.h>#include <asm/ia32.h>#include <asm/processor.h>#include <asm/uaccess.h>#include <asm/fpswa.h>static fpswa_interface_t *fpswa_interface;void __inittrap_init (void){	printk("fpswa interface at %lx\n", ia64_boot_param.fpswa);	if (ia64_boot_param.fpswa) {#define OLD_FIRMWARE#ifdef OLD_FIRMWARE		/*		 * HACK to work around broken firmware.  This code		 * applies the label fixup to the FPSWA interface and		 * works both with old and new (fixed) firmware.		 */		unsigned long addr = (unsigned long) __va(ia64_boot_param.fpswa);		unsigned long gp_val = *(unsigned long *)(addr + 8);		/* go indirect and indexed to get table address */		addr = gp_val;		gp_val = *(unsigned long *)(addr + 8);		while (gp_val == *(unsigned long *)(addr + 8)) {			*(unsigned long *)addr |= PAGE_OFFSET;			*(unsigned long *)(addr + 8) |= PAGE_OFFSET;			addr += 16;		}#endif		/* FPSWA fixup: make the interface pointer a kernel virtual address: */		fpswa_interface = __va(ia64_boot_param.fpswa);	}}voiddie_if_kernel (char *str, struct pt_regs *regs, long err){	if (user_mode(regs)) {#if 0		/* XXX for debugging only */		printk ("!!die_if_kernel: %s(%d): %s %ld\n",			current->comm, current->pid, str, err);		show_regs(regs);#endif		return;	}	printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);	show_regs(regs);	if (current->thread.flags & IA64_KERNEL_DEATH) {		printk("die_if_kernel recursion detected.\n");		sti();		while (1);	}	current->thread.flags |= IA64_KERNEL_DEATH;	do_exit(SIGSEGV);}voidia64_bad_break (unsigned long break_num, struct pt_regs *regs){	siginfo_t siginfo;	int sig, code;	/* SIGILL, SIGFPE, SIGSEGV, and SIGBUS want these field initialized: */	siginfo.si_addr = (void *) (regs->cr_iip + ia64_psr(regs)->ri);	siginfo.si_imm = break_num;	switch (break_num) {	      case 0: /* unknown error */		sig = SIGILL; code = ILL_ILLOPC;		break;	      case 1: /* integer divide by zero */		sig = SIGFPE; code = FPE_INTDIV;		break;	      case 2: /* integer overflow */		sig = SIGFPE; code = FPE_INTOVF;		break;	      case 3: /* range check/bounds check */		sig = SIGFPE; code = FPE_FLTSUB;		break;	      case 4: /* null pointer dereference */		sig = SIGSEGV; code = SEGV_MAPERR;		break;	      case 5: /* misaligned data */		sig = SIGSEGV; code = BUS_ADRALN;		break;	      case 6: /* decimal overflow */		sig = SIGFPE; code = __FPE_DECOVF;		break;	      case 7: /* decimal divide by zero */		sig = SIGFPE; code = __FPE_DECDIV;		break;	      case 8: /* packed decimal error */		sig = SIGFPE; code = __FPE_DECERR;		break;	      case 9: /* invalid ASCII digit */		sig = SIGFPE; code = __FPE_INVASC;		break;	      case 10: /* invalid decimal digit */		sig = SIGFPE; code = __FPE_INVDEC;		break;	      case 11: /* paragraph stack overflow */		sig = SIGSEGV; code = __SEGV_PSTKOVF;		break;	      default:		if (break_num < 0x40000 || break_num > 0x100000)			die_if_kernel("Bad break", regs, break_num);		if (break_num < 0x80000) {			sig = SIGILL; code = __ILL_BREAK;		} else {			sig = SIGTRAP; code = TRAP_BRKPT;		}	}	siginfo.si_signo = sig;	siginfo.si_errno = 0;	siginfo.si_code = code;	force_sig_info(sig, &siginfo, current);}/* * Unimplemented system calls.  This is called only for stuff that * we're supposed to implement but haven't done so yet.  Everything * else goes to sys_ni_syscall. */asmlinkage longia64_ni_syscall (unsigned long arg0, unsigned long arg1, unsigned long arg2, unsigned long arg3,		 unsigned long arg4, unsigned long arg5, unsigned long arg6, unsigned long arg7,		 unsigned long stack){	struct pt_regs *regs = (struct pt_regs *) &stack;	printk("<sc%ld(%lx,%lx,%lx,%lx)>\n", regs->r15, arg0, arg1, arg2, arg3);	return -ENOSYS;}/* * disabled_fph_fault() is called when a user-level process attempts * to access one of the registers f32..f127 when it doesn't own the * fp-high register partition.  When this happens, we save the current * fph partition in the task_struct of the fpu-owner (if necessary) * and then load the fp-high partition of the current task (if * necessary).  Note that the kernel has access to fph by the time we * get here, as the IVT's "Diabled FP-Register" handler takes care of * clearing psr.dfh. */static inline voiddisabled_fph_fault (struct pt_regs *regs){	struct ia64_psr *psr = ia64_psr(regs);	/* first, grant user-level access to fph partition: */	psr->dfh = 0;#ifndef CONFIG_SMP	{		struct task_struct *fpu_owner = ia64_get_fpu_owner();		if (fpu_owner == current)			return;		if (fpu_owner)			ia64_flush_fph(fpu_owner);		ia64_set_fpu_owner(current);	}#endif /* !CONFIG_SMP */	if ((current->thread.flags & IA64_THREAD_FPH_VALID) != 0) {		__ia64_load_fpu(current->thread.fph);		psr->mfh = 0;	} else {		__ia64_init_fpu();		/*		 * Set mfh because the state in thread.fph does not match the state in		 * the fph partition.		 */		psr->mfh = 1;	}}static inline intfp_emulate (int fp_fault, void *bundle, long *ipsr, long *fpsr, long *isr, long *pr, long *ifs,	    struct pt_regs *regs){	fp_state_t fp_state;	fpswa_ret_t ret;#ifdef FPSWA_BUG	struct ia64_fpreg f6_15[10];#endif	if (!fpswa_interface)		return -1;	memset(&fp_state, 0, sizeof(fp_state_t));	/*	 * compute fp_state.  only FP registers f6 - f11 are used by the 	 * kernel, so set those bits in the mask and set the low volatile	 * pointer to point to these registers.	 */#ifndef FPSWA_BUG	fp_state.bitmask_low64 = 0x3c0;  /* bit 6..9 */	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) &regs->f6;#else	fp_state.bitmask_low64 = 0xffc0;  /* bit6..bit15 */	f6_15[0] = regs->f6;	f6_15[1] = regs->f7;	f6_15[2] = regs->f8;	f6_15[3] = regs->f9; 	__asm__ ("stf.spill %0=f10%P0" : "=m"(f6_15[4])); 	__asm__ ("stf.spill %0=f11%P0" : "=m"(f6_15[5])); 	__asm__ ("stf.spill %0=f12%P0" : "=m"(f6_15[6])); 	__asm__ ("stf.spill %0=f13%P0" : "=m"(f6_15[7])); 	__asm__ ("stf.spill %0=f14%P0" : "=m"(f6_15[8])); 	__asm__ ("stf.spill %0=f15%P0" : "=m"(f6_15[9]));	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_15;#endif        /*	 * unsigned long (*EFI_FPSWA) (	 *      unsigned long    trap_type,	 *	void             *Bundle,	 *	unsigned long    *pipsr,	 *	unsigned long    *pfsr,	 *	unsigned long    *pisr,	 *	unsigned long    *ppreds,	 *	unsigned long    *pifs,	 *	void             *fp_state);	 */	ret = (*fpswa_interface->fpswa)((unsigned long) fp_fault, bundle,					(unsigned long *) ipsr, (unsigned long *) fpsr,					(unsigned long *) isr, (unsigned long *) pr,					(unsigned long *) ifs, &fp_state);#ifdef FPSWA_BUG

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -