summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/x86/smm/smihandler.c29
-rw-r--r--src/include/cpu/x86/smm.h37
-rw-r--r--src/southbridge/intel/bd82x6x/smihandler.c2
3 files changed, 43 insertions, 25 deletions
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 <types.h>
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 */