CaseySJ
Moderator
- Joined
- Nov 11, 2018
- Messages
- 22,211
- Motherboard
- Asus ProArt Z690-Creator
- CPU
- i7-12700K
- Graphics
- RX 6800 XT
- Mac
- Classic Mac
- Mobile Phone
@Elias64FrIt would be good to dump x86_validate_tolopogy() to see how macOS probes the cpuid or logical/physical processors... to devise a workaround. And even if we workaround it, it's not clear how the thread scheduler will schedule threads on the Golden Cove cores vs the Gracemont cores.
One step at a time!
Thanks to Apple's Open Source commitment, here is the source code for
x86_validate_topology()
from macOS 11.5 (Big Sur). After examining this, we may be able to patch it, but this is not always practical. This particular code is located here:xnu-7195.141.2 --> osfmk --> i386 --> cpu_threads.c
First, we see that x86_validate_topology() says: @cpu_threads.c:1043
This means line 1043, which is this:
In this example we see that nCPUs is 12 and real_ncpus is 20. Although we could patch line 1041 from this:
C:
if (nCPUs != real_ncpus) {
C:
if (nCPUs > real_ncpus) {
And here is the full function:
C:
/*
* Validates that the topology was built correctly. Must be called only
* after the complete topology is built and no other changes are being made.
*/
void
x86_validate_topology(void)
{
x86_pkg_t *pkg;
x86_die_t *die;
x86_core_t *core;
x86_lcpu_t *lcpu;
uint32_t nDies;
uint32_t nCores;
uint32_t nCPUs;
if (topo_dbg) {
debug_topology_print();
}
/*
* Called after processors are registered but before non-boot processors
* are started:
* - real_ncpus: number of registered processors driven from MADT
* - max_ncpus: max number of processors that will be started
*/
nCPUs = topoParms.nPackages * topoParms.nLThreadsPerPackage;
if (nCPUs != real_ncpus) {
panic("x86_validate_topology() %d threads but %d registered from MADT",
nCPUs, real_ncpus);
}
pkg = x86_pkgs;
while (pkg != NULL) {
/*
* Make sure that the package has the correct number of dies.
*/
nDies = 0;
die = pkg->dies;
while (die != NULL) {
if (die->package == NULL) {
panic("Die(%d)->package is NULL",
die->pdie_num);
}
if (die->package != pkg) {
panic("Die %d points to package %d, should be %d",
die->pdie_num, die->package->lpkg_num, pkg->lpkg_num);
}
TOPO_DBG("Die(%d)->package %d\n",
die->pdie_num, pkg->lpkg_num);
/*
* Make sure that the die has the correct number of cores.
*/
TOPO_DBG("Die(%d)->cores: ", die->pdie_num);
nCores = 0;
core = die->cores;
while (core != NULL) {
if (core->die == NULL) {
panic("Core(%d)->die is NULL",
core->pcore_num);
}
if (core->die != die) {
panic("Core %d points to die %d, should be %d",
core->pcore_num, core->die->pdie_num, die->pdie_num);
}
nCores += 1;
TOPO_DBG("%d ", core->pcore_num);
core = core->next_in_die;
}
TOPO_DBG("\n");
if (nCores != topoParms.nLCoresPerDie) {
panic("Should have %d Cores, but only found %d for Die %d",
topoParms.nLCoresPerDie, nCores, die->pdie_num);
}
/*
* Make sure that the die has the correct number of CPUs.
*/
TOPO_DBG("Die(%d)->lcpus: ", die->pdie_num);
nCPUs = 0;
lcpu = die->lcpus;
while (lcpu != NULL) {
if (lcpu->die == NULL) {
panic("CPU(%d)->die is NULL",
lcpu->cpu_num);
}
if (lcpu->die != die) {
panic("CPU %d points to die %d, should be %d",
lcpu->cpu_num, lcpu->die->pdie_num, die->pdie_num);
}
nCPUs += 1;
TOPO_DBG("%d ", lcpu->cpu_num);
lcpu = lcpu->next_in_die;
}
TOPO_DBG("\n");
if (nCPUs != topoParms.nLThreadsPerDie) {
panic("Should have %d Threads, but only found %d for Die %d",
topoParms.nLThreadsPerDie, nCPUs, die->pdie_num);
}
nDies += 1;
die = die->next_in_pkg;
}
if (nDies != topoParms.nLDiesPerPackage) {
panic("Should have %d Dies, but only found %d for package %d",
topoParms.nLDiesPerPackage, nDies, pkg->lpkg_num);
}
/*
* Make sure that the package has the correct number of cores.
*/
nCores = 0;
core = pkg->cores;
while (core != NULL) {
if (core->package == NULL) {
panic("Core(%d)->package is NULL",
core->pcore_num);
}
if (core->package != pkg) {
panic("Core %d points to package %d, should be %d",
core->pcore_num, core->package->lpkg_num, pkg->lpkg_num);
}
TOPO_DBG("Core(%d)->package %d\n",
core->pcore_num, pkg->lpkg_num);
/*
* Make sure that the core has the correct number of CPUs.
*/
nCPUs = 0;
lcpu = core->lcpus;
TOPO_DBG("Core(%d)->lcpus: ", core->pcore_num);
while (lcpu != NULL) {
if (lcpu->core == NULL) {
panic("CPU(%d)->core is NULL",
lcpu->cpu_num);
}
if (lcpu->core != core) {
panic("CPU %d points to core %d, should be %d",
lcpu->cpu_num, lcpu->core->pcore_num, core->pcore_num);
}
TOPO_DBG("%d ", lcpu->cpu_num);
nCPUs += 1;
lcpu = lcpu->next_in_core;
}
TOPO_DBG("\n");
if (nCPUs != topoParms.nLThreadsPerCore) {
panic("Should have %d Threads, but only found %d for Core %d",
topoParms.nLThreadsPerCore, nCPUs, core->pcore_num);
}
nCores += 1;
core = core->next_in_pkg;
}
if (nCores != topoParms.nLCoresPerPackage) {
panic("Should have %d Cores, but only found %d for package %d",
topoParms.nLCoresPerPackage, nCores, pkg->lpkg_num);
}
/*
* Make sure that the package has the correct number of CPUs.
*/
nCPUs = 0;
lcpu = pkg->lcpus;
while (lcpu != NULL) {
if (lcpu->package == NULL) {
panic("CPU(%d)->package is NULL",
lcpu->cpu_num);
}
if (lcpu->package != pkg) {
panic("CPU %d points to package %d, should be %d",
lcpu->cpu_num, lcpu->package->lpkg_num, pkg->lpkg_num);
}
TOPO_DBG("CPU(%d)->package %d\n",
lcpu->cpu_num, pkg->lpkg_num);
nCPUs += 1;
lcpu = lcpu->next_in_pkg;
}
if (nCPUs != topoParms.nLThreadsPerPackage) {
panic("Should have %d Threads, but only found %d for package %d",
topoParms.nLThreadsPerPackage, nCPUs, pkg->lpkg_num);
}
pkg = pkg->next;
}
}
Last edited: