📄 vm_pt.c
字号:
#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 + -