Index: head/share/man/man4/smp.4 =================================================================== --- head/share/man/man4/smp.4 +++ head/share/man/man4/smp.4 @@ -23,7 +23,7 @@ .\" .\" $FreeBSD$ .\" -.Dd January 6, 2018 +.Dd January 4, 2019 .Dt SMP 4 .Os .Sh NAME @@ -35,27 +35,6 @@ The .Nm kernel implements symmetric multi-processor support. -.Sh COMPATIBILITY -Support for multi-processor systems is present for all Tier-1 -architectures on -.Fx . -Currently, this includes amd64, i386 and sparc64. -Support is enabled using -.Cd options SMP . -It is permissible to use the SMP kernel configuration on non-SMP equipped -motherboards. -.Sh I386 NOTES -For i386 systems, the -.Nm -kernel supports motherboards that follow the Intel MP specification, -version 1.4. -In addition to -.Cd options SMP , -i386 also requires -.Cd device apic . -The -.Xr mptable 1 -command may be used to view the status of multi-processor support. .Pp .Nm support can be disabled by setting the loader tunable @@ -66,6 +45,13 @@ the read-only sysctl variable .Va hw.ncpu . .Pp +The number of online threads per CPU core is available in the read-only sysctl +variable +.Va kern.smp.threads_per_core . +The number of physical CPU cores detected by the system is available in the +read-only sysctl variable +.Va kern.smp.cores . +.Pp .Fx allows specific CPUs on a multi-processor system to be disabled. This can be done using the @@ -74,6 +60,12 @@ Setting this tunable to 1 will result in the corresponding CPU being disabled. .Pp +.Fx +supports simultaneous multithreading on x86 and powerpc platforms. +On x86, the logical CPUs can be disabled by setting the +.Va machdep.hyperthreading_allowed +tunable to zero. +.Pp The .Xr sched_ule 4 scheduler implements CPU topology detection and adjusts the scheduling @@ -122,13 +114,26 @@ .Pp This information is used internally by the kernel to schedule related tasks on CPUs that are closely grouped together. -.Pp -.Fx -supports hyperthreading on Intel CPU's on the i386 and AMD64 platforms. -Because using logical CPUs can cause performance penalties under certain loads, -the logical CPUs can be disabled by setting the -.Va machdep.hyperthreading_allowed -tunable to zero. +.Sh COMPATIBILITY +Support for multi-processor systems is present for all Tier-1 and Tier-2 +architectures on +.Fx . +Currently, this includes x86, powerpc, arm, and sparc64. +Support is enabled using +.Cd options SMP . +It is permissible to use the SMP kernel configuration on non-SMP hardware. +.Sh I386 NOTES +For i386 systems, the +.Nm +kernel supports motherboards that follow the Intel MP specification, +version 1.4. +In addition to +.Cd options SMP , +i386 also requires +.Cd device apic . +The +.Xr mptable 1 +command may be used to view the status of multi-processor support. .Sh SEE ALSO .Xr cpuset 1 , .Xr mptable 1 , @@ -166,3 +171,20 @@ also introduced support for SMP on the sparc64 architecture. .Sh AUTHORS .An Steve Passe Aq Mt fsmp@FreeBSD.org +.Sh CAVEATS +The +.Va kern.smp.threads_per_core +and +.Va kern.smp.cores +sysctl variables are provided as a best-effort guess. +If an architecture or platform adds SMT and +.Fx +has not yet implemented detection, the reported values may be inaccurate. +In this case, +.Va kern.smp.threads_per_core +will report +.Dv 1 +and +.Va kern.smp.cores +will report the same value as +.Va hw.ncpu . Index: head/sys/kern/subr_smp.c =================================================================== --- head/sys/kern/subr_smp.c +++ head/sys/kern/subr_smp.c @@ -98,6 +98,14 @@ SYSCTL_INT(_kern_smp, OID_AUTO, cpus, CTLFLAG_RD|CTLFLAG_CAPRD, &smp_cpus, 0, "Number of CPUs online"); +int smp_threads_per_core = 1; /* how many SMT threads are running per core */ +SYSCTL_INT(_kern_smp, OID_AUTO, threads_per_core, CTLFLAG_RD|CTLFLAG_CAPRD, + &smp_threads_per_core, 0, "Number of SMT threads online per core"); + +int mp_ncores = -1; /* how many physical cores running */ +SYSCTL_INT(_kern_smp, OID_AUTO, cores, CTLFLAG_RD|CTLFLAG_CAPRD, &mp_ncores, 0, + "Number of CPUs online"); + int smp_topology = 0; /* Which topology we're using. */ SYSCTL_INT(_kern_smp, OID_AUTO, topology, CTLFLAG_RDTUN, &smp_topology, 0, "Topology override setting; 0 is default provided by hardware."); @@ -154,6 +162,7 @@ /* Probe for MP hardware. */ if (smp_disabled != 0 || cpu_mp_probe() == 0) { + mp_ncores = 1; mp_ncpus = 1; CPU_SETOF(PCPU_GET(cpuid), &all_cpus); return; @@ -162,6 +171,11 @@ cpu_mp_start(); printf("FreeBSD/SMP: Multiprocessor System Detected: %d CPUs\n", mp_ncpus); + + /* Provide a default for most architectures that don't have SMT/HTT. */ + if (mp_ncores < 0) + mp_ncores = mp_ncpus; + cpu_mp_announce(); } SYSINIT(cpu_mp, SI_SUB_CPU, SI_ORDER_THIRD, mp_start, NULL); @@ -823,6 +837,7 @@ mp_setvariables_for_up(void *dummy) { mp_ncpus = 1; + mp_ncores = 1; mp_maxid = PCPU_GET(cpuid); CPU_SETOF(mp_maxid, &all_cpus); KASSERT(PCPU_GET(cpuid) == 0, ("UP must have a CPU ID of zero")); Index: head/sys/powerpc/powernv/platform_powernv.c =================================================================== --- head/sys/powerpc/powernv/platform_powernv.c +++ head/sys/powerpc/powernv/platform_powernv.c @@ -435,12 +435,16 @@ break; } + smp_threads_per_core = nthreads; + if (mp_ncpus % nthreads != 0) { printf("WARNING: Irregular SMP topology. Performance may be " "suboptimal (%d threads, %d on first core)\n", mp_ncpus, nthreads); return (smp_topo_none()); } + + mp_ncores = mp_ncpus / nthreads; /* Don't do anything fancier for non-threaded SMP */ if (nthreads == 1) Index: head/sys/powerpc/powerpc/mp_machdep.c =================================================================== --- head/sys/powerpc/powerpc/mp_machdep.c +++ head/sys/powerpc/powerpc/mp_machdep.c @@ -186,6 +186,11 @@ next: error = platform_smp_next_cpu(&cpu); } + +#ifdef SMP + /* Probe mp_ncores and smp_threads_per_core as a side effect. */ + (void)cpu_topo(); +#endif } void Index: head/sys/powerpc/ps3/platform_ps3.c =================================================================== --- head/sys/powerpc/ps3/platform_ps3.c +++ head/sys/powerpc/ps3/platform_ps3.c @@ -246,6 +246,8 @@ static struct cpu_group * ps3_smp_topo(platform_t plat) { + mp_ncores = 1; + smp_threads_per_core = 2; return (smp_topo_1level(CG_SHARE_L1, 2, CG_FLAG_SMT)); } #endif Index: head/sys/powerpc/pseries/platform_chrp.c =================================================================== --- head/sys/powerpc/pseries/platform_chrp.c +++ head/sys/powerpc/pseries/platform_chrp.c @@ -517,6 +517,8 @@ ncpus++; } + mp_ncores = ncores; + if (ncpus % ncores != 0) { printf("WARNING: Irregular SMP topology. Performance may be " "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores); @@ -527,6 +529,7 @@ if (ncpus == ncores) return (smp_topo_none()); + smp_threads_per_core = ncpus / ncores; return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT)); } #endif Index: head/sys/sys/smp.h =================================================================== --- head/sys/sys/smp.h +++ head/sys/sys/smp.h @@ -167,8 +167,10 @@ extern u_int mp_maxid; extern int mp_maxcpus; +extern int mp_ncores; extern int mp_ncpus; extern volatile int smp_started; +extern int smp_threads_per_core; extern cpuset_t all_cpus; extern cpuset_t cpuset_domain[MAXMEMDOM]; /* CPUs in each NUMA domain. */ Index: head/sys/x86/x86/mp_x86.c =================================================================== --- head/sys/x86/x86/mp_x86.c +++ head/sys/x86/x86/mp_x86.c @@ -607,6 +607,7 @@ { struct topo_node *node; u_int smt_mask; + int nhyper; smt_mask = (1u << core_id_shift) - 1; @@ -615,6 +616,7 @@ * beyond MAXCPU. CPU 0 is always assigned to the BSP. */ mp_ncpus = 0; + nhyper = 0; TOPO_FOREACH(node, &topo_root) { if (node->type != TOPO_TYPE_PU) continue; @@ -642,6 +644,9 @@ continue; } + if (cpu_info[node->hwid].cpu_hyperthread) + nhyper++; + cpu_apic_ids[mp_ncpus] = node->hwid; apic_cpuids[node->hwid] = mp_ncpus; topo_set_pu_id(node, mp_ncpus); @@ -651,6 +656,9 @@ KASSERT(mp_maxid >= mp_ncpus - 1, ("%s: counters out of sync: max %d, count %d", __func__, mp_maxid, mp_ncpus)); + + mp_ncores = mp_ncpus - nhyper; + smp_threads_per_core = mp_ncpus / mp_ncores; } /*