AGESA: Disable CAR with empty stack
Calling disable_cache_as_ram() with valuables in stack is not
a stable solution, as per documentation AMD_DISABLE_STACK
should destroy stack in cache.
Change-Id: I986bb7a88f53f7f7a0b05d4edcd5020f5dbeb4b7
Signed-off-by: Kyösti Mälkki <kyosti.malkki@gmail.com>
Reviewed-on: https://review.coreboot.org/18626
Tested-by: build bot (Jenkins)
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
diff --git a/src/cpu/amd/agesa/cache_as_ram.inc b/src/cpu/amd/agesa/cache_as_ram.inc
index 1258d15..857873a 100644
--- a/src/cpu/amd/agesa/cache_as_ram.inc
+++ b/src/cpu/amd/agesa/cache_as_ram.inc
@@ -26,12 +26,8 @@
#include "gcccar.inc"
#include <cpu/x86/cache.h>
-/*
- * XMM map:
- */
-
.code32
-.globl cache_as_ram_setup, disable_cache_as_ram, cache_as_ram_setup_out
+.globl cache_as_ram_setup, cache_as_ram_setup_out
cache_as_ram_setup:
@@ -110,17 +106,13 @@
pushl $0x0
pushl %ebp
call romstage_main
+ movl %eax, %ebx
- /* Should never see this postcode */
- post_code(0xaf)
-stop:
- jmp stop
+/* Register %ebx is new stacktop for remaining of romstage.
+ * It is the only register preserved in AMD_DISABLE_STACK.
+ */
disable_cache_as_ram:
- /* Save return stack */
- movd 0(%esp), %xmm1
- movd %esp, %xmm0
-
/* Disable cache */
movl %cr0, %eax
orl $CR0_CacheDisable, %eax
@@ -132,12 +124,13 @@
movl %cr0, %eax
andl $0x9fffffff, %eax
movl %eax, %cr0
- xorl %eax, %eax
- /* Restore the return stack */
- wbinvd
- movd %xmm0, %esp
- movd %xmm1, (%esp)
- ret
+ movl %ebx, %esp
+ call romstage_after_car
+
+ /* Should never see this postcode */
+ post_code(0xaf)
+stop:
+ jmp stop
cache_as_ram_setup_out:
diff --git a/src/cpu/amd/agesa/family12/romstage.c b/src/cpu/amd/agesa/family12/romstage.c
index 13b9f06..8f4e81a 100644
--- a/src/cpu/amd/agesa/family12/romstage.c
+++ b/src/cpu/amd/agesa/family12/romstage.c
@@ -14,8 +14,6 @@
* GNU General Public License for more details.
*/
-#include <arch/stages.h>
-
#include <console/console.h>
#include <cpu/amd/car.h>
@@ -49,8 +47,15 @@
post_code(0x37);
agesawrapper_amdinitearly();
+ printk(BIOS_INFO, "Normal boot\n");
+
post_code(0x38);
agesawrapper_amdinitpost();
+}
+
+void agesa_postcar(struct sysinfo *cb)
+{
+ printk(BIOS_INFO, "Normal boot postcar\n");
post_code(0x39);
printk(BIOS_DEBUG, "sb_before_pci_init ");
@@ -59,7 +64,4 @@
post_code(0x40);
agesawrapper_amdinitenv();
-
- post_code(0x43);
- copy_and_run();
}
diff --git a/src/cpu/amd/agesa/family14/romstage.c b/src/cpu/amd/agesa/family14/romstage.c
index b8c9bd3..e89b2fc 100644
--- a/src/cpu/amd/agesa/family14/romstage.c
+++ b/src/cpu/amd/agesa/family14/romstage.c
@@ -14,9 +14,6 @@
* GNU General Public License for more details.
*/
-#include <arch/stages.h>
-#include <cpu/amd/agesa/s3_resume.h>
-
#include <console/console.h>
#include <cpu/amd/car.h>
@@ -51,32 +48,31 @@
post_code(0x40);
agesawrapper_amdinitpost();
+ } else {
+ printk(BIOS_INFO, "S3 detected\n");
+
+ post_code(0x60);
+ agesawrapper_amdinitresume();
+ }
+}
+
+void agesa_postcar(struct sysinfo *cb)
+{
+ if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot postcar\n");
post_code(0x41);
agesawrapper_amdinitenv();
post_code(0x42);
amd_initenv();
-
} else {
- printk(BIOS_INFO, "S3 detected\n");
-
- post_code(0x60);
-
- agesawrapper_amdinitresume();
+ printk(BIOS_INFO, "S3 resume postcar\n");
post_code(0x61);
-
agesawrapper_amds3laterestore();
post_code(0x62);
-
- prepare_for_resume();
}
-
- post_code(0x50);
- copy_and_run();
-
- /* Not reached */
}
diff --git a/src/cpu/amd/agesa/family15/romstage.c b/src/cpu/amd/agesa/family15/romstage.c
index 1c23308..7b5c0bc 100644
--- a/src/cpu/amd/agesa/family15/romstage.c
+++ b/src/cpu/amd/agesa/family15/romstage.c
@@ -16,8 +16,6 @@
#include <lib.h>
#include <reset.h>
-#include <arch/stages.h>
-#include <cpu/amd/agesa/s3_resume.h>
#include <console/console.h>
#include <cpu/amd/car.h>
@@ -73,17 +71,13 @@
post_code(0x40);
agesawrapper_amdinitpost();
+ printk(BIOS_INFO, "Normal boot\n");
+}
+
+void agesa_postcar(struct sysinfo *cb)
+{
+ printk(BIOS_INFO, "Normal boot postcar\n");
+
post_code(0x41);
agesawrapper_amdinitenv();
- post_code(0x42);
-
- post_code(0x50);
- print_debug("Disabling cache as ram ");
- disable_cache_as_ram();
- print_debug("done\n");
-
- post_code(0x51);
- copy_and_run();
-
- /* Not reached */
}
diff --git a/src/cpu/amd/agesa/family15rl/romstage.c b/src/cpu/amd/agesa/family15rl/romstage.c
index 25cd987..369ae33 100644
--- a/src/cpu/amd/agesa/family15rl/romstage.c
+++ b/src/cpu/amd/agesa/family15rl/romstage.c
@@ -14,9 +14,6 @@
* GNU General Public License for more details.
*/
-#include <arch/stages.h>
-#include <cpu/amd/agesa/s3_resume.h>
-
#include <console/console.h>
#include <cpu/amd/car.h>
@@ -43,29 +40,32 @@
agesawrapper_amdinitearly();
if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot\n");
+
post_code(0x40);
agesawrapper_amdinitpost();
-
- post_code(0x41);
- agesawrapper_amdinitenv();
-
- disable_cache_as_ram();
} else {
printk(BIOS_INFO, "S3 detected\n");
post_code(0x60);
agesawrapper_amdinitresume();
-
- amd_initcpuio();
- agesawrapper_amds3laterestore();
-
- post_code(0x61);
- prepare_for_resume();
}
- post_code(0x50);
- copy_and_run();
-
- /* Not reached */
}
+void agesa_postcar(struct sysinfo *cb)
+{
+ if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot postcar\n");
+ post_code(0x41);
+ agesawrapper_amdinitenv();
+ } else {
+ printk(BIOS_INFO, "S3 resume postcar\n");
+
+ post_code(0x61);
+ amd_initcpuio();
+
+ post_code(0x62);
+ agesawrapper_amds3laterestore();
+ }
+}
diff --git a/src/cpu/amd/agesa/family15tn/romstage.c b/src/cpu/amd/agesa/family15tn/romstage.c
index 55bb4b1..fc1aeee 100644
--- a/src/cpu/amd/agesa/family15tn/romstage.c
+++ b/src/cpu/amd/agesa/family15tn/romstage.c
@@ -15,9 +15,6 @@
* GNU General Public License for more details.
*/
-#include <arch/stages.h>
-#include <cpu/amd/agesa/s3_resume.h>
-
#include <console/console.h>
#include <cpu/amd/car.h>
@@ -45,28 +42,32 @@
agesawrapper_amdinitearly();
if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot\n");
+
post_code(0x40);
agesawrapper_amdinitpost();
-
- post_code(0x41);
- agesawrapper_amdinitenv();
-
- disable_cache_as_ram();
} else {
printk(BIOS_INFO, "S3 detected\n");
post_code(0x60);
agesawrapper_amdinitresume();
+ }
+}
- amd_initcpuio();
- agesawrapper_amds3laterestore();
+void agesa_postcar(struct sysinfo *cb)
+{
+ if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot postcar\n");
+
+ post_code(0x41);
+ agesawrapper_amdinitenv();
+ } else {
+ printk(BIOS_INFO, "S3 resume postcar\n");
post_code(0x61);
- prepare_for_resume();
+ amd_initcpuio();
+
+ post_code(0x62);
+ agesawrapper_amds3laterestore();
}
-
- post_code(0x50);
- copy_and_run();
-
- /* Not reached */
}
diff --git a/src/cpu/amd/agesa/family16kb/romstage.c b/src/cpu/amd/agesa/family16kb/romstage.c
index 175ea54..e0fff35 100644
--- a/src/cpu/amd/agesa/family16kb/romstage.c
+++ b/src/cpu/amd/agesa/family16kb/romstage.c
@@ -14,9 +14,6 @@
* GNU General Public License for more details.
*/
-#include <arch/stages.h>
-#include <cpu/amd/agesa/s3_resume.h>
-
#include <console/console.h>
#include <cpu/amd/car.h>
@@ -43,30 +40,35 @@
agesawrapper_amdinitearly();
if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot\n");
+
post_code(0x40);
agesawrapper_amdinitpost();
- post_code(0x41);
- agesawrapper_amdinitenv();
-
- /* TODO: Disable cache is not ok. */
- disable_cache_as_ram();
} else {
printk(BIOS_INFO, "S3 detected\n");
post_code(0x60);
agesawrapper_amdinitresume();
-
- amd_initcpuio();
- agesawrapper_amds3laterestore();
-
- post_code(0x61);
- prepare_for_resume();
}
-
- post_code(0x50);
- copy_and_run();
-
- /* Not reached */
}
+void agesa_postcar(struct sysinfo *cb)
+{
+ if (!cb->s3resume) {
+ printk(BIOS_INFO, "Normal boot postcar\n");
+
+ post_code(0x41);
+ agesawrapper_amdinitenv();
+ } else {
+ printk(BIOS_INFO, "S3 resume postcar\n");
+
+ post_code(0x61);
+ amd_initcpuio();
+
+ post_code(0x62);
+ agesawrapper_amds3laterestore();
+
+ post_code(0x63);
+ }
+}
diff --git a/src/cpu/amd/agesa/romstage.c b/src/cpu/amd/agesa/romstage.c
index f77bab9..11a62ad 100644
--- a/src/cpu/amd/agesa/romstage.c
+++ b/src/cpu/amd/agesa/romstage.c
@@ -15,11 +15,17 @@
#include <arch/acpi.h>
#include <arch/cpu.h>
+#include <cbmem.h>
#include <cpu/amd/car.h>
+#include <cpu/amd/agesa/s3_resume.h>
#include <cpu/x86/bist.h>
+#include <cpu/x86/mtrr.h>
#include <console/console.h>
+#include <halt.h>
+#include <program_loading.h>
#include <smp/node.h>
#include <string.h>
+#include <northbridge/amd/agesa/agesa_helper.h>
#include <northbridge/amd/agesa/state_machine.h>
static void fill_sysinfo(struct sysinfo *cb)
@@ -51,6 +57,33 @@
agesa_main(cb);
- /* Not reached */
- return NULL;
+ uintptr_t stack_top = CACHE_TMP_RAMTOP;
+ if (cb->s3resume) {
+ if (cbmem_recovery(1)) {
+ printk(BIOS_EMERG, "Unable to recover CBMEM\n");
+ halt();
+ }
+ stack_top = romstage_ram_stack_base(HIGH_ROMSTAGE_STACK_SIZE,
+ ROMSTAGE_STACK_CBMEM);
+ stack_top += HIGH_ROMSTAGE_STACK_SIZE;
+ }
+
+ printk(BIOS_DEBUG, "Move CAR stack.\n");
+ return (void*)stack_top;
+}
+
+void asmlinkage romstage_after_car(void)
+{
+ struct sysinfo romstage_state;
+ struct sysinfo *cb = &romstage_state;
+
+ printk(BIOS_DEBUG, "CAR disabled.\n");
+
+ fill_sysinfo(cb);
+ agesa_postcar(cb);
+
+ if (cb->s3resume)
+ set_resume_cache();
+
+ run_ramstage();
}
diff --git a/src/cpu/amd/agesa/s3_resume.c b/src/cpu/amd/agesa/s3_resume.c
index f45ff3c..8aaa25b 100644
--- a/src/cpu/amd/agesa/s3_resume.c
+++ b/src/cpu/amd/agesa/s3_resume.c
@@ -51,7 +51,7 @@
#endif
}
-static void set_resume_cache(void)
+void set_resume_cache(void)
{
msr_t msr;
diff --git a/src/cpu/amd/agesa/s3_resume.h b/src/cpu/amd/agesa/s3_resume.h
index b10489e..bb65af3 100644
--- a/src/cpu/amd/agesa/s3_resume.h
+++ b/src/cpu/amd/agesa/s3_resume.h
@@ -18,6 +18,7 @@
void restore_mtrr(void);
void prepare_for_resume(void);
+void set_resume_cache(void);
void backup_mtrr(void *mtrr_store, u32 *mtrr_store_size);
const void *OemS3Saved_MTRR_Storage(void);