aboutsummaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
authorSridhar Siricilla <sridhar.siricilla@intel.com>2023-03-30 11:25:36 +0530
committerSridhar Siricilla <sridhar.siricilla@intel.com>2023-04-02 10:53:46 +0000
commitf8ac3dda02f22ebf857efb5b845db97f00598f7d (patch)
treee9f869c44c5e05c5b6e51ac276bb0929d9112893 /src/soc
parent450699d1c8e9b0305c1f0d9872f8f4a45983103e (diff)
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>
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/block/acpi/cpu_hybrid.c121
1 files changed, 64 insertions, 57 deletions
diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c
index 81c4add0b6..a6f9103380 100644
--- a/src/soc/intel/common/block/acpi/cpu_hybrid.c
+++ b/src/soc/intel/common/block/acpi/cpu_hybrid.c
@@ -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,70 +19,74 @@ 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];
+
+ /* 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 bool is_perf_core(void)
-{
- return get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE;
-}
+static struct cpu_apic_info_type cpu_apic_info;
-static enum cpu_perf_eff_type get_core_type(void)
+/*
+ * 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) ?
- CPU_TYPE_PERF : CPU_TYPE_EFF;
-}
+ 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;
+ }
-void set_dev_core_type(void)
-{
- struct cpu_info *info = cpu_info();
- info->cpu->path.apic.core_type = get_core_type();
-}
+ if (perf_core_cnt > 1)
+ bubblesort(cpu_apic_info.apic_ids, perf_core_cnt, NUM_ASCENDING);
-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;
-}
+ for (i = perf_core_cnt; j < eff_core_cnt; i++, j++)
+ cpu_apic_info.apic_ids[i] = eff_apic_ids[j];
-static u32 get_cpu_index(void)
-{
- u32 cpu_index = 0;
- struct device *dev;
- u32 my_apic_id = lapicid();
+ if (eff_core_cnt > 1)
+ bubblesort(&cpu_apic_info.apic_ids[perf_core_cnt], eff_core_cnt, NUM_ASCENDING);
- for (dev = get_cpu_bus_first_child(); dev; dev = dev->sibling)
- if (my_apic_id > dev->path.apic.apic_id)
- cpu_index++;
+ /* Populate total core count */
+ cpu_apic_info.total_cpu_cnt = perf_core_cnt + eff_core_cnt;
- return cpu_index;
+ cpu_apic_info.perf_cpu_cnt = perf_core_cnt;
}
-/*
- * 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)
+static enum cpu_perf_eff_type get_core_type(void)
{
- 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);
+ return (get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE) ?
+ CPU_TYPE_PERF : CPU_TYPE_EFF;
}
-static void run_set_cpu_type(void *unused)
+void set_dev_core_type(void)
{
- 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;
- }
+ struct cpu_info *info = cpu_info();
+ info->cpu->path.apic.core_type = get_core_type();
}
static void acpi_get_cpu_nomi_perf(u16 *eff_core_nom_perf, u16 *perf_core_nom_perf)
@@ -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);