[coreboot] New patch to review for coreboot: 0e64b4a haswell: romstage: pass stack pointer and MTRRs

Stefan Reinauer (stefan.reinauer@coreboot.org) gerrit at coreboot.org
Fri Mar 15 20:50:11 CET 2013


Stefan Reinauer (stefan.reinauer at coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2755

-gerrit

commit 0e64b4a773edefeb528395636043f1d5f79ac362
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Thu Feb 7 00:03:33 2013 -0600

    haswell: romstage: pass stack pointer and MTRRs
    
    Instead of hard coding the policy for the stack and MTRR values after
    the cache-as-ram is torn down, allow for the C code to pass those
    policies back to the cache-as-ram assembly file. That way, ramstage
    relocation can use a different stack as well as different MTRR policies.
    
    Change-Id: Ied024d933f96a12ed0703c51c506586f4b50bd14
    Signed-off-by: Aaron Durbin <adurbin at chromium.org>
---
 src/cpu/intel/haswell/cache_as_ram.inc | 51 ++++++++++--------
 src/cpu/intel/haswell/haswell.h        | 16 ++++++
 src/cpu/intel/haswell/romstage.c       | 95 +++++++++++++++++++++++++++++++---
 3 files changed, 133 insertions(+), 29 deletions(-)

diff --git a/src/cpu/intel/haswell/cache_as_ram.inc b/src/cpu/intel/haswell/cache_as_ram.inc
index 72b4958..5fb5712 100644
--- a/src/cpu/intel/haswell/cache_as_ram.inc
+++ b/src/cpu/intel/haswell/cache_as_ram.inc
@@ -182,7 +182,11 @@ clear_mtrrs:
 before_romstage:
 	post_code(0x29)
 	/* Call romstage.c main function. */
-	call	main
+	call	romstage_main
+	/* Save return value from romstage_main. It contains the stack to use
+	 * after cache-as-ram is torn down. It also contains the information
+	 * for setting up MTTRs. */
+	movl	%eax, %ebx
 
 	post_code(0x2f)
 
@@ -251,30 +255,34 @@ before_romstage:
 
 	post_code(0x38)
 
-	/* Enable Write Back and Speculative Reads for the first MB
-	 * and coreboot_ram.
-	 */
-	movl	$MTRRphysBase_MSR(0), %ecx
-	movl	$(0x00000000 | MTRR_TYPE_WRBACK), %eax
-	xorl	%edx, %edx
-	wrmsr
-	movl	$MTRRphysMask_MSR(0), %ecx
-	movl	$(~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid), %eax
-	movl	$CPU_PHYSMASK_HI, %edx	// 36bit address space
-	wrmsr
+	/* Setup stack as indicated by return value from ramstage_main(). */
+	movl	%ebx, %esp
 
-	/* Enable Caching and speculative Reads for the
-	 * complete ROM now that we actually have RAM.
-	 */
-	movl	$MTRRphysBase_MSR(1), %ecx
-	movl	$(0xffc00000 | MTRR_TYPE_WRPROT), %eax
-	xorl	%edx, %edx
+	/* Get number of MTTRs. */
+	popl	%ebx
+	movl	$MTRRphysBase_MSR(0), %ecx
+1:
+	testl	%ebx, %ebx
+	jz	1f
+
+	/* Low 32 bits of MTTR base. */
+	popl	%eax
+	/* Upper 32 bits of MTTR base. */
+	popl	%edx
+	/* Write MTRR base. */
 	wrmsr
-	movl	$MTRRphysMask_MSR(1), %ecx
-	movl	$(~(4*1024*1024 - 1) | MTRRphysMaskValid), %eax
-	movl	$CPU_PHYSMASK_HI, %edx
+	inc	%ecx
+	/* Low 32 bits of MTTR mask. */
+	popl	%eax
+	/* Upper 32 bits of MTTR mask. */
+	popl	%edx
+	/* Write MTRR mask. */
 	wrmsr
+	inc	%ecx
 
+	dec	%ebx
+	jmp	1b
+1:
 	post_code(0x39)
 
 	/* And enable cache again after setting MTRRs. */
@@ -326,7 +334,6 @@ __main:
 
 	movl	%ebp, %esi
 
-	movl	$ROMSTAGE_STACK, %esp
 	movl	%esp, %ebp
 	pushl	%esi
 	call	copy_and_run
diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h
index 3ced0c0..7a55ef7 100644
--- a/src/cpu/intel/haswell/haswell.h
+++ b/src/cpu/intel/haswell/haswell.h
@@ -113,6 +113,22 @@ struct romstage_params {
 };
 void mainboard_romstage_entry(unsigned long bist);
 void romstage_common(const struct romstage_params *params);
+/* romstage_main is called from the cache-as-ram assembly file. The return
+ * value is the stack value to be used for romstage once cache-as-ram is
+ * torn down. The following values are pushed onto the stack to setup the
+ * MTRRs:
+ *   +0: Number of MTRRs
+ *   +4: MTTR base 0 31:0
+ *   +8: MTTR base 0 63:32
+ *  +12: MTTR mask 0 31:0
+ *  +16: MTTR mask 0 63:32
+ *  +20: MTTR base 1 31:0
+ *  +24: MTTR base 1 63:32
+ *  +28: MTTR mask 1 31:0
+ *  +32: MTTR mask 1 63:32
+ *  ...
+ */
+void * __attribute__((regparm(0))) romstage_main(unsigned long bist);
 #endif
 
 #ifdef __SMM__
diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c
index 1d00af1..8b0e2cc 100644
--- a/src/cpu/intel/haswell/romstage.c
+++ b/src/cpu/intel/haswell/romstage.c
@@ -23,6 +23,8 @@
 #include <arch/cpu.h>
 #include <cpu/x86/bist.h>
 #include <cpu/x86/msr.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/stack.h>
 #include <lib.h>
 #include <timestamp.h>
 #include <arch/io.h>
@@ -40,16 +42,90 @@
 #include "southbridge/intel/lynxpoint/me.h"
 
 
-/* The cache-as-ram assembly file calls main() after setting up cache-as-ram.
- * main() will then call the mainboards's mainboard_romstage_entry() function.
- * That function then calls romstage_common() below. The reason for the back
- * and forth is to provide common entry point from cache-as-ram while still
- * allowing for code sharing. Because we can't use global variables the stack
- * is used for allocations -- thus the need to call back and forth. */
+/* The cache-as-ram assembly file calls romstage_main() after setting up
+ * cache-as-ram.  romstage_main() will then call the mainboards's
+ * mainboard_romstage_entry() function. That function then calls
+ * romstage_common() below. The reason for the back and forth is to provide
+ * common entry point from cache-as-ram while still allowing for code sharing.
+ * Because we can't use global variables the stack is used for allocations --
+ * thus the need to call back and forth. */
 
-void main(unsigned long bist)
+
+static inline u32 *stack_push(u32 *stack, u32 value)
+{
+	stack = &stack[-1];
+	*stack = value;
+	return stack;
+}
+
+/* setup_romstage_stack_after_car() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use. */
+static void *setup_romstage_stack_after_car(void)
+{
+	unsigned long top_of_stack;
+	int num_mtrrs;
+	u32 *slot;
+	u32 mtrr_mask_upper;
+
+	/* Top of stack needs to be aligned to a 4-byte boundary. */
+	top_of_stack = ROMSTAGE_STACK & ~3;
+	slot = (void *)top_of_stack;
+	num_mtrrs = 0;
+
+	/* The upper bits of the MTRR mask need to set according to the number
+	 * of physical address bits. */
+	mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
+
+	/* The order for each MTTR is value then base with upper 32-bits of
+	 * each value coming before the lower 32-bits. The reasoning for
+	 * this ordering is to create a stack layout like the following:
+	 *   +0: Number of MTRRs
+	 *   +4: MTTR base 0 31:0
+	 *   +8: MTTR base 0 63:32
+	 *  +12: MTTR mask 0 31:0
+	 *  +16: MTTR mask 0 63:32
+	 *  +20: MTTR base 1 31:0
+	 *  +24: MTTR base 1 63:32
+	 *  +28: MTTR mask 1 31:0
+	 *  +32: MTTR mask 1 63:32
+	 */
+
+	/* Cache the ROM as WP just below 4GiB. */
+	slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+	slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRRphysMaskValid);
+	slot = stack_push(slot, 0); /* upper base */
+	slot = stack_push(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+	num_mtrrs++;
+
+	/* Cache RAM as WB from 0 -> CONFIG_RAMTOP. */
+	slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+	slot = stack_push(slot, ~(CONFIG_RAMTOP - 1) | MTRRphysMaskValid);
+	slot = stack_push(slot, 0); /* upper base */
+	slot = stack_push(slot, 0 | MTRR_TYPE_WRBACK);
+	num_mtrrs++;
+
+	/* Cache 8MiB below the top of ram. On haswell systems the top of
+	 * ram under 4GiB is the start of the TSEG region. It is required to
+	 * be 8MiB aligned. Set this area as cacheable so it can be used later
+	 * for ramstage before setting up the entire RAM as cacheable. */
+	slot = stack_push(slot, mtrr_mask_upper); /* upper mask */
+	slot = stack_push(slot, ~((8 << 20) - 1) | MTRRphysMaskValid);
+	slot = stack_push(slot, 0); /* upper base */
+	slot = stack_push(slot,
+	                  (get_top_of_ram() - (8 << 20)) | MTRR_TYPE_WRBACK);
+	num_mtrrs++;
+
+	/* Save the number of MTTRs to setup. Return the stack location
+	 * pointing to the number of MTRRs. */
+	slot = stack_push(slot, num_mtrrs);
+
+	return slot;
+}
+
+void * __attribute__((regparm(0))) romstage_main(unsigned long bist)
 {
 	int i;
+	void *romstage_stack_after_car;
 	const int num_guards = 4;
 	const u32 stack_guard = 0xdeadbeef;
 	u32 *stack_base = (void *)(CONFIG_DCACHE_RAM_BASE +
@@ -69,10 +145,15 @@ void main(unsigned long bist)
 		printk(BIOS_DEBUG, "Smashed stack detected in romstage!\n");
 	}
 
+	/* Get the stack to use after cache-as-ram is torn down. */
+	romstage_stack_after_car = setup_romstage_stack_after_car();
+
 #if CONFIG_CONSOLE_CBMEM
 	/* Keep this the last thing this function does. */
 	cbmemc_reinit();
 #endif
+
+	return romstage_stack_after_car;
 }
 
 void romstage_common(const struct romstage_params *params)



More information about the coreboot mailing list