svn commit: r362572 - in stable/12/sys: amd64/amd64 i386/i386 x86/include x86/x86

Konstantin Belousov kib at FreeBSD.org
Wed Jun 24 06:35:51 UTC 2020


Author: kib
Date: Wed Jun 24 06:35:50 2020
New Revision: 362572
URL: https://svnweb.freebsd.org/changeset/base/362572

Log:
  MFC r362031, r362065, r362075:
  amd64 pmap: reorder IPI send and local TLB flush in TLB invalidations.

Modified:
  stable/12/sys/amd64/amd64/pmap.c
  stable/12/sys/i386/i386/pmap.c
  stable/12/sys/i386/i386/vm_machdep.c
  stable/12/sys/x86/include/x86_smp.h
  stable/12/sys/x86/x86/mp_x86.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/amd64/amd64/pmap.c
==============================================================================
--- stable/12/sys/amd64/amd64/pmap.c	Wed Jun 24 05:12:00 2020	(r362571)
+++ stable/12/sys/amd64/amd64/pmap.c	Wed Jun 24 06:35:50 2020	(r362572)
@@ -2412,6 +2412,20 @@ DEFINE_IFUNC(static, void, pmap_invalidate_page_mode, 
 	return (pmap_invalidate_page_nopcid);
 }
 
+static void
+pmap_invalidate_page_curcpu_cb(pmap_t pmap, vm_offset_t va,
+    vm_offset_t addr2 __unused)
+{
+
+	if (pmap == kernel_pmap) {
+		invlpg(va);
+	} else {
+		if (pmap == PCPU_GET(curpmap))
+			invlpg(va);
+		pmap_invalidate_page_mode(pmap, va);
+	}
+}
+
 void
 pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
 {
@@ -2424,16 +2438,8 @@ pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
 	KASSERT(pmap->pm_type == PT_X86,
 	    ("pmap_invalidate_page: invalid type %d", pmap->pm_type));
 
-	sched_pin();
-	if (pmap == kernel_pmap) {
-		invlpg(va);
-	} else {
-		if (pmap == PCPU_GET(curpmap))
-			invlpg(va);
-		pmap_invalidate_page_mode(pmap, va);
-	}
-	smp_masked_invlpg(pmap_invalidate_cpu_mask(pmap), va, pmap);
-	sched_unpin();
+	smp_masked_invlpg(pmap_invalidate_cpu_mask(pmap), va, pmap,
+	    pmap_invalidate_page_curcpu_cb);
 }
 
 /* 4k PTEs -- Chosen to exceed the total size of Broadwell L2 TLB */
@@ -2509,10 +2515,26 @@ DEFINE_IFUNC(static, void, pmap_invalidate_range_mode,
 	return (pmap_invalidate_range_nopcid);
 }
 
+static void
+pmap_invalidate_range_curcpu_cb(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
+{
+	vm_offset_t addr;
+
+	if (pmap == kernel_pmap) {
+		for (addr = sva; addr < eva; addr += PAGE_SIZE)
+			invlpg(addr);
+	} else {
+		if (pmap == PCPU_GET(curpmap)) {
+			for (addr = sva; addr < eva; addr += PAGE_SIZE)
+				invlpg(addr);
+		}
+		pmap_invalidate_range_mode(pmap, sva, eva);
+	}
+}
+
 void
 pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
 {
-	vm_offset_t addr;
 
 	if (eva - sva >= PMAP_INVLPG_THRESHOLD) {
 		pmap_invalidate_all(pmap);
@@ -2527,19 +2549,8 @@ pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm
 	KASSERT(pmap->pm_type == PT_X86,
 	    ("pmap_invalidate_range: invalid type %d", pmap->pm_type));
 
-	sched_pin();
-	if (pmap == kernel_pmap) {
-		for (addr = sva; addr < eva; addr += PAGE_SIZE)
-			invlpg(addr);
-	} else {
-		if (pmap == PCPU_GET(curpmap)) {
-			for (addr = sva; addr < eva; addr += PAGE_SIZE)
-				invlpg(addr);
-		}
-		pmap_invalidate_range_mode(pmap, sva, eva);
-	}
-	smp_masked_invlpg_range(pmap_invalidate_cpu_mask(pmap), sva, eva, pmap);
-	sched_unpin();
+	smp_masked_invlpg_range(pmap_invalidate_cpu_mask(pmap), sva, eva, pmap,
+	    pmap_invalidate_range_curcpu_cb);
 }
 
 static inline void
@@ -2626,6 +2637,14 @@ DEFINE_IFUNC(static, void, pmap_invalidate_all_mode, (
 	return (pmap_invalidate_all_nopcid);
 }
 
+static void
+pmap_invalidate_all_curcpu_cb(pmap_t pmap, vm_offset_t addr1 __unused,
+    vm_offset_t addr2 __unused)
+{
+
+	pmap_invalidate_all_mode(pmap);
+}
+
 void
 pmap_invalidate_all(pmap_t pmap)
 {
@@ -2638,20 +2657,23 @@ pmap_invalidate_all(pmap_t pmap)
 	KASSERT(pmap->pm_type == PT_X86,
 	    ("pmap_invalidate_all: invalid type %d", pmap->pm_type));
 
-	sched_pin();
-	pmap_invalidate_all_mode(pmap);
-	smp_masked_invltlb(pmap_invalidate_cpu_mask(pmap), pmap);
-	sched_unpin();
+	smp_masked_invltlb(pmap_invalidate_cpu_mask(pmap), pmap,
+	    pmap_invalidate_all_curcpu_cb);
 }
 
+static void
+pmap_invalidate_cache_curcpu_cb(pmap_t pmap __unused, vm_offset_t va __unused,
+    vm_offset_t addr2 __unused)
+{
+
+	wbinvd();
+}
+
 void
 pmap_invalidate_cache(void)
 {
 
-	sched_pin();
-	wbinvd();
-	smp_cache_flush();
-	sched_unpin();
+	smp_cache_flush(pmap_invalidate_cache_curcpu_cb);
 }
 
 struct pde_action {

Modified: stable/12/sys/i386/i386/pmap.c
==============================================================================
--- stable/12/sys/i386/i386/pmap.c	Wed Jun 24 05:12:00 2020	(r362571)
+++ stable/12/sys/i386/i386/pmap.c	Wed Jun 24 06:35:50 2020	(r362572)
@@ -1164,6 +1164,13 @@ invltlb_glob(void)
 
 
 #ifdef SMP
+
+static void
+pmap_curcpu_cb_dummy(pmap_t pmap __unused, vm_offset_t addr1 __unused,
+    vm_offset_t addr2 __unused)
+{
+}
+
 /*
  * For SMP, these functions have to use the IPI mechanism for coherence.
  *
@@ -1202,7 +1209,7 @@ pmap_invalidate_page(pmap_t pmap, vm_offset_t va)
 		CPU_AND(&other_cpus, &pmap->pm_active);
 		mask = &other_cpus;
 	}
-	smp_masked_invlpg(*mask, va, pmap);
+	smp_masked_invlpg(*mask, va, pmap, pmap_curcpu_cb_dummy);
 	sched_unpin();
 }
 
@@ -1235,7 +1242,7 @@ pmap_invalidate_range(pmap_t pmap, vm_offset_t sva, vm
 		CPU_AND(&other_cpus, &pmap->pm_active);
 		mask = &other_cpus;
 	}
-	smp_masked_invlpg_range(*mask, sva, eva, pmap);
+	smp_masked_invlpg_range(*mask, sva, eva, pmap, pmap_curcpu_cb_dummy);
 	sched_unpin();
 }
 
@@ -1258,18 +1265,21 @@ pmap_invalidate_all(pmap_t pmap)
 		CPU_AND(&other_cpus, &pmap->pm_active);
 		mask = &other_cpus;
 	}
-	smp_masked_invltlb(*mask, pmap);
+	smp_masked_invltlb(*mask, pmap, pmap_curcpu_cb_dummy);
 	sched_unpin();
 }
 
+static void
+pmap_invalidate_cache_curcpu_cb(pmap_t pmap __unused,
+    vm_offset_t addr1 __unused, vm_offset_t addr2 __unused)
+{
+	wbinvd();
+}
+
 void
 pmap_invalidate_cache(void)
 {
-
-	sched_pin();
-	wbinvd();
-	smp_cache_flush();
-	sched_unpin();
+	smp_cache_flush(pmap_invalidate_cache_curcpu_cb);
 }
 
 struct pde_action {

Modified: stable/12/sys/i386/i386/vm_machdep.c
==============================================================================
--- stable/12/sys/i386/i386/vm_machdep.c	Wed Jun 24 05:12:00 2020	(r362571)
+++ stable/12/sys/i386/i386/vm_machdep.c	Wed Jun 24 06:35:50 2020	(r362572)
@@ -615,6 +615,12 @@ sf_buf_map(struct sf_buf *sf, int flags)
 }
 
 #ifdef SMP
+static void
+sf_buf_shootdown_curcpu_cb(pmap_t pmap __unused,
+    vm_offset_t addr1 __unused, vm_offset_t addr2 __unused)
+{
+}
+
 void
 sf_buf_shootdown(struct sf_buf *sf, int flags)
 {
@@ -633,7 +639,8 @@ sf_buf_shootdown(struct sf_buf *sf, int flags)
 		CPU_NAND(&other_cpus, &sf->cpumask);
 		if (!CPU_EMPTY(&other_cpus)) {
 			CPU_OR(&sf->cpumask, &other_cpus);
-			smp_masked_invlpg(other_cpus, sf->kva, kernel_pmap);
+			smp_masked_invlpg(other_cpus, sf->kva, kernel_pmap,
+			    sf_buf_shootdown_curcpu_cb);
 		}
 	}
 	sched_unpin();

Modified: stable/12/sys/x86/include/x86_smp.h
==============================================================================
--- stable/12/sys/x86/include/x86_smp.h	Wed Jun 24 05:12:00 2020	(r362571)
+++ stable/12/sys/x86/include/x86_smp.h	Wed Jun 24 06:35:50 2020	(r362572)
@@ -80,6 +80,9 @@ inthand_t
 	IDTVEC(cpususpend),	/* CPU suspends & waits to be resumed */
 	IDTVEC(rendezvous);	/* handle CPU rendezvous */
 
+typedef void (*smp_invl_cb_t)(struct pmap *, vm_offset_t addr1,
+    vm_offset_t addr2);
+
 /* functions in x86_mp.c */
 void	assign_cpu_ids(void);
 void	cpu_add(u_int apic_id, char boot_cpu);
@@ -99,11 +102,13 @@ void	ipi_cpu(int cpu, u_int ipi);
 int	ipi_nmi_handler(void);
 void	ipi_selected(cpuset_t cpus, u_int ipi);
 void	set_interrupt_apic_ids(void);
-void	smp_cache_flush(void);
-void	smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, struct pmap *pmap);
+void	smp_cache_flush(smp_invl_cb_t curcpu_cb);
+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);
-void	smp_masked_invltlb(cpuset_t mask, struct pmap *pmap);
+	    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);
 void	ipi_send_cpu(int cpu, u_int ipi);

Modified: stable/12/sys/x86/x86/mp_x86.c
==============================================================================
--- stable/12/sys/x86/x86/mp_x86.c	Wed Jun 24 05:12:00 2020	(r362571)
+++ stable/12/sys/x86/x86/mp_x86.c	Wed Jun 24 06:35:50 2020	(r362572)
@@ -1613,29 +1613,48 @@ volatile uint32_t smp_tlb_generation;
 #define	read_eflags() read_rflags()
 #endif
 
+/*
+ * Used by pmap to request invalidation of TLB or cache on local and
+ * remote processors.  Mask provides the set of remote CPUs which are
+ * to be signalled with the IPI specified by vector.  The curcpu_cb
+ * callback is invoked on the calling CPU while waiting for remote
+ * CPUs to complete the operation.
+ *
+ * The callback function is called unconditionally on the caller's
+ * underlying processor, even when this processor is not set in the
+ * mask.  So, the callback function must be prepared to handle such
+ * spurious invocations.
+ */
 static void
 smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector, pmap_t pmap,
-    vm_offset_t addr1, vm_offset_t addr2)
+    vm_offset_t addr1, vm_offset_t addr2, smp_invl_cb_t curcpu_cb)
 {
 	cpuset_t other_cpus;
 	volatile uint32_t *p_cpudone;
 	uint32_t generation;
 	int cpu;
 
-	/* It is not necessary to signal other CPUs while in the debugger. */
-	if (kdb_active || panicstr != NULL)
+	/*
+	 * It is not necessary to signal other CPUs while booting or
+	 * when in the debugger.
+	 */
+	if (kdb_active || panicstr != NULL || !smp_started) {
+		curcpu_cb(pmap, addr1, addr2);
 		return;
+	}
 
+	sched_pin();
+
 	/*
 	 * Check for other cpus.  Return if none.
 	 */
 	if (CPU_ISFULLSET(&mask)) {
 		if (mp_ncpus <= 1)
-			return;
+			goto nospinexit;
 	} else {
 		CPU_CLR(PCPU_GET(cpuid), &mask);
 		if (CPU_EMPTY(&mask))
-			return;
+			goto nospinexit;
 	}
 
 	if (!(read_eflags() & PSL_I))
@@ -1659,6 +1678,7 @@ smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector
 			ipi_send_cpu(cpu, vector);
 		}
 	}
