Module Name: src Committed By: cherry Date: Mon Jan 9 12:58:49 UTC 2012
Modified Files: src/sys/arch/x86/x86: pmap.c src/sys/arch/xen/x86: xen_pmap.c Log Message: Harden cross-cpu L3 sync - avoid optimisations that may race. Update ci->ci_kpm_pdir from user pmap, not global pmap_kernel() entry which may get clobbered by other CPUs. XXX: Look into why we use pmap_kernel() userspace entries at all. To generate a diff of this commit: cvs rdiff -u -r1.152 -r1.153 src/sys/arch/x86/x86/pmap.c cvs rdiff -u -r1.12 -r1.13 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.152 src/sys/arch/x86/x86/pmap.c:1.153 --- src/sys/arch/x86/x86/pmap.c:1.152 Mon Jan 9 04:55:35 2012 +++ src/sys/arch/x86/x86/pmap.c Mon Jan 9 12:58:49 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: pmap.c,v 1.152 2012/01/09 04:55:35 cherry Exp $ */ +/* $NetBSD: pmap.c,v 1.153 2012/01/09 12:58:49 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.152 2012/01/09 04:55:35 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.153 2012/01/09 12:58:49 cherry Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -1882,20 +1882,14 @@ pmap_free_ptp(struct pmap *pmap, struct * If ptp is a L3 currently mapped in kernel space, * on any cpu, clear it before freeing */ - struct cpu_info *ci; - CPU_INFO_ITERATOR cii; + if (level == PTP_LEVELS - 1) { + pmap_pte_set(&pmap_kernel()->pm_pdir[index], 0); + /* + * Update the per-cpu PD on all cpus the current + * pmap is active on + */ + xen_kpm_sync(pmap, index); - for (CPU_INFO_FOREACH(cii, ci)) { - if (pmap_pdirpa(pmap, 0) == ci->ci_xen_current_user_pgd - && level == PTP_LEVELS - 1) { - pmap_pte_set(&pmap_kernel()->pm_pdir[index], 0); - /* - * Update the per-cpu PD on all cpus the current - * pmap is active on - */ - xen_kpm_sync(pmap, index); - break; - } } # endif /*__x86_64__ */ invaladdr = level == 1 ? (vaddr_t)ptes : Index: src/sys/arch/xen/x86/xen_pmap.c diff -u src/sys/arch/xen/x86/xen_pmap.c:1.12 src/sys/arch/xen/x86/xen_pmap.c:1.13 --- src/sys/arch/xen/x86/xen_pmap.c:1.12 Fri Dec 30 16:55:21 2011 +++ src/sys/arch/xen/x86/xen_pmap.c Mon Jan 9 12:58:49 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: xen_pmap.c,v 1.12 2011/12/30 16:55:21 cherry Exp $ */ +/* $NetBSD: xen_pmap.c,v 1.13 2012/01/09 12:58:49 cherry Exp $ */ /* * Copyright (c) 2007 Manuel Bouyer. @@ -102,7 +102,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.12 2011/12/30 16:55:21 cherry Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xen_pmap.c,v 1.13 2012/01/09 12:58:49 cherry Exp $"); #include "opt_user_ldt.h" #include "opt_lockdebug.h" @@ -576,6 +576,8 @@ pmap_kpm_sync_xcall(void *arg1, void *ar struct pmap *pmap = arg1; int index = *(int *)arg2; + KASSERT(pmap == pmap_kernel() || index < PDIR_SLOT_PTE); + struct cpu_info *ci = xpq_cpu(); if (pmap == pmap_kernel()) { @@ -596,7 +598,7 @@ pmap_kpm_sync_xcall(void *arg1, void *ar } pmap_pte_set(&ci->ci_kpm_pdir[index], - pmap_kernel()->pm_pdir[index]); + pmap->pm_pdir[index]); pmap_pte_flush(); #endif /* PAE || __x86_64__ */ } @@ -650,6 +652,7 @@ xen_kpm_sync(struct pmap *pmap, int inde #else /* MULTIPROCESSOR */ #define CPU_IS_CURCPU(ci) __predict_true((ci) == curcpu()) #endif /* MULTIPROCESSOR */ +#if 0 /* XXX: Race with remote pmap_load() */ if (ci->ci_want_pmapload && !CPU_IS_CURCPU(ci)) { /* @@ -659,7 +662,7 @@ xen_kpm_sync(struct pmap *pmap, int inde */ continue; } - +#endif /* 0 */ where = xc_unicast(XC_HIGHPRI, pmap_kpm_sync_xcall, pmap, &index, ci); xc_wait(where);