cpu/x86/mpinit: Serialize microcode updates for HT threads

This change affects Intel CPUs only. As most platforms are doing
uCode update using FIT, they aren't affected by this code either.

Update microcode in MP-init using a single spinlock when running on
a Hyper-Threading enabled CPU on pre FIT platforms.
This will slow down the MP-init boot flow.

Intel SDM and various BWGs specify to use a semaphore to update
microcode on one thread per core on Hyper-Threading enabled CPUs.
Due to this complex code would be necessary to determine the core #ID,
initializing and picking the right semaphore out of CONFIG_MAX_CPUS / 2.
Instead use the existing global spinlock already present in MPinit code.
Assuming that only pre-FIT platforms with Hyper-Threading enabled and at
most 8 threads will ever run into this condition, the boot delay is
negligible.

This change is a counterproposal to the previous published patch series
being much more unsophisticated.

Change-Id: I27bf5177859c12e92d6ce7a2966c965d7262b472
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/49303
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Angel Pons <th3fanbus@gmail.com>
This commit is contained in:
Patrick Rudolph 2021-01-11 09:21:58 +01:00 committed by Patrick Georgi
parent bc15e01958
commit ce51b34186
6 changed files with 22 additions and 5 deletions

View File

@ -33,7 +33,7 @@ static int get_cpu_count(void)
static void get_microcode_info(const void **microcode, int *parallel) static void get_microcode_info(const void **microcode, int *parallel)
{ {
*microcode = microcode_patch; *microcode = microcode_patch;
*parallel = 1; *parallel = !intel_ht_supported();
} }
/* the SMRR enable and lock bit need to be set in IA32_FEATURE_CONTROL /* the SMRR enable and lock bit need to be set in IA32_FEATURE_CONTROL

View File

@ -251,7 +251,7 @@ static void get_microcode_info(const void **microcode, int *parallel)
{ {
microcode_patch = intel_microcode_find(); microcode_patch = intel_microcode_find();
*microcode = microcode_patch; *microcode = microcode_patch;
*parallel = 1; *parallel = !intel_ht_supported();
} }
static void per_cpu_smm_trigger(void) static void per_cpu_smm_trigger(void)

View File

@ -497,7 +497,7 @@ static void get_microcode_info(const void **microcode, int *parallel)
{ {
microcode_patch = intel_microcode_find(); microcode_patch = intel_microcode_find();
*microcode = microcode_patch; *microcode = microcode_patch;
*parallel = 1; *parallel = !intel_ht_supported();
} }
static void per_cpu_smm_trigger(void) static void per_cpu_smm_trigger(void)

View File

@ -102,6 +102,13 @@ _start:
/* Save CPU number. */ /* Save CPU number. */
mov %ecx, %esi mov %ecx, %esi
/*
* The following code only needs to run on Intel platforms and thus the caller
* doesn't provide a microcode_ptr if not on Intel.
* On Intel platforms which update microcode using FIT the version check will
* also skip the microcode update.
*/
/* Determine if one should check microcode versions. */ /* Determine if one should check microcode versions. */
mov microcode_ptr, %edi mov microcode_ptr, %edi
test %edi, %edi test %edi, %edi
@ -116,6 +123,16 @@ _start:
test %edx, %edx test %edx, %edx
jnz microcode_done jnz microcode_done
/*
* Intel SDM and various BWGs specify to use a semaphore to update microcode
* on one thread per core on Hyper-Threading enabled CPUs. Due to this complex
* code would be necessary to determine the core #ID, initializing and picking
* the right semaphore out of CONFIG_MAX_CPUS / 2.
* Instead of the per core approachm, as recommended, use one global spinlock.
* Assuming that only pre-FIT platforms with Hyper-Threading enabled and at
* most 8 threads will ever run into this condition, the boot delay is negligible.
*/
/* Determine if parallel microcode loading is allowed. */ /* Determine if parallel microcode loading is allowed. */
cmpl $0xffffffff, microcode_lock cmpl $0xffffffff, microcode_lock
je load_microcode je load_microcode

View File

@ -149,7 +149,7 @@ static void get_microcode_info(const void **microcode, int *parallel)
const struct pattrs *pattrs = pattrs_get(); const struct pattrs *pattrs = pattrs_get();
*microcode = pattrs->microcode_patch; *microcode = pattrs->microcode_patch;
*parallel = 1; *parallel = !intel_ht_supported();
} }
static void per_cpu_smm_trigger(void) static void per_cpu_smm_trigger(void)

View File

@ -152,7 +152,7 @@ static void get_microcode_info(const void **microcode, int *parallel)
const struct pattrs *pattrs = pattrs_get(); const struct pattrs *pattrs = pattrs_get();
*microcode = pattrs->microcode_patch; *microcode = pattrs->microcode_patch;
*parallel = 1; *parallel = !intel_ht_supported();
} }
static void per_cpu_smm_trigger(void) static void per_cpu_smm_trigger(void)