]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/cpu_threads.c
b7f108ecf828e5b48f27303e13cdaa5d42e73c2c
[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 bitmask(h,l) ((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
39 #define bitfield(x,h,l) (((x) & bitmask(h,l)) >> l)
40
41 /*
42 * Kernel parameter determining whether threads are halted unconditionally
43 * in the idle state. This is the default behavior.
44 * See machine_idle() for use.
45 */
46 int idlehalt = 1;
47
48 x86_pkg_t *x86_pkgs = NULL;
49 uint32_t num_packages = 0;
50 uint32_t num_Lx_caches[MAX_CACHE_DEPTH] = { 0 };
51
52 static x86_pkg_t *free_pkgs = NULL;
53 static x86_core_t *free_cores = NULL;
54
55 static x86_cpu_cache_t *x86_caches = NULL;
56 static uint32_t num_caches = 0;
57
58 decl_simple_lock_data(, x86_topo_lock);
59
60 static x86_cpu_cache_t *
61 x86_cache_alloc(void)
62 {
63 x86_cpu_cache_t *cache;
64 int i;
65
66 if (x86_caches == NULL) {
67 cache = kalloc(sizeof(x86_cpu_cache_t) + (MAX_CPUS * sizeof(x86_lcpu_t *)));
68 if (cache == NULL)
69 return(NULL);
70 } else {
71 cache = x86_caches;
72 x86_caches = cache->next;
73 cache->next = NULL;
74 }
75
76 bzero(cache, sizeof(x86_cpu_cache_t));
77 cache->next = NULL;
78 cache->maxcpus = MAX_CPUS;
79 for (i = 0; i < cache->maxcpus; i += 1) {
80 cache->cpus[i] = NULL;
81 }
82
83 num_caches += 1;
84
85 return(cache);
86 }
87
88 static void
89 x86_cache_free(x86_cpu_cache_t *cache)
90 {
91 num_caches -= 1;
92 if (cache->level > 0 && cache->level <= MAX_CACHE_DEPTH)
93 num_Lx_caches[cache->level - 1] -= 1;
94 cache->next = x86_caches;
95 x86_caches = cache;
96 }
97
98 /*
99 * This returns a list of cache structures that represent the
100 * caches for a CPU. Some of the structures may have to be
101 * "freed" if they are actually shared between CPUs.
102 */
103 static x86_cpu_cache_t *
104 x86_cache_list(void)
105 {
106 x86_cpu_cache_t *root = NULL;
107 x86_cpu_cache_t *cur = NULL;
108 x86_cpu_cache_t *last = NULL;
109 uint32_t index;
110 uint32_t cache_info[4];
111 uint32_t nsets;
112
113 do_cpuid(0, cache_info);
114
115 if (cache_info[eax] < 4) {
116 /*
117 * Processor does not support deterministic
118 * cache information. Don't report anything
119 */
120 return NULL;
121 }
122
123 for (index = 0; ; index += 1) {
124 cache_info[eax] = 4;
125 cache_info[ecx] = index;
126 cache_info[ebx] = 0;
127 cache_info[edx] = 0;
128
129 cpuid(cache_info);
130
131 /*
132 * See if all levels have been queried.
133 */
134 if (bitfield(cache_info[eax], 4, 0) == 0)
135 break;
136
137 cur = x86_cache_alloc();
138 if (cur == NULL) {
139 break;
140 }
141
142 cur->type = bitfield(cache_info[eax], 4, 0);
143 cur->level = bitfield(cache_info[eax], 7, 5);
144 cur->nlcpus = bitfield(cache_info[eax], 25, 14) + 1;
145 cur->line_size = bitfield(cache_info[ebx], 11, 0) + 1;
146 cur->partitions = bitfield(cache_info[ebx], 21, 12) + 1;
147 cur->ways = bitfield(cache_info[ebx], 31, 22) + 1;
148 nsets = bitfield(cache_info[ecx], 31, 0) + 1;
149 cur->cache_size = cur->line_size * cur->ways * cur->partitions * nsets;
150
151 if (last == NULL) {
152 root = cur;
153 last = cur;
154 } else {
155 last->next = cur;
156 last = cur;
157 }
158
159 num_Lx_caches[cur->level - 1] += 1;
160 }
161
162 return(root);
163 }
164
165 static boolean_t
166 cpu_is_hyperthreaded(void)
167 {
168 if (cpuid_features() & CPUID_FEATURE_HTT)
169 return (cpuid_info()->cpuid_logical_per_package /
170 cpuid_info()->cpuid_cores_per_package) > 1;
171 else
172 return FALSE;
173 }
174
175 static void
176 x86_lcpu_init(int cpu)
177 {
178 cpu_data_t *cpup;
179 x86_lcpu_t *lcpu;
180 int i;
181
182 cpup = cpu_datap(cpu);
183
184 lcpu = &cpup->lcpu;
185 lcpu->lcpu = lcpu;
186 lcpu->cpu = cpup;
187 lcpu->next = NULL;
188 lcpu->core = NULL;
189 lcpu->lnum = cpu;
190 lcpu->pnum = cpup->cpu_phys_number;
191 lcpu->halted = FALSE; /* XXX is this correct? */
192 lcpu->idle = FALSE; /* XXX is this correct? */
193 for (i = 0; i < MAX_CACHE_DEPTH; i += 1)
194 lcpu->caches[i] = NULL;
195
196 lcpu->master = (lcpu->pnum == (unsigned int) master_cpu);
197 lcpu->primary = (lcpu->pnum % cpuid_info()->cpuid_logical_per_package) == 0;
198 }
199
200 static x86_core_t *
201 x86_core_alloc(int cpu)
202 {
203 x86_core_t *core;
204 cpu_data_t *cpup;
205 uint32_t cpu_in_pkg;
206 uint32_t lcpus_per_core;
207
208 cpup = cpu_datap(cpu);
209
210 simple_lock(&x86_topo_lock);
211 if (free_cores != NULL) {
212 core = free_cores;
213 free_cores = core->next;
214 core->next = NULL;
215 simple_unlock(&x86_topo_lock);
216 } else {
217 simple_unlock(&x86_topo_lock);
218 core = kalloc(sizeof(x86_core_t));
219 if (core == NULL)
220 panic("x86_core_alloc() kalloc of x86_core_t failed!\n");
221 }
222
223 bzero((void *) core, sizeof(x86_core_t));
224
225 cpu_in_pkg = cpu % cpuid_info()->cpuid_logical_per_package;
226 lcpus_per_core = cpuid_info()->cpuid_logical_per_package /
227 cpuid_info()->cpuid_cores_per_package;
228
229 core->pcore_num = cpup->cpu_phys_number / lcpus_per_core;
230 core->lcore_num = core->pcore_num % cpuid_info()->cpuid_cores_per_package;
231
232 core->flags = X86CORE_FL_PRESENT | X86CORE_FL_READY
233 | X86CORE_FL_HALTED | X86CORE_FL_IDLE;
234
235 return(core);
236 }
237
238 static void
239 x86_core_free(x86_core_t *core)
240 {
241 simple_lock(&x86_topo_lock);
242 core->next = free_cores;
243 free_cores = core;
244 simple_unlock(&x86_topo_lock);
245 }
246
247 static x86_pkg_t *
248 x86_package_find(int cpu)
249 {
250 x86_pkg_t *pkg;
251 cpu_data_t *cpup;
252 uint32_t pkg_num;
253
254 cpup = cpu_datap(cpu);
255
256 pkg_num = cpup->cpu_phys_number / cpuid_info()->cpuid_logical_per_package;
257
258 pkg = x86_pkgs;
259 while (pkg != NULL) {
260 if (pkg->ppkg_num == pkg_num)
261 break;
262 pkg = pkg->next;
263 }
264
265 return(pkg);
266 }
267
268 static x86_core_t *
269 x86_core_find(int cpu)
270 {
271 x86_core_t *core;
272 x86_pkg_t *pkg;
273 cpu_data_t *cpup;
274 uint32_t core_num;
275
276 cpup = cpu_datap(cpu);
277
278 core_num = cpup->cpu_phys_number
279 / (cpuid_info()->cpuid_logical_per_package
280 / cpuid_info()->cpuid_cores_per_package);
281
282 pkg = x86_package_find(cpu);
283 if (pkg == NULL)
284 return(NULL);
285
286 core = pkg->cores;
287 while (core != NULL) {
288 if (core->pcore_num == core_num)
289 break;
290 core = core->next;
291 }
292
293 return(core);
294 }
295
296 static void
297 x86_core_add_lcpu(x86_core_t *core, x86_lcpu_t *lcpu)
298 {
299 x86_cpu_cache_t *list;
300 x86_cpu_cache_t *cur;
301 x86_core_t *cur_core;
302 x86_lcpu_t *cur_lcpu;
303 boolean_t found;
304 int level;
305 int i;
306 uint32_t cpu_mask;
307
308 assert(core != NULL);
309 assert(lcpu != NULL);
310
311 /*
312 * Add the cache data to the topology.
313 */
314 list = x86_cache_list();
315
316 simple_lock(&x86_topo_lock);
317
318 while (list != NULL) {
319 /*
320 * Remove the cache from the front of the list.
321 */
322 cur = list;
323 list = cur->next;
324 cur->next = NULL;
325 level = cur->level - 1;
326
327 /*
328 * If the cache isn't shared then just put it where it
329 * belongs.
330 */
331 if (cur->nlcpus == 1) {
332 goto found_first;
333 }
334
335 /*
336 * We'll assume that all of the caches at a particular level
337 * have the same sharing. So if we have a cache already at
338 * this level, we'll just skip looking for the match.
339 */
340 if (lcpu->caches[level] != NULL) {
341 x86_cache_free(cur);
342 continue;
343 }
344
345 /*
346 * This is a shared cache, so we have to figure out if
347 * this is the first time we've seen this cache. We do
348 * this by searching through the package and seeing if
349 * a related core is already describing this cache.
350 *
351 * NOTE: This assumes that CPUs whose ID mod <# sharing cache>
352 * are indeed sharing the cache.
353 */
354 cpu_mask = lcpu->pnum & ~(cur->nlcpus - 1);
355 cur_core = core->package->cores;
356 found = FALSE;
357
358 while (cur_core != NULL && !found) {
359 cur_lcpu = cur_core->lcpus;
360 while (cur_lcpu != NULL && !found) {
361 if ((cur_lcpu->pnum & ~(cur->nlcpus - 1)) == cpu_mask) {
362 lcpu->caches[level] = cur_lcpu->caches[level];
363 found = TRUE;
364 x86_cache_free(cur);
365
366 /*
367 * Put the new CPU into the list of the cache.
368 */
369 cur = lcpu->caches[level];
370 for (i = 0; i < cur->nlcpus; i += 1) {
371 if (cur->cpus[i] == NULL) {
372 cur->cpus[i] = lcpu;
373 break;
374 }
375 }
376 }
377 cur_lcpu = cur_lcpu->next;
378 }
379
380 cur_core = cur_core->next;
381 }
382
383 if (!found) {
384 found_first:
385 cur->next = lcpu->caches[level];
386 lcpu->caches[level] = cur;
387 cur->cpus[0] = lcpu;
388 }
389 }
390
391 /*
392 * Add the Logical CPU to the core.
393 */
394 lcpu->next = core->lcpus;
395 lcpu->core = core;
396 core->lcpus = lcpu;
397 core->num_lcpus += 1;
398
399 simple_unlock(&x86_topo_lock);
400 }
401
402 static x86_pkg_t *
403 x86_package_alloc(int cpu)
404 {
405 x86_pkg_t *pkg;
406 cpu_data_t *cpup;
407
408 cpup = cpu_datap(cpu);
409
410 simple_lock(&x86_topo_lock);
411 if (free_pkgs != NULL) {
412 pkg = free_pkgs;
413 free_pkgs = pkg->next;
414 pkg->next = NULL;
415 simple_unlock(&x86_topo_lock);
416 } else {
417 simple_unlock(&x86_topo_lock);
418 pkg = kalloc(sizeof(x86_pkg_t));
419 if (pkg == NULL)
420 panic("x86_package_alloc() kalloc of x86_pkg_t failed!\n");
421 }
422
423 bzero((void *) pkg, sizeof(x86_pkg_t));
424
425 pkg->ppkg_num = cpup->cpu_phys_number
426 / cpuid_info()->cpuid_logical_per_package;
427
428 pkg->lpkg_num = num_packages;
429 atomic_incl((long *) &num_packages, 1);
430
431 pkg->flags = X86PKG_FL_PRESENT | X86PKG_FL_READY;
432 return(pkg);
433 }
434
435 static void
436 x86_package_free(x86_pkg_t *pkg)
437 {
438 simple_lock(&x86_topo_lock);
439 pkg->next = free_pkgs;
440 free_pkgs = pkg;
441 atomic_decl((long *) &num_packages, 1);
442 simple_unlock(&x86_topo_lock);
443 }
444
445 static void
446 x86_package_add_core(x86_pkg_t *pkg, x86_core_t *core)
447 {
448 assert(pkg != NULL);
449 assert(core != NULL);
450
451 core->next = pkg->cores;
452 core->package = pkg;
453 pkg->cores = core;
454 pkg->num_cores += 1;
455 }
456
457 void *
458 cpu_thread_alloc(int cpu)
459 {
460 x86_core_t *core;
461 x86_pkg_t *pkg;
462 cpu_data_t *cpup;
463 uint32_t phys_cpu;
464
465 cpup = cpu_datap(cpu);
466
467 phys_cpu = cpup->cpu_phys_number;
468
469 x86_lcpu_init(cpu);
470
471 /*
472 * Assume that all cpus have the same features.
473 */
474 if (cpu_is_hyperthreaded()) {
475 cpup->cpu_threadtype = CPU_THREADTYPE_INTEL_HTT;
476 } else {
477 cpup->cpu_threadtype = CPU_THREADTYPE_NONE;
478 }
479
480 /*
481 * Only allow one to manipulate the topology at a time.
482 */
483 simple_lock(&x86_topo_lock);
484
485 /*
486 * Get the core for this logical CPU.
487 */
488 core_again:
489 core = x86_core_find(cpu);
490 if (core == NULL) {
491 /*
492 * Core structure hasn't been created yet, do it now.
493 *
494 * Get the package that the core is part of.
495 */
496 package_again:
497 pkg = x86_package_find(cpu);
498 if (pkg == NULL) {
499 /*
500 * Package structure hasn't been created yet, do it now.
501 */
502 simple_unlock(&x86_topo_lock);
503 pkg = x86_package_alloc(cpu);
504 simple_lock(&x86_topo_lock);
505 if (x86_package_find(cpu) != NULL) {
506 x86_package_free(pkg);
507 goto package_again;
508 }
509
510 /*
511 * Add the new package to the global list of packages.
512 */
513 pkg->next = x86_pkgs;
514 x86_pkgs = pkg;
515 }
516
517 /*
518 * Allocate the core structure now.
519 */
520 simple_unlock(&x86_topo_lock);
521 core = x86_core_alloc(cpu);
522 simple_lock(&x86_topo_lock);
523 if (x86_core_find(cpu) != NULL) {
524 x86_core_free(core);
525 goto core_again;
526 }
527
528 /*
529 * Add it to the package.
530 */
531 x86_package_add_core(pkg, core);
532 machine_info.physical_cpu_max += 1;
533
534 /*
535 * Allocate performance counter structure.
536 */
537 simple_unlock(&x86_topo_lock);
538 core->pmc = pmc_alloc();
539 simple_lock(&x86_topo_lock);
540 }
541
542 /*
543 * Done manipulating the topology, so others can get in.
544 */
545 machine_info.logical_cpu_max += 1;
546 simple_unlock(&x86_topo_lock);
547
548 x86_core_add_lcpu(core, &cpup->lcpu);
549
550 return (void *) core;
551 }
552
553 void
554 cpu_thread_init(void)
555 {
556 int my_cpu = get_cpu_number();
557 cpu_data_t *cpup = current_cpu_datap();
558 x86_core_t *core;
559 static int initialized = 0;
560
561 /*
562 * If we're the boot processor, we do all of the initialization of
563 * the CPU topology infrastructure.
564 */
565 if (my_cpu == master_cpu && !initialized) {
566 simple_lock_init(&x86_topo_lock, 0);
567
568 /*
569 * Put this logical CPU into the physical CPU topology.
570 */
571 cpup->lcpu.core = cpu_thread_alloc(my_cpu);
572
573 initialized = 1;
574 }
575
576 /*
577 * Do the CPU accounting.
578 */
579 core = cpup->lcpu.core;
580 simple_lock(&x86_topo_lock);
581 machine_info.logical_cpu += 1;
582 if (core->active_lcpus == 0)
583 machine_info.physical_cpu += 1;
584 core->active_lcpus += 1;
585 cpup->lcpu.halted = FALSE;
586 cpup->lcpu.idle = FALSE;
587 simple_unlock(&x86_topo_lock);
588
589 pmCPUMarkRunning(cpup);
590 etimer_resync_deadlines();
591 }
592
593 /*
594 * Called for a cpu to halt permanently
595 * (as opposed to halting and expecting an interrupt to awaken it).
596 */
597 void
598 cpu_thread_halt(void)
599 {
600 x86_core_t *core;
601 cpu_data_t *cpup = current_cpu_datap();
602
603 simple_lock(&x86_topo_lock);
604 machine_info.logical_cpu -= 1;
605 cpup->lcpu.idle = TRUE;
606 core = cpup->lcpu.core;
607 core->active_lcpus -= 1;
608 if (core->active_lcpus == 0)
609 machine_info.physical_cpu -= 1;
610 simple_unlock(&x86_topo_lock);
611
612 /*
613 * Let the power management code determine the best way to "stop"
614 * the processor.
615 */
616 ml_set_interrupts_enabled(FALSE);
617 while (1) {
618 pmCPUHalt(PM_HALT_NORMAL);
619 }
620 /* NOT REACHED */
621 }