Patchwork SMM on K8

login
register
about
Submitter Rudolf Marek
Date 2010-11-17 19:48:06
Message ID <4CE43176.3000402@assembler.cz>
Download mbox | patch
Permalink /patch/2329/
State Superseded
Headers show

Comments

Rudolf Marek - 2010-11-17 19:48:06
Hi all,

Here is a SMM patch that actually works on VT8237S! It supports only SMI CMD so 
sending something to port 0x52f should trigger it.

It is mostly in good state however following needs to be done. Thats left to 
Tobias or Fengwei.

0) only enabled board is m2v-mx se (trivial to enable others VIA 8237 based)
1) PCIe access is hardcoded to 0xe000000

This sucks,but generally mmconfig is good idea beacuse it does not create races...

So what about that?

a) change the SMM handler to save PCIcfg/PCIdata??? regs
b) make MMCONFIG static to 0xe00000
c) some clever way to get idea where it is without PCI access


2) Dualcore/more cpus

I hardcoded that for single CPU. You need most likely change model_fxx_init.c 
and call smm_init from there (except that copy can done via CPU)

All CPUs needs to set Aseg ENable and SMM_BASE (to different address)

No smm_relocate.S is used because we dont need it on AMD, we have the MSRs...

3) More features to SMM

Handy would be ACPI enable/disable -maybe whats there will work
and Poweroff if powerbutton is pressed and acpi does not work yet ;)

Otherwise SMM is not used at all so we don't really need any features...

4) Cool stuff

Emulate some hardware one can do traps for IO and for MMIO so any HW can be 
created just for fun (TPM ;)

5) remove HACK_SMM
The header file dislikes the include someone needs to fix that.

6) SMM locking

The SMM should be locked, there is even a register for that. However I dont know 
if all CPUs needs to lock... and if some cpu is locked, can others still access 
the memory (for the memcopy?)

Also we lock SMM on the base in the RAM, we should create a dummy "RSM" like 
handler if we don't have any SMI handler on K8.

Thanks goes to Stepan for initial version (from mine POC version).


Thanks,
Rudolf
Marc Jones - 2010-11-19 16:41:01
2010/11/17 Rudolf Marek <r.marek@assembler.cz>:
> Hi all,
>
> Here is a SMM patch that actually works on VT8237S! It supports only SMI CMD
> so sending something to port 0x52f should trigger it.
>
> It is mostly in good state however following needs to be done. Thats left to
> Tobias or Fengwei.
>
> 0) only enabled board is m2v-mx se (trivial to enable others VIA 8237 based)
> 1) PCIe access is hardcoded to 0xe000000
>
> This sucks,but generally mmconfig is good idea beacuse it does not create
> races...
>
> So what about that?
>
> a) change the SMM handler to save PCIcfg/PCIdata??? regs
> b) make MMCONFIG static to 0xe00000
> c) some clever way to get idea where it is without PCI access
>
>
> 2) Dualcore/more cpus
>
> I hardcoded that for single CPU. You need most likely change
> model_fxx_init.c and call smm_init from there (except that copy can done via
> CPU)
>
> All CPUs needs to set Aseg ENable and SMM_BASE (to different address)
>
> No smm_relocate.S is used because we dont need it on AMD, we have the
> MSRs...
>
> 3) More features to SMM
>
> Handy would be ACPI enable/disable -maybe whats there will work
> and Poweroff if powerbutton is pressed and acpi does not work yet ;)
>
> Otherwise SMM is not used at all so we don't really need any features...
>
> 4) Cool stuff
>
> Emulate some hardware one can do traps for IO and for MMIO so any HW can be
> created just for fun (TPM ;)
>
> 5) remove HACK_SMM
> The header file dislikes the include someone needs to fix that.
>
> 6) SMM locking
>
> The SMM should be locked, there is even a register for that. However I dont
> know if all CPUs needs to lock... and if some cpu is locked, can others
> still access the memory (for the memcopy?)
>
> Also we lock SMM on the base in the RAM, we should create a dummy "RSM" like
> handler if we don't have any SMI handler on K8.
>
> Thanks goes to Stepan for initial version (from mine POC version).
>

