diff options
author | Robert Mustacchi <rm@joyent.com> | 2019-02-16 23:40:22 +0000 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2019-02-27 01:24:49 +0000 |
commit | 3c9f6075b5ed073bc3fc76531874aea0329d6cbd (patch) | |
tree | 76e6977d3839a9d06d28e4266382867ac12ed589 | |
parent | 0d3f2b61dcfb18edace4fd257054f6fdbe07c99c (diff) | |
download | illumos-joyent-3c9f6075b5ed073bc3fc76531874aea0329d6cbd.tar.gz |
OS-7597 OS-7486 broke older Intel CPUs
OS-7590 Regression in westmere MCA initialization
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: John Levon <john.levon@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
-rw-r--r-- | usr/src/uts/i86pc/os/cpuid.c | 80 |
1 files changed, 72 insertions, 8 deletions
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c index d0489a0148..96d00a5f8a 100644 --- a/usr/src/uts/i86pc/os/cpuid.c +++ b/usr/src/uts/i86pc/os/cpuid.c @@ -819,6 +819,23 @@ * share the same last level cache. IDs should not overlap between * packages. * + * cpi_ncore_bits + * + * This indicates the number of bits that are required to represent all of + * the cores in the system. As cores are derived based on their APIC IDs, + * we aren't guaranteed a run of APIC IDs starting from zero. It's OK for + * this value to be larger than the actual number of IDs that are present + * in the system. This is used to size tables by the CMI framework. It is + * only filled in for Intel and AMD CPUs. + * + * cpi_nthread_bits + * + * This indicates the number of bits required to represent all of the IDs + * that cover the logical CPUs that exist on a given core. It's OK for this + * value to be larger than the actual number of IDs that are present in the + * system. This is used to size tables by the CMI framework. It is + * only filled in for Intel and AMD CPUs. + * * ----------- * Hypervisors * ----------- @@ -1184,6 +1201,13 @@ struct cpuid_info { int cpi_pkgcoreid; /* core number within single package */ uint_t cpi_ncore_per_chip; /* AMD: fn 0x80000008: %ecx[7-0] */ /* Intel: fn 4: %eax[31-26] */ + + /* + * These values represent the number of bits that are required to store + * information about the number of cores and threads. + */ + uint_t cpi_ncore_bits; + uint_t cpi_nthread_bits; /* * supported feature information */ @@ -1704,17 +1728,30 @@ cpuid_amd_ncores(struct cpuid_info *cpi, uint_t *ncpus, uint_t *ncores) *ncores = nthreads / nthread_per_core; } +/* + * Seed the initial values for the cores and threads for an Intel based + * processor. These values will be overwritten if we detect that the processor + * supports CPUID leaf 0xb. + */ static void cpuid_intel_ncores(struct cpuid_info *cpi, uint_t *ncpus, uint_t *ncores) { + /* + * Only seed the number of physical cores from the first level leaf 4 + * information. The number of threads there indicate how many share the + * L1 cache, which may or may not have anything to do with the number of + * logical CPUs per core. + */ if (cpi->cpi_maxeax >= 4) { *ncores = BITX(cpi->cpi_std[4].cp_eax, 31, 26) + 1; - *ncpus = BITX(cpi->cpi_std[4].cp_eax, 25, 14) + 1; - } else if ((cpi->cpi_std[1].cp_edx & CPUID_INTC_EDX_HTT) != 0) { + } else { *ncores = 1; + } + + if ((cpi->cpi_std[1].cp_edx & CPUID_INTC_EDX_HTT) != 0) { *ncpus = CPI_CPU_COUNT(cpi); } else { - *ncpus = *ncores = 1; + *ncpus = *ncores; } } @@ -1779,6 +1816,11 @@ cpuid_leafB_getids(cpu_t *cpu) cpi->cpi_procnodeid = cpi->cpi_chipid; cpi->cpi_compunitid = cpi->cpi_coreid; + if (coreid_shift > 0 && chipid_shift > coreid_shift) { + cpi->cpi_nthread_bits = coreid_shift; + cpi->cpi_ncore_bits = chipid_shift - coreid_shift; + } + return (B_TRUE); } else { return (B_FALSE); @@ -1807,6 +1849,17 @@ cpuid_intel_getids(cpu_t *cpu, void *feature) if (cpuid_leafB_getids(cpu)) return; + /* + * In this case, we have the leaf 1 and leaf 4 values for ncpu_per_chip + * and ncore_per_chip. These represent the largest power of two values + * that we need to cover all of the IDs in the system. Therefore, we use + * those values to seed the number of bits needed to cover information + * in the case when leaf B is not available. These values will probably + * be larger than required, but that's OK. + */ + cpi->cpi_nthread_bits = ddi_fls(cpi->cpi_ncpu_per_chip); + cpi->cpi_ncore_bits = ddi_fls(cpi->cpi_ncore_per_chip); + for (i = 1; i < cpi->cpi_ncpu_per_chip; i <<= 1) chipid_shift++; @@ -2059,6 +2112,10 @@ cpuid_amd_getids(cpu_t *cpu, uchar_t *features) cpi->cpi_chipid = cpi->cpi_procnodeid / cpi->cpi_procnodes_per_pkg; + + cpi->cpi_ncore_bits = coreidsz; + cpi->cpi_nthread_bits = ddi_fls(cpi->cpi_ncpu_per_chip / + cpi->cpi_ncore_per_chip); } static void @@ -6466,20 +6523,27 @@ patch_memops(uint_t vendor) /* * We're being asked to tell the system how many bits are required to represent - * the various thread and strand IDs. + * the various thread and strand IDs. While it's tempting to derive this based + * on the values in cpi_ncore_per_chip and cpi_ncpu_per_chip, that isn't quite + * correct. Instead, this needs to be based on the number of bits that the APIC + * allows for these different configurations. We only update these to a larger + * value if we find one. */ void cpuid_get_ext_topo(cpu_t *cpu, uint_t *core_nbits, uint_t *strand_nbits) { struct cpuid_info *cpi; - uint_t nthreads; VERIFY(cpuid_checkpass(CPU, 1)); cpi = cpu->cpu_m.mcpu_cpi; - nthreads = cpi->cpi_ncpu_per_chip / cpi->cpi_ncore_per_chip; - *core_nbits = ddi_fls(cpi->cpi_ncore_per_chip); - *strand_nbits = ddi_fls(nthreads); + if (cpi->cpi_ncore_bits > *core_nbits) { + *core_nbits = cpi->cpi_ncore_bits; + } + + if (cpi->cpi_nthread_bits > *strand_nbits) { + *strand_nbits = cpi->cpi_nthread_bits; + } } void |