Module Name: src Committed By: cherry Date: Fri Dec 30 16:55:21 UTC 2011
Modified Files: src/sys/arch/x86/x86: pmap.c src/sys/arch/xen/include: xenpmap.h src/sys/arch/xen/x86: cpu.c xen_pmap.c Log Message: per-cpu shadow directory pages should be updated locally via cross-calls. Do this. To generate a diff of this commit: cvs rdiff -u -r1.147 -r1.148 src/sys/arch/x86/x86/pmap.c cvs rdiff -u -r1.32 -r1.33 src/sys/arch/xen/include/xenpmap.h cvs rdiff -u -r1.71 -r1.72 src/sys/arch/xen/x86/cpu.c cvs rdiff -u -r1.11 -r1.12 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/x86/pmap.c diff -u src/sys/arch/x86/x86/pmap.c:1.147 src/sys/arch/x86/x86/pmap.c:1.148 --- src/sys/arch/x86/x86/pmap.c:1.147 Fri Dec 9 17:32:51 2011 +++ src/sys/arch/x86/x86/pmap.c Fri Dec 30 16:55:21 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.147 2011/12/09 17:32:51 chs Exp $ */ +/* $NetBSD: pmap.c,v 1.148 2011/12/30 16:55:21 cherry Exp $ */ /*- * Copyright (c) 2008, 2010 The NetBSD Foundation, Inc. @@ -171,7 +171,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.147 2011/12/09 17:32:51 chs Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.148 2011/12/30 16:55:21 cherry Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -1915,16 +1915,7 @@ pmap_free_ptp(struct pmap *pmap, struct * Update the per-cpu PD on all cpus the current * pmap is active on */ - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - for (CPU_INFO_FOREACH(cii, ci)) { - if (ci == NULL) { - continue; - } - if (ci->ci_cpumask & pmap->pm_cpus) { - pmap_pte_set(&ci->ci_kpm_pdir[index], 0); - } - } + xen_kpm_sync(pmap, index); } # endif /*__x86_64__ */ invaladdr = level == 1 ? (vaddr_t)ptes : @@ -2029,17 +2020,7 @@ pmap_get_ptp(struct pmap *pmap, vaddr_t * Update the per-cpu PD on all cpus the current * pmap is active on */ - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - for (CPU_INFO_FOREACH(cii, ci)) { - if (ci == NULL) { - continue; - } - if (ci->ci_cpumask & pmap->pm_cpus) { - pmap_pte_set(&ci->ci_kpm_pdir[index], - (pd_entry_t) (pmap_pa2pte(pa) | PG_u | PG_RW | PG_V)); - } - } + xen_kpm_sync(pmap, index); } #endif /* XEN && __x86_64__ */ pmap_pte_flush(); @@ -4247,33 +4228,14 @@ pmap_alloc_level(pd_entry_t * const *pde pmap_get_physpage(va, level - 1, &pa); pte = pmap_pa2pte(pa) | PG_k | PG_V | PG_RW; #ifdef XEN - switch (level) { - case PTP_LEVELS: + xpq_queue_pte_update(xpmap_ptetomach(&pdep[i]), pte); + if (level == PTP_LEVELS) { #if defined(PAE) || defined(__x86_64__) if (i >= PDIR_SLOT_KERN) { /* update per-cpu PMDs on all cpus */ - CPU_INFO_ITERATOR cii; - struct cpu_info *ci; - for (CPU_INFO_FOREACH(cii, ci)) { - if (ci == NULL) { - continue; - } -#ifdef PAE - xpq_queue_pte_update( - xpmap_ptetomach(&ci->ci_kpm_pdir[l2tol2(i)]), pte); -#elif defined(__x86_64__) - xpq_queue_pte_update( - xpmap_ptetomach(&ci->ci_kpm_pdir[i]), pte); -#endif /* PAE */ - } + xen_kpm_sync(pmap_kernel(), i); } #endif /* PAE || __x86_64__ */ - /* FALLTHROUGH */ - - default: /* All other levels */ - xpq_queue_pte_update( - xpmap_ptetomach(&pdep[i]), - pte); } #else /* XEN */ pdep[i] = pte; Index: src/sys/arch/xen/include/xenpmap.h diff -u src/sys/arch/xen/include/xenpmap.h:1.32 src/sys/arch/xen/include/xenpmap.h:1.33 --- src/sys/arch/xen/include/xenpmap.h:1.32 Wed Nov 23 00:56:56 2011 +++ src/sys/arch/xen/include/xenpmap.h Fri Dec 30 16:55:21 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: xenpmap.h,v 1.32 2011/11/23 00:56:56 jym Exp $ */ +/* $NetBSD: xenpmap.h,v 1.33 2011/12/30 16:55:21 cherry Exp $ */ /* * @@ -61,6 +61,10 @@ void pmap_map_recursive_entries(void); void pmap_unmap_recursive_entries(void); #endif /* PAE */ +#if defined(PAE) || defined(__x86_64__) +void xen_kpm_sync(struct pmap *, int); +#endif /* PAE || __x86_64__ */ + #define xpq_queue_pin_l1_table(pa) \ xpq_queue_pin_table(pa, MMUEXT_PIN_L1_TABLE) #define xpq_queue_pin_l2_table(pa) \ Index: src/sys/arch/xen/x86/cpu.c diff -u src/sys/arch/xen/x86/cpu.c:1.71 src/sys/arch/xen/x86/cpu.c:1.72 --- src/sys/arch/xen/x86/cpu.c:1.71 Wed Dec 7 15:47:43 2011 +++ src/sys/arch/xen/x86/cpu.c Fri Dec 30 16:55:21 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: cpu.c,v 1.71 2011/12/07 15:47:43 cegger Exp $ */ +/* $NetBSD: cpu.c,v 1.72 2011/12/30 16:55:21 cherry Exp $ */ /* NetBSD: cpu.c,v 1.18 2004/02/20 17:35:01 yamt Exp */ /*- @@ -66,7 +66,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.71 2011/12/07 15:47:43 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.72 2011/12/30 16:55:21 cherry Exp $"); #include "opt_ddb.h" #include "opt_multiprocessor.h" @@ -1102,6 +1102,7 @@ static struct cpu_info *cpu_primary(void { return &cpu_info_primary; } +/* XXX: rename to something more generic. users other than xpq exist */ struct cpu_info * (*xpq_cpu)(void) = cpu_primary; void Index: src/sys/arch/xen/x86/xen_pmap.c diff -u src/sys/arch/xen/x86/xen_pmap.c:1.11 src/sys/arch/xen/x86/xen_pmap.c:1.12 --- src/sys/arch/xen/x86/xen_pmap.c:1.11 Wed Dec 7 15:47:43 2011 +++ src/sys/arch/xen/x86/xen_pmap.c Fri Dec 30 16:55:21 2011 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_pmap.c,v 1.11 2011/12/07 15:47:43 cegger Exp $ */ +/* $NetBSD: xen_pmap.c,v 1.12 2011/12/30 16:55:21 cherry Exp $ */ /* * Copyright (c) 2007 Manuel Bouyer. @@ -102,7 +102,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.11 2011/12/07 15:47:43 cegger Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.12 2011/12/30 16:55:21 cherry Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -550,3 +550,123 @@ pmap_unmap_recursive_entries(void) } #endif /* PAE */ + +#if defined(PAE) || defined(__x86_64__) + +extern struct cpu_info * (*xpq_cpu)(void); +static __inline void +pmap_kpm_setpte(struct cpu_info *ci, int index) +{ +#ifdef PAE + xpq_queue_pte_update( + xpmap_ptetomach(&ci->ci_kpm_pdir[l2tol2(index)]), + pmap_kernel()->pm_pdir[index]); +#elif defined(__x86_64__) + xpq_queue_pte_update( + xpmap_ptetomach(&ci->ci_kpm_pdir[index]), + pmap_kernel()->pm_pdir[index]); +#endif /* PAE */ +} + +static void +pmap_kpm_sync_xcall(void *arg1, void *arg2) +{ + KASSERT(arg1 != NULL); + KASSERT(arg2 != NULL); + + struct pmap *pmap = arg1; + int index = *(int *)arg2; + struct cpu_info *ci = xpq_cpu(); + + if (pmap == pmap_kernel()) { + KASSERT(index >= PDIR_SLOT_KERN); + pmap_kpm_setpte(ci, index); + pmap_pte_flush(); + return; + } + +#ifdef PAE + KASSERTMSG(false, "%s not allowed for PAE user pmaps", __func__); + return; +#else /* __x86_64__ */ + + if (ci->ci_pmap != pmap) { + /* pmap changed. Nothing to do. */ + return; + } + + pmap_pte_set(&ci->ci_kpm_pdir[index], + pmap_kernel()->pm_pdir[index]); + pmap_pte_flush(); +#endif /* PAE || __x86_64__ */ +} + +/* + * Synchronise shadow pdir with the pmap on all cpus on which it is + * loaded. + */ +void +xen_kpm_sync(struct pmap *pmap, int index) +{ + uint64_t where; + + KASSERT(pmap != NULL); + + pmap_pte_flush(); + + if (__predict_false(xpq_cpu != &x86_curcpu)) { /* Too early to xcall */ + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + for (CPU_INFO_FOREACH(cii, ci)) { + if (ci == NULL) { + continue; + } + if (pmap == pmap_kernel() || + ci->ci_cpumask & pmap->pm_cpus) { + pmap_kpm_setpte(ci, index); + } + } + pmap_pte_flush(); + return; + } + + if (pmap == pmap_kernel()) { + where = xc_broadcast(XC_HIGHPRI, + pmap_kpm_sync_xcall, pmap, &index); + xc_wait(where); + } else { + KASSERT(mutex_owned(pmap->pm_lock)); + KASSERT(kpreempt_disabled()); + + CPU_INFO_ITERATOR cii; + struct cpu_info *ci; + for (CPU_INFO_FOREACH(cii, ci)) { + if (ci == NULL) { + continue; + } + while (ci->ci_cpumask & pmap->pm_cpus) { +#ifdef MULTIPROCESSOR +#define CPU_IS_CURCPU(ci) __predict_false((ci) == curcpu()) +#else /* MULTIPROCESSOR */ +#define CPU_IS_CURCPU(ci) __predict_true((ci) == curcpu()) +#endif /* MULTIPROCESSOR */ + if (ci->ci_want_pmapload && + !CPU_IS_CURCPU(ci)) { + /* + * XXX: make this more cpu + * cycle friendly/co-operate + * with pmap_load() + */ + continue; + } + + where = xc_unicast(XC_HIGHPRI, pmap_kpm_sync_xcall, + pmap, &index, ci); + xc_wait(where); + break; + } + } + } +} + +#endif /* PAE || __x86_64__ */