📄 vectors.c
字号:
/* Initialize cache controller: Enable memory * transactions, enable cache, enable error * reporting, clear errors, and flush cache. */ mtpr(VIADR, 0x520); mtpr(VIDLO, 0x138e00); /* Initialize vector controller status * register enable hard and soft error * reporting. */ mtpr(VIADR, 0x489); mtpr(VIDLO, 0xc0000); /* read VMAC ??? */ /* do SYNC ??? */ } if (owning_vpc->vpc_error & VPC_ERROR_IMP) { u.u_code = TERM_VECT_HARD; psignal (vpd->vpd_proc, SIGKILL); } if (owning_vpc->vpc_error & VPC_ERROR_IVO) { u.u_code = ILL_VECOP_FAULT; uprintf ("illegal vector opcode on vector capable cpu\n"); psignal (vpd->vpd_proc, SIGILL); return ; } if (owning_vpc->vpc_error & VPC_ERROR_AEX) { if (vpd->vpd_proc != u.u_procp) panic ("DVF: not loading VAER into u_code"); else u.u_code = owning_vpc->vpc_vaer; psignal (vpd->vpd_proc, SIGFPE); } /* * if the current proc and the owning proc are the * same, then return. this will give control back * to trap(). trap() will see the signal and kill * the process. since the process is killed, the * instruction which caused the disabled fault will * not be re-issued (debby - is this true ???) */ if ((owning_vpc->vpc_error & VPC_ERROR) && (pcpu->cpu_proc == vpd->vpd_proc)) { return ; } } } /* end else VP has an owner */ /* end error processing */ if ( u.u_procp == vpd->vpd_proc ) { /* the current process already owns the vector processor */ /* Refresh the memory management registers */ /* * This is necessary for Rigel, and so it must be * necessary for Mariah. Not necessary for Aquarius. */ if(cpu == VAX_6400) { mtpr (P0BR, mfpr (P0BR)); mtpr (P0LR, mfpr (P0LR)); mtpr (P1BR, mfpr (P1BR)); mtpr (P1LR, mfpr (P1LR)); mtpr (SBR, mfpr (SBR)); mtpr (SLR, mfpr (SLR)); } /* * since there is an "owner" for the VP, it cannot be VPC_WAIT * nor VPC_SAVED. it must be VPC_LOAD or VPC_LIMBO. if it is * VPC_LOAD then the translation buffer is already o.k. if * it is VPC_LIMBO, then the translation buffer needs to be * invalidated */ if (owning_vpc->vpc_state == VPC_LIMBO) { /* flush the vector translation buffer */ /* * This is necessary for Rigel, and so it must be * necessary for Mariah. Not necessary for Aquarius. */ if(cpu == VAX_6400) mtpr (VTBIA, 0); owning_vpc->vpc_state = VPC_LOAD; } /* update statistics */ /* cheap context switches per process */ owning_vpc->vpc_cheap ++ ; /* cheap context switches per cpu */ vpd->vpd_ccsw ++ ; /* requesting process given "ownership" of vector processor */ vpd->vpd_success ++ ; /* * enable the vector processor (that is, after all, why I'm * here */ mtpr (VPSR, (mfpr(VPSR) | VPSR_VEN)); mfpr(VPSR); vpd->vpd_state &= ~ VPD_DISABLED; vpd->vpd_state |= VPD_ENABLED; return ; } /* * current process does not own the vector processor. if this is the * only vector processor in the system, then take it. if there is * more than one, then call vp_proc() to ask permission to take it. */ if ((vptotal == 1) || (vp_proc(pcpu->cpu_proc) == PROC_MAY_HAVE_VP)) { /* * go ahead and take the vector processor. * since we might have to call vp_contextsave() or * vp_contextrest() which will be executing stuff in kernel * mode, enable the vector processor now. */ mtpr (VPSR, (mfpr (VPSR) | VPSR_VEN) ); mfpr(VPSR); vpd->vpd_state &= ~ VPD_DISABLED; vpd->vpd_state |= VPD_ENABLED; /* * look to see if there is a context in the vector processor. * if there is, then the vector processor is "owned" by * someone else, and that vector process needs to be saved * before this vector process can "steal" the vector * processor. */ if (vpd->vpd_proc != NULL) { if (vp_contextsave (vpd->vpd_proc) == VP_FAILURE) { /* * vp_contextsave() will only fail if it * gets a vector IMP error. When this * happen the system panics, to the * following signal will never be * reached. However... Some future * vector implementation may allow a * recovery from an IMP error. If that * ever happens then the following * psignal should be reconsidered. */ psignal (vpd->vpd_proc, SIGKILL); return ; } /* * vp_contextsave() succeeded so restore the saved * affinity and update the vpc_state. update vpfree * and update the state of the saved process * note: if the saved affinity does not include a * cpu with a vector unit, then don't touch * the process affinity. The only time * this could occur is if the following * happens: * - there is no vector processor on the * boot cpu * - the vector process, while in a state * of VPC_LIMBO issues an instruction * which causes the kernel to move the * process to the boot cpu. While there, * the process needs to wait for some * reason and is taken off of the run queue. * - another vector process takes this * vector cpu, forcing a vp_contextsave() * on this process. Since vpc_affinity * is kept up to date by switch_affinity, * the saved affinity would not include a * cpu with a vector processor. * - note: the routine which calls * switch_affinity is responsible for * keeping a copy of the old affinity. * Therefore, before the user level * process can execute another vector * instruction, an affinity which includes * a vector processor will be in place. */ new_affinity = owning_vpc->vpc_affinity & vpmask; if (new_affinity != 0) { vpd->vpd_proc->p_affinity = new_affinity; } owning_vpc->vpc_state = VPC_SAVED; vpd->vpd_proc = NULL; set_bit_atomic (pcpu->cpu_num, &vpfree); } /* * make the current process the owner of the vector processor. * update the vpfree mask. load this process's vector context * into the vector processor. */ vpd->vpd_proc = pcpu->cpu_proc; owning_vpc = vpd->vpd_proc->p_vpcontext; if (vp_contextrest (pcpu->cpu_proc) == VP_FAILURE) { /* * vp_contextrest() will only fail if it gets a * vector IMP error. When this happen the system * panics, to the following signal will never be * reached. However... Some future vector * implementation may allow a recovery from an * IMP error. If that ever happens then the * following psignal should be reconsidered. */ psignal (pcpu->cpu_proc, SIGKILL); return ; } else { owning_vpc->vpc_state = VPC_LOAD; } clear_bit_atomic (pcpu->cpu_num, &vpfree); /* limit this process's affinity to this cpu */ pcpu->cpu_proc->p_affinity = pcpu->cpu_mask; /* * refresh the memory management registers, this is done by * writing to these regs on the scalar, this will cause the * vector copy to be updated. and invalidate the translation * buffer */ /* * This is necessary for Rigel, and so it must be * necessary for Mariah. Not necessary for Aquarius? */ if(cpu == VAX_6400) { mtpr (P0BR, mfpr (P0BR)); mtpr (P0LR, mfpr (P0LR)); mtpr (P1BR, mfpr (P1BR)); mtpr (P1LR, mfpr (P1LR)); mtpr (SBR, mfpr (SBR)); mtpr (SLR, mfpr (SLR)); mtpr (VTBIA, 0); } /* update statistics */ /* expensive context switches per process */ owning_vpc->vpc_expen ++ ; /* expensive context switches per cpu */ vpd->vpd_ecsw += 1 ; /* requesting process given "ownership" of vector processor */ vpd->vpd_success ++ ; /* clear the vpd_in_kernel flag */ vpd->vpd_in_kernel = ~VPD_IN_KERNEL; return ; } else { /* vp_proc() returned PROC_MAY_NOT_HAVE_VP */ /* update statistics */ /* no. times process refused "ownership" (count per process) */ current_vpc->vpc_refuse ++ ; /* requesting process refued "ownership" of vector processor * (count per cpu) */ vpd->vpd_failed ++ ; /* * eliminate this processor from the process's affinity mask. * this will prevent this process from being immediately * scheduled on this processor again. note: don't need to * check for an affinity of zero here because that possibility * would have been eliminated by vp_proc(). * (need switch_affinity ???) */ pcpu->cpu_proc->p_affinity &= ~(pcpu->cpu_mask); return ; } } /* endif - kernel or user mode */}vp_reset (cpu_number)int cpu_number;{int i;/* * input: cpu_number * the cpu number of the cpu whose vector processor is being * reset. * note: this cannot be obtained from CURRENT_CPUDATA because * when a non-boot processor is being started, * CURRENT_CPUDATA refers to the boot cpu, but this * routine is resetting one of the non-boot cpus. * description: reset the vector processor from the scalar side and from the * vector side. leave the vector processor disabled, but make * sure that memory management is enabled. * issues: */ if(cpu == VAX_6400) { /* Rigel/Mariah only */ /* * first, reset from the scalar side. This is done by setting * the reset bit in the Vector INTerface Status Register. This * bit must be set for 100 scalar cycles. Then it may be * cleared. It must be cleared for 100 cycles before accessing * the vector processor. */ mtpr (VINTSR, VINTSR_VECTOR_MODULE_RESET); for (i=0; i<100; i++) ; mtpr (VINTSR, 0); for (i=0; i<100; i++) ; } /* * wait for the VP to go idle, and all memory references to complete * and all errors to be reported. this is probably unnessary since * it follows a reset, but it's unlikely that it will hurt. also, * the spec says that a VPSR_RST while VPSR_BSY is set will have * undefined results, so ... */ while (mfpr(VPSR) & VPSR_BSY) ; mfpr (VMAC); mfpr (VMAC); /* * now reset the vector side. setting the VPSR_RST bit will * clear the VPSR (vector processor status register), the VAER * (vector arithmetic exception register and the VCTL_CSR. * Leave the VP disabled. */ mtpr (VPSR, VPSR_RST); mfpr(VPSR); if (cpu==VAX_6400) { /* * Enable mapping by writting a 1 to VIR_LSX_TBCSR (TB control * register) */ mtpr(VIADR, 0x509); mtpr(VIDLO, 1); /* Initialize cache controller: Enable memory transactions, * enable cache, enable error reporting, clear errors, * and flush cache. * this is donw by writing a 0x138e00 to VIR_LSX_CCSR (Cache * control register) */ mtpr(VIADR, 0x520); mtpr(VIDLO, 0x138e00); /* Initialize vector controller status register; enable * hard and soft error reporting. * This is done by writing a 0xc0000 to VIR_VCTL_CSR (Vector * controller Status) */ mtpr(VIADR, 0x489); mtpr(VIDLO, 0xc0000); /* * refresh the memory management registers, this is done by * writing to these regs on the scalar, this will cause the * vector copy to be updated. and invalidate the translation * buffer */ mtpr (P0BR, mfpr (P0BR)); mtpr (P0LR, mfpr (P0LR)); mtpr (P1BR, mfpr (P1BR)); mtpr (P1LR, mfpr (P1LR)); mtpr (SBR, mfpr (SBR)); mtpr (SLR, mfpr (SLR)); mtpr (VTBIA, 0); } CURRENT_CPUDATA->cpu_vpdata->vpd_state = VPD_ALIVE | VPD_DISABLED;}vp_imp (){/* * input: unknown at this time * output: VP_IMP_FATAL or VP_IMP_NOT_FATAL * description: handle implementation specific vector hardware errors. do * whatever the specific implementation has recommended and * clear VPSR<IMP>. */ panic ("vp_imp(): now what??"); return (VP_IMP_FATAL);}vp_idle(){/* * description: Idle the vector processor (if any) associated with the * current scalar processor. */ if(vpmask & (1 << CURRENT_CPUDATA->cpu_num)) { while(mfpr(VPSR) & VPSR_BSY) ; mfpr(VMAC); mfpr(VMAC); }}#endif VECTORS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -