Module Name: src Committed By: dyoung Date: Mon May 10 18:46:59 UTC 2010
Modified Files: src/sys/arch/x86/include: pmap.h src/sys/arch/x86/x86: bus_space.c pmap.c src/sys/arch/xen/conf: files.xen Added Files: src/sys/arch/xen/x86: xen_pmap.c Log Message: Provide pmap_enter_ma(), pmap_extract_ma(), pmap_kenter_ma() in all x86 kernels, and use them in the bus_space(9) implementation instead of ugly Xen #ifdef-age. In a non-Xen kernel, the _ma() functions either call or alias the equivalent _pa() functions. Reviewed on port-...@netbsd.org and port-i...@netbsd.org. Passes rmind@'s and bouyer@'s inspection. Tested on i386 and on Xen DOMU / DOM0. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/arch/x86/include/pmap.h cvs rdiff -u -r1.28 -r1.29 src/sys/arch/x86/x86/bus_space.c cvs rdiff -u -r1.108 -r1.109 src/sys/arch/x86/x86/pmap.c cvs rdiff -u -r1.106 -r1.107 src/sys/arch/xen/conf/files.xen cvs rdiff -u -r0 -r1.1 src/sys/arch/xen/x86/xen_pmap.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/x86/include/pmap.h diff -u src/sys/arch/x86/include/pmap.h:1.29 src/sys/arch/x86/include/pmap.h:1.30 --- src/sys/arch/x86/include/pmap.h:1.29 Tue Feb 9 22:51:13 2010 +++ src/sys/arch/x86/include/pmap.h Mon May 10 18:46:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.h,v 1.29 2010/02/09 22:51:13 jym Exp $ */ +/* $NetBSD: pmap.h,v 1.30 2010/05/10 18:46:58 dyoung Exp $ */ /* * @@ -228,6 +228,12 @@ void pmap_emap_remove(vaddr_t, vsize_t); void pmap_emap_sync(bool); +void pmap_map_ptes(struct pmap *, struct pmap **, pd_entry_t **, + pd_entry_t * const **); +void pmap_unmap_ptes(struct pmap *, struct pmap *); + +int pmap_pdes_invalid(vaddr_t, pd_entry_t * const *, pd_entry_t *); + vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */ void pmap_tlb_shootdown(pmap_t, vaddr_t, vaddr_t, pt_entry_t); @@ -248,6 +254,12 @@ * inline functions */ +__inline static bool __unused +pmap_pdes_valid(vaddr_t va, pd_entry_t * const *pdes, pd_entry_t *lastpde) +{ + return pmap_pdes_invalid(va, pdes, lastpde) == 0; +} + /* * pmap_update_pg: flush one page from the TLB (or flush the whole thing * if hardware doesn't support one-page flushing) @@ -401,17 +413,17 @@ /* Xen helpers to change bits of a pte */ #define XPMAP_UPDATE_DIRECT 1 /* Update direct map entry flags too */ +paddr_t vtomach(vaddr_t); +#define vtomfn(va) (vtomach(va) >> PAGE_SHIFT) + +#endif /* XEN */ + /* pmap functions with machine addresses */ void pmap_kenter_ma(vaddr_t, paddr_t, vm_prot_t, u_int); int pmap_enter_ma(struct pmap *, vaddr_t, paddr_t, paddr_t, vm_prot_t, u_int, int); bool pmap_extract_ma(pmap_t, vaddr_t, paddr_t *); -paddr_t vtomach(vaddr_t); -#define vtomfn(va) (vtomach(va) >> PAGE_SHIFT) - -#endif /* XEN */ - /* * Hooks for the pool allocator. */ Index: src/sys/arch/x86/x86/bus_space.c diff -u src/sys/arch/x86/x86/bus_space.c:1.28 src/sys/arch/x86/x86/bus_space.c:1.29 --- src/sys/arch/x86/x86/bus_space.c:1.28 Wed Apr 28 20:27:36 2010 +++ src/sys/arch/x86/x86/bus_space.c Mon May 10 18:46:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: bus_space.c,v 1.28 2010/04/28 20:27:36 dyoung Exp $ */ +/* $NetBSD: bus_space.c,v 1.29 2010/05/10 18:46:58 dyoung Exp $ */ /*- * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.28 2010/04/28 20:27:36 dyoung Exp $"); +__KERNEL_RCSID(0, "$NetBSD: bus_space.c,v 1.29 2010/05/10 18:46:58 dyoung Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -48,9 +48,6 @@ #ifdef XEN #include <xen/hypervisor.h> -#include <xen/xenpmap.h> - -#define pmap_extract(a, b, c) pmap_extract_ma(a, b, c) #endif /* @@ -339,11 +336,7 @@ *bshp = (bus_space_handle_t)(sva + (bpa & PGOFSET)); for (va = sva; pa != endpa; pa += PAGE_SIZE, va += PAGE_SIZE) { -#ifdef XEN pmap_kenter_ma(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags); -#else - pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, pmapflags); -#endif /* XEN */ } pmap_update(pmap_kernel()); @@ -395,7 +388,7 @@ } #endif - if (pmap_extract(pmap_kernel(), va, &bpa) == FALSE) { + if (pmap_extract_ma(pmap_kernel(), va, &bpa) == FALSE) { panic("_x86_memio_unmap:" " wrong virtual address"); } @@ -447,7 +440,7 @@ panic("x86_memio_unmap: overflow"); #endif - (void) pmap_extract(pmap_kernel(), va, &bpa); + (void) pmap_extract_ma(pmap_kernel(), va, &bpa); bpa += (bsh & PGOFSET); pmap_kremove(va, endva - va); Index: src/sys/arch/x86/x86/pmap.c diff -u src/sys/arch/x86/x86/pmap.c:1.108 src/sys/arch/x86/x86/pmap.c:1.109 --- src/sys/arch/x86/x86/pmap.c:1.108 Tue May 4 23:27:14 2010 +++ src/sys/arch/x86/x86/pmap.c Mon May 10 18:46:58 2010 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.108 2010/05/04 23:27:14 jym Exp $ */ +/* $NetBSD: pmap.c,v 1.109 2010/05/10 18:46:58 dyoung Exp $ */ /* * Copyright (c) 2007 Manuel Bouyer. @@ -149,7 +149,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.108 2010/05/04 23:27:14 jym Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.109 2010/05/10 18:46:58 dyoung Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -531,6 +531,8 @@ static pt_entry_t *csrc_pte, *cdst_pte, *zero_pte, *ptp_pte, *early_zero_pte; static char *csrcp, *cdstp, *zerop, *ptpp, *early_zerop; +int pmap_enter_default(pmap_t, vaddr_t, paddr_t, vm_prot_t, u_int); + /* * pool and cache that PDPs are allocated from */ @@ -580,8 +582,6 @@ pd_entry_t * const *); static bool pmap_is_curpmap(struct pmap *); static bool pmap_is_active(struct pmap *, struct cpu_info *, bool); -static void pmap_map_ptes(struct pmap *, struct pmap **, - pt_entry_t **, pd_entry_t * const **); static bool pmap_remove_pte(struct pmap *, struct vm_page *, pt_entry_t *, vaddr_t, struct pv_entry **); @@ -589,13 +589,8 @@ vaddr_t, vaddr_t, vaddr_t, struct pv_entry **); -static void pmap_unmap_ptes(struct pmap *, struct pmap *); static void pmap_unmap_apdp(void); static bool pmap_get_physpage(vaddr_t, int, paddr_t *); -static int pmap_pdes_invalid(vaddr_t, pd_entry_t * const *, - pd_entry_t *); -#define pmap_pdes_valid(va, pdes, lastpde) \ - (pmap_pdes_invalid((va), (pdes), (lastpde)) == 0) static void pmap_alloc_level(pd_entry_t * const *, vaddr_t, int, long *); @@ -781,7 +776,7 @@ * => must be undone with pmap_unmap_ptes before returning */ -static void +void pmap_map_ptes(struct pmap *pmap, struct pmap **pmap2, pd_entry_t **ptepp, pd_entry_t * const **pdeppp) { @@ -914,7 +909,7 @@ * pmap_unmap_ptes: unlock the PTE mapping of "pmap" */ -static void +void pmap_unmap_ptes(struct pmap *pmap, struct pmap *pmap2) { @@ -1122,47 +1117,7 @@ } } -#ifdef XEN -/* - * pmap_kenter_ma: enter a kernel mapping without R/M (pv_entry) tracking - * - * => no need to lock anything, assume va is already allocated - * => should be faster than normal pmap enter function - * => we expect a MACHINE address - */ - -void -pmap_kenter_ma(vaddr_t va, paddr_t ma, vm_prot_t prot, u_int flags) -{ - pt_entry_t *pte, opte, npte; - - if (va < VM_MIN_KERNEL_ADDRESS) - pte = vtopte(va); - else - pte = kvtopte(va); - - npte = ma | ((prot & VM_PROT_WRITE) ? PG_RW : PG_RO) | - PG_V | PG_k; - if (flags & PMAP_NOCACHE) - npte |= PG_N; - - if ((cpu_feature[2] & CPUID_NOX) && !(prot & VM_PROT_EXECUTE)) - npte |= PG_NX; - - opte = pmap_pte_testset (pte, npte); /* zap! */ - - if (pmap_valid_entry(opte)) { -#if defined(MULTIPROCESSOR) - kpreempt_disable(); - pmap_tlb_shootdown(pmap_kernel(), va, 0, opte); - kpreempt_enable(); -#else - /* Don't bother deferring in the single CPU case. */ - pmap_update_pg(va); -#endif - } -} -#endif /* XEN */ +__weak_alias(pmap_kenter_ma, pmap_kenter_pa); #if defined(__x86_64__) /* @@ -2883,7 +2838,7 @@ * some misc. functions */ -static int +int pmap_pdes_invalid(vaddr_t va, pd_entry_t * const *pdes, pd_entry_t *lastpde) { int i; @@ -2977,39 +2932,9 @@ return (0); } -#ifdef XEN -/* - * pmap_extract_ma: extract a MA for the given VA - */ +__weak_alias(pmap_extract_ma, pmap_extract); -bool -pmap_extract_ma(struct pmap *pmap, vaddr_t va, paddr_t *pap) -{ - pt_entry_t *ptes, pte; - pd_entry_t pde; - pd_entry_t * const *pdes; - struct pmap *pmap2; - - kpreempt_disable(); - pmap_map_ptes(pmap, &pmap2, &ptes, &pdes); - if (!pmap_pdes_valid(va, pdes, &pde)) { - pmap_unmap_ptes(pmap, pmap2); - kpreempt_enable(); - return false; - } - - pte = ptes[pl1_i(va)]; - pmap_unmap_ptes(pmap, pmap2); - kpreempt_enable(); - - if (__predict_true((pte & PG_V) != 0)) { - if (pap != NULL) - *pap = (pte & PG_FRAME) | (va & (NBPD_L1 - 1)); - return true; - } - - return false; -} +#ifdef XEN /* * vtomach: virtual address to machine address. For use by @@ -3028,8 +2953,6 @@ #endif /* XEN */ - - /* * pmap_virtual_space: used during bootup [pmap_steal_memory] to * determine the bounds of the kernel virtual addess space. @@ -3985,24 +3908,25 @@ * defined as macro in pmap.h */ +__weak_alias(pmap_enter, pmap_enter_default); + +int +pmap_enter_default(pmap_t pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, + u_int flags) +{ + return pmap_enter_ma(pmap, va, pa, pa, prot, flags, 0); +} + /* * pmap_enter: enter a mapping into a pmap * * => must be done "now" ... no lazy-evaluation * => we set pmap => pv_head locking */ -#ifdef XEN int pmap_enter_ma(struct pmap *pmap, vaddr_t va, paddr_t ma, paddr_t pa, vm_prot_t prot, u_int flags, int domid) { -#else /* XEN */ -int -pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, - u_int flags) -{ - paddr_t ma = pa; -#endif /* XEN */ pt_entry_t *ptes, opte, npte; pt_entry_t *ptep; pd_entry_t * const *pdes; @@ -4214,22 +4138,6 @@ return error; } -#ifdef XEN -int -pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) -{ - paddr_t ma; - - if (__predict_false(pa < pmap_pa_start || pmap_pa_end <= pa)) { - ma = pa; /* XXX hack */ - } else { - ma = xpmap_ptom(pa); - } - - return pmap_enter_ma(pmap, va, ma, pa, prot, flags, DOMID_SELF); -} -#endif /* XEN */ - static bool pmap_get_physpage(vaddr_t va, int level, paddr_t *paddrp) { Index: src/sys/arch/xen/conf/files.xen diff -u src/sys/arch/xen/conf/files.xen:1.106 src/sys/arch/xen/conf/files.xen:1.107 --- src/sys/arch/xen/conf/files.xen:1.106 Tue Nov 3 05:23:28 2009 +++ src/sys/arch/xen/conf/files.xen Mon May 10 18:46:58 2010 @@ -1,4 +1,4 @@ -# $NetBSD: files.xen,v 1.106 2009/11/03 05:23:28 dyoung Exp $ +# $NetBSD: files.xen,v 1.107 2010/05/10 18:46:58 dyoung Exp $ # NetBSD: files.x86,v 1.10 2003/10/08 17:30:00 bouyer Exp # NetBSD: files.i386,v 1.254 2004/03/25 23:32:10 jmc Exp @@ -106,6 +106,7 @@ # file arch/x86/x86/mtrr_i686.c mtrr file arch/x86/x86/syscall.c file arch/xen/x86/x86_xpmap.c +file arch/xen/x86/xen_pmap.c file arch/xen/x86/xen_intr.c file arch/xen/x86/xenfunc.c Added files: Index: src/sys/arch/xen/x86/xen_pmap.c diff -u /dev/null src/sys/arch/xen/x86/xen_pmap.c:1.1 --- /dev/null Mon May 10 18:46:59 2010 +++ src/sys/arch/xen/x86/xen_pmap.c Mon May 10 18:46:59 2010 @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2007 Manuel Bouyer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +/* + * Copyright (c) 2006 Mathieu Ropert <m...@adviseo.fr> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * + * Copyright (c) 1997 Charles D. Cranor and Washington University. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by Charles D. Cranor and + * Washington University. + * 4. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Copyright 2001 (c) Wasabi Systems, Inc. + * All rights reserved. + * + * Written by Frank van der Linden for Wasabi Systems, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed for the NetBSD Project by + * Wasabi Systems, Inc. + * 4. The name of Wasabi Systems, Inc. may not be used to endorse + * or promote products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.1 2010/05/10 18:46:59 dyoung Exp $"); + +#include "opt_user_ldt.h" +#include "opt_lockdebug.h" +#include "opt_multiprocessor.h" +#include "opt_xen.h" +#if !defined(__x86_64__) +#include "opt_kstack_dr0.h" +#endif /* !defined(__x86_64__) */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/pool.h> +#include <sys/kernel.h> +#include <sys/atomic.h> +#include <sys/cpu.h> +#include <sys/intr.h> +#include <sys/xcall.h> + +#include <uvm/uvm.h> + +#include <dev/isa/isareg.h> + +#include <machine/specialreg.h> +#include <machine/gdt.h> +#include <machine/isa_machdep.h> +#include <machine/cpuvar.h> + +#include <x86/pmap.h> +#include <x86/pmap_pv.h> + +#include <x86/i82489reg.h> +#include <x86/i82489var.h> + +#ifdef XEN +#include <xen/xen3-public/xen.h> +#include <xen/hypervisor.h> +#endif + +/* flag to be used for kernel mappings: PG_u on Xen/amd64, 0 otherwise */ +#if defined(XEN) && defined(__x86_64__) +#define PG_k PG_u +#else +#define PG_k 0 +#endif + +extern paddr_t pmap_pa_start; /* PA of first physical page for this domain */ +extern paddr_t pmap_pa_end; /* PA of last physical page for this domain */ + +int +pmap_enter(struct pmap *pmap, vaddr_t va, paddr_t pa, vm_prot_t prot, u_int flags) +{ + paddr_t ma; + + if (__predict_false(pa < pmap_pa_start || pmap_pa_end <= pa)) { + ma = pa; /* XXX hack */ + } else { + ma = xpmap_ptom(pa); + } + + return pmap_enter_ma(pmap, va, ma, pa, prot, flags, DOMID_SELF); +} + +/* + * pmap_kenter_ma: enter a kernel mapping without R/M (pv_entry) tracking + * + * => no need to lock anything, assume va is already allocated + * => should be faster than normal pmap enter function + * => we expect a MACHINE address + */ + +void +pmap_kenter_ma(vaddr_t va, paddr_t ma, vm_prot_t prot, u_int flags) +{ + pt_entry_t *pte, opte, npte; + + if (va < VM_MIN_KERNEL_ADDRESS) + pte = vtopte(va); + else + pte = kvtopte(va); + + npte = ma | ((prot & VM_PROT_WRITE) ? PG_RW : PG_RO) | + PG_V | PG_k; + if (flags & PMAP_NOCACHE) + npte |= PG_N; + + if ((cpu_feature[2] & CPUID_NOX) && !(prot & VM_PROT_EXECUTE)) + npte |= PG_NX; + + opte = pmap_pte_testset (pte, npte); /* zap! */ + + if (pmap_valid_entry(opte)) { +#if defined(MULTIPROCESSOR) + kpreempt_disable(); + pmap_tlb_shootdown(pmap_kernel(), va, 0, opte); + kpreempt_enable(); +#else + /* Don't bother deferring in the single CPU case. */ + pmap_update_pg(va); +#endif + } +} + +/* + * pmap_extract_ma: extract a MA for the given VA + */ + +bool +pmap_extract_ma(struct pmap *pmap, vaddr_t va, paddr_t *pap) +{ + pt_entry_t *ptes, pte; + pd_entry_t pde; + pd_entry_t * const *pdes; + struct pmap *pmap2; + + kpreempt_disable(); + pmap_map_ptes(pmap, &pmap2, &ptes, &pdes); + if (!pmap_pdes_valid(va, pdes, &pde)) { + pmap_unmap_ptes(pmap, pmap2); + kpreempt_enable(); + return false; + } + + pte = ptes[pl1_i(va)]; + pmap_unmap_ptes(pmap, pmap2); + kpreempt_enable(); + + if (__predict_true((pte & PG_V) != 0)) { + if (pap != NULL) + *pap = (pte & PG_FRAME) | (va & (NBPD_L1 - 1)); + return true; + } + + return false; +}