Mon Jan 13 20:30:08 2020 UTC ()
Fix some more bugs in the topo stuff, that prevented it from working
properly with fake topo info + MP.


(ad)
diff -r1.10 -r1.11 src/sys/kern/subr_cpu.c

cvs diff -r1.10 -r1.11 src/sys/kern/subr_cpu.c (expand / switch to unified diff)

--- src/sys/kern/subr_cpu.c 2020/01/13 02:18:13 1.10
+++ src/sys/kern/subr_cpu.c 2020/01/13 20:30:08 1.11
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: subr_cpu.c,v 1.10 2020/01/13 02:18:13 mrg Exp $ */ 1/* $NetBSD: subr_cpu.c,v 1.11 2020/01/13 20:30:08 ad Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 2007, 2008, 2009, 2010, 2012, 2019, 2020 4 * Copyright (c) 2007, 2008, 2009, 2010, 2012, 2019, 2020
5 * The NetBSD Foundation, Inc. 5 * The NetBSD Foundation, Inc.
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to The NetBSD Foundation 8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Andrew Doran. 9 * by Andrew Doran.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -51,27 +51,27 @@ @@ -51,27 +51,27 @@
51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 51 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 52 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 53 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 54 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 55 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE. 56 * SUCH DAMAGE.
57 */ 57 */
58 58
59/* 59/*
60 * CPU related routines shared with rump. 60 * CPU related routines shared with rump.
61 */ 61 */
62 62
63#include <sys/cdefs.h> 63#include <sys/cdefs.h>
64__KERNEL_RCSID(0, "$NetBSD: subr_cpu.c,v 1.10 2020/01/13 02:18:13 mrg Exp $"); 64__KERNEL_RCSID(0, "$NetBSD: subr_cpu.c,v 1.11 2020/01/13 20:30:08 ad Exp $");
65 65
66#include <sys/param.h> 66#include <sys/param.h>
67#include <sys/systm.h> 67#include <sys/systm.h>
68#include <sys/sched.h> 68#include <sys/sched.h>
69#include <sys/conf.h> 69#include <sys/conf.h>
70#include <sys/cpu.h> 70#include <sys/cpu.h>
71#include <sys/proc.h> 71#include <sys/proc.h>
72#include <sys/kernel.h> 72#include <sys/kernel.h>
73#include <sys/kmem.h> 73#include <sys/kmem.h>
74 74
75static void cpu_topology_fake1(struct cpu_info *); 75static void cpu_topology_fake1(struct cpu_info *);
76 76
77kmutex_t cpu_lock __cacheline_aligned; 77kmutex_t cpu_lock __cacheline_aligned;
@@ -226,104 +226,109 @@ cpu_topology_fake1(struct cpu_info *ci) @@ -226,104 +226,109 @@ cpu_topology_fake1(struct cpu_info *ci)
226{ 226{
227 enum cpu_rel rel; 227 enum cpu_rel rel;
228 228
229 for (rel = 0; rel < __arraycount(ci->ci_sibling); rel++) { 229 for (rel = 0; rel < __arraycount(ci->ci_sibling); rel++) {
230 ci->ci_sibling[rel] = ci; 230 ci->ci_sibling[rel] = ci;
231 ci->ci_nsibling[rel] = 1; 231 ci->ci_nsibling[rel] = 1;
232 } 232 }
233 if (!cpu_topology_present) { 233 if (!cpu_topology_present) {
234 ci->ci_package_id = cpu_index(ci); 234 ci->ci_package_id = cpu_index(ci);
235 } 235 }
236 ci->ci_schedstate.spc_flags |= 236 ci->ci_schedstate.spc_flags |=
237 (SPCF_CORE1ST | SPCF_PACKAGE1ST | SPCF_1STCLASS); 237 (SPCF_CORE1ST | SPCF_PACKAGE1ST | SPCF_1STCLASS);
238 ci->ci_package1st = ci; 238 ci->ci_package1st = ci;
 239 ci->ci_is_slow = false;
 240 cpu_topology_haveslow = false;
239} 241}
240 242
241/* 243/*
242 * Fake up topology info if we have none, or if what we got was bogus. 244 * Fake up topology info if we have none, or if what we got was bogus.
243 * Don't override ci_package_id, etc, if cpu_topology_present is set. 245 * Don't override ci_package_id, etc, if cpu_topology_present is set.
244 * MD code also uses these. 246 * MD code also uses these.
245 */ 247 */
246static void 248static void
247cpu_topology_fake(void) 249cpu_topology_fake(void)
248{ 250{
249 CPU_INFO_ITERATOR cii; 251 CPU_INFO_ITERATOR cii;
250 struct cpu_info *ci; 252 struct cpu_info *ci;
251 253
252 for (CPU_INFO_FOREACH(cii, ci)) { 254 for (CPU_INFO_FOREACH(cii, ci)) {
253 cpu_topology_fake1(ci); 255 cpu_topology_fake1(ci);
 256 /* Undo (early boot) flag set so everything links OK. */
 257 ci->ci_schedstate.spc_flags &=
 258 ~(SPCF_CORE1ST | SPCF_PACKAGE1ST | SPCF_1STCLASS);
254 } 259 }
255 cpu_topology_dump(); 260}
256 } 
257 261
258/* 262/*
259 * Fix up basic CPU topology info. Right now that means attach each CPU to 263 * Fix up basic CPU topology info. Right now that means attach each CPU to
260 * circular lists of its siblings in the same core, and in the same package.  264 * circular lists of its siblings in the same core, and in the same package.
261 */ 265 */
262void 266void
263cpu_topology_init(void) 267cpu_topology_init(void)
264{ 268{
265 CPU_INFO_ITERATOR cii, cii2; 269 CPU_INFO_ITERATOR cii, cii2;
266 struct cpu_info *ci, *ci2, *ci3; 270 struct cpu_info *ci, *ci2, *ci3;
267 u_int minsmt, mincore; 271 u_int minsmt, mincore;
268 272
269 if (!cpu_topology_present) { 273 if (!cpu_topology_present) {
270 cpu_topology_fake(); 274 cpu_topology_fake();
271 return; 275 goto linkit;
272 } 276 }
273 277
274 /* Find siblings in same core and package. */ 278 /* Find siblings in same core and package. */
275 for (CPU_INFO_FOREACH(cii, ci)) { 279 for (CPU_INFO_FOREACH(cii, ci)) {
276 ci->ci_schedstate.spc_flags &= 280 ci->ci_schedstate.spc_flags &=
277 ~(SPCF_CORE1ST | SPCF_PACKAGE1ST | SPCF_1STCLASS); 281 ~(SPCF_CORE1ST | SPCF_PACKAGE1ST | SPCF_1STCLASS);
278 for (CPU_INFO_FOREACH(cii2, ci2)) { 282 for (CPU_INFO_FOREACH(cii2, ci2)) {
279 /* Avoid bad things happening. */ 283 /* Avoid bad things happening. */
280 if (ci2->ci_package_id == ci->ci_package_id && 284 if (ci2->ci_package_id == ci->ci_package_id &&
281 ci2->ci_core_id == ci->ci_core_id && 285 ci2->ci_core_id == ci->ci_core_id &&
282 ci2->ci_smt_id == ci->ci_smt_id && 286 ci2->ci_smt_id == ci->ci_smt_id &&
283 ci2 != ci) { 287 ci2 != ci) {
284#ifdef DEBUG 288#ifdef DEBUG
285 printf("cpu%u %p pkg %u core %u smt %u same as " 289 printf("cpu%u %p pkg %u core %u smt %u same as "
286 "cpu%u %p pkg %u core %u smt %u\n",  290 "cpu%u %p pkg %u core %u smt %u\n",
287 cpu_index(ci), ci, ci->ci_package_id, 291 cpu_index(ci), ci, ci->ci_package_id,
288 ci->ci_core_id, ci->ci_smt_id, 292 ci->ci_core_id, ci->ci_smt_id,
289 cpu_index(ci2), ci2, ci2->ci_package_id, 293 cpu_index(ci2), ci2, ci2->ci_package_id,
290 ci2->ci_core_id, ci2->ci_smt_id); 294 ci2->ci_core_id, ci2->ci_smt_id);
291#endif 295#endif
292 printf("cpu_topology_init: info bogus, " 296 printf("cpu_topology_init: info bogus, "
293 "faking it\n"); 297 "faking it\n");
294 cpu_topology_fake(); 298 cpu_topology_fake();
295 return; 299 goto linkit;
296 } 300 }
297 if (ci2 == ci || 301 if (ci2 == ci ||
298 ci2->ci_package_id != ci->ci_package_id) { 302 ci2->ci_package_id != ci->ci_package_id) {
299 continue; 303 continue;
300 } 304 }
301 /* Find CPUs in the same core. */ 305 /* Find CPUs in the same core. */
302 if (ci->ci_nsibling[CPUREL_CORE] == 1 && 306 if (ci->ci_nsibling[CPUREL_CORE] == 1 &&
303 ci->ci_core_id == ci2->ci_core_id) { 307 ci->ci_core_id == ci2->ci_core_id) {
304 cpu_topology_link(ci, ci2, CPUREL_CORE); 308 cpu_topology_link(ci, ci2, CPUREL_CORE);
305 } 309 }
306 /* Find CPUs in the same package. */ 310 /* Find CPUs in the same package. */
307 if (ci->ci_nsibling[CPUREL_PACKAGE] == 1) { 311 if (ci->ci_nsibling[CPUREL_PACKAGE] == 1) {
308 cpu_topology_link(ci, ci2, CPUREL_PACKAGE); 312 cpu_topology_link(ci, ci2, CPUREL_PACKAGE);
309 } 313 }
310 if (ci->ci_nsibling[CPUREL_CORE] > 1 && 314 if (ci->ci_nsibling[CPUREL_CORE] > 1 &&
311 ci->ci_nsibling[CPUREL_PACKAGE] > 1) { 315 ci->ci_nsibling[CPUREL_PACKAGE] > 1) {
312 break; 316 break;
313 } 317 }
314 } 318 }
315 } 319 }
316 320
 321 linkit:
317 /* Identify lowest numbered SMT in each core. */ 322 /* Identify lowest numbered SMT in each core. */
318 for (CPU_INFO_FOREACH(cii, ci)) { 323 for (CPU_INFO_FOREACH(cii, ci)) {
319 ci2 = ci3 = ci; 324 ci2 = ci3 = ci;
320 minsmt = ci->ci_smt_id; 325 minsmt = ci->ci_smt_id;
321 do { 326 do {
322 if (ci2->ci_smt_id < minsmt) { 327 if (ci2->ci_smt_id < minsmt) {
323 ci3 = ci2; 328 ci3 = ci2;
324 minsmt = ci2->ci_smt_id; 329 minsmt = ci2->ci_smt_id;
325 } 330 }
326 ci2 = ci2->ci_sibling[CPUREL_CORE]; 331 ci2 = ci2->ci_sibling[CPUREL_CORE];
327 } while (ci2 != ci); 332 } while (ci2 != ci);
328 ci3->ci_schedstate.spc_flags |= SPCF_CORE1ST; 333 ci3->ci_schedstate.spc_flags |= SPCF_CORE1ST;
329 } 334 }
@@ -348,27 +353,27 @@ cpu_topology_init(void) @@ -348,27 +353,27 @@ cpu_topology_init(void)
348 353
349 if ((ci3->ci_schedstate.spc_flags & SPCF_PACKAGE1ST) != 0) { 354 if ((ci3->ci_schedstate.spc_flags & SPCF_PACKAGE1ST) != 0) {
350 /* Already identified - nothing more to do. */ 355 /* Already identified - nothing more to do. */
351 continue; 356 continue;
352 } 357 }
353 ci3->ci_schedstate.spc_flags |= SPCF_PACKAGE1ST; 358 ci3->ci_schedstate.spc_flags |= SPCF_PACKAGE1ST;
354 359
355 /* Walk through all CPUs in package and point to first. */ 360 /* Walk through all CPUs in package and point to first. */
356 ci2 = ci3; 361 ci2 = ci3;
357 do { 362 do {
358 ci2->ci_package1st = ci3; 363 ci2->ci_package1st = ci3;
359 ci2->ci_sibling[CPUREL_PACKAGE1ST] = ci3; 364 ci2->ci_sibling[CPUREL_PACKAGE1ST] = ci3;
360 ci2 = ci2->ci_sibling[CPUREL_PACKAGE]; 365 ci2 = ci2->ci_sibling[CPUREL_PACKAGE];
361 } while (ci2 != ci); 366 } while (ci2 != ci3);
362 367
363 /* Now look for somebody else to link to. */ 368 /* Now look for somebody else to link to. */
364 for (CPU_INFO_FOREACH(cii2, ci2)) { 369 for (CPU_INFO_FOREACH(cii2, ci2)) {
365 if ((ci2->ci_schedstate.spc_flags & SPCF_PACKAGE1ST) 370 if ((ci2->ci_schedstate.spc_flags & SPCF_PACKAGE1ST)
366 != 0 && ci2 != ci3) { 371 != 0 && ci2 != ci3) {
367 cpu_topology_link(ci3, ci2, CPUREL_PACKAGE1ST); 372 cpu_topology_link(ci3, ci2, CPUREL_PACKAGE1ST);
368 break; 373 break;
369 } 374 }
370 } 375 }
371 } 376 }
372 377
373 /* Walk through all packages, starting with value of ci3 from above. */ 378 /* Walk through all packages, starting with value of ci3 from above. */
374 KASSERT(ci3 != NULL); 379 KASSERT(ci3 != NULL);