From d192590e29167a34a55439308686957feee07b71 Mon Sep 17 00:00:00 2001 From: Aamir Bohra Date: Fri, 19 Feb 2021 16:18:07 +0530 Subject: intel/common/block/cpu: Add APIs to get CPU info from lapic ID Add support to get core, package and thread ID from lapic ID. Implementation uses CPUID extended topology instruction to derive bit offsets for core, package and thread info in apic ID. BUG=b:179113790 Change-Id: If26d34d4250f5a88bdafacdd5d56b8882b69409e Signed-off-by: Aamir Bohra Reviewed-on: https://review.coreboot.org/c/coreboot/+/50913 Tested-by: build bot (Jenkins) Reviewed-by: Angel Pons Reviewed-by: EricR Lai --- src/soc/intel/common/block/cpu/cpulib.c | 69 ++++++++++++++++++++++ .../common/block/include/intelblocks/cpulib.h | 4 ++ 2 files changed, 73 insertions(+) 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 */ -- cgit v1.2.3