Patrick Rudolph has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/44904 )
Change subject: [WIP] cpu/x86/mpinit: Serialize microcode updates for HT threads ......................................................................
[WIP] cpu/x86/mpinit: Serialize microcode updates for HT threads
Update microcode using a core specific semaphore. The SDM and most of the BWGs suggest doing this.
Change-Id: I89a01f6ff94e7d35f1feded3ddb0c43caf7c6c5d Signed-off-by: Patrick Rudolph patrick.rudolph@9elements.com --- M src/cpu/x86/mp_init.c M src/cpu/x86/sipi_vector.S 2 files changed, 74 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/04/44904/1
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index 5807831..4c4de09 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -25,6 +25,7 @@ #include <symbols.h> #include <timer.h> #include <thread.h> +#include <lib.h>
#include <security/intel/stm/SmmStm.h>
@@ -97,6 +98,9 @@ uint32_t msr_count; uint32_t c_handler; atomic_t ap_count; + uint32_t microcode_lock_ht; /* 1 special microcode locking for Intel HT CPUs */ + uint32_t apic_core_id_mask; + uint32_t hyperthreading_lock[CONFIG_MAX_CPUS/2]; } __packed;
/* This also needs to match the assembly code for saved MSR encoding. */ @@ -216,6 +220,31 @@ sp->stack_top = ALIGN_DOWN((uintptr_t)&_estack, CONFIG_STACK_SIZE); /* Adjust the stack top to take into account cpu_info. */ sp->stack_top -= sizeof(struct cpu_info); + sp->microcode_lock_ht = !!(cpuid_edx(1) & CPUID_FEAURE_HTT); + if (sp->microcode_lock_ht) { + struct cpuid_result result; + unsigned int core_ids, apic_ids, threads; + + apic_ids = 1; + if (cpuid_eax(0) >= 1) + apic_ids = (cpuid_ebx(1) >> 16) & 0xff; + if (apic_ids == 0) + apic_ids = 1; + + core_ids = 1; + if (cpuid_eax(0) >= 4) { + result = cpuid_ext(4, 0); + core_ids += (result.eax >> 26) & 0x3f; + } + + threads = (apic_ids / core_ids); + + sp->apic_core_id_mask = 1UL << log2_ceil(core_ids); + sp->apic_core_id_mask <<= log2_ceil(threads); + } else { + sp->apic_core_id_mask = 0; + } + memset(sp->hyperthreading_lock, 0, sizeof(sp->hyperthreading_lock)); }
#define NUM_FIXED_MTRRS 11 diff --git a/src/cpu/x86/sipi_vector.S b/src/cpu/x86/sipi_vector.S index ba1ecb7..abf0549 100644 --- a/src/cpu/x86/sipi_vector.S +++ b/src/cpu/x86/sipi_vector.S @@ -3,6 +3,7 @@ #include <cpu/x86/cr.h> #include <cpu/amd/mtrr.h> #include <cpu/x86/msr.h> +#include <cpu/x86/lapic_def.h> #include <arch/ram_segs.h>
/* The SIPI vector is responsible for initializing the APs in the system. It @@ -33,6 +34,12 @@ .long 0 ap_count: .long 0 +apic_core_id_mask: +.long 0 +hyperthreading_lock: +.space CONFIG_MAX_CPUS/2 +microcode_lock_ht: +.long 0
#define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW) #define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE) @@ -115,6 +122,35 @@ test %edx, %edx jnz microcode_done
+ /* Determine if Hyper-Threading semaphore should be used */ + cmpl $0, microcode_lock_ht + je load_microcode + + /* Get this CPU's LAPIC ID */ + movl $(LOCAL_APIC_ADDR | LAPIC_ID), %esi + movl (%esi), %ecx + shr $24, %ecx + + movl apic_core_id_mask, %eax + andl %eax, %ecx +1: + bt $0, %eax + jc 1f + shr $1, %eax + shr $1, %ecx + jmp 1b +1: + /* ecx now contains the core ID */ + movl $(hyperthreading_lock), %ebx + shl $2, %ecx + addl %ecx, %ebx + +lock_ht_semaphore: + /* Lock the core specific semaphore */ + lock bts $0, (%ebx) + jc lock_ht_semaphore + jmp load_microcode + /* Determine if parallel microcode loading is allowed. */ cmpl $0xffffffff, microcode_lock je load_microcode @@ -136,6 +172,15 @@ wrmsr popa
+ /* Determine if Hyper-Threading semaphore should be used */ + cmpl $0, microcode_lock_ht + jne 1f + + xor %eax, %eax + mov %eax, (%ebx) + je microcode_done + +1: /* Unconditionally unlock microcode loading. */ cmpl $0xffffffff, microcode_lock je microcode_done