From 62f100b02888c2de21d61caf5d850f1184e8be1a Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 7 Nov 2012 12:27:29 -0600 Subject: smm: Update rev 0x30101 SMM revision save state According to both Haswell and the SandyBridge/Ivybridge BWGs the save state area actually starts at 0x7c00 offset from 0x8000. Update the em64t101_smm_state_save_area_t structure and introduce a define for the offset. Note: I have no idea what eptp is. It's just listed in the haswell BWG. The offsets should not be changed. Change-Id: I38d1d1469e30628a83f10b188ab2fe53d5a50e5a Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/2515 Tested-by: build bot (Jenkins) Reviewed-by: Paul Menzel Reviewed-by: Ronald G. Minnich --- src/cpu/x86/smm/smihandler.c | 29 +++++++++++++---------- src/include/cpu/x86/smm.h | 37 ++++++++++++++++++++---------- src/southbridge/intel/bd82x6x/smihandler.c | 2 +- 3 files changed, 43 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/cpu/x86/smm/smihandler.c b/src/cpu/x86/smm/smihandler.c index 10f38f9690..b4b7f36dba 100644 --- a/src/cpu/x86/smm/smihandler.c +++ b/src/cpu/x86/smm/smihandler.c @@ -107,6 +107,12 @@ static void smi_restore_pci_address(void) outl(pci_orig, 0xcf8); } +static inline void *smm_save_state(u32 base, int arch_offset, int node) +{ + base += SMM_SAVE_STATE_BEGIN(arch_offset) - (node * 0x400); + return (void *)base; +} + /** * @brief Interrupt handler for SMI# * @@ -117,13 +123,13 @@ void smi_handler(u32 smm_revision) { unsigned int node; smm_state_save_area_t state_save; - u32 smm_base = 0xa8000; /* ASEG */ + u32 smm_base = 0xa0000; /* ASEG */ #if CONFIG_SMM_TSEG /* Update global variable TSEG base */ if (!smi_get_tseg_base()) return; - smm_base = smi_get_tseg_base() + 0x8000; + smm_base = smi_get_tseg_base(); #else /* Are we ok to execute the handler? */ if (!smi_obtain_lock()) { @@ -151,24 +157,23 @@ void smi_handler(u32 smm_revision) case 0x00030002: case 0x00030007: state_save.type = LEGACY; - state_save.legacy_state_save = (legacy_smm_state_save_area_t *) - (smm_base + 0x7e00 - (node * 0x400)); + state_save.legacy_state_save = + smm_save_state(smm_base, 0x7e00, node); break; case 0x00030100: state_save.type = EM64T; - state_save.em64t_state_save = (em64t_smm_state_save_area_t *) - (smm_base + 0x7d00 - (node * 0x400)); - break; - case 0x00030101: /* SandyBridge/IvyBridge */ + state_save.em64t_state_save = + smm_save_state(smm_base, 0x7d00, node); + case 0x00030101: /* SandyBridge, IvyBridge, and Haswell */ state_save.type = EM64T101; state_save.em64t101_state_save = - (em64t101_smm_state_save_area_t *) - (smm_base + 0x7d00 - (node * 0x400)); + smm_save_state(smm_base, + SMM_EM64T101_ARCH_OFFSET, node); break; case 0x00030064: state_save.type = AMD64; - state_save.amd64_state_save = (amd64_smm_state_save_area_t *) - (smm_base + 0x7e00 - (node * 0x400)); + state_save.amd64_state_save = + smm_save_state(smm_base, 0x7e00, node); break; default: printk(BIOS_DEBUG, "smm_revision: 0x%08x\n", smm_revision); diff --git a/src/include/cpu/x86/smm.h b/src/include/cpu/x86/smm.h index b52a315017..3ffebf4255 100644 --- a/src/include/cpu/x86/smm.h +++ b/src/include/cpu/x86/smm.h @@ -27,6 +27,9 @@ /* 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 typedef struct { u16 es_selector; @@ -202,11 +205,17 @@ typedef struct { /* Intel Revision 30101 SMM State-Save Area - * Used in SandyBridge/IvyBridge architecture - * starts @ 0x7d00 + * 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[208]; + u8 reserved0[256]; + u8 reserved1[208]; u32 gdtr_upper_base; u32 ldtr_upper_base; @@ -219,25 +228,29 @@ typedef struct { u64 io_rcx; u64 io_rsi; - u8 reserved1[52]; + u8 reserved2[52]; u32 shutdown_auto_restart; - u8 reserved2[8]; + u8 reserved3[8]; u32 cr4; - u8 reserved3[72]; + u8 reserved4[72]; u32 gdtr_base; - u8 reserved4[4]; - u32 idtr_base; u8 reserved5[4]; + u32 idtr_base; + u8 reserved6[4]; u32 ldtr_base; - u8 reserved6[68]; + 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 reserved7[4]; + u8 reserved8[4]; u32 iedbase; - u8 reserved8[8]; + u8 reserved9[8]; u32 smbase; u32 smm_revision; @@ -245,7 +258,7 @@ typedef struct { u16 io_restart; u16 autohalt_restart; - u8 reserved9[24]; + u8 reserved10[24]; u64 r15; u64 r14; diff --git a/src/southbridge/intel/bd82x6x/smihandler.c b/src/southbridge/intel/bd82x6x/smihandler.c index 804607c927..420c5db211 100644 --- a/src/southbridge/intel/bd82x6x/smihandler.c +++ b/src/southbridge/intel/bd82x6x/smihandler.c @@ -432,7 +432,7 @@ static void southbridge_smi_sleep(unsigned int node, smm_state_save_area_t *stat static em64t101_smm_state_save_area_t *smi_apmc_find_state_save(u8 cmd) { em64t101_smm_state_save_area_t *state; - u32 base = smi_get_tseg_base() + 0x8000 + 0x7d00; + u32 base = smi_get_tseg_base() + SMM_EM64T101_SAVE_STATE_OFFSET; int node; /* Check all nodes looking for the one that issued the IO */ -- cgit v1.2.3