blob: b9a9ae7bb1c7b20149ba435be127910f07aa68ca [file] [log] [blame]
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00001#include <console/console.h>
2#include <cpu/cpu.h>
3#include <cpu/x86/lapic.h>
4#include <cpu/intel/hyperthreading.h>
5#include <device/device.h>
6#include <pc80/mc146818rtc.h>
7#include <smp/spinlock.h>
Kyösti Mälkki8b28d502012-03-09 17:02:37 +02008#include <assert.h>
9
Sven Schnelle51676b12012-07-29 19:18:03 +020010#if !CONFIG_SERIAL_CPU_INIT
11#error Intel hyper-threading requires serialized cpu init
12#endif
13
14static int first_time = 1;
15static int disable_siblings = !CONFIG_LOGICAL_CPUS;
16
Kyösti Mälkki9ed14562012-06-27 16:14:49 +030017/* Return true if running thread does not have the smallest lapic ID
18 * within a CPU core.
19 */
20int intel_ht_sibling(void)
21{
22 unsigned int core_ids, apic_ids, threads;
23
24 apic_ids = 1;
25 if (cpuid_eax(0) >= 1)
26 apic_ids = (cpuid_ebx(1) >> 16) & 0xff;
27 if (apic_ids < 1)
28 apic_ids = 1;
29
30 core_ids = 1;
31 if (cpuid_eax(0) >= 4)
32 core_ids += (cpuid_eax(4) >> 26) & 0x3f;
33
34 threads = (apic_ids / core_ids);
35 return !!(lapicid() & (threads-1));
36}
Sven Schnelle51676b12012-07-29 19:18:03 +020037
38void intel_sibling_init(device_t cpu)
39{
40 unsigned i, siblings;
41 struct cpuid_result result;
42
43 /* On the bootstrap processor see if I want sibling cpus enabled */
44 if (first_time) {
45 first_time = 0;
46 get_option(&disable_siblings, "hyper_threading");
47 }
48 result = cpuid(1);
49 /* Is hyperthreading supported */
50 if (!(result.edx & (1 << 28))) {
51 return;
52 }
53 /* See how many sibling cpus we have */
54 siblings = (result.ebx >> 16) & 0xff;
55 if (siblings < 1) {
56 siblings = 1;
57 }
58
59 printk(BIOS_DEBUG, "CPU: %u %d siblings\n",
60 cpu->path.apic.apic_id,
61 siblings);
62
63 /* See if I am a sibling cpu */
64 if (cpu->path.apic.apic_id & (siblings -1)) {
65 if (disable_siblings) {
66 cpu->enabled = 0;
67 }
68 return;
69 }
70
71 /* I am the primary cpu start up my siblings */
72 for(i = 1; i < siblings; i++) {
73 struct device_path cpu_path;
74 device_t new;
75 /* Build the cpu device path */
76 cpu_path.type = DEVICE_PATH_APIC;
77 cpu_path.apic.apic_id = cpu->path.apic.apic_id + i;
78
79
80 /* Allocate new cpu device structure iff sibling CPU
81 * was not in static device tree.
82 */
83 new = alloc_find_dev(cpu->bus, &cpu_path);
84
85 if (!new) {
86 continue;
87 }
88
89 printk(BIOS_DEBUG, "CPU: %u has sibling %u\n",
90 cpu->path.apic.apic_id,
91 new->path.apic.apic_id);
92 }
93}
94