Hello,

This is just a technology demonstrator. Its an implementation of SMM for K8 with VT8237S. It install a SMM handler and it just supports the SMI command interface. Thats all. I'm dumping here whole patch as is to save it for future use. (It worked for me).

Rudolf
Index: src/southbridge/via/vt8237r/Config.lb
===================================================================
--- src/southbridge/via/vt8237r/Config.lb	(revision 3738)
+++ src/southbridge/via/vt8237r/Config.lb	(working copy)
@@ -24,3 +24,35 @@
 driver vt8237r_ide.o
 driver vt8237r_lpc.o
 driver vt8237r_sata.o
+
+object vt8237r_smi.o
+object smmrelocate.S
+
+makerule smmhandler.o
+	depends	"$(TOP)/src/southbridge/via/vt8237r/smmhandler.S" 
+	action	"@$(CC) -c $(CPU_OPT) $(CPPFLAGS) $(CFLAGS) -o $@ $<"
+end
+
+makerule smihandler.o
+	depends	"$(TOP)/src/southbridge/via/vt8237r/smihandler.c" 
+	action	"@$(CC) -c $(CPU_OPT) $(CPPFLAGS) $(CFLAGS) -o $@ $<"
+end
+
+makerule smm.o
+	depends	"smmhandler.o smihandler.o printk.o vtxprintf.o $(LIBGCC_FILE_NAME)" 
+	action	"$(CC) $(DISTRO_LFLAGS) -nostdlib -r -o $@ smmhandler.o smihandler.o printk.o vtxprintf.o $(LIBGCC_FILE_NAME)"
+end
+
+makerule smm
+	depends	"smm.o $(TOP)/src/southbridge/via/vt8237r/smm.ld ldoptions" 
+	action	"$(CC) $(DISTRO_LFLAGS) -nostdlib -nostartfiles -static -o smm.elf -T $(TOP)/src/southbridge/via/vt8237r/smm.ld smm.o"
+	action 	"$(CROSS_COMPILE)nm -n smm.elf | sort > smm.map"
+	action  "$(OBJCOPY) -O binary smm.elf smm"
+end
+
+makerule smm_bin.c
+	depends "smm"
+	action "(echo 'unsigned char smm[] = {'; od -vtx1 smm | sed -e 's,^[0-9]* *,,' -e 's:[0-9a-f][0-9a-f] :0x&,:g' -e 's:[0-9a-f][0-9a-f]$$:0x&,:'; echo '}; unsigned int smm_len = '; wc -c smm |awk '{print $$1;}' ; echo ';')  > smm_bin.c"
+end
+
+object ./smm_bin.o
Index: src/southbridge/via/vt8237r/vt8237_ctrl.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237_ctrl.c	(revision 3738)
+++ src/southbridge/via/vt8237r/vt8237_ctrl.c	(working copy)
@@ -165,6 +165,7 @@
 	/* Configure PCI1 and copy mirror registers from D0F3. */
 	vt8237_cfg(dev);
 	dump_south(dev);
