DragonFlyBSD Kernel Audit
DF-0941 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/subr_cpu_topology.c b/sys/kern/subr_cpu_topology.c
--- a/sys/kern/subr_cpu_topology.c
+++ b/sys/kern/subr_cpu_topology.c
@@ -78,11 +78,11 @@
 
 MALLOC_DEFINE(M_PCPUSYS, "pcpusys", "pcpu sysctl topology");
 
-SYSCTL_INT(_hw, OID_AUTO, cpu_topology_ht_ids, CTLFLAG_RW,
+SYSCTL_INT(_hw, OID_AUTO, cpu_topology_ht_ids, CTLFLAG_RD,
 	   &cpu_topology_ht_ids, 0, "# of logical cores per real core");
-SYSCTL_INT(_hw, OID_AUTO, cpu_topology_core_ids, CTLFLAG_RW,
+SYSCTL_INT(_hw, OID_AUTO, cpu_topology_core_ids, CTLFLAG_RD,
 	   &cpu_topology_core_ids, 0, "# of real cores per package");
-SYSCTL_INT(_hw, OID_AUTO, cpu_topology_phys_ids, CTLFLAG_RW,
+SYSCTL_INT(_hw, OID_AUTO, cpu_topology_phys_ids, CTLFLAG_RD,
 	   &cpu_topology_phys_ids, 0, "# of physical packages");
 
 /* Get the next valid apicid starting
diff --git a/sys/vm/vm_page.c b/sys/vm/vm_page.c
--- a/sys/vm/vm_page.c
+++ b/sys/vm/vm_page.c
@@ -1192,7 +1192,9 @@
 	 */
 	object_pg_color = object ? object->pg_color : 0;
 
-	if (cpu_topology_ht_ids) {
+	if (cpu_topology_ht_ids > 0 &&
+	    cpu_topology_core_ids > 0 &&
+	    cpu_topology_phys_ids > 0) {
 		int phys_id;
 		int core_id;
 		int ht_id;
@@ -1226,6 +1228,14 @@
 		grpscale = physcale / cpu_topology_core_ids;
 		cpuscale = grpscale / cpu_topology_ht_ids;
 
+		/*
+		 * If the topology is too wide for PQ_L2_SIZE cpuscale
+		 * collapses to zero and the modulo below would divide by
+		 * zero.  Fall back to the simple distribution.
+		 */
+		if (cpuscale == 0)
+			goto simple;
+
 		pg_color = phys_id * physcale;
 		pg_color += core_id * grpscale;
 		pg_color += ht_id * cpuscale;
@@ -1247,6 +1257,8 @@
 		}
 #endif
 	} else {
+	simple:
+		;
 		/*
 		 * Unknown topology, distribute things evenly.
 		 *