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

📄 traps.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Architecture-specific trap handling. * * Copyright (C) 1998-2001 Hewlett-Packard Co *	David Mosberger-Tang <davidm@hpl.hp.com> * * 05/12/00 grao <goutham.rao@intel.com> : added isr in siginfo for SIGFPE *//* * fp_emulate() 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 <linux/vt_kern.h>		/* For unblank_screen() */#include <asm/hardirq.h>#include <asm/ia32.h>#include <asm/processor.h>#include <asm/uaccess.h>#include <asm/fpswa.h>extern spinlock_t timerlist_lock;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)		/* FPSWA fixup: make the interface pointer a kernel virtual address: */		fpswa_interface = __va(ia64_boot_param->fpswa);}/* * Unlock any spinlocks which will prevent us from getting the message out (timerlist_lock * is acquired through the console unblank code) */voidbust_spinlocks (int yes){	spin_lock_init(&timerlist_lock);	if (yes) {		oops_in_progress = 1;#ifdef CONFIG_SMP		global_irq_lock = 0;	/* Many serial drivers do __global_cli() */#endif	} else {		int loglevel_save = console_loglevel;#ifdef CONFIG_VT		unblank_screen();#endif		oops_in_progress = 0;		/*		 * OK, the message is on the console.  Now we call printk() without		 * oops_in_progress set so that printk will give klogd a poke.  Hold onto		 * your hats...		 */		console_loglevel = 15;		/* NMI oopser may have shut the console up */		printk(" ");		console_loglevel = loglevel_save;	}}voiddie (const char *str, struct pt_regs *regs, long err){	static struct {		spinlock_t lock;		int lock_owner;		int lock_owner_depth;	} die = {		lock:			SPIN_LOCK_UNLOCKED,		lock_owner:		-1,		lock_owner_depth:	0	};	if (die.lock_owner != smp_processor_id()) {		console_verbose();		spin_lock_irq(&die.lock);		die.lock_owner = smp_processor_id();		die.lock_owner_depth = 0;		bust_spinlocks(1);	}	if (++die.lock_owner_depth < 3) {		printk("%s[%d]: %s %ld\n", current->comm, current->pid, str, err);		show_regs(regs);  	} else		printk(KERN_ERR "Recursive die() failure, output suppressed\n");	bust_spinlocks(0);	die.lock_owner = -1;	spin_unlock_irq(&die.lock);  	do_exit(SIGSEGV);}voiddie_if_kernel (char *str, struct pt_regs *regs, long err){	if (!user_mode(regs))		die(str, regs, err);}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 f32..f127 * and 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 "Disabled 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){	struct ia64_fpreg f6_11[6];	fp_state_t fp_state;	fpswa_ret_t ret;	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.	 */	fp_state.bitmask_low64 = 0xfc0;  /* bit6..bit11 */	f6_11[0] = regs->f6; f6_11[1] = regs->f7;	f6_11[2] = regs->f8; f6_11[3] = regs->f9;	__asm__ ("stf.spill %0=f10%P0" : "=m"(f6_11[4]));	__asm__ ("stf.spill %0=f11%P0" : "=m"(f6_11[5]));	fp_state.fp_state_low_volatile = (fp_state_low_volatile_t *) f6_11;	/*	 * unsigned long (*EFI_FPSWA) (	 *      unsigned long    trap_type,	 *	void             *Bundle,	 *	unsigned long    *pipsr,	 *	unsigned long    *pfsr,	 *	unsigned long    *pisr,	 *	unsigned long    *ppreds,

⌨️ 快捷键说明

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