[coreboot] Patch set updated for coreboot: ff18431 S3 code in coreboot public folder.

Zheng Bao (zheng.bao@amd.com) gerrit at coreboot.org
Wed Feb 15 03:32:36 CET 2012


Zheng Bao (zheng.bao at amd.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/623

-gerrit

commit ff18431547606654d8530d4c9bd0b0514a1125b8
Author: zbao <fishbaozi at gmail.com>
Date:   Tue Feb 14 18:51:46 2012 +0800

    S3 code in coreboot public folder.
    
    1. Move the Stack to hig memory.
    2. Restore the MTRR before cb jump to the wakeup vector.
    
    Change-Id: I9872e02fcd7eed98e7f630aa29ece810ac32d55a
    Signed-off-by: Zheng Bao <zheng.bao at amd.com>
    Signed-off-by: zbao <fishbaozi at gmail.com>
---
 src/arch/x86/Makefile.inc                        |   10 +
 src/arch/x86/boot/acpi.c                         |    2 +
 src/arch/x86/boot/tables.c                       |    3 +-
 src/boot/hardwaremain.c                          |    5 +-
 src/cpu/amd/agesa/Makefile.inc                   |    2 +
 src/cpu/amd/agesa/cache_as_ram.inc               |    7 +
 src/cpu/amd/agesa/family14/Kconfig               |    8 +
 src/cpu/amd/agesa/family14/model_14_init.c       |  165 ++++++-----
 src/cpu/amd/agesa/s3_resume.c                    |  348 ++++++++++++++++++++++
 src/cpu/amd/agesa/s3_resume.h                    |   42 +++
 src/cpu/amd/car/post_cache_as_ram.c              |   18 +-
 src/devices/pci_device.c                         |   10 +
 src/include/cbmem.h                              |   11 +-
 src/include/string.h                             |    1 +
 src/lib/cbmem.c                                  |    2 +
 src/lib/memcpy.c                                 |   15 +
 src/northbridge/amd/agesa/family14/northbridge.c |  104 +++++--
 17 files changed, 622 insertions(+), 131 deletions(-)

diff --git a/src/arch/x86/Makefile.inc b/src/arch/x86/Makefile.inc
index c9cbb01..31de1e3 100755
--- a/src/arch/x86/Makefile.inc
+++ b/src/arch/x86/Makefile.inc
@@ -107,6 +107,16 @@ ifeq ($(CONFIG_INCLUDE_CONFIG_FILE),y)
 	sed -e '/^#/d' -e '/^ *$$/d' $(DOTCONFIG) >> $(obj)/config.tmp ; \
 	$(CBFSTOOL) $@.tmp add $(obj)/config.tmp config raw; rm -f $(obj)/config.tmp ; fi
 endif
+ifeq ($(CONFIG_HAVE_ACPI_RESUME),y)
+# This S3 storage area in flash is a bit tricky. The location is set and used
+# by the southbridge ROM access functions. This should probably be
+# connected with the #define somehow...
+	@printf "    S3 NVRAM   0xffff0000 (S3 storage area)\n"
+	rm -f $(obj)/s3.rom
+	dd if=/dev/zero of=$(obj)/fill.rom bs=20k count=1 2> /dev/null
+	$(CBFSTOOL) $@.tmp add $(obj)/fill.rom "s3nv" raw 0xffff0000
+	rm -f $(obj)/s3.rom
+endif
 	mv $@.tmp $@
 	@printf "    CBFSPRINT  $(subst $(obj)/,,$(@))\n\n"
 	$(CBFSTOOL) $@ print
diff --git a/src/arch/x86/boot/acpi.c b/src/arch/x86/boot/acpi.c
index f1be034..077f47c 100644
--- a/src/arch/x86/boot/acpi.c
+++ b/src/arch/x86/boot/acpi.c
@@ -474,6 +474,8 @@ void suspend_resume(void)
 	wake_vec = acpi_find_wakeup_vector();
 	if (wake_vec)
 		acpi_jump_to_wakeup(wake_vec);
+	else
+		die("Error: No Wake Vector Found!\n   Reset for normal boot path.");
 }
 
 /* This is to be filled by SB code - startup value what was found. */
diff --git a/src/arch/x86/boot/tables.c b/src/arch/x86/boot/tables.c
index 29d2ec0..ba5cdf3 100644
--- a/src/arch/x86/boot/tables.c
+++ b/src/arch/x86/boot/tables.c
@@ -230,13 +230,12 @@ struct lb_memory *write_tables(void)
 	}
 
 	post_code(0x9e);
-
 #if CONFIG_HAVE_ACPI_RESUME
 	/* Let's prepare the ACPI S3 Resume area now already, so we can rely on
 	 * it begin there during reboot time. We don't need the pointer, nor
 	 * the result right now. If it fails, ACPI resume will be disabled.
 	 */
-	cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE);
+	cbmem_add(CBMEM_ID_RESUME, HIGH_MEMORY_SAVE + HIGH_SCRATCH_MEMORY_SIZE);
 #endif
 
 #if CONFIG_MULTIBOOT
diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c
index 3d15b55..56a5f0c 100644
--- a/src/boot/hardwaremain.c
+++ b/src/boot/hardwaremain.c
@@ -35,7 +35,7 @@ it with the version available from LANL.
 #include <boot/tables.h>
 #include <boot/elf.h>
 #include <cbfs.h>
-#if CONFIG_HAVE_ACPI_RESUME
+#if CONFIG_HAVE_ACPI_RESUME == 1
 #include <arch/acpi.h>
 #endif
 #if CONFIG_WRITE_HIGH_TABLES
@@ -94,7 +94,8 @@ void hardwaremain(int boot_complete)
 	cbmem_initialize();
 #endif
 #if CONFIG_HAVE_ACPI_RESUME == 1
-	suspend_resume();
+	if (acpi_slp_type == 3)
+		suspend_resume();
 	post_code(0x8a);
 #endif
 
diff --git a/src/cpu/amd/agesa/Makefile.inc b/src/cpu/amd/agesa/Makefile.inc
index 4331435..cfe6a43 100644
--- a/src/cpu/amd/agesa/Makefile.inc
+++ b/src/cpu/amd/agesa/Makefile.inc
@@ -20,5 +20,7 @@ subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY10) += family10
 subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY12) += family12
 subdirs-$(CONFIG_CPU_AMD_AGESA_FAMILY14) += family14
 
+romstage-$(CONFIG_HAVE_ACPI_RESUME) += s3_resume.c
+ramstage-$(CONFIG_HAVE_ACPI_RESUME) += s3_resume.c
 ramstage-y += apic_timer.c
 cpu_incs += $(src)/cpu/amd/agesa/cache_as_ram.inc
diff --git a/src/cpu/amd/agesa/cache_as_ram.inc b/src/cpu/amd/agesa/cache_as_ram.inc
index f328db4..2124bf3 100755
--- a/src/cpu/amd/agesa/cache_as_ram.inc
+++ b/src/cpu/amd/agesa/cache_as_ram.inc
@@ -86,6 +86,13 @@ disable_cache_as_ram:
   /* Save return stack */
   movd %esp, %xmm0
 
+  /* Disable cache */
+  movl	%cr0, %eax
+  orl	$(1 << 30), %eax
+  movl	%eax, %cr0
+
+  invd
+
   AMD_DISABLE_STACK
 
   /* Restore the return stack */
diff --git a/src/cpu/amd/agesa/family14/Kconfig b/src/cpu/amd/agesa/family14/Kconfig
index 702270c..d1140f3 100644
--- a/src/cpu/amd/agesa/family14/Kconfig
+++ b/src/cpu/amd/agesa/family14/Kconfig
@@ -67,3 +67,11 @@ config HAVE_INIT_TIMER
 	default y
 	depends on CPU_AMD_AGESA_FAMILY14
 
+config RESUME_SCRATCH_MEMORY_SIZE
+# This is derived from AGESA gccar.inc
+# BSP_STACK_SIZE + CORE0_STACK_SIZE * 8 + CORE1_STACK_SIZE * 64 + HEAP_SIZE
+# For 2 core Fam14: BSP_STACK_SIZE + CORE1_STACK_SIZE + HEAP_SIZE
+# 0x10000 + 0x1000 + 20000
+	hex
+	default 0x31000
+	depends on CPU_AMD_AGESA_FAMILY14
diff --git a/src/cpu/amd/agesa/family14/model_14_init.c b/src/cpu/amd/agesa/family14/model_14_init.c
index 6f697cf..d90695a 100644
--- a/src/cpu/amd/agesa/family14/model_14_init.c
+++ b/src/cpu/amd/agesa/family14/model_14_init.c
@@ -32,109 +32,126 @@
 #include <cpu/x86/cache.h>
 #include <cpu/x86/mtrr.h>
 #include <cpu/amd/amdfam14.h>
+#include <arch/acpi.h>
+#include <cpu/amd/agesa/s3_resume.h>
 
 #define MCI_STATUS 0x401
 
 msr_t rdmsr_amd(u32 index)
 {
-  msr_t result;
-  __asm__ __volatile__(
-    "rdmsr"
-    :"=a"(result.lo), "=d"(result.hi)
-    :"c"(index), "D"(0x9c5a203a)
-  );
-  return result;
+	msr_t result;
+	__asm__ __volatile__(
+		"rdmsr"
+		:"=a"(result.lo), "=d"(result.hi)
+		:"c"(index), "D"(0x9c5a203a)
+		);
+	return result;
 }
 
 void wrmsr_amd(u32 index, msr_t msr)
 {
-  __asm__ __volatile__(
-    "wrmsr"
-    : /* No outputs */
-    :"c"(index), "a"(msr.lo), "d"(msr.hi), "D"(0x9c5a203a)
-  );
+	__asm__ __volatile__(
+		"wrmsr"
+		: /* No outputs */
+		:"c"(index), "a"(msr.lo), "d"(msr.hi), "D"(0x9c5a203a)
+		);
 }
 
 static void model_14_init(device_t dev)
 {
-  printk(BIOS_DEBUG, "Model 14 Init.\n");
-
-  u8 i;
-  msr_t msr;
-  int msrno;
+	u32 i;
+	msr_t msr;
 #if CONFIG_LOGICAL_CPUS == 1
-  u32 siblings;
+	u32 siblings;
+#endif
+	printk(BIOS_DEBUG, "Model 14 Init.\n");
+
+	disable_cache ();
+	/*
+	 * AGESA sets the MTRRs main MTRRs. The shadow area needs to be set
+	 * by coreboot. The amd_setup_mtrrs should work, but needs debug on fam14.
+	 * TODO:
+	 * amd_setup_mtrrs();
+	 */
+
+	/* Enable access to AMD RdDram and WrDram extension bits */
+	msr = rdmsr(SYSCFG_MSR);
+	msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	msr.lo &= ~SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+
+	/* Set shadow WB, RdMEM, WrMEM */
+	msr.lo = msr.hi = 0;
+	wrmsr (0x259, msr);
+	msr.hi = msr.lo = 0x1e1e1e1e;
+	wrmsr(0x250, msr);
+	wrmsr(0x258, msr);
+	for (i = 0x268; i <= 0x26f; i++)
+		wrmsr(i, msr);
+
+	msr = rdmsr(SYSCFG_MSR);
+	msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+	msr.lo |= SYSCFG_MSR_MtrrFixDramEn;
+	wrmsr(SYSCFG_MSR, msr);
+
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	if (acpi_slp_type == 3)
+		restore_mtrr();
 #endif
 
-  disable_cache ();
-  /* Enable access to AMD RdDram and WrDram extension bits */
-  msr = rdmsr(SYSCFG_MSR);
-  msr.lo |= SYSCFG_MSR_MtrrFixDramModEn;
-  wrmsr(SYSCFG_MSR, msr);
-
-   // BSP: make a0000-bffff UC, c0000-fffff WB, same as OntarioApMtrrSettingsList for APs
-   msr.lo = msr.hi = 0;
-   wrmsr (0x259, msr);
-   msr.lo = msr.hi = 0x1e1e1e1e;
-   for (msrno = 0x268; msrno <= 0x26f; msrno++)
-      wrmsr (msrno, msr);
-
-  /* disable access to AMD RdDram and WrDram extension bits */
-  msr = rdmsr(SYSCFG_MSR);
-  msr.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
-  wrmsr(SYSCFG_MSR, msr);
-  enable_cache ();
-
-  /* zero the machine check error status registers */
-  msr.lo = 0;
-  msr.hi = 0;
-  for (i = 0; i < 6; i++) {
-    wrmsr(MCI_STATUS + (i * 4), msr);
-  }
-
-  /* Enable the local cpu apics */
-  setup_lapic();
+	x86_mtrr_check();
+	x86_enable_cache();
+
+	/* zero the machine check error status registers */
+	msr.lo = 0;
+	msr.hi = 0;
+	for (i = 0; i < 6; i++) {
+		wrmsr(MCI_STATUS + (i * 4), msr);
+	}
+
+	/* Enable the local cpu apics */
+	setup_lapic();
 
 #if CONFIG_LOGICAL_CPUS == 1
-  siblings = cpuid_ecx(0x80000008) & 0xff;
-
-  if (siblings > 0) {
-    msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
-    msr.lo |= 1 << 28;
-    wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
-
-    msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
-    msr.hi |= 1 << (33 - 32);
-    wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
-  }
-  printk(BIOS_DEBUG, "siblings = %02d, ", siblings);
+	siblings = cpuid_ecx(0x80000008) & 0xff;
+
+	if (siblings > 0) {
+		msr = rdmsr_amd(CPU_ID_FEATURES_MSR);
+		msr.lo |= 1 << 28;
+		wrmsr_amd(CPU_ID_FEATURES_MSR, msr);
+
+		msr = rdmsr_amd(CPU_ID_EXT_FEATURES_MSR);
+		msr.hi |= 1 << (33 - 32);
+		wrmsr_amd(CPU_ID_EXT_FEATURES_MSR, msr);
+	}
 #endif
 
-  /* DisableCf8ExtCfg */
-  msr = rdmsr(NB_CFG_MSR);
-  msr.hi &= ~(1 << (46 - 32));
-  wrmsr(NB_CFG_MSR, msr);
+	/* DisableCf8ExtCfg */
+	msr = rdmsr(NB_CFG_MSR);
+	msr.hi &= ~(1 << (46 - 32));
+	wrmsr(NB_CFG_MSR, msr);
 
+	/* Write protect SMM space with SMMLOCK. */
+	msr = rdmsr(HWCR_MSR);
+	msr.lo |= (1 << 0);
+	wrmsr(HWCR_MSR, msr);
 
-  /* Write protect SMM space with SMMLOCK. */
-  msr = rdmsr(HWCR_MSR);
-  msr.lo |= (1 << 0);
-  wrmsr(HWCR_MSR, msr);
+	printk(BIOS_SPEW, "%s done.\n", __func__);
 }
 
 static struct device_operations cpu_dev_ops = {
-  .init = model_14_init,
+	.init = model_14_init,
 };
 
 static struct cpu_device_id cpu_table[] = {
-  { X86_VENDOR_AMD, 0x500f00 },   /* ON-A0 */
-  { X86_VENDOR_AMD, 0x500f01 },   /* ON-A1 */
-  { X86_VENDOR_AMD, 0x500f10 },   /* ON-B0 */
-  { X86_VENDOR_AMD, 0x500f20 },   /* ON-C0 */
-  { 0, 0 },
+	{ X86_VENDOR_AMD, 0x500f00 },   /* ON-A0 */
+	{ X86_VENDOR_AMD, 0x500f01 },   /* ON-A1 */
+	{ X86_VENDOR_AMD, 0x500f10 },   /* ON-B0 */
+	{ X86_VENDOR_AMD, 0x500f20 },   /* ON-C0 */
+	{ 0, 0 },
 };
 
 static const struct cpu_driver model_14 __cpu_driver = {
-  .ops      = &cpu_dev_ops,
-  .id_table = cpu_table,
+	.ops      = &cpu_dev_ops,
+	.id_table = cpu_table,
 };
diff --git a/src/cpu/amd/agesa/s3_resume.c b/src/cpu/amd/agesa/s3_resume.c
new file mode 100644
index 0000000..d67bf80
--- /dev/null
+++ b/src/cpu/amd/agesa/s3_resume.c
@@ -0,0 +1,348 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2012 Advanced Micro Devices, Inc.
+ *
+ * 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 "AGESA.h"
+#include "amdlib.h"
+#include <console/console.h>
+#include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/amd/mtrr.h>
+#include <cpu/x86/cache.h>
+#if CONFIG_WRITE_HIGH_TABLES
+#include <cbmem.h>
+#endif
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <arch/io.h>
+#include <arch/acpi.h>
+#include <string.h>
+#include "Porting.h"
+#include "BiosCallOuts.h"
+#include "s3_resume.h"
+#include "agesawrapper.h"
+
+#ifndef __PRE_RAM__
+#include "spi.h"
+#endif
+
+void restore_mtrr(void)
+{
+	u32 msr;
+	volatile UINT32 *msrPtr = (volatile UINT32 *)S3_DATA_MTRR_POS;
+	msr_t msr_data;
+
+	printk(BIOS_SPEW, "%s\n", __func__);
+
+	disable_cache();
+
+	/* Enable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Now restore the Fixed MTRRs */
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(0x250, msr_data);
+
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(0x258, msr_data);
+
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(0x259, msr_data);
+
+	for (msr = 0x268; msr <= 0x26F; msr++) {
+		msr_data.lo = *msrPtr;
+		msrPtr ++;
+		msr_data.hi = *msrPtr;
+		msrPtr ++;
+		wrmsr(msr, msr_data);
+	}
+
+	/* Disable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Restore the Variable MTRRs */
+	for (msr = 0x200; msr <= 0x20F; msr++) {
+		msr_data.lo = *msrPtr;
+		msrPtr ++;
+		msr_data.hi = *msrPtr;
+		msrPtr ++;
+		wrmsr(msr, msr_data);
+	}
+
+	/* Restore SYSCFG MTRR */
+	msr_data.lo = *msrPtr;
+	msrPtr ++;
+	msr_data.hi = *msrPtr;
+	msrPtr ++;
+	wrmsr(SYS_CFG, msr_data);
+}
+
+inline void *backup_resume(void)
+{
+	unsigned long high_ram_base;
+	void *resume_backup_memory;
+
+	/* Start address of high memory tables */
+	high_ram_base = (u32) get_cbmem_toc();
+
+	/*
+	 * printk(BIOS_DEBUG, "CBMEM TOC is at: %x\n", (u32_t)high_ram_base);
+	 * printk(BIOS_DEBUG, "CBMEM TOC 0-size:%x\n ",(u32_t)(high_ram_base + HIGH_MEMORY_SIZE + 4096));
+	 */
+
+	cbmem_reinit((u64) high_ram_base);
+
+	resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+	if (((u32) resume_backup_memory == 0)
+	    || ((u32) resume_backup_memory == -1)) {
+		printk(BIOS_ERR, "Error: resume_backup_memory: %x\n",
+		       (u32) resume_backup_memory);
+		for (;;) ;
+	}
+
+	return resume_backup_memory;
+}
+
+void move_stack_high_mem(void *resume_backup_memory)
+{
+#if 0
+	u32 *sp, index;
+	__asm__ volatile ("mov %%esp, %0":"=r" (sp)
+			  ::);
+	printk(BIOS_DEBUG, "%x:", (u32) sp);
+	printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[0], sp[1], sp[2], sp[3]);
+	printk(BIOS_DEBUG, "%x:", (u32) (sp + 4));
+	printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[4], sp[5], sp[6], sp[7]);
+	printk(BIOS_DEBUG, "%x:", (u32) (sp + 8));
+	printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[8], sp[9], sp[10], sp[11]);
+#endif
+
+	memcopy_fast(resume_backup_memory, (void *)BSP_STACK_BASE_ADDR,
+		(HIGH_SCRATCH_MEMORY_SIZE - BIOS_HEAP_SIZE));
+
+	__asm__
+	    volatile ("add	%0, %%esp; add %0, %%ebp; invd"::"g"
+		      (resume_backup_memory - BSP_STACK_BASE_ADDR)
+		      :);
+
+#if 0
+	__asm__ volatile ("mov %%esp, %0":"=r" (sp)
+			  ::);
+	printk(BIOS_DEBUG, "%x:", (u32) sp);
+	printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[0], sp[1], sp[2], sp[3]);
+	printk(BIOS_DEBUG, "%x:", (u32) (sp + 4));
+	printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[4], sp[5], sp[6],sp[7]);
+	printk(BIOS_DEBUG, "%x:", (u32) (sp + 8));
+	printk(BIOS_DEBUG, "[%08x,%08x,%08x,%08x]\n", sp[8], sp[9], sp[10], sp[11]);
+#endif
+}
+
+void OemAgesaSaveMtrr(void)
+{
+#ifndef __PRE_RAM__
+	u32 spi_address;
+	msr_t  msr_data;
+	device_t dev;
+	u32 nvram_pos = S3_DATA_MTRR_POS;
+	u32 i;
+
+	dev = dev_find_slot(0, PCI_DEVFN(0x14, 3));
+	spi_address = pci_read_config32(dev, 0xA0) & ~0x1F;
+
+	/* Enable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo |= SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Fixed MTRRs */
+	msr_data = rdmsr(0x250);
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+	nvram_pos += 4;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+	nvram_pos += 4;
+
+	msr_data = rdmsr(0x258);
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+	nvram_pos += 4;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+	nvram_pos += 4;
+
+	msr_data = rdmsr(0x259);
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+	nvram_pos += 4;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+	nvram_pos += 4;
+
+	for (i = 0x268; i < 0x270; i++) {
+		msr_data = rdmsr(i);
+		dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+		nvram_pos += 4;
+		dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+		nvram_pos += 4;
+	}
+
+	/* Disable access to AMD RdDram and WrDram extension bits */
+	msr_data = rdmsr(SYS_CFG);
+	msr_data.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
+	wrmsr(SYS_CFG, msr_data);
+
+	/* Variable MTRRs */
+	for (i = 0x200; i < 0x210; i++) {
+		msr_data = rdmsr(i);
+		dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+		nvram_pos += 4;
+		dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+		nvram_pos += 4;
+	}
+
+	/* SYS_CFG */
+	msr_data = rdmsr(0xC0010010);
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+	nvram_pos += 4;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+	nvram_pos += 4;
+
+	/* TOM */
+	msr_data = rdmsr(0xC001001A);
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+	nvram_pos += 4;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+	nvram_pos += 4;
+
+	/* TOM2 */
+	msr_data = rdmsr(0xC001001D);
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.lo);
+	nvram_pos += 4;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos, msr_data.hi);
+	nvram_pos += 4;
+
+#endif
+}
+
+void OemAgesaGetS3Info(S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data)
+{
+	AMD_CONFIG_PARAMS StdHeader;
+	if (S3DataType == S3DataTypeNonVolatile) {
+		*Data = (void *)S3_DATA_NONVOLATILE_POS;
+		*DataSize = *(UINTN *) (*Data);
+		*Data += 4;
+	} else {
+		*DataSize = *(UINTN *) S3_DATA_VOLATILE_POS;
+		*Data = (void *) GetHeapBase(&StdHeader);
+		memcopy_fast((void *)(*Data), (void *)(S3_DATA_VOLATILE_POS + 4), *DataSize);
+	}
+}
+
+u32 OemAgesaSaveS3Info(S3_DATA_TYPE S3DataType, u32 DataSize, void *Data)
+{
+
+	u32 pos = S3_DATA_VOLATILE_POS;
+#ifndef __PRE_RAM__
+	u32 spi_address, data;
+	u32 nvram_pos;
+	device_t dev;
+#endif
+
+	if (S3DataType == S3DataTypeNonVolatile) {
+		pos = S3_DATA_NONVOLATILE_POS;
+	} else {		/* S3DataTypeVolatile */
+		pos = S3_DATA_VOLATILE_POS;
+	}
+
+#ifndef __PRE_RAM__
+	dev = dev_find_slot(0, PCI_DEVFN(0x14, 3));
+	spi_address = pci_read_config32(dev, 0xA0) & ~0x1F;
+
+	/* printk(BIOS_DEBUG, "spi_address=%x\n", spi_address); */
+	readSPIID((u8 *) spi_address);
+	writeSPIStatus((u8 *)spi_address, 0);
+	if (S3DataType == S3DataTypeNonVolatile) {
+		sectorEraseSPI((u8 *) spi_address, S3_DATA_NONVOLATILE_POS);
+	} else {
+		sectorEraseSPI((u8 *) spi_address, S3_DATA_VOLATILE_POS);
+		sectorEraseSPI((u8 *) spi_address,
+			       S3_DATA_VOLATILE_POS + 0x1000);
+		sectorEraseSPI((u8 *) spi_address,
+			       S3_DATA_VOLATILE_POS + 0x2000);
+		sectorEraseSPI((u8 *) spi_address,
+			       S3_DATA_VOLATILE_POS + 0x3000);
+	}
+
+	nvram_pos = 0;
+	dwordnoneAAIProgram((u8 *) spi_address, nvram_pos + pos, DataSize);
+
+	for (nvram_pos = 0; nvram_pos < DataSize; nvram_pos += 4) {
+		data = *(u32 *) (Data + nvram_pos);
+		dwordnoneAAIProgram((u8 *) spi_address, nvram_pos + pos + 4,
+				    *(u32 *) (Data + nvram_pos));
+	}
+#endif
+
+	return AGESA_SUCCESS;
+}
+
+void set_resume_cache(void)
+{
+	msr_t msr;
+
+	/* disable fixed mtrr for now,  it will be enabled by mtrr restore */
+	msr = rdmsr(SYSCFG_MSR);
+	msr.lo &= ~(SYSCFG_MSR_MtrrFixDramEn | SYSCFG_MSR_MtrrFixDramModEn);
+	wrmsr(SYSCFG_MSR, msr);
+
+	/* Enable caching for 0 - coreboot ram using variable mtrr */
+	msr.lo = 0 | MTRR_TYPE_WRBACK;
+	msr.hi = 0;
+	wrmsr(MTRRphysBase_MSR(0), msr);
+	msr.lo = ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid;
+	msr.hi = (1 << (CONFIG_CPU_ADDR_BITS - 32)) - 1;
+	wrmsr(MTRRphysMask_MSR(0), msr);
+
+	/* Set the default memory type and disable fixed and enable variable MTRRs */
+	msr.hi = 0;
+	msr.lo = (1 << 11);
+	wrmsr(MTRRdefType_MSR, msr);
+
+	enable_cache();
+}
+
+void s3_resume(void)
+{
+	int status;
+
+	printk(BIOS_DEBUG, "agesawrapper_amds3laterestore ");
+	status = agesawrapper_amds3laterestore();
+	if (status)
+		printk(BIOS_DEBUG, "error level: %x \n", (u32) status);
+	else
+		printk(BIOS_DEBUG, "passed.\n");
+}
diff --git a/src/cpu/amd/agesa/s3_resume.h b/src/cpu/amd/agesa/s3_resume.h
new file mode 100644
index 0000000..a62f90e
--- /dev/null
+++ b/src/cpu/amd/agesa/s3_resume.h
@@ -0,0 +1,42 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2011 Advanced Micro Devices, Inc.
+ *
+ * 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
+ */
+
+#ifndef S3_RESUME_H
+#define S3_RESUME_H
+
+#define S3_DATA_NONVOLATILE_POS	0xFFFF4000
+#define S3_DATA_VOLATILE_POS	0xFFFF0000
+#define S3_DATA_MTRR_POS	0xFFFF3100
+
+typedef enum {
+	S3DataTypeNonVolatile=0,            ///< NonVolatile Data Type
+	S3DataTypeVolatile                  ///< Volatile Data Type
+} S3_DATA_TYPE;
+
+void restore_mtrr(void);
+void s3_resume(void);
+inline void *backup_resume(void);
+void set_resume_cache(void);
+void move_stack_high_mem(void *resume_backup_memory);
+
+u32 OemAgesaSaveS3Info (S3_DATA_TYPE S3DataType, u32 DataSize, void *Data);
+void OemAgesaGetS3Info (S3_DATA_TYPE S3DataType, u32 *DataSize, void **Data);
+void OemAgesaSaveMtrr (void);
+
+#endif
diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c
index 270c542..74423f2 100644
--- a/src/cpu/amd/car/post_cache_as_ram.c
+++ b/src/cpu/amd/car/post_cache_as_ram.c
@@ -13,22 +13,6 @@ static inline void print_debug_pcar(const char *strval, uint32_t val)
 	printk(BIOS_DEBUG, "%s%08x\n", strval, val);
 }
 
-/* from linux kernel 2.6.32 asm/string_32.h */
-
-static void inline __attribute__((always_inline))  memcopy(void *dest, const void *src, unsigned long bytes)
-{
-	int d0, d1, d2;
-	asm volatile("cld ; rep ; movsl\n\t"
-			"movl %4,%%ecx\n\t"
-			"andl $3,%%ecx\n\t"
-			"jz 1f\n\t"
-			"rep ; movsb\n\t"
-			"1:"
-			: "=&c" (d0), "=&D" (d1), "=&S" (d2)
-			: "0" (bytes / 4), "g" (bytes), "1" ((long)dest), "2" ((long)src)
-			: "memory", "cc");
-}
-
 #if CONFIG_HAVE_ACPI_RESUME == 1
 
 static inline void *backup_resume(void) {
@@ -58,7 +42,7 @@ static inline void *backup_resume(void) {
 	if (resume_backup_memory) {
 		print_debug_pcar("Will copy coreboot region to: ", (uint32_t) resume_backup_memory);
 		/* copy only backup only memory used for CAR */
-		memcopy(resume_backup_memory+HIGH_MEMORY_SAVE-CONFIG_DCACHE_RAM_SIZE,
+		memcopy_fast(resume_backup_memory+HIGH_MEMORY_SAVE-CONFIG_DCACHE_RAM_SIZE,
 			(void *)((CONFIG_RAMTOP)-CONFIG_DCACHE_RAM_SIZE),
 			 CONFIG_DCACHE_RAM_SIZE); //inline
 	}
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index 2ccb38a..59ccff6 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -650,6 +650,10 @@ void pci_dev_set_subsystem(struct device *dev, unsigned vendor, unsigned device)
 			   ((device & 0xffff) << 16) | (vendor & 0xffff));
 }
 
+#if CONFIG_HAVE_ACPI_RESUME == 1
+extern u8 acpi_slp_type;
+#endif
+
 /** Default handler: only runs the relevant PCI BIOS. */
 void pci_dev_init(struct device *dev)
 {
@@ -664,6 +668,12 @@ void pci_dev_init(struct device *dev)
 	    ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA))
 		return;
 
+#if CONFIG_HAVE_ACPI_RESUME == 1
+	/* Don't re-run roms on s3 resume. */
+	if (acpi_slp_type == 3)
+		return;
+#endif
+
 	rom = pci_rom_probe(dev);
 	if (rom == NULL)
 		return;
diff --git a/src/include/cbmem.h b/src/include/cbmem.h
index 7c5ec07..b7207b9 100644
--- a/src/include/cbmem.h
+++ b/src/include/cbmem.h
@@ -25,11 +25,16 @@
 extern uint64_t high_tables_base, high_tables_size;
 
 #if CONFIG_HAVE_ACPI_RESUME
-#define HIGH_MEMORY_SIZE	((CONFIG_RAMTOP - CONFIG_RAMBASE) + HIGH_MEMORY_DEF_SIZE)
-#define HIGH_MEMORY_SAVE	( HIGH_MEMORY_SIZE - HIGH_MEMORY_DEF_SIZE )
+#ifdef CONFIG_RESUME_SCRATCH_MEMORY_SIZE
+#define HIGH_SCRATCH_MEMORY_SIZE	CONFIG_RESUME_SCRATCH_MEMORY_SIZE
 #else
-#define HIGH_MEMORY_SIZE	HIGH_MEMORY_DEF_SIZE
+#define HIGH_SCRATCH_MEMORY_SIZE	0
 #endif
+#define HIGH_MEMORY_SAVE	(CONFIG_RAMTOP - CONFIG_RAMBASE)
+#define HIGH_MEMORY_SIZE	(HIGH_MEMORY_SAVE + HIGH_SCRATCH_MEMORY_SIZE + HIGH_MEMORY_DEF_SIZE)
+#else /* CONFIG_HAVE_ACPI_RESUME */
+#define HIGH_MEMORY_SIZE	HIGH_MEMORY_DEF_SIZE
+#endif /* CONFIG_HAVE_ACPI_RESUME */
 
 #define CBMEM_ID_FREESPACE	0x46524545
 #define CBMEM_ID_GDT		0x4c474454
diff --git a/src/include/string.h b/src/include/string.h
index 2168947..234f848 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -8,6 +8,7 @@ void *memcpy(void *dest, const void *src, size_t n);
 void *memmove(void *dest, const void *src, size_t n);
 void *memset(void *s, int c, size_t n);
 int memcmp(const void *s1, const void *s2, size_t n);
+void inline __attribute__((always_inline))  memcopy_fast(void *dest, const void *src, unsigned long bytes);
 #if !defined(__PRE_RAM__)
 int sprintf(char * buf, const char *fmt, ...);
 #endif
diff --git a/src/lib/cbmem.c b/src/lib/cbmem.c
index 202f521..18f05b5 100644
--- a/src/lib/cbmem.c
+++ b/src/lib/cbmem.c
@@ -176,6 +176,8 @@ void *cbmem_find(u32 id)
 		return NULL;
 
 	for (i = 0; i < MAX_CBMEM_ENTRIES; i++) {
+		printk(BIOS_SPEW, "CBMEM TOC ID %d is: %x base: %x%x\n", i,
+		      (u32) cbmem_toc[i].id, (u32) (cbmem_toc[i].base >> 32), (u32) cbmem_toc[i].base);
 		if (cbmem_toc[i].id == id)
 			return (void *)(unsigned long)cbmem_toc[i].base;
 	}
diff --git a/src/lib/memcpy.c b/src/lib/memcpy.c
index 1053a53..217f73b 100644
--- a/src/lib/memcpy.c
+++ b/src/lib/memcpy.c
@@ -10,3 +10,18 @@ void *memcpy(void *vdest, const void *vsrc, size_t bytes)
 
 	return vdest;
 }
+
+/* from linux kernel 2.6.32 asm/string_32.h */
+void inline __attribute__((always_inline))  memcopy_fast(void *dest, const void *src, unsigned long bytes)
+{
+	int d0, d1, d2;
+	asm volatile("cld ; rep ; movsl\n\t"
+			"movl %4,%%ecx\n\t"
+			"andl $3,%%ecx\n\t"
+			"jz 1f\n\t"
+			"rep ; movsb\n\t"
+			"1:"
+			: "=&c" (d0), "=&D" (d1), "=&S" (d2)
+			: "0" (bytes / 4), "g" (bytes), "1" ((long)dest), "2" ((long)src)
+			: "memory", "cc");
+}
diff --git a/src/northbridge/amd/agesa/family14/northbridge.c b/src/northbridge/amd/agesa/family14/northbridge.c
index b2ca256..759f0c2 100644
--- a/src/northbridge/amd/agesa/family14/northbridge.c
+++ b/src/northbridge/amd/agesa/family14/northbridge.c
@@ -28,6 +28,7 @@
 #include <string.h>
 #include <bitops.h>
 #include <cpu/cpu.h>
+#include <cbmem.h>
 
 #include <cpu/x86/lapic.h>
 
@@ -332,11 +333,6 @@ static struct hw_mem_hole_info get_hw_mem_hole_info(void)
 }
 #endif
 
-#if CONFIG_WRITE_HIGH_TABLES==1
-#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
-extern uint64_t high_tables_base, high_tables_size;
-#endif
-
 #if CONFIG_GFXUMA == 1
 extern uint64_t uma_memory_base, uma_memory_size;
 
@@ -691,12 +687,12 @@ printk(BIOS_DEBUG, "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",  mmi
                     if (high_tables_base==0) {
                     /* Leave some space for ACPI, PIRQ and MP tables */
 #if CONFIG_GFXUMA == 1
-                        high_tables_base = uma_memory_base - (HIGH_TABLES_SIZE * 1024);
+                        high_tables_base = uma_memory_base - HIGH_MEMORY_SIZE;
 #else
-                        high_tables_base = (mmio_basek - HIGH_TABLES_SIZE) * 1024;
+                        high_tables_base = (mmio_basek * 1024) - HIGH_MEMORY_SIZE;
 #endif
-                        high_tables_size = HIGH_TABLES_SIZE * 1024;
-                        printk(BIOS_DEBUG, " split: %dK table at =%08llx\n", HIGH_TABLES_SIZE,
+                        high_tables_size = HIGH_MEMORY_SIZE;
+                        printk(BIOS_DEBUG, " split: %dK table at =%08llx\n", (u32)high_tables_size,
                                  high_tables_base);
                     }
 #endif
@@ -721,17 +717,18 @@ printk(BIOS_DEBUG, "adsr: mmio_basek=%08lx, basek=%08llx, limitk=%08llx\n",  mmi
         if (high_tables_base==0) {
         /* Leave some space for ACPI, PIRQ and MP tables */
 #if CONFIG_GFXUMA == 1
-            high_tables_base = uma_memory_base - (HIGH_TABLES_SIZE * 1024);
-            printk(BIOS_DEBUG, "  adsr - uma_memory_base = %llx.\n",uma_memory_base);
+		high_tables_base = uma_memory_base - HIGH_MEMORY_SIZE;
+		printk(BIOS_DEBUG, "  adsr - uma_memory_base = %llx, ",uma_memory_base);
 #else
-            high_tables_base = (limitk - HIGH_TABLES_SIZE) * 1024;
+		high_tables_base = (limitk * 1024)- HIGH_MEMORY_SIZE;
 #endif
-            high_tables_size = HIGH_TABLES_SIZE * 1024;
-        }
+		high_tables_size = HIGH_MEMORY_SIZE;
+		}
 #endif
     }
 printk(BIOS_DEBUG, "  adsr - mmio_basek = %lx.\n",mmio_basek);
 printk(BIOS_DEBUG, "  adsr - high_tables_size = %llx.\n",high_tables_size);
+printk(BIOS_DEBUG, "  adsr - high_tables_base=%x%x\n", (u32) (high_tables_base >> 32), (u32) high_tables_base);
 
 #if CONFIG_GFXUMA == 1
     printk(BIOS_DEBUG, "adsr - adding uma resource.\n");
@@ -746,22 +743,46 @@ printk(BIOS_DEBUG, "  adsr - high_tables_size = %llx.\n",high_tables_size);
 printk(BIOS_DEBUG, "  adsr - leaving this lovely routine.\n");
 }
 
+extern u8 acpi_slp_type;
 
 static void domain_enable_resources(device_t dev)
 {
   u32 val;
 
 #if CONFIG_AMD_SB_CIMX
+  #if CONFIG_HAVE_ACPI_RESUME == 1
+  if (acpi_slp_type != 3) {
+	  sb_After_Pci_Init();
+	  sb_Mid_Post_Init();
+  } else {
+	  sb_After_Pci_Restore_Init();
+  }
+  #else
   sb_After_Pci_Init();
   sb_Mid_Post_Init();
+  #endif
 #endif
 
   /* Must be called after PCI enumeration and resource allocation */
   printk(BIOS_DEBUG, "\nFam14h - domain_enable_resources: AmdInitMid.\n");
-  val = agesawrapper_amdinitmid ();
-  if(val) {
-    printk(BIOS_DEBUG, "agesawrapper_amdinitmid failed: %x \n", val);
+
+#if CONFIG_HAVE_ACPI_RESUME == 1
+  if (acpi_slp_type != 3) {
+	printk(BIOS_DEBUG, "agesawrapper_amdinitmid ");
+	val = agesawrapper_amdinitmid ();
+	if (val)
+		printk(BIOS_DEBUG, "error level: %x \n", val);
+	else
+		printk(BIOS_DEBUG, "passed.\n");
   }
+#else
+  printk(BIOS_DEBUG, "agesawrapper_amdinitmid ");
+  val = agesawrapper_amdinitmid ();
+  if (val)
+	  printk(BIOS_DEBUG, "error level: %x \n", val);
+  else
+	  printk(BIOS_DEBUG, "passed.\n");
+#endif
 
   printk(BIOS_DEBUG, "  ader - leaving domain_enable_resources.\n");
 }
@@ -795,24 +816,41 @@ static void cpu_bus_set_resources(device_t dev)
     pci_dev_set_resources(dev);
 }
 
-static void cpu_bus_init(device_t dev)
+static u32 cpu_bus_scan(device_t dev, u32 max)
 {
-	struct device_path cpu_path;
 	device_t cpu;
-    int apic_id;
-
-    initialize_cpus(dev->link_list);
+	struct device_path cpu_path;
+	int apic_id, cores_found;
+
+	/* There is only one node for fam14, but there may be multiple cores. */
+	cpu = dev_find_slot(0, PCI_DEVFN(0x18, 0));
+	if (!cpu)
+		printk(BIOS_ERR, "ERROR: %02x:%02x.0 not found", 0, 0x18);
+
+	cores_found = (pci_read_config32(dev_find_slot(0,PCI_DEVFN(0x18,0x3)), 0xe8) >> 12) & 3;
+	printk(BIOS_DEBUG, "  AP siblings=%d\n", cores_found);
+
+
+	for (apic_id = 0; apic_id <= cores_found; apic_id++) {
+		cpu_path.type = DEVICE_PATH_APIC;
+		cpu_path.apic.apic_id = apic_id;
+		cpu = alloc_find_dev(dev->link_list, &cpu_path);
+		if (cpu) {
+			cpu->enabled = 1;
+			cpu->path.apic.node_id = 0;
+			cpu->path.apic.core_id = apic_id;
+			printk(BIOS_DEBUG, "CPU: %s %s\n",
+					dev_path(cpu), cpu->enabled?"enabled":"disabled");
+		} else {
+			cpu->enabled = 0;
+		}
+	}
+	return max;
+}
 
-	/* Build the AP cpu device path(s) */
-    for (apic_id = 1; apic_id < CONFIG_MAX_CPUS; apic_id++) {
-	    cpu_path.type = DEVICE_PATH_APIC;
-	    cpu_path.apic.apic_id = apic_id;
-    	cpu = alloc_dev(dev->link_list, &cpu_path);
-        if (!cpu) return;
-        cpu->enabled = 1;
-    	cpu->path.apic.node_id = 0;
-    	cpu->path.apic.core_id = apic_id;
-    }
+static void cpu_bus_init(device_t dev)
+{
+	initialize_cpus(dev->link_list);
 }
 
 
@@ -858,7 +896,7 @@ static struct device_operations cpu_bus_ops = {
     .set_resources    = cpu_bus_set_resources,
     .enable_resources = NULL,
     .init             = cpu_bus_init,
-    .scan_bus         = NULL,
+    .scan_bus         = cpu_bus_scan,
 };
 
 




More information about the coreboot mailing list