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 | { |
Timothy Pearson | d657446 | 2015-10-24 14:09:49 -0500 | [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 | { |
Timothy Pearson | 83c3c9e | 2015-10-24 15:27:49 -0500 | [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 | { |
Timothy Pearson | d657446 | 2015-10-24 14:09:49 -0500 | [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 | |
| 64 | print_car_debug("Done\n"); |
| 65 | } |
| 66 | |
| 67 | static 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 Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 79 | print_car_debug("Done\n"); |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 80 | } |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 81 | |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 82 | /* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33 */ |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 83 | |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 84 | static void vErrata343(void) |
| 85 | { |
Myles Watson | 6e23576 | 2009-09-29 14:56:15 +0000 | [diff] [blame] | 86 | #ifdef BU_CFG2_MSR |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame^] | 87 | msr_t msr; |
| 88 | unsigned int uiMask = 0xFFFFFFF7; |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 89 | |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame^] | 90 | msr = rdmsr(BU_CFG2_MSR); |
| 91 | msr.hi &= uiMask; // IcDisSpecTlbWr (bit 35) = 0 |
| 92 | wrmsr(BU_CFG2_MSR, msr); |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 93 | #endif |
| 94 | } |
Yinghai Lu | d4b278c | 2006-10-04 20:46:15 +0000 | [diff] [blame] | 95 | |
Kyösti Mälkki | 142b52c | 2013-12-10 07:33:36 +0200 | [diff] [blame] | 96 | void post_cache_as_ram(void) |
Yinghai Lu | 9a791df | 2006-04-03 20:38:34 +0000 | [diff] [blame] | 97 | { |
Vladimir Serbinenko | a6c29fe | 2013-11-26 17:49:29 +0100 | [diff] [blame] | 98 | void *resume_backup_memory = NULL; |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame^] | 99 | uint32_t family = amd_fam1x_cpu_family(); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 100 | |
Timothy Pearson | 2003844 | 2015-09-05 18:46:24 -0500 | [diff] [blame] | 101 | 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älkki | 78c5d58 | 2015-01-09 23:48:47 +0200 | [diff] [blame] | 108 | int s3resume = acpi_is_wakeup_s3(); |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 109 | if (s3resume) { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 110 | cbmem_recovery(s3resume); |
| 111 | resume_backup_memory = cbmem_find(CBMEM_ID_RESUME); |
Myles Watson | f326e3a | 2010-03-11 22:12:10 +0000 | [diff] [blame] | 112 | } |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 113 | prepare_romstage_ramstack(resume_backup_memory); |
Yinghai Lu | 9a791df | 2006-04-03 20:38:34 +0000 | [diff] [blame] | 114 | |
| 115 | /* from here don't store more data in CAR */ |
Timothy Pearson | 730a043 | 2015-10-16 13:51:51 -0500 | [diff] [blame^] | 116 | if (family < 0x6f) { |
| 117 | /* Family 10h or earlier */ |
| 118 | vErrata343(); |
| 119 | } |
Marco Schmidt | c263b44 | 2009-06-06 11:21:52 +0000 | [diff] [blame] | 120 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 121 | 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 Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 128 | 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älkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 134 | /* 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 Serbinenko | a6c29fe | 2013-11-26 17:49:29 +0100 | [diff] [blame] | 139 | } |
Yinghai Lu | d4b278c | 2006-10-04 20:46:15 +0000 | [diff] [blame] | 140 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 141 | void cache_as_ram_new_stack (void) |
Vladimir Serbinenko | a6c29fe | 2013-11-26 17:49:29 +0100 | [diff] [blame] | 142 | { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 143 | void *resume_backup_memory = NULL; |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 144 | |
Timothy Pearson | 83c3c9e | 2015-10-24 15:27:49 -0500 | [diff] [blame] | 145 | 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] | 146 | print_car_debug("Disabling cache as ram now\n"); |
Zheng Bao | 8a0c649 | 2010-03-19 08:23:50 +0000 | [diff] [blame] | 147 | disable_cache_as_ram_bsp(); |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 148 | |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 149 | disable_cache(); |
Timothy Pearson | 1c4508e | 2015-09-05 17:50:29 -0500 | [diff] [blame] | 150 | /* Enable cached access to RAM in the range 1M to CONFIG_RAMTOP */ |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 151 | set_var_mtrr(0, 0x00000000, CONFIG_RAMTOP, MTRR_TYPE_WRBACK); |
| 152 | enable_cache(); |
| 153 | |
Kyösti Mälkki | 78c5d58 | 2015-01-09 23:48:47 +0200 | [diff] [blame] | 154 | if (acpi_is_wakeup_s3()) { |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 155 | resume_backup_memory = cbmem_find(CBMEM_ID_RESUME); |
Timothy Pearson | 2003844 | 2015-09-05 18:46:24 -0500 | [diff] [blame] | 156 | print_car_debug("Resume backup memory location: %p\n", resume_backup_memory); |
Rudolf Marek | bcaea14 | 2010-11-22 22:00:52 +0000 | [diff] [blame] | 157 | } |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 158 | prepare_ramstage_region(resume_backup_memory); |
Stefan Reinauer | 806e146 | 2005-12-01 10:54:44 +0000 | [diff] [blame] | 159 | |
Myles Watson | f326e3a | 2010-03-11 22:12:10 +0000 | [diff] [blame] | 160 | 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] | 161 | |
Furquan Shaikh | 20f25dd | 2014-04-22 10:41:05 -0700 | [diff] [blame] | 162 | /*copy and execute ramstage */ |
Stefan Reinauer | 648d166 | 2013-05-06 18:05:39 -0700 | [diff] [blame] | 163 | copy_and_run(); |
Myles Watson | f326e3a | 2010-03-11 22:12:10 +0000 | [diff] [blame] | 164 | /* We will not return */ |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 165 | |
Kyösti Mälkki | abc083e | 2013-12-29 12:07:54 +0200 | [diff] [blame] | 166 | print_car_debug("should not be here -\n"); |
Ronald G. Minnich | fb0a64b | 2005-11-23 21:01:08 +0000 | [diff] [blame] | 167 | } |