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 #include #include #include @@ -12,6 +13,24 @@ #include #include +#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 */