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>
This commit is contained in:
parent
eaa219b5bb
commit
b7cf7d36d7
|
@ -2,6 +2,7 @@
|
|||
|
||||
ifeq ($(CONFIG_SOC_INTEL_COOPERLAKE_SP),y)
|
||||
|
||||
subdirs-y += ../../../../cpu/intel/turbo
|
||||
subdirs-y += ../../../../cpu/x86/lapic
|
||||
subdirs-y += ../../../../cpu/x86/mtrr
|
||||
subdirs-y += ../../../../cpu/x86/tsc
|
||||
|
|
|
@ -2,18 +2,49 @@
|
|||
|
||||
#include <acpi/acpigen.h>
|
||||
#include <acpi/acpi.h>
|
||||
#include <assert.h>
|
||||
#include <console/console.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/intel/microcode.h>
|
||||
#include <cpu/intel/turbo.h>
|
||||
#include <cpu/x86/lapic.h>
|
||||
#include <cpu/x86/mp.h>
|
||||
#include <cpu/x86/mtrr.h>
|
||||
#include <intelblocks/cpulib.h>
|
||||
#include <intelblocks/mp_init.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <soc/msr.h>
|
||||
#include <soc/soc_util.h>
|
||||
#include "chip.h"
|
||||
|
||||
static const void *microcode_patch;
|
||||
|
||||
static const config_t *chip_config = NULL;
|
||||
|
||||
static void xeon_configure_mca(void)
|
||||
{
|
||||
msr_t msr;
|
||||
struct cpuid_result cpuid_regs;
|
||||
|
||||
/*
|
||||
* Check feature flag in CPUID.(EAX=1):EDX[7]==1 MCE
|
||||
* and CPUID.(EAX=1):EDX[14]==1 MCA
|
||||
*/
|
||||
cpuid_regs = cpuid(1);
|
||||
if ((cpuid_regs.edx & (1 << 7 | 1 << 14)) != (1 << 7 | 1 << 14))
|
||||
return;
|
||||
|
||||
msr = rdmsr(IA32_MCG_CAP);
|
||||
if (msr.lo & IA32_MCG_CAP_CTL_P_MASK) {
|
||||
/* Enable all error logging */
|
||||
msr.lo = msr.hi = 0xffffffff;
|
||||
wrmsr(IA32_MCG_CTL, msr);
|
||||
}
|
||||
|
||||
mca_configure();
|
||||
}
|
||||
|
||||
|
||||
void get_microcode_info(const void **microcode, int *parallel)
|
||||
{
|
||||
*microcode = intel_mp_current_microcode();
|
||||
|
@ -27,10 +58,28 @@ const void *intel_mp_current_microcode(void)
|
|||
|
||||
static void each_cpu_init(struct device *cpu)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
printk(BIOS_SPEW, "%s dev: %s, cpu: %d, apic_id: 0x%x\n",
|
||||
__func__, dev_path(cpu), cpu_index(), cpu->path.apic.apic_id);
|
||||
|
||||
setup_lapic();
|
||||
|
||||
/* Enable Fast Strings */
|
||||
msr = rdmsr(IA32_MISC_ENABLE);
|
||||
msr.lo |= FAST_STRINGS_ENABLE_BIT;
|
||||
wrmsr(IA32_MISC_ENABLE, msr);
|
||||
/* Enable Turbo */
|
||||
enable_turbo();
|
||||
|
||||
/* Enable speed step. */
|
||||
if (get_turbo_state() == TURBO_ENABLED) {
|
||||
msr = rdmsr(IA32_MISC_ENABLE);
|
||||
msr.lo |= SPEED_STEP_ENABLE_BIT;
|
||||
wrmsr(IA32_MISC_ENABLE, msr);
|
||||
}
|
||||
|
||||
/* Clear out pending MCEs */
|
||||
xeon_configure_mca();
|
||||
}
|
||||
|
||||
static struct device_operations cpu_dev_ops = {
|
||||
|
@ -47,6 +96,33 @@ static const struct cpu_driver driver __cpu_driver = {
|
|||
.id_table = cpu_table,
|
||||
};
|
||||
|
||||
static void set_max_turbo_freq(void)
|
||||
{
|
||||
msr_t msr, perf_ctl;
|
||||
|
||||
FUNC_ENTER();
|
||||
perf_ctl.hi = 0;
|
||||
|
||||
/* Check for configurable TDP option */
|
||||
if (get_turbo_state() == TURBO_ENABLED) {
|
||||
msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
|
||||
perf_ctl.lo = (msr.lo & 0xff) << 8;
|
||||
} else if (cpu_config_tdp_levels()) {
|
||||
/* Set to nominal TDP ratio */
|
||||
msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
|
||||
perf_ctl.lo = (msr.lo & 0xff) << 8;
|
||||
} else {
|
||||
/* Platform Info bits 15:8 give max ratio */
|
||||
msr = rdmsr(MSR_PLATFORM_INFO);
|
||||
perf_ctl.lo = msr.lo & 0xff00;
|
||||
}
|
||||
wrmsr(IA32_PERF_CTL, perf_ctl);
|
||||
|
||||
printk(BIOS_DEBUG, "cpu: frequency set to %d\n",
|
||||
((perf_ctl.lo >> 8) & 0xff) * CPU_BCLK);
|
||||
FUNC_EXIT();
|
||||
}
|
||||
|
||||
/*
|
||||
* Do essential initialization tasks before APs can be fired up
|
||||
*/
|
||||
|
@ -72,10 +148,17 @@ static int get_thread_count(void)
|
|||
return num_virts * CONFIG_MAX_SOCKET;
|
||||
}
|
||||
|
||||
static void post_mp_init(void)
|
||||
{
|
||||
/* Set Max Ratio */
|
||||
set_max_turbo_freq();
|
||||
}
|
||||
|
||||
static const struct mp_ops mp_ops = {
|
||||
.pre_mp_init = pre_mp_init,
|
||||
.get_cpu_count = get_thread_count,
|
||||
.get_microcode_info = get_microcode_info
|
||||
.get_microcode_info = get_microcode_info,
|
||||
.post_mp_init = post_mp_init,
|
||||
};
|
||||
|
||||
void cpx_init_cpus(struct device *dev)
|
||||
|
@ -89,4 +172,13 @@ void cpx_init_cpus(struct device *dev)
|
|||
|
||||
if (mp_init_with_smm(dev->link_list, &mp_ops) < 0)
|
||||
printk(BIOS_ERR, "MP initialization failure.\n");
|
||||
|
||||
/*
|
||||
* chip_config is used in cpu device callback. Other than cpu 0,
|
||||
* rest of the CPU devices do not have chip_info updated.
|
||||
*/
|
||||
chip_config = dev->chip_info;
|
||||
|
||||
/* update numa domain for all cpu devices */
|
||||
xeonsp_init_cpu_config();
|
||||
}
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
|
||||
#define CPUID_COOPERLAKE_SP_A0 0x05065a
|
||||
|
||||
/* CPU bus clock is fixed at 100MHz */
|
||||
#define CPU_BCLK 100
|
||||
|
||||
void cpx_init_cpus(struct device *dev);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,99 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _SOC_MSR_H_
|
||||
#define _SOC_MSR_H_
|
||||
|
||||
#include <intelblocks/msr.h>
|
||||
|
||||
#define IA32_MCG_CAP 0x179
|
||||
#define IA32_MCG_CAP_COUNT_MASK 0xff
|
||||
#define IA32_MCG_CAP_CTL_P_BIT 8
|
||||
#define IA32_MCG_CAP_CTL_P_MASK (1 << IA32_MCG_CAP_CTL_P_BIT)
|
||||
|
||||
#define IA32_MCG_CTL 0x17b
|
||||
|
||||
/* IA32_MISC_ENABLE bits */
|
||||
#define FAST_STRINGS_ENABLE_BIT (1 << 0)
|
||||
#define SPEED_STEP_ENABLE_BIT (1 << 16)
|
||||
#define MONIOR_ENABLE_BIT (1 << 18)
|
||||
|
||||
#define MSR_IA32_ENERGY_PERF_BIAS 0x1b0
|
||||
|
||||
/* MSR_PKG_CST_CONFIG_CONTROL bits */
|
||||
#define MSR_PKG_CST_CONFIG_CONTROL 0xe2
|
||||
#define PKG_CSTATE_LIMIT_SHIFT 0 /* 0:3 */
|
||||
/* No package C-state limit. All C-States supported by the processor are available. */
|
||||
#define PKG_CSTATE_LIMIT_MASK (0xf << PKG_CSTATE_LIMIT_SHIFT)
|
||||
#define PKG_CSTATE_NO_LIMIT (0x7 << PKG_CSTATE_LIMIT_SHIFT)
|
||||
#define IO_MWAIT_REDIRECTION_SHIFT 10
|
||||
#define IO_MWAIT_REDIRECTION_ENABLE (1 << IO_MWAIT_REDIRECTION_SHIFT)
|
||||
#define CFG_LOCK_SHIFT 15
|
||||
#define CFG_LOCK_ENABLE (1 << CFG_LOCK_SHIFT)
|
||||
|
||||
/* MSR_PMG_IO_CAPTURE_BASE bits */
|
||||
#define MSR_PMG_IO_CAPTURE_BASE 0xe4
|
||||
#define LVL_2_BASE_ADDRESS_SHIFT 0 /* 15:0 bits */
|
||||
#define LVL_2_BASE_ADDRESS (0x0514 << LVL_2_BASE_ADDRESS_SHIFT)
|
||||
#define CST_RANGE_SHIFT 16 /* 18:16 bits */
|
||||
#define CST_RANGE_MAX_C6 (0x1 << CST_RANGE_SHIFT)
|
||||
|
||||
/* MSR_POWER_CTL bits */
|
||||
#define MSR_POWER_CTL 0x1fc
|
||||
#define BIDIR_PROCHOT_ENABLE_SHIFT 0
|
||||
#define BIDIR_PROCHOT_ENABLE (1 << BIDIR_PROCHOT_ENABLE_SHIFT)
|
||||
#define FAST_BRK_SNP_ENABLE_SHIFT 3
|
||||
#define FAST_BRK_SNP_ENABLE (1 << FAST_BRK_SNP_ENABLE_SHIFT)
|
||||
#define FAST_BRK_INT_ENABLE_SHIFT 4
|
||||
#define FAST_BRK_INT_ENABLE (1 << FAST_BRK_INT_ENABLE_SHIFT)
|
||||
#define PHOLD_CST_PREVENTION_INIT_SHIFT 6
|
||||
#define PHOLD_CST_PREVENTION_INIT_VALUE (1 << PHOLD_CST_PREVENTION_INIT_SHIFT)
|
||||
#define ENERGY_PERF_BIAS_ACCESS_ENABLE_SHIFT 18
|
||||
#define ENERGY_PERF_BIAS_ACCESS_ENABLE (1 << ENERGY_PERF_BIAS_ACCESS_ENABLE_SHIFT)
|
||||
#define PROCHOT_OUTPUT_DISABLE_SHIFT 21
|
||||
#define PROCHOT_OUTPUT_DISABLE (1 << PROCHOT_OUTPUT_DISABLE_SHIFT)
|
||||
#define PWR_PERF_TUNING_DYN_SWITCHING_SHIFT 24
|
||||
#define PWR_PERF_TUNING_DYN_SWITCHING_ENABLE (1 << PWR_PERF_TUNING_DYN_SWITCHING_SHIFT)
|
||||
#define PROCHOT_LOCK_SHIFT 27
|
||||
#define PROCHOT_LOCK_ENABLE (1 << PROCHOT_LOCK_SHIFT)
|
||||
#define LTR_IIO_DISABLE_SHIFT 29
|
||||
#define LTR_IIO_DISABLE (1 << LTR_IIO_DISABLE_SHIFT)
|
||||
|
||||
/* MSR_IA32_PERF_CTRL (0x199) bits */
|
||||
#define MSR_IA32_PERF_CTRL 0x199
|
||||
#define PSTATE_REQ_SHIFT 8 /* 8:14 bits */
|
||||
#define PSTATE_REQ_MASK (0x7f << PSTATE_REQ_SHIFT)
|
||||
#define PSTATE_REQ_RATIO (0xa << PSTATE_REQ_SHIFT)
|
||||
|
||||
/* MSR_MISC_PWR_MGMT bits */
|
||||
#define MSR_MISC_PWR_MGMT 0x1aa
|
||||
#define HWP_ENUM_SHIFT 6
|
||||
#define HWP_ENUM_ENABLE (1 << HWP_ENUM_SHIFT)
|
||||
#define HWP_EPP_SHIFT 12
|
||||
#define HWP_EPP_ENUM_ENABLE (1 << HWP_EPP_SHIFT)
|
||||
#define LOCK_MISC_PWR_MGMT_MSR_SHIFT 13
|
||||
#define LOCK_MISC_PWR_MGMT_MSR (1 << LOCK_MISC_PWR_MGMT_MSR_SHIFT)
|
||||
#define LOCK_THERM_INT_SHIFT 22
|
||||
#define LOCK_THERM_INT (1 << LOCK_THERM_INT_SHIFT)
|
||||
|
||||
/* MSR_TURBO_RATIO_LIMIT bits */
|
||||
#define MSR_TURBO_RATIO_LIMIT 0x1ad
|
||||
|
||||
/* MSR_TURBO_RATIO_LIMIT_CORES (0x1ae) */
|
||||
#define MSR_TURBO_RATIO_LIMIT_CORES 0x1ae
|
||||
|
||||
/* MSR_VR_CURRENT_CONFIG bits */
|
||||
#define MSR_VR_CURRENT_CONFIG 0x601
|
||||
#define CURRENT_LIMIT_LOCK_SHIFT 31
|
||||
#define CURRENT_LIMIT_LOCK (0x1 << CURRENT_LIMIT_LOCK_SHIFT)
|
||||
|
||||
/* MSR_TURBO_ACTIVATION_RATIO bits */
|
||||
#define MSR_TURBO_ACTIVATION_RATIO 0x64c
|
||||
#define MAX_NON_TURBO_RATIO_SHIFT 0
|
||||
#define MAX_NON_TURBO_RATIO (0xff << MAX_NON_TURBO_RATIO_SHIFT)
|
||||
|
||||
/* MSR_ENERGY_PERF_BIAS_CONFIG bits */
|
||||
#define MSR_ENERGY_PERF_BIAS_CONFIG 0xa01
|
||||
#define EPB_ENERGY_POLICY_SHIFT 3
|
||||
#define EPB_ENERGY_POLICY_MASK (0xf << EPB_ENERGY_POLICY_SHIFT)
|
||||
|
||||
#endif /* _SOC_MSR_H_ */
|
|
@ -16,10 +16,24 @@
|
|||
printk(BIOS_SPEW, "%s:%s:%d: EXIT (dev: %s)\n", __FILE__, \
|
||||
__func__, __LINE__, dev_path(dev))
|
||||
|
||||
#define FUNC_ENTER() \
|
||||
printk(BIOS_SPEW, "%s:%s:%d: ENTER\n", __FILE__, __func__, __LINE__)
|
||||
|
||||
#define FUNC_EXIT() \
|
||||
printk(BIOS_SPEW, "%s:%s:%d: EXIT\n", __FILE__, __func__, __LINE__)
|
||||
|
||||
struct iiostack_resource {
|
||||
uint8_t no_of_stacks;
|
||||
STACK_RES res[MAX_SOCKET * MAX_LOGIC_IIO_STACK];
|
||||
};
|
||||
|
||||
uint8_t get_iiostack_info(struct iiostack_resource *info);
|
||||
|
||||
void xeonsp_init_cpu_config(void);
|
||||
const IIO_UDS *get_iio_uds(void);
|
||||
void get_core_thread_bits(uint32_t *core_bits, uint32_t *thread_bits);
|
||||
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);
|
||||
unsigned int xeon_sp_get_cpu_count(void);
|
||||
|
||||
#endif /* _SOC_UTIL_H_ */
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue