Am Freitag 13 Februar 2009 13:42:15 schrieb Carl-Daniel Hailfinger:
> This is absolutely awesome! Not only did you manage to keep the code
> readable, you also have kept the changes localized and really minimal.
> Although I had something similar (untested, unfinished) on disk, your
> solution is clearly the way to go. No doubt about that.
Thank you!

> I'd ack straight away, but there is one thing I couldn't figure out
> immediately from the code: Can the code handle Fam11h processors? AFAIK
> they have to be treated like Fam10h.
Right. A better way would be to compare against the K8 CPUID, and switch the 
jump direction in jmp_if_k8. That should be enough, until AMD decides to 
devise a new scheme for future CPU generations.

Attached patch does that, but is totally untested (in fact, I patched the 
patch directly)


Regards,
Patrick
What this patch does:
1. Enable SSE (to get some more registers to play with)
2. Determine CPUID, and stash it in an XMM register, and reference
   value for comparison in another XMM register
3. Add a macro jmp_if_k8, which jumps if the CPU is K8 (using an SSE compare)
4. Replace #if CAR_FAM10 sections with runtime checks using jmp_if_k8.
   This is pretty mechanical work. The macro uses local labels (1: and 2:) to
   prevent namespace issues
5. At one time, CPU_ADDR_BITS is used to fill a register. This is replaced
   with hardcoded values for both cases, and switched appropriately.
6. Disable SSE

Signed-off-by: Patrick Georgi <[email protected]>

Index: src/cpu/amd/car/cache_as_ram.inc
===================================================================
--- src/cpu/amd/car/cache_as_ram.inc	(Revision 3943)
+++ src/cpu/amd/car/cache_as_ram.inc	(Arbeitskopie)
@@ -24,12 +24,22 @@
 /* leave some space for global variable to pass to RAM stage */
 #define GlobalVarSize DCACHE_RAM_GLOBAL_VAR_SIZE
 
-#if CAR_FAM10 == 1
+/* for CAR_FAM10 */
 #define CacheSizeAPStack 0x400 /* 1K */
-#endif
 
+#define jmp_if_k8(x)	comisd	%xmm1, %xmm2; jz x
+
+#define CPUID_MASK		0x0ff00f00
+#define CPUID_MASK_K8		0x00000f00
+
 #include <cpu/x86/mtrr.h>
 #include <cpu/amd/mtrr.h>
+/*
+ XMM map:
+    xmm1: cpu family
+    xmm2: K8 comparison value
+    xmm3: backup ebx
+*/
 
 	/* Save the BIST result */
 	movl	%eax, %ebp
@@ -41,6 +51,21 @@
 	movb	$0xA0, %al
 	outb	%al, $0x80
 
+	/* enable SSE */
+	movl %cr4, %eax
+	orl $(3<<9), %eax
+	movl %eax, %cr4
+
+	/* figure out cpu family */
+	cvtsi2sd %ebx, %xmm3
+	movl	$0x01, %eax
+	cpuid
+	andl	$CPUID_MASK, %eax
+	cvtsi2sd %eax, %xmm1
+	movl	$CPUID_MASK_K8, %eax
+	cvtsi2sd %eax, %xmm2
+	cvtsd2si %xmm3, %ebx
+
 	/* hope we can skip the double set for normal part */
 #if ((HAVE_FAILOVER_BOOT == 1) && (USE_FAILOVER_IMAGE == 1)) || ((HAVE_FAILOVER_BOOT == 0) && (USE_FALLBACK_IMAGE == 1))
 
@@ -50,7 +75,8 @@
 	andl	$(1 << 11), %eax
 	movl	%eax, %ebx	/* We store the status */
 
-#if CAR_FAM10 == 1
+	jmp_if_k8(CAR_FAM10_out_post_errata)
+
 	/* for GH, CAR need to set DRAM Base/Limit Registers to direct that to node0 */
 
 	/* Only BSP needed, for other nodes set during HT/memory init. */
@@ -86,17 +112,15 @@
 
 CAR_FAM10_out:
 
