The current K8 stack preservation code in disable_car() works by chance,
but that's not something we should rely on.

The new code is entirely rewritten, fixes a few missing constraints in
the asm and should be a lot more readable. However, the generated code
should be mostly identical.

Attached for Ron.

Signed-off-by: Carl-Daniel Hailfinger <[EMAIL PROTECTED]>

Index: corebootv3-k8_car_disable_inline_asm/arch/x86/amd/k8/stage1.c
===================================================================
--- corebootv3-k8_car_disable_inline_asm/arch/x86/amd/k8/stage1.c       
(Revision 856)
+++ corebootv3-k8_car_disable_inline_asm/arch/x86/amd/k8/stage1.c       
(Arbeitskopie)
@@ -34,20 +34,31 @@
  */
 void disable_car(void)
 {
-       /* OK, here is the theory: we should be able to copy 
-        * the data back over itself, and the wbinvd should then 
-        * flush to memory. Let's see. 
-        */
-       /* nope. 
-       __asm__ __volatile__("cld; rep movsl" ::"D" (CONFIG_CARBASE), "S" 
(CONFIG_CARBASE), "c" (CONFIG_CARSIZE/4): "memory");
-        */
        /* call the inlined function */
        disable_cache_as_ram();
 
-       /* copy it down, wbinvd, copy it back? */
-       __asm__ __volatile__("cld; rep movsl" ::"D" (0x88000), "S" 
(CONFIG_CARBASE), "c" (CONFIG_CARSIZE/4): "memory");
-       __asm__ __volatile__ ("wbinvd\n");
-       __asm__ __volatile__("cld; rep movsl" ::"D" (CONFIG_CARBASE), "S" 
(0x88000), "c" (CONFIG_CARSIZE/4): "memory");
+       /* The BKDG says that a WBINVD will not flush CAR to RAM (because the
+        * cache tags are not dirty).
+        * Solution:
+        * - Two subsequent memcpy in the same inline asm block, one from stack
+        *   to backup, one from backup to stack.
+        * The solution for geode of using a inline asm memcpy of the stack
+        * onto itself will not mark the cache tags as dirty on K8.
+        */
+       __asm__ __volatile__(
+       "       movl %[carbase], %%esi          \n"
+       "       movl %[backuplocation], %%edi   \n"
+       "       movl %[carsizequads], %%ecx     \n"
+       "       cld                             \n"
+       "       rep movsl                       \n"
+       "       wbinvd                          \n"
+       "       movl %[backuplocation], %%esi   \n"
+       "       movl %[carbase], %%edi          \n"
+       "       movl %[carsizequads], %%ecx     \n"
+       "       rep movsl                       \n"
+       :: [carbase] "i" (CONFIG_CARBASE), [backuplocation] "i" (0x88000),
+          [carsizequads] "i" (CONFIG_CARSIZE/4)
+       : "memory", "%edi", "%esi", "%ecx");
        banner(BIOS_DEBUG, "Disable_car: done wbinvd");
        banner(BIOS_DEBUG, "disable_car: done");
 }


-- 
http://www.hailfinger.org/

Index: corebootv3-k8_car_disable_inline_asm/arch/x86/amd/k8/stage1.c
===================================================================
--- corebootv3-k8_car_disable_inline_asm/arch/x86/amd/k8/stage1.c	(Revision 856)
+++ corebootv3-k8_car_disable_inline_asm/arch/x86/amd/k8/stage1.c	(Arbeitskopie)
@@ -34,20 +34,31 @@
  */
 void disable_car(void)
 {
-	/* OK, here is the theory: we should be able to copy 
-	 * the data back over itself, and the wbinvd should then 
-	 * flush to memory. Let's see. 
-	 */
-	/* nope. 
-	__asm__ __volatile__("cld; rep movsl" ::"D" (CONFIG_CARBASE), "S" (CONFIG_CARBASE), "c" (CONFIG_CARSIZE/4): "memory");
-	 */
 	/* call the inlined function */
 	disable_cache_as_ram();
 
-	/* copy it down, wbinvd, copy it back? */
-	__asm__ __volatile__("cld; rep movsl" ::"D" (0x88000), "S" (CONFIG_CARBASE), "c" (CONFIG_CARSIZE/4): "memory");
-	__asm__ __volatile__ ("wbinvd\n");
-	__asm__ __volatile__("cld; rep movsl" ::"D" (CONFIG_CARBASE), "S" (0x88000), "c" (CONFIG_CARSIZE/4): "memory");
+	/* The BKDG says that a WBINVD will not flush CAR to RAM (because the
+	 * cache tags are not dirty).
+	 * Solution:
+	 * - Two subsequent memcpy in the same inline asm block, one from stack
+	 *   to backup, one from backup to stack.
+	 * The solution for geode of using a inline asm memcpy of the stack
+	 * onto itself will not mark the cache tags as dirty on K8.
+	 */
+	__asm__ __volatile__(
+	"	movl %[carbase], %%esi		\n"
+	"	movl %[backuplocation], %%edi	\n"
+	"	movl %[carsizequads], %%ecx	\n"
+	"	cld				\n"
+	"	rep movsl			\n"
+	"	wbinvd				\n"
+	"	movl %[backuplocation], %%esi	\n"
+	"	movl %[carbase], %%edi		\n"
+	"	movl %[carsizequads], %%ecx	\n"
+	"	rep movsl			\n"
+	:: [carbase] "i" (CONFIG_CARBASE), [backuplocation] "i" (0x88000),
+	   [carsizequads] "i" (CONFIG_CARSIZE/4)
+	: "memory", "%edi", "%esi", "%ecx");
 	banner(BIOS_DEBUG, "Disable_car: done wbinvd");
 	banner(BIOS_DEBUG, "disable_car: done");
 }
--
coreboot mailing list
[email protected]
http://www.coreboot.org/mailman/listinfo/coreboot

Reply via email to