2 * This file is part of the coreboot project.
4 * Copyright (C) 2015 Timothy Pearson <tpearson@raptorengineeringinc.com>,
6 * Copyright (C) 2012 ChromeOS Authors
8 * 2006.3 yhlu add copy data from CAR to ram
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.
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.
20 #include <arch/stages.h>
21 #include <arch/early_variables.h>
22 #include <cpu/x86/mtrr.h>
23 #include <cpu/amd/mtrr.h>
24 #include <cpu/amd/car.h>
25 #include <arch/acpi.h>
26 #include <romstage_handoff.h>
28 #include "cpu/amd/car/disable_cache_as_ram.c"
30 #if CONFIG_RAMTOP <= 0x100000
31 #error "You need to set CONFIG_RAMTOP greater than 1M"
34 #if IS_ENABLED(CONFIG_DEBUG_CAR)
35 #define print_car_debug(format, arg...) printk(BIOS_DEBUG, "%s: " format, __func__, ##arg)
37 #define print_car_debug(format, arg...)
40 static size_t backup_size(void)
42 size_t car_size
= car_data_size();
43 return ALIGN(car_size
+ 1024, 1024);
46 static void memcpy_(void *d
, const void *s
, size_t len
)
48 print_car_debug(" Copy [%08x-%08x] to [%08x - %08x] ...",
49 (uint32_t) s
, (uint32_t) (s
+ len
- 1), (uint32_t) d
, (uint32_t) (d
+ len
- 1));
53 static void memset_(void *d
, int val
, size_t len
)
55 print_car_debug(" Fill [%08x-%08x] ...", (uint32_t) d
, (uint32_t) (d
+ len
- 1));
59 static int memcmp_(void *d
, const void *s
, size_t len
)
61 print_car_debug(" Compare [%08x-%08x] with [%08x - %08x] ...",
62 (uint32_t) s
, (uint32_t) (s
+ len
- 1), (uint32_t) d
, (uint32_t) (d
+ len
- 1));
63 return memcmp(d
, s
, len
);
66 static void prepare_romstage_ramstack(int s3resume
)
68 size_t backup_top
= backup_size();
69 print_car_debug("Prepare CAR migration and stack regions...");
72 void *resume_backup_memory
= cbmem_find(CBMEM_ID_RESUME
);
73 if (resume_backup_memory
)
74 memcpy_(resume_backup_memory
+ HIGH_MEMORY_SAVE
- backup_top
,
75 (void *)(CONFIG_RAMTOP
- backup_top
), backup_top
);
77 memset_((void *)(CONFIG_RAMTOP
- backup_top
), 0, backup_top
);
79 print_car_debug(" Done\n");
82 static void prepare_ramstage_region(int s3resume
)
84 size_t backup_top
= backup_size();
85 print_car_debug("Prepare ramstage memory region...");
88 void *resume_backup_memory
= cbmem_find(CBMEM_ID_RESUME
);
89 if (resume_backup_memory
)
90 memcpy_(resume_backup_memory
, (void *) CONFIG_RAMBASE
,
91 HIGH_MEMORY_SAVE
- backup_top
);
92 memset_((void*) CONFIG_RAMBASE
, 0, HIGH_MEMORY_SAVE
- backup_top
);
94 memset_((void*)0, 0, CONFIG_RAMTOP
- backup_top
);
97 print_car_debug(" Done\n");
100 /* Disable Erratum 343 Workaround, see RevGuide for Fam10h, Pub#41322 Rev 3.33
101 * and RevGuide for Fam12h, Pub#44739 Rev 3.10
104 static void vErrata343(void)
107 unsigned int uiMask
= 0xFFFFFFF7;
109 msr
= rdmsr(BU_CFG2_MSR
);
110 msr
.hi
&= uiMask
; // IcDisSpecTlbWr (bit 35) = 0
111 wrmsr(BU_CFG2_MSR
, msr
);
114 void post_cache_as_ram(void)
116 uint32_t family
= amd_fam1x_cpu_family();
118 /* Verify that the BSP didn't overrun the lower stack
119 * boundary during romstage execution
121 volatile uint32_t *lower_stack_boundary
;
122 lower_stack_boundary
= (void *)((CONFIG_DCACHE_RAM_BASE
+ CONFIG_DCACHE_RAM_SIZE
) - CONFIG_DCACHE_BSP_STACK_SIZE
);
123 if ((*lower_stack_boundary
) != 0xdeadbeef)
124 printk(BIOS_WARNING
, "BSP overran lower stack boundary. Undefined behaviour may result!\n");
126 int s3resume
= acpi_is_wakeup_s3();
128 /* Boards with EARLY_CBMEM_INIT need to do this in cache_as_ram_main().
130 if (s3resume
&& !IS_ENABLED(CONFIG_EARLY_CBMEM_INIT
))
131 cbmem_recovery(s3resume
);
133 prepare_romstage_ramstack(s3resume
);
135 if (IS_ENABLED(CONFIG_EARLY_CBMEM_INIT
)) {
136 struct romstage_handoff
*handoff
;
137 handoff
= romstage_handoff_find_or_add();
139 handoff
->s3_resume
= s3resume
;
141 printk(BIOS_DEBUG
, "Romstage handoff structure not added!\n");
144 /* from here don't store more data in CAR */
145 if (family
>= 0x1f && family
<= 0x3f) {
146 /* Family 10h and 12h, 11h until shown otherwise */
150 size_t car_size
= car_data_size();
151 void *migrated_car
= (void *)(CONFIG_RAMTOP
- car_size
);
153 print_car_debug("Copying data from cache to RAM...");
154 memcpy_(migrated_car
, _car_relocatable_data_start
, car_size
);
155 print_car_debug(" Done\n");
157 print_car_debug("Verifying data integrity in RAM...");
158 if (memcmp_(migrated_car
, _car_relocatable_data_start
, car_size
) == 0)
159 print_car_debug(" Done\n");
161 print_car_debug(" FAILED\n");
163 /* New stack grows right below migrated_car. */
164 print_car_debug("Switching to use RAM as stack...");
165 cache_as_ram_switch_stack(migrated_car
);
167 /* We do not come back. */
170 void cache_as_ram_new_stack (void)
172 print_car_debug("Disabling cache as ram now\n");
173 disable_cache_as_ram_bsp();
176 /* Enable cached access to RAM in the range 0M to CACHE_TMP_RAMTOP */
177 set_var_mtrr(0, 0x00000000, CACHE_TMP_RAMTOP
, MTRR_TYPE_WRBACK
);
180 prepare_ramstage_region(acpi_is_wakeup_s3());
182 set_sysinfo_in_ram(1); // So other core0 could start to train mem
184 /*copy and execute ramstage */
186 /* We will not return */
188 print_car_debug("should not be here -\n");