blob: 49b9ee3fe3aed1f1ce27596ab4147decaa827572 [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{
Timothy Pearsond6574462015-10-24 14:09:49 -050035 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{
Timothy Pearson83c3c9e2015-10-24 15:27:49 -050042 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{
Timothy Pearsond6574462015-10-24 14:09:49 -050048 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
64 print_car_debug("Done\n");
65}
66
67static void prepare_ramstage_region(void *resume_backup_memory)
68{
69 size_t backup_top = backup_size();
70 print_car_debug("Prepare ramstage memory region... ");
71
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
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020079 print_car_debug("Done\n");
Rudolf Marekbcaea142010-11-22 22:00:52 +000080}
Rudolf Marekbcaea142010-11-22 22:00:52 +000081
Marco Schmidtc263b442009-06-06 11:21:52 +000082/* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33 */
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +000083
Marco Schmidtc263b442009-06-06 11:21:52 +000084static void vErrata343(void)
85{
Myles Watson6e235762009-09-29 14:56:15 +000086#ifdef BU_CFG2_MSR
Timothy Pearson730a0432015-10-16 13:51:51 -050087 msr_t msr;
88 unsigned int uiMask = 0xFFFFFFF7;
Marco Schmidtc263b442009-06-06 11:21:52 +000089
Timothy Pearson730a0432015-10-16 13:51:51 -050090 msr = rdmsr(BU_CFG2_MSR);
91 msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0
92 wrmsr(BU_CFG2_MSR, msr);
Marco Schmidtc263b442009-06-06 11:21:52 +000093#endif
94}
Yinghai Lud4b278c2006-10-04 20:46:15 +000095
Kyösti Mälkki142b52c2013-12-10 07:33:36 +020096void post_cache_as_ram(void)
Yinghai Lu9a791df2006-04-03 20:38:34 +000097{
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +010098 void *resume_backup_memory = NULL;
Timothy Pearson730a0432015-10-16 13:51:51 -050099 uint32_t family = amd_fam1x_cpu_family();
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200100
Timothy Pearson20038442015-09-05 18:46:24 -0500101 struct romstage_handoff *handoff;
102 handoff = romstage_handoff_find_or_add();
103 if (handoff != NULL)
104 handoff->s3_resume = acpi_is_wakeup_s3();
105 else
106 printk(BIOS_DEBUG, "Romstage handoff structure not added!\n");
107
Kyösti Mälkki78c5d582015-01-09 23:48:47 +0200108 int s3resume = acpi_is_wakeup_s3();
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200109 if (s3resume) {
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200110 cbmem_recovery(s3resume);
111 resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
Myles Watsonf326e3a2010-03-11 22:12:10 +0000112 }
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200113 prepare_romstage_ramstack(resume_backup_memory);
Yinghai Lu9a791df2006-04-03 20:38:34 +0000114
115 /* from here don't store more data in CAR */
Timothy Pearson730a0432015-10-16 13:51:51 -0500116 if (family < 0x6f) {
117 /* Family 10h or earlier */
118 vErrata343();
119 }
Marco Schmidtc263b442009-06-06 11:21:52 +0000120
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200121 size_t car_size = car_data_size();
122 void *migrated_car = (void *)(CONFIG_RAMTOP - car_size);
123
124 print_car_debug("Copying data from cache to RAM... ");
125 memcpy_(migrated_car, &_car_data_start[0], car_size);
126 print_car_debug("Done\n");
127
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500128 print_car_debug("Verifying data integrity in RAM... ");
129 if (memcmp_(migrated_car, &_car_data_start[0], car_size) == 0)
130 print_car_debug("Done\n");
131 else
132 print_car_debug("FAILED\n");
133
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200134 /* New stack grows right below migrated_car. */
135 print_car_debug("Switching to use RAM as stack... ");
136 cache_as_ram_switch_stack(migrated_car);
137
138 /* We do not come back. */
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100139}
Yinghai Lud4b278c2006-10-04 20:46:15 +0000140
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200141void cache_as_ram_new_stack (void)
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100142{
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200143 void *resume_backup_memory = NULL;
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000144
Timothy Pearson83c3c9e2015-10-24 15:27:49 -0500145 print_car_debug("Top about %08x ... Done\n", (uint32_t) &resume_backup_memory);
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200146 print_car_debug("Disabling cache as ram now\n");
Zheng Bao8a0c6492010-03-19 08:23:50 +0000147 disable_cache_as_ram_bsp();
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000148
Rudolf Marekbcaea142010-11-22 22:00:52 +0000149 disable_cache();
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500150 /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */
Rudolf Marekbcaea142010-11-22 22:00:52 +0000151 set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK);
152 enable_cache();
153
Kyösti Mälkki78c5d582015-01-09 23:48:47 +0200154 if (acpi_is_wakeup_s3()) {
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200155 resume_backup_memory = cbmem_find(CBMEM_ID_RESUME);
Timothy Pearson20038442015-09-05 18:46:24 -0500156 print_car_debug("Resume backup memory location: %p\n", resume_backup_memory);
Rudolf Marekbcaea142010-11-22 22:00:52 +0000157 }
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200158 prepare_ramstage_region(resume_backup_memory);
Stefan Reinauer806e1462005-12-01 10:54:44 +0000159
Myles Watsonf326e3a2010-03-11 22:12:10 +0000160 set_sysinfo_in_ram(1); // So other core0 could start to train mem
Yinghai Lud4b278c2006-10-04 20:46:15 +0000161
Furquan Shaikh20f25dd2014-04-22 10:41:05 -0700162 /*copy and execute ramstage */
Stefan Reinauer648d1662013-05-06 18:05:39 -0700163 copy_and_run();
Myles Watsonf326e3a2010-03-11 22:12:10 +0000164 /* We will not return */
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000165
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200166 print_car_debug("should not be here -\n");
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000167}