[coreboot] [patch 3/3] Implement post_main/post_cache_as_ram resume hooks for romstage on Intel and use them for Slot-1 cpus if CONFIG_GENERATE_ACPI_TABLES=y. (rediffed against r6176)

Tobias Diedrich ranma+coreboot at tdiedrich.de
Mon Dec 13 23:46:11 CET 2010


Rediffed against r6176 to account for renames.

Slot-1 boards:
asus/p3b-f
asus/p2b-ds
asus/p2b-f
asus/p2b-d
asus/p2b
asus/p2b-ls
azza/pt-6ibd
gigabyte/ga-6bxc
gigabyte/ga-6bxe
compaq/deskpro_en_sff_p600
a-trend/atc-6220
a-trend/atc-6240
tyan/s1846
msi/ms6119
msi/ms6147
msi/ms6156
soyo/sy-6ba-plus-iii
abit/be6-ii_v2_0
biostar/m6tba

Slot-1 boards with HAVE_ACPI_TABLES:
asus/p2b

Abuild-tested.
Tested on P2B (Slot1 440BX/82371EB).
Tested on M2V (Socket AM2/K8T890/VT8237A) to make sure S3 still works with all
3 patches applied.

(Rediffed patchset only non-abuild compile-tested due to hw
currently not being accessible).

Signed-off-by: Tobias Diedrich <ranma+coreboot at tdiedrich.de>

---

Index: src/northbridge/intel/i440bx/northbridge.c
===================================================================
--- src/northbridge/intel/i440bx/northbridge.c.orig	2010-12-13 23:34:06.190921624 +0100
+++ src/northbridge/intel/i440bx/northbridge.c	2010-12-13 23:34:14.042912591 +0100
@@ -9,6 +9,7 @@
 #include <bitops.h>
 #include <cpu/cpu.h>
 #include <pc80/keyboard.h>
+#include <cbmem.h>
 #include "chip.h"
 #include "northbridge.h"
 #include "i440bx.h"
Index: src/cpu/intel/car/post_cache_as_ram.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/cpu/intel/car/post_cache_as_ram.c	2010-12-13 23:35:22.327299572 +0100
@@ -0,0 +1,240 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * original idea yhlu 6.2005 (assembler code)
+ *
+ * Copyright (C) 2010 Rudolf Marek <r.marek at 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
+ *
+ * be warned, this file will be used other cores and core 0 / node 0
+ */
+#include <string.h>
+#include <arch/stages.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include <arch/acpi.h>
+#include <cbmem.h>
+#include "cpu/x86/mtrr/earlymtrr.c"
+
+#if CONFIG_RAMTOP <= 0x100000
+	#error "You need to set CONFIG_RAMTOP greater than 1M"
+#endif
+
+#define DCACHE_RAM_BASE (CONFIG_DCACHE_RAM_TOP - CONFIG_DCACHE_RAM_SIZE)
+
+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");
+}
+
+static u8 acpi_checksum(u8 *table, u32 length)
+{
+	u8 ret = 0;
+	while (length--) {
+		ret += *table;
+		table++;
+	}
+	return -ret;
+}
+
+static int valid_rsdp(acpi_rsdp_t *rsdp)
+{
+	unsigned *sig;
+	sig = (void*)rsdp;
+	if (*sig != 0x20445352)
+		return 0;
+	sig++;
+	if (*sig != 0x20525450)
+		return 0;
+
+	print_debug("Looking on ");
+	print_debug_hex32((u32)rsdp);
+	print_debug(" for valid checksum\n");
+
+	if (acpi_checksum((void *)rsdp, 20) != 0)
+		return 0;
+	print_debug("Checksum 1 passed\n");
+
+	if ((rsdp->revision > 1) &&
+	    (acpi_checksum((void *)rsdp, rsdp->length) != 0))
+		return 0;
+	print_debug("Checksum 2 passed all OK\n");
+
+	return 1;
+}
+
+struct cbmem_entry *get_cbmem_toc(void)
+{
+	char *p;
+	acpi_rsdp_t *rsdp;
+	cbmem_toc_ptr_t *cbmem_tocp;
+
+	print_debug("Trying to find the backup area pointer...\n");
+
+	/* Find RSDP. */
+	rsdp = NULL;
+	for (p = (char *)0xe0000; p < (char *)0xfffff; p += 16) {
+		rsdp = (acpi_rsdp_t *)p;
+		if (valid_rsdp(rsdp))
+			break;
+		rsdp = NULL;
+	}
+
+	if (rsdp == NULL) {
+		print_debug("RSDP not found\n");
+		return NULL;
+	}
+
+	cbmem_tocp = (cbmem_toc_ptr_t *)(rsdp->rsdt_address - sizeof(cbmem_toc_ptr_t));
+	if (cbmem_tocp->sig != CBMEM_TOC_PTR_SIG) {
+		printk(BIOS_DEBUG, "cbmem toc pointer not found at %p (sig %08x sz %d)\n", cbmem_tocp, cbmem_tocp->sig, sizeof(cbmem_toc_ptr_t));
+		return NULL;
+	}
+
+	return cbmem_tocp->ptr;
+}
+
+static 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();
+
+	print_debug_pcar("CBMEM TOC is at: ", high_ram_base);
+	print_debug_pcar("CBMEM TOC 0-size: ", (high_ram_base + HIGH_MEMORY_SIZE + 4096));
+
+	cbmem_reinit((u64)high_ram_base);
+
+	resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+
+	/* copy 1MB - 64K to high tables ram_base to prevent memory corruption
+	 * through stage 2. We could keep stuff like stack and heap in high tables
+	 * memory completely, but that's a wonderful clean up task for another
+	 * day.
+	 */
+
+	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,
+			(void *)((CONFIG_RAMTOP)-CONFIG_DCACHE_RAM_SIZE),
+			 CONFIG_DCACHE_RAM_SIZE); //inline
+	}
+
+	return resume_backup_memory;
+}
+
+void enable_pm(void);
+int acpi_get_sleep_type(void);
+
+void* acpi_resume_post_main(void);
+void acpi_resume_post_cache_as_ram(void *resume_backup_memory);
+
+void* acpi_resume_post_main(void)
+{
+	int sleep_type;
+	void *resume_backup_memory = NULL;
+
+	enable_pm();
+	sleep_type = acpi_get_sleep_type();
+
+#if 1
+	{
+	/* Check value of esp to verify if we have enough rom for stack in Cache as RAM */
+	unsigned v_esp;
+	__asm__ volatile (
+		"movl   %%esp, %0\n\t"
+		: "=a" (v_esp)
+	);
+	print_debug_pcar("v_esp=", v_esp);
+	}
+#endif
+
+	unsigned testx = 0x5a5a5a5a;
+	print_debug_pcar("testx = ", testx);
+
+	/* copy data from cache as ram to
+		ram need to set CONFIG_RAMTOP to 2M and use var mtrr instead.
+	 */
+	if (sleep_type == 2 || sleep_type == 3)
+	 	resume_backup_memory = backup_resume();
+
+	printk(BIOS_DEBUG, "resume_backup_memory=%p\n", resume_backup_memory);
+
+	print_debug("Copying data from cache to RAM -- switching to use RAM as stack... ");
+
+	memcopy((void *)((CONFIG_RAMTOP)-CONFIG_DCACHE_RAM_SIZE), (void *)DCACHE_RAM_BASE, CONFIG_DCACHE_RAM_SIZE); //inline
+
+	__asm__ volatile (
+		/* set new esp */ /* before CONFIG_RAMBASE */
+		"subl   %0, %%esp\n\t"
+		::"a"( (DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)- (CONFIG_RAMTOP) )
+		/* discard all registers (eax is used for %0), so gcc redo everything
+		   after the stack is moved */
+		: "cc", "memory", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp"
+	);
+
+	/* We can put data to stack again */
+
+	/* only global variable sysinfo in cache need to be offset */
+	print_debug("Done\n");
+	print_debug_pcar("testx = ", testx);
+
+	return resume_backup_memory;
+}
+
+void acpi_resume_post_cache_as_ram(void *resume_backup_memory)
+{
+	print_debug("After cache as ram disabled \n");
+	printk(BIOS_DEBUG, "resume_backup_memory=%p\n", resume_backup_memory);
+
+	/* now copy the rest of the area, using the WB method because we already
+	   run normal RAM */
+	if (resume_backup_memory) {
+		memcopy(resume_backup_memory,
+				(void *)(CONFIG_RAMBASE),
+				(CONFIG_RAMTOP) - CONFIG_RAMBASE - CONFIG_DCACHE_RAM_SIZE);
+	}
+
+	print_debug("Clearing initial memory region: ");
+
+	/* clear only coreboot used region of memory. Note: this may break ECC enabled boards */
+	memset((void*) CONFIG_RAMBASE, 0, (CONFIG_RAMTOP) - CONFIG_RAMBASE - CONFIG_DCACHE_RAM_SIZE);
+	print_debug("Done\n");
+
+	/*copy and execute coreboot_ram */
+	copy_and_run(0);
+	/* We will not return */
+
+	print_debug("should not be here -\n");
+	for (;;);
+}
Index: src/cpu/intel/car/cache_as_ram.inc
===================================================================
--- src/cpu/intel/car/cache_as_ram.inc.orig	2010-12-13 23:34:06.238921550 +0100
+++ src/cpu/intel/car/cache_as_ram.inc	2010-12-13 23:34:14.042912591 +0100
@@ -26,8 +26,12 @@
 #include <cpu/x86/mtrr.h>
 #include <cpu/x86/lapic_def.h>
 
+#ifndef CONFIG_DCACHE_RAM_TOP
+#define CONFIG_DCACHE_RAM_TOP	0xd0000
+#endif
+
 #define CacheSize		CONFIG_DCACHE_RAM_SIZE
-#define CacheBase		(0xd0000 - CacheSize)
+#define CacheBase		(CONFIG_DCACHE_RAM_TOP - CacheSize)
 
 	save_bist_result()
 
@@ -325,6 +329,11 @@
 	pushl	%eax  /* BIST */
 	call	main
 
+#if CONFIG_HAVE_ACPI_RESUME && CONFIG_POST_CAR_RESUME
+	call	acpi_resume_post_main
+	pushl	%eax /* save resume_backup_memory pointer */
+#endif
+
 	/* We don't need CAR from now on. */
 
 	disable_cache()
@@ -351,6 +360,13 @@
 
 	enable_cache();
 
+#if CONFIG_HAVE_ACPI_RESUME && CONFIG_POST_CAR_RESUME
+	popl	%eax
+	movl	%esp, %ebp
+	pushl	%eax  /* resume_backup_memory pointer */
+	call	acpi_resume_post_cache_as_ram
+#endif
+
 	/* Clear boot_complete flag. */
 	xorl	%ebp, %ebp
 __main:
Index: src/arch/x86/include/arch/acpi.h
===================================================================
--- src/arch/x86/include/arch/acpi.h.orig	2010-12-13 23:34:06.214921588 +0100
+++ src/arch/x86/include/arch/acpi.h	2010-12-13 23:34:14.042912591 +0100
@@ -357,6 +357,8 @@
 	u8 ec_id[];				/* EC ID  */
 } __attribute__ ((packed)) acpi_ecdt_t;
 
+#if !defined(__PRE_RAM__)
+
 /* These are implemented by the target port or north/southbridge. */
 unsigned long write_acpi_tables(unsigned long addr);
 unsigned long acpi_fill_madt(unsigned long current);
@@ -431,6 +433,8 @@
 /* cpu/intel/speedstep/acpi.c */
 void generate_cpu_entries(void);
 
+#endif // __PRE_RAM__
+
 #else // CONFIG_GENERATE_ACPI_TABLES
 
 #define write_acpi_tables(start) (start)
Index: src/cpu/intel/Makefile.inc
===================================================================
--- src/cpu/intel/Makefile.inc.orig	2010-12-13 23:34:06.298921457 +0100
+++ src/cpu/intel/Makefile.inc	2010-12-13 23:34:14.042912591 +0100
@@ -16,6 +16,7 @@
 subdirs-$(CONFIG_CPU_INTEL_SOCKET_PGA370) += socket_PGA370
 subdirs-$(CONFIG_CPU_INTEL_SLOT_2) += slot_2
 subdirs-$(CONFIG_CPU_INTEL_SLOT_1) += slot_1
+subdirs-$(CONFIG_CPU_INTEL) += car
 
 #socket_mPGA604_533Mhz
 #socket_mPGA604_800Mhz
Index: src/cpu/intel/car/Makefile.inc
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/cpu/intel/car/Makefile.inc	2010-12-13 23:34:14.042912591 +0100
@@ -0,0 +1,21 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2010 Tobias Diedrich <ranma+coreboot at tdiedrich.de>
+##
+## 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; either version 2 of the License, or
+## (at your option) any later version.
+##
+## 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
+##
+
+romstage-$(CONFIG_POST_CAR_RESUME) += post_cache_as_ram.c
Index: src/cpu/intel/Kconfig
===================================================================
--- src/cpu/intel/Kconfig.orig	2010-12-13 23:34:06.290921469 +0100
+++ src/cpu/intel/Kconfig	2010-12-13 23:34:14.042912591 +0100
@@ -28,3 +28,17 @@
 source src/cpu/intel/socket_mPGA604/Kconfig
 source src/cpu/intel/socket_PGA370/Kconfig
 source src/cpu/intel/socket_441/Kconfig
+
+config CPU_INTEL
+	bool
+	default n
+
+config POST_CAR_RESUME
+	bool
+	default n
+
+config DCACHE_RAM_TOP
+	hex
+	default 0xd0000
+	depends on CACHE_AS_RAM
+	depends on CPU_INTEL
Index: src/mainboard/asus/p2b/dsdt.asl
===================================================================
--- src/mainboard/asus/p2b/dsdt.asl.orig	2010-12-13 23:34:06.146921691 +0100
+++ src/mainboard/asus/p2b/dsdt.asl	2010-12-13 23:34:14.042912591 +0100
@@ -40,6 +40,11 @@
 	 */
 	Name (\_S0, Package () { 0x05, 0x05, 0x00, 0x00 })
 	Name (\_S1, Package () { 0x03, 0x03, 0x00, 0x00 })
+	Name (\_S2, Package () { 0x02, 0x02, 0x00, 0x00 })
+	Name (\_S3, Package () { 0x01, 0x01, 0x00, 0x00 })
+	/* Note: S4 would be suspend to disk, which would require smm code,
+	 * but Linux and Windows handle suspend to disk themselves, so we
+	 * don't need this */
 	Name (\_S5, Package () { 0x00, 0x00, 0x00, 0x00 })
 
 	OperationRegion (SIO1, SystemIO, Add(DEFAULT_PMBASE, GPO0), 2)
Index: src/southbridge/intel/i82371eb/Makefile.inc
===================================================================
--- src/southbridge/intel/i82371eb/Makefile.inc.orig	2010-12-13 23:34:06.166921662 +0100
+++ src/southbridge/intel/i82371eb/Makefile.inc	2010-12-13 23:34:14.042912591 +0100
@@ -30,3 +30,4 @@
 
 romstage-y += early_pm.c
 romstage-y += early_smbus.c
+romstage-$(CONFIG_HAVE_ACPI_RESUME) += wakeup.c
Index: src/cpu/intel/slot_1/Kconfig
===================================================================
--- src/cpu/intel/slot_1/Kconfig.orig	2010-12-13 23:34:06.330921409 +0100
+++ src/cpu/intel/slot_1/Kconfig	2010-12-13 23:34:14.042912591 +0100
@@ -20,6 +20,8 @@
 config CPU_INTEL_SLOT_1
 	bool
 	select CACHE_AS_RAM
+	select CPU_INTEL
+	select POST_CAR_RESUME
 
 config DCACHE_RAM_SIZE
 	hex




More information about the coreboot mailing list