+	smm_init();
 }
 
 static const struct device_operations ctrl_ops = {
Index: src/southbridge/via/vt8237r/smihandler.c
===================================================================
--- src/southbridge/via/vt8237r/smihandler.c	(revision 0)
+++ src/southbridge/via/vt8237r/smihandler.c	(revision 0)
@@ -0,0 +1,314 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 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 <arch/io.h>
+#include <arch/romcc_io.h>
+#include <console/console.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include "chip.h"
+
+// Future TODO: Move to i82801gx directory
+//#include "../../../northbridge/intel/i945/ich7.h"
+
+#define DEBUG_SMI
+
+#define ACPI_DISABLE	0x1e
+#define ACPI_ENABLE	0xe1
+
+/* I945 */
+#define SMRAM		0x9d
+#define   D_OPEN	(1 << 6)
+#define   D_CLS		(1 << 5)
+#define   D_LCK		(1 << 4)
+#define   G_SMRANE	(1 << 3)
+#define   C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
+
+/* ICH7 */
+#define PM1_STS		0x00
+#define PM1_EN		0x02
+#define PM1_CNT		0x04
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define LV4		0x16
+#define PM2_CNT		0x20 // mobile only
+#define GPE0_STS	0x28
+#define GPE0_EN		0x2c
+#define SMI_EN		0x30
+#define   EL_SMI_EN	 (1 << 25) // Intel Quick Resume Technology
+#define   INTEL_USB2_EN	 (1 << 18) // Intel-Specific USB2 SMI logic
+#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+#define   PERIODIC_EN	 (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+#define   TCO_EN	 (1 << 13) // Enable TCO Logic (BIOSWE et al)
+#define   MCSMI_EN	 (1 << 11) // Trap microcontroller range access
+#define   BIOS_RLS	 (1 <<  7) // asserts SCI on bit set
+#define   SWSMI_TMR_EN	 (1 <<  6) // start software smi timer on bit set
+#define   APMC_EN	 (1 <<  5) // Writes to APM_CNT cause SMI#
+#define   SLP_SMI_EN	 (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+#define   BIOS_EN	 (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+#define   EOS		 (1 <<  1) // End of SMI (deassert SMI#)
+#define   GBL_SMI_EN	 (1 <<  0) // SMI# generation at all?
+#define SMI_STS		0x34
+#define ALT_GP_SMI_EN	0x38
+#define ALT_GP_SMI_STS	0x3a
+#define GPE_CNTL	0x42
+#define DEVACT_STS	0x44
+#define SS_CNT		0x50
+#define C3_RES		0x54
+
+#include "vt8237r.h"
+
+//#include "i82801gx_nvs.h"
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+static u16 pmbase = VT8237R_ACPI_IO_BASE;
+
+typedef enum { SMI_LOCKED, SMI_UNLOCKED } smi_semaphore;
+
+/* SMI multiprocessing semaphore */
+static volatile smi_semaphore smi_handler_status = SMI_UNLOCKED;
+
+static int smi_obtain_lock(void)
+{
+	u8 ret = SMI_LOCKED;
+
+	asm volatile (
+		"movb %2, %%al\n"
+		"xchgb %%al, %1\n"
+		"movb %%al, %0\n"
+		: "=g" (ret), "=m" (smi_handler_status)
+		: "g" (SMI_LOCKED)
+		: "eax"
+	);
+
+	return (ret == SMI_UNLOCKED);
+}
+
+static void smi_release_lock(void)
+{
+	asm volatile (
+		"movb %1, %%al\n"
+		"xchgb %%al, %0\n"
+		: "=m" (smi_handler_status)
+		: "g" (SMI_UNLOCKED)
+		: "eax"
+	);
+}
+
+#define LAPIC_ID 0xfee00020
+static inline __attribute__((always_inline)) unsigned long nodeid(void)
+{
+	return (*((volatile unsigned long *)(LAPIC_ID)) >> 24);
+}
+
+
+/* ********************* smi_util ************************* */
+
+/* Data */
+#define UART_RBR 0x00
+#define UART_TBR 0x00
+
+/* Control */
+#define UART_IER 0x01
+#define UART_IIR 0x02
+#define UART_FCR 0x02
+#define UART_LCR 0x03
+#define UART_MCR 0x04
+#define UART_DLL 0x00
+#define UART_DLM 0x01
+
+/* Status */
+#define UART_LSR 0x05
+#define UART_MSR 0x06
+#define UART_SCR 0x07
+
+static int uart_can_tx_byte(void)
+{
+	return inb(TTYS0_BASE + UART_LSR) & 0x20;
+}
+
+static void uart_wait_to_tx_byte(void)
+{
+	while(!uart_can_tx_byte()) 
+	;
+}
+
+static void uart_wait_until_sent(void)
+{
+	while(!(inb(TTYS0_BASE + UART_LSR) & 0x40))
+	; 
+}
+
+static void uart_tx_byte(unsigned char data)
+{
+	uart_wait_to_tx_byte();
+	outb(data, TTYS0_BASE + UART_TBR);
+	/* Make certain the data clears the fifos */
+	uart_wait_until_sent();
+}
+
+void console_tx_flush(void)
+{
+	uart_wait_to_tx_byte();
+}
+
+void console_tx_byte(unsigned char byte)
+{
+	if (byte == '\n')
+		uart_tx_byte('\r');
+	uart_tx_byte(byte);
+}
+
+/* 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/intel/i945/pcie_config.c"
+
+/* ********************* smi_util ************************* */
+
+u32 reg_pci_config;
+
+
+/**
+ * @brief Save the additional context
+ * TODO: CMOS state
+ */
+static void smm_save_state(void) {
+	reg_pci_config = inl(0xcf8);
+}
+
+/**
+ * @brief Restore the additional context
+ */
+static void smm_restore_state(void) {
+	outl(reg_pci_config, 0xcf8);
+}
+
+
+static void smm_process_command(void) {
+	u8 reg = inb(VT8237R_ACPI_IO_BASE + 0x28);
+
+	if (!(reg & (1 << 6)))
+		return;
+	
+	reg |= (1 << 6);
+	outb(reg, VT8237R_ACPI_IO_BASE + 0x28);
+
+	printk_debug("smm_command was: 0x%02x\n", inb(VT8237R_ACPI_IO_BASE + 0x2f));
+}
+
+/**
+ * @brief Check if other SMI is pending
+ */
+
+static  int check_pending_smi(void)
+{
+	u8 reg8;
+	
+	reg8 = inb(VT8237R_ACPI_IO_BASE + 0x2d);
+	reg8 |= 1;
+	outb(reg8, VT8237R_ACPI_IO_BASE + 0x2d);
+	return (inb(VT8237R_ACPI_IO_BASE + 0x2d) & 1);
+}
+
+/**
+ * @brief Interrupt handler for SMI#
+ *
+ * @param smm_revision revision of the smm state save map
+ */
+
+void smi_handler(u32 smm_revision)
+{
+	u8 reg8;
+	u16 pmctrl;
+	u16 pm1_sts;
+	u32 smi_sts, gpe0_sts, tco_sts;
+	unsigned int node;
+	smm_state_save_area_t state_save;
+
+	/* Are we ok to execute the handler? */
+	if (!smi_obtain_lock())
+		return;
+
+	smm_save_state();
+
+next:
+	node=nodeid();
+
+#ifdef DEBUG_SMI
+	console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
+#else
+	console_loglevel = 1;
+#endif
+
+	printk_debug("\nSMI# #%d\n", node);
+
+	switch (smm_revision) {
+	case 0x00030007:
+		state_save.type = LEGACY;
+		state_save.legacy_state_save = (legacy_smm_state_save_area_t *)
+			(0xa8000 + 0x7e00 - (node * 0x400));
+		break;
+	case 0x00030100:
+		state_save.type = EM64T;
+		state_save.em64t_state_save = (em64t_smm_state_save_area_t *)
+			(0xa8000 + 0x7d00 - (node * 0x400));
+		break;
+	case 0x00030064:
+		state_save.type = AMD64;
+		state_save.amd64_state_save = (amd64_smm_state_save_area_t *)
+			(0xa8000 + 0x7e00 - (node * 0x400));
+		break;
+	default:
+		printk_debug("smm_revision: 0x%08x\n", smm_revision);
+		printk_debug("SMI# not supported on your CPU\n");
+		/* Don't release lock, so no further SMI will happen,
+		 * if we don't handle it anyways.
+		 */
+		return;
+	}
+
+
+	smm_process_command();
+
+//	pmbase = pcie_read_config16(PCI_DEV(0, 0x1f, 0), 0x40) & 0xfffc;
+//	printk_spew("SMI#: pmbase = 0x%04x\n", pmbase);
+	
+	/* We need to clear the SMI status registers, or we won't see what's
+	 * happening in the following calls. */
+	 
+
+	/* De-assert SMI# signal to allow another SMI */
+
+
+	if (check_pending_smi()) {
+		goto next;
+	}
+
+	smm_restore_state();
+	smi_release_lock();
+}
Index: src/southbridge/via/vt8237r/vt8237r_smi.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_smi.c	(revision 0)
+++ src/southbridge/via/vt8237r/vt8237r_smi.c	(revision 0)
@@ -0,0 +1,186 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 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 <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
+#include <arch/io.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/smm.h>
+#include <string.h>
+#include "chip.h"
+#include "vt8237r.h"
+
+// Future TODO: Move to i82801gx directory
+//#include "../../../northbridge/intel/i945/ich7.h"
+
+extern unsigned char smm[];
+extern unsigned int smm_len;
+
+/* I945 */
+#define SMRAM		0x9d
+#define   D_OPEN	(1 << 6)
+#define   D_CLS		(1 << 5)
+#define   D_LCK		(1 << 4)
+#define   G_SMRAME	(1 << 3)
+#define   C_BASE_SEG	((0 << 2) | (1 << 1) | (0 << 0))
+
+/* ICH7 */
+#define PM1_STS		0x00
+#define PM1_EN		0x02
+#define PM1_CNT		0x04
+#define PM1_TMR		0x08
+#define PROC_CNT	0x10
+#define LV2		0x14
+#define LV3		0x15
+#define LV4		0x16
+#define PM2_CNT		0x20 // mobile only
+#define GPE0_STS	0x28
+#define GPE0_EN		0x2c
+//#define SMI_EN		0x30
+//#define   EL_SMI_EN	 (1 << 25) // Intel Quick Resume Technology
+//#define   INTEL_USB2_EN	 (1 << 18) // Intel-Specific USB2 SMI logic
+//#define   LEGACY_USB2_EN (1 << 17) // Legacy USB2 SMI logic
+//#define   PERIODIC_EN	 (1 << 14) // SMI on PERIODIC_STS in SMI_STS
+//#define   TCO_EN	 (1 << 13) // Enable TCO Logic (BIOSWE et al)
+//#define   MCSMI_EN	 (1 << 11) // Trap microcontroller range access
+//#define   BIOS_RLS	 (1 <<  7) // asserts SCI on bit set
+//#define   SWSMI_TMR_EN	 (1 <<  6) // start software smi timer on bit set
+//#define   APMC_EN	 (1 <<  5) // Writes to APM_CNT cause SMI#
+//#define   SLP_SMI_EN	 (1 <<  4) // Write to SLP_EN in PM1_CNT asserts SMI#
+//#define   LEGACY_USB_EN  (1 <<  3) // Legacy USB circuit SMI logic
+//#define   BIOS_EN	 (1 <<  2) // Assert SMI# on setting GBL_RLS bit
+//#define   EOS		 (1 <<  1) // End of SMI (deassert SMI#)
+//#define   GBL_SMI_EN	 (1 <<  0) // SMI# generation at all?
+#define GLOB_STS 0x2c
+#define SMI_ACT (1 << 8)
+#define SMI_CMD 0x2f
+
+//#define SMI_STS		0x34
+//#define ALT_GP_SMI_EN	0x38
+//#define ALT_GP_SMI_STS	0x3a
+//#define GPE_CNTL	0x42
+//#define DEVACT_STS	0x44
+//#define SS_CNT		0x50
+//#define C3_RES		0x54
+
+/* While we read PMBASE dynamically in case it changed, let's
+ * initialize it with a sane value
+ */
+
+extern uint8_t smm_relocation_start, smm_relocation_end;
+
+void smm_relocate(void)
+{
+	u32 smi_en;
+
+	printk_debug("Initializing SMM handler...");
+
+//	pmbase = pci_read_config16(dev_find_slot(0, PCI_DEVFN(0x1f, 0)), 0x40) & 0xfffc;
+//	printk_spew(" ... pmbase = 0x%04x\n", pmbase);
+
+//	smi_en = inl(pmbase + SMI_EN);
+//	if (smi_en & APMC_EN) {
+//		printk_info("SMI# handler already enabled?\n");
+//		return;
+//	}
+
+	/* copy the SMM relocation code */
+	memcpy((void *)0x38000, &smm_relocation_start,
+			&smm_relocation_end - &smm_relocation_start);
+	wbinvd();
+
+//	/* hack: copy the SMM code LOW */
+//	memcpy((void *)0x40000, &smm, smm_len);
+
+
+	printk_debug("\n");
+//	dump_smi_status(reset_smi_status());
+//	dump_pm1_status(reset_pm1_status());
+//	dump_gpe0_status(reset_gpe0_status());
+//	dump_tco_status(reset_tco_status());
+
+	/* Enable SMI generation:
+	 *  - on TCO events
+	 *  - on APMC writes (io 0xb2)
+	 *  - on writes to SLP_EN (sleep states)
+	 *  - on writes to GBL_RLS (bios commands)
+	 * No SMIs:
+	 *  - on microcontroller writes (io 0x62/0x66)
+	 */
+
+//	outl(smi_en | (TCO_EN | APMC_EN | SLP_SMI_EN | BIOS_EN |
+//				EOS | GBL_SMI_EN), pmbase + SMI_EN);
+
+	/**
+	 * There are several methods of raising a controlled SMI# via
+	 * software, among them:
+	 *  - Writes to io 0xb2 (APMC)
+	 *  - Writes to the Local Apic ICR with Delivery mode SMI.
+	 *
+	 * Using the local apic is a bit more tricky. According to 
+	 * AMD Family 11 Processor BKDG no destination shorthand must be 
+	 * used.
+	 * The whole SMM initialization is quite a bit hardware specific, so
+	 * I'm not too worried about the better of the methods at the moment
+	 */
+
+	/* raise an SMI interrupt */
+	printk_spew("  ... raise SMI# ...\n");
+	outb(0x00, VT8237R_ACPI_IO_BASE+SMI_CMD);
+	printk_spew("done?\n");
+//	outb(0x00, 0xb2);
+//	wbinvd();
+}
+
+void smm_install(void)
+{
+	/* enable the SMM memory window */
+//	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+//				D_OPEN | G_SMRAME | C_BASE_SEG);
+
+	/* copy the real SMM handler */
+//	memcpy((void *)0xa0000, smm, smm_len);
+//	wbinvd();
+
+//	/* close the SMM memory window and enable normal SMM */
+//	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+//			G_SMRAME | C_BASE_SEG);
+}
+
+void smm_init(void)
+{
+	smm_relocate();
+//	smm_install();
+}
+
+void smm_lock(void)
+{
+	/* LOCK the SMM memory window and enable normal SMM.
+	 * After running this function, only a full reset can
+	 * make the SMM registers writable again.
+	 */
+	printk_debug("Locking SMM.\n");
+//	pci_write_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), SMRAM,
+//			D_LCK | G_SMRAME | C_BASE_SEG);
+}
+
Index: src/southbridge/via/vt8237r/smm.ld
===================================================================
--- src/southbridge/via/vt8237r/smm.ld	(revision 0)
+++ src/southbridge/via/vt8237r/smm.ld	(revision 0)
@@ -0,0 +1,53 @@
+
+/* Maximum number of CPUs/cores */
+CPUS = 4;
+
+SECTIONS
+{
+	/* This is the actual SMM handler. 
+	 *
+	 * We just put code, rodata, data and bss all in a row.
+	 */
+	. = 0xa0000;
+	.handler (.): {
+		/* Assembler stub */
+		*(.handler)
+
+		/* C code of the SMM handler */
+		*(.text);
+		*(.text.*);
+
+		/* C read-only data of the SMM handler */
+		. = ALIGN(16);
+		*(.rodata)
+		*(.rodata.*)
+
+		/* C read-write data of the SMM handler */
+		 . = ALIGN(4);
+		*(.data)
+
+		/* C uninitialized data of the SMM handler */
+		 . = ALIGN(4);
+		*(.bss)
+		*(.sbss)
+
+		/* What is this? */
+		*(COMMON)
+		 . = ALIGN(4);
+	}
+
+	/* We are using the ASEG interleaved to stuff the SMM handlers
+	 * for all CPU cores in there. The jump table redirects the execution
+	 * to the actual SMM handler
+	 */
+	. = 0xa8000 - (( CPUS - 1) * 0x400);
+	.jumptable : {
+		*(.jumptable)
+	}	
+
+	/DISCARD/ : {
+		*(.comment)
+		*(.note)
+		*(.note.*)
+	}
+}
Index: src/southbridge/via/vt8237r/smmhandler.S
===================================================================
--- src/southbridge/via/vt8237r/smmhandler.S	(revision 0)
+++ src/southbridge/via/vt8237r/smmhandler.S	(revision 0)
@@ -0,0 +1,201 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 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
+ */
+
+/* NOTE: This handler assumes the SMM window goes from 0xa0000
+ * to 0xaffff. In fact, at least on Intel Core CPUs (i945 chipset)
+ * the SMM window is 128K big, covering 0xa0000 to 0xbffff.
+ * So there is a lot of potential for growth in here. Let's stick
+ * to 64k if we can though.
+ */
+
+/*
+ * +--------------------------------+ 0xaffff
+ * |  Save State Map Node 0         |
+ * |  Save State Map Node 1         |
+ * |  Save State Map Node 2         |
+ * |  Save State Map Node 3         |
+ * |  ...                           |
+ * +--------------------------------+ 0xaf000
+ * |                                |
+ * |                                |
+ * |                                |
+ * +--------------------------------+ 0xa8400
+ * | SMM Entry Node 0 (+ stack)     | 
+ * +--------------------------------+ 0xa8000
+ * | SMM Entry Node 1 (+ stack)     | 
+ * | SMM Entry Node 2 (+ stack)     | 
+ * | SMM Entry Node 3 (+ stack)     | 
+ * | ...                            |
+ * +--------------------------------+ 0xa7400
+ * |                                |
+ * | SMM Handler                    |
+ * |                                |
+ * +--------------------------------+ 0xa0000
+ *
+ */
+
+#include <arch/asm.h>
+
+#define LAPIC_ID 0xfee00020
+
+/* SMM_HANDLER_OFFSET is the 16bit offset within the ASEG
+ * at which smm_handler_start lives. At the moment the handler
+ * lives right at 0xa0000, so the offset is 0. 
+ */
+
+#define SMM_HANDLER_OFFSET 0x0000
+
+/* initially SMM is some sort of real mode. Let gcc know
+ * how to treat the SMM handler stub
+ */
+
+.section ".handler", "a", @progbits
+
+.code16
+
+/**
+ * SMM code to enable protected mode and jump to the
+ * C-written function void smi_handler(u32 smm_revision)
+ *
+ * All the bad magic is not all that bad after all.
+ */
+smm_handler_start:
+	movw    $(smm_gdtptr16 - smm_handler_start + SMM_HANDLER_OFFSET), %bx
+	data32  lgdt %cs:(%bx)
+
+	movl    %cr0, %eax
+	andl    $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */
+	orl     $0x60000001, %eax /* CD, NW, PE = 1 */
+	movl    %eax, %cr0
+
+	/* Enable protected mode */
+	data32  ljmp    $0x08, $1f
+
+.code32
+1:
+	/* Use flat data segment */
+	movw    $0x10, %ax
+	movw    %ax, %ds
+	movw    %ax, %es
+	movw    %ax, %ss
+	movw    %ax, %fs
+	movw    %ax, %gs
+
+	/* Get this CPU's LAPIC ID */
+	movl $LAPIC_ID, %esi
+	movl (%esi), %ecx
+	shr  $24, %ecx
+	
+	/* calculate stack offset by multiplying the APIC ID
+	 * by 1024 (0x400), and save that offset in ebp.
+	 */
+	shl $10, %ecx
+	movl %ecx, %ebp
+
+	/* We put the stack for each core right above 
+	 * its SMM entry point. Core 0 starts at 0xa8000, 
+	 * we spare 0x10 bytes for the jump to be sure.
+	 */
+	movl $0xa8010, %eax
+	subl %ecx, %eax		/* subtract offset, see above */
+	movl %eax, %ebx		/* Save bottom of stack in ebx */
+
+#define SMM_STACK_SIZE	(0x400 - 0x10)
+	/* clear stack */
+	cld
+	movl	%eax, %edi
+	movl	$(SMM_STACK_SIZE >> 2), %ecx
+	xorl	%eax, %eax
+	rep	stosl
+
+	/* set new stack */
+	addl	$SMM_STACK_SIZE, %ebx
+	movl	%ebx, %esp
+
+	/* Get SMM revision */
+	movl $0xa8000 + 0x7efc, %ebx	/* core 0 address */
+	subl %ebp, %ebx			/* subtract core X offset */
+	movl (%ebx), %eax
+	pushl %eax
+
+	/* Call 32bit C handler */
+	call smi_handler
+
+	/* To return, just do rsm. It will "clean up" protected mode */
+	rsm
+
+.code16
+
+.align	4, 0xff
+
+smm_gdtptr16:
+	.word	smm_gdt_end - smm_gdt - 1
+	.long	smm_gdt - smm_handler_start + 0xa0000 + SMM_HANDLER_OFFSET
+
+.code32
+
+smm_gdt:
+	/* The first GDT entry can not be used. Keep it zero */
+	.long	0x00000000, 0x00000000
+
+	/* gdt selector 0x08, flat code segment */
+	.word	0xffff, 0x0000		
+	.byte	0x00, 0x9b, 0xcf, 0x00 /* G=1 and 0x0f, 4GB limit */	
+
+	/* gdt selector 0x10, flat data segment */
+	.word	0xffff, 0x0000		
+	.byte	0x00, 0x93, 0xcf, 0x00
+
+smm_gdt_end:
+
+
+.section ".jumptable", "a", @progbits
+
+/* This is the SMM jump table. All cores use the same SMM handler
+ * for simplicity. But SMM Entry needs to be different due to the 
+ * save state area. The jump table makes sure all CPUs jump into the
+ * real handler on SMM entry.
+ */
+
+/* This code currently supports up to 4 CPU cores. If more than 4 CPU cores
+ * shall be used, below table has to be updated, as well as smm.ld
+ */
+
+/* GNU AS/LD will always generate code that assumes CS is 0xa000. In reality
+ * CS will be set to SMM_BASE[19:4] though. Knowing that the smm handler is the
+ * first thing in the ASEG, we do a far jump here, to set CS to 0xa000.
+ */
+
+.code16
+jumptable:
+	/* core 3 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET 
+.align 1024, 0x00
+	/* core 2 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET 
+.align 1024, 0x00
+	/* core 1 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET 
+.align 1024, 0x00
+	/* core 0 */
+	ljmp $0xa000, $SMM_HANDLER_OFFSET
+.align 1024, 0x00
+
Index: src/southbridge/via/vt8237r/smmrelocate.S
===================================================================
--- src/southbridge/via/vt8237r/smmrelocate.S	(revision 0)
+++ src/southbridge/via/vt8237r/smmrelocate.S	(revision 0)
@@ -0,0 +1,193 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 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 <arch/asm.h>
+
+//hack
+#define VT8237R_ACPI_IO_BASE 0x500 
+
+
+//#undef DEBUG_SMM_RELOCATION
+#define DEBUG_SMM_RELOCATION
+
+#define LAPIC_ID 0xfee00020
+
+.global smm_relocation_start
+.global smm_relocation_end
+
+/* initially SMM is some sort of real mode. */
+.code16
+
+/**
+ * This trampoline code relocates SMBASE to 0xa0000 - ( lapicid * 0x400 )
+ *
+ * Why 0x400? It is a safe value to cover the save state area per CPU. On
+ * current AMD CPUs this area is _documented_ to be 0x200 bytes. On Intel
+ * Core 2 CPUs the _documented_ parts of the save state area is 48 bytes
+ * bigger, effectively sizing our data structures 0x300 bytes.
+ *
+ * LAPICID	SMBASE		SMM Entry 	SAVE STATE
+ *    0		0xa0000		0xa8000		0xafd00
+ *    1		0x9fc00		0xa7c00		0xaf900
+ *    2		0x9f800		0xa7800		0xaf500
+ *    3		0x9f400		0xa7400		0xaf100
+ *    4		0x9f000		0xa7000		0xaed00
+ *    5		0x9ec00		0xa6c00		0xae900
+ *    6		0x9e800		0xa6800		0xae500
+ *    7		0x9e400		0xa6400		0xae100
+ *    8		0x9e000		0xa6000		0xadd00
+ *    9		0x9dc00		0xa5c00		0xad900
+ *   10		0x9d800		0xa5800		0xad500
+ *   11		0x9d400		0xa5400		0xad100
+ *   12		0x9d000		0xa5000		0xacd00
+ *   13		0x9cc00		0xa4c00		0xac900
+ *   14		0x9c800		0xa4800		0xac500
+ *   15		0x9c400		0xa4400		0xac100
+ *    .		   .		   .		   .
+ *    .		   .		   .		   .
+ *    .		   .		   .		   .
+ *   31		0x98400		0xa0400		0xa8100
+ *
+ * With 32 cores, the SMM handler would need to fit between
+ * 0xa0000-0xa0400 and the stub plus stack would need to go
+ * at 0xa8000-0xa8100 (example for core 0). That is not enough.
+ *
+ * This means we're basically limited to 16 cpu cores before 
+ * we need to use the TSEG/HSEG for the actual SMM handler plus stack.
+ * When we exceed 32 cores, we also need to put SMBASE to TSEG/HSEG.
+ *
+ * If we figure out the documented values above are safe to use,
+ * we could pack the structure above even more, so we could use the
+ * scheme to pack save state areas for 63 AMD CPUs or 58 Intel CPUs
+ * in the ASEG.
+ *
+ * Note: Some versions of Pentium M need their SMBASE aligned to 32k.
+ * On those the above only works for up to 2 cores. But for now we only
+ * care fore Core (2) Duo/Solo
+ *
+ */
+
+smm_relocation_start:
+	/* Check revision to see if AMD64 style SMM_BASE
+	 *   Intel Core Solo/Duo:  0x30007
+	 *   Intel Core2 Solo/Duo: 0x30100
+	 *   AMD64:                0x3XX64
+	 * This check does not make much sense, unless someone ports
+	 * SMI handling to AMD64 CPUs.
+	 */
+
+	movw $TTYS0_BASE, %dx
+	mov $'S', %al
+	outb %al, %dx
+
+	mov $0x38000 + 0x7efc, %ebx
+	addr32 mov (%ebx), %al
+	cmp $0x64, %al
+	je 1f
+ 
+	mov $0x38000 + 0x7ef8, %ebx
+	jmp smm_relocate
+1:
+	mov $0x38000 + 0x7f00, %ebx
+
+smm_relocate:
+	movw $TTYS0_BASE, %dx
+	mov $'M', %al
+	outb %al, %dx
+
+
+	/* Get this CPU's LAPIC ID */
+	movl $LAPIC_ID, %esi
+	addr32 movl (%esi), %ecx
+	shr  $24, %ecx
+	
+	/* calculate offset by multiplying the 
+	 * apic ID by 1024 (0x400)
+	 */
+	movl %ecx, %edx
+	shl $10, %edx
+
+	movl $0xa0000, %eax
+	subl %edx, %eax	/* subtract offset, see above */
+
+	addr32 movl %eax, (%ebx)
+
+	movw $TTYS0_BASE, %dx
+	mov $'M', %al
+	outb %al, %dx
+
+	/* copy the SMM handler to new location */
+	addr32 movl (smm_len), %ecx
+	shr $2, %ecx
+	inc %ecx
+	movl $smm,%esi
+	movl $0xa0000,%edi
+	cld
+	rep
+	addr32 movsl
+	wbinvd
+	movw $TTYS0_BASE, %dx
+	mov $'!', %al
+	outb %al, %dx
+
+	/* The next section of code is hardware specific */
+
+	/* Clear SW SMI so other SMIs can occur */
+	movw $(VT8237R_ACPI_IO_BASE + 0x28), %dx
+	inb %dx, %al
+	orb $(1 << 6), %al
+	outb %al, %dx
+
+	/* Set EOS bit so other SMIs can occur */
+	movw $(VT8237R_ACPI_IO_BASE + 0x2d), %dx
+	inb %dx, %al
+	orb $(1 << 0), %al
+	outb %al, %dx
+
+	/* End of hardware specific section. */
+#ifdef DEBUG_SMM_RELOCATION
+	/* print [SMM-x] so we can determine if CPUx went to SMM */
+	movw $TTYS0_BASE, %dx
+	mov $'[', %al
+	outb %al, %dx
+	mov $'S', %al
+	outb %al, %dx
+	mov $'M', %al
+	outb %al, %dx
+	outb %al, %dx
+	movb $'-', %al
+	outb %al, %dx
+/* calculate ascii of cpu number. More than 9 cores? -> FIXME */
+	movb %cl, %al
+	addb $'0', %al 
+	outb %al, %dx
+	mov $']', %al
+	outb %al, %dx
+	mov $'\r', %al
+	outb %al, %dx
+	mov $'\n', %al
+	outb %al, %dx
+#endif
+
+	/* That's it. return */
+	rsm
+smm_relocation_end:
+
Index: src/southbridge/via/vt8237r/vt8237r_lpc.c
===================================================================
--- src/southbridge/via/vt8237r/vt8237r_lpc.c	(revision 3738)
+++ src/southbridge/via/vt8237r/vt8237r_lpc.c	(working copy)
@@ -201,12 +201,9 @@
 	/* Disable SMI on GPIO. */
 	outw(0x0, VT8237R_ACPI_IO_BASE + 0x24);
 
-	/* Disable all global enable SMIs. */
-	outw(0x0, VT8237R_ACPI_IO_BASE + 0x2a);
+	/* Disable all global enable SMIs, except SW SMI */
+	outw(0x40, VT8237R_ACPI_IO_BASE + 0x2a);
 
-	/* All SMI off, both IDE buses ON, PSON rising edge. */
-	outw(0x0, VT8237R_ACPI_IO_BASE + 0x2c);
-
 	/* Primary activity SMI disable. */
 	outl(0x0, VT8237R_ACPI_IO_BASE + 0x34);
 
@@ -218,6 +215,9 @@
 
 	/* SCI is generated for RTC/pwrBtn/slpBtn. */
 	outw(0x001, VT8237R_ACPI_IO_BASE + 0x04);
+
+	/* All SMI on, both IDE buses ON, PSON rising edge. */
+	outw(0x1, VT8237R_ACPI_IO_BASE + 0x2c);
 }
 
 static void vt8237r_init(struct device *dev)
