blob: e55ef408f3368dafa34cb191dee5f69a7e97a9cc [file] [log] [blame]
Damien Rothbedbd672016-01-18 13:59:26 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>,
5 * Raptor Engineering
Patrick Georgi5b2a2d02018-09-26 20:46:04 +02006 * Copyright (C) 2012 Google LLC
Timothy Pearson1c4508e2015-09-05 17:50:29 -05007 * 2005.6 by yhlu
Yinghai Lu9a791df2006-04-03 20:38:34 +00008 * 2006.3 yhlu add copy data from CAR to ram
Damien Rothbedbd672016-01-18 13:59:26 -07009 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; version 2 of the License.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
Yinghai Lu9a791df2006-04-03 20:38:34 +000018 */
Patrick Georgi3d5bb232010-05-09 21:15:13 +000019#include <string.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110020#include <console/console.h>
Stefan Reinaueraa987b22010-04-09 13:31:07 +000021#include <arch/stages.h>
Aaron Durbin0dc73542015-07-16 16:07:02 -050022#include <arch/early_variables.h>
Patrick Georgic928a292010-05-14 11:02:56 +000023#include <cpu/x86/mtrr.h>
Kyösti Mälkki88a67f02013-12-12 12:27:53 +020024#include <cpu/amd/mtrr.h>
Kyösti Mälkki2458f422014-04-22 16:46:31 +030025#include <cpu/amd/car.h>
Damien Zammit75a3d1f2016-11-28 00:29:10 +110026#include <cpu/amd/msr.h>
Kyösti Mälkki207880c2013-12-10 09:03:17 +020027#include <arch/acpi.h>
Timothy Pearson20038442015-09-05 18:46:24 -050028#include <romstage_handoff.h>
Kyösti Mälkkib98391c2017-07-13 13:14:16 +030029
Stefan Reinauer806e1462005-12-01 10:54:44 +000030#include "cpu/amd/car/disable_cache_as_ram.c"
31
Kyösti Mälkkib98391c2017-07-13 13:14:16 +030032// For set_sysinfo_in_ram()
Elyes HAOUAS65bb5432018-07-03 14:59:50 +020033#include <northbridge/amd/amdfam10/raminit.h>
Kyösti Mälkkib98391c2017-07-13 13:14:16 +030034
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020035#if CONFIG_RAMTOP <= 0x100000
36 #error "You need to set CONFIG_RAMTOP greater than 1M"
37#endif
38
Timothy Pearsond6574462015-10-24 14:09:49 -050039#if IS_ENABLED(CONFIG_DEBUG_CAR)
40#define print_car_debug(format, arg...) printk(BIOS_DEBUG, "%s: " format, __func__, ##arg)
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020041#else
Timothy Pearsond6574462015-10-24 14:09:49 -050042#define print_car_debug(format, arg...)
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020043#endif
44
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020045static size_t backup_size(void)
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +000046{
Aaron Durbin0dc73542015-07-16 16:07:02 -050047 size_t car_size = car_data_size();
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020048 return ALIGN(car_size + 1024, 1024);
Yinghai Lu9a791df2006-04-03 20:38:34 +000049}
Rudolf Marekbcaea142010-11-22 22:00:52 +000050
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020051static void memcpy_(void *d, const void *s, size_t len)
52{
Paul Menzel42b62652015-11-07 09:15:06 +010053 print_car_debug(" Copy [%08x-%08x] to [%08x - %08x] ...",
Evelyn Huangacd02b52017-05-30 15:35:22 -060054 (uint32_t) s, (uint32_t) (s + len - 1),
55 (uint32_t) d, (uint32_t) (d + len - 1));
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020056 memcpy(d, s, len);
57}
Rudolf Marekbcaea142010-11-22 22:00:52 +000058
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020059static void memset_(void *d, int val, size_t len)
60{
Evelyn Huangacd02b52017-05-30 15:35:22 -060061 print_car_debug(" Fill [%08x-%08x] ...",
62 (uint32_t) d, (uint32_t) (d + len - 1));
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020063 memset(d, val, len);
64}
Rudolf Marekbcaea142010-11-22 22:00:52 +000065
Timothy Pearson1c4508e2015-09-05 17:50:29 -050066static int memcmp_(void *d, const void *s, size_t len)
67{
Paul Menzel42b62652015-11-07 09:15:06 +010068 print_car_debug(" Compare [%08x-%08x] with [%08x - %08x] ...",
Evelyn Huangacd02b52017-05-30 15:35:22 -060069 (uint32_t) s, (uint32_t) (s + len - 1),
70 (uint32_t) d, (uint32_t) (d + len - 1));
Timothy Pearson1c4508e2015-09-05 17:50:29 -050071 return memcmp(d, s, len);
72}
73
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +030074static void prepare_romstage_ramstack(int s3resume)
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020075{
76 size_t backup_top = backup_size();
77 print_car_debug("Prepare CAR migration and stack regions...");
Rudolf Marekbcaea142010-11-22 22:00:52 +000078
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +030079 if (s3resume) {
Evelyn Huangacd02b52017-05-30 15:35:22 -060080 void *resume_backup_memory =
81 acpi_backup_container(CONFIG_RAMBASE, HIGH_MEMORY_SAVE);
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +030082 if (resume_backup_memory)
Evelyn Huangacd02b52017-05-30 15:35:22 -060083 memcpy_(resume_backup_memory
84 + HIGH_MEMORY_SAVE - backup_top,
85 (void *)(CONFIG_RAMTOP - backup_top),
86 backup_top);
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020087 }
88 memset_((void *)(CONFIG_RAMTOP - backup_top), 0, backup_top);
89
Paul Menzel42b62652015-11-07 09:15:06 +010090 print_car_debug(" Done\n");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020091}
92
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +030093static void prepare_ramstage_region(int s3resume)
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020094{
95 size_t backup_top = backup_size();
Paul Menzel42b62652015-11-07 09:15:06 +010096 print_car_debug("Prepare ramstage memory region...");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +020097
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +030098 if (s3resume) {
Evelyn Huangacd02b52017-05-30 15:35:22 -060099 void *resume_backup_memory =
100 acpi_backup_container(CONFIG_RAMBASE, HIGH_MEMORY_SAVE);
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +0300101 if (resume_backup_memory)
102 memcpy_(resume_backup_memory, (void *) CONFIG_RAMBASE,
103 HIGH_MEMORY_SAVE - backup_top);
Rudolf Marekbcaea142010-11-22 22:00:52 +0000104 }
105
Paul Menzel42b62652015-11-07 09:15:06 +0100106 print_car_debug(" Done\n");
Rudolf Marekbcaea142010-11-22 22:00:52 +0000107}
Rudolf Marekbcaea142010-11-22 22:00:52 +0000108
Jonathan A. Kollasch20d9fb42015-11-24 10:15:22 -0600109/* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33
110 * and RevGuide for Fam12h, Pub#44739 Rev 3.10
111 */
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000112
Marco Schmidtc263b442009-06-06 11:21:52 +0000113static void vErrata343(void)
114{
Timothy Pearson730a0432015-10-16 13:51:51 -0500115 msr_t msr;
116 unsigned int uiMask = 0xFFFFFFF7;
Marco Schmidtc263b442009-06-06 11:21:52 +0000117
Timothy Pearson730a0432015-10-16 13:51:51 -0500118 msr = rdmsr(BU_CFG2_MSR);
119 msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0
120 wrmsr(BU_CFG2_MSR, msr);
Marco Schmidtc263b442009-06-06 11:21:52 +0000121}
Yinghai Lud4b278c2006-10-04 20:46:15 +0000122
Elyes HAOUAS6c9737b2018-07-08 12:30:02 +0200123asmlinkage void *post_cache_as_ram(void)
Yinghai Lu9a791df2006-04-03 20:38:34 +0000124{
Timothy Pearson730a0432015-10-16 13:51:51 -0500125 uint32_t family = amd_fam1x_cpu_family();
Kyösti Mälkki916b3312017-09-04 23:43:30 +0300126 int s3resume = 0;
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200127
Timothy Pearson1f780992015-06-01 23:58:59 -0500128 /* Verify that the BSP didn't overrun the lower stack
129 * boundary during romstage execution
130 */
131 volatile uint32_t *lower_stack_boundary;
Evelyn Huangacd02b52017-05-30 15:35:22 -0600132 lower_stack_boundary =
133 (void *)((CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE)
134 - CONFIG_DCACHE_BSP_STACK_SIZE);
Timothy Pearson1f780992015-06-01 23:58:59 -0500135 if ((*lower_stack_boundary) != 0xdeadbeef)
136 printk(BIOS_WARNING, "BSP overran lower stack boundary. Undefined behaviour may result!\n");
137
Kyösti Mälkkie0e1e642018-06-03 06:53:30 +0300138 s3resume = acpi_is_wakeup_s3();
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +0300139
140 prepare_romstage_ramstack(s3resume);
Yinghai Lu9a791df2006-04-03 20:38:34 +0000141
Aaron Durbin77e13992016-11-29 17:43:04 -0600142 romstage_handoff_init(s3resume);
Kyösti Mälkkid1131902016-06-26 15:44:05 +0300143
Yinghai Lu9a791df2006-04-03 20:38:34 +0000144 /* from here don't store more data in CAR */
Jonathan A. Kollasch20d9fb42015-11-24 10:15:22 -0600145 if (family >= 0x1f && family <= 0x3f) {
146 /* Family 10h and 12h, 11h until shown otherwise */
Timothy Pearson730a0432015-10-16 13:51:51 -0500147 vErrata343();
148 }
Marco Schmidtc263b442009-06-06 11:21:52 +0000149
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200150 size_t car_size = car_data_size();
151 void *migrated_car = (void *)(CONFIG_RAMTOP - car_size);
152
Paul Menzel42b62652015-11-07 09:15:06 +0100153 print_car_debug("Copying data from cache to RAM...");
Andrey Petrovdd56de92016-02-25 17:22:17 -0800154 memcpy_(migrated_car, _car_relocatable_data_start, car_size);
Paul Menzel42b62652015-11-07 09:15:06 +0100155 print_car_debug(" Done\n");
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200156
Paul Menzel42b62652015-11-07 09:15:06 +0100157 print_car_debug("Verifying data integrity in RAM...");
Andrey Petrovdd56de92016-02-25 17:22:17 -0800158 if (memcmp_(migrated_car, _car_relocatable_data_start, car_size) == 0)
Paul Menzel42b62652015-11-07 09:15:06 +0100159 print_car_debug(" Done\n");
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500160 else
Paul Menzel42b62652015-11-07 09:15:06 +0100161 print_car_debug(" FAILED\n");
Timothy Pearson1c4508e2015-09-05 17:50:29 -0500162
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200163 /* New stack grows right below migrated_car. */
Paul Menzel42b62652015-11-07 09:15:06 +0100164 print_car_debug("Switching to use RAM as stack...");
Kyösti Mälkki14382452017-07-13 14:11:52 +0300165 return migrated_car;
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100166}
Yinghai Lud4b278c2006-10-04 20:46:15 +0000167
Kyösti Mälkki14382452017-07-13 14:11:52 +0300168asmlinkage void cache_as_ram_new_stack(void)
Vladimir Serbinenkoa6c29fe2013-11-26 17:49:29 +0100169{
Elyes HAOUAS585d1a02016-07-28 19:15:34 +0200170 print_car_debug("Disabling cache as RAM now\n");
Kyösti Mälkkib98391c2017-07-13 13:14:16 +0300171 disable_cache_as_ram_real(0); // inline
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000172
Rudolf Marekbcaea142010-11-22 22:00:52 +0000173 disable_cache();
Kyösti Mälkki65cc5262016-06-19 20:38:41 +0300174 /* Enable cached access to RAM in the range 0M to CACHE_TMP_RAMTOP */
175 set_var_mtrr(0, 0x00000000, CACHE_TMP_RAMTOP, MTRR_TYPE_WRBACK);
Rudolf Marekbcaea142010-11-22 22:00:52 +0000176 enable_cache();
177
Kyösti Mälkkic30bfca2016-06-28 07:38:03 +0300178 prepare_ramstage_region(acpi_is_wakeup_s3());
Stefan Reinauer806e1462005-12-01 10:54:44 +0000179
Myles Watsonf326e3a2010-03-11 22:12:10 +0000180 set_sysinfo_in_ram(1); // So other core0 could start to train mem
Yinghai Lud4b278c2006-10-04 20:46:15 +0000181
Furquan Shaikh20f25dd2014-04-22 10:41:05 -0700182 /*copy and execute ramstage */
Stefan Reinauer648d1662013-05-06 18:05:39 -0700183 copy_and_run();
Myles Watsonf326e3a2010-03-11 22:12:10 +0000184 /* We will not return */
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000185
Kyösti Mälkkiabc083e2013-12-29 12:07:54 +0200186 print_car_debug("should not be here -\n");
Ronald G. Minnichfb0a64b2005-11-23 21:01:08 +0000187}