blob: 32c5e0156e9b152a3b972249778fac7642916f48 [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
Kyösti Mälkki5c3f3842014-05-08 15:27:15 +030010#if CONFIG_PARALLEL_CPU_INIT
Sven Schnelle51676b12012-07-29 19:18:03 +020011#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;
Kyösti Mälkkidf0fbc72012-07-04 12:02:58 +030031 if (cpuid_eax(0) >= 4) {
32 struct cpuid_result result;
33 result = cpuid_ext(4, 0);
34 core_ids += (result.eax >> 26) & 0x3f;
35 }
Kyösti Mälkki9ed14562012-06-27 16:14:49 +030036
37 threads = (apic_ids / core_ids);
38 return !!(lapicid() & (threads-1));
39}
Sven Schnelle51676b12012-07-29 19:18:03 +020040
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +110041void intel_sibling_init(struct device *cpu)
Sven Schnelle51676b12012-07-29 19:18:03 +020042{
43 unsigned i, siblings;
44 struct cpuid_result result;
45
46 /* On the bootstrap processor see if I want sibling cpus enabled */
47 if (first_time) {
48 first_time = 0;
49 get_option(&disable_siblings, "hyper_threading");
50 }
51 result = cpuid(1);
52 /* Is hyperthreading supported */
53 if (!(result.edx & (1 << 28))) {
54 return;
55 }
56 /* See how many sibling cpus we have */
57 siblings = (result.ebx >> 16) & 0xff;
58 if (siblings < 1) {
59 siblings = 1;
60 }
61
62 printk(BIOS_DEBUG, "CPU: %u %d siblings\n",
63 cpu->path.apic.apic_id,
64 siblings);
65
66 /* See if I am a sibling cpu */
67 if (cpu->path.apic.apic_id & (siblings -1)) {
68 if (disable_siblings) {
69 cpu->enabled = 0;
70 }
71 return;
72 }
73
74 /* I am the primary cpu start up my siblings */
75 for(i = 1; i < siblings; i++) {
76 struct device_path cpu_path;
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +110077 struct device *new;
Sven Schnelle51676b12012-07-29 19:18:03 +020078 /* Build the cpu device path */
79 cpu_path.type = DEVICE_PATH_APIC;
80 cpu_path.apic.apic_id = cpu->path.apic.apic_id + i;
81
82
83 /* Allocate new cpu device structure iff sibling CPU
84 * was not in static device tree.
85 */
86 new = alloc_find_dev(cpu->bus, &cpu_path);
87
88 if (!new) {
89 continue;
90 }
91
92 printk(BIOS_DEBUG, "CPU: %u has sibling %u\n",
93 cpu->path.apic.apic_id,
94 new->path.apic.apic_id);
95 }
96}