Index: src/southbridge/via/k8t890/k8t890_dram.c
===================================================================
--- src/southbridge/via/k8t890/k8t890_dram.c	(revision 3738)
+++ src/southbridge/via/k8t890/k8t890_dram.c	(working copy)
@@ -64,6 +64,12 @@
 	/* The Address Next to the Last Valid DRAM Address */
 	pci_write_config16(dev, 0x88, (msr.lo >> 24) | reg);
 
+	/*hack for SMM */
+	msr = rdmsr(0xC0010113);
+	/* set Aseg dram type and enable =0x000000fffff04003 */
+	msr.lo |= ((0 << 8) | (0 << 4) | (1 << 0));
+	wrmsr(0xC0010113, msr);
+
 }
 
 static void dram_enable_k8m890(struct device *dev)
Index: src/cpu/amd/model_fxx/model_fxx_init.c
===================================================================
--- src/cpu/amd/model_fxx/model_fxx_init.c	(revision 3738)
+++ src/cpu/amd/model_fxx/model_fxx_init.c	(working copy)
@@ -512,9 +512,9 @@
 	k8_errata();
 	
 	/* Set SMMLOCK to avoid exploits messing with SMM */
-	msr = rdmsr(HWCR_MSR);
-	msr.lo |= (1 << 0);
-	wrmsr(HWCR_MSR, msr);
+//	msr = rdmsr(HWCR_MSR);
+//	msr.lo |= (1 << 0);
+//	wrmsr(HWCR_MSR, msr);
 	
 	/* Set the processor name string */
 	init_processor_name();
