From 30188853dcde0f83778d9ec9ab2ccadd728482a7 Mon Sep 17 00:00:00 2001 From: thorpej Date: Mon, 27 Apr 1998 19:07:03 +0000 Subject: [PATCH] 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. --- sys/arch/alpha/alpha/pmap.c | 83 ++++++++++++++++++++--------------- sys/arch/alpha/include/pmap.h | 40 ++++++++++------- 2 files changed, 70 insertions(+), 53 deletions(-) diff --git a/sys/arch/alpha/alpha/pmap.c b/sys/arch/alpha/alpha/pmap.c index 6623878f8908..291bf88af143 100644 --- a/sys/arch/alpha/alpha/pmap.c +++ b/sys/arch/alpha/alpha/pmap.c @@ -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 /* 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 #include @@ -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) { diff --git a/sys/arch/alpha/include/pmap.h b/sys/arch/alpha/include/pmap.h index d089e23b7e25..52f0b1bb1106 100644 --- a/sys/arch/alpha/include/pmap.h +++ b/sys/arch/alpha/include/pmap.h @@ -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)]);