subr_smp.c (175057) | subr_smp.c (176734) |
---|---|
1/*- 2 * Copyright (c) 2001 3 * John Baldwin <jhb@FreeBSD.org>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 19 unchanged lines hidden (view full) --- 28 */ 29 30/* 31 * This module holds the global variables and machine independent functions 32 * used for the kernel SMP support. 33 */ 34 35#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 2001 3 * John Baldwin <jhb@FreeBSD.org>. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 19 unchanged lines hidden (view full) --- 28 */ 29 30/* 31 * This module holds the global variables and machine independent functions 32 * used for the kernel SMP support. 33 */ 34 35#include <sys/cdefs.h> |
36__FBSDID("$FreeBSD: head/sys/kern/subr_smp.c 175057 2008-01-02 17:09:15Z jhb $"); | 36__FBSDID("$FreeBSD: head/sys/kern/subr_smp.c 176734 2008-03-02 07:58:42Z jeff $"); |
37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/ktr.h> 42#include <sys/proc.h> 43#include <sys/bus.h> 44#include <sys/lock.h> --- 18 unchanged lines hidden (view full) --- 63#endif 64/* This is used in modules that need to work in both SMP and UP. */ 65cpumask_t all_cpus; 66 67int mp_ncpus; 68/* export this for libkvm consumers. */ 69int mp_maxcpus = MAXCPU; 70 | 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/ktr.h> 42#include <sys/proc.h> 43#include <sys/bus.h> 44#include <sys/lock.h> --- 18 unchanged lines hidden (view full) --- 63#endif 64/* This is used in modules that need to work in both SMP and UP. */ 65cpumask_t all_cpus; 66 67int mp_ncpus; 68/* export this for libkvm consumers. */ 69int mp_maxcpus = MAXCPU; 70 |
71struct cpu_top *smp_topology; | |
72volatile int smp_started; 73u_int mp_maxid; 74 75SYSCTL_NODE(_kern, OID_AUTO, smp, CTLFLAG_RD, NULL, "Kernel SMP"); 76 77SYSCTL_INT(_kern_smp, OID_AUTO, maxcpus, CTLFLAG_RD, &mp_maxcpus, 0, 78 "Max number of CPUs that the system was compiled for."); 79 --- 5 unchanged lines hidden (view full) --- 85SYSCTL_INT(_kern_smp, OID_AUTO, disabled, CTLFLAG_RDTUN, &smp_disabled, 0, 86 "SMP has been disabled from the loader"); 87TUNABLE_INT("kern.smp.disabled", &smp_disabled); 88 89int smp_cpus = 1; /* how many cpu's running */ 90SYSCTL_INT(_kern_smp, OID_AUTO, cpus, CTLFLAG_RD, &smp_cpus, 0, 91 "Number of CPUs online"); 92 | 71volatile int smp_started; 72u_int mp_maxid; 73 74SYSCTL_NODE(_kern, OID_AUTO, smp, CTLFLAG_RD, NULL, "Kernel SMP"); 75 76SYSCTL_INT(_kern_smp, OID_AUTO, maxcpus, CTLFLAG_RD, &mp_maxcpus, 0, 77 "Max number of CPUs that the system was compiled for."); 78 --- 5 unchanged lines hidden (view full) --- 84SYSCTL_INT(_kern_smp, OID_AUTO, disabled, CTLFLAG_RDTUN, &smp_disabled, 0, 85 "SMP has been disabled from the loader"); 86TUNABLE_INT("kern.smp.disabled", &smp_disabled); 87 88int smp_cpus = 1; /* how many cpu's running */ 89SYSCTL_INT(_kern_smp, OID_AUTO, cpus, CTLFLAG_RD, &smp_cpus, 0, 90 "Number of CPUs online"); 91 |
92int smp_topology = 0; /* Which topology we're using. */ 93SYSCTL_INT(_kern_smp, OID_AUTO, topology, CTLFLAG_RD, &smp_topology, 0, 94 "Topology override setting; 0 is default provided by hardware."); 95TUNABLE_INT("kern.smp.topology", &smp_topology); 96 |
|
93#ifdef SMP 94/* Enable forwarding of a signal to a process running on a different CPU */ 95static int forward_signal_enabled = 1; 96SYSCTL_INT(_kern_smp, OID_AUTO, forward_signal_enabled, CTLFLAG_RW, 97 &forward_signal_enabled, 0, 98 "Forwarding of a signal to a process on a different CPU"); 99 100/* Enable forwarding of roundrobin to all other cpus */ --- 279 unchanged lines hidden (view full) --- 380 381 if (teardown_func == smp_no_rendevous_barrier) 382 while (atomic_load_acq_int(&smp_rv_waiters[2]) < mp_ncpus) 383 cpu_spinwait(); 384 385 /* release lock */ 386 mtx_unlock_spin(&smp_ipi_mtx); 387} | 97#ifdef SMP 98/* Enable forwarding of a signal to a process running on a different CPU */ 99static int forward_signal_enabled = 1; 100SYSCTL_INT(_kern_smp, OID_AUTO, forward_signal_enabled, CTLFLAG_RW, 101 &forward_signal_enabled, 0, 102 "Forwarding of a signal to a process on a different CPU"); 103 104/* Enable forwarding of roundrobin to all other cpus */ --- 279 unchanged lines hidden (view full) --- 384 385 if (teardown_func == smp_no_rendevous_barrier) 386 while (atomic_load_acq_int(&smp_rv_waiters[2]) < mp_ncpus) 387 cpu_spinwait(); 388 389 /* release lock */ 390 mtx_unlock_spin(&smp_ipi_mtx); 391} |
388#else /* !SMP */ | |
389 | 392 |
390/* 391 * Provide dummy SMP support for UP kernels. Modules that need to use SMP 392 * APIs will still work using this dummy support. 393 */ 394static void 395mp_setvariables_for_up(void *dummy) | 393static struct cpu_group group[MAXCPU]; 394 395struct cpu_group * 396smp_topo(void) |
396{ | 397{ |
397 mp_ncpus = 1; 398 mp_maxid = PCPU_GET(cpuid); 399 all_cpus = PCPU_GET(cpumask); 400 KASSERT(PCPU_GET(cpuid) == 0, ("UP must have a CPU ID of zero")); | 398 struct cpu_group *top; 399 400 /* 401 * Check for a fake topology request for debugging purposes. 402 */ 403 switch (smp_topology) { 404 case 1: 405 /* Dual core with no sharing. */ 406 top = smp_topo_1level(CG_SHARE_NONE, 2, 0); 407 break; 408 case 3: 409 /* Dual core with shared L2. */ 410 top = smp_topo_1level(CG_SHARE_L2, 2, 0); 411 break; 412 case 4: 413 /* quad core, shared l3 among each package, private l2. */ 414 top = smp_topo_1level(CG_SHARE_L3, 4, 0); 415 break; 416 case 5: 417 /* quad core, 2 dualcore parts on each package share l2. */ 418 top = smp_topo_2level(CG_SHARE_NONE, 2, CG_SHARE_L2, 2, 0); 419 break; 420 case 6: 421 /* Single-core 2xHTT */ 422 top = smp_topo_1level(CG_SHARE_L1, 2, CG_FLAG_HTT); 423 break; 424 case 7: 425 /* quad core with a shared l3, 8 threads sharing L2. */ 426 top = smp_topo_2level(CG_SHARE_L3, 4, CG_SHARE_L2, 8, 427 CG_FLAG_THREAD); 428 break; 429 default: 430 /* Default, ask the system what it wants. */ 431 top = cpu_topo(); 432 break; 433 } 434 /* 435 * Verify the returned topology. 436 */ 437 if (top->cg_count != mp_ncpus) 438 panic("Built bad topology at %p. CPU count %d != %d", 439 top, top->cg_count, mp_ncpus); 440 if (top->cg_mask != all_cpus) 441 panic("Built bad topology at %p. CPU mask 0x%X != 0x%X", 442 top, top->cg_mask, all_cpus); 443 return (top); |
401} | 444} |
402SYSINIT(cpu_mp_setvariables, SI_SUB_TUNABLES, SI_ORDER_FIRST, 403 mp_setvariables_for_up, NULL) | |
404 | 445 |
446struct cpu_group * 447smp_topo_none(void) 448{ 449 struct cpu_group *top; 450 451 top = &group[0]; 452 top->cg_parent = NULL; 453 top->cg_child = NULL; 454 top->cg_mask = (1 << mp_ncpus) - 1; 455 top->cg_count = mp_ncpus; 456 top->cg_children = 0; 457 top->cg_level = CG_SHARE_NONE; 458 top->cg_flags = 0; 459 460 return (top); 461} 462 463static int 464smp_topo_addleaf(struct cpu_group *parent, struct cpu_group *child, int share, 465 int count, int flags, int start) 466{ 467 cpumask_t mask; 468 int i; 469 470 for (mask = 0, i = 0; i < count; i++, start++) 471 mask |= (1 << start); 472 child->cg_parent = parent; 473 child->cg_child = NULL; 474 child->cg_children = 0; 475 child->cg_level = share; 476 child->cg_count = count; 477 child->cg_flags = flags; 478 child->cg_mask = mask; 479 parent->cg_children++; 480 for (; parent != NULL; parent = parent->cg_parent) { 481 if ((parent->cg_mask & child->cg_mask) != 0) 482 panic("Duplicate children in %p. mask 0x%X child 0x%X", 483 parent, parent->cg_mask, child->cg_mask); 484 parent->cg_mask |= child->cg_mask; 485 parent->cg_count += child->cg_count; 486 } 487 488 return (start); 489} 490 491struct cpu_group * 492smp_topo_1level(int share, int count, int flags) 493{ 494 struct cpu_group *child; 495 struct cpu_group *top; 496 int packages; 497 int cpu; 498 int i; 499 500 cpu = 0; 501 top = &group[0]; 502 packages = mp_ncpus / count; 503 top->cg_child = child = &group[1]; 504 top->cg_level = CG_SHARE_NONE; 505 for (i = 0; i < packages; i++, child++) 506 cpu = smp_topo_addleaf(top, child, share, count, flags, cpu); 507 return (top); 508} 509 510struct cpu_group * 511smp_topo_2level(int l2share, int l2count, int l1share, int l1count, 512 int l1flags) 513{ 514 struct cpu_group *top; 515 struct cpu_group *l1g; 516 struct cpu_group *l2g; 517 int cpu; 518 int i; 519 int j; 520 521 cpu = 0; 522 top = &group[0]; 523 l2g = &group[1]; 524 top->cg_child = l2g; 525 top->cg_level = CG_SHARE_NONE; 526 top->cg_children = mp_ncpus / (l2count * l1count); 527 l1g = l2g + top->cg_children; 528 for (i = 0; i < top->cg_children; i++, l2g++) { 529 l2g->cg_parent = top; 530 l2g->cg_child = l1g; 531 l2g->cg_level = l2share; 532 for (j = 0; j < l2count; j++, l1g++) 533 cpu = smp_topo_addleaf(l2g, l1g, l1share, l1count, 534 l1flags, cpu); 535 } 536 return (top); 537} 538 539 540struct cpu_group * 541smp_topo_find(struct cpu_group *top, int cpu) 542{ 543 struct cpu_group *cg; 544 cpumask_t mask; 545 int children; 546 int i; 547 548 mask = (1 << cpu); 549 cg = top; 550 for (;;) { 551 if ((cg->cg_mask & mask) == 0) 552 return (NULL); 553 if (cg->cg_children == 0) 554 return (cg); 555 children = cg->cg_children; 556 for (i = 0, cg = cg->cg_child; i < children; cg++, i++) 557 if ((cg->cg_mask & mask) != 0) 558 break; 559 } 560 return (NULL); 561} 562#else /* !SMP */ 563 |
|
405void 406smp_rendezvous(void (*setup_func)(void *), 407 void (*action_func)(void *), 408 void (*teardown_func)(void *), 409 void *arg) 410{ 411 412 if (setup_func != NULL) 413 setup_func(arg); 414 if (action_func != NULL) 415 action_func(arg); 416 if (teardown_func != NULL) 417 teardown_func(arg); 418} | 564void 565smp_rendezvous(void (*setup_func)(void *), 566 void (*action_func)(void *), 567 void (*teardown_func)(void *), 568 void *arg) 569{ 570 571 if (setup_func != NULL) 572 setup_func(arg); 573 if (action_func != NULL) 574 action_func(arg); 575 if (teardown_func != NULL) 576 teardown_func(arg); 577} |
578 579/* 580 * Provide dummy SMP support for UP kernels. Modules that need to use SMP 581 * APIs will still work using this dummy support. 582 */ 583static void 584mp_setvariables_for_up(void *dummy) 585{ 586 mp_ncpus = 1; 587 mp_maxid = PCPU_GET(cpuid); 588 all_cpus = PCPU_GET(cpumask); 589 KASSERT(PCPU_GET(cpuid) == 0, ("UP must have a CPU ID of zero")); 590} 591SYSINIT(cpu_mp_setvariables, SI_SUB_TUNABLES, SI_ORDER_FIRST, 592 mp_setvariables_for_up, NULL) |
|
419#endif /* SMP */ | 593#endif /* SMP */ |