-#endif
-
-#if CAR_FAM10 == 1
 	/* Errata 193: Disable clean copybacks to L3 cache to allow cached ROM.
 	   Re-enable it in after RAM is initialized and before CAR is disabled */
 	movl	$0xc001102a, %ecx
 	rdmsr
 	bts	$15, %eax
 	wrmsr
-#endif
 
+CAR_FAM10_out_post_errata:
+
 	/* Set MtrrFixDramModEn for clear fixed mtrr */
 enable_fixed_mtrr_dram_modify:
 	movl	$SYSCFG_MSR, %ecx
@@ -134,8 +158,10 @@
 	 * macro will have a monotonically increasing segs parameter.
 	 */
 	xorl \reg, \reg
-#if CAR_FAM10 == 1
-.elseif \segs == 1
+.else
+	jmp_if_k8(1f)
+
+.if \segs == 1
 	movl $0x1e000000, \reg /* WB MEM type */
 .elseif \segs == 2
 	movl $0x1e1e0000, \reg /* WB MEM type */
@@ -143,8 +169,10 @@
 	movl $0x1e1e1e00, \reg /* WB MEM type */
 .elseif \segs >= 4
 	movl $0x1e1e1e1e, \reg /* WB MEM type */
-#else
-.elseif \segs == 1
+.endif
+	jmp 2f
+1:
+.if \segs == 1
 	movl $0x06000000, \reg /* WB IO type */
 .elseif \segs == 2
 	movl $0x06060000, \reg /* WB IO type */
@@ -152,8 +180,9 @@
 	movl $0x06060600, \reg /* WB IO type */
 .elseif \segs >= 4
 	movl $0x06060606, \reg /* WB IO type */
-#endif
 .endif
+2:
+.endif /* if \segs <= 0 */
 .endm
 
 /* size is the cache size in bytes we want to use for CAR.
@@ -219,7 +248,10 @@
 	wrmsr
 
 	movl	$0x203, %ecx
-	movl	$((1 << (CPU_ADDR_BITS - 32)) - 1), %edx  /* AMD 40 bit for K8, 48 bit for GH */
+	movl	$0xff, %edx /* (1 << (CPU_ADDR_BITS - 32)) - 1 for K8 (CPU_ADDR_BITS = 40) */
+	jmp_if_k8(wbcache_post_fam10_setup)
+	movl	$0xffff, %edx /* (1 << (CPU_ADDR_BITS - 32)) - 1 for FAM10 (CPU_ADDR_BITS = 48) */
+wbcache_post_fam10_setup:
 	movl	$(~(XIP_ROM_SIZE - 1) | 0x800), %eax
 	wrmsr
 #endif /* XIP_ROM_SIZE && XIP_ROM_BASE */
@@ -248,13 +280,14 @@
 	movl	%eax, %cr0
 
 
-#if CAR_FAM10 == 1
+	jmp_if_k8(fam10_end_part1)
+
 	/* So we need to check if it is BSP */
 	movl	$0x1b, %ecx
 	rdmsr
 	bt	$8, %eax /*BSC */
 	jnc	CAR_FAM10_ap
-#endif
+fam10_end_part1:
 
 	movb	$0xA2, %al
 	outb	%al, $0x80
@@ -280,8 +313,6 @@
 	movb	$0xA3, %al
 	outb	%al, $0x80
 
-#if CAR_FAM10 == 1
-
 	jmp	CAR_FAM10_ap_out
 CAR_FAM10_ap:
 	/* need to set stack pointer for AP */
@@ -326,11 +357,15 @@
 	outb	%al, $0x80
 
 CAR_FAM10_ap_out:
-#endif
 
 	movb	$0xA5, %al
 	outb	%al, $0x80
 
+	/* disable SSE */
+	movl %cr4, %eax
+	andl $~(3<<9), %eax
+	movl %eax, %cr4
+
 	/* Restore the BIST result */
 	movl	%ebp, %eax
 
--
coreboot mailing list: [email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to