blob: ca2aab57a048f159c142c56e5c03c6639dee0b8e [file] [log] [blame]
Angel Ponsf23ae0b2020-04-02 23:48:12 +02001/* SPDX-License-Identifier: GPL-2.0-only */
2/* This file is part of the coreboot project. */
Damien Rothbedbd672016-01-18 13:59:26 -07003
Kyösti Mälkki17bb2252017-04-19 19:55:54 +03004#include <cbmem.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00005#include <console/console.h>
6#include <device/device.h>
Tobias Diedrichc2924672010-11-09 22:31:11 +00007#include <arch/cpu.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +00008#include <cpu/x86/mtrr.h>
Kyösti Mälkki190011e2013-03-25 12:48:49 +02009#include <cpu/x86/msr.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000010#include <cpu/amd/mtrr.h>
11#include <cpu/x86/cache.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000012
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030013/* These will likely move to some device node or cbmem. */
14static uint64_t amd_topmem = 0;
15static uint64_t amd_topmem2 = 0;
16
17uint64_t bsp_topmem(void)
18{
19 return amd_topmem;
20}
21
22uint64_t bsp_topmem2(void)
23{
24 return amd_topmem2;
25}
26
27/* Take a copy of BSP CPUs TOP_MEM and TOP_MEM2 registers,
28 * so they can be distributed to AP CPUs. Not strictly MTRRs,
29 * but this is not that bad a place to have this code.
30 */
31void setup_bsp_ramtop(void)
32{
33 msr_t msr, msr2;
34
35 /* TOP_MEM: the top of DRAM below 4G */
36 msr = rdmsr(TOP_MEM);
37 printk(BIOS_INFO,
38 "%s, TOP MEM: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
39 __func__, msr.lo, msr.hi);
40
41 /* TOP_MEM2: the top of DRAM above 4G */
42 msr2 = rdmsr(TOP_MEM2);
43 printk(BIOS_INFO,
44 "%s, TOP MEM2: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
45 __func__, msr2.lo, msr2.hi);
46
Elyes HAOUAS168ef392017-06-27 22:54:42 +020047 amd_topmem = (uint64_t) msr.hi << 32 | msr.lo;
48 amd_topmem2 = (uint64_t) msr2.hi << 32 | msr2.lo;
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030049}
50
Kyösti Mälkki9de0fee2012-08-05 12:12:05 +030051static void setup_ap_ramtop(void)
52{
53 msr_t msr;
54 uint64_t v;
55
56 v = bsp_topmem();
57 if (!v)
58 return;
59
60 msr.hi = v >> 32;
61 msr.lo = (uint32_t) v;
62 wrmsr(TOP_MEM, msr);
63
64 v = bsp_topmem2();
65 msr.hi = v >> 32;
66 msr.lo = (uint32_t) v;
67 wrmsr(TOP_MEM2, msr);
68}
69
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030070void add_uma_resource_below_tolm(struct device *nb, int idx)
71{
72 uint32_t topmem = bsp_topmem();
Kyösti Mälkki70d92b92017-04-19 19:57:01 +030073 uint32_t top_of_cacheable = restore_top_of_low_cacheable();
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030074
75 if (top_of_cacheable == topmem)
76 return;
77
78 uint32_t uma_base = top_of_cacheable;
79 uint32_t uma_size = topmem - top_of_cacheable;
80
81 printk(BIOS_INFO, "%s: uma size 0x%08x, memory start 0x%08x\n",
82 __func__, uma_size, uma_base);
83
84 uma_resource(nb, idx, uma_base / KiB, uma_size / KiB);
85}
86
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000087void amd_setup_mtrrs(void)
88{
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000089 unsigned long address_bits;
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000090 unsigned long i;
Scott Duplichanf3cce2f2010-11-13 19:07:59 +000091 msr_t msr, sys_cfg;
Oskar Enoksson07bf9112011-10-06 18:21:19 +020092 // Test if this CPU is a Fam 0Fh rev. F or later
93 const int cpu_id = cpuid_eax(0x80000001);
Marc Jonesd8d8c632012-01-30 19:30:45 -070094 printk(BIOS_SPEW, "CPU ID 0x80000001: %x\n", cpu_id);
Oskar Enoksson07bf9112011-10-06 18:21:19 +020095 const int has_tom2wb =
Evelyn Huangccc55132017-06-07 12:02:48 -060096 // ExtendedFamily > 0
97 (((cpu_id>>20)&0xf) > 0) ||
98 // Family == 0F
99 ((((cpu_id>>8)&0xf) == 0xf) &&
100 // Rev>=F deduced from rev tables
101 (((cpu_id>>16)&0xf) >= 0x4));
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200102 if (has_tom2wb)
Marc Jonesd8d8c632012-01-30 19:30:45 -0700103 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 +0000104
Eric Biedermana1653cf2004-10-22 04:41:53 +0000105 /* Enable the access to AMD RdDram and WrDram extension bits */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000106 disable_cache();
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000107 sys_cfg = rdmsr(SYSCFG_MSR);
108 sys_cfg.lo |= SYSCFG_MSR_MtrrFixDramModEn;
109 wrmsr(SYSCFG_MSR, sys_cfg);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000110 enable_cache();
Eric Biedermanf3aa4702004-10-21 02:53:25 +0000111
Aaron Durbin57686f82013-03-20 15:50:59 -0500112 /* Setup fixed MTRRs, but do not enable them just yet. */
113 x86_setup_fixed_mtrrs_no_enable();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000114
115 disable_cache();
116
Kyösti Mälkki9de0fee2012-08-05 12:12:05 +0300117 setup_ap_ramtop();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000118
Kyösti Mälkki2354515f2012-07-12 01:18:31 +0300119 /* if DRAM above 4GB: set SYSCFG_MSR_TOM2En and SYSCFG_MSR_TOM2WB */
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000120 sys_cfg.lo &= ~(SYSCFG_MSR_TOM2En | SYSCFG_MSR_TOM2WB);
Elyes HAOUAS168ef392017-06-27 22:54:42 +0200121 if (bsp_topmem2() > (uint64_t)1 << 32) {
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200122 sys_cfg.lo |= SYSCFG_MSR_TOM2En;
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200123 if (has_tom2wb)
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200124 sys_cfg.lo |= SYSCFG_MSR_TOM2WB;
Yinghai Lu30576602005-12-14 20:16:49 +0000125 }
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000126
127 /* zero the IORR's before we enable to prevent
128 * undefined side effects.
129 */
130 msr.lo = msr.hi = 0;
Elyes HAOUASd35c7fe2018-10-30 07:07:00 +0100131 for (i = MTRR_IORR0_BASE; i <= MTRR_IORR1_MASK; i++)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000132 wrmsr(i, msr);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000133
Stefan Reinauer14e22772010-04-27 06:56:47 +0000134 /* Enable Variable Mtrrs
Eric Biedermana1653cf2004-10-22 04:41:53 +0000135 * Enable the RdMem and WrMem bits in the fixed mtrrs.
136 * Disable access to the RdMem and WrMem in the fixed mtrr.
137 */
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000138 sys_cfg.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn;
139 sys_cfg.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
140 wrmsr(SYSCFG_MSR, sys_cfg);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000141
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000142 enable_fixed_mtrr();
143
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000144 enable_cache();
Eric Biedermana1653cf2004-10-22 04:41:53 +0000145
Evelyn Huangccc55132017-06-07 12:02:48 -0600146 //K8 could be 40, and GH could be 48
147 address_bits = CONFIG_CPU_ADDR_BITS;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000148
Tobias Diedrichc2924672010-11-09 22:31:11 +0000149 /* AMD specific cpuid function to query number of address bits */
Evelyn Huangccc55132017-06-07 12:02:48 -0600150 if (cpuid_eax(0x80000000) >= 0x80000008)
Tobias Diedrichc2924672010-11-09 22:31:11 +0000151 address_bits = cpuid_eax(0x80000008) & 0xff;
Tobias Diedrichc2924672010-11-09 22:31:11 +0000152
Eric Biedermana1653cf2004-10-22 04:41:53 +0000153 /* Now that I have mapped what is memory and what is not
Martin Roth4c3ab732013-07-08 16:23:54 -0600154 * Set up the mtrrs so we can cache the memory.
Eric Biedermana1653cf2004-10-22 04:41:53 +0000155 */
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200156
Martin Roth4c3ab732013-07-08 16:23:54 -0600157 // Rev. F K8 supports has SYSCFG_MSR_TOM2WB and doesn't need
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200158 // variable MTRR to span memory above 4GB
159 // Lower revisions K8 need variable MTRR over 4GB
160 x86_setup_var_mtrrs(address_bits, has_tom2wb ? 0 : 1);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000161}