summaryrefslogtreecommitdiff
path: root/src/include/cpu/x86
diff options
context:
space:
mode:
authorAaron Durbin <adurbin@chromium.org>2016-04-29 22:55:49 -0500
committerMartin Roth <martinroth@google.com>2016-05-04 18:51:49 +0200
commit82501922b67e41e596447aee5b42bc4655a927f4 (patch)
tree7a9cb4886002240371ece9da85caea4a30f1ba6a /src/include/cpu/x86
parentd87c7bc07c03d80fc7c346a027cb000657f1e76b (diff)
cpu/x86: combine multiprocessor and SMM initialization
In order to reduce code duplication provide a common flow through callback functions that performs the multiprocessor and optionally SMM initialization. The existing MP flight records are utilized but a common flow is provided such that the chipset/cpu only needs to provide a mp_ops structure which has callbacks to gather info and provide hooks at certain points in the sequence. All current users of the MP code can be switched over to this flow since there haven't been any flight records that are overly complicated and long. After the conversion has taken place most of the surface area of the MP API can be hidden away within the compilation unit proper. Change-Id: I6f70969631012982126f0d0d76e5fac6880c24f0 Signed-off-by: Aaron Durbin <adurbin@chromium.org> Reviewed-on: https://review.coreboot.org/14557 Tested-by: build bot (Jenkins) Reviewed-by: Martin Roth <martinroth@google.com>
Diffstat (limited to 'src/include/cpu/x86')
-rw-r--r--src/include/cpu/x86/mp.h96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/include/cpu/x86/mp.h b/src/include/cpu/x86/mp.h
index 3227975254..ff88a20301 100644
--- a/src/include/cpu/x86/mp.h
+++ b/src/include/cpu/x86/mp.h
@@ -17,6 +17,7 @@
#define _X86_MP_H_
#include <arch/smp/atomic.h>
+#include <cpu/x86/smm.h>
#define CACHELINE_SIZE 64
@@ -78,6 +79,101 @@ struct mp_params {
int num_records;
};
+/* The sequence of the callbacks are in calling order. */
+struct mp_ops {
+ /*
+ * Optionally provide a callback prior to kicking off MP
+ * startup. This callback is done prior to loading the SIPI
+ * vector but after gathering the MP state information. Please
+ * see the sequence below.
+ */
+ void (*pre_mp_init)(void);
+ /*
+ * Return the number of logical x86 execution contexts that
+ * need to be brought out of SIPI state as well as have SMM
+ * handlers installed.
+ */
+ int (*get_cpu_count)(void);
+ /*
+ * Optionally fill in permanent SMM region and save state size. If
+ * this callback is not present no SMM handlers will be installed.
+ * The perm_smsize is the size available to house the permanent SMM
+ * handler.
+ */
+ void (*get_smm_info)(uintptr_t *perm_smbase, size_t *perm_smsize,
+ size_t *smm_save_state_size);
+ /*
+ * Optionally fill in pointer to microcode and indicate if the APs
+ * can load the microcode in parallel.
+ */
+ void (*get_microcode_info)(const void **microcode, int *parallel);
+ /*
+ * Optionally provide a function which adjusts the APIC id
+ * map to cpu number. By default the cpu number and APIC id
+ * are 1:1. To change the APIC id for a given cpu return the
+ * new APIC id. It's called for each cpu as indicated by
+ * get_cpu_count().
+ */
+ int (*adjust_cpu_apic_entry)(int cpu, int cur_apic_id);
+ /*
+ * Optionally adjust SMM handler parameters to override the default
+ * values. The is_perm variable indicates if the parameters to adjust
+ * are for the relocation handler or the permanent handler. This
+ * function is therefore called twice -- once for each handler.
+ * By default the parameters for each SMM handler are:
+ * stack_size num_concurrent_stacks num_concurrent_save_states
+ * relo: save_state_size get_cpu_count() 1
+ * perm: save_state_size get_cpu_count() get_cpu_count()
+ */
+ void (*adjust_smm_params)(struct smm_loader_params *slp, int is_perm);
+ /*
+ * Optionally provide a callback prior to the APs starting SMM
+ * relocation or cpu driver initialization. However, note that
+ * this callback is called after SMM handlers have been loaded.
+ */
+ void (*pre_mp_smm_init)(void);
+ /*
+ * Optional function to use to trigger SMM to perform relocation. If
+ * not provided, smm_initiate_relocation() is used.
+ */
+ void (*per_cpu_smm_trigger)(void);
+ /*
+ * This function is called while each cpu is in the SMM relocation
+ * handler. Its primary purpose is to adjust the SMBASE for the
+ * permanent handler. The parameters passed are the current cpu
+ * running the relocation handler, current SMBASE of relocation handler,
+ * and the pre-calculated staggered cpu SMBASE address of the permanent
+ * SMM handler.
+ */
+ void (*relocation_handler)(int cpu, uintptr_t curr_smbase,
+ uintptr_t staggered_smbase);
+ /*
+ * Optionally provide a callback that is called after the APs
+ * and the BSP have gone through the initialion sequence.
+ */
+ void (*post_mp_init)(void);
+};
+
+/*
+ * mp_init_with_smm() returns < 0 on failure and 0 on success. The mp_ops
+ * argument is used to drive the multiprocess initialization. Unless otherwise
+ * stated each callback is called on the BSP only. The sequence of operations
+ * is the following:
+ * 1. pre_mp_init()
+ * 2. get_cpu_count()
+ * 3. get_smm_info()
+ * 4. get_microcode_info()
+ * 5. adjust_cpu_apic_entry() for each number of get_cpu_count()
+ * 6. adjust_smm_params(is_perm=0)
+ * 7. adjust_smm_params(is_perm=1)
+ * 8. pre_mp_smm_init()
+ * 9. per_cpu_smm_trigger() in parallel for all cpus which calls
+ * relocation_handler() in SMM.
+ * 10. mp_initialize_cpu() for each cpu
+ * 11. post_mp_init()
+ */
+int mp_init_with_smm(struct bus *cpu_bus, const struct mp_ops *mp_ops);
+
/*
* 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