blob: fc3212f1fc3f4797b54a3013c64ff568a01c4334 [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Damien Rothbedbd672016-01-18 13:59:26 -07002
Kyösti Mälkki2446c1e2020-07-09 07:13:37 +03003#include <amdblocks/biosram.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00004#include <console/console.h>
5#include <device/device.h>
Tobias Diedrichc2924672010-11-09 22:31:11 +00006#include <arch/cpu.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00007#include <cpu/x86/mtrr.h>
Kyösti Mälkki190011e2013-03-25 12:48:49 +02008#include <cpu/x86/msr.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00009#include <cpu/amd/mtrr.h>
10#include <cpu/x86/cache.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000011
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030012/* These will likely move to some device node or cbmem. */
13static uint64_t amd_topmem = 0;
14static uint64_t amd_topmem2 = 0;
15
16uint64_t bsp_topmem(void)
17{
18 return amd_topmem;
19}
20
21uint64_t bsp_topmem2(void)
22{
23 return amd_topmem2;
24}
25
26/* Take a copy of BSP CPUs TOP_MEM and TOP_MEM2 registers,
27 * so they can be distributed to AP CPUs. Not strictly MTRRs,
28 * but this is not that bad a place to have this code.
29 */
30void setup_bsp_ramtop(void)
31{
32 msr_t msr, msr2;
33
34 /* TOP_MEM: the top of DRAM below 4G */
35 msr = rdmsr(TOP_MEM);
36 printk(BIOS_INFO,
37 "%s, TOP MEM: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
38 __func__, msr.lo, msr.hi);
39
40 /* TOP_MEM2: the top of DRAM above 4G */
41 msr2 = rdmsr(TOP_MEM2);
42 printk(BIOS_INFO,
43 "%s, TOP MEM2: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
44 __func__, msr2.lo, msr2.hi);
45
Elyes HAOUAS168ef392017-06-27 22:54:42 +020046 amd_topmem = (uint64_t) msr.hi << 32 | msr.lo;
47 amd_topmem2 = (uint64_t) msr2.hi << 32 | msr2.lo;
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030048}
49
Kyösti Mälkki9de0fee2012-08-05 12:12:05 +030050static void setup_ap_ramtop(void)
51{
52 msr_t msr;
53 uint64_t v;
54
55 v = bsp_topmem();
56 if (!v)
57 return;
58
59 msr.hi = v >> 32;
60 msr.lo = (uint32_t) v;
61 wrmsr(TOP_MEM, msr);
62
63 v = bsp_topmem2();
64 msr.hi = v >> 32;
65 msr.lo = (uint32_t) v;
66 wrmsr(TOP_MEM2, msr);
67}
68
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030069void add_uma_resource_below_tolm(struct device *nb, int idx)
70{
71 uint32_t topmem = bsp_topmem();
Kyösti Mälkki70d92b92017-04-19 19:57:01 +030072 uint32_t top_of_cacheable = restore_top_of_low_cacheable();
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030073
74 if (top_of_cacheable == topmem)
75 return;
76
77 uint32_t uma_base = top_of_cacheable;
78 uint32_t uma_size = topmem - top_of_cacheable;
79
80 printk(BIOS_INFO, "%s: uma size 0x%08x, memory start 0x%08x\n",
81 __func__, uma_size, uma_base);
82
83 uma_resource(nb, idx, uma_base / KiB, uma_size / KiB);
84}
85
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000086void amd_setup_mtrrs(void)
87{
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000088 unsigned long address_bits;
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000089 unsigned long i;
Scott Duplichanf3cce2f2010-11-13 19:07:59 +000090 msr_t msr, sys_cfg;
Oskar Enoksson07bf9112011-10-06 18:21:19 +020091 // Test if this CPU is a Fam 0Fh rev. F or later
92 const int cpu_id = cpuid_eax(0x80000001);
Marc Jonesd8d8c632012-01-30 19:30:45 -070093 printk(BIOS_SPEW, "CPU ID 0x80000001: %x\n", cpu_id);
Oskar Enoksson07bf9112011-10-06 18:21:19 +020094 const int has_tom2wb =
Evelyn Huangccc55132017-06-07 12:02:48 -060095 // ExtendedFamily > 0
96 (((cpu_id>>20)&0xf) > 0) ||
97 // Family == 0F
98 ((((cpu_id>>8)&0xf) == 0xf) &&
99 // Rev>=F deduced from rev tables
100 (((cpu_id>>16)&0xf) >= 0x4));
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200101 if (has_tom2wb)
Marc Jonesd8d8c632012-01-30 19:30:45 -0700102 printk(BIOS_DEBUG, "CPU is Fam 0Fh rev.F or later. We can use TOM2WB for any memory above 4GB\n");
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000103
Eric Biedermana1653cf2004-10-22 04:41:53 +0000104 /* Enable the access to AMD RdDram and WrDram extension bits */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000105 disable_cache();
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000106 sys_cfg = rdmsr(SYSCFG_MSR);
107 sys_cfg.lo |= SYSCFG_MSR_MtrrFixDramModEn;
108 wrmsr(SYSCFG_MSR, sys_cfg);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000109 enable_cache();
Eric Biedermanf3aa4702004-10-21 02:53:25 +0000110
Aaron Durbin57686f82013-03-20 15:50:59 -0500111 /* Setup fixed MTRRs, but do not enable them just yet. */
112 x86_setup_fixed_mtrrs_no_enable();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000113
114 disable_cache();
115
Kyösti Mälkki9de0fee2012-08-05 12:12:05 +0300116 setup_ap_ramtop();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000117
Kyösti Mälkki2354515f2012-07-12 01:18:31 +0300118 /* if DRAM above 4GB: set SYSCFG_MSR_TOM2En and SYSCFG_MSR_TOM2WB */
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000119 sys_cfg.lo &= ~(SYSCFG_MSR_TOM2En | SYSCFG_MSR_TOM2WB);
Elyes HAOUAS168ef392017-06-27 22:54:42 +0200120 if (bsp_topmem2() > (uint64_t)1 << 32) {
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200121 sys_cfg.lo |= SYSCFG_MSR_TOM2En;
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200122 if (has_tom2wb)
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200123 sys_cfg.lo |= SYSCFG_MSR_TOM2WB;
Yinghai Lu30576602005-12-14 20:16:49 +0000124 }
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000125
126 /* zero the IORR's before we enable to prevent
127 * undefined side effects.
128 */
129 msr.lo = msr.hi = 0;
Elyes HAOUASd35c7fe2018-10-30 07:07:00 +0100130 for (i = MTRR_IORR0_BASE; i <= MTRR_IORR1_MASK; i++)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000131 wrmsr(i, msr);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000132
Stefan Reinauer14e22772010-04-27 06:56:47 +0000133 /* Enable Variable Mtrrs
Eric Biedermana1653cf2004-10-22 04:41:53 +0000134 * Enable the RdMem and WrMem bits in the fixed mtrrs.
135 * Disable access to the RdMem and WrMem in the fixed mtrr.
136 */
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000137 sys_cfg.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn;
138 sys_cfg.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
139 wrmsr(SYSCFG_MSR, sys_cfg);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000140
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000141 enable_fixed_mtrr();
142
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000143 enable_cache();
Eric Biedermana1653cf2004-10-22 04:41:53 +0000144
Evelyn Huangccc55132017-06-07 12:02:48 -0600145 //K8 could be 40, and GH could be 48
146 address_bits = CONFIG_CPU_ADDR_BITS;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000147
Tobias Diedrichc2924672010-11-09 22:31:11 +0000148 /* AMD specific cpuid function to query number of address bits */
Evelyn Huangccc55132017-06-07 12:02:48 -0600149 if (cpuid_eax(0x80000000) >= 0x80000008)
Tobias Diedrichc2924672010-11-09 22:31:11 +0000150 address_bits = cpuid_eax(0x80000008) & 0xff;
Tobias Diedrichc2924672010-11-09 22:31:11 +0000151
Eric Biedermana1653cf2004-10-22 04:41:53 +0000152 /* Now that I have mapped what is memory and what is not
Martin Roth4c3ab732013-07-08 16:23:54 -0600153 * Set up the mtrrs so we can cache the memory.
Eric Biedermana1653cf2004-10-22 04:41:53 +0000154 */
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200155
Martin Roth4c3ab732013-07-08 16:23:54 -0600156 // Rev. F K8 supports has SYSCFG_MSR_TOM2WB and doesn't need
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200157 // variable MTRR to span memory above 4GB
158 // Lower revisions K8 need variable MTRR over 4GB
159 x86_setup_var_mtrrs(address_bits, has_tom2wb ? 0 : 1);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000160}