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

📄 traps.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif	if ((fp->un.fmt7.wb2s & WBV_040) &&	    !(fp->un.fmt7.wb2s & WBTT_040)) {		res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,				       fp->un.fmt7.wb2d);		if (res)			fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);		else			fp->un.fmt7.wb2s = 0;	}	/* do the 2nd wb only if the first one was successful (except for a kernel wb) */	if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {		res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,				       fp->un.fmt7.wb3d);		if (res)		    {			fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);			fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;			fp->un.fmt7.wb3s &= (~WBV_040);			fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;			fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;		    }		else			fp->un.fmt7.wb3s = 0;	}	if (res)		send_fault_sig(&fp->ptregs);}/* * called from sigreturn(), must ensure userspace code didn't * manipulate exception frame to circumvent protection, then complete * pending writebacks * we just clear TM2 to turn it into an userspace access */asmlinkage void berr_040cleanup(struct frame *fp){	fp->un.fmt7.wb2s &= ~4;	fp->un.fmt7.wb3s &= ~4;	do_040writebacks(fp);}static inline void access_error040(struct frame *fp){	unsigned short ssw = fp->un.fmt7.ssw;	unsigned long mmusr;#ifdef DEBUG	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,		fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);	printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",		fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,		fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);#endif	if (ssw & ATC_040) {		unsigned long addr = fp->un.fmt7.faddr;		unsigned long errorcode;		/*		 * The MMU status has to be determined AFTER the address		 * has been corrected if there was a misaligned access (MA).		 */		if (ssw & MA_040)			addr = (addr + 7) & -8;		/* MMU error, get the MMUSR info for this access */		mmusr = probe040(!(ssw & RW_040), addr, ssw);#ifdef DEBUG		printk("mmusr = %lx\n", mmusr);#endif		errorcode = 1;		if (!(mmusr & MMU_R_040)) {			/* clear the invalid atc entry */			__flush_tlb040_one(addr);			errorcode = 0;		}		/* despite what documentation seems to say, RMW		 * accesses have always both the LK and RW bits set */		if (!(ssw & RW_040) || (ssw & LK_040))			errorcode |= 2;		if (do_page_fault(&fp->ptregs, addr, errorcode)) {#ifdef DEBUG		        printk("do_page_fault() !=0 \n");#endif			if (user_mode(&fp->ptregs)){				/* delay writebacks after signal delivery */#ifdef DEBUG			        printk(".. was usermode - return\n");#endif				return;			}			/* disable writeback into user space from kernel			 * (if do_page_fault didn't fix the mapping,                         * the writeback won't do good)			 */#ifdef DEBUG			printk(".. disabling wb2\n");#endif			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)				fp->un.fmt7.wb2s &= ~WBV_040;		}	} else if (send_fault_sig(&fp->ptregs) > 0) {		printk("68040 access error, ssw=%x\n", ssw);		trap_c(fp);	}	do_040writebacks(fp);}#endif /* CONFIG_M68040 */#if defined(CONFIG_SUN3)#include <asm/sun3mmu.h>extern int mmu_emu_handle_fault (unsigned long, int, int);/* sun3 version of bus_error030 */static inline void bus_error030 (struct frame *fp){	unsigned char buserr_type = sun3_get_buserr ();	unsigned long addr, errorcode;	unsigned short ssw = fp->un.fmtb.ssw;	extern unsigned long _sun3_map_test_start, _sun3_map_test_end;#ifdef DEBUG	if (ssw & (FC | FB))		printk ("Instruction fault at %#010lx\n",			ssw & FC ?			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2			:			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);	if (ssw & DF)		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",			ssw & RW ? "read" : "write",			fp->un.fmtb.daddr,			space_names[ssw & DFC], fp->ptregs.pc);#endif	/*	 * Check if this page should be demand-mapped. This needs to go before	 * the testing for a bad kernel-space access (demand-mapping applies	 * to kernel accesses too).	 */	if ((ssw & DF)	    && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {		if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))			return;	}	/* Check for kernel-space pagefault (BAD). */	if (fp->ptregs.sr & PS_S) {		/* kernel fault must be a data fault to user space */		if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {		     // try checking the kernel mappings before surrender		     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))			  return;			/* instruction fault or kernel data fault! */			if (ssw & (FC | FB))				printk ("Instruction fault at %#010lx\n",					fp->ptregs.pc);			if (ssw & DF) {				/* was this fault incurred testing bus mappings? */				if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&				   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {					send_fault_sig(&fp->ptregs);					return;				}				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",					ssw & RW ? "read" : "write",					fp->un.fmtb.daddr,					space_names[ssw & DFC], fp->ptregs.pc);			}			printk ("BAD KERNEL BUSERR\n");			die_if_kernel("Oops", &fp->ptregs,0);			force_sig(SIGKILL, current);			return;		}	} else {		/* user fault */		if (!(ssw & (FC | FB)) && !(ssw & DF))			/* not an instruction fault or data fault! BAD */			panic ("USER BUSERR w/o instruction or data fault");	}	/* First handle the data fault, if any.  */	if (ssw & DF) {		addr = fp->un.fmtb.daddr;// errorcode bit 0:	0 -> no page		1 -> protection fault// errorcode bit 1:	0 -> read fault		1 -> write fault// (buserr_type & SUN3_BUSERR_PROTERR)	-> protection fault// (buserr_type & SUN3_BUSERR_INVALID)	-> invalid page fault		if (buserr_type & SUN3_BUSERR_PROTERR)			errorcode = 0x01;		else if (buserr_type & SUN3_BUSERR_INVALID)			errorcode = 0x00;		else {#ifdef DEBUG			printk ("*** unexpected busfault type=%#04x\n", buserr_type);			printk ("invalid %s access at %#lx from pc %#lx\n",				!(ssw & RW) ? "write" : "read", addr,				fp->ptregs.pc);#endif			die_if_kernel ("Oops", &fp->ptregs, buserr_type);			force_sig (SIGBUS, current);			return;		}//todo: wtf is RM bit? --m		if (!(ssw & RW) || ssw & RM)			errorcode |= 0x02;		/* Handle page fault. */		do_page_fault (&fp->ptregs, addr, errorcode);		/* Retry the data fault now. */		return;	}	/* Now handle the instruction fault. */	/* Get the fault address. */	if (fp->ptregs.format == 0xA)		addr = fp->ptregs.pc + 4;	else		addr = fp->un.fmtb.baddr;	if (ssw & FC)		addr -= 2;	if (buserr_type & SUN3_BUSERR_INVALID) {		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))			do_page_fault (&fp->ptregs, addr, 0);       } else {#ifdef DEBUG		printk ("protection fault on insn access (segv).\n");#endif		force_sig (SIGSEGV, current);       }}#else#if defined(CPU_M68020_OR_M68030)static inline void bus_error030 (struct frame *fp){	volatile unsigned short temp;	unsigned short mmusr;	unsigned long addr, errorcode;	unsigned short ssw = fp->un.fmtb.ssw;#ifdef DEBUG	unsigned long desc;	printk ("pid = %x  ", current->pid);	printk ("SSW=%#06x  ", ssw);	if (ssw & (FC | FB))		printk ("Instruction fault at %#010lx\n",			ssw & FC ?			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2			:			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);	if (ssw & DF)		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",			ssw & RW ? "read" : "write",			fp->un.fmtb.daddr,			space_names[ssw & DFC], fp->ptregs.pc);#endif	/* ++andreas: If a data fault and an instruction fault happen	   at the same time map in both pages.  */	/* First handle the data fault, if any.  */	if (ssw & DF) {		addr = fp->un.fmtb.daddr;#ifdef DEBUG		asm volatile ("ptestr %3,%2@,#7,%0\n\t"			      "pmove %%psr,%1@"			      : "=a&" (desc)			      : "a" (&temp), "a" (addr), "d" (ssw));#else		asm volatile ("ptestr %2,%1@,#7\n\t"			      "pmove %%psr,%0@"			      : : "a" (&temp), "a" (addr), "d" (ssw));#endif		mmusr = temp;#ifdef DEBUG		printk("mmusr is %#x for addr %#lx in task %p\n",		       mmusr, addr, current);		printk("descriptor address is %#lx, contents %#lx\n",		       __va(desc), *(unsigned long *)__va(desc));#endif		errorcode = (mmusr & MMU_I) ? 0 : 1;		if (!(ssw & RW) || (ssw & RM))			errorcode |= 2;		if (mmusr & (MMU_I | MMU_WP)) {			if (ssw & 4) {				printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",				       ssw & RW ? "read" : "write",				       fp->un.fmtb.daddr,				       space_names[ssw & DFC], fp->ptregs.pc);				goto buserr;			}			/* Don't try to do anything further if an exception was			   handled. */			if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)				return;		} else if (!(mmusr & MMU_I)) {			/* probably a 020 cas fault */			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {			printk("invalid %s access at %#lx from pc %#lx\n",			       !(ssw & RW) ? "write" : "read", addr,			       fp->ptregs.pc);			die_if_kernel("Oops",&fp->ptregs,mmusr);			force_sig(SIGSEGV, current);			return;		} else {#if 0			static volatile long tlong;#endif			printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",			       !(ssw & RW) ? "write" : "read", addr,			       fp->ptregs.pc, ssw);			asm volatile ("ptestr #1,%1@,#0\n\t"				      "pmove %%psr,%0@"				      : /* no outputs */				      : "a" (&temp), "a" (addr));			mmusr = temp;			printk ("level 0 mmusr is %#x\n", mmusr);#if 0			asm volatile ("pmove %%tt0,%0@"				      : /* no outputs */				      : "a" (&tlong));			printk("tt0 is %#lx, ", tlong);			asm volatile ("pmove %%tt1,%0@"				      : /* no outputs */				      : "a" (&tlong));			printk("tt1 is %#lx\n", tlong);#endif#ifdef DEBUG			printk("Unknown SIGSEGV - 1\n");#endif			die_if_kernel("Oops",&fp->ptregs,mmusr);			force_sig(SIGSEGV, current);			return;		}		/* setup an ATC entry for the access about to be retried */		if (!(ssw & RW) || (ssw & RM))			asm volatile ("ploadw %1,%0@" : /* no outputs */				      : "a" (addr), "d" (ssw));		else			asm volatile ("ploadr %1,%0@" : /* no outputs */				      : "a" (addr), "d" (ssw));	}	/* Now handle the instruction fault. */	if (!(ssw & (FC|FB)))		return;	if (fp->ptregs.sr & PS_S) {		printk("Instruction fault at %#010lx\n",			fp->ptregs.pc);	buserr:		printk ("BAD KERNEL BUSERR\n");		die_if_kernel("Oops",&fp->ptregs,0);		force_sig(SIGKILL, current);		return;	}	/* get the fault address */	if (fp->ptregs.format == 10)		addr = fp->ptregs.pc + 4;	else		addr = fp->un.fmtb.baddr;	if (ssw & FC)		addr -= 2;	if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)		/* Insn fault on same page as data fault.  But we		   should still create the ATC entry.  */		goto create_atc_entry;#ifdef DEBUG	asm volatile ("ptestr #1,%2@,#7,%0\n\t"		      "pmove %%psr,%1@"		      : "=a&" (desc)		      : "a" (&temp), "a" (addr));#else

⌨️ 快捷键说明

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