Arthur Heymans has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/69222 )
Change subject: cpu/x86/topology: Add code to fill in topology on struct path ......................................................................
cpu/x86/topology: Add code to fill in topology on struct path
This is needed to generate MADT and SRAT where lapicid for threads need to be added last.
Change-Id: I2210eb9b663dd90941a64132aa7154440dc7e5a9 Signed-off-by: Arthur Heymans arthur@aheymans.xyz --- M src/cpu/x86/Makefile.inc M src/cpu/x86/mp_init.c A src/cpu/x86/topology.c A src/include/cpu/x86/topology.h 4 files changed, 98 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/22/69222/1
diff --git a/src/cpu/x86/Makefile.inc b/src/cpu/x86/Makefile.inc index 159b069..e1aff49 100644 --- a/src/cpu/x86/Makefile.inc +++ b/src/cpu/x86/Makefile.inc @@ -64,3 +64,5 @@ $(call src-to-obj,$(TARGET_STAGE),$(SIPI_BIN).manual): $(SIPI_BIN) @printf " OBJCOPY $(subst $(obj)/,,$(@))\n" cd $(dir $<); $(OBJCOPY_rmodules_$(ARCH-$(TARGET_STAGE)-y)) -I binary $(notdir $<) $(target-objcopy) $(abspath $@) + +ramstage-y += topology.c diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index ee8a685..e7702a1 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -13,6 +13,7 @@ #include <cpu/x86/msr.h> #include <cpu/x86/mtrr.h> #include <cpu/x86/smm.h> +#include <cpu/x86/topology.h> #include <cpu/x86/mp.h> #include <delay.h> #include <device/device.h> @@ -198,6 +199,8 @@ dev->path.apic.initial_lapicid = initial_lapicid(); dev->enabled = 1;
+ set_cpu_topology_from_leaf_b(dev); + if (cpu_is_intel()) printk(BIOS_INFO, "AP: slot %zu apic_id %x, MCU rev: 0x%08x\n", info->index, info->cpu->path.apic.apic_id, get_current_microcode_rev()); diff --git a/src/cpu/x86/topology.c b/src/cpu/x86/topology.c new file mode 100644 index 0000000..c1e417f --- /dev/null +++ b/src/cpu/x86/topology.c @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <arch/cpu.h> +#include <device/device.h> +#include <cpu/x86/topology.h> + +#define CPUID_EXTENDED_CPU_TOPOLOGY 0x0b +#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) + +/* Get number of bits for core ID and SMT ID */ +static enum cb_err 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 */ + if (cpuid_max_func >= CPUID_EXTENDED_CPU_TOPOLOGY) + return CB_ERR; + + 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 */ + if (CPUID_CPU_TOPOLOGY_LEVEL(cpuid_regs) == LEVEL_TYPE_SMT) + return CB_ERR; + + *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)); + + return CB_SUCCESS; +} + +void set_cpu_topology_from_leaf_b(struct device *cpu) +{ + if (cpu->path.type != DEVICE_PATH_APIC) + return; + + uint32_t core_bits, thread_bits; + if (get_cpu_core_thread_bits(&core_bits, &thread_bits) != CB_SUCCESS) + return; + + const uint32_t apicid = cpu->path.apic.initial_lapicid; + cpu->path.apic.package_id = apicid >> (thread_bits + core_bits); + cpu->path.apic.core_id = (apicid >> thread_bits) & ((1 << core_bits) - 1); + cpu->path.apic.thread_id = apicid & ((1 << thread_bits) - 1); +} diff --git a/src/include/cpu/x86/topology.h b/src/include/cpu/x86/topology.h new file mode 100644 index 0000000..f92005b --- /dev/null +++ b/src/include/cpu/x86/topology.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef CPU_X86_TOPOLOGY_H +#define CPU_X86_TOPOLOGY_H + +void set_cpu_topology_from_leaf_b(struct device *cpu); + +#endif