Index: src/mainboard/asus/m2v-mx_se/Config.lb
===================================================================
--- src/mainboard/asus/m2v-mx_se/Config.lb	(revision 3738)
+++ src/mainboard/asus/m2v-mx_se/Config.lb	(working copy)
@@ -34,9 +34,16 @@
 default _ROMBASE     = (CONFIG_ROM_PAYLOAD_START + PAYLOAD_SIZE)
 
 ##WARNING enable caching of whole ROM during CAR
-default XIP_ROM_SIZE =  ROM_SIZE
+#default XIP_ROM_SIZE =  ROM_SIZE
+#default XIP_ROM_BASE =  0xffffffff + 1 - XIP_ROM_SIZE
+
+##WARNING enable caching of whole ROM during CAR
+##MEGA HACK
+default XIP_ROM_SIZE =  0x80000
 default XIP_ROM_BASE =  0xffffffff + 1 - XIP_ROM_SIZE
 
+
+
 arch i386 end 
 
 driver mainboard.o
Index: src/mainboard/asus/m2v-mx_se/Options.lb
===================================================================
--- src/mainboard/asus/m2v-mx_se/Options.lb	(revision 3738)
+++ src/mainboard/asus/m2v-mx_se/Options.lb	(working copy)
@@ -44,7 +44,7 @@
 uses STACK_SIZE
 uses HEAP_SIZE
 # uses USE_OPTION_TABLE
-# uses CONFIG_LB_MEM_TOPK
+uses CONFIG_LB_MEM_TOPK
 uses HAVE_ACPI_TABLES
 uses LB_CKS_RANGE_START
 uses LB_CKS_RANGE_END
@@ -152,8 +152,8 @@
 default STACK_SIZE = 8 * 1024
 default HEAP_SIZE = 256 * 1024
 # More 1M for pgtbl.
-# default CONFIG_LB_MEM_TOPK = 2048
-default _RAMBASE = 0x00004000
+default CONFIG_LB_MEM_TOPK = 2048
+default _RAMBASE = 0x100000
 # default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE
 default CONFIG_ROM_PAYLOAD = 1
 default CC = "$(CROSS_COMPILE)gcc -m32"
Index: src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c
===================================================================
--- src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c	(revision 3738)
+++ src/mainboard/asus/m2v-mx_se/cache_as_ram_auto.c	(working copy)
@@ -282,7 +282,7 @@
 	print_debug("after enable_fid_change\r\n");
 
 	/* FIXME does not work yet */
-//	init_fidvid_bsp(bsp_apicid);
+	init_fidvid_bsp(bsp_apicid);
 
 	/* Stop the APs so we can start them later in init. */
 	allow_all_aps_stop(bsp_apicid);
