]> git.saurik.com Git - apple/xnu.git/blame - osfmk/i386/cpu_threads.c
xnu-7195.101.1.tar.gz
[apple/xnu.git] / osfmk / i386 / cpu_threads.c
CommitLineData
91447636 1/*
39037602 2 * Copyright (c) 2003-2016 Apple Inc. All rights reserved.
91447636 3 *
2d21ac55 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
2d21ac55
A
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.
0a7de745 14 *
2d21ac55
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
2d21ac55
A
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
8f6c56a5
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2d21ac55
A
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.
0a7de745 25 *
2d21ac55 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
91447636
A
27 */
28#include <vm/vm_kern.h>
f427ee49 29#include <kern/zalloc.h>
0a7de745 30#include <kern/lock_group.h>
39236c6e 31#include <kern/timer_queue.h>
91447636
A
32#include <mach/machine.h>
33#include <i386/cpu_threads.h>
34#include <i386/cpuid.h>
35#include <i386/machine_cpu.h>
2d21ac55 36#include <i386/pmCPU.h>
fe8ab488 37#include <i386/bit_routines.h>
2d21ac55 38
5ba3f43e
A
39#if MONOTONIC
40#include <kern/monotonic.h>
41#endif /* MONOTONIC */
42
0a7de745
A
43#define DIVISOR_GUARD(denom) \
44 if ((denom) == 0) { \
45 kprintf("%s: %d Zero divisor: " #denom, \
46 __FILE__, __LINE__); \
7ddcb079 47 }
b0d623f7 48
7ddcb079 49static void debug_topology_print(void);
c910b4d9 50
0a7de745 51boolean_t topo_dbg = FALSE;
91447636 52
0a7de745
A
53x86_pkg_t *x86_pkgs = NULL;
54uint32_t num_Lx_caches[MAX_CACHE_DEPTH] = { 0 };
2d21ac55 55
0a7de745
A
56static x86_pkg_t *free_pkgs = NULL;
57static x86_die_t *free_dies = NULL;
58static x86_core_t *free_cores = NULL;
59static uint32_t num_dies = 0;
2d21ac55 60
0a7de745
A
61static x86_cpu_cache_t *x86_caches = NULL;
62static uint32_t num_caches = 0;
2d21ac55 63
0a7de745
A
64static boolean_t topoParmsInited = FALSE;
65x86_topology_parameters_t topoParms;
593a1d5f 66
2d21ac55 67decl_simple_lock_data(, x86_topo_lock);
0a7de745 68
7ddcb079 69static struct cpu_cache {
0a7de745
A
70 int level; int type;
71} cpu_caches[LCACHE_MAX] = {
72 [L1D] = { 1, CPU_CACHE_TYPE_DATA },
73 [L1I] = { 1, CPU_CACHE_TYPE_INST },
74 [L2U] = { 2, CPU_CACHE_TYPE_UNIF },
75 [L3U] = { 3, CPU_CACHE_TYPE_UNIF },
7ddcb079
A
76};
77
593a1d5f
A
78static boolean_t
79cpu_is_hyperthreaded(void)
80{
0a7de745 81 i386_cpu_info_t *cpuinfo;
593a1d5f 82
0a7de745
A
83 cpuinfo = cpuid_info();
84 return cpuinfo->thread_count > cpuinfo->core_count;
593a1d5f 85}
2d21ac55
A
86
87static x86_cpu_cache_t *
88x86_cache_alloc(void)
89{
0a7de745
A
90 x86_cpu_cache_t *cache;
91 int i;
92
93 if (x86_caches == NULL) {
f427ee49
A
94 cache = zalloc_permanent(sizeof(x86_cpu_cache_t) +
95 (MAX_CPUS * sizeof(x86_lcpu_t *)), ZALIGN(x86_cpu_cache_t));
0a7de745
A
96 if (cache == NULL) {
97 return NULL;
98 }
99 } else {
100 cache = x86_caches;
101 x86_caches = cache->next;
102 cache->next = NULL;
103 }
2d21ac55 104
0a7de745
A
105 cache->next = NULL;
106 cache->maxcpus = MAX_CPUS;
107 for (i = 0; i < cache->maxcpus; i += 1) {
108 cache->cpus[i] = NULL;
109 }
2d21ac55 110
0a7de745 111 num_caches += 1;
2d21ac55 112
0a7de745 113 return cache;
2d21ac55 114}
0a7de745 115
593a1d5f
A
116static void
117x86_LLC_info(void)
118{
0a7de745
A
119 int cache_level = 0;
120 uint32_t nCPUsSharing = 1;
121 i386_cpu_info_t *cpuinfo;
122 struct cpu_cache *cachep;
123 int i;
593a1d5f 124
0a7de745 125 cpuinfo = cpuid_info();
593a1d5f 126
0a7de745
A
127 for (i = 0, cachep = &cpu_caches[0]; i < LCACHE_MAX; i++, cachep++) {
128 if (cachep->type == 0 || cpuid_info()->cache_size[i] == 0) {
129 continue;
130 }
593a1d5f 131
0a7de745
A
132 /*
133 * Only worry about it if it's a deeper level than
134 * what we've seen before.
135 */
136 if (cachep->level > cache_level) {
137 cache_level = cachep->level;
138
139 /*
140 * Save the number of CPUs sharing this cache.
141 */
142 nCPUsSharing = cpuinfo->cache_sharing[i];
143 }
144 }
593a1d5f
A
145
146 /*
0a7de745 147 * Make the level of the LLC be 0 based.
593a1d5f 148 */
0a7de745 149 topoParms.LLCDepth = cache_level - 1;
593a1d5f 150
0a7de745
A
151 /*
152 * nCPUsSharing represents the *maximum* number of cores or
153 * logical CPUs sharing the cache.
154 */
155 topoParms.maxSharingLLC = nCPUsSharing;
156
157 topoParms.nCoresSharingLLC = nCPUsSharing / (cpuinfo->thread_count /
158 cpuinfo->core_count);
159 topoParms.nLCPUsSharingLLC = nCPUsSharing;
160
161 /*
162 * nCPUsSharing may not be the number of *active* cores or
163 * threads that are sharing the cache.
164 */
165 if (nCPUsSharing > cpuinfo->core_count) {
166 topoParms.nCoresSharingLLC = cpuinfo->core_count;
167 }
168 if (nCPUsSharing > cpuinfo->thread_count) {
169 topoParms.nLCPUsSharingLLC = cpuinfo->thread_count;
593a1d5f 170 }
593a1d5f
A
171}
172
173static void
174initTopoParms(void)
175{
0a7de745
A
176 i386_cpu_info_t *cpuinfo;
177
178 topoParms.stable = FALSE;
179
180 cpuinfo = cpuid_info();
181
182 PE_parse_boot_argn("-topo", &topo_dbg, sizeof(topo_dbg));
183
184 /*
185 * We need to start with getting the LLC information correct.
186 */
187 x86_LLC_info();
188
189 /*
190 * Compute the number of threads (logical CPUs) per core.
191 */
192 DIVISOR_GUARD(cpuinfo->core_count);
193 topoParms.nLThreadsPerCore = cpuinfo->thread_count / cpuinfo->core_count;
194 DIVISOR_GUARD(cpuinfo->cpuid_cores_per_package);
195 topoParms.nPThreadsPerCore = cpuinfo->cpuid_logical_per_package / cpuinfo->cpuid_cores_per_package;
196
197 /*
198 * Compute the number of dies per package.
199 */
200 DIVISOR_GUARD(topoParms.nCoresSharingLLC);
201 topoParms.nLDiesPerPackage = cpuinfo->core_count / topoParms.nCoresSharingLLC;
202 DIVISOR_GUARD(topoParms.nPThreadsPerCore);
203 DIVISOR_GUARD(topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
204 topoParms.nPDiesPerPackage = cpuinfo->cpuid_cores_per_package / (topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
205
206
207 /*
208 * Compute the number of cores per die.
209 */
210 topoParms.nLCoresPerDie = topoParms.nCoresSharingLLC;
211 topoParms.nPCoresPerDie = (topoParms.maxSharingLLC / topoParms.nPThreadsPerCore);
212
213 /*
214 * Compute the number of threads per die.
215 */
216 topoParms.nLThreadsPerDie = topoParms.nLThreadsPerCore * topoParms.nLCoresPerDie;
217 topoParms.nPThreadsPerDie = topoParms.nPThreadsPerCore * topoParms.nPCoresPerDie;
218
219 /*
220 * Compute the number of cores per package.
221 */
222 topoParms.nLCoresPerPackage = topoParms.nLCoresPerDie * topoParms.nLDiesPerPackage;
223 topoParms.nPCoresPerPackage = topoParms.nPCoresPerDie * topoParms.nPDiesPerPackage;
224
225 /*
226 * Compute the number of threads per package.
227 */
228 topoParms.nLThreadsPerPackage = topoParms.nLThreadsPerCore * topoParms.nLCoresPerPackage;
229 topoParms.nPThreadsPerPackage = topoParms.nPThreadsPerCore * topoParms.nPCoresPerPackage;
230
231 TOPO_DBG("\nCache Topology Parameters:\n");
232 TOPO_DBG("\tLLC Depth: %d\n", topoParms.LLCDepth);
233 TOPO_DBG("\tCores Sharing LLC: %d\n", topoParms.nCoresSharingLLC);
234 TOPO_DBG("\tThreads Sharing LLC: %d\n", topoParms.nLCPUsSharingLLC);
235 TOPO_DBG("\tmax Sharing of LLC: %d\n", topoParms.maxSharingLLC);
236
237 TOPO_DBG("\nLogical Topology Parameters:\n");
238 TOPO_DBG("\tThreads per Core: %d\n", topoParms.nLThreadsPerCore);
239 TOPO_DBG("\tCores per Die: %d\n", topoParms.nLCoresPerDie);
240 TOPO_DBG("\tThreads per Die: %d\n", topoParms.nLThreadsPerDie);
241 TOPO_DBG("\tDies per Package: %d\n", topoParms.nLDiesPerPackage);
242 TOPO_DBG("\tCores per Package: %d\n", topoParms.nLCoresPerPackage);
243 TOPO_DBG("\tThreads per Package: %d\n", topoParms.nLThreadsPerPackage);
244
245 TOPO_DBG("\nPhysical Topology Parameters:\n");
246 TOPO_DBG("\tThreads per Core: %d\n", topoParms.nPThreadsPerCore);
247 TOPO_DBG("\tCores per Die: %d\n", topoParms.nPCoresPerDie);
248 TOPO_DBG("\tThreads per Die: %d\n", topoParms.nPThreadsPerDie);
249 TOPO_DBG("\tDies per Package: %d\n", topoParms.nPDiesPerPackage);
250 TOPO_DBG("\tCores per Package: %d\n", topoParms.nPCoresPerPackage);
251 TOPO_DBG("\tThreads per Package: %d\n", topoParms.nPThreadsPerPackage);
252
253 topoParmsInited = TRUE;
593a1d5f 254}
2d21ac55
A
255
256static void
257x86_cache_free(x86_cpu_cache_t *cache)
258{
0a7de745
A
259 num_caches -= 1;
260 if (cache->level > 0 && cache->level <= MAX_CACHE_DEPTH) {
261 num_Lx_caches[cache->level - 1] -= 1;
262 }
263 cache->next = x86_caches;
264 x86_caches = cache;
2d21ac55
A
265}
266
267/*
268 * This returns a list of cache structures that represent the
269 * caches for a CPU. Some of the structures may have to be
270 * "freed" if they are actually shared between CPUs.
271 */
272static x86_cpu_cache_t *
273x86_cache_list(void)
274{
0a7de745
A
275 x86_cpu_cache_t *root = NULL;
276 x86_cpu_cache_t *cur = NULL;
277 x86_cpu_cache_t *last = NULL;
278 struct cpu_cache *cachep;
279 int i;
280
281 /*
282 * Cons up a list driven not by CPUID leaf 4 (deterministic cache params)
283 * but by the table above plus parameters already cracked from cpuid...
284 */
285 for (i = 0, cachep = &cpu_caches[0]; i < LCACHE_MAX; i++, cachep++) {
286 if (cachep->type == 0 || cpuid_info()->cache_size[i] == 0) {
287 continue;
288 }
289
290 cur = x86_cache_alloc();
291 if (cur == NULL) {
292 break;
293 }
294
295 cur->type = cachep->type;
296 cur->level = cachep->level;
297 cur->nlcpus = 0;
298 cur->maxcpus = cpuid_info()->cache_sharing[i];
299 cur->partitions = cpuid_info()->cache_partitions[i];
300 cur->cache_size = cpuid_info()->cache_size[i];
301 cur->line_size = cpuid_info()->cache_linesize;
302
303 if (last == NULL) {
304 root = cur;
305 last = cur;
306 } else {
307 last->next = cur;
308 last = cur;
309 }
310 num_Lx_caches[cur->level - 1] += 1;
2d21ac55 311 }
0a7de745 312 return root;
2d21ac55 313}
0c530ab8 314
7ddcb079 315
593a1d5f
A
316static x86_cpu_cache_t *
317x86_match_cache(x86_cpu_cache_t *list, x86_cpu_cache_t *matcher)
4452a7af 318{
0a7de745
A
319 x86_cpu_cache_t *cur_cache;
320
321 cur_cache = list;
322 while (cur_cache != NULL) {
323 if (cur_cache->maxcpus == matcher->maxcpus
324 && cur_cache->type == matcher->type
325 && cur_cache->level == matcher->level
326 && cur_cache->partitions == matcher->partitions
327 && cur_cache->line_size == matcher->line_size
328 && cur_cache->cache_size == matcher->cache_size) {
329 break;
330 }
331
332 cur_cache = cur_cache->next;
333 }
334
335 return cur_cache;
2d21ac55
A
336}
337
338static void
339x86_lcpu_init(int cpu)
340{
0a7de745
A
341 cpu_data_t *cpup;
342 x86_lcpu_t *lcpu;
343 int i;
344
345 cpup = cpu_datap(cpu);
346
347 lcpu = &cpup->lcpu;
348 lcpu->lcpu = lcpu;
349 lcpu->cpu = cpup;
350 lcpu->next_in_core = NULL;
351 lcpu->next_in_die = NULL;
352 lcpu->next_in_pkg = NULL;
353 lcpu->core = NULL;
354 lcpu->die = NULL;
355 lcpu->package = NULL;
356 lcpu->cpu_num = cpu;
357 lcpu->lnum = cpu;
358 lcpu->pnum = cpup->cpu_phys_number;
359 lcpu->state = LCPU_OFF;
360 for (i = 0; i < MAX_CACHE_DEPTH; i += 1) {
361 lcpu->caches[i] = NULL;
362 }
2d21ac55
A
363}
364
365static x86_core_t *
366x86_core_alloc(int cpu)
367{
0a7de745
A
368 x86_core_t *core;
369 cpu_data_t *cpup;
2d21ac55 370
0a7de745 371 cpup = cpu_datap(cpu);
2d21ac55 372
0a7de745
A
373 mp_safe_spin_lock(&x86_topo_lock);
374 if (free_cores != NULL) {
375 core = free_cores;
376 free_cores = core->next_in_die;
377 core->next_in_die = NULL;
378 simple_unlock(&x86_topo_lock);
379 } else {
380 simple_unlock(&x86_topo_lock);
f427ee49 381 core = zalloc_permanent_type(x86_core_t);
0a7de745 382 if (core == NULL) {
f427ee49 383 panic("x86_core_alloc() alloc of x86_core_t failed!\n");
0a7de745
A
384 }
385 }
2d21ac55 386
0a7de745
A
387 core->pcore_num = cpup->cpu_phys_number / topoParms.nPThreadsPerCore;
388 core->lcore_num = core->pcore_num % topoParms.nPCoresPerPackage;
2d21ac55 389
0a7de745
A
390 core->flags = X86CORE_FL_PRESENT | X86CORE_FL_READY
391 | X86CORE_FL_HALTED | X86CORE_FL_IDLE;
2d21ac55 392
0a7de745 393 return core;
2d21ac55
A
394}
395
396static void
397x86_core_free(x86_core_t *core)
398{
0a7de745
A
399 mp_safe_spin_lock(&x86_topo_lock);
400 core->next_in_die = free_cores;
401 free_cores = core;
402 simple_unlock(&x86_topo_lock);
2d21ac55
A
403}
404
405static x86_pkg_t *
406x86_package_find(int cpu)
407{
0a7de745
A
408 x86_pkg_t *pkg;
409 cpu_data_t *cpup;
410 uint32_t pkg_num;
2d21ac55 411
0a7de745 412 cpup = cpu_datap(cpu);
2d21ac55 413
0a7de745 414 pkg_num = cpup->cpu_phys_number / topoParms.nPThreadsPerPackage;
2d21ac55 415
0a7de745
A
416 pkg = x86_pkgs;
417 while (pkg != NULL) {
418 if (pkg->ppkg_num == pkg_num) {
419 break;
420 }
421 pkg = pkg->next;
422 }
2d21ac55 423
0a7de745 424 return pkg;
2d21ac55 425}
0a7de745 426
593a1d5f
A
427static x86_die_t *
428x86_die_find(int cpu)
429{
0a7de745
A
430 x86_die_t *die;
431 x86_pkg_t *pkg;
432 cpu_data_t *cpup;
433 uint32_t die_num;
593a1d5f 434
0a7de745 435 cpup = cpu_datap(cpu);
593a1d5f 436
0a7de745 437 die_num = cpup->cpu_phys_number / topoParms.nPThreadsPerDie;
593a1d5f 438
0a7de745
A
439 pkg = x86_package_find(cpu);
440 if (pkg == NULL) {
441 return NULL;
442 }
593a1d5f 443
0a7de745
A
444 die = pkg->dies;
445 while (die != NULL) {
446 if (die->pdie_num == die_num) {
447 break;
448 }
449 die = die->next_in_pkg;
450 }
593a1d5f 451
0a7de745 452 return die;
593a1d5f 453}
2d21ac55
A
454
455static x86_core_t *
456x86_core_find(int cpu)
457{
0a7de745
A
458 x86_core_t *core;
459 x86_die_t *die;
460 cpu_data_t *cpup;
461 uint32_t core_num;
2d21ac55 462
0a7de745 463 cpup = cpu_datap(cpu);
2d21ac55 464
0a7de745 465 core_num = cpup->cpu_phys_number / topoParms.nPThreadsPerCore;
2d21ac55 466
0a7de745
A
467 die = x86_die_find(cpu);
468 if (die == NULL) {
469 return NULL;
470 }
2d21ac55 471
0a7de745
A
472 core = die->cores;
473 while (core != NULL) {
474 if (core->pcore_num == core_num) {
475 break;
476 }
477 core = core->next_in_die;
478 }
2d21ac55 479
0a7de745 480 return core;
2d21ac55 481}
0a7de745 482
593a1d5f 483void
39236c6e 484x86_set_logical_topology(x86_lcpu_t *lcpu, int pnum, int lnum)
593a1d5f 485{
0a7de745
A
486 x86_core_t *core = lcpu->core;
487 x86_die_t *die = lcpu->die;
488 x86_pkg_t *pkg = lcpu->package;
593a1d5f 489
0a7de745
A
490 assert(core != NULL);
491 assert(die != NULL);
492 assert(pkg != NULL);
39236c6e 493
0a7de745
A
494 lcpu->cpu_num = lnum;
495 lcpu->pnum = pnum;
496 lcpu->master = (lnum == master_cpu);
497 lcpu->primary = (lnum % topoParms.nLThreadsPerPackage) == 0;
39236c6e 498
0a7de745 499 lcpu->lnum = lnum % topoParms.nLThreadsPerCore;
593a1d5f 500
0a7de745
A
501 core->pcore_num = lnum / topoParms.nLThreadsPerCore;
502 core->lcore_num = core->pcore_num % topoParms.nLCoresPerDie;
593a1d5f 503
0a7de745
A
504 die->pdie_num = lnum / (topoParms.nLThreadsPerCore * topoParms.nLCoresPerDie);
505 die->ldie_num = die->pdie_num % topoParms.nLDiesPerPackage;
39236c6e 506
0a7de745
A
507 pkg->ppkg_num = lnum / topoParms.nLThreadsPerPackage;
508 pkg->lpkg_num = pkg->ppkg_num;
593a1d5f
A
509}
510
511static x86_die_t *
512x86_die_alloc(int cpu)
513{
0a7de745
A
514 x86_die_t *die;
515 cpu_data_t *cpup;
593a1d5f 516
0a7de745 517 cpup = cpu_datap(cpu);
593a1d5f 518
0a7de745
A
519 mp_safe_spin_lock(&x86_topo_lock);
520 if (free_dies != NULL) {
521 die = free_dies;
522 free_dies = die->next_in_pkg;
523 die->next_in_pkg = NULL;
524 simple_unlock(&x86_topo_lock);
525 } else {
526 simple_unlock(&x86_topo_lock);
f427ee49 527 die = zalloc_permanent_type(x86_die_t);
0a7de745 528 if (die == NULL) {
f427ee49 529 panic("x86_die_alloc() alloc of x86_die_t failed!\n");
0a7de745
A
530 }
531 }
593a1d5f 532
0a7de745 533 die->pdie_num = cpup->cpu_phys_number / topoParms.nPThreadsPerDie;
593a1d5f 534
0a7de745
A
535 die->ldie_num = num_dies;
536 atomic_incl((long *) &num_dies, 1);
593a1d5f 537
0a7de745
A
538 die->flags = X86DIE_FL_PRESENT;
539 return die;
593a1d5f 540}
2d21ac55
A
541
542static void
593a1d5f
A
543x86_die_free(x86_die_t *die)
544{
0a7de745
A
545 mp_safe_spin_lock(&x86_topo_lock);
546 die->next_in_pkg = free_dies;
547 free_dies = die;
548 atomic_decl((long *) &num_dies, 1);
549 simple_unlock(&x86_topo_lock);
593a1d5f
A
550}
551
552static x86_pkg_t *
553x86_package_alloc(int cpu)
554{
0a7de745
A
555 x86_pkg_t *pkg;
556 cpu_data_t *cpup;
593a1d5f 557
0a7de745 558 cpup = cpu_datap(cpu);
593a1d5f 559
0a7de745
A
560 mp_safe_spin_lock(&x86_topo_lock);
561 if (free_pkgs != NULL) {
562 pkg = free_pkgs;
563 free_pkgs = pkg->next;
564 pkg->next = NULL;
565 simple_unlock(&x86_topo_lock);
566 } else {
567 simple_unlock(&x86_topo_lock);
f427ee49 568 pkg = zalloc_permanent_type(x86_pkg_t);
0a7de745 569 if (pkg == NULL) {
f427ee49 570 panic("x86_package_alloc() alloc of x86_pkg_t failed!\n");
0a7de745
A
571 }
572 }
593a1d5f 573
0a7de745 574 pkg->ppkg_num = cpup->cpu_phys_number / topoParms.nPThreadsPerPackage;
593a1d5f 575
0a7de745
A
576 pkg->lpkg_num = topoParms.nPackages;
577 atomic_incl((long *) &topoParms.nPackages, 1);
593a1d5f 578
0a7de745
A
579 pkg->flags = X86PKG_FL_PRESENT | X86PKG_FL_READY;
580 return pkg;
593a1d5f
A
581}
582
583static void
584x86_package_free(x86_pkg_t *pkg)
585{
0a7de745
A
586 mp_safe_spin_lock(&x86_topo_lock);
587 pkg->next = free_pkgs;
588 free_pkgs = pkg;
589 atomic_decl((long *) &topoParms.nPackages, 1);
590 simple_unlock(&x86_topo_lock);
593a1d5f
A
591}
592
593static void
594x86_cache_add_lcpu(x86_cpu_cache_t *cache, x86_lcpu_t *lcpu)
595{
0a7de745
A
596 x86_cpu_cache_t *cur_cache;
597 int i;
598
599 /*
600 * Put the new CPU into the list of the cache.
601 */
602 cur_cache = lcpu->caches[cache->level - 1];
603 lcpu->caches[cache->level - 1] = cache;
604 cache->next = cur_cache;
605 cache->nlcpus += 1;
606 for (i = 0; i < cache->nlcpus; i += 1) {
607 if (cache->cpus[i] == NULL) {
608 cache->cpus[i] = lcpu;
609 break;
610 }
593a1d5f 611 }
593a1d5f
A
612}
613
614static void
615x86_lcpu_add_caches(x86_lcpu_t *lcpu)
2d21ac55 616{
0a7de745
A
617 x86_cpu_cache_t *list;
618 x86_cpu_cache_t *cur;
619 x86_cpu_cache_t *match;
620 x86_die_t *die;
621 x86_core_t *core;
622 x86_lcpu_t *cur_lcpu;
623 uint32_t level;
624 boolean_t found = FALSE;
2d21ac55 625
0a7de745 626 assert(lcpu != NULL);
2d21ac55 627
2d21ac55 628 /*
0a7de745 629 * Add the cache data to the topology.
2d21ac55 630 */
0a7de745 631 list = x86_cache_list();
2d21ac55 632
0a7de745 633 mp_safe_spin_lock(&x86_topo_lock);
2d21ac55 634
0a7de745
A
635 while (list != NULL) {
636 /*
637 * Remove the cache from the front of the list.
638 */
639 cur = list;
640 list = cur->next;
641 cur->next = NULL;
642 level = cur->level - 1;
2d21ac55 643
593a1d5f 644 /*
0a7de745
A
645 * If the cache isn't shared then just put it where it
646 * belongs.
593a1d5f 647 */
0a7de745
A
648 if (cur->maxcpus == 1) {
649 x86_cache_add_lcpu(cur, lcpu);
650 continue;
593a1d5f 651 }
2d21ac55 652
593a1d5f 653 /*
0a7de745
A
654 * We'll assume that all of the caches at a particular level
655 * have the same sharing. So if we have a cache already at
656 * this level, we'll just skip looking for the match.
593a1d5f 657 */
0a7de745
A
658 if (lcpu->caches[level] != NULL) {
659 x86_cache_free(cur);
660 continue;
2d21ac55 661 }
593a1d5f 662
593a1d5f 663 /*
0a7de745
A
664 * This is a shared cache, so we have to figure out if
665 * this is the first time we've seen this cache. We do
666 * this by searching through the topology and seeing if
667 * this cache is already described.
668 *
669 * Assume that L{LLC-1} are all at the core level and that
670 * LLC is shared at the die level.
593a1d5f 671 */
0a7de745
A
672 if (level < topoParms.LLCDepth) {
673 /*
674 * Shared at the core.
675 */
676 core = lcpu->core;
677 cur_lcpu = core->lcpus;
678 while (cur_lcpu != NULL) {
679 /*
680 * Skip ourselves.
681 */
682 if (cur_lcpu == lcpu) {
683 cur_lcpu = cur_lcpu->next_in_core;
684 continue;
685 }
686
687 /*
688 * If there's a cache on this logical CPU,
689 * then use that one.
690 */
691 match = x86_match_cache(cur_lcpu->caches[level], cur);
692 if (match != NULL) {
693 x86_cache_free(cur);
694 x86_cache_add_lcpu(match, lcpu);
695 found = TRUE;
696 break;
697 }
698
699 cur_lcpu = cur_lcpu->next_in_core;
700 }
701 } else {
702 /*
703 * Shared at the die.
704 */
705 die = lcpu->die;
706 cur_lcpu = die->lcpus;
707 while (cur_lcpu != NULL) {
708 /*
709 * Skip ourselves.
710 */
711 if (cur_lcpu == lcpu) {
712 cur_lcpu = cur_lcpu->next_in_die;
713 continue;
714 }
715
716 /*
717 * If there's a cache on this logical CPU,
718 * then use that one.
719 */
720 match = x86_match_cache(cur_lcpu->caches[level], cur);
721 if (match != NULL) {
722 x86_cache_free(cur);
723 x86_cache_add_lcpu(match, lcpu);
724 found = TRUE;
725 break;
726 }
727
728 cur_lcpu = cur_lcpu->next_in_die;
729 }
593a1d5f 730 }
2d21ac55 731
593a1d5f 732 /*
0a7de745
A
733 * If a shared cache wasn't found, then this logical CPU must
734 * be the first one encountered.
593a1d5f 735 */
0a7de745
A
736 if (!found) {
737 x86_cache_add_lcpu(cur, lcpu);
593a1d5f 738 }
2d21ac55
A
739 }
740
0a7de745 741 simple_unlock(&x86_topo_lock);
2d21ac55
A
742}
743
593a1d5f
A
744static void
745x86_core_add_lcpu(x86_core_t *core, x86_lcpu_t *lcpu)
2d21ac55 746{
0a7de745
A
747 assert(core != NULL);
748 assert(lcpu != NULL);
2d21ac55 749
0a7de745 750 mp_safe_spin_lock(&x86_topo_lock);
2d21ac55 751
0a7de745
A
752 lcpu->next_in_core = core->lcpus;
753 lcpu->core = core;
754 core->lcpus = lcpu;
755 core->num_lcpus += 1;
756 simple_unlock(&x86_topo_lock);
593a1d5f 757}
2d21ac55 758
593a1d5f
A
759static void
760x86_die_add_lcpu(x86_die_t *die, x86_lcpu_t *lcpu)
761{
0a7de745
A
762 assert(die != NULL);
763 assert(lcpu != NULL);
764
765 lcpu->next_in_die = die->lcpus;
766 lcpu->die = die;
767 die->lcpus = lcpu;
593a1d5f 768}
2d21ac55 769
593a1d5f
A
770static void
771x86_die_add_core(x86_die_t *die, x86_core_t *core)
772{
0a7de745
A
773 assert(die != NULL);
774 assert(core != NULL);
2d21ac55 775
0a7de745
A
776 core->next_in_die = die->cores;
777 core->die = die;
778 die->cores = core;
779 die->num_cores += 1;
2d21ac55
A
780}
781
0a7de745 782static void
593a1d5f 783x86_package_add_lcpu(x86_pkg_t *pkg, x86_lcpu_t *lcpu)
2d21ac55 784{
0a7de745
A
785 assert(pkg != NULL);
786 assert(lcpu != NULL);
593a1d5f 787
0a7de745
A
788 lcpu->next_in_pkg = pkg->lcpus;
789 lcpu->package = pkg;
790 pkg->lcpus = lcpu;
2d21ac55
A
791}
792
793static void
794x86_package_add_core(x86_pkg_t *pkg, x86_core_t *core)
795{
0a7de745
A
796 assert(pkg != NULL);
797 assert(core != NULL);
2d21ac55 798
0a7de745
A
799 core->next_in_pkg = pkg->cores;
800 core->package = pkg;
801 pkg->cores = core;
593a1d5f
A
802}
803
804static void
805x86_package_add_die(x86_pkg_t *pkg, x86_die_t *die)
806{
0a7de745
A
807 assert(pkg != NULL);
808 assert(die != NULL);
593a1d5f 809
0a7de745
A
810 die->next_in_pkg = pkg->dies;
811 die->package = pkg;
812 pkg->dies = die;
813 pkg->num_dies += 1;
0c530ab8 814}
21362eb3 815
0c530ab8
A
816void *
817cpu_thread_alloc(int cpu)
818{
0a7de745
A
819 x86_core_t *core = NULL;
820 x86_die_t *die = NULL;
821 x86_pkg_t *pkg = NULL;
822 cpu_data_t *cpup;
823 uint32_t phys_cpu;
91447636 824
0a7de745
A
825 /*
826 * Only allow one to manipulate the topology at a time.
827 */
828 mp_safe_spin_lock(&x86_topo_lock);
829
830 /*
831 * Make sure all of the topology parameters have been initialized.
832 */
833 if (!topoParmsInited) {
834 initTopoParms();
2d21ac55 835 }
0a7de745
A
836
837 cpup = cpu_datap(cpu);
838
839 phys_cpu = cpup->cpu_phys_number;
840
841 x86_lcpu_init(cpu);
842
843 /*
844 * Assume that all cpus have the same features.
845 */
846 if (cpu_is_hyperthreaded()) {
847 cpup->cpu_threadtype = CPU_THREADTYPE_INTEL_HTT;
848 } else {
849 cpup->cpu_threadtype = CPU_THREADTYPE_NONE;
593a1d5f 850 }
0a7de745
A
851
852 /*
853 * Get the package that the logical CPU is in.
854 */
855 do {
856 pkg = x86_package_find(cpu);
857 if (pkg == NULL) {
858 /*
859 * Package structure hasn't been created yet, do it now.
860 */
861 simple_unlock(&x86_topo_lock);
862 pkg = x86_package_alloc(cpu);
863 mp_safe_spin_lock(&x86_topo_lock);
864 if (x86_package_find(cpu) != NULL) {
865 x86_package_free(pkg);
866 continue;
867 }
868
869 /*
870 * Add the new package to the global list of packages.
871 */
872 pkg->next = x86_pkgs;
873 x86_pkgs = pkg;
874 }
875 } while (pkg == NULL);
876
877 /*
878 * Get the die that the logical CPU is in.
879 */
880 do {
881 die = x86_die_find(cpu);
882 if (die == NULL) {
883 /*
884 * Die structure hasn't been created yet, do it now.
885 */
886 simple_unlock(&x86_topo_lock);
887 die = x86_die_alloc(cpu);
888 mp_safe_spin_lock(&x86_topo_lock);
889 if (x86_die_find(cpu) != NULL) {
890 x86_die_free(die);
891 continue;
892 }
893
894 /*
895 * Add the die to the package.
896 */
897 x86_package_add_die(pkg, die);
898 }
899 } while (die == NULL);
900
901 /*
902 * Get the core for this logical CPU.
903 */
904 do {
905 core = x86_core_find(cpu);
906 if (core == NULL) {
907 /*
908 * Allocate the core structure now.
909 */
910 simple_unlock(&x86_topo_lock);
911 core = x86_core_alloc(cpu);
912 mp_safe_spin_lock(&x86_topo_lock);
913 if (x86_core_find(cpu) != NULL) {
914 x86_core_free(core);
915 continue;
916 }
917
918 /*
919 * Add the core to the die & package.
920 */
921 x86_die_add_core(die, core);
922 x86_package_add_core(pkg, core);
923 machine_info.physical_cpu_max += 1;
924 }
925 } while (core == NULL);
926
927
928 /*
929 * Done manipulating the topology, so others can get in.
930 */
931 machine_info.logical_cpu_max += 1;
932 simple_unlock(&x86_topo_lock);
933
934 /*
935 * Add the logical CPU to the other topology structures.
936 */
937 x86_core_add_lcpu(core, &cpup->lcpu);
938 x86_die_add_lcpu(core->die, &cpup->lcpu);
939 x86_package_add_lcpu(core->package, &cpup->lcpu);
940 x86_lcpu_add_caches(&cpup->lcpu);
941
942 return (void *) core;
0c530ab8
A
943}
944
945void
946cpu_thread_init(void)
947{
0a7de745
A
948 int my_cpu = get_cpu_number();
949 cpu_data_t *cpup = current_cpu_datap();
950 x86_core_t *core;
951 static int initialized = 0;
952
953 /*
954 * If we're the boot processor, we do all of the initialization of
955 * the CPU topology infrastructure.
956 */
957 if (my_cpu == master_cpu && !initialized) {
958 simple_lock_init(&x86_topo_lock, 0);
959
960 /*
961 * Put this logical CPU into the physical CPU topology.
962 */
963 cpup->lcpu.core = cpu_thread_alloc(my_cpu);
964
965 initialized = 1;
966 }
0c530ab8
A
967
968 /*
0a7de745 969 * Do the CPU accounting.
0c530ab8 970 */
0a7de745
A
971 core = cpup->lcpu.core;
972 mp_safe_spin_lock(&x86_topo_lock);
973 machine_info.logical_cpu += 1;
974 if (core->active_lcpus == 0) {
975 machine_info.physical_cpu += 1;
976 }
977 core->active_lcpus += 1;
978 simple_unlock(&x86_topo_lock);
979
980 pmCPUMarkRunning(cpup);
981 timer_resync_deadlines();
91447636
A
982}
983
984/*
985 * Called for a cpu to halt permanently
986 * (as opposed to halting and expecting an interrupt to awaken it).
987 */
39037602 988__attribute__((noreturn))
91447636
A
989void
990cpu_thread_halt(void)
991{
0a7de745
A
992 x86_core_t *core;
993 cpu_data_t *cpup = current_cpu_datap();
994
995 mp_safe_spin_lock(&x86_topo_lock);
996 machine_info.logical_cpu -= 1;
997 core = cpup->lcpu.core;
998 core->active_lcpus -= 1;
999 if (core->active_lcpus == 0) {
1000 machine_info.physical_cpu -= 1;
1001 }
1002 simple_unlock(&x86_topo_lock);
1003
1004 /*
1005 * Let the power management code determine the best way to "stop"
1006 * the processor.
1007 */
1008 ml_set_interrupts_enabled(FALSE);
1009 while (1) {
1010 pmCPUHalt(PM_HALT_NORMAL);
1011 }
1012 /* NOT REACHED */
91447636 1013}
593a1d5f 1014
c910b4d9
A
1015/*
1016 * Validates that the topology was built correctly. Must be called only
1017 * after the complete topology is built and no other changes are being made.
1018 */
1019void
39236c6e 1020x86_validate_topology(void)
c910b4d9 1021{
0a7de745
A
1022 x86_pkg_t *pkg;
1023 x86_die_t *die;
1024 x86_core_t *core;
1025 x86_lcpu_t *lcpu;
1026 uint32_t nDies;
1027 uint32_t nCores;
1028 uint32_t nCPUs;
1029
1030 if (topo_dbg) {
1031 debug_topology_print();
c910b4d9
A
1032 }
1033
c910b4d9 1034 /*
0a7de745
A
1035 * Called after processors are registered but before non-boot processors
1036 * are started:
1037 * - real_ncpus: number of registered processors driven from MADT
1038 * - max_ncpus: max number of processors that will be started
c910b4d9 1039 */
0a7de745
A
1040 nCPUs = topoParms.nPackages * topoParms.nLThreadsPerPackage;
1041 if (nCPUs != real_ncpus) {
1042 panic("x86_validate_topology() %d threads but %d registered from MADT",
1043 nCPUs, real_ncpus);
c910b4d9
A
1044 }
1045
0a7de745
A
1046 pkg = x86_pkgs;
1047 while (pkg != NULL) {
1048 /*
1049 * Make sure that the package has the correct number of dies.
1050 */
1051 nDies = 0;
1052 die = pkg->dies;
1053 while (die != NULL) {
1054 if (die->package == NULL) {
1055 panic("Die(%d)->package is NULL",
1056 die->pdie_num);
1057 }
1058 if (die->package != pkg) {
1059 panic("Die %d points to package %d, should be %d",
1060 die->pdie_num, die->package->lpkg_num, pkg->lpkg_num);
1061 }
1062
1063 TOPO_DBG("Die(%d)->package %d\n",
1064 die->pdie_num, pkg->lpkg_num);
1065
1066 /*
1067 * Make sure that the die has the correct number of cores.
1068 */
1069 TOPO_DBG("Die(%d)->cores: ", die->pdie_num);
1070 nCores = 0;
1071 core = die->cores;
1072 while (core != NULL) {
1073 if (core->die == NULL) {
1074 panic("Core(%d)->die is NULL",
1075 core->pcore_num);
1076 }
1077 if (core->die != die) {
1078 panic("Core %d points to die %d, should be %d",
1079 core->pcore_num, core->die->pdie_num, die->pdie_num);
1080 }
1081 nCores += 1;
1082 TOPO_DBG("%d ", core->pcore_num);
1083 core = core->next_in_die;
1084 }
1085 TOPO_DBG("\n");
1086
1087 if (nCores != topoParms.nLCoresPerDie) {
1088 panic("Should have %d Cores, but only found %d for Die %d",
1089 topoParms.nLCoresPerDie, nCores, die->pdie_num);
1090 }
1091
1092 /*
1093 * Make sure that the die has the correct number of CPUs.
1094 */
1095 TOPO_DBG("Die(%d)->lcpus: ", die->pdie_num);
1096 nCPUs = 0;
1097 lcpu = die->lcpus;
1098 while (lcpu != NULL) {
1099 if (lcpu->die == NULL) {
1100 panic("CPU(%d)->die is NULL",
1101 lcpu->cpu_num);
1102 }
1103 if (lcpu->die != die) {
1104 panic("CPU %d points to die %d, should be %d",
1105 lcpu->cpu_num, lcpu->die->pdie_num, die->pdie_num);
1106 }
1107 nCPUs += 1;
1108 TOPO_DBG("%d ", lcpu->cpu_num);
1109 lcpu = lcpu->next_in_die;
1110 }
1111 TOPO_DBG("\n");
1112
1113 if (nCPUs != topoParms.nLThreadsPerDie) {
1114 panic("Should have %d Threads, but only found %d for Die %d",
1115 topoParms.nLThreadsPerDie, nCPUs, die->pdie_num);
1116 }
1117
1118 nDies += 1;
1119 die = die->next_in_pkg;
1120 }
c910b4d9 1121
0a7de745
A
1122 if (nDies != topoParms.nLDiesPerPackage) {
1123 panic("Should have %d Dies, but only found %d for package %d",
1124 topoParms.nLDiesPerPackage, nDies, pkg->lpkg_num);
1125 }
c910b4d9 1126
0a7de745
A
1127 /*
1128 * Make sure that the package has the correct number of cores.
1129 */
1130 nCores = 0;
1131 core = pkg->cores;
1132 while (core != NULL) {
1133 if (core->package == NULL) {
1134 panic("Core(%d)->package is NULL",
1135 core->pcore_num);
1136 }
1137 if (core->package != pkg) {
1138 panic("Core %d points to package %d, should be %d",
1139 core->pcore_num, core->package->lpkg_num, pkg->lpkg_num);
1140 }
1141 TOPO_DBG("Core(%d)->package %d\n",
1142 core->pcore_num, pkg->lpkg_num);
1143
1144 /*
1145 * Make sure that the core has the correct number of CPUs.
1146 */
1147 nCPUs = 0;
1148 lcpu = core->lcpus;
1149 TOPO_DBG("Core(%d)->lcpus: ", core->pcore_num);
1150 while (lcpu != NULL) {
1151 if (lcpu->core == NULL) {
1152 panic("CPU(%d)->core is NULL",
1153 lcpu->cpu_num);
1154 }
1155 if (lcpu->core != core) {
1156 panic("CPU %d points to core %d, should be %d",
1157 lcpu->cpu_num, lcpu->core->pcore_num, core->pcore_num);
1158 }
1159 TOPO_DBG("%d ", lcpu->cpu_num);
1160 nCPUs += 1;
1161 lcpu = lcpu->next_in_core;
1162 }
1163 TOPO_DBG("\n");
1164
1165 if (nCPUs != topoParms.nLThreadsPerCore) {
1166 panic("Should have %d Threads, but only found %d for Core %d",
1167 topoParms.nLThreadsPerCore, nCPUs, core->pcore_num);
1168 }
1169 nCores += 1;
1170 core = core->next_in_pkg;
1171 }
c910b4d9 1172
0a7de745
A
1173 if (nCores != topoParms.nLCoresPerPackage) {
1174 panic("Should have %d Cores, but only found %d for package %d",
1175 topoParms.nLCoresPerPackage, nCores, pkg->lpkg_num);
1176 }
1177
1178 /*
1179 * Make sure that the package has the correct number of CPUs.
1180 */
1181 nCPUs = 0;
1182 lcpu = pkg->lcpus;
1183 while (lcpu != NULL) {
1184 if (lcpu->package == NULL) {
1185 panic("CPU(%d)->package is NULL",
1186 lcpu->cpu_num);
1187 }
1188 if (lcpu->package != pkg) {
1189 panic("CPU %d points to package %d, should be %d",
1190 lcpu->cpu_num, lcpu->package->lpkg_num, pkg->lpkg_num);
1191 }
1192 TOPO_DBG("CPU(%d)->package %d\n",
1193 lcpu->cpu_num, pkg->lpkg_num);
1194 nCPUs += 1;
1195 lcpu = lcpu->next_in_pkg;
1196 }
1197
1198 if (nCPUs != topoParms.nLThreadsPerPackage) {
1199 panic("Should have %d Threads, but only found %d for package %d",
1200 topoParms.nLThreadsPerPackage, nCPUs, pkg->lpkg_num);
1201 }
1202
1203 pkg = pkg->next;
1204 }
c910b4d9
A
1205}
1206
593a1d5f
A
1207/*
1208 * Prints out the topology
1209 */
7ddcb079 1210static void
593a1d5f
A
1211debug_topology_print(void)
1212{
0a7de745
A
1213 x86_pkg_t *pkg;
1214 x86_die_t *die;
1215 x86_core_t *core;
1216 x86_lcpu_t *cpu;
1217
1218 pkg = x86_pkgs;
1219 while (pkg != NULL) {
1220 kprintf("Package:\n");
1221 kprintf(" Physical: %d\n", pkg->ppkg_num);
1222 kprintf(" Logical: %d\n", pkg->lpkg_num);
1223
1224 die = pkg->dies;
1225 while (die != NULL) {
1226 kprintf(" Die:\n");
1227 kprintf(" Physical: %d\n", die->pdie_num);
1228 kprintf(" Logical: %d\n", die->ldie_num);
1229
1230 core = die->cores;
1231 while (core != NULL) {
1232 kprintf(" Core:\n");
1233 kprintf(" Physical: %d\n", core->pcore_num);
1234 kprintf(" Logical: %d\n", core->lcore_num);
1235
1236 cpu = core->lcpus;
1237 while (cpu != NULL) {
1238 kprintf(" LCPU:\n");
1239 kprintf(" CPU #: %d\n", cpu->cpu_num);
1240 kprintf(" Physical: %d\n", cpu->pnum);
1241 kprintf(" Logical: %d\n", cpu->lnum);
1242 kprintf(" Flags: ");
1243 if (cpu->master) {
1244 kprintf("MASTER ");
1245 }
1246 if (cpu->primary) {
1247 kprintf("PRIMARY");
1248 }
1249 if (!cpu->master && !cpu->primary) {
1250 kprintf("(NONE)");
1251 }
1252 kprintf("\n");
1253
1254 cpu = cpu->next_in_core;
1255 }
1256
1257 core = core->next_in_die;
1258 }
1259
1260 die = die->next_in_pkg;
593a1d5f
A
1261 }
1262
0a7de745 1263 pkg = pkg->next;
593a1d5f 1264 }
593a1d5f 1265}