coreboot-kgpe-d16/src/include/cpu/x86/smm.h

484 lines
9.5 KiB
C
Raw Normal View History

/*
* This file is part of the coreboot project.
*
* Copyright (C) 2008-2009 coresystems GmbH
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* AMD64 SMM State-Save Area
* starts @ 0x7e00
*/
#ifndef CPU_X86_SMM_H
#define CPU_X86_SMM_H
/* used only by C programs so far */
#define SMM_BASE 0xa0000
#define SMM_ENTRY_OFFSET 0x8000
#define SMM_SAVE_STATE_BEGIN(x) (SMM_ENTRY_OFFSET + (x))
#include <types.h>
typedef struct {
u16 es_selector;
u16 es_attributes;
u32 es_limit;
u64 es_base;
u16 cs_selector;
u16 cs_attributcs;
u32 cs_limit;
u64 cs_base;
u16 ss_selector;
u16 ss_attributss;
u32 ss_limit;
u64 ss_base;
u16 ds_selector;
u16 ds_attributds;
u32 ds_limit;
u64 ds_base;
u16 fs_selector;
u16 fs_attributfs;
u32 fs_limit;
u64 fs_base;
u16 gs_selector;
u16 gs_attributgs;
u32 gs_limit;
u64 gs_base;
u8 reserved0[4];
u16 gdtr_limit;
u8 reserved1[2];
u64 gdtr_base;
u16 ldtr_selector;
u16 ldtr_attributes;
u32 ldtr_limit;
u64 ldtr_base;
u8 reserved2[4];
u16 idtr_limit;
u8 reserved3[2];
u64 idtr_base;
u16 tr_selector;
u16 tr_attributes;
u32 tr_limit;
u64 tr_base;
u8 reserved4[40];
u8 io_restart;
u8 autohalt_restart;
u8 reserved5[6];
u64 efer;
u8 reserved6[36];
u32 smm_revision;
u32 smbase;
u8 reserved7[68];
u64 cr4;
u64 cr3;
u64 cr0;
u64 dr7;
u64 dr6;
u64 rflags;
u64 rip;
u64 r15;
u64 r14;
u64 r13;
u64 r12;
u64 r11;
u64 r10;
u64 r9;
u64 r8;
u64 rdi;
u64 rsi;
u64 rpb;
u64 rsp;
u64 rbx;
u64 rdx;
u64 rcx;
u64 rax;
} __attribute__((packed)) amd64_smm_state_save_area_t;
/* Intel Core 2 (EM64T) SMM State-Save Area
* starts @ 0x7d00
*/
typedef struct {
u8 reserved0[208];
u32 gdtr_upper_base;
u32 ldtr_upper_base;
u32 idtr_upper_base;
u8 reserved1[4];
u64 io_rdi;
u64 io_rip;
u64 io_rcx;
u64 io_rsi;
u64 cr4;
u8 reserved2[68];
u64 gdtr_base;
u64 idtr_base;
u64 ldtr_base;
u8 reserved3[84];
u32 smm_revision;
u32 smbase;
u16 io_restart;
u16 autohalt_restart;
u8 reserved4[24];
u64 r15;
u64 r14;
u64 r13;
u64 r12;
u64 r11;
u64 r10;
u64 r9;
u64 r8;
u64 rax;
u64 rcx;
u64 rdx;
u64 rbx;
u64 rsp;
u64 rbp;
u64 rsi;
u64 rdi;
u64 io_mem_addr;
u32 io_misc_info;
u32 es_sel;
u32 cs_sel;
u32 ss_sel;
u32 ds_sel;
u32 fs_sel;
u32 gs_sel;
u32 ldtr_sel;
u32 tr_sel;
u64 dr7;
u64 dr6;
u64 rip;
u64 efer;
u64 rflags;
u64 cr3;
u64 cr0;
} __attribute__((packed)) em64t_smm_state_save_area_t;
/* Intel Revision 30101 SMM State-Save Area
* The following processor architectures use this:
* - SandyBridge
* - IvyBridge
* - Haswell
*/
#define SMM_EM64T101_ARCH_OFFSET 0x7c00
#define SMM_EM64T101_SAVE_STATE_OFFSET \
SMM_SAVE_STATE_BEGIN(SMM_EM64T101_ARCH_OFFSET)
typedef struct {
u8 reserved0[256];
u8 reserved1[208];
u32 gdtr_upper_base;
u32 ldtr_upper_base;
u32 idtr_upper_base;
u32 io_cf8;
u64 io_rdi;
u64 io_rip;
u64 io_rcx;
u64 io_rsi;
u8 reserved2[52];
u32 shutdown_auto_restart;
u8 reserved3[8];
u32 cr4;
u8 reserved4[72];
u32 gdtr_base;
u8 reserved5[4];
u32 idtr_base;
u8 reserved6[4];
u32 ldtr_base;
u8 reserved7[56];
/* EPTP fields are only on Haswell according to BWGs, but Intel was
* wise and reused the same revision number. */
u64 eptp;
u32 eptp_en;
u32 cs_base;
u8 reserved8[4];
u32 iedbase;
u8 reserved9[8];
u32 smbase;
u32 smm_revision;
u16 io_restart;
u16 autohalt_restart;
u8 reserved10[24];
u64 r15;
u64 r14;
u64 r13;
u64 r12;
u64 r11;
u64 r10;
u64 r9;
u64 r8;
u64 rax;
u64 rcx;
u64 rdx;
u64 rbx;
u64 rsp;
u64 rbp;
u64 rsi;
u64 rdi;
u64 io_mem_addr;
u32 io_misc_info;
u32 es_sel;
u32 cs_sel;
u32 ss_sel;
u32 ds_sel;
u32 fs_sel;
u32 gs_sel;
u32 ldtr_sel;
u32 tr_sel;
u64 dr7;
u64 dr6;
u64 rip;
u64 efer;
u64 rflags;
u64 cr3;
u64 cr0;
} __attribute__((packed)) em64t101_smm_state_save_area_t;
/* Legacy x86 SMM State-Save Area
* starts @ 0x7e00
*/
typedef struct {
u8 reserved0[248];
u32 smbase;
u32 smm_revision;
u16 io_restart;
u16 autohalt_restart;
u8 reserved1[132];
u32 gdtbase;
u8 reserved2[8];
u32 idtbase;
u8 reserved3[16];
u32 es;
u32 cs;
u32 ss;
u32 ds;
u32 fs;
u32 gs;
u32 ldtbase;
u32 tr;
u32 dr7;
u32 dr6;
u32 eax;
u32 ecx;
u32 edx;
u32 ebx;
u32 esp;
u32 ebp;
u32 esi;
u32 edi;
u32 eip;
u32 eflags;
u32 cr3;
u32 cr0;
} __attribute__((packed)) legacy_smm_state_save_area_t;
typedef enum {
AMD64,
EM64T,
EM64T101,
LEGACY
} save_state_type_t;
typedef struct {
save_state_type_t type;
union {
amd64_smm_state_save_area_t *amd64_state_save;
em64t_smm_state_save_area_t *em64t_state_save;
em64t101_smm_state_save_area_t *em64t101_state_save;
legacy_smm_state_save_area_t *legacy_state_save;
};
} smm_state_save_area_t;
#define APM_CNT 0xb2
#define APM_CNT_CST_CONTROL 0x85
#define APM_CNT_PST_CONTROL 0x80
#define APM_CNT_ACPI_DISABLE 0x1e
#define APM_CNT_ACPI_ENABLE 0xe1
#define APM_CNT_MBI_UPDATE 0xeb
#define APM_CNT_GNVS_UPDATE 0xea
#define APM_STS 0xb3
/* SMI handler function prototypes */
void smi_handler(u32 smm_revision);
void io_trap_handler(int smif);
int southbridge_io_trap_handler(int smif);
int __attribute__((weak)) mainboard_io_trap_handler(int smif);
void southbridge_smi_set_eos(void);
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>
2013-01-04 00:38:47 +01:00
#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);
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);
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>
2013-01-04 00:38:47 +01:00
#endif /* CONFIG_SMM_MODULES */
#if !CONFIG_SMM_TSEG
void smi_release_lock(void);
#define tseg_relocate(ptr)
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>
2013-01-04 00:38:47 +01:00
#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);
/* Adjust pointer with TSEG base */
void tseg_relocate(void **ptr);
#endif
/* Get PMBASE address */
u16 smm_get_pmbase(void);
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>
2013-01-04 00:38:47 +01:00
#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