blob: 38f6efcf974191968db806006c67938e9809867a [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Damien Roth07a196e2016-01-19 20:20:15 -07002
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00003#include <console/console.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00004#include <cpu/intel/hyperthreading.h>
5#include <device/device.h>
Kyösti Mälkkicbf95712020-01-05 08:05:45 +02006#include <option.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00007#include <smp/spinlock.h>
Kyösti Mälkki8b28d502012-03-09 17:02:37 +02008
Julius Wernercd49cce2019-03-05 16:53:33 -08009#if CONFIG(PARALLEL_CPU_INIT)
Elyes HAOUASd82be922016-07-28 18:58:27 +020010#error Intel hyper-threading requires serialized CPU init
Sven Schnelle51676b12012-07-29 19:18:03 +020011#endif
12
13static int first_time = 1;
Julius Werner5d1f9a02019-03-07 17:07:26 -080014static int disable_siblings = !CONFIG(LOGICAL_CPUS);
Sven Schnelle51676b12012-07-29 19:18:03 +020015
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +110016void intel_sibling_init(struct device *cpu)
Sven Schnelle51676b12012-07-29 19:18:03 +020017{
Lee Leahy73a28942017-03-15 17:52:06 -070018 unsigned int i, siblings;
Sven Schnelle51676b12012-07-29 19:18:03 +020019 struct cpuid_result result;
20
21 /* On the bootstrap processor see if I want sibling cpus enabled */
22 if (first_time) {
23 first_time = 0;
Angel Pons88dcb312021-04-26 17:10:28 +020024 disable_siblings = get_uint_option("hyper_threading", disable_siblings);
Sven Schnelle51676b12012-07-29 19:18:03 +020025 }
26 result = cpuid(1);
27 /* Is hyperthreading supported */
Lee Leahy26eeb0f2017-03-15 18:08:50 -070028 if (!(result.edx & (1 << 28)))
Sven Schnelle51676b12012-07-29 19:18:03 +020029 return;
Lee Leahy26eeb0f2017-03-15 18:08:50 -070030
Sven Schnelle51676b12012-07-29 19:18:03 +020031 /* See how many sibling cpus we have */
32 siblings = (result.ebx >> 16) & 0xff;
Lee Leahy26eeb0f2017-03-15 18:08:50 -070033 if (siblings < 1)
Sven Schnelle51676b12012-07-29 19:18:03 +020034 siblings = 1;
Sven Schnelle51676b12012-07-29 19:18:03 +020035
36 printk(BIOS_DEBUG, "CPU: %u %d siblings\n",
37 cpu->path.apic.apic_id,
38 siblings);
39
40 /* See if I am a sibling cpu */
Lee Leahy9d62e7e2017-03-15 17:40:50 -070041 if (cpu->path.apic.apic_id & (siblings - 1)) {
Lee Leahy26eeb0f2017-03-15 18:08:50 -070042 if (disable_siblings)
Sven Schnelle51676b12012-07-29 19:18:03 +020043 cpu->enabled = 0;
Sven Schnelle51676b12012-07-29 19:18:03 +020044 return;
45 }
46
Elyes HAOUASd82be922016-07-28 18:58:27 +020047 /* I am the primary CPU start up my siblings */
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +020048 for (i = 1; i < siblings; i++) {
Sven Schnelle51676b12012-07-29 19:18:03 +020049 struct device_path cpu_path;
Edward O'Callaghan2c9d2cf2014-10-27 23:29:29 +110050 struct device *new;
Elyes HAOUASd82be922016-07-28 18:58:27 +020051 /* Build the CPU device path */
Sven Schnelle51676b12012-07-29 19:18:03 +020052 cpu_path.type = DEVICE_PATH_APIC;
53 cpu_path.apic.apic_id = cpu->path.apic.apic_id + i;
54
Elyes HAOUASd82be922016-07-28 18:58:27 +020055 /* Allocate new CPU device structure iff sibling CPU
Sven Schnelle51676b12012-07-29 19:18:03 +020056 * was not in static device tree.
57 */
58 new = alloc_find_dev(cpu->bus, &cpu_path);
59
Lee Leahy26eeb0f2017-03-15 18:08:50 -070060 if (!new)
Sven Schnelle51676b12012-07-29 19:18:03 +020061 continue;
Sven Schnelle51676b12012-07-29 19:18:03 +020062
63 printk(BIOS_DEBUG, "CPU: %u has sibling %u\n",
64 cpu->path.apic.apic_id,
65 new->path.apic.apic_id);
66 }
67}