I haven't looked at the patch, but this is exciting development. Open
SMM implementation should interest many people.

Marc

Patch

Index: src/southbridge/via/vt8237r/Makefile.inc
===================================================================
--- src/southbridge/via/vt8237r/Makefile.inc.orig	2010-11-17 11:55:54.000000000 +0100
+++ src/southbridge/via/vt8237r/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -25,3 +25,7 @@ 
 driver-y += vt8237r_usb.c
 driver-$(CONFIG_PIRQ_ROUTE) += vt8237r_pirq.c
 ramstage-$(CONFIG_GENERATE_ACPI_TABLES) += vt8237_fadt.c
+
+smm-$(CONFIG_HAVE_SMI_HANDLER) += vt8237r_smihandler.c
+
+
Index: src/southbridge/via/vt8237r/vt8237r.h
===================================================================
--- src/southbridge/via/vt8237r/vt8237r.h.orig	2010-11-14 15:15:44.000000000 +0100
+++ src/southbridge/via/vt8237r/vt8237r.h	2010-11-17 20:00:23.000000000 +0100
@@ -20,12 +20,11 @@ 
 #ifndef SOUTHBRIDGE_VIA_VT8237R_VT8237R_H
 #define SOUTHBRIDGE_VIA_VT8237R_VT8237R_H
 
-#include <stdint.h>
-
 /* Static resources for the VT8237R southbridge */
 
 #define VT8237R_APIC_ID			0x2
 #define VT8237R_ACPI_IO_BASE		0x500
+#define DEFAULT_PMBASE			VT8237R_ACPI_IO_BASE
 #define VT8237R_SMBUS_IO_BASE		0x400
 /* 0x0 disabled, 0x2 reserved, 0xf = IRQ15 */
 #define VT8237R_ACPI_IRQ		0x9
@@ -36,6 +35,36 @@ 
 #endif
 #define VT8237R_HPET_ADDR		0xfed00000ULL
 
+/* PMBASE FIXME mostly taken from ich7 */
+#define PM1_STS		0x00
+#define   WAK_STS	(1 << 15)
+#define   PCIEXPWAK_STS	(1 << 14)
+#define   PRBTNOR_STS	(1 << 11)
+#define   RTC_STS	(1 << 10)
+#define   PWRBTN_STS	(1 << 8)
+#define   GBL_STS	(1 << 5)
+#define   BM_STS	(1 << 4)
+#define   TMROF_STS	(1 << 0)
+#define PM1_EN		0x02
+#define   PCIEXPWAK_DIS	(1 << 14)
+#define   RTC_EN	(1 << 10)
+#define   PWRBTN_EN	(1 << 8)
+#define   GBL_EN	(1 << 5)
+#define   TMROF_EN	(1 << 0)
+#define PM1_CNT		0x04
+#define   SLP_EN	(1 << 13)
+#define   SLP_TYP	(7 << 10)
+#define   GBL_RLS	(1 << 2)
+#define   BM_RLD	(1 << 1)
+#define   SCI_EN	(1 << 0)
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define SMI_STS		0x28
+#define SMI_EN		0x2d
+#define EOS		(1 << 0)
+
 /* IDE */
 #define IDE_CS				0x40
 #define IDE_CONF_I			0x41
@@ -107,6 +136,15 @@ 
 #endif
 ;
 
+#define MAINBOARD_POWER_OFF	0
+#define MAINBOARD_POWER_ON	1
+#define MAINBOARD_POWER_KEEP	2
+
+#ifndef CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL
+#define CONFIG_MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
+#endif
+
+
 #ifdef __PRE_RAM__
 #ifndef __ROMCC__
 u8 smbus_read_byte(u8 dimm, u8 offset);
