Patchwork add proper "memory management" for high table area (aka CBMEM)

login
register
about
Submitter Stefan Reinauer
Date 2009-10-24 22:52:46
Message ID <4AE3853E.80801@coresystems.de>
Download mbox | patch
Permalink /patch/483/
State Accepted
Headers show

Comments

Stefan Reinauer - 2009-10-24 22:52:46
See patch
Peter Stuge - 2009-10-25 14:30:19
Stefan Reinauer wrote:
> CBMEM high table memory manager.

Nice.


> This code adds a very simple toc based memory manager for the high tables area.
> The purpose of this code is to make it simpler and more reliable to find
> certain data structures in memory. This will also make it possible to have ACPI
> S3 Resume working without an ugly hole at 31MB.
> 
> Signed-off-by: Stefan Reinauer <stepan@coresystems.de>

Acked-by: Peter Stuge <peter@stuge.se>


Maybe name it CBMM instead?



> +++ src/include/cbmem.h	(revision 0)
..
> +#if CONFIG_HAVE_ACPI_RESUME
> +#define HIGH_MEMORY_SIZE	( 1024 * 1024 )
> +#define HIGH_MEMORY_SAVE	( HIGH_MEMORY_SIZE - HIGH_MEMORY_TABLES )
> +#else
> +#define HIGH_MEMORY_SIZE	HIGH_MEMORY_TABLES
> +#endif

Note that _HAVE_ in general is meant for when the port has a
capability. It does not mean that the user enabled the capability
during build. Now, ACPI resume is not currently configurable, and I
don't know if it should be, but it's good to be consistent with
naming.


> +++ src/lib/cbmem.c	(revision 0)
..
> +// The CBMEM TOC reserves 512 bytes to keep
> +// the other entries somewhat aligned.
> +// Increase if MAX_CBMEM_ENTRIES exceeds 21
> +#define CBMEM_TOC_RESERVED	512
> +#define MAX_CBMEM_ENTRIES	16

It would be nice if only one of these was explicitly set, and the
other determined by the first.

#define MAX_CBMEM_ENTRIES 16
#define CBMEM_TOC_RESERVED ALIGN_UP(512, (MAX_CBMEM_ENTRIES * sizeof(struct cbmem_entry)))

Or something similar.


> +#define CBMEM_MAGIC		0x434f5245

Maybe CBMM rather than CORE? (with or without rename)


> +++ src/cpu/intel/model_6ex/cache_as_ram_disable.c	(working copy)
..
> -        {
> -        	/* 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)
> -	        );
> -	        printk_spew("v_esp=%08x\r\n", v_esp);
> -        }
> +#if CAR_DEBUG
> +        /* 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"
> +		: "=a" (v_esp)
> +	);
> +	printk_spew("v_esp=%08x\n", v_esp);
> +#endif

I guess this is unrelated, but it looks benign.


> -	if(cpu_reset==0) {
> -#define CLEAR_FIRST_1M_RAM 1
> -#include "cache_as_ram_post.c"
> -	} else {
>  #undef CLEAR_FIRST_1M_RAM 
>  #include "cache_as_ram_post.c"
> -	}

Um?



> +	/* For now: use rambase + 1MB - 64K (counting downwards) as stack. This
> +	 * makes sure that we stay completely within the 1M of memory we
> +	 * preserve with the memcpy above.
> +	 */
> +
> +#ifndef HIGH_MEMORY_SAVE
> +#define HIGH_MEMORY_SAVE ( (1024 - 64) * 1024 )
> +#endif
> +
>  	__asm__ volatile (
> -                /* set new esp */ /* before CONFIG_RAMBASE */
> -                "subl   %0, %%ebp\n\t"
> -                "subl   %0, %%esp\n\t"
> -                ::"a"( (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)- CONFIG_RAMBASE )
> +		"movl %0, %%ebp\n"
> +		"movl %0, %%esp\n"
> +		:: "a" (CONFIG_RAMBASE + HIGH_MEMORY_SAVE)

Uhm again? :)


> -#ifdef DEACTIVATE_CAR
> -		print_debug("Deactivating CAR");
> -#include DEACTIVATE_CAR_FILE
> -		print_debug(" - Done.\r\n");
> -#endif

I guess this happens elsewhere then?


> -		/* We will not return */
>  	}
>  
> -	print_debug("sorry. parachute did not open.\r\n");
> +	/* We will not return */
> +	printk_debug("sorry. parachute did not open.\n");
>  }

Better message please? :) And maybe a die() call?


> +++ src/cpu/intel/model_6fx/cache_as_ram_disable.c	(working copy)

Same stuff as for model_6ex.


