From fb3f025ea6f5a8a2f6e3dbc6c693c5e3943dbf53 Mon Sep 17 00:00:00 2001 From: Naresh Solanki Date: Wed, 2 Apr 2025 19:24:17 +0530 Subject: [PATCH] soc/amd/common/cpu/noncar: Add SMBIOS helper Some SoC like Glinda, 1. It has multiple L3 caches block, each identified by a unique cache UID. Each core is associated with a specific L3 cache, which can be determined based on the CPU core ID. 2. Each CPU core have slightly different CPU boost frequency. For L3 cache info in DMI table type 7, the default implementation (x86_get_cpu_cache_info) retrieves cache information only for the current core and assumes that the same L3 cache is shared across all cores. To accurately determine the total L3 cache size: 1. Retrieves L3 cache information for each CPU core. 2. Identifies the unique cache ID associated with each core. 3. Aggregates cache sizes for all unique cache IDs to compute the total L3 cache size, ensuring correct summation even when L3 cache blocks have different sizes. Additionally to get core max boost frequency, 1. Determine max boost frequency among all cores & update smbios_cpu_get_max_speed_mhz such that it return max of all cores. TEST=Build for Glinda SoC & check output of `dmidecode -t 7` & `dmidecode -t 4`. Verify DMI Type7 table to report L3 cache size as 24MB (16 + 8) & Also verify DMI Type4 'Max Speed: 5408 MHz' which is maximum boost clock frequency. Change-Id: I2569a9c744f7f41e4df692626e77a178184b7e0e Signed-off-by: Naresh Solanki Reviewed-on: https://review.coreboot.org/c/coreboot/+/87123 Tested-by: build bot (Jenkins) Reviewed-by: Maximilian Brune --- src/soc/amd/common/block/cpu/noncar/cpu.c | 56 +++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/soc/amd/common/block/cpu/noncar/cpu.c b/src/soc/amd/common/block/cpu/noncar/cpu.c index dfa6a69f42..c88e541ab6 100644 --- a/src/soc/amd/common/block/cpu/noncar/cpu.c +++ b/src/soc/amd/common/block/cpu/noncar/cpu.c @@ -115,6 +115,62 @@ unsigned int get_reserved_phys_addr_bits(void) CPUID_EBX_MEM_ENCRYPT_ADDR_BITS_SHIFT; } +unsigned int smbios_cpu_get_max_speed_mhz(void) +{ + uint32_t max_freq = 0; + + for (int i = 0; i < get_cpu_count(); i++) { + struct core_info *core_info = &core_info_list[i]; + + if (max_freq < core_info->max_frequency) + max_freq = core_info->max_frequency; + } + return max_freq; +} + +/* + * On some SoCs like AMD Glinda, multiple unique L3 cache blocks exist, + * each with a distinct UID and possibly different sizes. The default + * method assumes a single shared L3 cache across all cores, which is + * inaccurate. This function aggregates sizes of all uniquely identified + * L3 cache blocks to compute the correct total L3 size. + */ +bool soc_fill_cpu_cache_info(uint8_t level, struct cpu_cache_info *info) +{ + if (level != CACHE_L3) + return x86_get_cpu_cache_info(level, info); + + if (!info) + return false; + + uint32_t total_cache = 0; + bool seen_cache_ids[CONFIG_MAX_CPUS] = {false}; + + x86_get_cpu_cache_info(level, info); + + /* + * To calculate the total L3 cache size, iterate over core_info_list and add up the sizes + * of the L3 cache blocks with unique cache ID. + */ + for (int i = 0; i < get_cpu_count(); i++) { + struct core_info *cache = &core_info_list[i]; + + printk(BIOS_SPEW, "CPU %d: Cache Level: %d, Cache Size: %zu bytes\n", + i, cache->l3_cache_uid, cache->l3_cache_size); + + if (!seen_cache_ids[cache->l3_cache_uid]) { + total_cache += cache->l3_cache_size; + seen_cache_ids[cache->l3_cache_uid] = true; + } + } + + info->num_cores_shared = get_cpu_count(); + info->size = total_cache; + + printk(BIOS_SPEW, "Total cache at level: %d is:%zu\n", level, info->size); + return true; +} + static uint32_t get_max_boost_frequency(void) { msr_t msr = rdmsr(MSR_CPPC_CAPABILITY_1);