Index: sys/kern/sched_ule.c =================================================================== --- sys/kern/sched_ule.c +++ sys/kern/sched_ule.c @@ -1423,6 +1423,45 @@ } #ifdef SMP +static void +sched_format_topo(struct sbuf *sb, char cpusetbuf[__min_size(CPUSETBUFSIZ)], + int level, const struct cpu_group *cg) +{ + int i, children; + + sbuf_printf(sb, "%*scount %d, children %d, level %d, flags 0x%02x, " + "cpuset %s\n", level * 4, "", cg->cg_count, (int)cg->cg_children, + (int)cg->cg_level, (int)cg->cg_flags, + cpusetobj_strprint(cpusetbuf, &cg->cg_mask)); + + children = cg->cg_children; + for (i = 0, cg = cg->cg_child; i < children; cg++, i++) + sched_format_topo(sb, cpusetbuf, level + 1, cg); +} + +static void +sched_print_topo(void) +{ +#ifndef PRINTF_BUFR_SIZE +#define PRINTF_BUFR_SIZE 64 +#endif + char cpusetbuf[CPUSETBUFSIZ]; + char bufr[PRINTF_BUFR_SIZE]; + struct sbuf sb, *sbp __unused; + + sbp = sbuf_new(&sb, bufr, sizeof(bufr), SBUF_FIXEDLEN); + KASSERT(sbp != NULL, ("sbuf_new misused?")); + + sbuf_set_drain(&sb, sbuf_printf_drain, NULL); + + sbuf_cat(&sb, "Sched CPU Groups:\n"); + sched_format_topo(&sb, cpusetbuf, 0, cpu_top); + + sbuf_nl_terminate(&sb); + sbuf_finish(&sb); + sbuf_delete(&sb); +} + static void sched_setup_smp(void) { @@ -1430,6 +1469,8 @@ int i; cpu_top = smp_topo(); + if (bootverbose) + sched_print_topo(); CPU_FOREACH(i) { tdq = DPCPU_ID_PTR(i, tdq); tdq_setup(tdq, i); Index: sys/kern/subr_smp.c =================================================================== --- sys/kern/subr_smp.c +++ sys/kern/subr_smp.c @@ -806,24 +806,29 @@ struct cpu_group * smp_topo_find(struct cpu_group *top, int cpu) { - struct cpu_group *cg; + struct cpu_group *cg, *best; cpuset_t mask; int children; int i; CPU_SETOF(cpu, &mask); cg = top; - for (;;) { + for (best = NULL;;) { + /* + * If the CPU cannot be found in the set, return the best (most + * specific) match we've seen. + */ if (!CPU_OVERLAP(&cg->cg_mask, &mask)) - return (NULL); + return (best); if (cg->cg_children == 0) return (cg); + best = cg; children = cg->cg_children; for (i = 0, cg = cg->cg_child; i < children; cg++, i++) if (CPU_OVERLAP(&cg->cg_mask, &mask)) break; } - return (NULL); + return (best); } #else /* !SMP */ Index: sys/x86/x86/mp_x86.c =================================================================== --- sys/x86/x86/mp_x86.c +++ sys/x86/x86/mp_x86.c @@ -679,9 +679,11 @@ void cpu_mp_announce(void) { - struct topo_node *node; + struct topo_node *node, *t; const char *hyperthread; struct topo_analysis topology; + char cpusetbuf[CPUSETBUFSIZ]; + int level; printf("FreeBSD/SMP: "); if (topo_analyze(&topo_root, 1, &topology)) { @@ -730,12 +732,30 @@ return; TOPO_FOREACH(node, &topo_root) { + level = 0; + for (t = node; t != NULL && t != &topo_root; t = t->parent) + level++; + + printf("%*s", 4 * level, ""); + switch (node->type) { + case TOPO_TYPE_SYSTEM: + printf("System HW ID ="); + break; + case TOPO_TYPE_GROUP: + printf("Group HW ID ="); + break; + case TOPO_TYPE_NODE: + printf("Node HW ID ="); + break; + case TOPO_TYPE_CACHE: + printf("Cache L%jd HW ID =", (intmax_t)node->subtype); + break; case TOPO_TYPE_PKG: - printf("Package HW ID = %u\n", node->hwid); + printf("Package HW ID ="); break; case TOPO_TYPE_CORE: - printf("\tCore HW ID = %u\n", node->hwid); + printf("Core HW ID ="); break; case TOPO_TYPE_PU: if (cpu_info[node->hwid].cpu_hyperthread) @@ -744,19 +764,24 @@ hyperthread = ""; if (node->subtype == 0) - printf("\t\tCPU (AP%s): APIC ID: %u" - "(disabled)\n", hyperthread, node->hwid); + printf("CPU (AP%s): APIC ID:", hyperthread); else if (node->id == 0) - printf("\t\tCPU0 (BSP): APIC ID: %u\n", - node->hwid); + printf("CPU0 (BSP): APIC ID:"); else - printf("\t\tCPU%u (AP%s): APIC ID: %u\n", - node->id, hyperthread, node->hwid); + printf("CPU%u (AP%s): APIC ID:", node->id, + hyperthread); break; default: - /* ignored */ + printf("Unknown (%d) HW ID =", (int)node->type); break; } + + printf(" %u", node->hwid); + + if (node->type == TOPO_TYPE_PU && node->subtype == 0) + printf(" (disabled)"); + + printf(" [%s]\n", cpusetobj_strprint(cpusetbuf, &node->cpuset)); } } @@ -817,6 +842,7 @@ while (node != NULL) { if ((node->type != TOPO_TYPE_GROUP && node->type != TOPO_TYPE_CACHE) || + CPU_EMPTY(&node->cpuset) || (root->type != TOPO_TYPE_SYSTEM && CPU_CMP(&node->cpuset, &root->cpuset) == 0)) { node = topo_next_node(root, node); @@ -838,6 +864,7 @@ while (node != NULL) { if ((node->type != TOPO_TYPE_GROUP && node->type != TOPO_TYPE_CACHE) || + CPU_EMPTY(&node->cpuset) || (root->type != TOPO_TYPE_SYSTEM && CPU_CMP(&node->cpuset, &root->cpuset) == 0)) { node = topo_next_node(root, node);