blob: 8cb6658d18f6db7bf9cbe5f22081f4519aeac0bd [file] [log] [blame]
Damien Rothbedbd672016-01-18 13:59:26 -07001/*
2 * This file is part of the coreboot project.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030014#include <cbmem.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000015#include <console/console.h>
16#include <device/device.h>
Tobias Diedrichc2924672010-11-09 22:31:11 +000017#include <arch/cpu.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000018#include <cpu/x86/mtrr.h>
Kyösti Mälkki190011e2013-03-25 12:48:49 +020019#include <cpu/x86/msr.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000020#include <cpu/amd/mtrr.h>
21#include <cpu/x86/cache.h>
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000022
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030023/* These will likely move to some device node or cbmem. */
24static uint64_t amd_topmem = 0;
25static uint64_t amd_topmem2 = 0;
26
27uint64_t bsp_topmem(void)
28{
29 return amd_topmem;
30}
31
32uint64_t bsp_topmem2(void)
33{
34 return amd_topmem2;
35}
36
37/* Take a copy of BSP CPUs TOP_MEM and TOP_MEM2 registers,
38 * so they can be distributed to AP CPUs. Not strictly MTRRs,
39 * but this is not that bad a place to have this code.
40 */
41void setup_bsp_ramtop(void)
42{
43 msr_t msr, msr2;
44
45 /* TOP_MEM: the top of DRAM below 4G */
46 msr = rdmsr(TOP_MEM);
47 printk(BIOS_INFO,
48 "%s, TOP MEM: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
49 __func__, msr.lo, msr.hi);
50
51 /* TOP_MEM2: the top of DRAM above 4G */
52 msr2 = rdmsr(TOP_MEM2);
53 printk(BIOS_INFO,
54 "%s, TOP MEM2: msr.lo = 0x%08x, msr.hi = 0x%08x\n",
55 __func__, msr2.lo, msr2.hi);
56
Elyes HAOUAS168ef392017-06-27 22:54:42 +020057 amd_topmem = (uint64_t) msr.hi << 32 | msr.lo;
58 amd_topmem2 = (uint64_t) msr2.hi << 32 | msr2.lo;
Kyösti Mälkkidbc47392012-08-05 12:11:40 +030059}
60
Kyösti Mälkki9de0fee2012-08-05 12:12:05 +030061static void setup_ap_ramtop(void)
62{
63 msr_t msr;
64 uint64_t v;
65
66 v = bsp_topmem();
67 if (!v)
68 return;
69
70 msr.hi = v >> 32;
71 msr.lo = (uint32_t) v;
72 wrmsr(TOP_MEM, msr);
73
74 v = bsp_topmem2();
75 msr.hi = v >> 32;
76 msr.lo = (uint32_t) v;
77 wrmsr(TOP_MEM2, msr);
78}
79
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030080void add_uma_resource_below_tolm(struct device *nb, int idx)
81{
82 uint32_t topmem = bsp_topmem();
Kyösti Mälkki70d92b92017-04-19 19:57:01 +030083 uint32_t top_of_cacheable = restore_top_of_low_cacheable();
Kyösti Mälkki17bb2252017-04-19 19:55:54 +030084
85 if (top_of_cacheable == topmem)
86 return;
87
88 uint32_t uma_base = top_of_cacheable;
89 uint32_t uma_size = topmem - top_of_cacheable;
90
91 printk(BIOS_INFO, "%s: uma size 0x%08x, memory start 0x%08x\n",
92 __func__, uma_size, uma_base);
93
94 uma_resource(nb, idx, uma_base / KiB, uma_size / KiB);
95}
96
Eric Biedermanfcd5ace2004-10-14 19:29:29 +000097void amd_setup_mtrrs(void)
98{
Yinghai Lu13f1c2a2005-07-08 02:49:49 +000099 unsigned long address_bits;
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000100 unsigned long i;
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000101 msr_t msr, sys_cfg;
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200102 // Test if this CPU is a Fam 0Fh rev. F or later
103 const int cpu_id = cpuid_eax(0x80000001);
Marc Jonesd8d8c632012-01-30 19:30:45 -0700104 printk(BIOS_SPEW, "CPU ID 0x80000001: %x\n", cpu_id);
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200105 const int has_tom2wb =
Evelyn Huangccc55132017-06-07 12:02:48 -0600106 // ExtendedFamily > 0
107 (((cpu_id>>20)&0xf) > 0) ||
108 // Family == 0F
109 ((((cpu_id>>8)&0xf) == 0xf) &&
110 // Rev>=F deduced from rev tables
111 (((cpu_id>>16)&0xf) >= 0x4));
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200112 if (has_tom2wb)
Marc Jonesd8d8c632012-01-30 19:30:45 -0700113 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 +0000114
Eric Biedermana1653cf2004-10-22 04:41:53 +0000115 /* Enable the access to AMD RdDram and WrDram extension bits */
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000116 disable_cache();
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000117 sys_cfg = rdmsr(SYSCFG_MSR);
118 sys_cfg.lo |= SYSCFG_MSR_MtrrFixDramModEn;
119 wrmsr(SYSCFG_MSR, sys_cfg);
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000120 enable_cache();
Eric Biedermanf3aa4702004-10-21 02:53:25 +0000121
Aaron Durbin57686f82013-03-20 15:50:59 -0500122 /* Setup fixed MTRRs, but do not enable them just yet. */
123 x86_setup_fixed_mtrrs_no_enable();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000124
125 disable_cache();
126
Kyösti Mälkki9de0fee2012-08-05 12:12:05 +0300127 setup_ap_ramtop();
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000128
Kyösti Mälkki2354515f2012-07-12 01:18:31 +0300129 /* if DRAM above 4GB: set SYSCFG_MSR_TOM2En and SYSCFG_MSR_TOM2WB */
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000130 sys_cfg.lo &= ~(SYSCFG_MSR_TOM2En | SYSCFG_MSR_TOM2WB);
Elyes HAOUAS168ef392017-06-27 22:54:42 +0200131 if (bsp_topmem2() > (uint64_t)1 << 32) {
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200132 sys_cfg.lo |= SYSCFG_MSR_TOM2En;
Elyes HAOUAScbe7464c2016-08-23 21:07:28 +0200133 if (has_tom2wb)
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200134 sys_cfg.lo |= SYSCFG_MSR_TOM2WB;
Yinghai Lu30576602005-12-14 20:16:49 +0000135 }
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000136
137 /* zero the IORR's before we enable to prevent
138 * undefined side effects.
139 */
140 msr.lo = msr.hi = 0;
Evelyn Huangccc55132017-06-07 12:02:48 -0600141 for (i = IORR_FIRST; i <= IORR_LAST; i++)
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000142 wrmsr(i, msr);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000143
Stefan Reinauer14e22772010-04-27 06:56:47 +0000144 /* Enable Variable Mtrrs
Eric Biedermana1653cf2004-10-22 04:41:53 +0000145 * Enable the RdMem and WrMem bits in the fixed mtrrs.
146 * Disable access to the RdMem and WrMem in the fixed mtrr.
147 */
Scott Duplichanf3cce2f2010-11-13 19:07:59 +0000148 sys_cfg.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn;
149 sys_cfg.lo &= ~SYSCFG_MSR_MtrrFixDramModEn;
150 wrmsr(SYSCFG_MSR, sys_cfg);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000151
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000152 enable_fixed_mtrr();
153
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000154 enable_cache();
Eric Biedermana1653cf2004-10-22 04:41:53 +0000155
Evelyn Huangccc55132017-06-07 12:02:48 -0600156 //K8 could be 40, and GH could be 48
157 address_bits = CONFIG_CPU_ADDR_BITS;
Yinghai Lu13f1c2a2005-07-08 02:49:49 +0000158
Tobias Diedrichc2924672010-11-09 22:31:11 +0000159 /* AMD specific cpuid function to query number of address bits */
Evelyn Huangccc55132017-06-07 12:02:48 -0600160 if (cpuid_eax(0x80000000) >= 0x80000008)
Tobias Diedrichc2924672010-11-09 22:31:11 +0000161 address_bits = cpuid_eax(0x80000008) & 0xff;
Tobias Diedrichc2924672010-11-09 22:31:11 +0000162
Eric Biedermana1653cf2004-10-22 04:41:53 +0000163 /* Now that I have mapped what is memory and what is not
Martin Roth4c3ab732013-07-08 16:23:54 -0600164 * Set up the mtrrs so we can cache the memory.
Eric Biedermana1653cf2004-10-22 04:41:53 +0000165 */
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200166
Martin Roth4c3ab732013-07-08 16:23:54 -0600167 // Rev. F K8 supports has SYSCFG_MSR_TOM2WB and doesn't need
Oskar Enoksson07bf9112011-10-06 18:21:19 +0200168 // variable MTRR to span memory above 4GB
169 // Lower revisions K8 need variable MTRR over 4GB
170 x86_setup_var_mtrrs(address_bits, has_tom2wb ? 0 : 1);
Eric Biedermanfcd5ace2004-10-14 19:29:29 +0000171}