3-level MMU changes: software MMU data structures now display a VM model

consisting of `regions', `segments' and `page maps'.
This commit is contained in:
pk 1995-04-13 13:48:46 +00:00
parent c6bf93b06b
commit ba43a19831
2 changed files with 82 additions and 30 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.h,v 1.14 1995/04/10 12:42:23 mycroft Exp $ */
/* $NetBSD: pmap.h,v 1.15 1995/04/13 13:48:54 pk Exp $ */
/*
* Copyright (c) 1992, 1993
@ -103,8 +103,10 @@
* have no software copies. Its mmu entries are nonetheless kept on lists
* so that the code that fiddles with mmu lists has something to fiddle.
*/
#define NKSEG ((int)((-(unsigned)KERNBASE) / NBPSG)) /* i.e., 512 */
#define NUSEG (4096 - NKSEG) /* i.e., 3584 */
#define NKREG ((int)((-(unsigned)KERNBASE) / NBPRG)) /* i.e., 8 */
#define NUREG (256 - NKREG) /* i.e., 248 */
TAILQ_HEAD(mmuhd,mmuentry);
/* data appearing in both user and kernel pmaps */
struct pmap {
@ -114,29 +116,29 @@ struct pmap {
simple_lock_data_t pm_lock; /* spinlock */
#endif
int pm_refcount; /* just what it says */
struct mmuentry *pm_mmuforw; /* pmap pmeg chain */
struct mmuentry **pm_mmuback; /* (two way street) */
void *pm_segstore;
pmeg_t *pm_segmap; /* points to pm_rsegmap per above */
u_char *pm_npte; /* points to pm_rnpte */
int **pm_pte; /* points to pm_rpte */
int pm_gap_start; /* Starting with this vseg there's */
int pm_gap_end; /* no valid mapping until here */
#ifdef MMU_3L
struct mmuhd pm_reglist; /* MMU regions on this pmap */
#endif
struct mmuhd pm_seglist; /* MMU segments on this pmap */
void *pm_regstore;
struct regmap *pm_regmap;
int pm_gap_start; /* Starting with this vreg there's */
int pm_gap_end; /* no valid mapping until here */
struct pmap_statistics pm_stats; /* pmap statistics */
};
/* data appearing only in user pmaps */
struct usegmap {
pmeg_t us_segmap[NUSEG]; /* segment map */
u_char us_npte[NUSEG]; /* number of valid PTEs per seg */
int *us_pte[NUSEG]; /* points to PTEs for valid segments */
struct regmap {
struct segmap *rg_segmap; /* point to NSGPRG PMEGs */
smeg_t rg_smeg; /* the MMU region number */
u_char rg_nsegmap; /* number of valid PMEGS */
};
/* data appearing only in the kernel pmap */
struct ksegmap {
pmeg_t ks_segmap[NKSEG]; /* segment map */
u_char ks_npte[NKSEG]; /* number of valid PTEs per kseg */
int *ks_pte[NKSEG]; /* always NULL */
struct segmap {
int *sg_pte; /* points to NPTESG PTEs */
pmeg_t sg_pmeg; /* the MMU segment number */
u_char sg_npte; /* number of valid PTEs per seg */
};
typedef struct pmap *pmap_t;
@ -146,7 +148,6 @@ typedef struct pmap *pmap_t;
#define PMAP_NULL ((pmap_t)0)
extern struct pmap kernel_pmap_store;
extern struct ksegmap kernel_segmap_store;
extern vm_offset_t vm_first_phys, vm_num_phys;
/*
@ -164,7 +165,7 @@ extern vm_offset_t vm_first_phys, vm_num_phys;
#define PMAP_NC 4 /* tells pmap_enter to set PG_NC */
#define PMAP_TNC 7 /* mask to get PG_TYPE & PG_NC */
void pmap_bootstrap __P((int nmmu, int nctx));
void pmap_bootstrap __P((int nmmu, int nctx, int nregion));
int pmap_count_ptes __P((struct pmap *));
vm_offset_t pmap_prefer __P((vm_offset_t, vm_offset_t));
int pmap_pa_exists __P((vm_offset_t));

View File

@ -1,4 +1,4 @@
/* $NetBSD: pte.h,v 1.7 1994/11/20 20:53:26 deraadt Exp $ */
/* $NetBSD: pte.h,v 1.8 1995/04/13 13:48:46 pk Exp $ */
/*
* Copyright (c) 1992, 1993
@ -56,23 +56,40 @@
* 64 (sun4c) PTEs.
*/
typedef u_short pmeg_t; /* 9 bits needed per Sun-4 segmap entry */
/*
* Region maps contain `smeg' (Segment Entry Group) numbers.
* An SMEG is simply an index that names a group of 64 PMEGs
*/
typedef u_char smeg_t; /* 6 bits needed per Sun-4 regmap entry */
#endif
/*
* Address translation works as follows:
*
* (for sun4c and 2-level sun4)
* 1. test va<31:29> -- these must be 000 or 111 (or you get a fault)
* 2. concatenate context_reg<2:0> and va<29:18> to get a 15 bit number;
* use this to index the segment maps, yeilding a 7 or 9 bit value.
* use this to index the segment maps, yielding a 7 or 9 bit value.
* (for 3-level sun4)
* 1. concatenate context_reg<3:0> and va<31:24> to get a 8 bit number;
* use this to index the region maps, yielding a 10 bit value.
* 2. take the value from (1) above and concatenate va<17:12> to
* get a `segment map entry' index. This gives a 9 bit value.
* (for sun4c)
* 3. take the value from (2) above and concatenate va<17:12> to
* get a `page map entry' index. This gives a 32-bit PTE.
* (for sun4)
* 3. take the value from (2) above and concatenate va<17:13> to
* 3. take the value from (2 or 3) above and concatenate va<17:13> to
* get a `page map entry' index. This gives a 32-bit PTE.
*
* In other words:
*
* struct sun4_3_levelmmu_virtual_addr {
* u_int va_reg:8, (virtual region)
* va_seg:6, (virtual segment)
* va_pg:5, (virtual page within segment)
* va_off:13; (offset within page)
* };
* struct sun4_virtual_addr {
* u_int :2, (required to be the same as bit 29)
* va_seg:12, (virtual segment)
@ -88,12 +105,17 @@ typedef u_short pmeg_t; /* 9 bits needed per Sun-4 segmap entry */
*
* Then, given any `va':
*
* extern smeg_t regmap[16][1<<8]; (3-level MMU only)
* extern pmeg_t segmap[8][1<<12]; ([16][1<<12] for sun4)
* extern int ptetable[128][1<<6]; ([512][1<<5] for sun4)
*
* (the above being in the hardware, accessed as Alternate Address Spaces)
*
* physseg = segmap[curr_ctx][va.va_seg];
* if (mmu_3l)
* physreg = regmap[curr_ctx][va.va_reg];
* physseg = segmap[physreg][va.va_seg];
* else
* physseg = segmap[curr_ctx][va.va_seg];
* pte = ptetable[physseg][va.va_pg];
* if (!(pte & PG_V)) TRAP();
* if (writing && !pte.pg_w) TRAP();
@ -105,6 +127,19 @@ typedef u_short pmeg_t; /* 9 bits needed per Sun-4 segmap entry */
* physadr = ((pte & PG_PFNUM) << PGSHIFT) | va.va_off;
*/
#if defined(MMU_3L) && !defined(SUN4)
#error "configuration error"
#endif
#if defined(MMU_3L)
extern int mmu_3l;
#endif
#define NBPRG (1 << 24) /* bytes per segment */
#define RGSHIFT 24 /* log2(NBPSG) */
#define RGOFSET (NBPRG - 1) /* mask for segment offset */
#define NSEGRG (NBPRG / NBPSG) /* segments per region */
#define NBPSG (1 << 18) /* bytes per segment */
#define SGSHIFT 18 /* log2(NBPSG) */
#define SGOFSET (NBPSG - 1) /* mask for segment offset */
@ -117,18 +152,34 @@ extern int nptesg;
#define NPTESG (NBPSG / NBPG)
#endif
/* virtual address to virtual region number */
#define VA_VREG(va) (((unsigned int)(va) >> RGSHIFT) & 255)
/* virtual address to virtual segment number */
#define VA_VSEG(va) (((int)(va) >> SGSHIFT) & 0xfff)
#define VA_VSEG(va) (((unsigned int)(va) >> SGSHIFT) & 63)
/* virtual address to virtual page number, for Sun-4 and Sun-4c */
#define VA_SUN4_VPG(va) (((int)(va) >> 13) & 31)
#define VA_SUN4C_VPG(va) (((int)(va) >> 12) & 63)
/* truncate virtual address to region base */
#define VA_ROUNDDOWNTOREG(va) ((int)(va) & ~RGOFSET)
/* truncate virtual address to segment base */
#define VA_ROUNDDOWNTOSEG(va) ((int)(va) & ~SGOFSET)
/* virtual segment to virtual address (must sign extend!) */
#define VSTOVA(vseg) (((int)(vseg) << 20) >> 2)
/* virtual segment to virtual address (must sign extend on holy MMUs!) */
#if defined(MMU_3L)
#define VRTOVA(vr) (mmu_3l \
? ((int)(vr) << RGSHIFT) \
: (((int)(vr) << (RGSHIFT+2)) >> 2))
#define VSTOVA(vr,vs) (mmu_3l \
? (((int)vr << RGSHIFT) + ((int)vs << SGSHIFT)) \
: ((((int)vr << (RGSHIFT+2)) >> 2) + ((int)vs << SGSHIFT)))
#else
#define VRTOVA(vr) (((int)vr << (RGSHIFT+2)) >> 2)
#define VSTOVA(vr,vs) ((((int)vr << (RGSHIFT+2)) >> 2) + ((int)vs << SGSHIFT))
#endif
#if defined(SUN4) && defined(SUN4C)
#define VA_VPG(va) (cputyp==CPU_SUN4C ? VA_SUN4C_VPG(va) : VA_SUN4_VPG(va))