[coreboot-gerrit] Patch set updated for coreboot: 28237b7 AMD (K8/fam10): Rewrite CAR migration in post_cache_as_ram

Kyösti Mälkki (kyosti.malkki@gmail.com) gerrit at coreboot.org
Wed Apr 30 08:11:22 CEST 2014


Kyösti Mälkki (kyosti.malkki at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/4583

-gerrit

commit 28237b76dbf9596f82151dbc36d38e1b1593b9a0
Author: Kyösti Mälkki <kyosti.malkki at gmail.com>
Date:   Sun Dec 29 12:07:54 2013 +0200

    AMD (K8/fam10): Rewrite CAR migration in post_cache_as_ram
    
    Old routine copied all of CAR region as-is right below CONFIG_RAMTOP.
    Most of this region was reserved to interleave AP CPU address spaces
    and unused on BSP CPU. The only part of CAR region requiring a copy
    in RAM is the sysinfo structure.
    
    Improved routine changes this as follows:
    
    A region of size 'backup_size' below CONFIG_RAMTOP is cleared. In
    case of S3 resume, OS context from this region is first copied to
    high memory (CBMEM_ID_RESUME).
    
    At stack switch, CAR stack is discarded. Top of the stack for BSP
    is located at 'CONFIG_RAMTOP - car_size' for the remaining part
    of the romstage. This region is part of 'backup_size' and was zeroed
    before the switch took place.
    
    Before CAR is torn down the region of CAR_GLOBALS (and CAR_CBMEM),
    including the relevant sysinfo data for AP nodes memory training,
    is copied at 'CONFIG_RAMTOP - car_size'.
    
    Change-Id: Ie45b576aec6a2e006bfcb26b52fdb77c24f72e3b
    Signed-off-by: Kyösti Mälkki <kyosti.malkki at gmail.com>
---
 src/cpu/amd/car/cache_as_ram.inc    |   5 +-
 src/cpu/amd/car/post_cache_as_ram.c | 176 ++++++++++++++++++------------------
 src/include/cpu/amd/car.h           |   4 +-
 3 files changed, 92 insertions(+), 93 deletions(-)

diff --git a/src/cpu/amd/car/cache_as_ram.inc b/src/cpu/amd/car/cache_as_ram.inc
index dd02f6c..dadf8f7 100644
--- a/src/cpu/amd/car/cache_as_ram.inc
+++ b/src/cpu/amd/car/cache_as_ram.inc
@@ -424,10 +424,9 @@ CAR_FAM10_ap_out:
 cache_as_ram_switch_stack:
 	/* Return address.  */
 	popl	%eax
-	/* Resume memory.  */
+	/* New stack.  */
 	popl	%eax
-	subl	$(( (CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)- (CONFIG_RAMTOP) )), %esp
-	pushl	%eax
+	movl	%eax, %esp
 	call	cache_as_ram_new_stack
 
 all_mtrr_msrs:
diff --git a/src/cpu/amd/car/post_cache_as_ram.c b/src/cpu/amd/car/post_cache_as_ram.c
index 51caec5..2321f11 100644
--- a/src/cpu/amd/car/post_cache_as_ram.c
+++ b/src/cpu/amd/car/post_cache_as_ram.c
@@ -9,58 +9,78 @@
 #include "cbmem.h"
 #include "cpu/amd/car/disable_cache_as_ram.c"
 
-static inline void print_debug_pcar(const char *strval, uint32_t val)
-{
-	printk(BIOS_DEBUG, "%s%08x\n", strval, val);
-}
+#if CONFIG_RAMTOP <= 0x100000
+	#error "You need to set CONFIG_RAMTOP greater than 1M"
+#endif
 
-/* from linux kernel 2.6.32 asm/string_32.h */
+#define PRINTK_IN_CAR	1
 
-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
+#if PRINTK_IN_CAR
+#define print_car_debug(x) print_debug(x)
+#else
+#define print_car_debug(x)
+#endif
 
-static inline void *backup_resume(void) {
-	void *resume_backup_memory;
-	int suspend = acpi_is_wakeup_early();
+extern char _car_data_start[];
+extern char _car_data_end[];
 
-	if (!suspend)
-		return NULL;
+static size_t car_data_size(void)
+{
+	size_t car_size = &_car_data_end[0] - &_car_data_start[0];
+	return ALIGN(car_size, 64);
+}
 
-	if (cbmem_recovery(1))
-		return NULL;
+static size_t backup_size(void)
+{
+	size_t car_size = &_car_data_end[0] - &_car_data_start[0];
+	return ALIGN(car_size + 1024, 1024);
+}
 
-	resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+static void memcpy_(void *d, const void *s, size_t len)
+{
+#if PRINTK_IN_CAR
+	printk(BIOS_SPEW, " Copy [%08x-%08x] to [%08x - %08x] ... ",
+		(u32) s, (u32) (s + len - 1), (u32) d, (u32) (d + len - 1));
+#endif
+	memcpy(d, s, len);
+}
 
-	/* 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.
-	 */
+static void memset_(void *d, int val, size_t len)
+{
+#if PRINTK_IN_CAR
+	printk(BIOS_SPEW, " Fill [%08x-%08x] ... ", (u32) d, (u32) (d + len - 1));
+#endif
+	memset(d, val, len);
+}
 
+static void prepare_romstage_ramstack(void *resume_backup_memory)
+{
+	size_t backup_top = backup_size();
+	print_car_debug("Prepare CAR migration and stack regions...");
+#if CONFIG_HAVE_ACPI_RESUME
 	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
+		memcpy_(resume_backup_memory + HIGH_MEMORY_SAVE - backup_top,
+			(void *)(CONFIG_RAMTOP - backup_top), backup_top);
 	}
-
-	return resume_backup_memory;
+#endif
+	memset_((void *)(CONFIG_RAMTOP - backup_top), 0, backup_top);
+	print_car_debug("Done\n");
 }
+
+static void prepare_ramstage_region(void *resume_backup_memory)
+{
+	size_t backup_top = backup_size();
+	print_car_debug("Prepare ramstage memory region... ");
+#if CONFIG_HAVE_ACPI_RESUME
+	if (resume_backup_memory) {
+		memcpy_(resume_backup_memory, (void *) CONFIG_RAMBASE, HIGH_MEMORY_SAVE - backup_top);
+		memset_((void*) CONFIG_RAMBASE, 0, HIGH_MEMORY_SAVE - backup_top);
+	}
 #endif
+	if (!resume_backup_memory)
+		memset_((void*)0, 0, CONFIG_RAMTOP - backup_top);
+	print_car_debug("Done\n");
+}
 
 /* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33 */
 
@@ -79,48 +99,41 @@ static void vErrata343(void)
 void post_cache_as_ram(void)
 {
 	void *resume_backup_memory = NULL;
-#if 1
-	{
-	/* Check value of esp to verify if we have enough room 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
-
-	/* copy data from cache as ram to
-		ram need to set CONFIG_RAMTOP to 2M and use var mtrr instead.
-	 */
-#if CONFIG_RAMTOP <= 0x100000
-	#error "You need to set CONFIG_RAMTOP greater than 1M"
-#endif
 
 #if CONFIG_HAVE_ACPI_RESUME
- 	resume_backup_memory = backup_resume();
+	int s3resume = acpi_is_wakeup_early();
+	if (s3resume) {
+		cbmem_recovery(s3resume);
+		resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
+	}
 #endif
-
-	print_debug("Copying data from cache to RAM -- switching to use RAM as stack... ");
+	prepare_romstage_ramstack(resume_backup_memory);
 
 	/* from here don't store more data in CAR */
 	vErrata343();
 
-	memcopy((void *)((CONFIG_RAMTOP)-CONFIG_DCACHE_RAM_SIZE), (void *)CONFIG_DCACHE_RAM_BASE, CONFIG_DCACHE_RAM_SIZE); //inline
-	cache_as_ram_switch_stack(resume_backup_memory);
-}
+	size_t car_size = car_data_size();
+	void *migrated_car = (void *)(CONFIG_RAMTOP - car_size);
 
-void
-cache_as_ram_new_stack (void *resume_backup_memory __attribute__ ((unused)))
-{
-	/* We can put data to stack again */
+	print_car_debug("Copying data from cache to RAM... ");
+	memcpy_(migrated_car, &_car_data_start[0], car_size);
+	print_car_debug("Done\n");
 
-	/* only global variable sysinfo in cache need to be offset */
-	print_debug("Done\n");
+	/* New stack grows right below migrated_car. */
+	print_car_debug("Switching to use RAM as stack... ");
+	cache_as_ram_switch_stack(migrated_car);
 
-	print_debug("Disabling cache as ram now \n");
+	/* We do not come back. */
+}
 
+void cache_as_ram_new_stack (void)
+{
+	void *resume_backup_memory = NULL;
+
+#if PRINTK_IN_CAR
+	printk(BIOS_DEBUG, "Top about %08x ... Done\n", (u32) &resume_backup_memory);
+#endif
+	print_car_debug("Disabling cache as ram now\n");
 	disable_cache_as_ram_bsp();
 
 	disable_cache();
@@ -128,24 +141,11 @@ cache_as_ram_new_stack (void *resume_backup_memory __attribute__ ((unused)))
 	enable_cache();
 
 #if CONFIG_HAVE_ACPI_RESUME
-	/* 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);
+	if (acpi_is_wakeup_early()) {
+		resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
 	}
 #endif
-
-	print_debug("Clearing initial memory region: ");
-
-#if CONFIG_HAVE_ACPI_RESUME
-	/* 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);
-#else
-	memset((void*)0, 0, ((CONFIG_RAMTOP) - CONFIG_DCACHE_RAM_SIZE));
-#endif
-	print_debug("Done\n");
+	prepare_ramstage_region(resume_backup_memory);
 
 	set_sysinfo_in_ram(1); // So other core0 could start to train mem
 
@@ -153,5 +153,5 @@ cache_as_ram_new_stack (void *resume_backup_memory __attribute__ ((unused)))
 	copy_and_run();
 	/* We will not return */
 
-	print_debug("should not be here -\n");
+	print_car_debug("should not be here -\n");
 }
diff --git a/src/include/cpu/amd/car.h b/src/include/cpu/amd/car.h
index a001c93..c00310a 100644
--- a/src/include/cpu/amd/car.h
+++ b/src/include/cpu/amd/car.h
@@ -5,8 +5,8 @@ void cache_as_ram_main(unsigned long bist, unsigned long cpu_init_detectedx);
 void done_cache_as_ram_main(void);
 void post_cache_as_ram(void);
 
-void cache_as_ram_switch_stack(void *resume_backup_memory);
-void cache_as_ram_new_stack(void *resume_backup_memory);
+void cache_as_ram_switch_stack(void *stacktop);
+void cache_as_ram_new_stack(void);
 
 #if CONFIG_CPU_AMD_AGESA
 void disable_cache_as_ram(void);



More information about the coreboot-gerrit mailing list