> +++ src/arch/i386/boot/tables.c	(working copy)
..
> +	/* Ok, this is a bit hacky still, because some day we want to have this
> +	 * completely dynamic. But right now we are setting fixed sizes. 
> +	 * It's probably still better than the old high_table_base code because
> +	 * now at least we know when we have an overflow in the area.

Maybe make the reserved size determined completely at run time then?


> +#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, 1024 * (1024-64));
> +#endif

So one chunk is only reserved with ACPI_RESUME, but the size from
which reservations are made is always the same? That makes for some
unfortunate asymmetry when that space is almost full.


> +	// Remove before sending upstream
> +	cbmem_list();

Are we upstream? :)


> +++ src/boot/hardwaremain.c	(working copy)
..
> +	/* console_init() MUST PRECEDE ALL printk()! */

What about printk_*() ?


//Peter

Patch

Index: src/include/cbmem.h
===================================================================
--- src/include/cbmem.h	(revision 0)
+++ src/include/cbmem.h	(revision 0)
@@ -0,0 +1,49 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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
+ */
+
+#ifndef _CBMEM_H_
+#define _CBMEM_H_
+
+/* Reserve 64k for ACPI and other tables */
+#define HIGH_MEMORY_TABLES	( 64 * 1024 )
+
+#if CONFIG_HAVE_ACPI_RESUME
+#define HIGH_MEMORY_SIZE	( 1024 * 1024 )
+#define HIGH_MEMORY_SAVE	( HIGH_MEMORY_SIZE - HIGH_MEMORY_TABLES )
+#else
+#define HIGH_MEMORY_SIZE	HIGH_MEMORY_TABLES
+#endif
+
+#define CBMEM_ID_FREESPACE	0x46524545
+#define CBMEM_ID_GDT		0x4c474454
+#define CBMEM_ID_ACPI		0x41435049
+#define CBMEM_ID_CBTABLE	0x43425442
+#define CBMEM_ID_PIRQ		0x49525154
+#define CBMEM_ID_MPTABLE	0x534d5054
+#define CBMEM_ID_RESUME		0x5245534d
+#define CBMEM_ID_NONE		0x00000000
+
+void cbmem_initialize(void);
+
+void cbmem_init(u64 baseaddr, u64 size);
+int cbmem_reinit(u64 baseaddr);
+void *cbmem_add(u32 id, u64 size);
+void *cbmem_find(u32 id);
+
+#endif
Index: src/lib/Makefile.inc
===================================================================
--- src/lib/Makefile.inc	(revision 4842)
+++ src/lib/Makefile.inc	(working copy)
@@ -13,6 +13,7 @@ 
 obj-y += lzma.o
 #obj-y += lzmadecode.o
 obj-y += gcc.o
+obj-y += cbmem.o
 
 initobj-y += uart8250.o
 initobj-y += memset.o
Index: src/lib/Config.lb
===================================================================
--- src/lib/Config.lb	(revision 4842)
+++ src/lib/Config.lb	(working copy)
@@ -18,6 +18,9 @@ 
 object compute_ip_checksum.o
 object version.o
 object gcc.o
+object cbfs.o
+object lzma.o
+object cbmem.o
 
 # Force version.o to recompile every time
 makedefine .PHONY : version.o
@@ -27,5 +30,4 @@ 
 initobject memcpy.o
 initobject memcmp.o
 
