diff options
author | Aaron Durbin <adurbin@chromium.org> | 2013-01-03 17:38:47 -0600 |
---|---|---|
committer | Ronald G. Minnich <rminnich@gmail.com> | 2013-03-14 05:01:50 +0100 |
commit | 50a34648cdc7fc55e1fa75d51ece608c0e27245a (patch) | |
tree | 4c0853f9500e4b01007b6c24caebbea1007ff9a0 /src/include | |
parent | 5ca4f4119bf00a1ec64358f3e6b41d696b1dc123 (diff) |
x86: SMM Module Support
Add support for SMM modules by leveraging the RMODULE lib. This allows
for easier dynamic SMM handler placement. The SMM module support
consists of a common stub which puts the executing CPU into protected
mode and calls into a pre-defined handler. This stub can then be used
for SMM relocation as well as the real SMM handler. For the relocation
one can call back into coreboot ramstage code to perform relocation in
C code.
The handler is essentially a copy of smihandler.c, but it drops the TSEG
differences. It also doesn't rely on the SMM revision as the cpu code
should know what processor it is supported.
Ideally the CONFIG_SMM_TSEG option could be removed once the existing
users of that option transitioned away from tseg_relocate() and
smi_get_tseg_base().
The generic SMI callbacks are now not marked as weak in the
declaration so that there aren't unlinked references. The handler
has default implementations of the generic SMI callbacks which are
marked as weak. If an external compilation module has a strong symbol
the linker will use that instead of the link one.
Additionally, the parameters to the generic callbacks are dropped as
they don't seem to be used directly. The SMM runtime can provide the
necessary support if needed.
Change-Id: I1e2fed71a40b2eb03197697d29e9c4b246e3b25e
Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Reviewed-on: http://review.coreboot.org/2693
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
Diffstat (limited to 'src/include')
-rw-r--r-- | src/include/cpu/x86/smm.h | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index 00a8c7a218..302873f893 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -379,6 +379,14 @@ int __attribute__((weak)) mainboard_io_trap_handler(int smif); void southbridge_smi_set_eos(void); +#if CONFIG_SMM_MODULES +void cpu_smi_handler(void); +void northbridge_smi_handler(void); +void southbridge_smi_handler(void); +void mainboard_smi_gpi(u16 gpi_sts); +int mainboard_smi_apmc(u8 data); +void mainboard_smi_sleep(u8 slp_typ); +#else void __attribute__((weak)) cpu_smi_handler(unsigned int node, smm_state_save_area_t *state_save); void __attribute__((weak)) northbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save); void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save); @@ -386,10 +394,14 @@ void __attribute__((weak)) southbridge_smi_handler(unsigned int node, smm_state_ void __attribute__((weak)) mainboard_smi_gpi(u16 gpi_sts); int __attribute__((weak)) mainboard_smi_apmc(u8 data); void __attribute__((weak)) mainboard_smi_sleep(u8 slp_typ); +#endif /* CONFIG_SMM_MODULES */ #if !CONFIG_SMM_TSEG void smi_release_lock(void); #define tseg_relocate(ptr) +#elif CONFIG_SMM_MODULES +#define tseg_relocate(ptr) +#define smi_get_tseg_base() 0 #else /* Return address of TSEG base */ u32 smi_get_tseg_base(void); @@ -400,4 +412,72 @@ void tseg_relocate(void **ptr); /* Get PMBASE address */ u16 smm_get_pmbase(void); +#if CONFIG_SMM_MODULES + +struct smm_runtime { + u32 smbase; + u32 save_state_size; + /* The apic_id_to_cpu provides a mapping from APIC id to cpu number. + * The cpu number is indicated by the index into the array by matching + * the deafult APIC id and value at the index. The stub loader + * initializes this array with a 1:1 mapping. If the APIC ids are not + * contiguous like the 1:1 mapping it is up to the caller of the stub + * loader to adjust this mapping. */ + u8 apic_id_to_cpu[CONFIG_MAX_CPUS]; +} __attribute__ ((packed)); + +typedef void (*smm_handler_t)(void *arg, int cpu, + const struct smm_runtime *runtime); + +#ifdef __SMM__ +/* SMM Runtime helpers. */ + +/* Entry point for SMM modules. */ +void smm_handler_start(void *arg, int cpu, const struct smm_runtime *runtime); + +/* Retrieve SMM save state for a given CPU. WARNING: This does not take into + * account CPUs which are configured to not save their state to RAM. */ +void *smm_get_save_state(int cpu); + +#else +/* SMM Module Loading API */ + +/* Ths smm_loader_params structure provides direction to the SMM loader: + * - stack_top - optional external stack provided to loader. It must be at + * least per_cpu_stack_size * num_concurrent_stacks in size. + * - per_cpu_stack_size - stack size per cpu for smm modules. + * - num_concurrent_stacks - number of concurrent cpus in handler needing stack + * optional for setting up relocation handler. + * - per_cpu_save_state_size - the smm save state size per cpu + * - num_concurrent_save_states - number of concurrent cpus needing save state + * space + * - handler - optional handler to call. Only used during SMM relocation setup. + * - handler_arg - optional argument to handler for SMM relocation setup. For + * loading the SMM module, the handler_arg is filled in with + * the address of the module's parameters (if present). + * - runtime - this field is a result only. The SMM runtime location is filled + * into this field so the code doing the loading can manipulate the + * runtime's assumptions. e.g. updating the apic id to cpu map to + * handle sparse apic id space. + */ +struct smm_loader_params { + void *stack_top; + int per_cpu_stack_size; + int num_concurrent_stacks; + + int per_cpu_save_state_size; + int num_concurrent_save_states; + + smm_handler_t handler; + void *handler_arg; + + struct smm_runtime *runtime; +}; + +/* Both of these return 0 on success, < 0 on failure. */ +int smm_setup_relocation_handler(struct smm_loader_params *params); +int smm_load_module(void *smram, int size, struct smm_loader_params *params); +#endif /* __SMM__ */ +#endif /* CONFIG_SMM_MODULES */ + #endif |