@@ -119,10 +157,11 @@ 
 int vt8237_early_network_init(struct vt8237_network_rom *rom);
 #endif
 #else
-#include <device/device.h>
-void writeback(struct device *dev, u16 where, u8 what);
+void writeback(device_t dev, u16 where, u8 what);
 void dump_south(device_t dev);
+#ifndef SMM_HACK
 u32 vt8237_ide_80pin_detect(struct device *dev);
 #endif
+#endif
 
 #endif
Index: src/southbridge/via/vt8237r/vt8237r_smihandler.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/southbridge/via/vt8237r/vt8237r_smihandler.c	2010-11-17 20:05:55.000000000 +0100
@@ -0,0 +1,233 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008-2009 coresystems GmbH
+ * Copyright (C) 2010 Rudolf Marek <r.marek@assembler.cz>
+ *
+ * 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
+ */
+
+#include <types.h>
+#include <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <device/pci_def.h>
+
+#define SMM_HACK 1
+#include "vt8237r.h"
+
+#define APM_CNT		0xb2
+#define   CST_CONTROL	0x85
+#define   PST_CONTROL	0x80
+#define   ACPI_DISABLE	0x1e
+#define   ACPI_ENABLE	0xe1
+#define   GNVS_UPDATE   0xea
+#define APM_STS		0xb3
+
+#include "vt8237r_nvs.h"
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+u16 pmbase = DEFAULT_PMBASE;
+u8 smm_initialized = 0;
+
+#if 0
+/**
+ * @brief read and clear PM1_STS
+ * @return PM1_STS register
+ */
+static u16 reset_pm1_status(void)
+{
+	u16 reg16;
+
+	reg16 = inw(pmbase + PM1_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outw(reg16, pmbase + PM1_STS);
+
+	return reg16;
+}
+
+static void dump_pm1_status(u16 pm1_sts)
+{
+	printk(BIOS_SPEW, "PM1_STS: ");
+	if (pm1_sts & (1 << 15)) printk(BIOS_SPEW, "WAK ");
+	if (pm1_sts & (1 << 14)) printk(BIOS_SPEW, "PCIEXPWAK ");
+	if (pm1_sts & (1 << 11)) printk(BIOS_SPEW, "PRBTNOR ");
+	if (pm1_sts & (1 << 10)) printk(BIOS_SPEW, "RTC ");
+	if (pm1_sts & (1 <<  8)) printk(BIOS_SPEW, "PWRBTN ");
+	if (pm1_sts & (1 <<  5)) printk(BIOS_SPEW, "GBL ");
+	if (pm1_sts & (1 <<  4)) printk(BIOS_SPEW, "BM ");
+	if (pm1_sts & (1 <<  0)) printk(BIOS_SPEW, "TMROF ");
+	printk(BIOS_SPEW, "\n");
+	int reg16 = inw(pmbase + PM1_EN);
+	printk(BIOS_SPEW, "PM1_EN: %x\n", reg16);
+}
+#endif
+
+/**
+ * @brief read and clear SMI_STS
+ * @return SMI_STS register
+ */
+static u32 reset_smi_status(void)
+{
+	u32 reg32;
+
+	reg32 = inw(pmbase + SMI_STS);
+	/* set status bits are cleared by writing 1 to them */
+	outw(reg32, pmbase + SMI_STS);
+
+	return reg32;
+}
+
+static void dump_smi_status(u32 smi_sts)
+{
+	printk(BIOS_DEBUG, "SMI_STS: ");
+	if (smi_sts & (1 << 15)) printk(BIOS_DEBUG, "GPIO RANGE1 ");
+	if (smi_sts & (1 << 14)) printk(BIOS_DEBUG, "GPIO RANGE0 ");
+	if (smi_sts & (1 << 13)) printk(BIOS_DEBUG, "GP3 Timeout ");
+	if (smi_sts & (1 << 12)) printk(BIOS_DEBUG, "GP2 Timeout ");
+	if (smi_sts & (1 << 11)) printk(BIOS_DEBUG, "SERR IRQ SMI status ");
+	if (smi_sts & (1 << 10)) printk(BIOS_DEBUG, "PMIO 5 gets written ");
+	if (smi_sts & (1 <<  9)) printk(BIOS_DEBUG, "THRMTRIP# ");
+	if (smi_sts & (1 <<  8)) printk(BIOS_DEBUG, "CLKRUN# ");
+	if (smi_sts & (1 <<  7)) printk(BIOS_DEBUG, "Primary IRQ/NMI/SMI resume ");
+	if (smi_sts & (1 <<  6)) printk(BIOS_DEBUG, "Software SMI ");
+	if (smi_sts & (1 <<  5)) printk(BIOS_DEBUG, "BIOS Status ");
+	if (smi_sts & (1 <<  4)) printk(BIOS_DEBUG, "Legacy USB Status ");
+	if (smi_sts & (1 <<  3)) printk(BIOS_DEBUG, "GP1 Timeout ");
+	if (smi_sts & (1 <<  2)) printk(BIOS_DEBUG, "GP0 Timeout ");
+	if (smi_sts & (1 <<  1)) printk(BIOS_DEBUG, "Secondary Event TMR ");
+	if (smi_sts & (1 <<  0)) printk(BIOS_DEBUG, "Primary Activity ");
+
+	printk(BIOS_DEBUG, "\n");
+}
+
+int southbridge_io_trap_handler(int smif)
+{
+	/* Not handled */
+	return 0;
+}
+
+/**
+ * @brief Set the EOS bit
+ */
+void southbridge_smi_set_eos(void)
+{
+	u8 reg8;
+
+	reg8 = inb(pmbase + SMI_EN);
+	reg8 |= EOS;
+	outb(reg8, pmbase + SMI_EN);
+
+}
+
+
+/* We are using PCIe accesses for now
+ *  1. the chipset can do it
+ *  2. we don't need to worry about how we leave 0xcf8/0xcfc behind
+ */
+#include "../../../northbridge/amd/amdk8/pcie_config.c"
+
+
+typedef void (*smi_handler_t)(unsigned int node,
+		smm_state_save_area_t *state_save);
+
+static void southbridge_smi_cmd(unsigned int node, smm_state_save_area_t *state_save)
+{
+	u32 pmctrl;
+	u8 reg8;
+	reg8 = inb(pmbase + 0x2f);
+	switch (reg8) {
+	case ACPI_DISABLE:
+		pmctrl = inw(pmbase + PM1_CNT);
+		pmctrl &= ~SCI_EN;
+		outw(pmctrl, pmbase + PM1_CNT);
+		printk(BIOS_DEBUG, "SMI#: ACPI disabled.\n");
+		break;
+	case ACPI_ENABLE:
+		pmctrl = inw(pmbase + PM1_CNT);
+		pmctrl |= SCI_EN;
+		outw(pmctrl, pmbase + PM1_CNT);
+		printk(BIOS_DEBUG, "SMI#: ACPI enabled.\n");
+		break;
+	default:
+		printk(BIOS_DEBUG, "SMI#: Unknown function SMI_CMD=%02x\n", reg8);
+	}
+}
+
+smi_handler_t southbridge_smi[16] = {
+	NULL,			  //  [0]
+	NULL,			  //  [1]
+	NULL,			  //  [2]
+	NULL,			  //  [3]
+	NULL,			  //  [4]
+	NULL,			  //  [5]
+	southbridge_smi_cmd,	  //  [6]
+	NULL,			  //  [7]
+	NULL,			  //  [8]
+	NULL,			  //  [9]
+	NULL,			  //  [10]
+	NULL,			  //  [11]
+	NULL,			  //  [12]
+	NULL,			  //  [13]
+	NULL,			  //  [14]
+	NULL,			  //  [15]
+};
+
+/**
+ * @brief Interrupt handler for SMI#
+ *
+ * @param smm_revision revision of the smm state save map
+ */
+
+void southbridge_smi_handler(unsigned int node, smm_state_save_area_t *state_save)
+{
+	int i, dump = 0;
+	u32 smi_sts;
+
+	/* Update global variable pmbase */
+	pmbase = pcie_read_config16(PCI_DEV(0, 0x11, 0), 0x88) & 0xfffc;
+
+	/* We need to clear the SMI status registers, or we won't see what's
+	 * happening in the following calls.
+	 */
+	smi_sts = reset_smi_status();
+
+	/* Filter all non-enabled SMI events */
+	// FIXME Double check, this clears MONITOR
+	// smi_sts &= inl(pmbase + SMI_EN);
+
+	/* Call SMI sub handler for each of the status bits */
+	for (i = 0; i < 16; i++) {
+		if (smi_sts & (1 << i)) {
+			if (southbridge_smi[i])
+				southbridge_smi[i](node, state_save);
+			else {
+				printk(BIOS_DEBUG, "SMI_STS[%d] occured, but no "
+						"handler available.\n", i);
+				dump = 1;
+			}
+		}
+	}
+
+	if(dump) {
+		dump_smi_status(smi_sts);
+	}
+
+}
Index: src/southbridge/via/vt8237r/vt8237r_nvs.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/southbridge/via/vt8237r/vt8237r_nvs.h	2010-11-17 17:38:39.000000000 +0100
@@ -0,0 +1,46 @@ 
+/*
+ * 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
+ */
+
+typedef struct {
+	/* Miscellaneous */
+	u16	osys; /* 0x00 - Operating System */
+	u8	smif; /* 0x02 - SMI function call ("TRAP") */
+	u8	prm0; /* 0x03 - SMI function call parameter */
+	u8	prm1; /* 0x04 - SMI function call parameter */
+	u8	scif; /* 0x05 - SCI function call (via _L00) */
+	u8	prm2; /* 0x06 - SCI function call parameter */
+	u8	prm3; /* 0x07 - SCI function call parameter */
+	u8	lckf; /* 0x08 - Global Lock function for EC */
+	u8	prm4; /* 0x09 - Lock function parameter */
+	u8	prm5; /* 0x0a - Lock function parameter */
+	u32	p80d; /* 0x0b - Debug port (IO 0x80) value */
+	u8	lids; /* 0x0f - LID state (open = 1) */
+	u8	pwrs; /* 0x10 - Power state (AC = 1) */
+	u8	dbgs; /* 0x11 - Debug state */
+	u8	linx; /* 0x12 - Linux OS */
+	u8	dckn; /* 0x13 - PCIe docking state */
+	u8      rsvd[0x28-0x14];
+	/* Processor Identification */
+	u8	apic; /* 0x28 - APIC enabled */
+	u8	mpen; /* 0x29 - MP capable/enabled */
+	u8	pcp0; /* 0x2a - PDC CPU/CORE 0 */
+	u8	pcp1; /* 0x2b - PDC CPU/CORE 1 */
+	u8	ppcm; /* 0x2c - Max. PPC state */
+} __attribute__((packed)) global_nvs_t;
+
Index: src/southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_lpc.c.orig	2010-11-17 12:20:03.000000000 +0100
+++ src/southbridge/via/vt8237r/vt8237r_lpc.c	2010-11-17 18:54:34.000000000 +0100
@@ -28,6 +28,7 @@ 
 #include <pc80/mc146818rtc.h>
 #include <arch/ioapic.h>
 #include <cpu/x86/lapic.h>
+#include <cpu/cpu.h>
 #include <pc80/keyboard.h>
 #include <pc80/i8259.h>
 #include <stdlib.h>
@@ -217,11 +218,8 @@ 
 	/* Disable SMI on GPIO. */
 	outw(0x0, VT8237R_ACPI_IO_BASE + 0x24);
 
-	/* Disable all global enable SMIs. */
-	outw(0x0, VT8237R_ACPI_IO_BASE + 0x2a);
-
-	/* All SMI off, both IDE buses ON, PSON rising edge. */
-	outw(0x0, VT8237R_ACPI_IO_BASE + 0x2c);
+	/* Disable all global enable SMIs, except SW SMI */
+	outw(0x40, VT8237R_ACPI_IO_BASE + 0x2a);
 
 	/* Primary activity SMI disable. */
 	outl(0x0, VT8237R_ACPI_IO_BASE + 0x34);
@@ -238,6 +236,10 @@ 
 	acpi_slp_type = ((tmp & (7 << 10)) >> 10) == 1 ? 3 : 0 ;
 	printk(BIOS_DEBUG, "SLP_TYP type was %x %x\n", tmp, acpi_slp_type);
 #endif
+
+	/* All SMI on, both IDE buses ON, PSON rising edge. */
+	outw(0x1, VT8237R_ACPI_IO_BASE + 0x2c);
+
 	/* clear sleep */
 	tmp &= ~(7 << 10);
 	tmp |= 1;
@@ -500,7 +502,7 @@ 
 
 	/* Enable serial IRQ, 6PCI clocks. */
 	pci_write_config8(dev, 0x52, 0x9);
-
+	smm_init();
 #endif
 
 	/* Power management setup */
Index: src/include/cpu/x86/smm.h
===================================================================
--- src/include/cpu/x86/smm.h.orig	2010-11-14 14:45:09.000000000 +0100
+++ src/include/cpu/x86/smm.h	2010-11-17 17:38:39.000000000 +0100
@@ -254,7 +254,7 @@ 
 
 void io_trap_handler(int smif);
 int southbridge_io_trap_handler(int smif);
-int mainboard_io_trap_handler(int smif);
+int __attribute__((weak)) mainboard_io_trap_handler(int smif);
 
 void southbridge_smi_set_eos(void);
 
Index: src/cpu/amd/socket_S1G1/Makefile.inc
===================================================================
--- src/cpu/amd/socket_S1G1/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_S1G1/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -7,7 +7,8 @@ 
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
-subdirs-y += ../../x86/smm
 subdirs-y += ../../x86/mtrr
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_940/Makefile.inc
===================================================================
--- src/cpu/amd/socket_940/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_940/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -8,5 +8,7 @@ 
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/model_fxx/model_fxx_init.c
===================================================================
--- src/cpu/amd/model_fxx/model_fxx_init.c.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/model_fxx/model_fxx_init.c	2010-11-17 20:27:20.000000000 +0100
@@ -499,11 +499,6 @@ 
 
 	k8_errata();
 
-	/* Set SMMLOCK to avoid exploits messing with SMM */
-	msr = rdmsr(HWCR_MSR);
-	msr.lo |= (1 << 0);
-	wrmsr(HWCR_MSR, msr);
-
 	enable_cache();
 
 	/* Set the processor name string */
Index: src/cpu/amd/socket_AM2/Makefile.inc
===================================================================
--- src/cpu/amd/socket_AM2/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_AM2/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -9,5 +9,6 @@ 
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
 subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_754/Makefile.inc
===================================================================
--- src/cpu/amd/socket_754/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_754/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -8,5 +8,7 @@ 
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_AM3/Makefile.inc
===================================================================
--- src/cpu/amd/socket_AM3/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_AM3/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -7,7 +7,8 @@ 
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
-subdirs-y += ../../x86/smm
 subdirs-y += ../../x86/mtrr
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_AM2r2/Makefile.inc
===================================================================
--- src/cpu/amd/socket_AM2r2/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_AM2r2/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -7,7 +7,8 @@ 
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
-subdirs-y += ../../x86/smm
 subdirs-y += ../../x86/mtrr
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/smm/smm_init.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/cpu/amd/smm/smm_init.c	2010-11-17 20:38:14.000000000 +0100
@@ -0,0 +1,88 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 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
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <cpu/amd/mtrr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/model_fxx_msr.h>
+
+#include <string.h>
+
+#define MSR_SMM_BASE 0xc0010111
+#define MSR_SMM_MASK 0xc0010113
+#define SMM_BASE 0xa0000
+
+extern unsigned char _binary_smm_start;
+extern unsigned char _binary_smm_size;
+
+void smm_init(void)
+{
+	/* FIXME: all other CPUs should setup the SMM base according to our scheme */
+	msr_t msr, syscfg_old, fixa0000_old;
+
+	msr = rdmsr(HWCR_MSR);
+	if (msr.lo & (1 << 0)) {
+		printk(BIOS_INFO, "SMM is locked from last boot, using old handler\n");
+		return;
+	}
+	disable_cache();
+	syscfg_old = rdmsr(SYSCFG_MSR);
+	fixa0000_old = rdmsr(MTRRfix16K_A0000_MSR);
+	msr = syscfg_old;
+	msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+
+	/* set DRAM access to 0xa0000 */
+	msr.lo = 0x18181818;
+	msr.hi = 0x18181818;
+	wrmsr(MTRRfix16K_A0000_MSR, msr);
+	msr.lo |= SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+
+	/* copy the real SMM handler */
+	memcpy((void *)SMM_BASE, &_binary_smm_start, (size_t)&_binary_smm_size);
+
+	msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+	wrmsr(MTRRfix16K_A0000_MSR, fixa0000_old);
+	wrmsr(SYSCFG_MSR, syscfg_old);
+	enable_cache();
+
+	msr = rdmsr(MSR_SMM_BASE);
+	msr.lo = SMM_BASE;
+	wrmsr(MSR_SMM_BASE, msr);
+
+	/* enable the SMM memory window */
+	msr = rdmsr(MSR_SMM_MASK);
+	msr.lo |= (1 << 0); /* Enable ASEG SMRAM Range */
+	wrmsr(MSR_SMM_MASK, msr);
+
+	/* Set SMMLOCK to avoid exploits messing with SMM
+	 NOTE: if we do INIT we - wont rewrite the handler!
+	msr = rdmsr(HWCR_MSR);
+	msr.lo |= (1 << 0);
+	wrmsr(HWCR_MSR, msr);
+	*/
+}
Index: src/cpu/amd/smm/Makefile.inc
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/cpu/amd/smm/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -0,0 +1,2 @@ 
+
+ramstage-$(CONFIG_HAVE_SMI_HANDLER) += smm_init.c
Index: src/cpu/amd/socket_939/Makefile.inc
===================================================================
--- src/cpu/amd/socket_939/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_939/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -8,5 +8,7 @@ 
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_F/Makefile.inc
===================================================================
--- src/cpu/amd/socket_F/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_F/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -9,5 +9,6 @@ 
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
 subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_ASB2/Makefile.inc
===================================================================
--- src/cpu/amd/socket_ASB2/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_ASB2/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -7,7 +7,8 @@ 
 subdirs-y += ../../x86/lapic
 subdirs-y += ../../x86/cache
 subdirs-y += ../../x86/pae
-subdirs-y += ../../x86/smm
 subdirs-y += ../../x86/mtrr
+subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/amd/socket_F_1207/Makefile.inc
===================================================================
--- src/cpu/amd/socket_F_1207/Makefile.inc.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/amd/socket_F_1207/Makefile.inc	2010-11-17 17:38:39.000000000 +0100
@@ -9,5 +9,6 @@ 
 subdirs-y += ../../x86/mtrr
 subdirs-y += ../../x86/pae
 subdirs-y += ../../x86/smm
+subdirs-y += ../smm
 
 cpu_incs += $(src)/cpu/amd/car/cache_as_ram.inc
Index: src/cpu/x86/smm/smmrelocate.S
===================================================================
--- src/cpu/x86/smm/smmrelocate.S.orig	2010-11-14 14:45:10.000000000 +0100
+++ src/cpu/x86/smm/smmrelocate.S	2010-11-17 17:38:39.000000000 +0100
@@ -22,6 +22,8 @@ 
 // Make sure no stage 2 code is included:
 #define __PRE_RAM__
 
+#if !defined(CONFIG_NORTHBRIDGE_AMD_AMDK8) && !defined(CONFIG_NORTHBRIDGE_AMD_FAM10)
+
 // FIXME: Is this piece of code southbridge specific, or
 // can it be cleaned up so this include is not required?
 // It's needed right now because we get our DEFAULT_PMBASE from
@@ -175,4 +177,4 @@ 
 	/* That's it. return */
 	rsm
 smm_relocation_end:
-
+#endif
Index: src/mainboard/asus/m2v-mx_se/Kconfig
===================================================================
--- src/mainboard/asus/m2v-mx_se/Kconfig.orig	2010-11-17 11:54:03.000000000 +0100
+++ src/mainboard/asus/m2v-mx_se/Kconfig	2010-11-17 17:38:39.000000000 +0100
@@ -37,6 +37,7 @@ 
 	select TINY_BOOTBLOCK
 	select HAVE_MAINBOARD_RESOURCES
 	select QRANK_DIMM_SUPPORT
+	select HAVE_SMI_HANDLER
 	select SET_FIDVID
 
 config MAINBOARD_DIR
Index: src/northbridge/amd/amdk8/pcie_config.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/northbridge/amd/amdk8/pcie_config.c	2010-11-17 17:38:39.000000000 +0100
@@ -0,0 +1,68 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-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
+ */
+
+#include "amdk8.h"
+
+static inline __attribute__ ((always_inline))
+u8 pcie_read_config8(device_t dev, unsigned int where)
+{
+	unsigned long addr;
+	addr = DEFAULT_PCIEXBAR | dev | where;
+	return read8(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u16 pcie_read_config16(device_t dev, unsigned int where)
+{
+	unsigned long addr;
+	addr = DEFAULT_PCIEXBAR | dev | where;
+	return read16(addr);
+}
+
+static inline __attribute__ ((always_inline))
+u32 pcie_read_config32(device_t dev, unsigned int where)
+{
+	unsigned long addr;
+	addr = DEFAULT_PCIEXBAR | dev | where;
+	return read32(addr);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config8(device_t dev, unsigned int where, u8 value)
+{
+	unsigned long addr;
+	addr = DEFAULT_PCIEXBAR | dev | where;
+	write8(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config16(device_t dev, unsigned int where, u16 value)
+{
+	unsigned long addr;
+	addr = DEFAULT_PCIEXBAR | dev | where;
+	write16(addr, value);
+}
+
+static inline __attribute__ ((always_inline))
+void pcie_write_config32(device_t dev, unsigned int where, u32 value)
+{
+	unsigned long addr;
+	addr = DEFAULT_PCIEXBAR | dev | where;
+	write32(addr, value);
+}
Index: src/northbridge/amd/amdk8/amdk8.h
===================================================================
--- src/northbridge/amd/amdk8/amdk8.h.orig	2010-11-14 14:45:14.000000000 +0100
+++ src/northbridge/amd/amdk8/amdk8.h	2010-11-17 17:38:39.000000000 +0100
@@ -2,6 +2,8 @@ 
 
 #define AMDK8_H
 
+#define DEFAULT_PCIEXBAR 0xe0000000
+
 #if CONFIG_K8_REV_F_SUPPORT == 1
         #include "amdk8_f.h"
 #else