git: 8882b7852acf - main - add pmap_active_cpus()

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Wed, 23 Aug 2023 00:07:35 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=8882b7852acf2588d87ccb6d4c6bf7694511fc56

commit 8882b7852acf2588d87ccb6d4c6bf7694511fc56
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-10-07 22:25:54 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2023-08-23 00:02:21 +0000

    add pmap_active_cpus()
    
    For amd64, i386, arm, and riscv, i.e. all architectures except arm64,
    the custom implementation is provided since we maintain the bitmask of
    active CPUs anyway.
    
    Arm64 uses somewhat naive iteration over CPUs and match current vmspace'
    pmap with the argument. It is not guaranteed that vmspace->pmap is the
    same as the active pmap, but the inaccuracy should be toleratable.
    
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D32360
---
 sys/amd64/amd64/pmap.c              |  6 ++++++
 sys/arm/arm/pmap-v6.c               |  6 ++++++
 sys/arm64/include/pmap.h            |  2 ++
 sys/i386/i386/pmap_base.c           |  6 ++++++
 sys/powerpc/powerpc/pmap_dispatch.c |  6 ++++++
 sys/riscv/riscv/pmap.c              |  6 ++++++
 sys/vm/pmap.h                       |  2 ++
 sys/vm/vm_kern.c                    | 26 ++++++++++++++++++++++++++
 8 files changed, 60 insertions(+)

diff --git a/sys/amd64/amd64/pmap.c b/sys/amd64/amd64/pmap.c
index c7151fa59b91..b10997fd657b 100644
--- a/sys/amd64/amd64/pmap.c
+++ b/sys/amd64/amd64/pmap.c
@@ -10256,6 +10256,12 @@ pmap_activate_boot(pmap_t pmap)
 	PCPU_SET(ucr3, PMAP_NO_CR3);
 }
 
+void
+pmap_active_cpus(pmap_t pmap, cpuset_t *res)
+{
+	*res = pmap->pm_active;
+}
+
 void
 pmap_sync_icache(pmap_t pm, vm_offset_t va, vm_size_t sz)
 {
diff --git a/sys/arm/arm/pmap-v6.c b/sys/arm/arm/pmap-v6.c
index 5aa8eb169cad..719851432203 100644
--- a/sys/arm/arm/pmap-v6.c
+++ b/sys/arm/arm/pmap-v6.c
@@ -6194,6 +6194,12 @@ pmap_activate(struct thread *td)
 	critical_exit();
 }
 
