git: f627ff51b76c - main - riscv/pmap.c: Don't pass hartid map to 'smp_rendezvous_cpus'

From: Bojan Novković <bnovkov_at_FreeBSD.org>
Date: Sat, 10 Oct 2026 12:36:52 UTC
The branch main has been updated by bnovkov:

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

commit f627ff51b76c728b8c6c4a7e5490ce3803c562ad
Author:     Bojan Novković <bnovkov@FreeBSD.org>
AuthorDate: 2026-09-27 18:25:22 +0000
Commit:     Bojan Novković <bnovkov@FreeBSD.org>
CommitDate: 2026-10-10 12:34:57 +0000

    riscv/pmap.c: Don't pass hartid map to 'smp_rendezvous_cpus'
    
    The pm_active bitmask is indexed by hart IDs which can differ from
    CPU IDs. `pmap_invalidate_range_svinval` assumes that the map is
    indexed by CPU IDs, which is wrong and causes remote TLB invalidations
    on unrelated CPUs.
    
    Fix this by adding a routine that converts a hart-indexed bitmask
    to a CPU ID-indexed bitmask. While we're here, fix a similar issue
    in `pmap_active_cpus`.
    
    Fixes:  99360212c739 ("riscv/pmap.c: Add an Svinval-aware variant of pmap_invalidate_range")
    Reported by:    markj
    Reviewed by:    markj, mhorne
    Differential Revision:  https://reviews.freebsd.org/D60072
---
 sys/riscv/include/cpu.h      |  3 +++
 sys/riscv/include/smp.h      |  1 -
 sys/riscv/riscv/mp_machdep.c | 39 +++++++++++++++++++++++++++++++--------
 sys/riscv/riscv/pmap.c       | 11 ++++++-----
 4 files changed, 40 insertions(+), 14 deletions(-)

diff --git a/sys/riscv/include/cpu.h b/sys/riscv/include/cpu.h
index 59214f05f595..05d3c4c834a5 100644
--- a/sys/riscv/include/cpu.h
+++ b/sys/riscv/include/cpu.h
@@ -36,6 +36,8 @@
 #define	_MACHINE_CPU_H_
 
 #ifndef LOCORE
+#include <sys/_cpuset.h>
+
 #include <machine/atomic.h>
 #include <machine/cpufunc.h>
 #include <machine/frame.h>
@@ -105,6 +107,7 @@ void	cpu_reset(void) __dead2;
 void	fork_trampoline(void);
 void	identify_cpu(u_int cpu);
 void	printcpuinfo(u_int cpu);
+cpuset_t hartmask_to_cpumask(const cpuset_t);
 
 static __inline uint64_t
 get_cyclecount(void)
diff --git a/sys/riscv/include/smp.h b/sys/riscv/include/smp.h
index 863f0bbd6d21..bc1f77f32135 100644
--- a/sys/riscv/include/smp.h
+++ b/sys/riscv/include/smp.h
@@ -50,5 +50,4 @@ enum {
 void ipi_all_but_self(u_int ipi);
 void ipi_cpu(int cpu, u_int ipi);
 void ipi_selected(cpuset_t cpus, u_int ipi);
-
 #endif /* !_MACHINE_SMP_H_ */
diff --git a/sys/riscv/riscv/mp_machdep.c b/sys/riscv/riscv/mp_machdep.c
index 5402c6d388ed..1d5c85f8b13a 100644
--- a/sys/riscv/riscv/mp_machdep.c
+++ b/sys/riscv/riscv/mp_machdep.c
@@ -110,6 +110,19 @@ static volatile int aps_ready;
 /* Temporary variables for init_secondary()  */
 void *dpcpu[MAXCPU - 1];
 
+static u_int
+hartid_to_cpuid(u_int hart)
+{
+	u_int cpuid;
+
+	cpuid = hart;
+	if (cpuid < boot_hart)
+		cpuid += mp_maxid + 1;
+	cpuid -= boot_hart;
+
+	return (cpuid);
+}
+
 static void
 release_aps(void *dummy __unused)
 {
@@ -154,10 +167,7 @@ init_secondary(uint64_t hart)
 	u_int cpuid;
 
 	/* Renumber this cpu */
-	cpuid = hart;
-	if (cpuid < boot_hart)
-		cpuid += mp_maxid + 1;
-	cpuid -= boot_hart;
+	cpuid = hartid_to_cpuid(hart);
 
 	/* Setup the pcpu pointer */
 	pcpup = &__pcpu[cpuid];
@@ -366,10 +376,7 @@ cpu_init_fdt(u_int id, phandle_t node, u_int addr_size, pcell_t *reg)
 	 * Rotate the CPU IDs to put the boot CPU as CPU 0.
 	 * We keep the other CPUs ordered.
 	 */
-	cpuid = hart;
-	if (cpuid < boot_hart)
-		cpuid += mp_maxid + 1;
-	cpuid -= boot_hart;
+	cpuid = hartid_to_cpuid(hart);
 
 	/* Check if we are able to start this cpu */
 	if (cpuid > mp_maxid)
@@ -525,3 +532,19 @@ ipi_selected(cpuset_t cpus, u_int ipi)
 	CTR1(KTR_SMP, "ipi_selected: ipi: %x", ipi);
 	intr_ipi_send(cpus, ipi);
 }
+
+cpuset_t
+hartmask_to_cpumask(const cpuset_t harts)
+{
+	u_int hart;
+	u_int cpu;
+	cpuset_t cpumask;
+
+	CPU_ZERO(&cpumask);
+	CPU_FOREACH_ISSET(hart, &harts) {
+		cpu = hartid_to_cpuid(hart);
+		CPU_SET(cpu, &cpumask);
+	}
+
+	return (cpumask);
+}
diff --git a/sys/riscv/riscv/pmap.c b/sys/riscv/riscv/pmap.c
index b3f03eeaab9f..66dd65747f13 100644
--- a/sys/riscv/riscv/pmap.c
+++ b/sys/riscv/riscv/pmap.c
@@ -157,6 +157,7 @@
 #include <vm/vm_dumpset.h>
 #include <vm/uma.h>
 
+#include <machine/cpu.h>
 #include <machine/machdep.h>
 #include <machine/md_var.h>
 #include <machine/ifunc.h>
@@ -1149,11 +1150,11 @@ pmap_invalidate_range_svinval(pmap_t pmap, vm_offset_t sva, vm_offset_t eva)
 	args.sva = sva;
 	args.eva = eva;
 	fence();
-	if (smp_started)
-		smp_rendezvous_cpus(pmap->pm_active, smp_no_rendezvous_barrier,
-		    pmap_invalidate_range_svinval_cb,
+	if (smp_started) {
+		smp_rendezvous_cpus(hartmask_to_cpumask(pmap->pm_active),
+		    smp_no_rendezvous_barrier, pmap_invalidate_range_svinval_cb,
 		    smp_no_rendezvous_barrier, &args);
-	else
+	} else
 		pmap_invalidate_range_svinval_cb(&args);
 	sched_unpin();
 }
@@ -5323,7 +5324,7 @@ pmap_activate_boot(pmap_t pmap)
 void
 pmap_active_cpus(pmap_t pmap, cpuset_t *res)
 {
-	*res = pmap->pm_active;
+	*res = hartmask_to_cpumask(pmap->pm_active);
 }
 
 void