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:
parent
c6bf93b06b
commit
ba43a19831
|
@ -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));
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue