soc/intel/common: Fix invalid MADT entries creation

commit f8ac3dda02 ("soc/intel/common:
Order the CPUs based on their APIC IDs") sort algorithnm walks all the
`cpu_info' entries without discarding empty ones.  Since `cpu_info' is
not initialized, the data that is used is undefined and it generally
results in the creation of invalid `Local x2APIC' entries in the
MADT ("APIC") ACPI table.

Depending on the X2APIC ID value the Linux kernel behavior
changes (cf. arch/x86/kernel/acpi/boot.c::acpi_register_lapic()):
1. If (int)ID >= MAX_LOCAL_APIC (32768), the Linux kernel discards the
   entry with the "skipped apicid that is too big" INFO level
   message.
2. If (int)ID < MAX_LOCAL_APIC (32768) (including negative) this data
   is taken into account and it can lead to undesirable behavior such
   as core being disabled as (cf. "native_cpu_up: bad cpu" ERROR
   kernel message).

TEST=Verified the MADT does not contain any invalid entries on rex.

Change-Id: I19c7aa51f232bf48201bd6d28f108e9120a21f7e
Signed-off-by: Jeremy Compostella <jeremy.compostella@intel.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/77615
Reviewed-by: Bora Guvendik <bora.guvendik@intel.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Wonkyu Kim <wonkyu.kim@intel.com>
This commit is contained in:
Jeremy Compostella 2023-09-01 16:17:51 -07:00 committed by Subrata Banik
parent 2a6a79c706
commit ba7a9eefcf
2 changed files with 3 additions and 1 deletions

View File

@ -302,7 +302,7 @@ void arch_bootstate_coreboot_exit(void)
/* cpu_info() looks at address 0 at the base of %gs for a pointer to struct cpu_info */
static struct per_cpu_segment_data segment_data[CONFIG_MAX_CPUS];
struct cpu_info cpu_infos[CONFIG_MAX_CPUS];
struct cpu_info cpu_infos[CONFIG_MAX_CPUS] = {0};
enum cb_err set_cpu_info(unsigned int index, struct device *cpu)
{

View File

@ -54,6 +54,8 @@ static void acpi_set_hybrid_cpu_apicid_order(void *unused)
uint32_t i, j = 0;
for (i = 0; i < ARRAY_SIZE(cpu_apic_info.apic_ids); i++) {
if (!cpu_infos[i].cpu)
continue;
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;