Patrick Rudolph has uploaded this change for review.

View Change

cpu/x86/mpinit/sipi_vector: Move code to C

Use a C helper function to do early x86 CPU init.
The code is compiled without SSE and without optimizations.

Use existing code to update microcode.

Tested on Supermicro X11SSH:
* The microcode is still updated on all core
* All cores call into MPinit code

Change-Id: Ib6c2ffa2ce8c42eee9f3fe8ec8cff933942207ca
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
---
M src/cpu/x86/Makefile.inc
M src/cpu/x86/mp_init.c
M src/cpu/x86/sipi_vector.S
A src/cpu/x86/sipi_vector_c_handler.c
M src/include/cpu/x86/mp.h
5 files changed, 150 insertions(+), 124 deletions(-)

git pull ssh://review.coreboot.org:29418/coreboot refs/changes/21/46821/1
diff --git a/src/cpu/x86/Makefile.inc b/src/cpu/x86/Makefile.inc
index 66b1a68..54e2397 100644
--- a/src/cpu/x86/Makefile.inc
+++ b/src/cpu/x86/Makefile.inc
@@ -26,8 +26,11 @@

$(eval $(call create_class_compiler,sipi_vec,$(ARCH-$(TARGET_STAGE)-y)))
sipi_vec-generic-ccopts = $(rmodule_$(ARCH-$(TARGET_STAGE)-y)-generic-ccopts)
+sipi_vec-generic-ccopts += -mno-sse -O0

sipi_vec-$(CONFIG_PARALLEL_MP) += sipi_vector.S
+sipi_vec-$(CONFIG_PARALLEL_MP) += sipi_vector_c_handler.c
+sipi_vec-$(CONFIG_PARALLEL_MP) += $(top)/src/cpu/intel/microcode/microcode.c

$(SIPI_DOTO): $$(sipi_vec-objs) $(COMPILER_RT_sipi_vec)
$(LD_sipi_vec) -nostdlib -r -o $@ $(COMPILER_RT_FLAGS_sipi_vec) --whole-archive --start-group $(sipi_vec-objs) --no-whole-archive $(COMPILER_RT_sipi_vec) --end-group
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c
index 4870529..83d71190 100644
--- a/src/cpu/x86/mp_init.c
+++ b/src/cpu/x86/mp_init.c
@@ -83,29 +83,6 @@
int num_records;
};

-/* This needs to match the layout in the .module_parametrs section. */
-struct sipi_params {
- uint16_t gdtlimit;
- uint32_t gdt;
- uint16_t unused;
- uint32_t idt_ptr;
- uint32_t stack_top;
- uint32_t stack_size;
- uint32_t microcode_lock; /* 0xffffffff means parallel loading. */
- uint32_t microcode_ptr;
- uint32_t msr_table_ptr;
- uint32_t msr_count;
- uint32_t c_handler;
- atomic_t ap_count;
-} __packed;
-
-/* This also needs to match the assembly code for saved MSR encoding. */
-struct saved_msr {
- uint32_t index;
- uint32_t lo;
- uint32_t hi;
-} __packed;
-
/* The sipi vector rmodule is included in the ramstage using 'objdump -B'. */
extern char _binary_sipi_vector_start[];

diff --git a/src/cpu/x86/sipi_vector.S b/src/cpu/x86/sipi_vector.S
index ba1ecb7..52ca6ba 100644
--- a/src/cpu/x86/sipi_vector.S
+++ b/src/cpu/x86/sipi_vector.S
@@ -1,10 +1,14 @@
/* SPDX-License-Identifier: GPL-2.0-only */

#include <cpu/x86/cr.h>
-#include <cpu/amd/mtrr.h>
#include <cpu/x86/msr.h>
#include <arch/ram_segs.h>

+#define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
+#define CR0_CLEAR_FLAGS \
+ (CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_TS | CR0_EM | CR0_MP)
+#define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE)
+
/* The SIPI vector is responsible for initializing the APs in the system. It
* loads microcode, sets up MSRs, and enables caching before calling into
* C code. */
@@ -34,11 +38,6 @@
ap_count:
.long 0

-#define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
-#define CR0_SET_FLAGS (CR0_CLEAR_FLAGS_CACHE_ENABLE | CR0_PE)
-#define CR0_CLEAR_FLAGS \
- (CR0_PG | CR0_AM | CR0_WP | CR0_NE | CR0_TS | CR0_EM | CR0_MP)
-
.text
.code16
.global _start
@@ -101,102 +100,13 @@
/* Save CPU number. */
mov %ecx, %esi