Index: src/arch/i386/boot/tables.c
===================================================================
--- src/arch/i386/boot/tables.c	(revision 3738)
+++ src/arch/i386/boot/tables.c	(working copy)
@@ -42,8 +42,8 @@
 	unsigned long low_table_start, low_table_end, new_low_table_end;
 	unsigned long rom_table_start, rom_table_end;
 
-	rom_table_start = 0xf0000; 
-	rom_table_end =   0xf0000;
+	rom_table_start = ((512-64)*1024*1024) - 64*1024;
+	rom_table_end = rom_table_start;
 	/* Start low addr at 16 bytes instead of 0 because of a buglet
 	 * in the generic linux unzip code, as it tests for the a20 line.
 	 */
@@ -67,9 +67,10 @@
 	post_code(0x96);
 
 	/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
-	new_low_table_end = write_smp_table(low_table_end); // low_table_end is 0x10 at this point
+	rom_table_end = write_smp_table(rom_table_end);
+	rom_table_end = (rom_table_end+1023) & ~1023;
 
-#if HAVE_MP_TABLE==1
+#if 0 // HAVE_MP_TABLE==1
         /* Don't write anything in the traditional x86 BIOS data segment,
          * for example the linux kernel smp need to use 0x467 to pass reset vector
          * or use 0x40e/0x413 for EBDA finding...
Index: targets/asus/m2v-mx_se/Config.lb
===================================================================
--- targets/asus/m2v-mx_se/Config.lb	(revision 3738)
+++ targets/asus/m2v-mx_se/Config.lb	(working copy)
@@ -21,7 +21,7 @@
 mainboard asus/m2v-mx_se
 
 romimage "normal"
-	option ROM_SIZE = 512 * 1024
+	option ROM_SIZE = (512 * 1024) - 39424
 	option USE_FALLBACK_IMAGE = 0
 	option ROM_IMAGE_SIZE = 128 * 1024
 	option COREBOOT_EXTRA_VERSION=".0Normal"
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to