📄 vectors.c
字号:
#ifndef lintstatic char *sccsid = "@(#)vectors.c 4.6 ULTRIX 4/12/91";#endif lint/************************************************************************ * * * Copyright (c) 1983,1986,1988,1990 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* ------------------------------------------------------------------------ * Modification History: /sys/machine/vax/vectors.c * * 11-Apr-91 dlh * decreased number of times pointers were calculated * * added smp locks around uses of vpmask, vpfree & vptotal * * disabled fault handler: * - new affinity after vp_contextsave - now considers pre-vector * affinity. * - also will not allow new affinity to become zero. this could * have happened if the boot cpu does not have a vp and the * process has been forced to the boot cpu. * * vp_reset: * set's state of CURRENT cpu, not input cpu. * * vp_contextlimbo: * - if a CPU is being stopped, then it's VP context needs to be * saved, and it's affinity needs to be changed. * - Also, do not let the affinity go to zero. This would happen * if the secondary CPUs are being stopped and the boot * CPU does not have an attached vector processor. In * this case the vector process would 'hang' until a * secondary CPU with a VP is re-started. * * 12/20/90 - dlh * added parameter to vp_reset() * * 12/18/90 -- paradis * Added vp_idle() routine. * * 10/10/90 -- paradis * Added VAX 9000 support (this consisted primarily of identifying * those sections peculiar to Rigel/Mariah and making them * conditional on "if(cpu == VAX_6400)" * * 9/4/90 -- dlh * original * * * ------------------------------------------------------------------------ */#include "../h/types.h"#include "../h/param.h"#include "../machine/vectors.h"#include "../h/cpudata.h"#include "../h/time.h"#include "../machine/mtpr.h"#include "../h/proc.h"#include "../h/kmalloc.h"#include "../../machine/common/cpuconf.h"#include "../h/user.h"#include "../h/acct.h"#include "../h/signal.h"#ifdef VAX6400#include "../machine/ka6400.h"#endif VAX6400int max_vec_procs;#ifdef VECTORSvp_allocate (p)struct proc *p;{/* * input: pointer to proc structure of process which wants to * allocate a vpcontext area * output: VP_FAILURE or VP_SUCCESS * description: Convert a regular process to a vector process by allocating a * vector context (vpcontext) area for that process. Initialize * the vpcontext area. * side effect: set AVP flag in the accounting flag of the u area * errors: There is a maximum number of vector processes which are * allowed. If this maximum is exceeded then vp_allocate will * fail. * note: KM_ALLOC will sleep if there is not enough memory available * for the allocation. Therefore it is guaranteed that the * allocation will succeed. */struct vpcontext *vpc; if (++num_vec_procs > max_vec_procs) { --num_vec_procs; u.u_code = TERM_VECT_TOOMANY; u.u_error = EAGAIN; uprintf ("too many vector processes\n"); psignal (CURRENT_CPUDATA->cpu_proc, SIGTERM); return (VP_FAILURE); } KM_ALLOC ( p->p_vpcontext, struct vpcontext *, sizeof(struct vpcontext), KM_VECTOR, KM_CLEAR | KM_CONTIG); vpc = p->p_vpcontext; u.u_acflag |= AVP; vpc->vpc_state = VPC_WAIT; /* waiting for a vector processor to be allocated for this * process; i.e.: this process is a vector process, but it * does not have it's vector context stored in any vector * processor. */ vpc->vpc_affinity = p->p_affinity; /* save the current affinity of the process. This will allow * for returning to the saved affinity if this process ever * decides it is no longer a vector processes */ /* no need to initialize the vpc_refuse, vpc_cheap or the * vpc_expen fields since the memory was zeroed by KM_ALLOC() */ KM_ALLOC (vpc->vpc_vregs, char *, VPREGSIZE, KM_VECTOR, KM_CLEAR | KM_CONTIG); return (VP_SUCCESS);}vp_proc (p)struct proc *p;{/* * input: pointer to proc structure of process which is requesting the * attached vector processor * output: PROC_MAY_HAVE_VP or PROC_MAY_NOT_HAVE_VP (defined in vectors.h) * description: decide if the process can be given the attached vector * processor. * errors: * assumption: before calling vp_proc() the caller should test to see if * there is only one VP in the system. This may be done by * using the VP_PROC macro defined in vectors.h * issues: what if vptotal == 1 && vpd_state == VPD_DEAD ?? this * routine will never be called. */struct cpudata *pcpu;struct vpdata *vpd; pcpu = CURRENT_CPUDATA ; vpd = pcpu->cpu_vpdata ; if (vpd->vpd_state == VPD_DEAD) return (PROC_MAY_NOT_HAVE_VP); else if (vpd->vpd_proc == NULL) return (PROC_MAY_HAVE_VP); /* else if # of times this process has been refused is too great */ /* return (PROC_MAY_HAVE_VP); */ else if (pcpu->cpu_mask == p->p_affinity) return (PROC_MAY_HAVE_VP); else if (vpfree) return (PROC_MAY_NOT_HAVE_VP); else return (PROC_MAY_HAVE_VP);}vp_remove (){/* * input: none * description: permanently disable and remove the attached vector processor * by clearing the Vector Present bit in the Access Control and * Status register. Also remove software reference to this * processor. * note: the variable cpu is declared in cpu.h, but I have not yet * tracked down where it is initialized. */struct cpudata *pcpu;struct vpdata *vpd; pcpu = CURRENT_CPUDATA ; if (cpu==VAX_6400) { mtpr(ACCS,mfpr(ACCS) & ~1); } else { printf ("vp_remove(): cpu %d\n", cpu); } /* * update the system wide masks and count */ clear_bit_atomic (pcpu->cpu_num, &vpmask); clear_bit_atomic (pcpu->cpu_num, &vpfree); adawi ((-1), &vptotal); /* * update the vpdata struct withing the cpudata struct to reflect * the fact that the attached vp is out of commission. */ vpd = pcpu->cpu_vpdata ; vpd->vpd_proc = NULL; vpd->vpd_state &= ~(VPD_ALIVE | VPD_ENABLED); vpd->vpd_state |= VPD_DEAD;}vp_contextsave (p)struct proc *p;{/* * input: proc struct pointer * output: VP_FAILURE or VP_SUCCESS * description: copy the vector process context area from the vector * processor to the vpcontext area pointed to by the proc * struct. * assumptions: process is running on the SP-VP pair whose VP contains the * vpcontext * note: caller is responsible for: * updating the p_affinity * updating the vpc_state * updating the vpd_proc * this routine leaves the vector processor enabled. */struct cpudata *pcpu;struct vpcontext *vpc;struct vpdata *vpd; pcpu = CURRENT_CPUDATA; vpd = pcpu->cpu_vpdata; vpc = p->p_vpcontext; /* * when ever vector instructions will be executed while the * process is kernel mode, the VPD_IN_KERNEL flag must be set. */ vpd->vpd_in_kernel = VPD_IN_KERNEL; /* * enable the vector processor. this will prevent a vector * disabled fault */ mtpr (VPSR, (mfpr(VPSR) | VPSR_VEN)); mfpr(VPSR); /* * wait for the VP to be idle */ while (mfpr(VPSR) & VPSR_BSY) ; /* * wait for completion of vector memory access, and all * errors to be reproted. */ mfpr (VMAC); mfpr (VMAC); if (vpc->vpc_error & VPC_ERROR_PMF) { /* * According to the Chap 13 of the VAX Arch spec (the * chapter on vector processors), this fault will only * happen in a system which implements the "asyncronous * method of memeory management", which I don't think we * have. (Can you tell I'm not sure of myself!) Also, * after talking to the ULTRIX vm experts, I don't think * this will happen as long as I continue to guarentee * that a vector process will never run on a vector * processor / scalar processor pair where the scalar * process is running some other process. Until I find * out different, or get to that stage of debug, this if * clause will just write to the error logger. * * If I ever do add in code to fill this if clause it will * save the hardware state by: * 1. load the VSAR (Vector State Address Register) with * a pointer to the hardware area. this must be in * memory which is guarentee'd not to cause an * exception (see section 13.2.3, Internal Processor * Registers , of vax arch spec) * 2. Set the VSS (Vector State Store) bit of the VPSR * (Vector Status Register). This will cause the * state to be save. */ panic ("vp_contextsave(): got a VPC_ERROR_PMF, now what ?!"); } else if (vpc->vpc_error & VPC_ERROR_IMP) { panic ("vp_contextsave(): got a VPC_ERROR_IMP, now what ?!"); } else { /* * save the vector control registers: VCR, VLR and all * 64-bits of VMR */ vpc->vpc_vcr = mfvcr(); vpc->vpc_vlr = mfvlr(); vpc->vpc_vmrlo = mfvmrlo(); vpc->vpc_vmrhi = mfvmrhi(); /* * save the vector registers (load the length register and * issue the Store Vector Register Data into Memory * instruction) * (debby: does this need to be a macro or maybe a routine?) */ mtvlr (64); vstq (vpc->vpc_vregs); /* wait for the store to complete */ while (mfpr(VPSR) & VPSR_BSY) ; mfpr (VMAC); mfpr (VMAC); } vpd->vpd_in_kernel = ~ VPD_IN_KERNEL; if (vpc->vpc_error & VPC_ERROR_IMP) return (VP_FAILURE); else return (VP_SUCCESS);}vp_contextrest (p)struct proc *p;{/* * input: proc struct pointer * output: VP_FAILURE or VP_SUCCESS * description: copy the vector process context area from the vpcontext * area pointed to by the proc struct to the vector processor * note: caller is responsible for updating the vpc_state and vpd_proc */struct vpdata *vpd;struct vpcontext *vpc; vpd = CURRENT_CPUDATA->cpu_vpdata; vpc = p->p_vpcontext; vpd->vpd_in_kernel = VPD_IN_KERNEL; if (vpc->vpc_error & VPC_ERROR_IMP) { panic ("vp_contextrest(): got a VPC_ERROR_IMP, now what ?!"); } else { /* * restore the vector registers (load the length register and * issue the Load Memory Data into Vector Register * instruction) * (debby: does this need to be a macro or maybe a routine?) */ mtvlr (64); vldq (vpc->vpc_vregs); /* * restore the vector control registers: VCR, VLR and all * 64-bits of VMR */ mtvcr(vpc->vpc_vcr); mtvlr(vpc->vpc_vlr); mtvmrlo(vpc->vpc_vmrlo); mtvmrhi(vpc->vpc_vmrhi); /* * wait for the vector instruction(s), the memory references * to complete and all errors to be reported */ while (mfpr(VPSR) & VPSR_BSY) ; mfpr (VMAC); mfpr (VMAC); if (vpc->vpc_error & VPC_ERROR_PMF) { /* * According to the Chap 13 of the VAX Arch spec (the * chapter on vector processors), this fault will only * happen in a system which implements the * "asyncronous method of memeory management", which * is on neither Rigel nor Aquarius, but will be * on Mariah, so I'll worry about this one * latter! Also, after talking to the ULTRIX vm * experts, I don't think this will happen as long as * I continue to guarentee that a vector process will * never run on a vector processor / scalar processor * pair where the scalar process is running some other * process. Until I find out different, or get to * that stage of debug, this if clause will just write * to the error logger. * * If I ever do add in code to fill this if clause it * will restore the hardware state by: * 1. load the VSAR (Vector State Address * Register) with a pointer to the hardware * area. this must be in memory which is * guarentee'd not to cause an exception (see * section 13.2.3, Internal Processor * Registers , of vax arch spec) * 2. Set the RLD (vector ReLoaD) bit of the VPSR * (Vector Status Register). This will cause * the state to be restored. * 3. Clear the soft copy of vpcontext area * Pending Memory Fault (PMF) bit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -