Index: sys/amd64/amd64/mp_machdep.c =================================================================== --- sys/amd64/amd64/mp_machdep.c +++ sys/amd64/amd64/mp_machdep.c @@ -613,10 +613,10 @@ * completion. */ static void -smp_targeted_tlb_shootdown(cpuset_t mask, pmap_t pmap, vm_offset_t addr1, - vm_offset_t addr2, smp_invl_cb_t curcpu_cb, enum invl_op_codes op) +smp_targeted_tlb_shootdown(pmap_t pmap, vm_offset_t addr1, vm_offset_t addr2, + smp_invl_cb_t curcpu_cb, enum invl_op_codes op) { - cpuset_t other_cpus; + cpuset_t mask; uint32_t generation, *p_cpudone; int cpu; bool is_all; @@ -625,16 +625,18 @@ * It is not necessary to signal other CPUs while booting or * when in the debugger. */ - if (kdb_active || KERNEL_PANICKED() || !smp_started) + if (__predict_false(kdb_active || KERNEL_PANICKED() || !smp_started)) goto local_cb; KASSERT(curthread->td_pinned > 0, ("curthread not pinned")); /* - * Check for other cpus. Return if none. + * Make a stable copy of the set of CPUs on which the pmap is active. + * See if we have to interrupt other CPUs. */ - is_all = !CPU_CMP(&mask, &all_cpus); - CPU_CLR(PCPU_GET(cpuid), &mask); + CPU_COPY(pmap_invalidate_cpu_mask(pmap), &mask); + is_all = CPU_CMP(&mask, &all_cpus) == 0; + CPU_CLR(curcpu, &mask); if (CPU_EMPTY(&mask)) goto local_cb; @@ -663,7 +665,7 @@ CPU_FOREACH_ISSET(cpu, &mask) { KASSERT(*invl_scoreboard_slot(cpu) != 0, ("IPI scoreboard is zero, initiator %d target %d", - PCPU_GET(cpuid), cpu)); + curcpu, cpu)); *invl_scoreboard_slot(cpu) = 0; } @@ -674,14 +676,11 @@ */ if (is_all) { ipi_all_but_self(IPI_INVLOP); - other_cpus = all_cpus; - CPU_CLR(PCPU_GET(cpuid), &other_cpus); } else { - other_cpus = mask; ipi_selected(mask, IPI_INVLOP); } curcpu_cb(pmap, addr1, addr2); - CPU_FOREACH_ISSET(cpu, &other_cpus) { + CPU_FOREACH_ISSET(cpu, &mask) { p_cpudone = invl_scoreboard_slot(cpu); while (atomic_load_int(p_cpudone) != generation) ia32_pause(); @@ -705,29 +704,28 @@ } void -smp_masked_invltlb(cpuset_t mask, pmap_t pmap, smp_invl_cb_t curcpu_cb) +smp_masked_invltlb(pmap_t pmap, smp_invl_cb_t curcpu_cb) { - smp_targeted_tlb_shootdown(mask, pmap, 0, 0, curcpu_cb, invl_op_tlb); + smp_targeted_tlb_shootdown(pmap, 0, 0, curcpu_cb, invl_op_tlb); #ifdef COUNT_XINVLTLB_HITS ipi_global++; #endif } void -smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, pmap_t pmap, - smp_invl_cb_t curcpu_cb) +smp_masked_invlpg(vm_offset_t addr, pmap_t pmap, smp_invl_cb_t curcpu_cb) { - smp_targeted_tlb_shootdown(mask, pmap, addr, 0, curcpu_cb, invl_op_pg); + smp_targeted_tlb_shootdown(pmap, addr, 0, curcpu_cb, invl_op_pg); #ifdef COUNT_XINVLTLB_HITS ipi_page++; #endif } void -smp_masked_invlpg_range(cpuset_t mask, vm_offset_t addr1, vm_offset_t addr2, - pmap_t pmap, smp_invl_cb_t curcpu_cb) +smp_masked_invlpg_range(vm_offset_t addr1, vm_offset_t addr2, pmap_t pmap, + smp_invl_cb_t curcpu_cb) { - smp_targeted_tlb_shootdown(mask, pmap, addr1, addr2, curcpu_cb, + smp_targeted_tlb_shootdown(pmap, addr1, addr2, curcpu_cb, invl_op_pgrng); #ifdef COUNT_XINVLTLB_HITS ipi_range++; @@ -738,8 +736,7 @@ void smp_cache_flush(smp_invl_cb_t curcpu_cb) { - smp_targeted_tlb_shootdown(all_cpus, NULL, 0, 0, curcpu_cb, - INVL_OP_CACHE); + smp_targeted_tlb_shootdown(kernel_pmap, 0, 0, curcpu_cb, INVL_OP_CACHE); } /* Index: sys/amd64/amd64/pmap.c =================================================================== --- sys/amd64/amd64/pmap.c +++ sys/amd64/amd64/pmap.c @@ -1958,11 +1958,16 @@ kernel_pmap->pm_pmltop = kernel_pml4; kernel_pmap->pm_cr3 = KPML4phys; kernel_pmap->pm_ucr3 = PMAP_NO_CR3; - CPU_FILL(&kernel_pmap->pm_active); /* don't allow deactivation */ TAILQ_INIT(&kernel_pmap->pm_pvchunk); kernel_pmap->pm_stats.resident_count = res; kernel_pmap->pm_flags = pmap_flags; + /* + * The kernel pmap is always active on all CPUs. Once CPUs are + * enumerated, the mask will be set equal to all_cpus. + */ + CPU_FILL(&kernel_pmap->pm_active); + /* * Initialize the TLB invalidations generation number lock. */ @@ -2960,7 +2965,7 @@ * This will force the vcpu to exit and the cached EPT mappings * will be invalidated by the host before the next vmresume. */ -static __inline void +static __noinline void pmap_invalidate_ept(pmap_t pmap) { smr_seq_t goal; @@ -3010,10 +3015,15 @@ smr_wait(pmap->pm_eptsmr, goal); } -static cpuset_t +/* + * Returns a pointer to a set of CPUs on which the pmap is currently active. + * Note that the set can be modified without any mutual exclusion, so a copy + * must be made if a stable value is required. + */ +volatile cpuset_t * pmap_invalidate_cpu_mask(pmap_t pmap) { - return (pmap == kernel_pmap ? all_cpus : pmap->pm_active); + return (&pmap->pm_active); } static inline void @@ -3147,8 +3157,7 @@ ("pmap_invalidate_page: invalid type %d", pmap->pm_type)); pmap_invalidate_preipi(pmap); - smp_masked_invlpg(pmap_invalidate_cpu_mask(pmap), va, pmap, - pmap_invalidate_page_curcpu_cb); + smp_masked_invlpg(va, pmap, pmap_invalidate_page_curcpu_cb); } /* 4k PTEs -- Chosen to exceed the total size of Broadwell L2 TLB */ @@ -3246,7 +3255,7 @@ ("pmap_invalidate_range: invalid type %d", pmap->pm_type)); pmap_invalidate_preipi(pmap); - smp_masked_invlpg_range(pmap_invalidate_cpu_mask(pmap), sva, eva, pmap, + smp_masked_invlpg_range(sva, eva, pmap, pmap_invalidate_range_curcpu_cb); } @@ -3332,8 +3341,7 @@ ("pmap_invalidate_all: invalid type %d", pmap->pm_type)); pmap_invalidate_preipi(pmap); - smp_masked_invltlb(pmap_invalidate_cpu_mask(pmap), pmap, - pmap_invalidate_all_curcpu_cb); + smp_masked_invltlb(pmap, pmap_invalidate_all_curcpu_cb); } static void @@ -10925,7 +10933,14 @@ pti_finalized = true; VM_OBJECT_WUNLOCK(pti_obj); } -SYSINIT(pmap_pti, SI_SUB_CPU + 1, SI_ORDER_ANY, pmap_pti_init, NULL); + +static void +pmap_cpu_init(void *arg __unused) +{ + CPU_COPY(&all_cpus, &kernel_pmap->pm_active); + pmap_pti_init(); +} +SYSINIT(pmap_cpu, SI_SUB_CPU + 1, SI_ORDER_ANY, pmap_cpu_init, NULL); static pdp_entry_t * pmap_pti_pdpe(vm_offset_t va) Index: sys/amd64/include/pmap.h =================================================================== --- sys/amd64/include/pmap.h +++ sys/amd64/include/pmap.h @@ -485,6 +485,7 @@ void pmap_flush_cache_range(vm_offset_t, vm_offset_t); void pmap_flush_cache_phys_range(vm_paddr_t, vm_paddr_t, vm_memattr_t); void pmap_init_pat(void); +volatile cpuset_t *pmap_invalidate_cpu_mask(pmap_t); void pmap_kenter(vm_offset_t va, vm_paddr_t pa); void *pmap_kenter_temporary(vm_paddr_t pa, int i); vm_paddr_t pmap_kextract(vm_offset_t); Index: sys/x86/include/x86_smp.h =================================================================== --- sys/x86/include/x86_smp.h +++ sys/x86/include/x86_smp.h @@ -107,14 +107,23 @@ void ipi_selected(cpuset_t cpus, u_int ipi); void ipi_self_from_nmi(u_int vector); void set_interrupt_apic_ids(void); +void mem_range_AP_init(void); +void topo_probe(void); + +/* functions in mp_machdep.c */ void smp_cache_flush(smp_invl_cb_t curcpu_cb); +#ifdef __i386__ void smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, struct pmap *pmap, smp_invl_cb_t curcpu_cb); void smp_masked_invlpg_range(cpuset_t mask, vm_offset_t startva, vm_offset_t endva, struct pmap *pmap, smp_invl_cb_t curcpu_cb); void smp_masked_invltlb(cpuset_t mask, struct pmap *pmap, smp_invl_cb_t curcpu_cb); -void mem_range_AP_init(void); -void topo_probe(void); - +#else +void smp_masked_invlpg(vm_offset_t addr, struct pmap *pmap, + smp_invl_cb_t curcpu_cb); +void smp_masked_invlpg_range(vm_offset_t startva, vm_offset_t endva, + struct pmap *pmap, smp_invl_cb_t curcpu_cb); +void smp_masked_invltlb(struct pmap *pmap, smp_invl_cb_t curcpu_cb); +#endif #endif