soc/intel/common: Order the CPUs based on their APIC IDs
The patch defines acpi_set_cpu_apicid_order() which orders the APIC IDs based on APIC IDs of Performance cores and Efficient cores, calculates the total core count and total Performance cores count, populates the information in the cpu_apicid_order_info struct. The helper function useful to present the Performance and Efficient cores in order to OS through MADT table and _CPC object. TEST=Verify the build for Gimble (Alder Lake board) Change-Id: I8ab6053ffd036185d74d5469fbdf36d48e0021ce Signed-off-by: Sridhar Siricilla <sridhar.siricilla@intel.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/72131 Reviewed-by: Arthur Heymans <arthur@aheymans.xyz> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
parent
450699d1c8
commit
f8ac3dda02
|
@ -1,12 +1,15 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
#include <acpi/acpi.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <intelblocks/acpi.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <smp/spinlock.h>
|
||||
#include <device/device.h>
|
||||
#include <device/path.h>
|
||||
#include <bootstate.h>
|
||||
#include <commonlib/sort.h>
|
||||
#include <cpu/x86/lapic.h>
|
||||
#include <cpu/x86/mp.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <device/path.h>
|
||||
#include <intelblocks/acpi.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <types.h>
|
||||
|
||||
#define CPPC_NOM_FREQ_IDX 22
|
||||
#define CPPC_NOM_PERF_IDX 3
|
||||
|
@ -16,12 +19,62 @@ enum cpu_perf_eff_type {
|
|||
CPU_TYPE_PERF,
|
||||
};
|
||||
|
||||
DECLARE_SPIN_LOCK(cpu_lock);
|
||||
static u8 global_cpu_type[CONFIG_MAX_CPUS];
|
||||
struct cpu_apic_info_type {
|
||||
/*
|
||||
* Ordered APIC IDs based on core type.
|
||||
* Array begins with Performance Cores' APIC IDs,
|
||||
* then followed by Efficeint Cores's APIC IDs.
|
||||
*/
|
||||
int32_t apic_ids[CONFIG_MAX_CPUS];
|
||||
|
||||
static bool is_perf_core(void)
|
||||
/* Total CPU count */
|
||||
uint8_t total_cpu_cnt;
|
||||
|
||||
/*
|
||||
* Total Performance core count. This will be used
|
||||
* to identify the start of Efficient Cores's
|
||||
* APIC ID list
|
||||
*/
|
||||
uint8_t perf_cpu_cnt;
|
||||
};
|
||||
|
||||
static struct cpu_apic_info_type cpu_apic_info;
|
||||
|
||||
/*
|
||||
* The function orders APIC IDs such that orders first Performance cores and then
|
||||
* Efficient cores' APIC IDs in ascending order. Also calculates total number of
|
||||
* Performance cores and all cores count in the system and populates the information
|
||||
* in the cpu_apic_info sturct.
|
||||
*/
|
||||
static void acpi_set_hybrid_cpu_apicid_order(void *unused)
|
||||
{
|
||||
return get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE;
|
||||
size_t perf_core_cnt = 0, eff_core_cnt = 0;
|
||||
int32_t eff_apic_ids[CONFIG_MAX_CPUS] = {0};
|
||||
extern struct cpu_info cpu_infos[];
|
||||
uint32_t i, j = 0;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(cpu_apic_info.apic_ids); i++) {
|
||||
if (cpu_infos[i].cpu->path.apic.core_type == CPU_TYPE_PERF)
|
||||
cpu_apic_info.apic_ids[perf_core_cnt++] =
|
||||
cpu_infos[i].cpu->path.apic.apic_id;
|
||||
else
|
||||
eff_apic_ids[eff_core_cnt++] =
|
||||
cpu_infos[i].cpu->path.apic.apic_id;
|
||||
}
|
||||
|
||||
if (perf_core_cnt > 1)
|
||||
bubblesort(cpu_apic_info.apic_ids, perf_core_cnt, NUM_ASCENDING);
|
||||
|
||||
for (i = perf_core_cnt; j < eff_core_cnt; i++, j++)
|
||||
cpu_apic_info.apic_ids[i] = eff_apic_ids[j];
|
||||
|
||||
if (eff_core_cnt > 1)
|
||||
bubblesort(&cpu_apic_info.apic_ids[perf_core_cnt], eff_core_cnt, NUM_ASCENDING);
|
||||
|
||||
/* Populate total core count */
|
||||
cpu_apic_info.total_cpu_cnt = perf_core_cnt + eff_core_cnt;
|
||||
|
||||
cpu_apic_info.perf_cpu_cnt = perf_core_cnt;
|
||||
}
|
||||
|
||||
static enum cpu_perf_eff_type get_core_type(void)
|
||||
|
@ -36,52 +89,6 @@ void set_dev_core_type(void)
|
|||
info->cpu->path.apic.core_type = get_core_type();
|
||||
}
|
||||
|
||||
static struct device *get_cpu_bus_first_child(void)
|
||||
{
|
||||
struct device *dev = dev_find_path(NULL, DEVICE_PATH_CPU_CLUSTER);
|
||||
assert(dev != NULL);
|
||||
return (dev->link_list)->children;
|
||||
}
|
||||
|
||||
static u32 get_cpu_index(void)
|
||||
{
|
||||
u32 cpu_index = 0;
|
||||
struct device *dev;
|
||||
u32 my_apic_id = lapicid();
|
||||
|
||||
for (dev = get_cpu_bus_first_child(); dev; dev = dev->sibling)
|
||||
if (my_apic_id > dev->path.apic.apic_id)
|
||||
cpu_index++;
|
||||
|
||||
return cpu_index;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function determines the type (performance or efficient) of the CPU that
|
||||
* is executing it and stores the information (in a thread-safe manner) in an
|
||||
* global_cpu_type array.
|
||||
* It requires the SoC to implement a function `get_soc_cpu_type()` which will be
|
||||
* called in a critical section to determine the type of the executing CPU.
|
||||
*/
|
||||
static void set_cpu_type(void *unused)
|
||||
{
|
||||
spin_lock(&cpu_lock);
|
||||
u8 cpu_index = get_cpu_index();
|
||||
|
||||
if (is_perf_core())
|
||||
global_cpu_type[cpu_index] = CPU_TYPE_PERF;
|
||||
|
||||
spin_unlock(&cpu_lock);
|
||||
}
|
||||
|
||||
static void run_set_cpu_type(void *unused)
|
||||
{
|
||||
if (mp_run_on_all_cpus(set_cpu_type, NULL) != CB_SUCCESS) {
|
||||
printk(BIOS_ERR, "cpu_hybrid: Failed to set global_cpu_type with CPU type info\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_get_cpu_nomi_perf(u16 *eff_core_nom_perf, u16 *perf_core_nom_perf)
|
||||
{
|
||||
u8 max_non_turbo_ratio = cpu_get_max_non_turbo_ratio();
|
||||
|
@ -114,7 +121,7 @@ static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core
|
|||
|
||||
acpi_get_cpu_nomi_perf(&eff_core_nom_perf, &perf_core_nom_perf);
|
||||
|
||||
if (global_cpu_type[core_id] == CPU_TYPE_PERF)
|
||||
if (core_id < cpu_apic_info.perf_cpu_cnt)
|
||||
acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, perf_core_nom_perf);
|
||||
else
|
||||
acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX,
|
||||
|
@ -144,4 +151,4 @@ void acpigen_write_CPPC_hybrid_method(s32 core_id)
|
|||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, run_set_cpu_type, NULL);
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, acpi_set_hybrid_cpu_apicid_order, NULL);
|
||||
|
|
Loading…
Reference in New Issue