diff options
author | Jonathan Zhang <jonzhang@fb.com> | 2020-04-02 20:03:48 -0700 |
---|---|---|
committer | Philipp Deppenwiese <zaolin.daisuki@gmail.com> | 2020-06-06 07:44:07 +0000 |
commit | b7cf7d36d7cf97b0cce437b9f1577ca39eeb312d (patch) | |
tree | d1df2f10fbaf6a582db3c9a8cbd2da5f14f7e09e /src/soc/intel/xeon_sp/cpx/soc_util.c | |
parent | eaa219b5bba95cfdc03b9b20d1c06d84bd33c702 (diff) |
soc/intel/xeon_sp/cpx: set up cpus
Set up cpus:
* setup apic IDs.
* setup MSR to enable fast string, speed step, etc.
* Enable turbo
Signed-off-by: Jonathan Zhang <jonzhang@fb.com>
Signed-off-by: Reddy Chagam <anjaneya.chagam@intel.com>
Change-Id: I5765e98151f6ceebaabccc06db63d5911caf7ce8
Reviewed-on: https://review.coreboot.org/c/coreboot/+/40112
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Diffstat (limited to 'src/soc/intel/xeon_sp/cpx/soc_util.c')
-rw-r--r-- | src/soc/intel/xeon_sp/cpx/soc_util.c | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/src/soc/intel/xeon_sp/cpx/soc_util.c b/src/soc/intel/xeon_sp/cpx/soc_util.c index 8548615239..2d106575c3 100644 --- a/src/soc/intel/xeon_sp/cpx/soc_util.c +++ b/src/soc/intel/xeon_sp/cpx/soc_util.c @@ -1,10 +1,135 @@ /* SPDX-License-Identifier: GPL-2.0-only */ #include <assert.h> +#include <commonlib/sort.h> +#include <device/device.h> +#include <intelblocks/cpulib.h> +#include <soc/cpu.h> #include <soc/soc_util.h> #include <stdlib.h> #include <string.h> +void get_cpu_info_from_apicid(uint32_t apicid, uint32_t core_bits, uint32_t thread_bits, + uint8_t *package, uint8_t *core, uint8_t *thread) +{ + if (package != NULL) + *package = (apicid >> (thread_bits + core_bits)); + if (core != NULL) + *core = (uint32_t)((apicid >> thread_bits) & ~((~0) << core_bits)); + if (thread != NULL) + *thread = (uint32_t)(apicid & ~((~0) << thread_bits)); +} + +void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits) +{ + register int ecx; + struct cpuid_result cpuid_regs; + + /* get max index of CPUID */ + cpuid_regs = cpuid(0); + assert(cpuid_regs.eax >= 0xb); /* cpuid_regs.eax is max input value for cpuid */ + + *thread_bits = *core_bits = 0; + ecx = 0; + while (1) { + cpuid_regs = cpuid_ext(0xb, ecx); + if (ecx == 0) { + *thread_bits = (cpuid_regs.eax & 0x1f); + } else { + *core_bits = (cpuid_regs.eax & 0x1f) - *thread_bits; + break; + } + ecx++; + } +} + +const IIO_UDS *get_iio_uds(void) +{ + size_t hob_size; + const IIO_UDS *hob; + const uint8_t fsp_hob_iio_universal_data_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; + + hob = fsp_find_extension_hob_by_guid(fsp_hob_iio_universal_data_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + return hob; +} + +unsigned int xeon_sp_get_cpu_count(void) +{ + return get_iio_uds()->SystemStatus.numCpus; +} + +void xeonsp_init_cpu_config(void) +{ + struct device *dev; + int apic_ids[CONFIG_MAX_CPUS] = {0}, apic_ids_by_thread[CONFIG_MAX_CPUS] = {0}; + int num_apics = 0; + uint32_t core_bits, thread_bits; + unsigned int core_count, thread_count; + unsigned int num_cpus; + + /* + * sort APIC ids in asending order to identify apicid ranges for + * each numa domain + */ + for (dev = all_devices; dev; dev = dev->next) { + if ((dev->path.type != DEVICE_PATH_APIC) || + (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!dev->enabled) + continue; + if (num_apics >= ARRAY_SIZE(apic_ids)) + break; + apic_ids[num_apics++] = dev->path.apic.apic_id; + } + if (num_apics > 1) + bubblesort(apic_ids, num_apics, NUM_ASCENDING); + + /* Here num_cpus is the number of processors */ + /* The FSP HOB parameter has it named as num_cpus */ + num_cpus = xeon_sp_get_cpu_count(); + cpu_read_topology(&core_count, &thread_count); + assert(num_apics == (num_cpus * thread_count)); + + /* sort them by thread i.e., all cores with thread 0 and then thread 1 */ + int index = 0; + for (int id = 0; id < num_apics; ++id) { + int apic_id = apic_ids[id]; + if (apic_id & 0x1) { /* 2nd thread */ + apic_ids_by_thread[index + (num_apics/2) - 1] = apic_id; + } else { /* 1st thread */ + apic_ids_by_thread[index++] = apic_id; + } + } + + + /* update apic_id, node_id in sorted order */ + num_apics = 0; + get_core_thread_bits(&core_bits, &thread_bits); + for (dev = all_devices; dev; dev = dev->next) { + uint8_t package; + + if ((dev->path.type != DEVICE_PATH_APIC) || + (dev->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) { + continue; + } + if (!dev->enabled) + continue; + if (num_apics >= ARRAY_SIZE(apic_ids)) + break; + dev->path.apic.apic_id = apic_ids_by_thread[num_apics]; + get_cpu_info_from_apicid(dev->path.apic.apic_id, core_bits, thread_bits, + &package, NULL, NULL); + dev->path.apic.node_id = package; + printk(BIOS_DEBUG, "CPU %d apic_id: 0x%x (%d), node_id: 0x%x\n", + num_apics, dev->path.apic.apic_id, + dev->path.apic.apic_id, dev->path.apic.node_id); + + ++num_apics; + } +} + uint8_t get_iiostack_info(struct iiostack_resource *info) { size_t hob_size; |