summaryrefslogtreecommitdiffstats
path: root/arch/x86/include
diff options
context:
space:
mode:
authorSimon Glass <sjg@chromium.org>2015-04-29 22:25:59 -0600
committerSimon Glass <sjg@chromium.org>2015-04-30 16:13:38 -0600
commit45b5a37836d552db30ab571d8ba67f12d7ba23b1 (patch)
treecbfda1472f00b123b6dd7872deedac0fc381612c /arch/x86/include
parent6f41e0e7bcdc58e9e8af89988043893d5876bf7a (diff)
downloadblackbird-obmc-uboot-45b5a37836d552db30ab571d8ba67f12d7ba23b1.tar.gz
blackbird-obmc-uboot-45b5a37836d552db30ab571d8ba67f12d7ba23b1.zip
x86: Add multi-processor init
Most modern x86 CPUs include more than one CPU core. The OS normally requires that these 'Application Processors' (APs) be brought up by the boot loader. Add the required support to U-Boot to init additional APs. Signed-off-by: Simon Glass <sjg@chromium.org> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'arch/x86/include')
-rw-r--r--arch/x86/include/asm/arch-ivybridge/microcode.h3
-rw-r--r--arch/x86/include/asm/mp.h94
-rw-r--r--arch/x86/include/asm/mtrr.h6
-rw-r--r--arch/x86/include/asm/processor.h3
-rw-r--r--arch/x86/include/asm/sipi.h86
5 files changed, 187 insertions, 5 deletions
diff --git a/arch/x86/include/asm/arch-ivybridge/microcode.h b/arch/x86/include/asm/arch-ivybridge/microcode.h
index b868283761..67f32cc38f 100644
--- a/arch/x86/include/asm/arch-ivybridge/microcode.h
+++ b/arch/x86/include/asm/arch-ivybridge/microcode.h
@@ -7,9 +7,6 @@
#ifndef __ASM_ARCH_MICROCODE_H
#define __ASM_ARCH_MICROCODE_H
-/* Length of the public header on Intel microcode blobs */
-#define UCODE_HEADER_LEN 0x30
-
#ifndef __ASSEMBLY__
/**
diff --git a/arch/x86/include/asm/mp.h b/arch/x86/include/asm/mp.h
new file mode 100644
index 0000000000..c0930fd0c6
--- /dev/null
+++ b/arch/x86/include/asm/mp.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2015 Google, Inc
+ *
+ * SPDX-License-Identifier: GPL-2.0
+ *
+ * Taken from coreboot file of the same name
+ */
+
+#ifndef _X86_MP_H_
+#define _X86_MP_H_
+
+#include <asm/atomic.h>
+
+typedef int (*mp_callback_t)(struct udevice *cpu, void *arg);
+
+/*
+ * A mp_flight_record details a sequence of calls for the APs to perform
+ * along with the BSP to coordinate sequencing. Each flight record either
+ * provides a barrier for each AP before calling the callback or the APs
+ * are allowed to perform the callback without waiting. Regardless, each
+ * record has the cpus_entered field incremented for each record. When
+ * the BSP observes that the cpus_entered matches the number of APs
+ * the bsp_call is called with bsp_arg and upon returning releases the
+ * barrier allowing the APs to make further progress.
+ *
+ * Note that ap_call() and bsp_call() can be NULL. In the NULL case the
+ * callback will just not be called.
+ */
+struct mp_flight_record {
+ atomic_t barrier;
+ atomic_t cpus_entered;
+ mp_callback_t ap_call;
+ void *ap_arg;
+ mp_callback_t bsp_call;
+ void *bsp_arg;
+} __attribute__((aligned(ARCH_DMA_MINALIGN)));
+
+#define MP_FLIGHT_RECORD(barrier_, ap_func_, ap_arg_, bsp_func_, bsp_arg_) \
+ { \
+ .barrier = ATOMIC_INIT(barrier_), \
+ .cpus_entered = ATOMIC_INIT(0), \
+ .ap_call = ap_func_, \
+ .ap_arg = ap_arg_, \
+ .bsp_call = bsp_func_, \
+ .bsp_arg = bsp_arg_, \
+ }
+
+#define MP_FR_BLOCK_APS(ap_func, ap_arg, bsp_func, bsp_arg) \
+ MP_FLIGHT_RECORD(0, ap_func, ap_arg, bsp_func, bsp_arg)
+
+#define MP_FR_NOBLOCK_APS(ap_func, ap_arg, bsp_func, bsp_arg) \
+ MP_FLIGHT_RECORD(1, ap_func, ap_arg, bsp_func, bsp_arg)
+
+/*
+ * The mp_params structure provides the arguments to the mp subsystem
+ * for bringing up APs.
+ *
+ * At present this is overkill for U-Boot, but it may make it easier to add
+ * SMM support.
+ */
+struct mp_params {
+ int num_cpus; /* Total cpus include BSP */
+ int parallel_microcode_load;
+ const void *microcode_pointer;
+ /* Flight plan for APs and BSP */
+ struct mp_flight_record *flight_plan;
+ int num_records;
+};
+
+/*
+ * mp_init() will set up the SIPI vector and bring up the APs according to
+ * mp_params. Each flight record will be executed according to the plan. Note
+ * that the MP infrastructure uses SMM default area without saving it. It's
+ * up to the chipset or mainboard to either e820 reserve this area or save this
+ * region prior to calling mp_init() and restoring it after mp_init returns.
+ *
+ * At the time mp_init() is called the MTRR MSRs are mirrored into APs then
+ * caching is enabled before running the flight plan.
+ *
+ * The MP init has the following properties:
+ * 1. APs are brought up in parallel.
+ * 2. The ordering of cpu number and APIC ids is not deterministic.
+ * Therefore, one cannot rely on this property or the order of devices in
+ * the device tree unless the chipset or mainboard know the APIC ids
+ * a priori.
+ *
+ * mp_init() returns < 0 on error, 0 on success.
+ */
+int mp_init(struct mp_params *params);
+
+/* Probes the CPU device */
+int mp_init_cpu(struct udevice *cpu, void *unused);
+
+#endif /* _X86_MP_H_ */
diff --git a/arch/x86/include/asm/mtrr.h b/arch/x86/include/asm/mtrr.h
index 3841593cd5..3ad617cb4a 100644
--- a/arch/x86/include/asm/mtrr.h
+++ b/arch/x86/include/asm/mtrr.h
@@ -34,8 +34,10 @@
/* Number of MTRRs supported */
#define MTRR_COUNT 8
-#define NUM_FIXED_RANGES 88
-#define RANGES_PER_FIXED_MTRR 8
+#define NUM_FIXED_MTRRS 11
+#define RANGES_PER_FIXED_MTRR 8
+#define NUM_FIXED_RANGES (NUM_FIXED_MTRRS * RANGES_PER_FIXED_MTRR)
+
#define MTRR_FIX_64K_00000_MSR 0x250
#define MTRR_FIX_16K_80000_MSR 0x258
#define MTRR_FIX_16K_A0000_MSR 0x259
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 3575d34a53..7c77b90485 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -23,6 +23,9 @@
#define X86_GDT_SIZE (X86_GDT_NUM_ENTRIES * X86_GDT_ENTRY_SIZE)
+/* Length of the public header on Intel microcode blobs */
+#define UCODE_HEADER_LEN 0x30
+
#ifndef __ASSEMBLY__
/*
diff --git a/arch/x86/include/asm/sipi.h b/arch/x86/include/asm/sipi.h
new file mode 100644
index 0000000000..25d7d311d2
--- /dev/null
+++ b/arch/x86/include/asm/sipi.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2015 Gooogle, Inc
+ * Written by Simon Glass <sjg@chromium.org>
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#ifndef _ASM_SIPI_H
+#define _ASM_SIPI_H
+
+#define AP_DEFAULT_BASE 0x30000
+#define AP_DEFAULT_SIZE 0x10000
+
+#ifndef __ASSEMBLER__
+
+/**
+ * struct sipi_params_16bit - 16-bit SIPI entry-point parameters
+ *
+ * These are set up in the same space as the SIPI 16-bit code so that each AP
+ * can access the parameters when it boots.
+ *
+ * Each of these must be set up for the AP to boot, except @segment which is
+ * set in the assembly code.
+ *
+ * @ap_start: 32-bit SIPI entry point for U-Boot
+ * @segment: Code segment for U-Boot
+ * @pad: Padding (not used)
+ * @gdt_limit: U-Boot GDT limit (X86_GDT_SIZE - 1)
+ * @gdt: U-Boot GDT (gd->arch.gdt)
+ * @unused: Not used
+ */
+struct __packed sipi_params_16bit {
+ u32 ap_start;
+ u16 segment;
+ u16 pad;
+ u16 gdt_limit;
+ u32 gdt;
+ u16 unused;
+};
+
+/**
+ * struct sipi_params - 32-bit SIP entry-point parameters
+ *
+ * These are used by the AP init code and must be set up before the APs start.
+ *
+ * The stack area extends down from @stack_top, with @stack_size allocated
+ * for each AP.
+ *
+ * @idt_ptr: Interrupt descriptor table pointer
+ * @stack_top: Top of the AP stack area
+ * @stack_size: Size of each AP's stack
+ * @microcode_lock: Used to ensure only one AP loads microcode at once
+ * 0xffffffff enables parallel loading.
+ * @microcode_ptr: Pointer to microcode, or 0 if none
+ * @msr_table_ptr: Pointer to saved MSRs, a list of struct saved_msr
+ * @msr_count: Number of saved MSRs
+ * @c_handler: C function to call once early init is complete
+ * @ap_count: Shared atomic value to allocate CPU indexes
+ */
+struct sipi_params {
+ u32 idt_ptr;
+ u32 stack_top;
+ u32 stack_size;
+ u32 microcode_lock;
+ u32 microcode_ptr;
+ u32 msr_table_ptr;
+ u32 msr_count;
+ u32 c_handler;
+ atomic_t ap_count;
+};
+
+/* 16-bit AP entry point */
+void ap_start16(void);
+
+/* end of 16-bit code/data, marks the region to be copied to SIP vector */
+void ap_start16_code_end(void);
+
+/* 32-bit AP entry point */
+void ap_start(void);
+
+extern char sipi_params_16bit[];
+extern char sipi_params[];
+
+#endif /* __ASSEMBLER__ */
+
+#endif
OpenPOWER on IntegriCloud