+ x86_core_t *core;
+ cpu_data_t *cpup = current_cpu_datap();
+
+ mp_safe_spin_lock(&x86_topo_lock);
+ machine_info.logical_cpu -= 1;
+ core = cpup->lcpu.core;
+ core->active_lcpus -= 1;
+ if (core->active_lcpus == 0) {
+ machine_info.physical_cpu -= 1;
+ }
+ simple_unlock(&x86_topo_lock);
+
+ /*
+ * Let the power management code determine the best way to "stop"
+ * the processor.
+ */
+ ml_set_interrupts_enabled(FALSE);
+ while (1) {
+ pmCPUHalt(PM_HALT_NORMAL);
+ }
+ /* NOT REACHED */
+}
+
+/*
+ * 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;
+ }
+}
+
+/*
+ * Prints out the topology
+ */
+static void
+debug_topology_print(void)
+{
+ x86_pkg_t *pkg;
+ x86_die_t *die;
+ x86_core_t *core;
+ x86_lcpu_t *cpu;
+
+ pkg = x86_pkgs;
+ while (pkg != NULL) {
+ kprintf("Package:\n");
+ kprintf(" Physical: %d\n", pkg->ppkg_num);
+ kprintf(" Logical: %d\n", pkg->lpkg_num);
+
+ die = pkg->dies;
+ while (die != NULL) {
+ kprintf(" Die:\n");
+ kprintf(" Physical: %d\n", die->pdie_num);
+ kprintf(" Logical: %d\n", die->ldie_num);
+
+ core = die->cores;
+ while (core != NULL) {
+ kprintf(" Core:\n");
+ kprintf(" Physical: %d\n", core->pcore_num);
+ kprintf(" Logical: %d\n", core->lcore_num);
+
+ cpu = core->lcpus;
+ while (cpu != NULL) {
+ kprintf(" LCPU:\n");
+ kprintf(" CPU #: %d\n", cpu->cpu_num);
+ kprintf(" Physical: %d\n", cpu->pnum);
+ kprintf(" Logical: %d\n", cpu->lnum);
+ kprintf(" Flags: ");
+ if (cpu->master) {
+ kprintf("MASTER ");
+ }
+ if (cpu->primary) {
+ kprintf("PRIMARY");
+ }
+ if (!cpu->master && !cpu->primary) {
+ kprintf("(NONE)");
+ }
+ kprintf("\n");
+
+ cpu = cpu->next_in_core;
+ }
+
+ core = core->next_in_die;
+ }
+
+ die = die->next_in_pkg;
+ }
+
+ pkg = pkg->next;
+ }