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

📄 traps.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	si.si_signo = SIGFPE;	si.si_errno = 0;	si.si_code = code;	si.si_addr = (void *) regs->iaoq[0];	force_sig_info(SIGFPE, &si, current);	return -1; send_sigill:	si.si_signo = SIGILL;	si.si_errno = 0;	si.si_code = ILL_COPROC;	si.si_addr = (void *) regs->iaoq[0];	force_sig_info(SIGILL, &si, current);	return -1; success:	/* We absolutely have to clear the T bit and exception           registers to allow the process to recover.  Otherwise every           subsequent floating point instruction will trap. */	sw.status.t = 0;	memset(excepts, 0, sizeof(excepts));	memcpy(regs->fr, &sw, sizeof(sw));	memcpy(((char *) regs->fr) + 4,excepts , sizeof(excepts));	return 0;}int handle_toc(void){	return 0;}void default_trap(int code, struct pt_regs *regs){	printk("Trap %d on CPU %d\n", code, smp_processor_id());	show_regs(regs);}void (*cpu_lpmc) (int code, struct pt_regs *regs) = default_trap;#ifdef CONFIG_KWDBintdebug_call (void) {    printk ("Debug call.\n");    return 0;}intdebug_call_leaf (void) {    return 0;}#endif /* CONFIG_KWDB */extern void do_page_fault(struct pt_regs *, int, unsigned long);extern void parisc_terminate(char *, struct pt_regs *, int, unsigned long);extern void transfer_pim_to_trap_frame(struct pt_regs *);extern void pdc_console_restart(void);void handle_interruption(int code, struct pt_regs *regs){	unsigned long fault_address = 0;	unsigned long fault_space = 0;	struct siginfo si;#ifdef CONFIG_KWDB	struct save_state ssp;#endif /* CONFIG_KWDB */   	if (code == 1)	    pdc_console_restart();  /* switch back to pdc if HPMC */	else	    sti();#ifdef __LP64__	/*	 * FIXME:	 * For 32 bit processes we don't want the b bits (bits 0 & 1)	 * in the ior. This is more appropriately handled in the tlb	 * miss handlers. Changes need to be made to support addresses	 * >32 bits for 64 bit processes.	 */	regs->ior &= 0x3FFFFFFFFFFFFFFFUL;#endif#if 0	printk("interrupted with code %d, regs %p\n", code, regs);	show_regs(regs);#endif	switch(code) {	case  1:		parisc_terminate("High Priority Machine Check (HPMC)",regs,code,0);		/* NOT REACHED */	case  3: /* Recovery counter trap */		regs->gr[0] &= ~PSW_R;		if (regs->iasq[0])			handle_gdb_break(regs, TRAP_TRACE);		/* else this must be the start of a syscall - just let it		 * run.		 */		return;	case  5:		flush_all_caches();		cpu_lpmc(5, regs);		return;	case  6:		fault_address = regs->iaoq[0];		fault_space   = regs->iasq[0];		break;	case  9: /* Break Instruction */		handle_break(regs->iir,regs);		return;	case 14:		/* Assist Exception Trap, i.e. floating point exception. */		die_if_kernel("Floating point exception", regs, 0); /* quiet */		handle_fpe(regs);		return;	case 15:	case 16:  /* Non-Access TLB miss faulting address is in IOR */	case 17:	case 26:		fault_address = regs->ior;		fault_space   = regs->isr;		if (code == 26 && fault_space == 0)		    parisc_terminate("Data access rights fault in kernel",regs,code,fault_address);		break;	case 19:		regs->gr[0] |= PSW_X; /* So we can single-step over the trap */		/* fall thru */	case 21:		handle_gdb_break(regs, TRAP_HWBKPT);		return;	case 25: /* Taken branch trap */		regs->gr[0] &= ~PSW_T;		if (regs->iasq[0])			handle_gdb_break(regs, TRAP_BRANCH);		/* else this must be the start of a syscall - just let it		 * run.		 */		return;#if 0 /* def CONFIG_KWDB */	case I_TAKEN_BR:	/* 25 */		mtctl(0, 15);		pt_regs_to_ssp(regs, &ssp);		kgdb_trap(I_TAKEN_BR, &ssp, 1);		ssp_to_pt_regs(&ssp, regs);		break;#endif /* CONFIG_KWDB */	case  8:		die_if_kernel("Illegal instruction", regs, code);		si.si_code = ILL_ILLOPC;		goto give_sigill;	case 10:		die_if_kernel("Priviledged operation - shouldn't happen!", regs, code);		si.si_code = ILL_PRVOPC;		goto give_sigill;	case 11:		die_if_kernel("Priviledged register - shouldn't happen!", regs, code);		si.si_code = ILL_PRVREG;	give_sigill:		si.si_signo = SIGILL;		si.si_errno = 0;		si.si_addr = (void *) regs->iaoq[0];		force_sig_info(SIGILL, &si, current);		return;	case 28:  /* Unaligned just causes SIGBUS for now */		die_if_kernel("Unaligned data reference", regs, code);		si.si_code = BUS_ADRALN;		si.si_signo = SIGBUS;		si.si_errno = 0;		si.si_addr = (void *) regs->ior;		force_sig_info(SIGBUS, &si, current);		return;	default:		if (user_mode(regs)) {			printk("\nhandle_interruption() pid=%d command='%s'\n",			    current->pid, current->comm);			show_regs(regs);			/* SIGBUS, for lack of a better one. */			si.si_signo = SIGBUS;			si.si_code = BUS_OBJERR;			si.si_errno = 0;			si.si_addr = (void *) regs->ior;			force_sig_info(SIGBUS, &si, current);			return;		}		parisc_terminate("Unexpected Interruption!",regs,code,0);		/* NOT REACHED */	}	if (user_mode(regs)) {	    if (fault_space != regs->sr[7]) {		if (fault_space == 0)			printk("User Fault on Kernel Space ");		else /* this case should never happen, but whatever... */			printk("User Fault (long pointer) ");		printk("pid=%d command='%s'\n", current->pid, current->comm);		show_regs(regs);		si.si_signo = SIGSEGV;		si.si_errno = 0;		si.si_code = SEGV_MAPERR;		si.si_addr = (void *) regs->ior;		force_sig_info(SIGSEGV, &si, current);		return;	    }	}	else {	    /*	     * The kernel should never fault on its own address space.	     */	    if (fault_space == 0)		    parisc_terminate("Kernel Fault",regs,code,fault_address);	}#ifdef CONFIG_KWDB	debug_call_leaf ();#endif /* CONFIG_KWDB */	do_page_fault(regs, code, fault_address);	/*	 * This should not be necessary.	 * However, we do not currently	 * implement flush_page_to_ram.	 *	 * The problem is that if we just	 * brought in some code through the	 * D-cache, the I-cache may not see	 * it since it hasn't been flushed	 * to ram.	 *//* 	flush_all_caches(); */#if 0	printk("returning %p\n", regs);/*	show_regs(regs); */#endif	return;}void show_stack(unsigned long sp){#if 1	if ((sp & 0xc0000000UL) == 0xc0000000UL) {	    __u32 *stackptr;	    __u32 *dumpptr;	    /* Stack Dump! */	    stackptr = (__u32 *)sp;	    dumpptr  = (__u32 *)(sp & ~(INIT_TASK_SIZE - 1));	    printk("\nDumping Stack from %p to %p:\n",dumpptr,stackptr);	    while (dumpptr < stackptr) {		printk("%04x %08x %08x %08x %08x %08x %08x %08x %08x\n",		    ((__u32)dumpptr) & 0xffff,		    dumpptr[0], dumpptr[1], dumpptr[2], dumpptr[3],		    dumpptr[4], dumpptr[5], dumpptr[6], dumpptr[7]);		dumpptr += 8;	    }	}#endif}void parisc_terminate(char *msg, struct pt_regs *regs, int code, unsigned long offset){	set_eiem(0);	cli();	if (code == 1)	    transfer_pim_to_trap_frame(regs);#if 1	show_stack(regs->gr[30]);#endif	printk("\n%s: Code=%d regs=%p (Addr=%08lx)\n",msg,code,regs,offset);	show_regs(regs);	for(;;)	    ;}void transfer_pim_to_trap_frame(struct pt_regs *regs){    register int i;    extern unsigned int hpmc_pim_data[];    struct pdc_hpmc_pim_11 *pim_narrow;    struct pdc_hpmc_pim_20 *pim_wide;    if (boot_cpu_data.cpu_type >= pcxu) {	pim_wide = (struct pdc_hpmc_pim_20 *)hpmc_pim_data;	/*	 * Note: The following code will probably generate a	 * bunch of truncation error warnings from the compiler.	 * Could be handled with an ifdef, but perhaps there	 * is a better way.	 */	regs->gr[0] = pim_wide->cr[22];	for (i = 1; i < 32; i++)	    regs->gr[i] = pim_wide->gr[i];	for (i = 0; i < 32; i++)	    regs->fr[i] = pim_wide->fr[i];	for (i = 0; i < 8; i++)	    regs->sr[i] = pim_wide->sr[i];	regs->iasq[0] = pim_wide->cr[17];	regs->iasq[1] = pim_wide->iasq_back;	regs->iaoq[0] = pim_wide->cr[18];	regs->iaoq[1] = pim_wide->iaoq_back;	regs->cr30 = pim_wide->cr[30];	regs->sar  = pim_wide->cr[11];	regs->iir  = pim_wide->cr[19];	regs->isr  = pim_wide->cr[20];	regs->ior  = pim_wide->cr[21];    }    else {	pim_narrow = (struct pdc_hpmc_pim_11 *)hpmc_pim_data;	regs->gr[0] = pim_narrow->cr[22];	for (i = 1; i < 32; i++)	    regs->gr[i] = pim_narrow->gr[i];	for (i = 0; i < 32; i++)	    regs->fr[i] = pim_narrow->fr[i];	for (i = 0; i < 8; i++)	    regs->sr[i] = pim_narrow->sr[i];	regs->iasq[0] = pim_narrow->cr[17];	regs->iasq[1] = pim_narrow->iasq_back;	regs->iaoq[0] = pim_narrow->cr[18];	regs->iaoq[1] = pim_narrow->iaoq_back;	regs->cr30 = pim_narrow->cr[30];	regs->sar  = pim_narrow->cr[11];	regs->iir  = pim_narrow->cr[19];	regs->isr  = pim_narrow->cr[20];	regs->ior  = pim_narrow->cr[21];    }    /*     * The following fields only have meaning if we came through     * another path. So just zero them here.     */    regs->ksp = 0;    regs->kpc = 0;    regs->orig_r28 = 0;}int __init check_ivt(void *iva){	int i;	u32 check = 0;	u32 *ivap;	u32 *hpmcp;	u32 length;	extern void os_hpmc(void);	extern void os_hpmc_end(void);	if(strcmp((char *)iva, "cows can fly"))		return -1;	ivap = (u32 *)iva;	for (i = 0; i < 8; i++)	    *ivap++ = 0;	/* Compute Checksum for HPMC handler */	length = (u32)((unsigned long)os_hpmc_end - (unsigned long)os_hpmc);	ivap[7] = length;	hpmcp = (u32 *)os_hpmc;	for(i=0; i<length/4; i++)	    check += *hpmcp++;	for(i=0; i<8; i++)	    check += ivap[i];	ivap[5] = -check;	return 0;}	#ifndef __LP64__extern const void fault_vector_11;#endifextern const void fault_vector_20;void __init trap_init(void){	volatile long eiem;	void *iva;	printk("trap_init\n");		if (boot_cpu_data.cpu_type >= pcxu)		iva = (void *) &fault_vector_20;	else#ifdef __LP64__		panic("Can't boot 64-bit OS on PA1.1 processor!");#else		iva = (void *) &fault_vector_11;#endif	if(check_ivt(iva))		panic("IVT invalid");	mtctl(0, 30);	mtctl(90000000, 16);	set_eiem(-1L);	mtctl(-1L, 23);	asm volatile ("rsm 0,%0" : "=r" (eiem));}

⌨️ 快捷键说明

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