-object cbfs.o
-object lzma.o
+
Index: src/lib/cbmem.c
===================================================================
--- src/lib/cbmem.c	(revision 0)
+++ src/lib/cbmem.c	(revision 0)
@@ -0,0 +1,239 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 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 <types.h>
+#include <string.h>
+#include <cbmem.h>
+#include <console/console.h>
+
+#if 1
+#define debug(x...) printk_debug(x)
+#else
+#define debug(x...)
+#endif
+
+// The CBMEM TOC reserves 512 bytes to keep
+// the other entries somewhat aligned.
+// Increase if MAX_CBMEM_ENTRIES exceeds 21
+#define CBMEM_TOC_RESERVED	512
+#define MAX_CBMEM_ENTRIES	16
+#define CBMEM_MAGIC		0x434f5245
+
+static void *cbmem_base;
+static int cbmem_size;
+
+struct cbmem_entry {
+	u32 magic;
+	u32 id;
+	u64 base;
+	u64 size;
+} __attribute__((packed));
+
+#ifndef __ROMCC__
+struct cbmem_entry *bss_cbmem_toc;
+#endif
+
+/**
+ * cbmem is a simple mechanism to do some kind of book keeping of the coreboot
+ * high tables memory. This is a small amount of memory which is "stolen" from
+ * the system memory for coreboot purposes. Usually this memory is used for
+ *  - the coreboot table
+ *  - legacy tables (PIRQ, MP table)
+ *  - ACPI tables
+ *  - suspend/resume backup memory
+ */
+
+void cbmem_init(u64 baseaddr, u64 size)
+{
+	struct cbmem_entry *cbmem_toc;
+	cbmem_toc = (struct cbmem_entry *)(unsigned long)baseaddr;
+
+#ifndef __ROMCC__
+	bss_cbmem_toc = cbmem_toc;
+#endif
+	
+	debug("Initializing CBMEM area to 0x%llx (%lld bytes)\n", baseaddr, size);
+
+	if (size < (64 * 1024)) {
+		debug("Increase CBMEM size!!\n");
+		for (;;) ;
+	}
+
+	memset(cbmem_toc, 0, CBMEM_TOC_RESERVED);
+
+	cbmem_toc[0] = (struct cbmem_entry) {
+		.magic	= CBMEM_MAGIC,
+		.id	= CBMEM_ID_FREESPACE,
+		.base	= baseaddr + CBMEM_TOC_RESERVED,
+		.size	= size - CBMEM_TOC_RESERVED
+	};
+}
+
+int cbmem_reinit(u64 baseaddr)
+{
+	struct cbmem_entry *cbmem_toc;
+	cbmem_toc = (struct cbmem_entry *)(unsigned long)baseaddr;
+
+	debug("Re-Initializing CBMEM area to 0x%lx\n", baseaddr);
+#ifndef __ROMCC__
+	bss_cbmem_toc = cbmem_toc;
+#endif
+
+	return (cbmem_toc[0].magic == CBMEM_MAGIC);
+}
+
+void *cbmem_add(u32 id, u64 size)
+{
+	struct cbmem_entry *cbmem_toc;
+	int i;
+#ifdef __ROMCC__
+	 cbmem_toc = (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
+#else
+	 cbmem_toc = bss_cbmem_toc;
+#endif
+	
+	if (cbmem_toc == NULL) {
+		return NULL;
+	}
+
+	if (cbmem_toc[0].magic != CBMEM_MAGIC) {
+		printk_err("ERROR: CBMEM was not initialized yet.\n");
+		return NULL;
+	}
+
+	/* Will the entry fit at all? */
+	if (size > cbmem_toc[0].size) {
+		printk_err("ERROR: Not enough memory for table %x\n", id);
+		return NULL;
+	}
+
+	/* Align size to 512 byte blocks */
+
+	size = ALIGN(size, 512) < cbmem_toc[0].size ? 
+		ALIGN(size, 512) : cbmem_toc[0].size;
+
+	/* Now look for the first free/usable TOC entry */
+	for (i = 0; i < MAX_CBMEM_ENTRIES; i++) {
+		if (cbmem_toc[i].id == CBMEM_ID_NONE)
+			break;
+	}
+
+	if (i >= MAX_CBMEM_ENTRIES) {
+		printk_err("ERROR: No more CBMEM entries available.\n");
+		return NULL;
+	}
+
+	debug("Adding CBMEM entry as no. %d\n", i);
+
+	cbmem_toc[i] = (struct cbmem_entry) {
+		.magic = CBMEM_MAGIC,
+		.id	= id,
+		.base	= cbmem_toc[0].base,
+		.size	= size
+	};
+
+	cbmem_toc[0].base += size;
+	cbmem_toc[0].size -= size;
+
+	return (void *)cbmem_toc[i].base;
+}
+
+void *cbmem_find(u32 id)
+{
+	struct cbmem_entry *cbmem_toc;
+	int i;
+#ifdef __ROMCC__
+	 cbmem_toc = (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
+#else
+	 cbmem_toc = bss_cbmem_toc;
+#endif
+	
+	if (cbmem_toc == NULL)
+		return NULL;
+
+	for (i = 0; i < MAX_CBMEM_ENTRIES; i++) {
+		if (cbmem_toc[i].id == id)
+			return (void *)(unsigned long)cbmem_toc[i].base;
+	}
+
+	return (void *)NULL;
+}
+
+#ifndef __ROMCC__
+void cbmem_arch_init(void);
+#if CONFIG_HAVE_ACPI_RESUME
+extern u8 acpi_slp_type;
+#endif
+extern uint64_t high_tables_base, high_tables_size;
+
+void cbmem_initialize(void)
+{
+#if CONFIG_HAVE_ACPI_RESUME
+	if (acpi_slp_type == 3) {
+		if (!cbmem_reinit(high_tables_base)) {
+			/* Something went wrong, our high memory area got wiped */
+			acpi_slp_type == 0;
+			cbmem_init(high_tables_base, high_tables_size);
+		}
+	} else {
+		cbmem_init(high_tables_base, high_tables_size);
+	}
+#else
+	cbmem_init(high_tables_base, high_tables_size);
+#endif
+	cbmem_arch_init();
+}
+
+#ifndef __ROMCC__
+void cbmem_list(void)
+{
+	struct cbmem_entry *cbmem_toc;
+	int i;
+#ifdef __ROMCC__
+	 cbmem_toc = (struct cbmem_entry *)(get_top_of_ram() - HIGH_MEMORY_SIZE);
+#else
+	 cbmem_toc = bss_cbmem_toc;
+#endif
+	
+	if (cbmem_toc == NULL)
+		return NULL;
+
+	for (i = 0; i < MAX_CBMEM_ENTRIES; i++) {
+
+		if (cbmem_toc[i].magic != CBMEM_MAGIC)
+			continue;
+		printk_debug("%2d. ", i);
+		switch (cbmem_toc[i].id) {
+		case CBMEM_ID_FREESPACE: printk_debug("FREE SPACE "); break;
+		case CBMEM_ID_GDT:	 printk_debug("GDT        "); break;
+		case CBMEM_ID_ACPI:	 printk_debug("ACPI       "); break;
+		case CBMEM_ID_CBTABLE:	 printk_debug("COREBOOT   "); break;
+		case CBMEM_ID_PIRQ:	 printk_debug("IRQ TABLE  "); break;
+		case CBMEM_ID_MPTABLE:	 printk_debug("SMP TABLE  "); break;
+		case CBMEM_ID_RESUME:	 printk_debug("ACPI RESUME"); break;
+		default: printk_debug("%08x ", cbmem_toc[i].id);
+		}
+		printk_debug("%08llx ", cbmem_toc[i].base);
+		printk_debug("%08llx\n", cbmem_toc[i].size);
+	}
+}
+#endif
+
+#endif
+
Index: src/cpu/intel/model_6ex/cache_as_ram_disable.c
===================================================================
--- src/cpu/intel/model_6ex/cache_as_ram_disable.c	(revision 4842)
+++ src/cpu/intel/model_6ex/cache_as_ram_disable.c	(working copy)
@@ -1,7 +1,7 @@ 
 /*
  * This file is part of the coreboot project.
  * 
- * Copyright (C) 2007-2008 coresystems GmbH
+ * 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
@@ -53,44 +53,43 @@ 
 
 	/* No servicable parts below this line .. */
 
-        {
-        	/* 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)
-	        );
-	        printk_spew("v_esp=%08x\r\n", v_esp);
-        }
+#if CAR_DEBUG
+        /* 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"
+		: "=a" (v_esp)
+	);
+	printk_spew("v_esp=%08x\n", v_esp);
+#endif
 
 cpu_reset_x:
 
-        printk_spew("cpu_reset = %08x\r\n",cpu_reset);
+        printk_spew("cpu_reset = %08x\n", cpu_reset);
+	printk_spew("No cache as ram now - ");
 
-	if(cpu_reset == 0) {
-	        print_spew("Clearing initial memory region: ");
-	}
-	print_spew("No cache as ram now - ");
-
 	/* store cpu_reset to ebx */
         __asm__ volatile (
                 "movl %0, %%ebx\n\t"
                 ::"a" (cpu_reset)
         );
 
-	if(cpu_reset==0) {
-#define CLEAR_FIRST_1M_RAM 1
-#include "cache_as_ram_post.c"
-	} else {
 #undef CLEAR_FIRST_1M_RAM 
 #include "cache_as_ram_post.c"
-	}
 
+	/* For now: use rambase + 1MB - 64K (counting downwards) as stack. This
+	 * makes sure that we stay completely within the 1M of memory we
+	 * preserve with the memcpy above.
+	 */
+
+#ifndef HIGH_MEMORY_SAVE
+#define HIGH_MEMORY_SAVE ( (1024 - 64) * 1024 )
+#endif
+
 	__asm__ volatile (
-                /* set new esp */ /* before CONFIG_RAMBASE */
-                "subl   %0, %%ebp\n\t"
-                "subl   %0, %%esp\n\t"
-                ::"a"( (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)- CONFIG_RAMBASE )
+		"movl %0, %%ebp\n"
+		"movl %0, %%esp\n"
+		:: "a" (CONFIG_RAMBASE + HIGH_MEMORY_SAVE)
 	);
 
 	{
@@ -98,19 +97,14 @@ 
 
 		/* get back cpu_reset from ebx */
 		__asm__ volatile (
-			"movl %%ebx, %0\n\t"
+			"movl %%ebx, %0\n"
 			:"=a" (new_cpu_reset)
 		);
 
-#ifdef DEACTIVATE_CAR
-		print_debug("Deactivating CAR");
-#include DEACTIVATE_CAR_FILE
-		print_debug(" - Done.\r\n");
-#endif
 		/* Copy and execute coreboot_ram */
 		copy_and_run(new_cpu_reset);
-		/* We will not return */
 	}
 
-	print_debug("sorry. parachute did not open.\r\n");
+	/* We will not return */
+	printk_debug("sorry. parachute did not open.\n");
 }
Index: src/cpu/intel/model_6fx/cache_as_ram_disable.c
===================================================================
--- src/cpu/intel/model_6fx/cache_as_ram_disable.c	(revision 4842)
+++ src/cpu/intel/model_6fx/cache_as_ram_disable.c	(working copy)
@@ -1,7 +1,7 @@ 
 /*
  * This file is part of the coreboot project.
  * 
- * Copyright (C) 2007-2008 coresystems GmbH
+ * 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
@@ -53,44 +53,43 @@ 
 
 	/* No servicable parts below this line .. */
 
-        {
-        	/* 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)
-	        );
-	        printk_spew("v_esp=%08x\r\n", v_esp);
-        }
+#if CAR_DEBUG
+        /* 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"
+		: "=a" (v_esp)
+	);
+	printk_spew("v_esp=%08x\n", v_esp);
+#endif
 
 cpu_reset_x:
 
-        printk_spew("cpu_reset = %08x\r\n",cpu_reset);
+        printk_spew("cpu_reset = %08x\n", cpu_reset);
+	printk_spew("No cache as ram now - ");
 
-	if(cpu_reset == 0) {
-	        print_spew("Clearing initial memory region: ");
-	}
-	print_spew("No cache as ram now - ");
-
 	/* store cpu_reset to ebx */
         __asm__ volatile (
                 "movl %0, %%ebx\n\t"
                 ::"a" (cpu_reset)
         );
 
-	if(cpu_reset==0) {
-#define CLEAR_FIRST_1M_RAM 1
-#include "cache_as_ram_post.c"
-	} else {
 #undef CLEAR_FIRST_1M_RAM 
 #include "cache_as_ram_post.c"
-	}
 
+	/* For now: use rambase + 1MB - 64K (counting downwards) as stack. This
+	 * makes sure that we stay completely within the 1M of memory we
+	 * preserve with the memcpy above.
+	 */
+
+#ifndef HIGH_MEMORY_SAVE
+#define HIGH_MEMORY_SAVE ( (1024 - 64) * 1024 )
+#endif
+
 	__asm__ volatile (
-                /* set new esp */ /* before CONFIG_RAMBASE */
-                "subl   %0, %%ebp\n\t"
-                "subl   %0, %%esp\n\t"
-                ::"a"( (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)- CONFIG_RAMBASE )
+		"movl %0, %%ebp\n"
+		"movl %0, %%esp\n"
+		:: "a" (CONFIG_RAMBASE + HIGH_MEMORY_SAVE)
 	);
 
 	{
@@ -98,19 +97,14 @@ 
 
 		/* get back cpu_reset from ebx */
 		__asm__ volatile (
-			"movl %%ebx, %0\n\t"
+			"movl %%ebx, %0\n"
 			:"=a" (new_cpu_reset)
 		);
 
-#ifdef DEACTIVATE_CAR
-		print_debug("Deactivating CAR");
-#include DEACTIVATE_CAR_FILE
-		print_debug(" - Done.\r\n");
-#endif
 		/* Copy and execute coreboot_ram */
 		copy_and_run(new_cpu_reset);
-		/* We will not return */
 	}
 
-	print_debug("sorry. parachute did not open.\r\n");
+	/* We will not return */
+	printk_debug("sorry. parachute did not open.\n");
 }
Index: src/arch/i386/boot/gdt.c
===================================================================
--- src/arch/i386/boot/gdt.c	(revision 0)
+++ src/arch/i386/boot/gdt.c	(revision 0)
@@ -0,0 +1,59 @@ 
+/*
+ * 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
+ */
+
+#include <types.h>
+#include <string.h>
+#include <cbmem.h>
+#include <console/console.h>
+
+// Global Descriptor Table, defined in c_start.S
+extern char gdt;
+extern char gdt_end;
+
+/* i386 lgdt argument */
+struct gdtarg {
+	u16 limit;
+	u32 base;
+} __attribute__((packed));
+
+// Copy GDT to new location and reload it
+void move_gdt(void)
+{
+	void *newgdt;
+	u16 num_gdt_bytes = &gdt_end - &gdt;
+	struct gdtarg gdtarg;
+
+	newgdt = cbmem_find(CBMEM_ID_GDT);
+	if (!newgdt) {
+		newgdt = cbmem_add(CBMEM_ID_GDT, ALIGN(num_gdt_bytes, 512));
+		if (!newgdt) {
+			printk(BIOS_ERR, "Error: Could not relocate GDT.\n");
+			return;
+		}
+		printk_debug("Moving GDT to %#lx...", newgdt);
+		memcpy((void*)newgdt, &gdt, num_gdt_bytes);
+	}
+
+	gdtarg.base = newgdt;
+	gdtarg.limit = num_gdt_bytes - 1;
+
+	__asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
+	printk_debug("ok\n");
+}
+
Index: src/arch/i386/boot/Config.lb
===================================================================
--- src/arch/i386/boot/Config.lb	(revision 4842)
+++ src/arch/i386/boot/Config.lb	(working copy)
@@ -19,3 +19,4 @@ 
 object wakeup.S
 end
 end
+object gdt.o
Index: src/arch/i386/boot/Makefile.inc
===================================================================
--- src/arch/i386/boot/Makefile.inc	(revision 4842)
+++ src/arch/i386/boot/Makefile.inc	(working copy)
@@ -1,6 +1,7 @@ 
 obj-y += boot.o
 obj-y += coreboot_table.o
 obj-$(CONFIG_MULTIBOOT) += multiboot.o
+obj-y += gdt.o
 obj-y += tables.o
 obj-$(CONFIG_GENERATE_PIRQ_TABLE) += pirq_routing.o
 obj-$(CONFIG_GENERATE_ACPI_TABLES) += acpi.o
Index: src/arch/i386/boot/tables.c
===================================================================
--- src/arch/i386/boot/tables.c	(revision 4842)
+++ src/arch/i386/boot/tables.c	(working copy)
@@ -19,8 +19,6 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
-/* 2006.1 yhlu add mptable cross 0x467 processing */
-
 #include <console/console.h>
 #include <cpu/cpu.h>
 #include <boot/tables.h>
@@ -31,34 +29,20 @@ 
 #include <string.h>
 #include <cpu/x86/multiboot.h>
 #include "coreboot_table.h"
+#include <cbmem.h>
 
-// Global Descriptor Table, defined in c_start.S
-extern uint8_t gdt;
-extern uint8_t gdt_end;
+uint64_t high_tables_base = 0;
+uint64_t high_tables_size;
 
-/* i386 lgdt argument */
-struct gdtarg {
-	unsigned short limit;
-	unsigned int base;
-} __attribute__((packed));
+void cbmem_list(void);
 
-// Copy GDT to new location and reload it
-void move_gdt(unsigned long newgdt)
+void move_gdt(void);
+void cbmem_arch_init(void)
 {
-	uint16_t num_gdt_bytes = &gdt_end - &gdt;
-	struct gdtarg gdtarg;
-
-	printk_debug("Moving GDT to %#lx...", newgdt);
-	memcpy((void*)newgdt, &gdt, num_gdt_bytes);
-	gdtarg.base = newgdt;
-	gdtarg.limit = num_gdt_bytes - 1;
-	__asm__ __volatile__ ("lgdt %0\n\t" : : "m" (gdtarg));
-	printk_debug("ok\n");
+	/* defined in gdt.c */
+	move_gdt();
 }
 
-uint64_t high_tables_base = 0;
-uint64_t high_tables_size;
-
 struct lb_memory *write_tables(void)
 {
 	unsigned long low_table_start, low_table_end;
@@ -68,15 +52,16 @@ 
 	 * the low and the high area, so payloads and OSes don't need to know
 	 * about the high tables.
 	 */
-	unsigned long high_table_end=0;
+	unsigned long high_table_pointer;
 
-	if (high_tables_base) {
-		printk_debug("High Tables Base is %llx.\n", high_tables_base);
-		high_table_end = high_tables_base;
-	} else {
+	if (!high_tables_base) {
 		printk_err("ERROR: High Tables Base is not set.\n");
+		// Are there any boards without?
+		// Stepan thinks we should die() here!
 	}
 
+	printk_debug("High Tables Base is %llx.\n", high_tables_base);
+
 	rom_table_start = 0xf0000; 
 	rom_table_end =   0xf0000;
 
@@ -87,7 +72,9 @@ 
 	low_table_start = 0;
 	low_table_end = 0x500;
 
-	post_code(0x99);
+#if CONFIG_GENERATE_PIRQ_TABLE == 1
+#define MAX_PIRQ_TABLE_SIZE (4 * 1024)
+	post_code(0x9a);
 
 	/* This table must be between 0x0f0000 and 0x100000 */
 	rom_table_end = write_pirq_routing_table(rom_table_end);
@@ -96,26 +83,87 @@ 
 	/* And add a high table version for those payloads that
 	 * want to live in the F segment
 	 */
-	if (high_tables_base) {
-		high_table_end = write_pirq_routing_table(high_table_end);
-		high_table_end = ALIGN(high_table_end, 1024);
+	high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_PIRQ, MAX_PIRQ_TABLE_SIZE);
+	if (high_table_pointer) {
+		unsigned long new_high_table_pointer;
+		new_high_table_pointer = write_pirq_routing_table(high_table_pointer);
+		// FIXME make pirq table code intelligent enough to know how
+		// much space it's going to need.
+		if (new_high_table_pointer > (high_table_pointer + MAX_PIRQ_TABLE_SIZE)) {
+			printk(BIOS_ERR, "ERROR: Increase PIRQ size.\n");
+		}
+		printk(BIOS_DEBUG, "PIRQ table: %ld bytes.\n",
+				new_high_table_pointer - high_table_pointer);
 	}
 
-	post_code(0x9a);
+#endif
 
+#if CONFIG_GENERATE_MP_TABLE == 1
+#define MAX_MP_TABLE_SIZE (4 * 1024)
+	post_code(0x9b);
+
+	/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
+	rom_table_end = write_smp_table(rom_table_end);
+	rom_table_end = ALIGN(rom_table_end, 1024);
+
+	high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_MPTABLE, MAX_MP_TABLE_SIZE);
+	if (high_table_pointer) {
+		unsigned long new_high_table_pointer;
+		new_high_table_pointer = write_smp_table(high_table_pointer);
+		// FIXME make mp table code intelligent enough to know how
+		// much space it's going to need.
+		if (new_high_table_pointer > (high_table_pointer + MAX_MP_TABLE_SIZE)) {
+			printk(BIOS_ERR, "ERROR: Increase MP table size.\n");
+		}
+
+		printk(BIOS_DEBUG, "MP table: %ld bytes.\n",
+				new_high_table_pointer - high_table_pointer);
+	}
+#endif /* CONFIG_GENERATE_MP_TABLE */
+
+#if CONFIG_GENERATE_ACPI_TABLES == 1
+#define MAX_ACPI_SIZE (47 * 1024)
+	post_code(0x9c);
+
 	/* Write ACPI tables to F segment and high tables area */
-#if CONFIG_GENERATE_ACPI_TABLES == 1
-	if (high_tables_base) {
-		unsigned long acpi_start = high_table_end;
+
+	/* Ok, this is a bit hacky still, because some day we want to have this
+	 * completely dynamic. But right now we are setting fixed sizes. 
+	 * It's probably still better than the old high_table_base code because
+	 * now at least we know when we have an overflow in the area.
+	 *
+	 * We want to use 1MB - 64K for Resume backup. We use 512B for TOC and
+	 * 512 byte for GDT, 4K for PIRQ and 4K for MP table and 8KB for the
+	 * coreboot table. This leaves us with 47KB for all of ACPI. Let's see
+	 * how far we get.
+	 */
+	high_table_pointer = (unsigned long)cbmem_add(CBMEM_ID_ACPI, MAX_ACPI_SIZE);
+	if (high_table_pointer) {
+		unsigned long acpi_start = high_table_pointer;
+		unsigned long new_high_table_pointer;
+
 		rom_table_end = ALIGN(rom_table_end, 16);
-		high_table_end = write_acpi_tables(high_table_end);
-		while (acpi_start < high_table_end) {
+		new_high_table_pointer = write_acpi_tables(high_table_pointer);
+		if (new_high_table_pointer > ( high_table_pointer + MAX_ACPI_SIZE)) {
+			printk(BIOS_ERR, "ERROR: Increase ACPI size\n");
+		}
+                printk(BIOS_DEBUG, "ACPI tables: %ld bytes.\n",
+				new_high_table_pointer - high_table_pointer);
+
+		/* Now we need to create a low table copy of the RSDP. */
+
+		/* First we look for the high table RSDP */
+		while (acpi_start < new_high_table_pointer) {
 			if (memcmp(((acpi_rsdp_t *)acpi_start)->signature, RSDP_SIG, 8) == 0) {
 				break;
 			}
 			acpi_start++;
 		}
-		if (acpi_start != high_table_end) {
+
+		/* Now, if we found the RSDP, we take the RSDT and XSDT pointer
+		 * from it in order to write the low RSDP
+		 */
+		if (acpi_start < new_high_table_pointer) {
 			acpi_rsdp_t *low_rsdp = (acpi_rsdp_t *)rom_table_end,
 				    *high_rsdp = (acpi_rsdp_t *)acpi_start;
 
@@ -125,65 +173,61 @@ 
 		} else {
 			printk_err("ERROR: Didn't find RSDP in high table.\n");
 		}
-		high_table_end = ALIGN(high_table_end, 1024);
 		rom_table_end = ALIGN(rom_table_end + sizeof(acpi_rsdp_t), 16);
 	} else {
 		rom_table_end = write_acpi_tables(rom_table_end);
 		rom_table_end = ALIGN(rom_table_end, 1024);
 	}
+
 #endif
-	post_code(0x9b);
 
-#if CONFIG_GENERATE_MP_TABLE == 1
-	/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
-	rom_table_end = write_smp_table(rom_table_end);
-	rom_table_end = ALIGN(rom_table_end, 1024);
-
-	/* ... and a copy in the high tables */
-	if (high_tables_base) {
-		high_table_end = write_smp_table(high_table_end);
-		high_table_end = ALIGN(high_table_end, 1024);
-	}
-#endif /* CONFIG_GENERATE_MP_TABLE */
-
-	post_code(0x9c);
-
-	// Relocate the GDT to reserved memory, so it won't get clobbered
-	if (high_tables_base) {
-		move_gdt(high_table_end);
-		high_table_end += &gdt_end - &gdt;
-		high_table_end = ALIGN(high_table_end, 1024);
-	} else {
-		move_gdt(low_table_end);
-		low_table_end += &gdt_end - &gdt;
-	}
-
+#if CONFIG_MULTIBOOT
 	post_code(0x9d);
 
-#if CONFIG_MULTIBOOT
 	/* The Multiboot information structure */
 	rom_table_end = write_multiboot_info(
 				low_table_start, low_table_end,
 				rom_table_start, rom_table_end);
 #endif
 
-	post_code(0x9e);
+#define MAX_COREBOOT_TABLE_SIZE (8 * 1024)
+	post_code(0x9d);
 
-	if (high_tables_base) {
+	high_table_pointer = cbmem_add(CBMEM_ID_CBTABLE, MAX_COREBOOT_TABLE_SIZE);
+
+	if (high_table_pointer) {
+		unsigned long new_high_table_pointer;
+
 		/* Also put a forwarder entry into 0-4K */
-		write_coreboot_table(low_table_start, low_table_end,
-				high_tables_base, high_table_end);
-		if (high_table_end > high_tables_base + high_tables_size)
-			printk_err("%s: High tables didn't fit in %llx (%llx)\n",
-				   __func__, high_tables_size, high_table_end -
-				   high_tables_base);
+		new_high_table_pointer = write_coreboot_table(low_table_start, low_table_end,
+				high_tables_base, high_table_pointer);
+
+		if (new_high_table_pointer > (high_table_pointer +
+					MAX_COREBOOT_TABLE_SIZE))
+			printk_err("%s: coreboot table didn't fit (%llx)\n",
+				   __func__, new_high_table_pointer -
+				   high_table_pointer);
+
+                printk(BIOS_DEBUG, "coreboot table: %ld bytes.\n",
+				new_high_table_pointer - high_table_pointer);
 	} else {
 		/* The coreboot table must be in 0-4K or 960K-1M */
 		write_coreboot_table(low_table_start, low_table_end,
 			      rom_table_start, rom_table_end);
 	}
  
-	post_code(0x9f);
+	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, 1024 * (1024-64));
+#endif
+	
+	// Remove before sending upstream
+	cbmem_list();
+
 	return get_lb_mem();
 }

Index: src/boot/hardwaremain.c
===================================================================
--- src/boot/hardwaremain.c	(revision 4842)
+++ src/boot/hardwaremain.c	(working copy)
@@ -39,12 +39,14 @@ 
 #if CONFIG_HAVE_ACPI_RESUME
 #include <arch/acpi.h>
 #endif
+#if CONFIG_WRITE_HIGH_TABLES
+#include <cbmem.h>
+#endif
 
 /**
- * @brief Main function of the DRAM part of coreboot.
+ * @brief Main function of the RAM part of coreboot.
  *
- * Coreboot is divided into Pre-DRAM part and DRAM part. 
- *
+ * Coreboot is divided into Pre-RAM part and RAM part. 
  * 
  * Device Enumeration:
  *	In the dev_enumerate() phase, 
@@ -56,7 +58,7 @@ 
 
 	post_code(0x80);
 
-	/* displayinit MUST PRECEDE ALL PRINTK! */
+	/* console_init() MUST PRECEDE ALL printk()! */
 	console_init();
 	
 	post_code(0x39);
@@ -87,6 +89,9 @@ 
 	dev_initialize();
 	post_code(0x89);
 
+#if CONFIG_WRITE_HIGH_TABLES == 1
+	cbmem_initialize();
+#endif
 #if CONFIG_HAVE_ACPI_RESUME == 1
 	suspend_resume();
 	post_code(0x8a);