kqueue: Use wakeup_one based on # of threads sleep on kqueue
[dragonfly.git] / sys / kern / subr_cpu_topology.c
blob54d5ce37ef1af666d48422dbde826ef2537cdae7
1 /*
2 * Copyright (c) 2012 The DragonFly Project. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in
12 * the documentation and/or other materials provided with the
13 * distribution.
14 * 3. Neither the name of The DragonFly Project nor the names of its
15 * contributors may be used to endorse or promote products derived
16 * from this software without specific, prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
24 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
26 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
28 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/kernel.h>
36 #include <sys/sysctl.h>
37 #include <sys/sbuf.h>
38 #include <sys/cpu_topology.h>
40 #include <machine/smp.h>
42 #ifndef NAPICID
43 #define NAPICID 256
44 #endif
46 #define INDENT_BUF_SIZE LEVEL_NO*3
47 #define INVALID_ID -1
49 /* Per-cpu sysctl nodes and info */
50 struct per_cpu_sysctl_info {
51 struct sysctl_ctx_list sysctl_ctx;
52 struct sysctl_oid *sysctl_tree;
53 char cpu_name[32];
54 int physical_id;
55 int core_id;
56 char physical_siblings[8*MAXCPU];
57 char core_siblings[8*MAXCPU];
59 typedef struct per_cpu_sysctl_info per_cpu_sysctl_info_t;
61 static cpu_node_t cpu_topology_nodes[MAXCPU]; /* Memory for topology */
62 static cpu_node_t *cpu_root_node; /* Root node pointer */
64 static struct sysctl_ctx_list cpu_topology_sysctl_ctx;
65 static struct sysctl_oid *cpu_topology_sysctl_tree;
66 static char cpu_topology_members[8*MAXCPU];
67 static per_cpu_sysctl_info_t pcpu_sysctl[MAXCPU];
68 static void sbuf_print_cpuset(struct sbuf *sb, cpumask_t *mask);
70 int cpu_topology_levels_number = 1;
71 cpu_node_t *root_cpu_node;
73 /* Get the next valid apicid starting
74 * from current apicid (curr_apicid
76 static int
77 get_next_valid_apicid(int curr_apicid)
79 int next_apicid = curr_apicid;
80 do {
81 next_apicid++;
83 while(get_cpuid_from_apicid(next_apicid) == -1 &&
84 next_apicid < NAPICID);
85 if (next_apicid == NAPICID) {
86 kprintf("Warning: No next valid APICID found. Returning -1\n");
87 return -1;
89 return next_apicid;
92 /* Generic topology tree. The parameters have the following meaning:
93 * - children_no_per_level : the number of children on each level
94 * - level_types : the type of the level (THREAD, CORE, CHIP, etc)
95 * - cur_level : the current level of the tree
96 * - node : the current node
97 * - last_free_node : the last free node in the global array.
98 * - cpuid : basicly this are the ids of the leafs
99 */
100 static void
101 build_topology_tree(int *children_no_per_level,
102 uint8_t *level_types,
103 int cur_level,
104 cpu_node_t *node,
105 cpu_node_t **last_free_node,
106 int *apicid)
108 int i;
110 node->child_no = children_no_per_level[cur_level];
111 node->type = level_types[cur_level];
112 CPUMASK_ASSZERO(node->members);
113 node->compute_unit_id = -1;
115 if (node->child_no == 0) {
116 *apicid = get_next_valid_apicid(*apicid);
117 CPUMASK_ASSBIT(node->members, get_cpuid_from_apicid(*apicid));
118 return;
121 if (node->parent_node == NULL)
122 root_cpu_node = node;
124 for (i = 0; i < node->child_no; i++) {
125 node->child_node[i] = *last_free_node;
126 (*last_free_node)++;
128 node->child_node[i]->parent_node = node;
130 build_topology_tree(children_no_per_level,
131 level_types,
132 cur_level + 1,
133 node->child_node[i],
134 last_free_node,
135 apicid);
137 CPUMASK_ORMASK(node->members, node->child_node[i]->members);
141 #if defined(__x86_64__) && !defined(_KERNEL_VIRTUAL)
142 static void
143 migrate_elements(cpu_node_t **a, int n, int pos)
145 int i;
147 for (i = pos; i < n - 1 ; i++) {
148 a[i] = a[i+1];
150 a[i] = NULL;
152 #endif
154 /* Build CPU topology. The detection is made by comparing the
155 * chip, core and logical IDs of each CPU with the IDs of the
156 * BSP. When we found a match, at that level the CPUs are siblings.
158 static void
159 build_cpu_topology(void)
161 detect_cpu_topology();
162 int i;
163 int BSPID = 0;
164 int threads_per_core = 0;
165 int cores_per_chip = 0;
166 int chips_per_package = 0;
167 int children_no_per_level[LEVEL_NO];
168 uint8_t level_types[LEVEL_NO];
169 int apicid = -1;
171 cpu_node_t *root = &cpu_topology_nodes[0];
172 cpu_node_t *last_free_node = root + 1;
174 /* Assume that the topology is uniform.
175 * Find the number of siblings within chip
176 * and witin core to build up the topology
178 for (i = 0; i < ncpus; i++) {
179 cpumask_t mask;
181 CPUMASK_ASSBIT(mask, i);
183 if (CPUMASK_TESTMASK(mask, smp_active_mask) == 0)
184 continue;
186 if (get_chip_ID(BSPID) == get_chip_ID(i))
187 cores_per_chip++;
188 else
189 continue;
191 if (get_core_number_within_chip(BSPID) ==
192 get_core_number_within_chip(i))
193 threads_per_core++;
196 cores_per_chip /= threads_per_core;
197 chips_per_package = ncpus / (cores_per_chip * threads_per_core);
199 if (bootverbose)
200 kprintf("CPU Topology: cores_per_chip: %d; threads_per_core: %d; chips_per_package: %d;\n",
201 cores_per_chip, threads_per_core, chips_per_package);
203 if (threads_per_core > 1) { /* HT available - 4 levels */
205 children_no_per_level[0] = chips_per_package;
206 children_no_per_level[1] = cores_per_chip;
207 children_no_per_level[2] = threads_per_core;
208 children_no_per_level[3] = 0;
210 level_types[0] = PACKAGE_LEVEL;
211 level_types[1] = CHIP_LEVEL;
212 level_types[2] = CORE_LEVEL;
213 level_types[3] = THREAD_LEVEL;
215 build_topology_tree(children_no_per_level,
216 level_types,
218 root,
219 &last_free_node,
220 &apicid);
222 cpu_topology_levels_number = 4;
224 } else if (cores_per_chip > 1) { /* No HT available - 3 levels */
226 children_no_per_level[0] = chips_per_package;
227 children_no_per_level[1] = cores_per_chip;
228 children_no_per_level[2] = 0;
230 level_types[0] = PACKAGE_LEVEL;
231 level_types[1] = CHIP_LEVEL;
232 level_types[2] = CORE_LEVEL;
234 build_topology_tree(children_no_per_level,
235 level_types,
237 root,
238 &last_free_node,
239 &apicid);
241 cpu_topology_levels_number = 3;
243 } else { /* No HT and no Multi-Core - 2 levels */
245 children_no_per_level[0] = chips_per_package;
246 children_no_per_level[1] = 0;
248 level_types[0] = PACKAGE_LEVEL;
249 level_types[1] = CHIP_LEVEL;
251 build_topology_tree(children_no_per_level,
252 level_types,
254 root,
255 &last_free_node,
256 &apicid);
258 cpu_topology_levels_number = 2;
262 cpu_root_node = root;
265 #if defined(__x86_64__) && !defined(_KERNEL_VIRTUAL)
266 if (fix_amd_topology() == 0) {
267 int visited[MAXCPU], i, j, pos, cpuid;
268 cpu_node_t *leaf, *parent;
270 bzero(visited, MAXCPU * sizeof(int));
272 for (i = 0; i < ncpus; i++) {
273 if (visited[i] == 0) {
274 pos = 0;
275 visited[i] = 1;
276 leaf = get_cpu_node_by_cpuid(i);
278 if (leaf->type == CORE_LEVEL) {
279 parent = leaf->parent_node;
281 last_free_node->child_node[0] = leaf;
282 last_free_node->child_no = 1;
283 last_free_node->members = leaf->members;
284 last_free_node->compute_unit_id = leaf->compute_unit_id;
285 last_free_node->parent_node = parent;
286 last_free_node->type = CORE_LEVEL;
289 for (j = 0; j < parent->child_no; j++) {
290 if (parent->child_node[j] != leaf) {
292 cpuid = BSFCPUMASK(parent->child_node[j]->members);
293 if (visited[cpuid] == 0 &&
294 parent->child_node[j]->compute_unit_id == leaf->compute_unit_id) {
296 last_free_node->child_node[last_free_node->child_no] = parent->child_node[j];
297 last_free_node->child_no++;
298 CPUMASK_ORMASK(last_free_node->members, parent->child_node[j]->members);
300 parent->child_node[j]->type = THREAD_LEVEL;
301 parent->child_node[j]->parent_node = last_free_node;
302 visited[cpuid] = 1;
304 migrate_elements(parent->child_node, parent->child_no, j);
305 parent->child_no--;
306 j--;
308 } else {
309 pos = j;
312 if (last_free_node->child_no > 1) {
313 parent->child_node[pos] = last_free_node;
314 leaf->type = THREAD_LEVEL;
315 leaf->parent_node = last_free_node;
316 last_free_node++;
322 #endif
325 /* Recursive function helper to print the CPU topology tree */
326 static void
327 print_cpu_topology_tree_sysctl_helper(cpu_node_t *node,
328 struct sbuf *sb,
329 char * buf,
330 int buf_len,
331 int last)
333 int i;
334 int bsr_member;
336 sbuf_bcat(sb, buf, buf_len);
337 if (last) {
338 sbuf_printf(sb, "\\-");
339 buf[buf_len] = ' ';buf_len++;
340 buf[buf_len] = ' ';buf_len++;
341 } else {
342 sbuf_printf(sb, "|-");
343 buf[buf_len] = '|';buf_len++;
344 buf[buf_len] = ' ';buf_len++;
347 bsr_member = BSRCPUMASK(node->members);
349 if (node->type == PACKAGE_LEVEL) {
350 sbuf_printf(sb,"PACKAGE MEMBERS: ");
351 } else if (node->type == CHIP_LEVEL) {
352 sbuf_printf(sb,"CHIP ID %d: ",
353 get_chip_ID(bsr_member));
354 } else if (node->type == CORE_LEVEL) {
355 if (node->compute_unit_id != (uint8_t)-1) {
356 sbuf_printf(sb,"Compute Unit ID %d: ",
357 node->compute_unit_id);
358 } else {
359 sbuf_printf(sb,"CORE ID %d: ",
360 get_core_number_within_chip(bsr_member));
362 } else if (node->type == THREAD_LEVEL) {
363 if (node->compute_unit_id != (uint8_t)-1) {
364 sbuf_printf(sb,"CORE ID %d: ",
365 get_core_number_within_chip(bsr_member));
366 } else {
367 sbuf_printf(sb,"THREAD ID %d: ",
368 get_logical_CPU_number_within_core(bsr_member));
370 } else {
371 sbuf_printf(sb,"UNKNOWN: ");
373 sbuf_print_cpuset(sb, &node->members);
374 sbuf_printf(sb,"\n");
376 for (i = 0; i < node->child_no; i++) {
377 print_cpu_topology_tree_sysctl_helper(node->child_node[i],
378 sb, buf, buf_len, i == (node->child_no -1));
382 /* SYSCTL PROCEDURE for printing the CPU Topology tree */
383 static int
384 print_cpu_topology_tree_sysctl(SYSCTL_HANDLER_ARGS)
386 struct sbuf *sb;
387 int ret;
388 char buf[INDENT_BUF_SIZE];
390 KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
392 sb = sbuf_new(NULL, NULL, 500, SBUF_AUTOEXTEND);
393 if (sb == NULL) {
394 return (ENOMEM);
396 sbuf_printf(sb,"\n");
397 print_cpu_topology_tree_sysctl_helper(cpu_root_node, sb, buf, 0, 1);
399 sbuf_finish(sb);
401 ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
403 sbuf_delete(sb);
405 return ret;
408 /* SYSCTL PROCEDURE for printing the CPU Topology level description */
409 static int
410 print_cpu_topology_level_description_sysctl(SYSCTL_HANDLER_ARGS)
412 struct sbuf *sb;
413 int ret;
415 sb = sbuf_new(NULL, NULL, 500, SBUF_AUTOEXTEND);
416 if (sb == NULL)
417 return (ENOMEM);
419 if (cpu_topology_levels_number == 4) /* HT available */
420 sbuf_printf(sb, "0 - thread; 1 - core; 2 - socket; 3 - anything");
421 else if (cpu_topology_levels_number == 3) /* No HT available */
422 sbuf_printf(sb, "0 - core; 1 - socket; 2 - anything");
423 else if (cpu_topology_levels_number == 2) /* No HT and no Multi-Core */
424 sbuf_printf(sb, "0 - socket; 1 - anything");
425 else
426 sbuf_printf(sb, "Unknown");
428 sbuf_finish(sb);
430 ret = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb));
432 sbuf_delete(sb);
434 return ret;
437 /* Find a cpu_node_t by a mask */
438 static cpu_node_t *
439 get_cpu_node_by_cpumask(cpu_node_t * node,
440 cpumask_t mask) {
442 cpu_node_t * found = NULL;
443 int i;
445 if (CPUMASK_CMPMASKEQ(node->members, mask))
446 return node;
448 for (i = 0; i < node->child_no; i++) {
449 found = get_cpu_node_by_cpumask(node->child_node[i], mask);
450 if (found != NULL) {
451 return found;
454 return NULL;
457 cpu_node_t *
458 get_cpu_node_by_cpuid(int cpuid) {
459 cpumask_t mask;
461 CPUMASK_ASSBIT(mask, cpuid);
463 KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
465 return get_cpu_node_by_cpumask(cpu_root_node, mask);
468 /* Get the mask of siblings for level_type of a cpuid */
469 cpumask_t
470 get_cpumask_from_level(int cpuid,
471 uint8_t level_type)
473 cpu_node_t * node;
474 cpumask_t mask;
476 CPUMASK_ASSBIT(mask, cpuid);
478 KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
480 node = get_cpu_node_by_cpumask(cpu_root_node, mask);
482 if (node == NULL) {
483 CPUMASK_ASSZERO(mask);
484 return mask;
487 while (node != NULL) {
488 if (node->type == level_type) {
489 return node->members;
491 node = node->parent_node;
493 CPUMASK_ASSZERO(mask);
495 return mask;
498 static const cpu_node_t *
499 get_cpu_node_by_chipid2(const cpu_node_t *node, int chip_id)
501 int cpuid;
503 if (node->type != CHIP_LEVEL) {
504 const cpu_node_t *ret = NULL;
505 int i;
507 for (i = 0; i < node->child_no; ++i) {
508 ret = get_cpu_node_by_chipid2(node->child_node[i],
509 chip_id);
510 if (ret != NULL)
511 break;
513 return ret;
516 cpuid = BSRCPUMASK(node->members);
517 if (get_chip_ID(cpuid) == chip_id)
518 return node;
519 return NULL;
522 const cpu_node_t *
523 get_cpu_node_by_chipid(int chip_id)
525 KASSERT(cpu_root_node != NULL, ("cpu_root_node isn't initialized"));
526 return get_cpu_node_by_chipid2(cpu_root_node, chip_id);
529 /* init pcpu_sysctl structure info */
530 static void
531 init_pcpu_topology_sysctl(void)
533 int i;
534 cpumask_t mask;
535 struct sbuf sb;
537 for (i = 0; i < ncpus; i++) {
539 sbuf_new(&sb, pcpu_sysctl[i].cpu_name,
540 sizeof(pcpu_sysctl[i].cpu_name), SBUF_FIXEDLEN);
541 sbuf_printf(&sb,"cpu%d", i);
542 sbuf_finish(&sb);
545 /* Get physical siblings */
546 mask = get_cpumask_from_level(i, CHIP_LEVEL);
547 if (CPUMASK_TESTZERO(mask)) {
548 pcpu_sysctl[i].physical_id = INVALID_ID;
549 continue;
552 sbuf_new(&sb, pcpu_sysctl[i].physical_siblings,
553 sizeof(pcpu_sysctl[i].physical_siblings), SBUF_FIXEDLEN);
554 sbuf_print_cpuset(&sb, &mask);
555 sbuf_trim(&sb);
556 sbuf_finish(&sb);
558 pcpu_sysctl[i].physical_id = get_chip_ID(i);
560 /* Get core siblings */
561 mask = get_cpumask_from_level(i, CORE_LEVEL);
562 if (CPUMASK_TESTZERO(mask)) {
563 pcpu_sysctl[i].core_id = INVALID_ID;
564 continue;
567 sbuf_new(&sb, pcpu_sysctl[i].core_siblings,
568 sizeof(pcpu_sysctl[i].core_siblings), SBUF_FIXEDLEN);
569 sbuf_print_cpuset(&sb, &mask);
570 sbuf_trim(&sb);
571 sbuf_finish(&sb);
573 pcpu_sysctl[i].core_id = get_core_number_within_chip(i);
578 /* Build SYSCTL structure for revealing
579 * the CPU Topology to user-space.
581 static void
582 build_sysctl_cpu_topology(void)
584 int i;
585 struct sbuf sb;
587 /* SYSCTL new leaf for "cpu_topology" */
588 sysctl_ctx_init(&cpu_topology_sysctl_ctx);
589 cpu_topology_sysctl_tree = SYSCTL_ADD_NODE(&cpu_topology_sysctl_ctx,
590 SYSCTL_STATIC_CHILDREN(_hw),
591 OID_AUTO,
592 "cpu_topology",
593 CTLFLAG_RD, 0, "");
595 /* SYSCTL cpu_topology "tree" entry */
596 SYSCTL_ADD_PROC(&cpu_topology_sysctl_ctx,
597 SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
598 OID_AUTO, "tree", CTLTYPE_STRING | CTLFLAG_RD,
599 NULL, 0, print_cpu_topology_tree_sysctl, "A",
600 "Tree print of CPU topology");
602 /* SYSCTL cpu_topology "level_description" entry */
603 SYSCTL_ADD_PROC(&cpu_topology_sysctl_ctx,
604 SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
605 OID_AUTO, "level_description", CTLTYPE_STRING | CTLFLAG_RD,
606 NULL, 0, print_cpu_topology_level_description_sysctl, "A",
607 "Level description of CPU topology");
609 /* SYSCTL cpu_topology "members" entry */
610 sbuf_new(&sb, cpu_topology_members,
611 sizeof(cpu_topology_members), SBUF_FIXEDLEN);
612 sbuf_print_cpuset(&sb, &cpu_root_node->members);
613 sbuf_trim(&sb);
614 sbuf_finish(&sb);
615 SYSCTL_ADD_STRING(&cpu_topology_sysctl_ctx,
616 SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
617 OID_AUTO, "members", CTLFLAG_RD,
618 cpu_topology_members, 0,
619 "Members of the CPU Topology");
621 /* SYSCTL per_cpu info */
622 for (i = 0; i < ncpus; i++) {
623 /* New leaf : hw.cpu_topology.cpux */
624 sysctl_ctx_init(&pcpu_sysctl[i].sysctl_ctx);
625 pcpu_sysctl[i].sysctl_tree = SYSCTL_ADD_NODE(&pcpu_sysctl[i].sysctl_ctx,
626 SYSCTL_CHILDREN(cpu_topology_sysctl_tree),
627 OID_AUTO,
628 pcpu_sysctl[i].cpu_name,
629 CTLFLAG_RD, 0, "");
631 /* Check if the physical_id found is valid */
632 if (pcpu_sysctl[i].physical_id == INVALID_ID) {
633 continue;
636 /* Add physical id info */
637 SYSCTL_ADD_INT(&pcpu_sysctl[i].sysctl_ctx,
638 SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
639 OID_AUTO, "physical_id", CTLFLAG_RD,
640 &pcpu_sysctl[i].physical_id, 0,
641 "Physical ID");
643 /* Add physical siblings */
644 SYSCTL_ADD_STRING(&pcpu_sysctl[i].sysctl_ctx,
645 SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
646 OID_AUTO, "physical_siblings", CTLFLAG_RD,
647 pcpu_sysctl[i].physical_siblings, 0,
648 "Physical siblings");
650 /* Check if the core_id found is valid */
651 if (pcpu_sysctl[i].core_id == INVALID_ID) {
652 continue;
655 /* Add core id info */
656 SYSCTL_ADD_INT(&pcpu_sysctl[i].sysctl_ctx,
657 SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
658 OID_AUTO, "core_id", CTLFLAG_RD,
659 &pcpu_sysctl[i].core_id, 0,
660 "Core ID");
662 /*Add core siblings */
663 SYSCTL_ADD_STRING(&pcpu_sysctl[i].sysctl_ctx,
664 SYSCTL_CHILDREN(pcpu_sysctl[i].sysctl_tree),
665 OID_AUTO, "core_siblings", CTLFLAG_RD,
666 pcpu_sysctl[i].core_siblings, 0,
667 "Core siblings");
671 static
672 void
673 sbuf_print_cpuset(struct sbuf *sb, cpumask_t *mask)
675 int i;
676 int b = -1;
677 int e = -1;
678 int more = 0;
680 sbuf_printf(sb, "cpus(");
681 CPUSET_FOREACH(i, *mask) {
682 if (b < 0) {
683 b = i;
684 e = b + 1;
685 continue;
687 if (e == i) {
688 ++e;
689 continue;
691 if (more)
692 sbuf_printf(sb, ", ");
693 if (b == e - 1) {
694 sbuf_printf(sb, "%d", b);
695 } else {
696 sbuf_printf(sb, "%d-%d", b, e - 1);
698 more = 1;
699 b = i;
700 e = b + 1;
702 if (more)
703 sbuf_printf(sb, ", ");
704 if (b >= 0) {
705 if (b == e - 1) {
706 sbuf_printf(sb, "%d", b);
707 } else {
708 sbuf_printf(sb, "%d-%d", b, e - 1);
711 sbuf_printf(sb, ") ");
714 /* Build the CPU Topology and SYSCTL Topology tree */
715 static void
716 init_cpu_topology(void)
718 build_cpu_topology();
720 init_pcpu_topology_sysctl();
721 build_sysctl_cpu_topology();
723 SYSINIT(cpu_topology, SI_BOOT2_CPU_TOPOLOGY, SI_ORDER_FIRST,
724 init_cpu_topology, NULL);