Increase the efficiency of pmap_l{2,3}pte() somewhat, by allowing the

caller to pass an optional 3rd argument, which is the previous level
PTE corresponding the virtual address.  If this argument is non-NULL,
the table walk otherwise necessary will be bypassed.
This commit is contained in:
thorpej 1998-04-27 19:07:03 +00:00
parent a53c1863fe
commit 30188853dc
2 changed files with 70 additions and 53 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.c,v 1.31 1998/04/15 00:46:57 mjacob Exp $ */
/* $NetBSD: pmap.c,v 1.32 1998/04/27 19:07:03 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -161,7 +161,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.31 1998/04/15 00:46:57 mjacob Exp $");
__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.32 1998/04/27 19:07:03 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -611,17 +611,21 @@ do { \
#ifdef DEBUG
#define PMAP_KERNEL_PTE(va) \
({ \
if (pmap_pte_v(pmap_l1pte(pmap_kernel(), va)) == 0) { \
pt_entry_t *l1pte_, *l2pte_; \
\
l1pte_ = pmap_l1pte(pmap_kernel(), va); \
if (pmap_pte_v(l1pte_) == 0) { \
printf("kernel level 1 PTE not valid, va 0x%lx " \
"(line %ld)\n", (va), __LINE__); \
panic("PMAP_KERNEL_PTE"); \
} \
if (pmap_pte_v(pmap_l2pte(pmap_kernel(), va)) == 0) { \
l2pte_ = pmap_l2pte(pmap_kernel(), va, l1pte_); \
if (pmap_pte_v(l2pte_) == 0) { \
printf("kernel level 2 PTE not valid, va 0x%lx " \
"(line %ld)\n", (va), __LINE__); \
panic("PMAP_KERNEL_PTE"); \
} \
pmap_l3pte(pmap_kernel(), va); \
pmap_l3pte(pmap_kernel(), va, l2pte_); \
})
#else
#define PMAP_KERNEL_PTE(va) (&VPT[VPT_INDEX((va))])
@ -1153,7 +1157,7 @@ pmap_remove(pmap, sva, eva)
register pmap_t pmap;
register vm_offset_t sva, eva;
{
register pt_entry_t *pte;
register pt_entry_t *l1pte, *l2pte, *l3pte;
#ifdef DEBUG
if (pmapdebug & (PDB_FOLLOW|PDB_REMOVE|PDB_PROTECT))
@ -1171,7 +1175,8 @@ pmap_remove(pmap, sva, eva)
/*
* If level 1 mapping is invalid, just skip it.
*/
if (pmap_pte_v(pmap_l1pte(pmap, sva)) == 0) {
l1pte = pmap_l1pte(pmap, sva);
if (pmap_pte_v(l1pte) == 0) {
sva = alpha_trunc_l1seg(sva) + ALPHA_L1SEG_SIZE;
continue;
}
@ -1179,7 +1184,8 @@ pmap_remove(pmap, sva, eva)
/*
* If level 2 mapping is invalid, just skip it.
*/
if (pmap_pte_v(pmap_l2pte(pmap, sva)) == 0) {
l2pte = pmap_l2pte(pmap, sva, l1pte);
if (pmap_pte_v(l2pte) == 0) {
sva = alpha_trunc_l2seg(sva) + ALPHA_L2SEG_SIZE;
continue;
}
@ -1187,9 +1193,9 @@ pmap_remove(pmap, sva, eva)
/*
* Invalidate the mapping if it's valid.
*/
pte = pmap_l3pte(pmap, sva);
if (pmap_pte_v(pte))
pmap_remove_mapping(pmap, sva, pte);
l3pte = pmap_l3pte(pmap, sva, l2pte);
if (pmap_pte_v(l3pte))
pmap_remove_mapping(pmap, sva, l3pte);
sva += PAGE_SIZE;
}
}
@ -1264,9 +1270,9 @@ pmap_page_protect(pa, prot)
nextpv = LIST_NEXT(pv, pv_list);
pte = pmap_l3pte(pv->pv_pmap, pv->pv_va);
pte = pmap_l3pte(pv->pv_pmap, pv->pv_va, NULL);
#ifdef DEBUG
if (pmap_pte_v(pmap_l2pte(pv->pv_pmap, pv->pv_va)) == 0 ||
if (pmap_pte_v(pmap_l2pte(pv->pv_pmap, pv->pv_va, NULL)) == 0 ||
pmap_pte_pa(pte) != pa)
panic("pmap_page_protect: bad mapping");
#endif
@ -1301,7 +1307,7 @@ pmap_protect(pmap, sva, eva, prot)
register vm_offset_t sva, eva;
vm_prot_t prot;
{
register pt_entry_t *pte, bits;
register pt_entry_t *l1pte, *l2pte, *l3pte, bits;
boolean_t isactive;
boolean_t hadasm;
@ -1333,7 +1339,8 @@ pmap_protect(pmap, sva, eva, prot)
/*
* If level 1 mapping is invalid, just skip it.
*/
if (pmap_pte_v(pmap_l1pte(pmap, sva)) == 0) {
l1pte = pmap_l1pte(pmap, sva);
if (pmap_pte_v(l1pte) == 0) {
sva = alpha_trunc_l1seg(sva) + ALPHA_L1SEG_SIZE;
continue;
}
@ -1341,7 +1348,8 @@ pmap_protect(pmap, sva, eva, prot)
/*
* If level 2 mapping is invalid, just skip it.
*/
if (pmap_pte_v(pmap_l2pte(pmap, sva)) == 0) {
l2pte = pmap_l2pte(pmap, sva, l1pte);
if (pmap_pte_v(l2pte) == 0) {
sva = alpha_trunc_l2seg(sva) + ALPHA_L2SEG_SIZE;
continue;
}
@ -1350,10 +1358,10 @@ pmap_protect(pmap, sva, eva, prot)
* Change protection on mapping if it is valid and doesn't
* already have the correct protection.
*/
pte = pmap_l3pte(pmap, sva);
if (pmap_pte_v(pte) && pmap_pte_prot_chg(pte, bits)) {
hadasm = (pmap_pte_asm(pte) != 0);
pmap_pte_set_prot(pte, bits);
l3pte = pmap_l3pte(pmap, sva, l2pte);
if (pmap_pte_v(l3pte) && pmap_pte_prot_chg(l3pte, bits)) {
hadasm = (pmap_pte_asm(l3pte) != 0);
pmap_pte_set_prot(l3pte, bits);
PMAP_INVALIDATE_TLB(pmap, sva, hadasm, isactive,
(prot & VM_PROT_EXECUTE) != 0);
#ifdef PMAPSTATS
@ -1361,7 +1369,7 @@ pmap_protect(pmap, sva, eva, prot)
#endif
}
#ifdef PMAPSTATS
else if (pmap_pte_v(pte)) {
else if (pmap_pte_v(l3pte)) {
if (isro)
protect_stats.alreadyro++;
else
@ -1470,7 +1478,7 @@ pmap_enter(pmap, va, pa, prot, wired)
* A reference will be added to the level 3 table when
* the mapping is validated.
*/
l2pte = pmap_l2pte(pmap, va);
l2pte = pmap_l2pte(pmap, va, l1pte);
if (pmap_pte_v(l2pte) == 0) {
pmap_alloc_ptpage(pmap, l2pte);
pmap_ptpage_addref(l2pte);
@ -1485,7 +1493,7 @@ pmap_enter(pmap, va, pa, prot, wired)
/*
* Get the PTE that will map the page.
*/
pte = pmap_l3pte(pmap, va);
pte = pmap_l3pte(pmap, va, l2pte);
}
/*
@ -1769,14 +1777,14 @@ pmap_change_wiring(pmap, va, wired)
if (pmap == NULL)
return;
pte = pmap_l3pte(pmap, va);
pte = pmap_l3pte(pmap, va, NULL);
#ifdef DEBUG
/*
* Page table page is not allocated.
* Should this ever happen? Ignore it for now,
* we don't want to force allocation of unnecessary PTE pages.
*/
if (pmap_pte_v(pmap_l2pte(pmap, va)) == 0) {
if (pmap_pte_v(pmap_l2pte(pmap, va, NULL)) == 0) {
if (pmapdebug & PDB_PARANOIA)
printf("pmap_change_wiring: invalid STE for %lx\n", va);
return;
@ -1815,7 +1823,7 @@ pmap_extract(pmap, va)
register pmap_t pmap;
vm_offset_t va;
{
pt_entry_t *pte;
pt_entry_t *l1pte, *l2pte, *l3pte;
register vm_offset_t pa;
#ifdef DEBUG
@ -1824,16 +1832,19 @@ pmap_extract(pmap, va)
#endif
pa = 0;
if (pmap_pte_v(pmap_l1pte(pmap, va)) == 0)
goto out;
if (pmap_pte_v(pmap_l2pte(pmap, va)) == 0)
l1pte = pmap_l1pte(pmap, va);
if (pmap_pte_v(l1pte) == 0)
goto out;
pte = pmap_l3pte(pmap, va);
if (pmap_pte_v(pte) == 0)
l2pte = pmap_l2pte(pmap, va, l1pte);
if (pmap_pte_v(l2pte) == 0)
goto out;
pa = pmap_pte_pa(pte) | (va & PGOFSET);
l3pte = pmap_l3pte(pmap, va, l2pte);
if (pmap_pte_v(l3pte) == 0)
goto out;
pa = pmap_pte_pa(l3pte) | (va & PGOFSET);
out:
#ifdef DEBUG
@ -2333,7 +2344,7 @@ pmap_remove_mapping(pmap, va, pte)
* PTE not provided, compute it from pmap and va.
*/
if (pte == PT_ENTRY_NULL) {
pte = pmap_l3pte(pmap, va);
pte = pmap_l3pte(pmap, va, NULL);
if (pmap_pte_v(pte) == 0)
return;
}
@ -2371,7 +2382,7 @@ pmap_remove_mapping(pmap, va, pte)
pt_entry_t *l1pte, *l2pte;
l1pte = pmap_l1pte(pmap, va);
l2pte = pmap_l2pte(pmap, va);
l2pte = pmap_l2pte(pmap, va, l1pte);
/*
* Delete the reference on the level 3 table.
@ -2510,7 +2521,7 @@ pmap_changebit(pa, bit, setem)
#endif
}
pte = pmap_l3pte(pv->pv_pmap, va);
pte = pmap_l3pte(pv->pv_pmap, va, NULL);
if (setem)
npte = *pte | bit;
else
@ -2575,7 +2586,7 @@ pmap_emulate_reference(p, v, user, write)
if (p->p_vmspace == NULL)
panic("pmap_emulate_reference: bad p_vmspace");
#endif
pte = pmap_l3pte(p->p_vmspace->vm_map.pmap, v);
pte = pmap_l3pte(p->p_vmspace->vm_map.pmap, v, NULL);
}
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: pmap.h,v 1.14 1998/04/15 21:42:24 mjacob Exp $ */
/* $NetBSD: pmap.h,v 1.15 1998/04/27 19:07:03 thorpej Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@ -215,42 +215,48 @@ do { \
#define pmap_pte_prot_chg(pte, np) ((np) ^ pmap_pte_prot(pte))
static __inline pt_entry_t *pmap_l2pte __P((pmap_t, vm_offset_t));
static __inline pt_entry_t *pmap_l3pte __P((pmap_t, vm_offset_t));
static __inline pt_entry_t *pmap_l2pte __P((pmap_t, vm_offset_t, pt_entry_t *));
static __inline pt_entry_t *pmap_l3pte __P((pmap_t, vm_offset_t, pt_entry_t *));
#define pmap_l1pte(pmap, v) \
(&(pmap)->pm_lev1map[l1pte_index((vm_offset_t)(v))])
static __inline pt_entry_t *
pmap_l2pte(pmap, v)
pmap_l2pte(pmap, v, l1pte)
pmap_t pmap;
vm_offset_t v;
pt_entry_t *l1pte;
{
pt_entry_t *l1pte, *lev2map;
pt_entry_t *lev2map;
l1pte = pmap_l1pte(pmap, v);
if (pmap_pte_v(l1pte) == 0)
return (NULL);
if (l1pte == NULL) {
l1pte = pmap_l1pte(pmap, v);
if (pmap_pte_v(l1pte) == 0)
return (NULL);
}
lev2map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte));
return (&lev2map[l2pte_index(v)]);
}
static __inline pt_entry_t *
pmap_l3pte(pmap, v)
pmap_l3pte(pmap, v, l2pte)
pmap_t pmap;
vm_offset_t v;
pt_entry_t *l2pte;
{
pt_entry_t *l1pte, *lev2map, *l2pte, *lev3map;
pt_entry_t *l1pte, *lev2map, *lev3map;
l1pte = pmap_l1pte(pmap, v);
if (pmap_pte_v(l1pte) == 0)
return (NULL);
if (l2pte == NULL) {
l1pte = pmap_l1pte(pmap, v);
if (pmap_pte_v(l1pte) == 0)
return (NULL);
lev2map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte));
l2pte = &lev2map[l2pte_index(v)];
if (pmap_pte_v(l2pte) == 0)
return (NULL);
lev2map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l1pte));
l2pte = &lev2map[l2pte_index(v)];
if (pmap_pte_v(l2pte) == 0)
return (NULL);
}
lev3map = (pt_entry_t *)ALPHA_PHYS_TO_K0SEG(pmap_pte_pa(l2pte));
return (&lev3map[l3pte_index(v)]);