📄 vectors.c
字号:
mtpr (VINTSR, 0); } else { mtpr (VINTSR, VINTSR_DISABLE_VECT_INTF); } if ((ls_vintsr & LS_VINTSR_SET) != LS_VINTSR_SET) { return (FALSE); } else if ((ls_vintsr & LS_VINTSR_CLR) != 0) { return (FALSE); } else if ((ls_mod_rev & 0x80) != 0x80) { return (FALSE); } else if ((ls_vctl_csr & LS_VCTL_CSR_CLR) != 0) { return (FALSE); } else if ((ls_lsx_ccsr & LS_LSX_CCSR_CLR) != 0) { return (FALSE); } else if ((ls_alu_diag_ctrl & LSX_ALU_DIAG_CTRL_CLR) != 0) { return (FALSE); } else { return (TRUE); } }}#define VPC_ERROR (VPC_ERROR_IMP | VPC_ERROR_IVO | VPC_ERROR_AEX | \ VPC_ERROR_PMF)#define VPSR_ERROR (VPSR_IMP | VPSR_IVO | VPSR_AEX | VPSR_PMF)vp_disabled_fault_handler (mode)int mode; /* VP_DIS_USER_MODE or VP_DIS_KERN_MODE */{/* * input: mode VP_DIS_USER_MODE or * VP_DIS_KERN_MODE * output: unknown at this time * description: */int new_affinity; /* new affinity mask of a process becoming a * vector process or of a process which needs * to switch it's affinity for some other * reason. */int save_VPSR; /* save contents of VPSR for multiple tests * of various error bits. */struct cpudata *pcpu;struct vpdata *vpd;struct vpcontext *current_vpc;struct vpcontext *owning_vpc; pcpu = CURRENT_CPUDATA; vpd = pcpu->cpu_vpdata; current_vpc = pcpu->cpu_proc->p_vpcontext; if (mode == VP_DIS_KERN_MODE) { /* * process is running in kernel mode. since kernel code is not * supposed to use the VP for calculating, this is most likely a * fatal error. there are some exceptions to this: * 1. during vector process context switches, kernel mode code * will move data to/from VP registers. however, the code * which does this will set the VPD_IN_KERNEL flag and make sure * that the vector processor is enabled. * 2. an implentation dependent error may have occured. in this * case it may be possible to switch processors and keep going. */ if (vpd->vpd_proc == NULL) { /* * This process does not "own" the Vector Processor. Either * this process issued a vector instruction while in kernel * mode, or some hardware error has occured. In either case, */ panic("DVF in Kernel Mode - no owner of the vector processor"); } else if (vpd->vpd_in_kernel != VPD_IN_KERNEL) { /* * since this process is running in kernel mode, it should * have set the VPD_IN_KERNEL flag before doing anything that * could have cause this fault. */ panic("DVF in Kernel mode - vpd_in_kernel not set"); } else if (mfpr(VPSR) & VPSR_IMP) { /* * There was an implementation dependent error. There may be * hope. go see if this is a fatal error (fatal to the VP, * that is). It is possible that the VP had a problem which * need not be fatal to the process. */ /* NOTE: * to date, the only processors (6000-400, 6000-500 and 9000) * which have vectors cannot produce this error. So, * vp_imp() will panic if it is called. BUT: if this * section of code is ever to be executed, it should be * reviewed first. There are a couple of problems that I * can see: * 1. if the VP went bad with state in it, then the * user process should be killed, not switched to * another processor. * 2. if the VP state is saved, then the process can * continue, but switch_affinity should not be * called. If the disabled fault is allowed to * just exit, then the retry of the instruction * will automatically cause it to be moved to * another processor */ if (vp_imp() == VP_IMP_FATAL) { /* * permanently diable the VP and remove knowledge of * it's existance */ vp_remove (); /* update statistics here */ /* * set the VPC_ERROR_IMP bit in vpc_error so that when * this instruction is re-tried on another processor, * or if the process dies, it will still know that * there was a IMP failure. */ current_vpc->vpc_error |= VPC_ERROR_IMP; /* * if there is still a functioning vector processor, * then set process affinity to vpmask. This way when * the instruction is re-tried it will either get * another disabled fault on another processor. if * this was the last functioning vector processor in * this system (know this by checking vptotal) then * kill the process. */ if (vptotal) { /* * switch_affinity() (defined in * sys/kern_subr.c) is a routine to assign a * new affinity to a process and to switch the * process to the new cpu. this routine will * do the swtch(). it uses u.u_procp as the * proc pointer, so at least for debug * purposes i want to check this out. */ if (pcpu->cpu_proc != u.u_procp) panic ("DVF: pcpu->cpu_proc != u.u_procp"); new_affinity = vpmask & current_vpc->vpc_affinity; if (new_affinity == 0) panic ("DVF: vector affinity problem"); else { switch_affinity (new_affinity); pcpu = CURRENT_CPUDATA; vpd = pcpu->cpu_vpdata; current_vpc = pcpu->cpu_proc->p_vpcontext; } } else { /* no more functioning VPs in system */ /* need a u_code or a u_error here */ u.u_code = TERM_VECT_HARD; psignal (pcpu->cpu_proc, SIGKILL); } } else { /* * IMP error was not fatal to the VP, so it is fatal * to the process. Set the VPC_ERROR_IMP bit in * vpc_error so that when this process dies, it will * know that there was an IMP failure. */ current_vpc->vpc_error |= VPC_ERROR_IMP; /* * send a SIGKILL (kill signal) to the process * note: if there is ever a vector * implementation which can recover from a IMP * error, then it might be possible to let the * process continue. */ psignal (pcpu->cpu_proc, SIGKILL); } } else /* * This process is in Kernel mode, the vpd_in_kernel flag is * set and there has not been an IMP error, so some kernel * mode code is accessing VP registers without first making * sure that the VP is enabled, or something went wrong with * load/store/test of a VP register. The only thing left to * do is ... panic * * debby - note that the design spec spelled out checking for * AEX and IVO. since i am panicing at this point, i don't * see the purpose, but i didn't want to forget that i had * made this decision */ panic("DVF while in Kernel Mode"); } else { /* in user mode */ /* * wait for the VP to go idle, all memory references to * complete and all errors to be reported. This is a hook for * future changes to the vector support. If, in the futrue, we * decide to let one process run on the VP while another runs on * the SP, then this step becomes necessary. As long as we force * the same process to be running on the SP as is running on the * VP this step is uncessary. */ while (mfpr(VPSR) & VPSR_BSY) ; mfpr (VMAC); mfpr (VMAC); /* * sanity check - debug only * make sure cpu_proc and u_procp agree */ if (pcpu->cpu_proc != u.u_procp) panic ("DVF: CURRENT_CPUDATA->cpu_proc and u.uprocp do not agree"); /* * if this process does not have a vpcontext area then it asking to * become a vector process. go ahead and call vp_allocate() to * allocate the vpcontext area, and to intialize it. mask out the * non-vector present processors from the process affinity. this will * limit this process to: * 1. scalar processors it was already limited to * 2. scalar processors which are part of a scalar/vector pair * note: do not set affinity to just this processor because there is a * possibility that vp_proc will tell us that we cannot have this * processor. * if the new process affinity is zero (this will only happen if the * process was already limited to a set of processors which were not * part of a scalar/vector pair) then kill the process. */ if (current_vpc == NULL) { if (vp_allocate (pcpu->cpu_proc) == VP_FAILURE) { return; } current_vpc = pcpu->cpu_proc->p_vpcontext; new_affinity = pcpu->cpu_proc->p_affinity & vpmask; if (new_affinity == 0) { panic ("DVF: vector affinity problem"); } else { pcpu->cpu_proc->p_affinity = new_affinity; } current_vpc->vpc_state = VPC_WAIT; } /* * check for and deal with any errors which may have occured. * if the vector processor has no "owner" then * - clear the hardware (if necessary) * - log the error * - allow the process which caused this disabled vector * processor error to continue. * if the vector processor has an "owner" then * - charge the owning process with the error * - determine if the owning process can continue processing * (most likely not). */ if (vpd->vpd_proc == NULL) { /* * there is no current vector process which "owns" this vector * processor, so clean up any pending errors */ if (mfpr(VPSR) & VPSR_IMP) { /* * there has been an implementation dependent error. * call vp_imp() to perform any necessary error * recovery and to determine if the error is fatal to * the vector processor. */ /* NOTE: * to date, the only processors (6000-400, 6000-500 * and 9000) which have vectors cannot produce this * error. So, vp_imp() will panic if it is called. */ if (vp_imp() == VP_IMP_FATAL) { /* * permanently diable the VP and remove * knowledge of it's existance */ vp_remove (); /* update statistics here */ if (vptotal) { /* switch_affinity() (defined in * sys/kern_subr.c) is a routine to * assign a new affinity to a process * and to switch the process to the * new cpu. */ /* the new affinity of this process is * the logical and of the processors * which were in the affinity mask * before this process became a vector * process and the cpu mask of those * processors which have a functioning * vector processor. if this new * affinity is zero, then there are no * processors which are capable of * running this process */ new_affinity = vpmask & current_vpc->vpc_affinity; if (new_affinity == 0) { panic ("DVF: vector affinity problem"); } else { switch_affinity (new_affinity); pcpu = CURRENT_CPUDATA; vpd = pcpu->cpu_vpdata; current_vpc = pcpu->cpu_proc->p_vpcontext; } } else { /* no more functioning VPs in system */ u.u_code = TERM_VECT_HARD; psignal (pcpu->cpu_proc, SIGKILL); return ; } } /* the IMP error was not fatal to the VP */ panic ("DVF: uerf: IMP error, u mode, no own\n"); } /* endif - test for VPSR_IMP error */ if (mfpr(VPSR) & VPSR_AEX) /* vector processor arithmetic exception error */ mprintf ("DVF: uerf: AEX error, u mode, no owner\n"); if (mfpr(VPSR) & VPSR_IVO) /* vector processor illegal operand error */ panic ("DVF: uerf: IVO error, u mode, no owner\n"); } else { /* some process owns the VP */ owning_vpc = vpd->vpd_proc->p_vpcontext; /* * look for the errors. if there are any errors then log * them in the vpc_error field of the vpcontext structure and * clear the hardware. */ save_VPSR = mfpr (VPSR); if (save_VPSR & VPSR_IMP) { /* * there has been an implementation dependent error. * call vp_imp() to handle the error and to determine * if it is fatal to the vector processor. if it is * fatal to the vector processor, then call * vp_remove() to perminently remove the vector * processor from consideration as an operational * vector processor. */ /* NOTE: * to date, the only processors (6000-400, 6000-500 * and 9000) which have vectors cannot produce this * error. So, vp_imp() will panic if it is called. */ if (vp_imp() == VP_IMP_FATAL) vp_remove(); owning_vpc->vpc_error |= VPC_ERROR_IMP; } if (save_VPSR & VPSR_AEX) { /* * there has been an arithmetic exception error on the * vector processor. set the error bit in the * process's vpcontext struct, and make a copy of the * Vector Arithmethic Exception Register (this * register contains the encoded exception condition * summary - see chap 13 of the VAX Architecture * Standard for a breakdown of the contents of this * register. */ owning_vpc->vpc_error |= VPC_ERROR_AEX; owning_vpc->vpc_vaer = mfpr(VAER); } if (save_VPSR & VPSR_IVO) { /* * there has been an illegal vector opcode error. set * the error bit in the process's vpcontext struct. * debby - need to save pc ?? if so where and how ?? */ owning_vpc->vpc_error |= VPC_ERROR_IVO; } if (save_VPSR & VPSR_PMF) { /* * there has been a pending memory fault error. this * is cause for panic, since I have absolutely no code * in place to handle this */ panic("DVF: pending memory fault"); } /* * now that we have save off all the info we need, it there * have been any errors, then reset clear the * hardware. * then decide whether the process lives or dies. * if it dies as the result of an arithmetic error, then * send it a nice error packet. */ if (save_VPSR & VPSR_ERROR) { /* * there was some error, so reset the hardware. * this is done by setting the VPSR_BIT. This * will clear the VPSR (vector processor status * register) and the VAER (vector arithmetic * exception register. This will also clear all * the exceptions in the VP. */ mtpr (VPSR, VPSR_RST); mfpr(VPSR); if(cpu == VAX_6400) { /* note: re-setting the Rigel/Mariah * vector processor disables memory * mapping; need to re-enable it here. */ /* Enable mapping */ mtpr(VIADR, 0x509); mtpr(VIDLO, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -