📄 pt_machdep.c
字号:
#ifndef lintstatic char *sccsid = "@(#)pt_machdep.c 4.1 (ULTRIX) 7/2/90";#endif lint/*********************************************************************** * * * Copyright (c) 1984, 1986, 1988 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 * * 19-Jun-90 -- jmartin * Fixes for "panic: vrelvm rssize" * * 05 Mar 90 jaw * IPL level lowered when text lock is released in vinitpt. * * 06 Feb 90 gmm * Get lk_text if vinitpt() returns with value 0. The calling routine * expects lk_text to be held on return. * * 11 Dec 89 jaa * fixed mips to round from clicks to pt's in vinitpt * * 24 Jul 89 -- jmartin * Don't call swapout; just ask the swapper and sleep. * * 06-Jun-89 -- jaa * Creation date * split machdep routines from ../vm_pt.c */#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 "../machine/pte.h"#include "../machine/cpu.h"#include "../h/ipc.h"#include "../h/shm.h"#include "../h/cpudata.h"extern struct sminfo sminfo;extern int swapfrag;/* * 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, s, takelock; extern int memfree();#ifdef CACHETRICKS register struct cmap *c; register unsigned pf;#endif CACHETRICKSXPRINTF(XPR_VM,"enter vgetpt",0,0,0,0); /* * Must take MP lock for memfree during error path frees. */ takelock = (pmemfree == memfree); /* * 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) { if ((ad = rmalloc(kernelmap, (long)p->p_datapt)) == 0) return (0); if ((*pmemall)(&Usrptmap[ad], p->p_datapt, p, CSYS, NULL, V_NOOP) == 0) { rmfree(kernelmap, (long)p->p_datapt, ad); return (0); } } if (p->p_stakpt) { if ((as = rmalloc(kernelmap, (long)p->p_stakpt)) == 0) { if (p->p_datapt) { if (takelock) { s = splimp(); smp_lock(&lk_cmap, LK_RETRY); } (*pmemfree)(&Usrptmap[ad], p->p_datapt); if (takelock) { smp_unlock(&lk_cmap); (void) splx(s); } rmfree(kernelmap, (long)p->p_datapt, ad); } return (0); } if ((*pmemall)(&Usrptmap[as], p->p_stakpt, p, CSYS, NULL, V_NOOP) == 0) { if (p->p_datapt) { if (takelock) { s = splimp(); smp_lock(&lk_cmap, LK_RETRY); } (*pmemfree)(&Usrptmap[ad], p->p_datapt); if (takelock) { smp_unlock(&lk_cmap); (void) splx(s); } 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) { vmaccess(&Usrptmap[ad], (caddr_t)p->p_databr, p->p_datapt, DO_CACHE); 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) { vmaccess(&Usrptmap[as], (caddr_t)p->p_stakbr, p->p_stakpt, DO_CACHE); 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);}/* * Initialize text portion of page table. */vinitpt(p,s) struct proc *p; int s;{ register struct text *xp; register struct proc *q; register struct pte *pte; register int i; struct pte proto; unsigned unlock_flag = NULL; register long at = 0; XPRINTF(XPR_VM,"enter vinitpt",0,0,0,0); xp = p->p_textp; if (xp == 0) return (1); pte = tptopte(p, 0); if (q = xp->x_caddr) { /* * If there is another instance of same text in core * then just copy page tables from other process. * * This operation can be thought of as a large "distpte", so * we lock it under the same protocol as we lock "distpte". * We don't give up the lock until the process is linked to * the text chain (see xlink(p) in sys/vm_text.c), so that * real "distpte"s will see this process. */ p->p_textbr = q->p_textbr; p->p_textpt = q->p_textpt; goto done; } /* * OK to give up the spin lock, as we are the one and only * process using this text and have excluded others by * maintaining ((xp->x_flag & X_LOCK) == 1). */ unlock_flag = !NULL; smp_unlock(&lk_text); splx(s); /* * allocate text page table if it cannot be shared */ p->p_textpt = clrnd(ctopt(xp->x_size)); at = rmalloc(kernelmap, (long)p->p_textpt); if (at == 0){ (void)splimp(); smp_lock(&lk_text, LK_RETRY); return (0); } if (vmemall(&Usrptmap[at], p->p_textpt, p, CSYS, NULL, V_NOOP) == 0) { rmfree(kernelmap, (long)p->p_textpt, at); (void)splimp(); smp_lock(&lk_text, LK_RETRY); return (0); } p->p_textbr = kmxtob(at); vmaccess(&Usrptmap[at], (caddr_t)p->p_textbr, p->p_textpt, DO_CACHE); 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); /* * 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 || xp->x_flag & XNOSPCE) { 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 || xp->x_flag & XNOSPCE){ vinifod((struct fpte *)tptopte(p, 0), PG_FTEXT, xp->x_gptr, (daddr_t)0, xp->x_size); xp->x_flag &= ~XNOSPCE; /* clear the XNOSPCE flag setin xccdec*/ } else { register int *dp, poff, ptsize,nfrag; dp = xp->x_dmap->dm_ptdaddr; nfrag = dtob(swapfrag); poff = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -