Patchwork [2/3] Use ACPI table area to store cbmem_toc pointer needed for resume

login
register
about
Submitter Tobias Diedrich
Date 2010-12-01 19:46:57
Message ID <20101201210354.952358768@yamamaya.is-a-geek.org>
Download mbox | patch
Permalink /patch/2376/
State Superseded
Headers show

Comments

Tobias Diedrich - 2010-12-01 19:46:57
This adds a cbmem_toc_ptr_t structure, which is written just below the FADT,
so we can find it using the FADP information.  The actual writing is only
implemented for the Intel 82371EB southbridge.

Also adds code to acpi.c resume codepath to use this pointer when the chipset
has not overridden the weak get_cbmem_toc() function.

Effectively the latter part affects all boards that already implement ACPI S2
or S3 resume, but shouldn't change behaviour since none of them generate the
structure:

asus/m2v
asus/m4a785-m
asus/m2v-mx_se
gigabyte/ma78gm
gigabyte/ma785gmt
jetway/pa78vm5
iwill/dk8_htx
asrock/939a785gmh
amd/dbm690t
amd/mahogany
amd/tilapia_fam10
amd/pistachio
amd/serengeti_cheetah_fam10
amd/serengeti_cheetah
amd/mahogany_fam10
kontron/kt690
iei/kino-780am2-fam10
technexion/tim5690
technexion/tim8690

BTW, via/epia-m700 defines HAVE_ACPI_TABLES, but does not supply a dsdt.asl
(only a get_dsdt script)

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

---
Rudolf Marek - 2010-12-01 21:24:03
Hi,

In fact I was thinking that we can add custom "OEMx" tables to ACPI and dump 
them using acpi tools. I mean we can add the hooks to ACPI so cbmem stuff is 
available per table in ACPI.

The AMD chipsets needs to use NVRAM because there is stored DQS driving values 
for memory controller. Also the cbmem address is stored there because one cannot 
find it very easily if there is frambuffer (and on AMD all access is uncached 
that time). This NVRAM is not CMOS it is just 256 bytes of storage which 
survives S3 state.

Thanks,
Rudolf
Stefan Reinauer - 2010-12-03 02:55:27
On 01.12.2010, at 11:46, Tobias Diedrich <ranma+coreboot@tdiedrich.de> wrote:

> This adds a cbmem_toc_ptr_t structure, which is written just below the FADT,
> so we can find it using the FADP information.  The actual writing is only
> implemented for the Intel 82371EB southbridge.

Why is that needed?

Stefan

>
Tobias Diedrich - 2010-12-03 12:47:56
Stefan Reinauer wrote:
> On 01.12.2010, at 11:46, Tobias Diedrich <ranma+coreboot@tdiedrich.de> wrote:
> 
> > This adds a cbmem_toc_ptr_t structure, which is written just below the FADT,
> > so we can find it using the FADP information.  The actual writing is only
> > implemented for the Intel 82371EB southbridge.
> 
> Why is that needed?

There needs to be some way to find the backup area needed for saving
the memory parts that will be overwritten by coreboot after
disabling CAR.  I chose to add a structure relative to the FADT
address, because thats rather easy to find.
And as Rudolf already said, maybe this should be
exported as a coreboot-specific ACPI table (but that would make
finding it a tad bit more complex I think).
Another option would be to always use a fixed area directly after 1MB
(as this should not be affected by framebuffers in main memory) instead of
below TOM.
Rudolf Marek - 2010-12-04 14:20:23
> Another option would be to always use a fixed area directly after 1MB
> (as this should not be affected by framebuffers in main memory) instead of
> below TOM.
Nope the memory must be free (and not reserved) all bootloaders expect that it 
is free. ACPI specs says first hole can be 15-16MB.

Thanks,
Rudolf

Patch

Index: src/arch/i386/boot/acpi.c
===================================================================
--- src/arch/i386/boot/acpi.c.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/arch/i386/boot/acpi.c	2010-12-01 19:11:36.000000000 +0100
@@ -517,6 +517,7 @@ 
 	acpi_rsdt_t *rsdt;
 	acpi_facs_t *facs;
 	acpi_fadt_t *fadt;
+	cbmem_toc_ptr_t *cbmem_tocp;
 	void *wake_vec;
 	int i;
 
@@ -537,11 +538,22 @@ 
 		return NULL;
 
 	printk(BIOS_DEBUG, "RSDP found at %p\n", rsdp);
