📄 pt_machdep.c
字号:
#ifndef lintstatic char *sccsid = "@(#)pt_machdep.c 4.3 (ULTRIX) 9/6/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 * * 4-Sep-90 dlh * added vector processor support code * * 03-Aug-90 rafiey (Ali Rafieymehr) * Set the pages (u.pages) to modify. * * 19-Jun-90 -- jmartin * Fixes for "panic: vrelvm rssize" * * 05 Mar 90 jaw * IPL level lowered when text lock is released 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/mtpr.h"#include "../machine/cpu.h"#include "../h/ipc.h"#include "../h/shm.h"#include "../h/cpudata.h"#ifdef vax#include "../machine/cpu.h"#include "../../machine/common/cpuconf.h"#include "../machine/vectors.h"#endif vaxextern struct sminfo sminfo;extern int swapfrag;/* * 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, pmemfree) register struct proc *p; int (*pmemall)(); int (*pmemfree)(); /* here for consistency with mips */{ register long a; register int i; 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.). */ if ((a = rmalloc(kernelmap, (long)p->p_szpt)) == 0) return (0); if ((*pmemall)(&Usrptmap[a], p->p_szpt, p, CSYS, NULL, V_NOOP) == 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, 0); blkclr((caddr_t)p->p_p0br, p->p_szpt*NBPG); 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; 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. */ struct pte *qpte = tptopte(q, 0); int s1; /* synchronize with ptexpand() */ s1 = splclock(); smp_lock(&lk_rq,LK_RETRY); if (CURRENT_CPUDATA->cpu_tbi_flag) { mtpr(TBIA,0); CURRENT_CPUDATA->cpu_tbi_flag = 0; } smp_unlock(&lk_rq); splx(s1); blkcpy((caddr_t)qpte, (caddr_t)pte, (unsigned) (sizeof(struct pte) * xp->x_size)); 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); /* * 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)1, 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; ptsize = xp->x_size * sizeof (struct pte); while(ptsize > nfrag){ if(*dp == 0) panic("vinitpt: text pt swap addr 0"); swap(p, *dp++, (caddr_t)tptopte(p, poff), nfrag, B_READ, B_PAGET, swapdev,0); ptsize -= nfrag; poff += nfrag/sizeof(struct pte); } if(*dp == 0) panic("vinitpt: text pt swap addr 0"); swap(p, *dp, (caddr_t)tptopte(p, poff), ptsize, 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. */ if (p == u.u_procp) newptes(p, tptov(p, 0), xp->x_size); else SET_P_VM(p, SPTECHG); if (unlock_flag) { (void)splimp(); smp_lock(&lk_text, LK_RETRY); } return(1);}/* VINITSMPT - Initialize shared memory portion of page table *//* for the given shared memory segment. *//* As a short cut, to get this done in a hurry, I have *//* made shared memory segment page tables wired-down. *//* LeRoy Fundingsland 1/18/85 DEC SHMEM */vinitsmpt(p, sp) register struct proc *p; register struct smem *sp;{ register struct pte *pte, *pte1; register int i, smindex; register int smsize; /* SMS size in clicks */ int s; XPRINTF(XPR_VM,"enter vinitsmpt",0,0,0,0); if(sp == NULL) return; if(p->p_sm == (struct p_sm *) NULL) { panic("vinitsmpt: p_sm"); } for(smindex=0; smindex < sminfo.smseg; smindex++) if(p->p_sm[smindex].sm_p == sp) break; if(smindex >= sminfo.smseg) panic("vinitsmpt"); pte = p->p_p0br + p->p_sm[smindex].sm_saddr; smsize = clrnd(btoc(sp->sm_size)); /* set up process' ptes */ pte1 = sp->sm_ptaddr; for(i=0; i < smsize; i++) *(int *)pte++ = *(int *)pte1++ | (int)p->p_sm[smindex].sm_pflag; /* * In the case where we are overlaying ourself with new page * table entries, old user-space translations must be flushed. */ if (p == u.u_procp) newptes(p, tptov(p,p->p_sm[smindex].sm_saddr), smsize); else SET_P_VM(p, SPTECHG);}#ifndef distpte/* * Update the page tables of all processes linked * to a particular text segment, by distributing * dpte to the the text page at virtual frame v. * * Note that invalidation in the translation buffer for * the current process is the responsibility of the caller. */distpte(xp, tp, dpte) struct text *xp; register size_t tp; register struct pte *dpte;{ register struct proc *p; register struct pte *pte; register int i; int s;#ifdef SMP_DEBUG if (smp_debug) lsert(&lk_text);#endif SMP_DEBUG s = splclock(); smp_lock(&lk_rq,LK_RETRY); if (CURRENT_CPUDATA->cpu_tbi_flag) { mtpr(TBIA,0); CURRENT_CPUDATA->cpu_tbi_flag = 0; } smp_unlock(&lk_rq); splx(s); for (p = xp->x_caddr; p; p = p->p_xlink) { pte = tptopte(p, tp); SET_P_VM(p, SPTECHG); if (pte != dpte) { for (i = 0; i < CLSIZE; i++) pte[i] = dpte[i]; } }}#endif distpte#ifndef distsmpte/* DISTSMPTE - Update the page tables of all processes linked *//* to a particular shared memory segment, by distributing *//* dpte to the the shared memory page at virtual frame smp.*//* *//* Note that invalidation in the translation buffer for *//* the current process is the responsibility of the caller.*//* SHMEM */distsmpte(sp, smp, dpte, cm) register struct smem *sp; size_t smp; register struct pte *dpte; /* Global PTE */ int cm; /* clear pg_m flag */{ register struct pte *pte; register int i, j; register struct proc *p; int s; /* if the SMS is currently not attached */ /* to any process then return. */ if(sp->sm_ccount == 0 || sp->sm_caddr == NULL) return; p = sp->sm_caddr; if(p->p_sm == (struct p_sm *) NULL) { panic("distmpte: p_sm1"); } for(i=0; i < sminfo.smseg; i++) if(p->p_sm[i].sm_p == sp) break; if(i >= sminfo.smseg) panic("distsmpte"); /* if requested, clear pg_m bit in global PTE */ if (cm == PG_CLEARM) { dpte->pg_m = 0; distcl(dpte); } while(p){ int unlock_text; unlock_text = 0; if (smp_owner(&lk_text) == LK_FALSE) { smp_lock(&lk_text, LK_RETRY); ++unlock_text; } pte = p->p_p0br + p->p_sm[i].sm_saddr+smp; /* synchronize with ptexpand() */ s = splclock(); smp_lock(&lk_rq,LK_RETRY); if (CURRENT_CPUDATA->cpu_tbi_flag) { mtpr(TBIA,0); CURRENT_CPUDATA->cpu_tbi_flag = 0; } smp_unlock(&lk_rq); splx(s); /* this panic should eventually go away */ if (pte->pg_v && dpte->pg_fod) { panic("distsmpte: PG_V && PG_FOD"); } SET_P_VM(p, SPTECHG); /* CAREFUL: I'm incrementing 'pte' */ for (j=0; j < CLSIZE; j++, pte++) { *(int *) pte &= PG_PROT|PG_M; *(int *) pte |= (*(int *)(dpte+j)) & ~(PG_PROT|PG_M); if (cm == PG_CLEARM) pte->pg_m = 0; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -