Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 1 | /* Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>, Raptor Engineering |
Timothy Pearson | 2003844 | 2015-09-05 18:46:24 -0500 | [diff] [blame] | 2 | * Copyright (C) 2012 ChromeOS Authors |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 3 | * 2005.6 by yhlu |
Yinghai Lu | 9a791df | 2006-04-03 20:38:34 +0000 | [diff] [blame] | 4 | * 2006.3 yhlu add copy data from CAR to ram |
| 5 | */ |
Patrick Georgi | 3d5bb23 | 2010-05-09 21:15:13 +0000 | [diff] [blame] | 6 | #include <string.h> |
Stefan Reinauer | aa987b2 | 2010-04-09 13:31:07 +0000 | [diff] [blame] | 7 | #include <arch/stages.h> |
Aaron Durbin | 0dc7354 | 2015-07-16 16:07:02 -0500 | [diff] [blame] | 8 | #include <arch/early_variables.h> |
Patrick Georgi | c928a29 | 2010-05-14 11:02:56 +0000 | [diff] [blame] | 9 | #include <cpu/x86/mtrr.h> |
Kyösti Mälkki | 88a67f0 | 2013-12-12 12:27:53 +0200 | [diff] [blame] | 10 | #include <cpu/amd/mtrr.h> |
Kyösti Mälkki | 2458f42 | 2014-04-22 16:46:31 +0300 | [diff] [blame] | 11 | #include <cpu/amd/car.h> |
Kyösti Mälkki | 207880c | 2013-12-10 09:03:17 +0200 | [diff] [blame] | 12 | #include <arch/acpi.h> |
Timothy Pearson | 2003844 | 2015-09-05 18:46:24 -0500 | [diff] [blame] | 13 | #include <romstage_handoff.h> |
efdesign98 | 00c8c4a | 2011-07-20 12:37:58 -0600 | [diff] [blame] | 14 | #include "cbmem.h" |
Stefan Reinauer | 806e146 | 2005-12-01 10:54:44 +0000 | [diff] [blame] | 15 | #include "cpu/amd/car/disable_cache_as_ram.c" |
| 16 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 17 | #if CONFIG_RAMTOP <= 0x100000 |
| 18 | #error "You need to set CONFIG_RAMTOP greater than 1M" |
| 19 | #endif |
| 20 | |
Timothy Pearson | d657446 | 2015-10-24 14:09:49 -0500 | [diff] [blame] | 21 | #if IS_ENABLED(CONFIG_DEBUG_CAR) |
| 22 | #define print_car_debug(format, arg...) printk(BIOS_DEBUG, "%s: " format, __func__, ##arg) |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 23 | #else |
Timothy Pearson | d657446 | 2015-10-24 14:09:49 -0500 | [diff] [blame] | 24 | #define print_car_debug(format, arg...) |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 25 | #endif |
| 26 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 27 | static size_t backup_size(void) |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 28 | { |
Aaron Durbin | 0dc7354 | 2015-07-16 16:07:02 -0500 | [diff] [blame] | 29 | size_t car_size = car_data_size(); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 30 | return ALIGN(car_size + 1024, 1024); |
Yinghai Lu | 9a791df | 2006-04-03 20:38:34 +0000 | [diff] [blame] | 31 | } |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 32 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 33 | static void memcpy_(void *d, const void *s, size_t len) |
| 34 | { |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 35 | print_car_debug(" Copy [%08x-%08x] to [%08x - %08x] ...", |
Timothy Pearson | 83c3c9e | 2015-10-24 15:27:49 -0500 | [diff] [blame] | 36 | (uint32_t) s, (uint32_t) (s + len - 1), (uint32_t) d, (uint32_t) (d + len - 1)); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 37 | memcpy(d, s, len); |
| 38 | } |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 39 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 40 | static void memset_(void *d, int val, size_t len) |
| 41 | { |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 42 | print_car_debug(" Fill [%08x-%08x] ...", (uint32_t) d, (uint32_t) (d + len - 1)); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 43 | memset(d, val, len); |
| 44 | } |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 45 | |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 46 | static int memcmp_(void *d, const void *s, size_t len) |
| 47 | { |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 48 | print_car_debug(" Compare [%08x-%08x] with [%08x - %08x] ...", |
Timothy Pearson | 83c3c9e | 2015-10-24 15:27:49 -0500 | [diff] [blame] | 49 | (uint32_t) s, (uint32_t) (s + len - 1), (uint32_t) d, (uint32_t) (d + len - 1)); |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 50 | return memcmp(d, s, len); |
| 51 | } |
| 52 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 53 | static 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 Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 57 | |
| 58 | if (resume_backup_memory) { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 59 | 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 Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 64 | print_car_debug(" Done\n"); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 65 | } |
| 66 | |
| 67 | static void prepare_ramstage_region(void *resume_backup_memory) |
| 68 | { |
| 69 | size_t backup_top = backup_size(); |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 70 | print_car_debug("Prepare ramstage memory region..."); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 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 Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Timothy Pearson | 44d5342 | 2015-05-18 16:04:10 -0500 | [diff] [blame] | 79 | #if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_CONSOLE_SPINLOCK) |
| 80 | initialize_romstage_console_lock(); |
| 81 | #endif |
Timothy Pearson | 7b22d84 | 2015-08-28 19:52:05 -0500 | [diff] [blame] | 82 | #if IS_ENABLED(CONFIG_HAVE_ROMSTAGE_NVRAM_CBFS_SPINLOCK) |
| 83 | initialize_romstage_nvram_cbfs_lock(); |
| 84 | #endif |
Timothy Pearson | 44d5342 | 2015-05-18 16:04:10 -0500 | [diff] [blame] | 85 | |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 86 | print_car_debug(" Done\n"); |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 87 | } |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 88 | |
Jonathan A. Kollasch | 20d9fb4 | 2015-11-24 10:15:22 -0600 | [diff] [blame] | 89 | /* 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. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 92 | |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 93 | static void vErrata343(void) |
| 94 | { |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 95 | msr_t msr; |
| 96 | unsigned int uiMask = 0xFFFFFFF7; |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 97 | |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 98 | msr = rdmsr(BU_CFG2_MSR); |
| 99 | msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0 |
| 100 | wrmsr(BU_CFG2_MSR, msr); |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 101 | } |
Yinghai Lu | d4b278c | 2006-10-04 20:46:15 +0000 | [diff] [blame] | 102 | |
Kyösti Mälkki | 142b52c | 2013-12-10 07:33:36 +0200 | [diff] [blame] | 103 | void post_cache_as_ram(void) |
Yinghai Lu | 9a791df | 2006-04-03 20:38:34 +0000 | [diff] [blame] | 104 | { |
Vladimir Serbinenko | a6c29fe | 2013-11-26 17:49:29 +0100 | [diff] [blame] | 105 | void *resume_backup_memory = NULL; |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 106 | uint32_t family = amd_fam1x_cpu_family(); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 107 | |
Timothy Pearson | 1f78099 | 2015-06-01 23:58:59 -0500 | [diff] [blame] | 108 | /* 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 Pearson | 2003844 | 2015-09-05 18:46:24 -0500 | [diff] [blame] | 116 | 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älkki | 78c5d58 | 2015-01-09 23:48:47 +0200 | [diff] [blame] | 123 | int s3resume = acpi_is_wakeup_s3(); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 124 | if (s3resume) { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 125 | cbmem_recovery(s3resume); |
| 126 | resume_backup_memory = cbmem_find(CBMEM_ID_RESUME); |
Myles Watson | f326e3a | 2010-03-11 22:12:10 +0000 | [diff] [blame] | 127 | } |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 128 | prepare_romstage_ramstack(resume_backup_memory); |
Yinghai Lu | 9a791df | 2006-04-03 20:38:34 +0000 | [diff] [blame] | 129 | |
| 130 | /* from here don't store more data in CAR */ |
Jonathan A. Kollasch | 20d9fb4 | 2015-11-24 10:15:22 -0600 | [diff] [blame] | 131 | if (family >= 0x1f && family <= 0x3f) { |
| 132 | /* Family 10h and 12h, 11h until shown otherwise */ |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame] | 133 | vErrata343(); |
| 134 | } |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 135 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 136 | size_t car_size = car_data_size(); |
| 137 | void *migrated_car = (void *)(CONFIG_RAMTOP - car_size); |
| 138 | |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 139 | print_car_debug("Copying data from cache to RAM..."); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 140 | memcpy_(migrated_car, &_car_data_start[0], car_size); |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 141 | print_car_debug(" Done\n"); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 142 | |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 143 | print_car_debug("Verifying data integrity in RAM..."); |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 144 | if (memcmp_(migrated_car, &_car_data_start[0], car_size) == 0) |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 145 | print_car_debug(" Done\n"); |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 146 | else |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 147 | print_car_debug(" FAILED\n"); |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 148 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 149 | /* New stack grows right below migrated_car. */ |
Paul Menzel | 42b6265 | 2015-11-07 09:15:06 +0100 | [diff] [blame] | 150 | print_car_debug("Switching to use RAM as stack..."); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 151 | cache_as_ram_switch_stack(migrated_car); |
| 152 | |
| 153 | /* We do not come back. */ |
Vladimir Serbinenko | a6c29fe | 2013-11-26 17:49:29 +0100 | [diff] [blame] | 154 | } |
Yinghai Lu | d4b278c | 2006-10-04 20:46:15 +0000 | [diff] [blame] | 155 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 156 | void cache_as_ram_new_stack (void) |
Vladimir Serbinenko | a6c29fe | 2013-11-26 17:49:29 +0100 | [diff] [blame] | 157 | { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 158 | void *resume_backup_memory = NULL; |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 159 | |
Timothy Pearson | 83c3c9e | 2015-10-24 15:27:49 -0500 | [diff] [blame] | 160 | print_car_debug("Top about %08x ... Done\n", (uint32_t) &resume_backup_memory); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 161 | print_car_debug("Disabling cache as ram now\n"); |
Zheng Bao | 8a0c649 | 2010-03-19 08:23:50 +0000 | [diff] [blame] | 162 | disable_cache_as_ram_bsp(); |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 163 | |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 164 | disable_cache(); |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 165 | /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */ |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 166 | set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK); |
| 167 | enable_cache(); |
| 168 | |
Kyösti Mälkki | 78c5d58 | 2015-01-09 23:48:47 +0200 | [diff] [blame] | 169 | if (acpi_is_wakeup_s3()) { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 170 | resume_backup_memory = cbmem_find(CBMEM_ID_RESUME); |
Timothy Pearson | 2003844 | 2015-09-05 18:46:24 -0500 | [diff] [blame] | 171 | print_car_debug("Resume backup memory location: %p\n", resume_backup_memory); |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 172 | } |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 173 | prepare_ramstage_region(resume_backup_memory); |
Stefan Reinauer | 806e146 | 2005-12-01 10:54:44 +0000 | [diff] [blame] | 174 | |
Myles Watson | f326e3a | 2010-03-11 22:12:10 +0000 | [diff] [blame] | 175 | set_sysinfo_in_ram(1); // So other core0 could start to train mem |
Yinghai Lu | d4b278c | 2006-10-04 20:46:15 +0000 | [diff] [blame] | 176 | |
Furquan Shaikh | 20f25dd | 2014-04-22 10:41:05 -0700 | [diff] [blame] | 177 | /*copy and execute ramstage */ |
Stefan Reinauer | 648d166 | 2013-05-06 18:05:39 -0700 | [diff] [blame] | 178 | copy_and_run(); |
Myles Watson | f326e3a | 2010-03-11 22:12:10 +0000 | [diff] [blame] | 179 | /* We will not return */ |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 180 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 181 | print_car_debug("should not be here -\n"); |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 182 | } |