]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/cpu_threads.c
7727eb7eac654bb9bf8482457ce7c4c6bba88bf6
[apple/xnu.git] / osfmk / i386 / cpu_threads.c
1 /*
2 * Copyright (c) 2003-2008 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28 #include <vm/vm_kern.h>
29 #include <kern/kalloc.h>
30 #include <mach/machine.h>
31 #include <i386/cpu_threads.h>
32 #include <i386/cpuid.h>
33 #include <i386/machine_cpu.h>
34 #include <i386/lock.h>
35 #include <i386/perfmon.h>
36 #include <i386/pmCPU.h>
37
38 //#define TOPO_DEBUG 1
39 #if TOPO_DEBUG
40 void debug_topology_print(void);
41 #define DBG(x...) kprintf("DBG: " x)
42 #else
43 #define DBG(x...)
44 #endif /* TOPO_DEBUG */
45
46 #define bitmask(h,l) ((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
47 #define bitfield(x,h,l) (((x) & bitmask(h,l)) >> l)
48
49 x86_pkg_t *x86_pkgs = NULL;
50 uint32_t num_Lx_caches[MAX_CACHE_DEPTH] = { 0 };
51
52 static x86_pkg_t *free_pkgs = NULL;
53 static x86_die_t *free_dies = NULL;
54 static x86_core_t *free_cores = NULL;
55 static uint32_t num_dies = 0;
56
57 static x86_cpu_cache_t *x86_caches = NULL;
58 static uint32_t num_caches = 0;
59
60 static boolean_t topoParmsInited = FALSE;
61 x86_topology_parameters_t topoParms;
62
63 decl_simple_lock_data(, x86_topo_lock);
64
65 static boolean_t
66 cpu_is_hyperthreaded(void)
67 {
68 i386_cpu_info_t *cpuinfo;
69
70 cpuinfo = cpuid_info();
71 return(cpuinfo->thread_count > cpuinfo->core_count);
72 }
73
74 static x86_cpu_cache_t *
75 x86_cache_alloc(void)
76 {
77 x86_cpu_cache_t *cache;
78 int i;
79
80 if (x86_caches == NULL) {
81 cache = kalloc(sizeof(x86_cpu_cache_t) + (MAX_CPUS * sizeof(x86_lcpu_t *)));
82 if (cache == NULL)
83 return(NULL);
84 } else {
85 cache = x86_caches;
86 x86_caches = cache->next;
87 cache->next = NULL;
88 }
89
90 bzero(cache, sizeof(x86_cpu_cache_t));
91 cache->next = NULL;
92 cache->maxcpus = MAX_CPUS;
93 for (i = 0; i < cache->maxcpus; i += 1) {
94 cache->cpus[i] = NULL;
95 }
96
97 num_caches += 1;
98
99 return(cache);
100 }
101
102 static void
103 x86_LLC_info(void)
104 {
105 uint32_t index;
106 uint32_t cache_info[4];
107 uint32_t cache_level = 0;
108 uint32_t nCPUsSharing = 1;
109 i386_cpu_info_t *cpuinfo;
110
111 cpuinfo = cpuid_info();
112
113 do_cpuid(0, cache_info);
114
115 if (cache_info[eax] < 4) {
116 /*
117 * Processor does not support deterministic
118 * cache information. Set LLC sharing to 1, since
119 * we have no better information.
120 */
121 if (cpu_is_hyperthreaded()) {
122 topoParms.nCoresSharingLLC = 1;
123 topoParms.nLCPUsSharingLLC = 2;
124 topoParms.maxSharingLLC = 2;
125 } else {
126 topoParms.nCoresSharingLLC = 1;
127 topoParms.nLCPUsSharingLLC = 1;
128 topoParms.maxSharingLLC = 1;
129 }
130 return;
131 }
132
133 for (index = 0; ; index += 1) {
134 uint32_t this_level;
135
136 cache_info[eax] = 4;
137 cache_info[ecx] = index;
138 cache_info[ebx] = 0;
139 cache_info[edx] = 0;
140
141 cpuid(cache_info);
142
143 /*
144 * See if all levels have been queried.
145 */
146 if (bitfield(cache_info[eax], 4, 0) == 0)
147 break;
148
149 /*
150 * Get the current level.
151 */
152 this_level = bitfield(cache_info[eax], 7, 5);
153
154 /*
155 * Only worry about it if it's a deeper level than
156 * what we've seen before.
157 */
158 if (this_level > cache_level) {
159 cache_level = this_level;
160
161 /*
162 * Save the number of CPUs sharing this cache.
163 */
164 nCPUsSharing = bitfield(cache_info[eax], 25, 14) + 1;
165 }
166 }
167
168 /*
169 * Make the level of the LLC be 0 based.
170 */
171 topoParms.LLCDepth = cache_level - 1;
172
173 /*
174 * nCPUsSharing represents the *maximum* number of cores or
175 * logical CPUs sharing the cache.
176 */
177 topoParms.maxSharingLLC = nCPUsSharing;
178
179 topoParms.nCoresSharingLLC = nCPUsSharing;
180 topoParms.nLCPUsSharingLLC = nCPUsSharing;
181
182 /*
183 * nCPUsSharing may not be the number of *active* cores or
184 * threads that are sharing the cache.
185 */
186 if (nCPUsSharing > cpuinfo->core_count)
187 topoParms.nCoresSharingLLC = cpuinfo->core_count;
188 if (nCPUsSharing > cpuinfo->thread_count)
189 topoParms.nLCPUsSharingLLC = cpuinfo->thread_count;
190
191
192 if (nCPUsSharing > cpuinfo->thread_count)
193 topoParms.maxSharingLLC = cpuinfo->thread_count;
194 }
195
196 static void
197 initTopoParms(void)
198 {
199 i386_cpu_info_t *cpuinfo;
200
201 cpuinfo = cpuid_info();
202
203 /*
204 * We need to start with getting the LLC information correct.
205 */
206 x86_LLC_info();
207
208 /*
209 * Compute the number of threads (logical CPUs) per core.
210 */
211 topoParms.nLThreadsPerCore = cpuinfo->thread_count / cpuinfo->core_count;
212 topoParms.nPThreadsPerCore = cpuinfo->cpuid_logical_per_package / cpuinfo->cpuid_cores_per_package;
213
214 /*
215 * Compute the number of dies per package.
216 */
217 topoParms.nLDiesPerPackage = cpuinfo->core_count / topoParms.nCoresSharingLLC;
218 topoParms.nPDiesPerPackage = cpuinfo->cpuid_cores_per_package / (topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
219
220 /*
221 * Compute the number of cores per die.
222 */
223 topoParms.nLCoresPerDie = topoParms.nCoresSharingLLC;
224 topoParms.nPCoresPerDie = (topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
225
226 /*
227 * Compute the number of threads per die.
228 */
229 topoParms.nLThreadsPerDie = topoParms.nLThreadsPerCore * topoParms.nLCoresPerDie;
230 topoParms.nPThreadsPerDie = topoParms.nPThreadsPerCore * topoParms.nPCoresPerDie;
231
232 /*
233 * Compute the number of cores per package.
234 */
235 topoParms.nLCoresPerPackage = topoParms.nLCoresPerDie * topoParms.nLDiesPerPackage;
236 topoParms.nPCoresPerPackage = topoParms.nPCoresPerDie * topoParms.nPDiesPerPackage;
237
238 /*
239 * Compute the number of threads per package.
240 */
241 topoParms.nLThreadsPerPackage = topoParms.nLThreadsPerCore * topoParms.nLCoresPerPackage;
242 topoParms.nPThreadsPerPackage = topoParms.nPThreadsPerCore * topoParms.nPCoresPerPackage;
243
244 DBG("\nLogical Topology Parameters:\n");
245 DBG("\tThreads per Core: %d\n", topoParms.nLThreadsPerCore);
246 DBG("\tCores per Die: %d\n", topoParms.nLCoresPerDie);
247 DBG("\tThreads per Die: %d\n", topoParms.nLThreadsPerDie);
248 DBG("\tDies per Package: %d\n", topoParms.nLDiesPerPackage);
249 DBG("\tCores per Package: %d\n", topoParms.nLCoresPerPackage);
250 DBG("\tThreads per Package: %d\n", topoParms.nLThreadsPerPackage);
251
252 DBG("\nPhysical Topology Parameters:\n");
253 DBG("\tThreads per Core: %d\n", topoParms.nPThreadsPerCore);
254 DBG("\tCores per Die: %d\n", topoParms.nPCoresPerDie);
255 DBG("\tThreads per Die: %d\n", topoParms.nPThreadsPerDie);
256 DBG("\tDies per Package: %d\n", topoParms.nPDiesPerPackage);
257 DBG("\tCores per Package: %d\n", topoParms.nPCoresPerPackage);
258 DBG("\tThreads per Package: %d\n", topoParms.nPThreadsPerPackage);
259
260 topoParmsInited = TRUE;
261 }
262
263 static void
264 x86_cache_free(x86_cpu_cache_t *cache)
265 {
266 num_caches -= 1;
267 if (cache->level > 0 && cache->level <= MAX_CACHE_DEPTH)
268 num_Lx_caches[cache->level - 1] -= 1;
269 cache->next = x86_caches;
270 x86_caches = cache;
271 }
272
273 /*
274 * This returns a list of cache structures that represent the
275 * caches for a CPU. Some of the structures may have to be
276 * "freed" if they are actually shared between CPUs.
277 */
278 static x86_cpu_cache_t *
279 x86_cache_list(void)
280 {
281 x86_cpu_cache_t *root = NULL;
282 x86_cpu_cache_t *cur = NULL;
283 x86_cpu_cache_t *last = NULL;
284 uint32_t index;
285 uint32_t cache_info[4];
286 uint32_t nsets;
287
288 do_cpuid(0, cache_info);
289
290 if (cache_info[eax] < 4) {
291 /*
292 * Processor does not support deterministic
293 * cache information. Don't report anything
294 */
295 return NULL;
296 }
297
298 for (index = 0; ; index += 1) {
299 cache_info[eax] = 4;
300 cache_info[ecx] = index;
301 cache_info[ebx] = 0;
302 cache_info[edx] = 0;
303
304 cpuid(cache_info);
305
306 /*
307 * See if all levels have been queried.
308 */
309 if (bitfield(cache_info[eax], 4, 0) == 0)
310 break;
311
312 cur = x86_cache_alloc();
313 if (cur == NULL) {
314 break;
315 }
316
317 cur->type = bitfield(cache_info[eax], 4, 0);
318 cur->level = bitfield(cache_info[eax], 7, 5);
319 cur->maxcpus = (bitfield(cache_info[eax], 25, 14) + 1);
320 cur->line_size = bitfield(cache_info[ebx], 11, 0) + 1;
321 cur->partitions = bitfield(cache_info[ebx], 21, 12) + 1;
322 cur->ways = bitfield(cache_info[ebx], 31, 22) + 1;
323 nsets = bitfield(cache_info[ecx], 31, 0) + 1;
324 cur->cache_size = cur->line_size * cur->ways * cur->partitions * nsets;
325
326 if (last == NULL) {
327 root = cur;
328 last = cur;
329 } else {
330 last->next = cur;
331 last = cur;
332 }
333
334 cur->nlcpus = 0;
335 num_Lx_caches[cur->level - 1] += 1;
336 }
337
338 return(root);
339 }
340
341 static x86_cpu_cache_t *
342 x86_match_cache(x86_cpu_cache_t *list, x86_cpu_cache_t *matcher)
343 {
344 x86_cpu_cache_t *cur_cache;
345
346 cur_cache = list;
347 while (cur_cache != NULL) {
348 if (cur_cache->maxcpus == matcher->maxcpus
349 && cur_cache->type == matcher->type
350 && cur_cache->level == matcher->level
351 && cur_cache->ways == matcher->ways
352 && cur_cache->partitions == matcher->partitions
353 && cur_cache->line_size == matcher->line_size
354 && cur_cache->cache_size == matcher->cache_size)
355 break;
356
357 cur_cache = cur_cache->next;
358 }
359
360 return(cur_cache);
361 }
362
363 static void
364 x86_lcpu_init(int cpu)
365 {
366 cpu_data_t *cpup;
367 x86_lcpu_t *lcpu;
368 int i;
369
370 cpup = cpu_datap(cpu);
371
372 lcpu = &cpup->lcpu;
373 lcpu->lcpu = lcpu;
374 lcpu->cpu = cpup;
375 lcpu->next_in_core = NULL;
376 lcpu->next_in_die = NULL;
377 lcpu->next_in_pkg = NULL;
378 lcpu->core = NULL;
379 lcpu->die = NULL;
380 lcpu->package = NULL;
381 lcpu->cpu_num = cpu;
382 lcpu->lnum = cpu;
383 lcpu->pnum = cpup->cpu_phys_number;
384 lcpu->state = LCPU_OFF;
385 for (i = 0; i < MAX_CACHE_DEPTH; i += 1)
386 lcpu->caches[i] = NULL;
387
388 lcpu->master = (lcpu->cpu_num == (unsigned int) master_cpu);
389 lcpu->primary = (lcpu->pnum % topoParms.nPThreadsPerPackage) == 0;
390 }
391
392 static x86_core_t *
393 x86_core_alloc(int cpu)
394 {
395 x86_core_t *core;
396 cpu_data_t *cpup;
397
398 cpup = cpu_datap(cpu);
399
400 simple_lock(&x86_topo_lock);
401 if (free_cores != NULL) {
402 core = free_cores;
403 free_cores = core->next_in_die;
404 core->next_in_die = NULL;
405 simple_unlock(&x86_topo_lock);
406 } else {
407 simple_unlock(&x86_topo_lock);
408 core = kalloc(sizeof(x86_core_t));
409 if (core == NULL)
410 panic("x86_core_alloc() kalloc of x86_core_t failed!\n");
411 }
412
413 bzero((void *) core, sizeof(x86_core_t));
414
415 core->pcore_num = cpup->cpu_phys_number / topoParms.nPThreadsPerCore;
416 core->lcore_num = core->pcore_num % topoParms.nPCoresPerPackage;
417
418 core->flags = X86CORE_FL_PRESENT | X86CORE_FL_READY
419 | X86CORE_FL_HALTED | X86CORE_FL_IDLE;
420
421 return(core);
422 }
423
424 static void
425 x86_core_free(x86_core_t *core)
426 {
427 simple_lock(&x86_topo_lock);
428 core->next_in_die = free_cores;
429 free_cores = core;
430 simple_unlock(&x86_topo_lock);
431 }
432
433 static x86_pkg_t *
434 x86_package_find(int cpu)
435 {
436 x86_pkg_t *pkg;
437 cpu_data_t *cpup;
438 uint32_t pkg_num;
439
440 cpup = cpu_datap(cpu);
441
442 pkg_num = cpup->cpu_phys_number / topoParms.nPThreadsPerPackage;
443
444 pkg = x86_pkgs;
445 while (pkg != NULL) {
446 if (pkg->ppkg_num == pkg_num)
447 break;
448 pkg = pkg->next;
449 }
450
451 return(pkg);
452 }
453
454 static x86_die_t *
455 x86_die_find(int cpu)
456 {
457 x86_die_t *die;
458 x86_pkg_t *pkg;
459 cpu_data_t *cpup;
460 uint32_t die_num;
461
462 cpup = cpu_datap(cpu);
463
464 die_num = cpup->cpu_phys_number / topoParms.nPThreadsPerDie;
465
466 pkg = x86_package_find(cpu);
467 if (pkg == NULL)
468 return(NULL);
469
470 die = pkg->dies;
471 while (die != NULL) {
472 if (die->pdie_num == die_num)
473 break;
474 die = die->next_in_pkg;
475 }
476
477 return(die);
478 }
479
480 static x86_core_t *
481 x86_core_find(int cpu)
482 {
483 x86_core_t *core;
484 x86_die_t *die;
485 cpu_data_t *cpup;
486 uint32_t core_num;
487
488 cpup = cpu_datap(cpu);
489
490 core_num = cpup->cpu_phys_number / topoParms.nPThreadsPerCore;
491
492 die = x86_die_find(cpu);
493 if (die == NULL)
494 return(NULL);
495
496 core = die->cores;
497 while (core != NULL) {
498 if (core->pcore_num == core_num)
499 break;
500 core = core->next_in_die;
501 }
502
503 return(core);
504 }
505
506 void
507 x86_set_lcpu_numbers(x86_lcpu_t *lcpu)
508 {
509 lcpu->lnum = lcpu->cpu_num % topoParms.nLThreadsPerCore;
510 }
511
512 void
513 x86_set_core_numbers(x86_core_t *core, x86_lcpu_t *lcpu)
514 {
515 core->pcore_num = lcpu->cpu_num / topoParms.nLThreadsPerCore;
516 core->lcore_num = core->pcore_num % topoParms.nLCoresPerDie;
517 }
518
519 void
520 x86_set_die_numbers(x86_die_t *die, x86_lcpu_t *lcpu)
521 {
522 die->pdie_num = lcpu->cpu_num / (topoParms.nLThreadsPerCore * topoParms.nLCoresPerDie);
523 die->ldie_num = die->pdie_num % topoParms.nLDiesPerPackage;
524 }
525
526 void
527 x86_set_pkg_numbers(x86_pkg_t *pkg, x86_lcpu_t *lcpu)
528 {
529 pkg->ppkg_num = lcpu->cpu_num / topoParms.nLThreadsPerPackage;
530 pkg->lpkg_num = pkg->ppkg_num;
531 }
532
533 static x86_die_t *
534 x86_die_alloc(int cpu)
535 {
536 x86_die_t *die;
537 cpu_data_t *cpup;
538
539 cpup = cpu_datap(cpu);
540
541 simple_lock(&x86_topo_lock);
542 if (free_dies != NULL) {
543 die = free_dies;
544 free_dies = die->next_in_pkg;
545 die->next_in_pkg = NULL;
546 simple_unlock(&x86_topo_lock);
547 } else {
548 simple_unlock(&x86_topo_lock);
549 die = kalloc(sizeof(x86_die_t));
550 if (die == NULL)
551 panic("x86_die_alloc() kalloc of x86_die_t failed!\n");
552 }
553
554 bzero((void *) die, sizeof(x86_die_t));
555
556 die->pdie_num = cpup->cpu_phys_number / topoParms.nPThreadsPerDie;
557
558 die->ldie_num = num_dies;
559 atomic_incl((long *) &num_dies, 1);
560
561 die->flags = X86DIE_FL_PRESENT;
562 return(die);
563 }
564
565 static void
566 x86_die_free(x86_die_t *die)
567 {
568 simple_lock(&x86_topo_lock);
569 die->next_in_pkg = free_dies;
570 free_dies = die;
571 atomic_decl((long *) &num_dies, 1);
572 simple_unlock(&x86_topo_lock);
573 }
574
575 static x86_pkg_t *
576 x86_package_alloc(int cpu)
577 {
578 x86_pkg_t *pkg;
579 cpu_data_t *cpup;
580
581 cpup = cpu_datap(cpu);
582
583 simple_lock(&x86_topo_lock);
584 if (free_pkgs != NULL) {
585 pkg = free_pkgs;
586 free_pkgs = pkg->next;
587 pkg->next = NULL;
588 simple_unlock(&x86_topo_lock);
589 } else {
590 simple_unlock(&x86_topo_lock);
591 pkg = kalloc(sizeof(x86_pkg_t));
592 if (pkg == NULL)
593 panic("x86_package_alloc() kalloc of x86_pkg_t failed!\n");
594 }
595
596 bzero((void *) pkg, sizeof(x86_pkg_t));
597
598 pkg->ppkg_num = cpup->cpu_phys_number / topoParms.nPThreadsPerPackage;
599
600 pkg->lpkg_num = topoParms.nPackages;
601 atomic_incl((long *) &topoParms.nPackages, 1);
602
603 pkg->flags = X86PKG_FL_PRESENT | X86PKG_FL_READY;
604 return(pkg);
605 }
606
607 static void
608 x86_package_free(x86_pkg_t *pkg)
609 {
610 simple_lock(&x86_topo_lock);
611 pkg->next = free_pkgs;
612 free_pkgs = pkg;
613 atomic_decl((long *) &topoParms.nPackages, 1);
614 simple_unlock(&x86_topo_lock);
615 }
616
617 static void
618 x86_cache_add_lcpu(x86_cpu_cache_t *cache, x86_lcpu_t *lcpu)
619 {
620 x86_cpu_cache_t *cur_cache;
621 int i;
622
623 /*
624 * Put the new CPU into the list of the cache.
625 */
626 cur_cache = lcpu->caches[cache->level - 1];
627 lcpu->caches[cache->level - 1] = cache;
628 cache->next = cur_cache;
629 cache->nlcpus += 1;
630 for (i = 0; i < cache->nlcpus; i += 1) {
631 if (cache->cpus[i] == NULL) {
632 cache->cpus[i] = lcpu;
633 break;
634 }
635 }
636 }
637
638 static void
639 x86_lcpu_add_caches(x86_lcpu_t *lcpu)
640 {
641 x86_cpu_cache_t *list;
642 x86_cpu_cache_t *cur;
643 x86_cpu_cache_t *match;
644 x86_die_t *die;
645 x86_core_t *core;
646 x86_lcpu_t *cur_lcpu;
647 uint32_t level;
648 boolean_t found = FALSE;
649
650 assert(lcpu != NULL);
651
652 /*
653 * Add the cache data to the topology.
654 */
655 list = x86_cache_list();
656
657 simple_lock(&x86_topo_lock);
658
659 while (list != NULL) {
660 /*
661 * Remove the cache from the front of the list.
662 */
663 cur = list;
664 list = cur->next;
665 cur->next = NULL;
666 level = cur->level - 1;
667
668 /*
669 * If the cache isn't shared then just put it where it
670 * belongs.
671 */
672 if (cur->maxcpus == 1) {
673 x86_cache_add_lcpu(cur, lcpu);
674 continue;
675 }
676
677 /*
678 * We'll assume that all of the caches at a particular level
679 * have the same sharing. So if we have a cache already at
680 * this level, we'll just skip looking for the match.
681 */
682 if (lcpu->caches[level] != NULL) {
683 x86_cache_free(cur);
684 continue;
685 }
686
687 /*
688 * This is a shared cache, so we have to figure out if
689 * this is the first time we've seen this cache. We do
690 * this by searching through the topology and seeing if
691 * this cache is already described.
692 *
693 * Assume that L{LLC-1} are all at the core level and that
694 * LLC is shared at the die level.
695 */
696 if (level < topoParms.LLCDepth) {
697 /*
698 * Shared at the core.
699 */
700 core = lcpu->core;
701 cur_lcpu = core->lcpus;
702 while (cur_lcpu != NULL) {
703 /*
704 * Skip ourselves.
705 */
706 if (cur_lcpu == lcpu) {
707 cur_lcpu = cur_lcpu->next_in_core;
708 continue;
709 }
710
711 /*
712 * If there's a cache on this logical CPU,
713 * then use that one.
714 */
715 match = x86_match_cache(cur_lcpu->caches[level], cur);
716 if (match != NULL) {
717 x86_cache_free(cur);
718 x86_cache_add_lcpu(match, lcpu);
719 found = TRUE;
720 break;
721 }
722
723 cur_lcpu = cur_lcpu->next_in_core;
724 }
725 } else {
726 /*
727 * Shared at the die.
728 */
729 die = lcpu->die;
730 cur_lcpu = die->lcpus;
731 while (cur_lcpu != NULL) {
732 /*
733 * Skip ourselves.
734 */
735 if (cur_lcpu == lcpu) {
736 cur_lcpu = cur_lcpu->next_in_die;
737 continue;
738 }
739
740 /*
741 * If there's a cache on this logical CPU,
742 * then use that one.
743 */
744 match = x86_match_cache(cur_lcpu->caches[level], cur);
745 if (match != NULL) {
746 x86_cache_free(cur);
747 x86_cache_add_lcpu(match, lcpu);
748 found = TRUE;
749 break;
750 }
751
752 cur_lcpu = cur_lcpu->next_in_die;
753 }
754 }
755
756 /*
757 * If a shared cache wasn't found, then this logical CPU must
758 * be the first one encountered.
759 */
760 if (!found) {
761 x86_cache_add_lcpu(cur, lcpu);
762 }
763 }
764
765 simple_unlock(&x86_topo_lock);
766 }
767
768 static void
769 x86_core_add_lcpu(x86_core_t *core, x86_lcpu_t *lcpu)
770 {
771 assert(core != NULL);
772 assert(lcpu != NULL);
773
774 simple_lock(&x86_topo_lock);
775
776 lcpu->next_in_core = core->lcpus;
777 lcpu->core = core;
778 core->lcpus = lcpu;
779 core->num_lcpus += 1;
780 simple_unlock(&x86_topo_lock);
781 }
782
783 static void
784 x86_die_add_lcpu(x86_die_t *die, x86_lcpu_t *lcpu)
785 {
786 assert(die != NULL);
787 assert(lcpu != NULL);
788
789 lcpu->next_in_die = die->lcpus;
790 lcpu->die = die;
791 die->lcpus = lcpu;
792 }
793
794 static void
795 x86_die_add_core(x86_die_t *die, x86_core_t *core)
796 {
797 assert(die != NULL);
798 assert(core != NULL);
799
800 core->next_in_die = die->cores;
801 core->die = die;
802 die->cores = core;
803 die->num_cores += 1;
804 }
805
806 static void
807 x86_package_add_lcpu(x86_pkg_t *pkg, x86_lcpu_t *lcpu)
808 {
809 assert(pkg != NULL);
810 assert(lcpu != NULL);
811
812 lcpu->next_in_pkg = pkg->lcpus;
813 lcpu->package = pkg;
814 pkg->lcpus = lcpu;
815 }
816
817 static void
818 x86_package_add_core(x86_pkg_t *pkg, x86_core_t *core)
819 {
820 assert(pkg != NULL);
821 assert(core != NULL);
822
823 core->next_in_pkg = pkg->cores;
824 core->package = pkg;
825 pkg->cores = core;
826 }
827
828 static void
829 x86_package_add_die(x86_pkg_t *pkg, x86_die_t *die)
830 {
831 assert(pkg != NULL);
832 assert(die != NULL);
833
834 die->next_in_pkg = pkg->dies;
835 die->package = pkg;
836 pkg->dies = die;
837 pkg->num_dies += 1;
838 }
839
840 void *
841 cpu_thread_alloc(int cpu)
842 {
843 x86_core_t *core = NULL;
844 x86_die_t *die = NULL;
845 x86_pkg_t *pkg = NULL;
846 cpu_data_t *cpup;
847 uint32_t phys_cpu;
848
849 /*
850 * Only allow one to manipulate the topology at a time.
851 */
852 simple_lock(&x86_topo_lock);
853
854 /*
855 * Make sure all of the topology parameters have been initialized.
856 */
857 if (!topoParmsInited)
858 initTopoParms();
859
860 cpup = cpu_datap(cpu);
861
862 phys_cpu = cpup->cpu_phys_number;
863
864 x86_lcpu_init(cpu);
865
866 /*
867 * Allocate performance counter structure.
868 */
869 simple_unlock(&x86_topo_lock);
870 cpup->lcpu.pmc = pmc_alloc();
871 simple_lock(&x86_topo_lock);
872
873 /*
874 * Assume that all cpus have the same features.
875 */
876 if (cpu_is_hyperthreaded()) {
877 cpup->cpu_threadtype = CPU_THREADTYPE_INTEL_HTT;
878 } else {
879 cpup->cpu_threadtype = CPU_THREADTYPE_NONE;
880 }
881
882 /*
883 * Get the package that the logical CPU is in.
884 */
885 do {
886 pkg = x86_package_find(cpu);
887 if (pkg == NULL) {
888 /*
889 * Package structure hasn't been created yet, do it now.
890 */
891 simple_unlock(&x86_topo_lock);
892 pkg = x86_package_alloc(cpu);
893 simple_lock(&x86_topo_lock);
894 if (x86_package_find(cpu) != NULL) {
895 x86_package_free(pkg);
896 continue;
897 }
898
899 /*
900 * Add the new package to the global list of packages.
901 */
902 pkg->next = x86_pkgs;
903 x86_pkgs = pkg;
904 }
905 } while (pkg == NULL);
906
907 /*
908 * Get the die that the logical CPU is in.
909 */
910 do {
911 die = x86_die_find(cpu);
912 if (die == NULL) {
913 /*
914 * Die structure hasn't been created yet, do it now.
915 */
916 simple_unlock(&x86_topo_lock);
917 die = x86_die_alloc(cpu);
918 simple_lock(&x86_topo_lock);
919 if (x86_die_find(cpu) != NULL) {
920 x86_die_free(die);
921 continue;
922 }
923
924 /*
925 * Add the die to the package.
926 */
927 x86_package_add_die(pkg, die);
928 }
929 } while (die == NULL);
930
931 /*
932 * Get the core for this logical CPU.
933 */
934 do {
935 core = x86_core_find(cpu);
936 if (core == NULL) {
937 /*
938 * Allocate the core structure now.
939 */
940 simple_unlock(&x86_topo_lock);
941 core = x86_core_alloc(cpu);
942 simple_lock(&x86_topo_lock);
943 if (x86_core_find(cpu) != NULL) {
944 x86_core_free(core);
945 continue;
946 }
947
948 /*
949 * Add the core to the die & package.
950 */
951 x86_die_add_core(die, core);
952 x86_package_add_core(pkg, core);
953 machine_info.physical_cpu_max += 1;
954 }
955 } while (core == NULL);
956
957
958 /*
959 * Done manipulating the topology, so others can get in.
960 */
961 machine_info.logical_cpu_max += 1;
962 simple_unlock(&x86_topo_lock);
963
964 /*
965 * Add the logical CPU to the other topology structures.
966 */
967 x86_core_add_lcpu(core, &cpup->lcpu);
968 x86_die_add_lcpu(core->die, &cpup->lcpu);
969 x86_package_add_lcpu(core->package, &cpup->lcpu);
970 x86_lcpu_add_caches(&cpup->lcpu);
971
972 return (void *) core;
973 }
974
975 void
976 cpu_thread_init(void)
977 {
978 int my_cpu = get_cpu_number();
979 cpu_data_t *cpup = current_cpu_datap();
980 x86_core_t *core;
981 static int initialized = 0;
982
983 /*
984 * If we're the boot processor, we do all of the initialization of
985 * the CPU topology infrastructure.
986 */
987 if (my_cpu == master_cpu && !initialized) {
988 simple_lock_init(&x86_topo_lock, 0);
989
990 /*
991 * Put this logical CPU into the physical CPU topology.
992 */
993 cpup->lcpu.core = cpu_thread_alloc(my_cpu);
994
995 initialized = 1;
996 }
997
998 /*
999 * Do the CPU accounting.
1000 */
1001 core = cpup->lcpu.core;
1002 simple_lock(&x86_topo_lock);
1003 machine_info.logical_cpu += 1;
1004 if (core->active_lcpus == 0)
1005 machine_info.physical_cpu += 1;
1006 core->active_lcpus += 1;
1007 simple_unlock(&x86_topo_lock);
1008
1009 pmCPUMarkRunning(cpup);
1010 etimer_resync_deadlines();
1011 }
1012
1013 /*
1014 * Called for a cpu to halt permanently
1015 * (as opposed to halting and expecting an interrupt to awaken it).
1016 */
1017 void
1018 cpu_thread_halt(void)
1019 {
1020 x86_core_t *core;
1021 cpu_data_t *cpup = current_cpu_datap();
1022
1023 simple_lock(&x86_topo_lock);
1024 machine_info.logical_cpu -= 1;
1025 core = cpup->lcpu.core;
1026 core->active_lcpus -= 1;
1027 if (core->active_lcpus == 0)
1028 machine_info.physical_cpu -= 1;
1029 simple_unlock(&x86_topo_lock);
1030
1031 /*
1032 * Let the power management code determine the best way to "stop"
1033 * the processor.
1034 */
1035 ml_set_interrupts_enabled(FALSE);
1036 while (1) {
1037 pmCPUHalt(PM_HALT_NORMAL);
1038 }
1039 /* NOT REACHED */
1040 }
1041
1042 #if TOPO_DEBUG
1043 /*
1044 * Prints out the topology
1045 */
1046 void
1047 debug_topology_print(void)
1048 {
1049 x86_pkg_t *pkg;
1050 x86_die_t *die;
1051 x86_core_t *core;
1052 x86_lcpu_t *cpu;
1053
1054 pkg = x86_pkgs;
1055 while (pkg != NULL) {
1056 kprintf("Package:\n");
1057 kprintf(" Physical: %d\n", pkg->ppkg_num);
1058 kprintf(" Logical: %d\n", pkg->lpkg_num);
1059
1060 die = pkg->dies;
1061 while (die != NULL) {
1062 kprintf(" Die:\n");
1063 kprintf(" Physical: %d\n", die->pdie_num);
1064 kprintf(" Logical: %d\n", die->ldie_num);
1065
1066 core = die->cores;
1067 while (core != NULL) {
1068 kprintf(" Core:\n");
1069 kprintf(" Physical: %d\n", core->pcore_num);
1070 kprintf(" Logical: %d\n", core->lcore_num);
1071
1072 cpu = core->lcpus;
1073 while (cpu != NULL) {
1074 kprintf(" LCPU:\n");
1075 kprintf(" CPU #: %d\n", cpu->cpu_num);
1076 kprintf(" Physical: %d\n", cpu->pnum);
1077 kprintf(" Logical: %d\n", cpu->lnum);
1078 kprintf(" Flags: ");
1079 if (cpu->master)
1080 kprintf("MASTER ");
1081 if (cpu->primary)
1082 kprintf("PRIMARY");
1083 if (!cpu->master && !cpu->primary)
1084 kprintf("(NONE)");
1085 kprintf("\n");
1086
1087 cpu = cpu->next_in_core;
1088 }
1089
1090 core = core->next_in_die;
1091 }
1092
1093 die = die->next_in_pkg;
1094 }
1095
1096 pkg = pkg->next;
1097 }
1098 }
1099 #endif /* TOPO_DEBUG */