+void
+pmap_active_cpus(pmap_t pmap, cpuset_t *res)
+{
+	*res = pmap->pm_active;
+}
+
 /*
  * Perform the pmap work for mincore(2).  If the page is not both referenced and
  * modified by this pmap, returns its physical address so that the caller can
diff --git a/sys/arm64/include/pmap.h b/sys/arm64/include/pmap.h
index fd8dc8d33f38..1789588210c3 100644
--- a/sys/arm64/include/pmap.h
+++ b/sys/arm64/include/pmap.h
@@ -129,6 +129,8 @@ extern struct pmap	kernel_pmap_store;
 	(uint64_t)(asid) << TTBR_ASID_SHIFT;			\
 })
 
+#define	PMAP_WANT_ACTIVE_CPUS_NAIVE
+
 extern vm_offset_t virtual_avail;
 extern vm_offset_t virtual_end;
 
diff --git a/sys/i386/i386/pmap_base.c b/sys/i386/i386/pmap_base.c
index b0c3413d1735..50229ee40caa 100644
--- a/sys/i386/i386/pmap_base.c
+++ b/sys/i386/i386/pmap_base.c
@@ -944,6 +944,12 @@ pmap_kremove(vm_offset_t va)
 	pmap_methods_ptr->pm_kremove(va);
 }
 
+void
+pmap_active_cpus(pmap_t pmap, cpuset_t *res)
+{
+	*res = pmap->pm_active;
+}
+
 extern struct pmap_methods pmap_pae_methods, pmap_nopae_methods;
 int pae_mode;
 SYSCTL_INT(_vm_pmap, OID_AUTO, pae_mode, CTLFLAG_RDTUN | CTLFLAG_NOFETCH,
diff --git a/sys/powerpc/powerpc/pmap_dispatch.c b/sys/powerpc/powerpc/pmap_dispatch.c
index ebf81551fa07..3f1ac937433f 100644
--- a/sys/powerpc/powerpc/pmap_dispatch.c
+++ b/sys/powerpc/powerpc/pmap_dispatch.c
@@ -253,3 +253,9 @@ pmap_is_valid_memattr(pmap_t pmap __unused, vm_memattr_t mode)
 		return (FALSE);
 	}
 }
+
+void
+pmap_active_cpus(pmap_t pmap, cpuset_t *res)
+{
+	*res = pmap->pm_active;
+}
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index 20e6ccd22b62..49ee54b37918 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -4687,6 +4687,12 @@ pmap_activate_boot(pmap_t pmap)
 	PCPU_SET(curpmap, pmap);
 }
 
+void
+pmap_active_cpus(pmap_t pmap, cpuset_t *res)
+{
+	*res = pmap->pm_active;
+}
+
 void
 pmap_sync_icache(pmap_t pmap, vm_offset_t va, vm_size_t sz)
 {
diff --git a/sys/vm/pmap.h b/sys/vm/pmap.h
index 7272882132e0..65e909df9b8f 100644
--- a/sys/vm/pmap.h
+++ b/sys/vm/pmap.h
@@ -90,6 +90,7 @@ typedef struct pmap_statistics *pmap_statistics_t;
 #include <machine/pmap.h>
 
 #ifdef _KERNEL
+#include <sys/_cpuset.h>
 struct thread;
 
 /*
@@ -118,6 +119,7 @@ extern vm_offset_t kernel_vm_end;
 #define	PMAP_TS_REFERENCED_MAX	5
 
 void		 pmap_activate(struct thread *td);
+void		 pmap_active_cpus(pmap_t pmap, cpuset_t *res);
 void		 pmap_advise(pmap_t pmap, vm_offset_t sva, vm_offset_t eva,
 		    int advice);
 void		 pmap_align_superpage(vm_object_t, vm_ooffset_t, vm_offset_t *,
diff --git a/sys/vm/vm_kern.c b/sys/vm/vm_kern.c
index c3695b5c94eb..f94200d77c47 100644
--- a/sys/vm/vm_kern.c
+++ b/sys/vm/vm_kern.c
@@ -78,6 +78,7 @@
 #include <sys/msan.h>
 #include <sys/proc.h>
 #include <sys/rwlock.h>
+#include <sys/smp.h>
 #include <sys/sysctl.h>
 #include <sys/vmem.h>
 #include <sys/vmmeter.h>
@@ -907,6 +908,31 @@ kmem_bootstrap_free(vm_offset_t start, vm_size_t size)
 #endif
 }
 
+#ifdef PMAP_WANT_ACTIVE_CPUS_NAIVE
+void
+pmap_active_cpus(pmap_t pmap, cpuset_t *res)
+{
+	struct thread *td;
+	struct proc *p;
+	struct vmspace *vm;
+	int c;
+
+	CPU_ZERO(res);
+	CPU_FOREACH(c) {
+		td = cpuid_to_pcpu[c]->pc_curthread;
+		p = td->td_proc;
+		if (p == NULL)
+			continue;
+		vm = vmspace_acquire_ref(p);
+		if (vm == NULL)
+			continue;
+		if (pmap == vmspace_pmap(vm))
+			CPU_SET(c, res);
+		vmspace_free(vm);
+	}
+}
+#endif
+
 /*
  * Allow userspace to directly trigger the VM drain routine for testing
  * purposes.