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
|
* Copyright (c) 1992, 1993
|
||||||
@ -103,8 +103,10 @@
|
|||||||
* have no software copies. Its mmu entries are nonetheless kept on lists
|
* 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.
|
* so that the code that fiddles with mmu lists has something to fiddle.
|
||||||
*/
|
*/
|
||||||
#define NKSEG ((int)((-(unsigned)KERNBASE) / NBPSG)) /* i.e., 512 */
|
#define NKREG ((int)((-(unsigned)KERNBASE) / NBPRG)) /* i.e., 8 */
|
||||||
#define NUSEG (4096 - NKSEG) /* i.e., 3584 */
|
#define NUREG (256 - NKREG) /* i.e., 248 */
|
||||||
|
|
||||||
|
TAILQ_HEAD(mmuhd,mmuentry);
|
||||||
|
|
||||||
/* data appearing in both user and kernel pmaps */
|
/* data appearing in both user and kernel pmaps */
|
||||||
struct pmap {
|
struct pmap {
|
||||||
@ -114,29 +116,29 @@ struct pmap {
|
|||||||
simple_lock_data_t pm_lock; /* spinlock */
|
simple_lock_data_t pm_lock; /* spinlock */
|
||||||
#endif
|
#endif
|
||||||
int pm_refcount; /* just what it says */
|
int pm_refcount; /* just what it says */
|
||||||
struct mmuentry *pm_mmuforw; /* pmap pmeg chain */
|
|
||||||
struct mmuentry **pm_mmuback; /* (two way street) */
|
#ifdef MMU_3L
|
||||||
void *pm_segstore;
|
struct mmuhd pm_reglist; /* MMU regions on this pmap */
|
||||||
pmeg_t *pm_segmap; /* points to pm_rsegmap per above */
|
#endif
|
||||||
u_char *pm_npte; /* points to pm_rnpte */
|
struct mmuhd pm_seglist; /* MMU segments on this pmap */
|
||||||
int **pm_pte; /* points to pm_rpte */
|
void *pm_regstore;
|
||||||
int pm_gap_start; /* Starting with this vseg there's */
|
struct regmap *pm_regmap;
|
||||||
int pm_gap_end; /* no valid mapping until here */
|
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 */
|
struct pmap_statistics pm_stats; /* pmap statistics */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* data appearing only in user pmaps */
|
struct regmap {
|
||||||
struct usegmap {
|
struct segmap *rg_segmap; /* point to NSGPRG PMEGs */
|
||||||
pmeg_t us_segmap[NUSEG]; /* segment map */
|
smeg_t rg_smeg; /* the MMU region number */
|
||||||
u_char us_npte[NUSEG]; /* number of valid PTEs per seg */
|
u_char rg_nsegmap; /* number of valid PMEGS */
|
||||||
int *us_pte[NUSEG]; /* points to PTEs for valid segments */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* data appearing only in the kernel pmap */
|
struct segmap {
|
||||||
struct ksegmap {
|
int *sg_pte; /* points to NPTESG PTEs */
|
||||||
pmeg_t ks_segmap[NKSEG]; /* segment map */
|
pmeg_t sg_pmeg; /* the MMU segment number */
|
||||||
u_char ks_npte[NKSEG]; /* number of valid PTEs per kseg */
|
u_char sg_npte; /* number of valid PTEs per seg */
|
||||||
int *ks_pte[NKSEG]; /* always NULL */
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct pmap *pmap_t;
|
typedef struct pmap *pmap_t;
|
||||||
@ -146,7 +148,6 @@ typedef struct pmap *pmap_t;
|
|||||||
#define PMAP_NULL ((pmap_t)0)
|
#define PMAP_NULL ((pmap_t)0)
|
||||||
|
|
||||||
extern struct pmap kernel_pmap_store;
|
extern struct pmap kernel_pmap_store;
|
||||||
extern struct ksegmap kernel_segmap_store;
|
|
||||||
extern vm_offset_t vm_first_phys, vm_num_phys;
|
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_NC 4 /* tells pmap_enter to set PG_NC */
|
||||||
#define PMAP_TNC 7 /* mask to get PG_TYPE & 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 *));
|
int pmap_count_ptes __P((struct pmap *));
|
||||||
vm_offset_t pmap_prefer __P((vm_offset_t, vm_offset_t));
|
vm_offset_t pmap_prefer __P((vm_offset_t, vm_offset_t));
|
||||||
int pmap_pa_exists __P((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
|
* Copyright (c) 1992, 1993
|
||||||
@ -56,23 +56,40 @@
|
|||||||
* 64 (sun4c) PTEs.
|
* 64 (sun4c) PTEs.
|
||||||
*/
|
*/
|
||||||
typedef u_short pmeg_t; /* 9 bits needed per Sun-4 segmap entry */
|
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
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Address translation works as follows:
|
* 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)
|
* 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;
|
* 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)
|
* (for sun4c)
|
||||||
* 3. take the value from (2) above and concatenate va<17:12> to
|
* 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.
|
* get a `page map entry' index. This gives a 32-bit PTE.
|
||||||
* (for sun4)
|
* (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.
|
* get a `page map entry' index. This gives a 32-bit PTE.
|
||||||
*
|
*
|
||||||
* In other words:
|
* 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 {
|
* struct sun4_virtual_addr {
|
||||||
* u_int :2, (required to be the same as bit 29)
|
* u_int :2, (required to be the same as bit 29)
|
||||||
* va_seg:12, (virtual segment)
|
* 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':
|
* 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 pmeg_t segmap[8][1<<12]; ([16][1<<12] for sun4)
|
||||||
* extern int ptetable[128][1<<6]; ([512][1<<5] for sun4)
|
* extern int ptetable[128][1<<6]; ([512][1<<5] for sun4)
|
||||||
*
|
*
|
||||||
* (the above being in the hardware, accessed as Alternate Address Spaces)
|
* (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];
|
* pte = ptetable[physseg][va.va_pg];
|
||||||
* if (!(pte & PG_V)) TRAP();
|
* if (!(pte & PG_V)) TRAP();
|
||||||
* if (writing && !pte.pg_w) 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;
|
* 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 NBPSG (1 << 18) /* bytes per segment */
|
||||||
#define SGSHIFT 18 /* log2(NBPSG) */
|
#define SGSHIFT 18 /* log2(NBPSG) */
|
||||||
#define SGOFSET (NBPSG - 1) /* mask for segment offset */
|
#define SGOFSET (NBPSG - 1) /* mask for segment offset */
|
||||||
@ -117,18 +152,34 @@ extern int nptesg;
|
|||||||
#define NPTESG (NBPSG / NBPG)
|
#define NPTESG (NBPSG / NBPG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* virtual address to virtual region number */
|
||||||
|
#define VA_VREG(va) (((unsigned int)(va) >> RGSHIFT) & 255)
|
||||||
|
|
||||||
/* virtual address to virtual segment number */
|
/* 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 */
|
/* virtual address to virtual page number, for Sun-4 and Sun-4c */
|
||||||
#define VA_SUN4_VPG(va) (((int)(va) >> 13) & 31)
|
#define VA_SUN4_VPG(va) (((int)(va) >> 13) & 31)
|
||||||
#define VA_SUN4C_VPG(va) (((int)(va) >> 12) & 63)
|
#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 */
|
/* truncate virtual address to segment base */
|
||||||
#define VA_ROUNDDOWNTOSEG(va) ((int)(va) & ~SGOFSET)
|
#define VA_ROUNDDOWNTOSEG(va) ((int)(va) & ~SGOFSET)
|
||||||
|
|
||||||
/* virtual segment to virtual address (must sign extend!) */
|
/* virtual segment to virtual address (must sign extend on holy MMUs!) */
|
||||||
#define VSTOVA(vseg) (((int)(vseg) << 20) >> 2)
|
#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)
|
#if defined(SUN4) && defined(SUN4C)
|
||||||
#define VA_VPG(va) (cputyp==CPU_SUN4C ? VA_SUN4C_VPG(va) : VA_SUN4_VPG(va))
|
#define VA_VPG(va) (cputyp==CPU_SUN4C ? VA_SUN4C_VPG(va) : VA_SUN4_VPG(va))
|
||||||
|
Loading…
Reference in New Issue
Block a user