From 66da043e48c65e6d89b385d840e5f7c53e482db9 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Tue, 28 May 2013 14:26:29 -0500 Subject: [PATCH] haswell: allow for disabled hyperthreading There were assumptions being made in the haswell MP and SMM code which assumed the APIC id space was 1:1 w.r.t. cpu number. When hyperthreading is disabled the APIC ids of the logical processors are all even. That means the APIC id space is sparse. Handle this situation. Change-Id: Ibe79ab156c0a171208a77db8a252aa5b73205d6c Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/3353 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Ronald G. Minnich --- src/cpu/intel/haswell/haswell.h | 3 +++ src/cpu/intel/haswell/mp_init.c | 22 +++++++++++++++++--- src/cpu/intel/haswell/smmrelocate.c | 32 ++++++++++++++++++++++++++--- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index c550cfa1a6..4a739a9e30 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -175,6 +175,9 @@ int setup_ap_init(struct bus *cpu_bus, int *max_cpus, /* Returns 0 on success, < 0 on failure. */ int start_aps(struct bus *cpu_bus, int max_cpus); void release_aps_for_smm_relocation(int do_parallel_relocation); +/* Determine if HyperThreading is disabled. The variable is not valid until + * setup_ap_init() has been called. */ +extern int ht_disabled; #endif /* This structure is saved along with the relocated ramstage program in SMM diff --git a/src/cpu/intel/haswell/mp_init.c b/src/cpu/intel/haswell/mp_init.c index 357fbb291d..1358418557 100644 --- a/src/cpu/intel/haswell/mp_init.c +++ b/src/cpu/intel/haswell/mp_init.c @@ -80,6 +80,8 @@ static atomic_t num_aps; static atomic_t num_aps_relocated_smm; /* Barrier to stop APs from performing SMM relcoation. */ static int smm_relocation_barrier_begin __attribute__ ((aligned (64))); +/* Determine if hyperthreading is disabled. */ +int ht_disabled; static inline void mfence(void) { @@ -197,6 +199,8 @@ static void asmlinkage ap_init(unsigned int cpu, void *microcode_ptr) static void setup_default_sipi_vector_params(struct sipi_params *sp) { int i; + u8 apic_id; + u8 apic_id_inc; sp->gdt = (u32)&gdt; sp->gdtlimit = (u32)&gdt_end - (u32)&gdt - 1; @@ -205,9 +209,15 @@ static void setup_default_sipi_vector_params(struct sipi_params *sp) sp->stack_top = (u32)&_estack; /* Adjust the stack top to take into account cpu_info. */ sp->stack_top -= sizeof(struct cpu_info); - /* Default to linear APIC id space. */ - for (i = 0; i < CONFIG_MAX_CPUS; i++) - sp->apic_to_cpu_num[i] = i; + + /* Default to linear APIC id space if HT is enabled. If it is + * disabled the APIC ids increase by 2 as the odd numbered APIC + * ids are not present.*/ + apic_id_inc = (ht_disabled) ? 2 : 1; + for (i = 0, apic_id = 0; i < CONFIG_MAX_CPUS; i++) { + sp->apic_to_cpu_num[i] = apic_id; + apic_id += apic_id_inc; + } } #define NUM_FIXED_MTRRS 11 @@ -374,6 +384,10 @@ static int allocate_cpu_devices(struct bus *cpu_bus, int *total_hw_threads) max_cpus = CONFIG_MAX_CPUS; } + /* Determine if hyperthreading is enabled. If not, the APIC id space + * is sparse with ids incrementing by 2 instead of 1. */ + ht_disabled = num_threads == num_cores; + for (i = 1; i < max_cpus; i++) { struct device_path cpu_path; device_t new; @@ -381,6 +395,8 @@ static int allocate_cpu_devices(struct bus *cpu_bus, int *total_hw_threads) /* Build the cpu device path */ cpu_path.type = DEVICE_PATH_APIC; cpu_path.apic.apic_id = info->cpu->path.apic.apic_id + i; + if (ht_disabled) + cpu_path.apic.apic_id = cpu_path.apic.apic_id * 2; /* Allocate the new cpu device structure */ new = alloc_find_dev(cpu_bus, &cpu_path); diff --git a/src/cpu/intel/haswell/smmrelocate.c b/src/cpu/intel/haswell/smmrelocate.c index 6caeafa5e1..4fe6489be2 100644 --- a/src/cpu/intel/haswell/smmrelocate.c +++ b/src/cpu/intel/haswell/smmrelocate.c @@ -286,6 +286,22 @@ static void fill_in_relocation_params(device_t dev, params->uncore_emrr_mask.hi = (1 << (39 - 32)) - 1; } +static void adjust_apic_id_map(struct smm_loader_params *smm_params) +{ + struct smm_runtime *runtime; + int i; + + /* Adjust the APIC id map if HT is disabled. */ + if (!ht_disabled) + return; + + runtime = smm_params->runtime; + + /* The APIC ids increment by 2 when HT is disabled. */ + for (i = 0; i < CONFIG_MAX_CPUS; i++) + runtime->apic_id_to_cpu[i] = runtime->apic_id_to_cpu[i] * 2; +} + static int install_relocation_handler(int num_cpus, struct smm_relocation_params *relo_params) { @@ -305,7 +321,12 @@ static int install_relocation_handler(int num_cpus, .handler_arg = (void *)relo_params, }; - return smm_setup_relocation_handler(&smm_params); + if (smm_setup_relocation_handler(&smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; } static void setup_ied_area(struct smm_relocation_params *params) @@ -347,8 +368,13 @@ static int install_permanent_handler(int num_cpus, printk(BIOS_DEBUG, "Installing SMM handler to 0x%08x\n", relo_params->smram_base); - return smm_load_module((void *)relo_params->smram_base, - relo_params->smram_size, &smm_params); + if (smm_load_module((void *)relo_params->smram_base, + relo_params->smram_size, &smm_params)) + return -1; + + adjust_apic_id_map(&smm_params); + + return 0; } static int cpu_smm_setup(void)