blob: 435fdcb588f2891a761a9207d35fc3ddc1f14b36 [file] [log] [blame]
Timothy Pearson1c4508e2015-09-05 17:50:29 -05001/* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering
Timothy Pearson20038442015-09-05 18:46:24 -05002 * Copyright (C) 2012 ChromeOS Authors
Timothy Pearson1c4508e2015-09-05 17:50:29 -05003 * 2005.6 by yhlu
Yinghai Lu9a791df2006-04-03 20:38:34 +00004 * 2006.3 yhlu add copy data from CAR to ram
5 */
Patrick Georgi3d5bb232010-05-09 21:15:13 +00006#include <string.h>
Stefan Reinaueraa987b22010-04-09 13:31:07 +00007#include <arch/stages.h>
Aaron Durbin0dc73542015-07-16 16:07:02 -05008#include <arch/early_variables.h>
Patrick Georgic928a292010-05-14 11:02:56 +00009#include <cpu/x86/mtrr.h>
Kyösti Mälkki88a67f02013-12-12 12:27:53 +020010#include <cpu/amd/mtrr.h>
Kyösti Mälkki2458f422014-04-22 16:46:31 +030011#include <cpu/amd/car.h>
Kyösti Mälkki207880c2013-12-10 09:03:17 +020012#include <arch/acpi.h>
Timothy Pearson20038442015-09-05 18:46:24 -050013#include <romstage_handoff.h>
efdesign9800c8c4a2011-07-20 12:37:58 -060014#include "cbmem.h"
Stefan Reinauer806e1462005-12-01 10:54:44 +000015#include "cpu/amd/car/disable_cache_as_ram.c"
16
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020017#if CONFIG_RAMTOP <= 0x100000
18 #error "You need to set CONFIG_RAMTOP greater than 1M"
19#endif
20
Timothy Pearsond6574462015-10-24 14:09:49 -050021#if IS_ENABLED(CONFIG_DEBUG_CAR)
22#define print_car_debug(format, arg...) printk(BIOS_DEBUG, "%s: " format, __func__, ##arg)
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020023#else
Timothy Pearsond6574462015-10-24 14:09:49 -050024#define print_car_debug(format, arg...)
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020025#endif
26
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020027static size_t backup_size(void)
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +000028{
Aaron Durbin0dc73542015-07-16 16:07:02 -050029 size_t car_size = car_data_size();
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020030 return ALIGN(car_size + 1024, 1024);
Yinghai Lu9a791df2006-04-03 20:38:34 +000031}
Rudolf Marekbcaea142010-11-22 22:00:52 +000032
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020033static void memcpy_(void *d, const void *s, size_t len)
34{
Paul Menzel42b62652015-11-07 09:15:06 +010035 print_car_debug(" Copy [%08x-%08x] to [%08x - %08x] ...",
Timothy Pearson83c3c9e2015-10-24 15:27:49 -050036 (uint32_t) s, (uint32_t) (s + len - 1), (uint32_t) d, (uint32_t) (d + len - 1));
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020037 memcpy(d, s, len);
38}
Rudolf Marekbcaea142010-11-22 22:00:52 +000039
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020040static void memset_(void *d, int val, size_t len)
41{
Paul Menzel42b62652015-11-07 09:15:06 +010042 print_car_debug(" Fill [%08x-%08x] ...", (uint32_t) d, (uint32_t) (d + len - 1));
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020043 memset(d, val, len);
44}
Rudolf Marekbcaea142010-11-22 22:00:52 +000045
Timothy Pearson1c4508e2015-09-05 17:50:29 -050046static int memcmp_(void *d, const void *s, size_t len)
47{
Paul Menzel42b62652015-11-07 09:15:06 +010048 print_car_debug(" Compare [%08x-%08x] with [%08x - %08x] ...",
Timothy Pearson83c3c9e2015-10-24 15:27:49 -050049 (uint32_t) s, (uint32_t) (s + len - 1), (uint32_t) d, (uint32_t) (d + len - 1));
Timothy Pearson1c4508e2015-09-05 17:50:29 -050050 return memcmp(d, s, len);
51}
52
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020053static void prepare_romstage_ramstack(void *resume_backup_memory)
54{
55 size_t backup_top = backup_size();
56 print_car_debug("Prepare CAR migration and stack regions...");
Rudolf Marekbcaea142010-11-22 22:00:52 +000057
58 if (resume_backup_memory) {
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020059 memcpy_(resume_backup_memory + HIGH_MEMORY_SAVE - backup_top,
60 (void *)(CONFIG_RAMTOP - backup_top), backup_top);
61 }
62 memset_((void *)(CONFIG_RAMTOP - backup_top), 0, backup_top);
63
Paul Menzel42b62652015-11-07 09:15:06 +010064 print_car_debug(" Done\n");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020065}
66
67static void prepare_ramstage_region(void *resume_backup_memory)
68{
69 size_t backup_top = backup_size();
Paul Menzel42b62652015-11-07 09:15:06 +010070 print_car_debug("Prepare ramstage memory region...");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020071
72 if (resume_backup_memory) {
73 memcpy_(resume_backup_memory, (void *) CONFIG_RAMBASE, HIGH_MEMORY_SAVE - backup_top);
74 memset_((void*) CONFIG_RAMBASE, 0, HIGH_MEMORY_SAVE - backup_top);
75 } else {
76 memset_((void*)0, 0, CONFIG_RAMTOP - backup_top);
Rudolf Marekbcaea142010-11-22 22:00:52 +000077 }
78
Timothy Pearson44d53422015-05-18 16:04:10 -050079#if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK)
80 initialize_romstage_console_lock();
81#endif
Timothy Pearson7b22d842015-08-28 19:52:05 -050082#if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK)
83 initialize_romstage_nvram_cbfs_lock();
84#endif
Timothy Pearson44d53422015-05-18 16:04:10 -050085
Paul Menzel42b62652015-11-07 09:15:06 +010086 print_car_debug(" Done\n");
Rudolf Marekbcaea142010-11-22 22:00:52 +000087}
Rudolf Marekbcaea142010-11-22 22:00:52 +000088
Jonathan A. Kollasch20d9fb42015-11-24 10:15:22 -060089/* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33
90 * and RevGuide for Fam12h, Pub#44739 Rev 3.10
91 */
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +000092
Marco Schmidtc263b442009-06-06 11:21:52 +000093static void vErrata343(void)
94{
Timothy Pearson730a0432015-10-16 13:51:51 -050095 msr_t msr;
96 unsigned int uiMask = 0xFFFFFFF7;
Marco Schmidtc263b442009-06-06 11:21:52 +000097
Timothy Pearson730a0432015-10-16 13:51:51 -050098 msr = rdmsr(BU_CFG2_MSR);
99 msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0
100 wrmsr(BU_CFG2_MSR, msr);
Marco Schmidtc263b442009-06-06 11:21:52 +0000101}
Yinghai Lud4b278c2006-10-04 20:46:15 +0000102
Kyösti Mälkki142b52c2013-12-10 07:33:36 +0200103void post_cache_as_ram(void)
Yinghai Lu9a791df2006-04-03 20:38:34 +0000104{
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100105 void *resume_backup_memory = NULL;
Timothy Pearson730a0432015-10-16 13:51:51 -0500106 uint32_t family = amd_fam1x_cpu_family();
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200107
Timothy Pearson1f780992015-06-01 23:58:59 -0500108 /* Verify that the BSP didn't overrun the lower stack
109 * boundary during romstage execution
110 */
111 volatile uint32_t *lower_stack_boundary;
112 lower_stack_boundary = (void *)((CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE) - CONFIG_DCACHE_BSP_STACK_SIZE);
113 if ((*lower_stack_boundary) != 0xdeadbeef)
114 printk(BIOS_WARNING, "BSP overran lower stack boundary. Undefined behaviour may result!\n");
115
Timothy Pearson20038442015-09-05 18:46:24 -0500116 struct romstage_handoff *handoff;
117 handoff = romstage_handoff_find_or_add();
118 if (handoff != NULL)
119 handoff->s3_resume = acpi_is_wakeup_s3();
120 else
121 printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
122
Kyösti Mälkki78c5d582015-01-09 23:48:47 +0200123 int s3resume = acpi_is_wakeup_s3();
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200124 if (s3resume) {
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200125 cbmem_recovery(s3resume);
126 resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
Myles Watsonf326e3a2010-03-11 22:12:10 +0000127 }
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200128 prepare_romstage_ramstack(resume_backup_memory);
Yinghai Lu9a791df2006-04-03 20:38:34 +0000129
130 /* from here don't store more data in CAR */
Jonathan A. Kollasch20d9fb42015-11-24 10:15:22 -0600131 if (family >= 0x1f && family <= 0x3f) {
132 /* Family 10h and 12h, 11h until shown otherwise */
Timothy Pearson730a0432015-10-16 13:51:51 -0500133 vErrata343();
134 }
Marco Schmidtc263b442009-06-06 11:21:52 +0000135
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200136 size_t car_size = car_data_size();
137 void *migrated_car = (void *)(CONFIG_RAMTOP - car_size);
138
Paul Menzel42b62652015-11-07 09:15:06 +0100139 print_car_debug("Copying data from cache to RAM...");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200140 memcpy_(migrated_car, &_car_data_start[0], car_size);
Paul Menzel42b62652015-11-07 09:15:06 +0100141 print_car_debug(" Done\n");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200142
Paul Menzel42b62652015-11-07 09:15:06 +0100143 print_car_debug("Verifying data integrity in RAM...");
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500144 if (memcmp_(migrated_car, &_car_data_start[0], car_size) == 0)
Paul Menzel42b62652015-11-07 09:15:06 +0100145 print_car_debug(" Done\n");
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500146 else
Paul Menzel42b62652015-11-07 09:15:06 +0100147 print_car_debug(" FAILED\n");
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500148
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200149 /* New stack grows right below migrated_car. */
Paul Menzel42b62652015-11-07 09:15:06 +0100150 print_car_debug("Switching to use RAM as stack...");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200151 cache_as_ram_switch_stack(migrated_car);
152
153 /* We do not come back. */
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100154}
Yinghai Lud4b278c2006-10-04 20:46:15 +0000155
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200156void cache_as_ram_new_stack (void)
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100157{
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200158 void *resume_backup_memory = NULL;
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000159
Timothy Pearson83c3c9e2015-10-24 15:27:49 -0500160 print_car_debug("Top about %08x ... Done\n", (uint32_t) &resume_backup_memory);
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200161 print_car_debug("Disabling cache as ram now\n");
Zheng Bao8a0c6492010-03-19 08:23:50 +0000162 disable_cache_as_ram_bsp();
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000163
Rudolf Marekbcaea142010-11-22 22:00:52 +0000164 disable_cache();
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500165 /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */
Rudolf Marekbcaea142010-11-22 22:00:52 +0000166 set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
167 enable_cache();
168
Kyösti Mälkki78c5d582015-01-09 23:48:47 +0200169 if (acpi_is_wakeup_s3()) {
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200170 resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
Timothy Pearson20038442015-09-05 18:46:24 -0500171 print_car_debug("Resume backup memory location: %p\n", resume_backup_memory);
Rudolf Marekbcaea142010-11-22 22:00:52 +0000172 }
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200173 prepare_ramstage_region(resume_backup_memory);
Stefan Reinauer806e1462005-12-01 10:54:44 +0000174
Myles Watsonf326e3a2010-03-11 22:12:10 +0000175 set_sysinfo_in_ram(1); // So other core0 could start to train mem
Yinghai Lud4b278c2006-10-04 20:46:15 +0000176
Furquan Shaikh20f25dd2014-04-22 10:41:05 -0700177 /*copy and execute ramstage */
Stefan Reinauer648d1662013-05-06 18:05:39 -0700178 copy_and_run();
Myles Watsonf326e3a2010-03-11 22:12:10 +0000179 /* We will not return */
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000180
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200181 print_car_debug("should not be here -\n");
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000182}