- /* Determine if one should check microcode versions. */
- mov microcode_ptr, %edi
- test %edi, %edi
- jz microcode_done /* Bypass if no microde exists. */
+ /* sipi_secondary_early_entry(ap_start_params), preserve proper stack alignment */
+ sub $8, %esp
+ push %esi
+ leal ap_start_params, %eax
+ push %eax
+ call sipi_secondary_early_entry

- /* Get the Microcode version. */
- mov $1, %eax
- cpuid
- mov $IA32_BIOS_SIGN_ID, %ecx
- rdmsr
- /* If something already loaded skip loading again. */
- test %edx, %edx
- jnz microcode_done
-
- /* Determine if parallel microcode loading is allowed. */
- cmpl $0xffffffff, microcode_lock
- je load_microcode
-
- /* Protect microcode loading. */
-lock_microcode:
- lock bts $0, microcode_lock
- jc lock_microcode
-
-load_microcode:
- /* Load new microcode. */
- mov $IA32_BIOS_UPDT_TRIG, %ecx
- xor %edx, %edx
- mov %edi, %eax
- /* The microcode pointer is passed in pointing to the header. Adjust
- * pointer to reflect the payload (header size is 48 bytes). */
- add $48, %eax
- pusha
- wrmsr
- popa
-
- /* Unconditionally unlock microcode loading. */
- cmpl $0xffffffff, microcode_lock
- je microcode_done
-
- xor %eax, %eax
- mov %eax, microcode_lock
-
-microcode_done:
- /*
- * Load MSRs. Each entry in the table consists of:
- * 0: index,
- * 4: value[31:0]
- * 8: value[63:32]
- */
- mov msr_table_ptr, %edi
- mov msr_count, %ebx
- test %ebx, %ebx
- jz 1f
-
-#if CONFIG(X86_AMD_FIXED_MTRRS)
- /* Allow modification of RdDram and WrDram bits */
- mov $SYSCFG_MSR, %ecx
- rdmsr
- or $SYSCFG_MSR_MtrrFixDramModEn, %eax
- wrmsr
-#endif
-
-load_msr:
- mov (%edi), %ecx
- mov 4(%edi), %eax
- mov 8(%edi), %edx
- wrmsr
- add $12, %edi
- dec %ebx
- jnz load_msr
-
-#if CONFIG(X86_AMD_FIXED_MTRRS)
- mov $SYSCFG_MSR, %ecx
- rdmsr
- and $~SYSCFG_MSR_MtrrFixDramModEn, %eax
- wrmsr
-#endif
-
-1:
- /* Enable caching. */
- mov %cr0, %eax
- and $~(CR0_CLEAR_FLAGS_CACHE_ENABLE), %eax
- mov %eax, %cr0
-
-#if CONFIG(SSE)
- /* Enable sse instructions. */
- mov %cr4, %eax
- orl $(CR4_OSFXSR | CR4_OSXMMEXCPT), %eax
- mov %eax, %cr4
-#endif
-
- /* c_handler(cpu_num), preserve proper stack alignment */
- sub $12, %esp
- push %esi /* cpu_num */
- mov c_handler, %eax
- call *%eax
halt_jump:
hlt
jmp halt_jump
diff --git a/src/cpu/x86/sipi_vector_c_handler.c b/src/cpu/x86/sipi_vector_c_handler.c
new file mode 100644
index 0000000..dab6c65
--- /dev/null
+++ b/src/cpu/x86/sipi_vector_c_handler.c
@@ -0,0 +1,113 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#include <cpu/x86/mp.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/cr.h>
+#include <arch/cpu.h>
+#include <cpu/intel/microcode.h>
+#include <cpu/amd/mtrr.h>
+
+asmlinkage void sipi_secondary_early_entry(struct sipi_params *params, int cpu_num);
+
+#define CR0_CLEAR_FLAGS_CACHE_ENABLE (CR0_CD | CR0_NW)
+
+static void sipi_update_microcode(struct sipi_params *params)
+{
+ /* Determine if one should check microcode versions. */
+ if (!params->microcode_ptr)
+ return;
+
+ /* Get the Microcode version. */
+ const uint32_t rev = get_current_microcode_rev();
+
+ /* If something already loaded skip loading again. */
+ if (rev)
+ return;
+
+ /* Determine if parallel microcode loading is allowed. */
+ if (params->microcode_lock != 0xffffffff) {
+
+ /* Protect microcode loading. */
+ asm volatile(
+ "\tlock_microcode:\n"
+ "\tlock bts $0, %0\n"
+ "\tjc lock_microcode\n"
+ : "=m"(params->microcode_lock)
+ : "m"(params->microcode_lock));
+ }
+
+ /* Load new microcode. */
+ intel_microcode_load_unlocked((void *)((uintptr_t)params->microcode_ptr));
+
+ /* Unconditionally unlock microcode loading. */
+ if (params->microcode_lock != 0xffffffff)
+ params->microcode_lock = 0;
+}
+
+static void sipi_set_mtrrs(struct sipi_params *params)
+{
+ struct saved_msr *smsr;
+ if (!params->msr_count)
+ return;
+
+ if (CONFIG(X86_AMD_FIXED_MTRRS)) {
+ msr_t msr;
+ /* Enable access to AMD RdDram and WrDram extension bits */
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+ wrmsr(SYSCFG_MSR, msr);
+ }
+
+ /* Load MSRs */
+ smsr = (struct saved_msr *)params->msr_table_ptr;
+ for (size_t i = 0; i < params->msr_count; i++) {
+ msr_t msr = {.lo = smsr->lo, .hi = smsr->hi};
+ wrmsr(smsr->index, msr);
+ }
+
+ if (CONFIG(X86_AMD_FIXED_MTRRS)) {
+ msr_t msr;
+ /* Enable access to AMD RdDram and WrDram extension bits */
+ msr = rdmsr(SYSCFG_MSR);
+ msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+ wrmsr(SYSCFG_MSR, msr);
+ }
+}
+
+static void sipi_enable_caches(struct sipi_params *params)
+{
+ /* Enable caches */
+ CRx_TYPE cr0 = read_cr0();
+ cr0 &= ~(CR0_CLEAR_FLAGS_CACHE_ENABLE);
+ write_cr0(cr0);
+}
+
+static void sipi_enable_sse(struct sipi_params *params)
+{
+ /* Enable sse instructions. */
+ if (CONFIG(SSE)) {
+ CRx_TYPE cr4 = read_cr4();
+ cr4 &= (CR4_OSFXSR | CR4_OSXMMEXCPT);
+ write_cr4(cr4);
+ }
+}
+
+/*
+ * Early CPU bringup hook.
+ * - No Microcode has been loaded
+ * - Caches are disabled
+ * - SSE is disabled
+ * - MTRR haven't been set up
+ *
+ * You have been warned, expect the unexpected!
+ */
+asmlinkage void sipi_secondary_early_entry(struct sipi_params *params, int cpu_num)
+{
+ sipi_update_microcode(params);
+ sipi_set_mtrrs(params);
+ sipi_enable_caches(params);
+ sipi_enable_sse(params);
+
+ void (*doit)(int) = (void (*)(int))params->c_handler;
+ doit(cpu_num);
+}
\ No newline at end of file
diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h
index b2704eb..75cbe26 100644
--- a/src/include/cpu/x86/mp.h
+++ b/src/include/cpu/x86/mp.h
@@ -143,4 +143,27 @@
/* Send SMI to self with single execution. */
void smm_initiate_relocation(void);

