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

📄 vm_pt.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)vm_pt.c	4.1	(ULTRIX)	7/2/90";#endif lint/*********************************************************************** *									* *			Copyright (c) 1984,86 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 * * 14 Sep 88 -- jaa *	Fixed vgetu() for mips box * * 15 Dec 86 -- depp *	Added fix to shared memory handling, in regards to a process' SM  *	page table swapping space.   * * 11 Sep 86 -- koehler *	gnode name change * * 18 Jun 86 -- depp *	Added ZFOD to distsmpte * * 17 Mar 86 -- depp *	Added fix to "stale stack" problem in "vrelu" and "vrelpt" * * 12-Feb-86 -- jrs *	Added calls to tbsync() for mp translation buffer control * * 03 Jan 86 -- depp *	Added check in "distsmpte" for NULL sm_caddr. * * 13 Nov 85 -- depp *	Added "cm" parameter to distsmpte call.  This parameter indicates that *	the "pg_m" bit is to be cleared in the processes PTEs that are sharing *	a data segment.  This replaces the "pg_cm" definition of "pg_alloc" *	which could cause a conflict. * * 11 Nov 85 -- depp *	Removed all conditional compiles for System V IPC. * * 19 Jul 85 -- depp *	Changed method of updating pte's in "distsmpte" so that only *	pg_v and pg_pfnum are updated everytime and pg_m is updated *	only if the pg_cm bit is set in the gpte. * *	Removed the pg_m set in "dirtysm".  It wasn't needed. * * 03 Apr 85 -- depp *	Added new routine "dirtysm" to indicate if any shared memory pte *	is dirty * * 11 Mar 85 -- depp *	Add in System V shared memory support including the following new *	routines: *		vgetsmpt	allocation shared memory pte *		vinitsmpt	initialize shared memory pte *		distsmpte	update all pte's in all processes that are *				sharing a given page *		 * 19 Dec 84 -- jrs *	Changed setjmp's to savectx for swap recovery fixes *	Derived from 4.2 BSD, labeled: *		vm_pt.c	6.1	84/07/29 * *---------------------------------------------------------------------- */#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/proc.h"#include "../h/map.h"#include "../h/cmap.h"#include "../h/vm.h"#include "../h/buf.h"#include "../h/text.h"#include "../h/mount.h"#include "../h/gnode.h"#include "../h/kernel.h"#include "../h/interlock.h"#include "../machine/pte.h"#include "../machine/cpu.h"#ifdef vax#include "../vax/mtpr.h"#endif vax#include "../h/ipc.h"#include "../h/shm.h"#ifndef V_NOOP#define V_NOOP 0#define V_CACHE 1#endif V_NOOPextern struct sminfo sminfo;extern int extracpu;#ifdef vax/* * Get page tables for process p.  Allocator * for memory is argument; process must be locked * from swapping if vmemall is used; if memall is * used, call will return w/o waiting for memory. * In any case an error return results if no user * page table space is available. */vgetpt(p, pmemall)	register struct proc *p;	int (*pmemall)();{	register long a;	register int i;	extern memall();	int ret;	if (p->p_szpt == 0)		panic("vgetpt");	/*	 * Allocate space in the kernel map for this process.	 * Then allocate page table pages, and initialize the	 * process' p0br and addr pointer to be the kernel	 * virtual addresses of the base of the page tables and	 * the pte for the process pcb (at the base of the u.).	 */	a = rmalloc(kernelmap, (long)p->p_szpt);	if (a == 0)		return (0);	if(pmemall == memall)		ret = (*pmemall)(&Usrptmap[a], p->p_szpt, p, CSYS, NULL,V_NOOP);	else		ret = (*pmemall)(&Usrptmap[a], p->p_szpt, p, CSYS);	if(ret == 0) {		rmfree(kernelmap, (long)p->p_szpt, a);		return (0);	}	p->p_p0br = kmxtob(a);	p->p_addr = uaddr(p);	/*	 * Now validate the system page table entries for the	 * user page table pages, flushing old translations	 * for these kernel virtual addresses.  Clear the new	 * page table pages for clean post-mortems.	 */	vmaccess(&Usrptmap[a], (caddr_t)p->p_p0br, p->p_szpt);	for (i = 0; i < p->p_szpt; i++)		clearseg(Usrptmap[a + i].pg_pfnum);	return (1);}#endif vax/* VGETSMPT - Get page tables for shared memory segment.	*//*	Process must be locked from swapping. In any case	*//*	an error return results if no user page table space is	*//*	available.	SHMEM					*/vgetsmpt(sp)    register struct smem *sp;{	register long a;	register int i;	register int smszpt;		/* in page table pages	*/#ifdef mips	XPRINTF(XPR_SM,"enter vgetsmpt",0,0,0,0);#endif mips	if (sp->sm_size == 0)		panic("vgetsmpt");			/* Allocate space in the kernel map for	*/			/* this shared memory segment. Then	*/			/* allocate page table pages, and	*/			/* initialize the segments' "sm_ptaddr"	*/			/* to be the kernel virtual address of	*/			/* the base of the page table.		*/	smszpt = clrnd(ctopt(btoc(sp->sm_size)));	a = rmalloc(kernelmap, (long)smszpt);	if (a == 0)		return (0);	if (memall(&Usrptmap[a], smszpt, &proc[0], CSYS, NULL, V_NOOP) == 0) {		rmfree(kernelmap, (long)smszpt, a);		return (0);	}	sp->sm_ptaddr = kmxtob(a);			/* Now validate the system page table	*/			/* entries for the user page table	*/			/* pages, flushing old translations for	*/			/* these kernel virtual addresses.	*/			/* Clear the new page table pages for	*/			/* clean post-mortems.			*/	vmaccess(&Usrptmap[a], (caddr_t)sp->sm_ptaddr, smszpt, DO_CACHE);	for (i=0; i < smszpt; i++)		clearseg(Usrptmap[a + i].pg_pfnum);#ifdef mips	XPRINTF(XPR_SM,"vgetsmpt ptaddr 0x%x; #ptpgs %d\n",		sp->sm_ptaddr,smszpt,0,0);#endif	return(1);}#ifdef mips/* * Get data and stack page tables for process p.  Allocator * for memory is argument; process must be locked * from swapping if vmemall is used; if memall is * used, call will return w/o waiting for memory. * In any case an error return results if no user * page table space is available. */vgetpt(p, pmemall, pmemfree)	register struct proc *p;	int (*pmemall)();	int (*pmemfree)();{	register long ad = 0;	register long as = 0;	register int i, ret;#ifdef CACHETRICKS	register struct cmap *c;	register unsigned pf;#endif CACHETRICKSXPRINTF(XPR_VM,"enter vgetpt",0,0,0,0);	/*	 * Allocate space in the kernel map for this process.	 * Then allocate page table pages, and initialize the	 * process' base registers and addr pointers to be the kernel	 * virtual addresses of the base of the page tables and	 * the pte for the process pcb (at the base of the u.).	 */	if (p->p_datapt) {		ad = rmalloc(kernelmap, (long)p->p_datapt);		if (ad == 0)			return (0);		if(pmemall == memall)			ret = (*pmemall)(&Usrptmap[ad], p->p_datapt, p, CSYS, NULL,V_NOOP);		else			ret = (*pmemall)(&Usrptmap[ad], p->p_datapt, p, CSYS);		if(ret == 0) {			rmfree(kernelmap, (long)p->p_datapt, ad);			return (0);		}	}	if (p->p_stakpt) {		as = rmalloc(kernelmap, (long)p->p_stakpt);		if (as == 0) {			if (p->p_datapt) {				(*pmemfree)(&Usrptmap[ad], p->p_datapt);				rmfree(kernelmap, (long)p->p_datapt, ad);			}			return (0);		}		if(pmemall == memall)			ret = (*pmemall)(&Usrptmap[as], p->p_stakpt, p, CSYS, NULL,V_NOOP);		else			ret = (*pmemall)(&Usrptmap[as], p->p_stakpt, p, CSYS);		if(ret == 0) {			if (p->p_datapt) {				(*pmemfree)(&Usrptmap[ad], p->p_datapt);				rmfree(kernelmap, (long)p->p_datapt, ad);			}			rmfree(kernelmap, (long)p->p_stakpt, as);			return (0);		}	}	p->p_databr = kmxtob(ad);	p->p_stakbr = kmxtob(as);	p->p_textbr = 0;	/*	 * Now validate the system page table entries for the	 * user page table pages, flushing old translations	 * for these kernel virtual addresses.  Clear the new	 * page table pages for clean post-mortems.	 */	if (p->p_datapt) {#ifdef mips		vmaccess(&Usrptmap[ad], (caddr_t)p->p_databr, p->p_datapt, DO_CACHE);#else !mips		vmaccess(&Usrptmap[ad], (caddr_t)p->p_databr, p->p_datapt);#endif !mips		for (i = 0; i < p->p_datapt; i++) {#ifdef USE_IDLE			/* don't bother if it's already done */			if (cmap[pgtocm(Usrptmap[ad + i].pg_pfnum)].c_zero) {				extern int v_zero_pt_hits;				v_zero_pt_hits++;				cmap[pgtocm(Usrptmap[ad+i].pg_pfnum)].c_zero=0;			}			else {				extern int v_zero_pt_misses;				v_zero_pt_misses++;				clearseg(Usrptmap[ad + i].pg_pfnum);			}#else			clearseg(Usrptmap[ad + i].pg_pfnum);#endif#ifdef CACHETRICKS			if (Usrptmap[ad + i].pg_n == 0) {				pf = Usrptmap[ad + i].pg_pfnum;				c = &cmap[pgtocm(pf)];				c->c_icachecnt = icachecnt[pf & icachemask];				c->c_dcachecnt = dcachecnt[pf & dcachemask];			}#endif CACHETRICKS		}	}	if (p->p_stakpt) {#ifdef mips		vmaccess(&Usrptmap[as], (caddr_t)p->p_stakbr, p->p_stakpt, DO_CACHE);#else !mips		vmaccess(&Usrptmap[as], (caddr_t)p->p_stakbr, p->p_stakpt);#endif !mips		for (i = 0; i < p->p_stakpt; i++) {#ifdef USE_IDLE			/* don't bother if it's already done */			if (cmap[pgtocm(Usrptmap[as + i].pg_pfnum)].c_zero) {				extern int v_zero_pt_hits;				v_zero_pt_hits++;				cmap[pgtocm(Usrptmap[as+i].pg_pfnum)].c_zero=0;			}			else {				extern int v_zero_pt_misses;				v_zero_pt_misses++;				clearseg(Usrptmap[as + i].pg_pfnum);			}#else			clearseg(Usrptmap[as + i].pg_pfnum);#endif#ifdef CACHETRICKS			if (Usrptmap[as + i].pg_n == 0) {				pf = Usrptmap[as + i].pg_pfnum;				c = &cmap[pgtocm(pf)];				c->c_icachecnt = icachecnt[pf & icachemask];				c->c_dcachecnt = dcachecnt[pf & dcachemask];			}#endif CACHETRICKS		}	}	return (1);}#endif mips/* * Initialize text portion of page table. */vinitpt(p)	struct proc *p;{	register struct text *xp;	register struct proc *q;	register struct pte *pte;	register int i;	struct pte proto;#ifdef mips        register long at = 0;#endif mips#ifdef mips	XPRINTF(XPR_VM,"enter vinitpt",0,0,0,0);#endif mips	xp = p->p_textp;	if (xp == 0)#ifdef vax		return;#endif vax#ifdef mips                return (1);#endif mips	pte = tptopte(p, 0);	/*	 * If there is another instance of same text in core	 * then just copy page tables from other process.	 */	if (q = xp->x_caddr) {#ifdef vax		bcopy((caddr_t)tptopte(q, 0), (caddr_t)pte,		    (unsigned) (sizeof(struct pte) * xp->x_size));#endif vax#ifdef mips                p->p_textbr = q->p_textbr;                p->p_textpt = q->p_textpt;#endif mips		goto done;	}#ifdef mips	/*	 * allocate text page table if it cannot be shared	 */	p->p_textpt = ctopt(xp->x_size);	at = rmalloc(kernelmap, (long)p->p_textpt);	if (at == 0)		return (0);	if (vmemall(&Usrptmap[at], p->p_textpt, p, CSYS) == 0) {		rmfree(kernelmap, (long)p->p_textpt, at);		return (0);	}	p->p_textbr = kmxtob(at);#ifdef mips	vmaccess(&Usrptmap[at], (caddr_t)p->p_textbr, p->p_textpt, DO_CACHE);#else !mips	vmaccess(&Usrptmap[at], (caddr_t)p->p_textbr, p->p_textpt);#endif !mips	for (i=0; i < p->p_textpt; i++) {#ifdef USE_IDLE		/* don't bother if it's already done */		if (cmap[pgtocm(Usrptmap[at+i].pg_pfnum)].c_zero) {			extern int v_zero_pt_hits;			v_zero_pt_hits++;			cmap[pgtocm(Usrptmap[at+i].pg_pfnum)].c_zero=0;		}		else {			extern int v_zero_pt_misses;			v_zero_pt_misses++;			clearseg(Usrptmap[at+i].pg_pfnum);		}#else		clearseg(Usrptmap[at+i].pg_pfnum);#endif USE_IDLE	}	pte = tptopte(p, 0);#endif mips	/*	 * Initialize text page tables, zfod if we are loading	 * the text now; unless the process is demand loaded,	 * this will suffice as the text will henceforth either be	 * read from a file or demand paged in.	 */	*(int *)&proto = PG_URKR;	if (xp->x_flag & XLOAD) {		proto.pg_fod = 1;		((struct fpte *)&proto)->pg_fileno = PG_FZERO;	}	for (i = 0; i < xp->x_size; i++)		*pte++ = proto;	if ((xp->x_flag & XPAGI) == 0)		goto done;	/*	 * Text is demand loaded.  If process is not loaded (i.e. being	 * swapped in) then retrieve page tables from swap area.  Otherwise	 * this is the first time and we must initialize the page tables	 * from the blocks in the file system.	 */	if (xp->x_flag & XLOAD)		vinifod((struct fpte *)tptopte(p, 0), PG_FTEXT, xp->x_gptr,#ifdef vax		    (daddr_t)1, #endif vax#ifdef mips		    (daddr_t)0, #endif mips		    xp->x_size);	else		swap(p, xp->x_ptdaddr, (caddr_t)tptopte(p, 0),		    xp->x_size * sizeof (struct pte), B_READ,		    B_PAGET, swapdev, 0);done:	/*	 * In the case where we are overlaying ourself with new page	 * table entries, old user-space translations should be flushed.

⌨️ 快捷键说明

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