summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/common/block/cpu/cpulib.c69
-rw-r--r--src/soc/intel/common/block/include/intelblocks/cpulib.h4
2 files changed, 73 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/cpu/cpulib.c b/src/soc/intel/common/block/cpu/cpulib.c
index 854da2ea1e..34ec233164 100644
--- a/src/soc/intel/common/block/cpu/cpulib.c
+++ b/src/soc/intel/common/block/cpu/cpulib.c
@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
+#include <assert.h>
#include <acpi/acpigen.h>
#include <console/console.h>
#include <cpu/intel/turbo.h>
@@ -12,6 +13,24 @@
#include <soc/soc_chip.h>
#include <types.h>
+#define CPUID_EXTENDED_CPU_TOPOLOGY 0x0b
+#define CPUID_EXTENDED_CPU_TOPOLOGY_V2 0x1f
+#define LEVEL_TYPE_CORE 2
+#define LEVEL_TYPE_SMT 1
+
+#define CPUID_CPU_TOPOLOGY(x, val) \
+ (((val) >> CPUID_CPU_TOPOLOGY_##x##_SHIFT) & CPUID_CPU_TOPOLOGY_##x##_MASK)
+
+#define CPUID_CPU_TOPOLOGY_LEVEL_TYPE_SHIFT 0x8
+#define CPUID_CPU_TOPOLOGY_LEVEL_TYPE_MASK 0xff
+#define CPUID_CPU_TOPOLOGY_LEVEL(res) CPUID_CPU_TOPOLOGY(LEVEL_TYPE, (res).ecx)
+
+#define CPUID_CPU_TOPOLOGY_LEVEL_BITS_SHIFT 0x0
+#define CPUID_CPU_TOPOLOGY_LEVEL_BITS_MASK 0x1f
+#define CPUID_CPU_TOPOLOGY_THREAD_BITS(res) CPUID_CPU_TOPOLOGY(LEVEL_BITS, (res).eax)
+#define CPUID_CPU_TOPOLOGY_CORE_BITS(res, threadbits) \
+ ((CPUID_CPU_TOPOLOGY(LEVEL_BITS, (res).eax)) - threadbits)
+
/*
* Set PERF_CTL MSR (0x199) P_Req with
* Turbo Ratio which is the Maximum Ratio.
@@ -380,3 +399,53 @@ int get_valid_prmrr_size(void)
return valid_size;
}
+
+/* Get number of bits for core ID and SMT ID */
+static void get_cpu_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits)
+{
+ struct cpuid_result cpuid_regs;
+ int level_num, cpu_id_op = 0;
+ const uint32_t cpuid_max_func = cpuid_get_max_func();
+
+ /* Assert if extended CPU topology not supported */
+ assert(cpuid_max_func >= CPUID_EXTENDED_CPU_TOPOLOGY);
+
+ /* Check for extended CPU topology CPUID support */
+ if (cpuid_max_func >= CPUID_EXTENDED_CPU_TOPOLOGY_V2)
+ cpu_id_op = CPUID_EXTENDED_CPU_TOPOLOGY_V2;
+ else if (cpuid_max_func >= CPUID_EXTENDED_CPU_TOPOLOGY)
+ cpu_id_op = CPUID_EXTENDED_CPU_TOPOLOGY;
+
+ *core_bits = level_num = 0;
+ cpuid_regs = cpuid_ext(cpu_id_op, level_num);
+
+ /* Sub-leaf index 0 enumerates SMT level, if not assert */
+ assert(CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs) == LEVEL_TYPE_SMT);
+
+ *thread_bits = CPUID_CPU_TOPOLOGY_THREAD_BITS(cpuid_regs);
+ do {
+ level_num++;
+ cpuid_regs = cpuid_ext(cpu_id_op, level_num);
+ if (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs) == LEVEL_TYPE_CORE) {
+ *core_bits = CPUID_CPU_TOPOLOGY_CORE_BITS(cpuid_regs, *thread_bits);
+ break;
+ }
+ /* Stop when level type is invalid i.e 0 */
+ } while (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs));
+}
+
+void get_cpu_topology_from_apicid(uint32_t apicid, uint8_t *package,
+ uint8_t *core, uint8_t *thread)
+{
+
+ uint32_t core_bits, thread_bits;
+
+ get_cpu_core_thread_bits(&core_bits, &thread_bits);
+
+ if (package)
+ *package = apicid >> (thread_bits + core_bits);
+ if (core)
+ *core = (apicid >> thread_bits) & ((1 << core_bits) - 1);
+ if (thread)
+ *thread = apicid & ((1 << thread_bits) - 1);
+}
diff --git a/src/soc/intel/common/block/include/intelblocks/cpulib.h b/src/soc/intel/common/block/include/intelblocks/cpulib.h
index 4dfbef48f6..6fc31b374e 100644
--- a/src/soc/intel/common/block/include/intelblocks/cpulib.h
+++ b/src/soc/intel/common/block/include/intelblocks/cpulib.h
@@ -162,4 +162,8 @@ int get_valid_prmrr_size(void);
*/
void enable_pm_timer_emulation(void);
+/* Derive core, package and thread information from lapic ID */
+void get_cpu_topology_from_apicid(uint32_t apicid, uint8_t *package,
+ uint8_t *core, uint8_t *thread);
+
#endif /* SOC_INTEL_COMMON_BLOCK_CPULIB_H */