+/* This needs to match the layout in the .module_parametrs section. */
+struct sipi_params {
+ uint16_t gdtlimit;
+ uint32_t gdt;
+ uint16_t unused;
+ uint32_t idt_ptr;
+ uint32_t stack_top;
+ uint32_t stack_size;
+ uint32_t microcode_lock; /* 0xffffffff means parallel loading. */
+ uint32_t microcode_ptr;
+ uint32_t msr_table_ptr;
+ uint32_t msr_count;
+ uint32_t c_handler;
+ atomic_t ap_count;
+} __packed;
+
+/* This also needs to match the assembly code for saved MSR encoding. */
+struct saved_msr {
+ uint32_t index;
+ uint32_t lo;
+ uint32_t hi;
+} __packed;
+
#endif /* _X86_MP_H_ */

To view, visit change 46821. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: coreboot
Gerrit-Branch: master
Gerrit-Change-Id: Ib6c2ffa2ce8c42eee9f3fe8ec8cff933942207ca
Gerrit-Change-Number: 46821
Gerrit-PatchSet: 1
Gerrit-Owner: Patrick Rudolph <patrick.rudolph@9elements.com>
Gerrit-Reviewer: Martin Roth <martinroth@google.com>
Gerrit-Reviewer: Patrick Georgi <pgeorgi@google.com>
Gerrit-MessageType: newchange