+	cbmem_tocp = (cbmem_toc_ptr_t *)(rsdp->rsdt_address - sizeof(cbmem_toc_ptr_t));
 	rsdt = (acpi_rsdt_t *) rsdp->rsdt_address;
 
 	end = (char *)rsdt + rsdt->header.length;
 	printk(BIOS_DEBUG, "RSDT found at %p ends at %p\n", rsdt, end);
 
+	if (get_cbmem_toc() == 0) { /* Only use cbmem_tocp if there is no chipset override */
+		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;
+		}
+		set_cbmem_toc(cbmem_tocp->ptr);
+	} else {
+		printk(BIOS_DEBUG, "cbmem toc is at %p\n", get_cbmem_toc());
+	}
+
 	for (i = 0; ((char *)&rsdt->entry[i]) < end; i++) {
 		fadt = (acpi_fadt_t *)rsdt->entry[i];
 		if (strncmp((char *)fadt, "FACP", 4) == 0)
Index: src/southbridge/intel/i82371eb/acpi_tables.c
===================================================================
--- src/southbridge/intel/i82371eb/acpi_tables.c.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/southbridge/intel/i82371eb/acpi_tables.c	2010-12-01 19:11:36.000000000 +0100
@@ -26,6 +26,7 @@ 
 #include <arch/smp/mpspec.h>
 #include <device/device.h>
 #include <device/pci_ids.h>
+#include <cbmem.h>
 #include "i82371eb.h"
 
 extern const unsigned char AmlCode[];
@@ -104,6 +105,7 @@ 
 unsigned long __attribute__((weak)) write_acpi_tables(unsigned long start)
 {
 	unsigned long current;
+	cbmem_toc_ptr_t *cbmem_tocp;
 	acpi_rsdp_t *rsdp;
 	acpi_rsdt_t *rsdt;
 	acpi_fadt_t *fadt;
@@ -113,20 +115,28 @@ 
 	acpi_header_t *dsdt;
 
 	/* Align ACPI tables to 16 byte. */
-	start = (start + 0x0f) & -0x10;
-	current = start;
+	current = ALIGN(start, 16);
 
 	printk(BIOS_INFO, "ACPI: Writing ACPI tables at %lx...\n", start);
 
 	/* We need at least an RSDP and an RSDT table. */
 	rsdp = (acpi_rsdp_t *) current;
 	current += sizeof(acpi_rsdp_t);
+
+	/* put cbmem toc ptr structure directly below rsdt */
+	printk(BIOS_INFO, "ACPI: Writing cbmem_toc pointer at %lx...\n", current);
+	cbmem_tocp = (cbmem_toc_ptr_t *) current;
+	current += sizeof(cbmem_toc_ptr_t);
+
 	rsdt = (acpi_rsdt_t *) current;
 	current += sizeof(acpi_rsdt_t);
 
 	/* Clear all table memory. */
 	memset((void *) start, 0, current - start);
 
+	cbmem_tocp->sig = CBMEM_TOC_PTR_SIG;
+	cbmem_tocp->ptr = get_cbmem_toc();
+
 	acpi_write_rsdp(rsdp, rsdt, NULL);
 	acpi_write_rsdt(rsdt);
 
Index: src/include/cbmem.h
===================================================================
--- src/include/cbmem.h.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/include/cbmem.h	2010-12-01 19:11:36.000000000 +0100
@@ -39,6 +39,13 @@ 
 #define CBMEM_ID_RESUME		0x5245534d
 #define CBMEM_ID_NONE		0x00000000
 
+#define CBMEM_TOC_PTR_SIG	0x43425443
+
+typedef struct cbmem_toc_ptr {
+	u32 sig;
+	void *ptr;
+} __attribute__((packed)) cbmem_toc_ptr_t;
+
 void cbmem_initialize(void);
 
 void cbmem_init(u64 baseaddr, u64 size);
Index: src/lib/cbmem.c
===================================================================
--- src/lib/cbmem.c.orig	2010-12-01 19:11:35.000000000 +0100
+++ src/lib/cbmem.c	2010-12-01 19:11:36.000000000 +0100
@@ -52,6 +52,9 @@ 
 
 static struct cbmem_entry *bss_cbmem_toc;
 
+/* chipset can override get/set_cbmem_toc to store the cbmem_toc address
+ * in nvram if available */
+
 struct cbmem_entry *__attribute__((weak)) get_cbmem_toc(void)
 {
 	return bss_cbmem_toc;
@@ -59,7 +62,7 @@ 
 
 void __attribute__((weak)) set_cbmem_toc(struct cbmem_entry * x)
 {
-	/* do nothing, this should be called by chipset to save TOC in NVRAM */
+	bss_cbmem_toc = x;
 }
 
 #endif