+	curcpu_cb(pmap, addr1, addr2);
 	while ((cpu = CPU_FFS(&other_cpus)) != 0) {
 		cpu--;
 		CPU_CLR(cpu, &other_cpus);
@@ -1667,55 +1687,54 @@ smp_targeted_tlb_shootdown(cpuset_t mask, u_int vector
 			ia32_pause();
 	}
 	mtx_unlock_spin(&smp_ipi_mtx);
+	sched_unpin();
+	return;
+
+nospinexit:
+	curcpu_cb(pmap, addr1, addr2);
+	sched_unpin();
 }
 
 void
-smp_masked_invltlb(cpuset_t mask, pmap_t pmap)
+smp_masked_invltlb(cpuset_t mask, pmap_t pmap, smp_invl_cb_t curcpu_cb)
 {
 
-	if (smp_started) {
-		smp_targeted_tlb_shootdown(mask, IPI_INVLTLB, pmap, 0, 0);
+	smp_targeted_tlb_shootdown(mask, IPI_INVLTLB, pmap, 0, 0, curcpu_cb);
 #ifdef COUNT_XINVLTLB_HITS
-		ipi_global++;
+	ipi_global++;
 #endif
-	}
 }
 
 void
-smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, pmap_t pmap)
+smp_masked_invlpg(cpuset_t mask, vm_offset_t addr, pmap_t pmap,
+    smp_invl_cb_t curcpu_cb)
 {
 
-	if (smp_started) {
-		smp_targeted_tlb_shootdown(mask, IPI_INVLPG, pmap, addr, 0);
+	smp_targeted_tlb_shootdown(mask, IPI_INVLPG, pmap, addr, 0, curcpu_cb);
 #ifdef COUNT_XINVLTLB_HITS
-		ipi_page++;
+	ipi_page++;
 #endif
-	}
 }
 
 void
 smp_masked_invlpg_range(cpuset_t mask, vm_offset_t addr1, vm_offset_t addr2,
-    pmap_t pmap)
+    pmap_t pmap, smp_invl_cb_t curcpu_cb)
 {
 
-	if (smp_started) {
-		smp_targeted_tlb_shootdown(mask, IPI_INVLRNG, pmap,
-		    addr1, addr2);
+	smp_targeted_tlb_shootdown(mask, IPI_INVLRNG, pmap, addr1, addr2,
+	    curcpu_cb);
 #ifdef COUNT_XINVLTLB_HITS
-		ipi_range++;
-		ipi_range_size += (addr2 - addr1) / PAGE_SIZE;
+	ipi_range++;
+	ipi_range_size += (addr2 - addr1) / PAGE_SIZE;
 #endif
-	}
 }
 
 void
-smp_cache_flush(void)
+smp_cache_flush(smp_invl_cb_t curcpu_cb)
 {
 
-	if (smp_started) {
-		smp_targeted_tlb_shootdown(all_cpus, IPI_INVLCACHE, NULL,
-		    0, 0);
-	}
+	smp_targeted_tlb_shootdown(all_cpus, IPI_INVLCACHE, NULL, 0, 0,
+	    curcpu_cb);
 }
 
 /*


More information about the svn-src-stable mailing list