Damien Roth | bedbd67 | 2016-01-18 13:59:26 -0700 | [diff] [blame] | 1 | /* |
| 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älkki | 17bb225 | 2017-04-19 19:55:54 +0300 | [diff] [blame] | 14 | #include <cbmem.h> |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 15 | #include <console/console.h> |
| 16 | #include <device/device.h> |
Tobias Diedrich | c292467 | 2010-11-09 22:31:11 +0000 | [diff] [blame] | 17 | #include <arch/cpu.h> |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 18 | #include <cpu/x86/mtrr.h> |
Kyösti Mälkki | 190011e | 2013-03-25 12:48:49 +0200 | [diff] [blame] | 19 | #include <cpu/x86/msr.h> |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 20 | #include <cpu/amd/mtrr.h> |
| 21 | #include <cpu/x86/cache.h> |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 22 | |
Kyösti Mälkki | dbc4739 | 2012-08-05 12:11:40 +0300 | [diff] [blame] | 23 | /* These will likely move to some device node or cbmem. */ |
| 24 | static uint64_t amd_topmem = 0; |
| 25 | static uint64_t amd_topmem2 = 0; |
| 26 | |
| 27 | uint64_t bsp_topmem(void) |
| 28 | { |
| 29 | return amd_topmem; |
| 30 | } |
| 31 | |
| 32 | uint64_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 | */ |
| 41 | void 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 HAOUAS | 168ef39 | 2017-06-27 22:54:42 +0200 | [diff] [blame] | 57 | amd_topmem = (uint64_t) msr.hi << 32 | msr.lo; |
| 58 | amd_topmem2 = (uint64_t) msr2.hi << 32 | msr2.lo; |
Kyösti Mälkki | dbc4739 | 2012-08-05 12:11:40 +0300 | [diff] [blame] | 59 | } |
| 60 | |
Kyösti Mälkki | 9de0fee | 2012-08-05 12:12:05 +0300 | [diff] [blame] | 61 | static 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älkki | 17bb225 | 2017-04-19 19:55:54 +0300 | [diff] [blame] | 80 | void add_uma_resource_below_tolm(struct device *nb, int idx) |
| 81 | { |
| 82 | uint32_t topmem = bsp_topmem(); |
Kyösti Mälkki | 70d92b9 | 2017-04-19 19:57:01 +0300 | [diff] [blame] | 83 | uint32_t top_of_cacheable = restore_top_of_low_cacheable(); |
Kyösti Mälkki | 17bb225 | 2017-04-19 19:55:54 +0300 | [diff] [blame] | 84 | |
| 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 Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 97 | void amd_setup_mtrrs(void) |
| 98 | { |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 99 | unsigned long address_bits; |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 100 | unsigned long i; |
Scott Duplichan | f3cce2f | 2010-11-13 19:07:59 +0000 | [diff] [blame] | 101 | msr_t msr, sys_cfg; |
Oskar Enoksson | 07bf911 | 2011-10-06 18:21:19 +0200 | [diff] [blame] | 102 | // Test if this CPU is a Fam 0Fh rev. F or later |
| 103 | const int cpu_id = cpuid_eax(0x80000001); |
Marc Jones | d8d8c63 | 2012-01-30 19:30:45 -0700 | [diff] [blame] | 104 | printk(BIOS_SPEW, "CPU ID 0x80000001: %x\n", cpu_id); |
Oskar Enoksson | 07bf911 | 2011-10-06 18:21:19 +0200 | [diff] [blame] | 105 | const int has_tom2wb = |
Evelyn Huang | ccc5513 | 2017-06-07 12:02:48 -0600 | [diff] [blame] | 106 | // 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 HAOUAS | cbe7464c | 2016-08-23 21:07:28 +0200 | [diff] [blame] | 112 | if (has_tom2wb) |
Marc Jones | d8d8c63 | 2012-01-30 19:30:45 -0700 | [diff] [blame] | 113 | printk(BIOS_DEBUG, "CPU is Fam 0Fh rev.F or later. We can use TOM2WB for any memory above 4GB\n"); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 114 | |
Eric Biederman | a1653cf | 2004-10-22 04:41:53 +0000 | [diff] [blame] | 115 | /* Enable the access to AMD RdDram and WrDram extension bits */ |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 116 | disable_cache(); |
Scott Duplichan | f3cce2f | 2010-11-13 19:07:59 +0000 | [diff] [blame] | 117 | sys_cfg = rdmsr(SYSCFG_MSR); |
| 118 | sys_cfg.lo |= SYSCFG_MSR_MtrrFixDramModEn; |
| 119 | wrmsr(SYSCFG_MSR, sys_cfg); |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 120 | enable_cache(); |
Eric Biederman | f3aa470 | 2004-10-21 02:53:25 +0000 | [diff] [blame] | 121 | |
Aaron Durbin | 57686f8 | 2013-03-20 15:50:59 -0500 | [diff] [blame] | 122 | /* Setup fixed MTRRs, but do not enable them just yet. */ |
| 123 | x86_setup_fixed_mtrrs_no_enable(); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 124 | |
| 125 | disable_cache(); |
| 126 | |
Kyösti Mälkki | 9de0fee | 2012-08-05 12:12:05 +0300 | [diff] [blame] | 127 | setup_ap_ramtop(); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 128 | |
Kyösti Mälkki | 2354515f | 2012-07-12 01:18:31 +0300 | [diff] [blame] | 129 | /* if DRAM above 4GB: set SYSCFG_MSR_TOM2En and SYSCFG_MSR_TOM2WB */ |
Scott Duplichan | f3cce2f | 2010-11-13 19:07:59 +0000 | [diff] [blame] | 130 | sys_cfg.lo &= ~(SYSCFG_MSR_TOM2En | SYSCFG_MSR_TOM2WB); |
Elyes HAOUAS | 168ef39 | 2017-06-27 22:54:42 +0200 | [diff] [blame] | 131 | if (bsp_topmem2() > (uint64_t)1 << 32) { |
Oskar Enoksson | 07bf911 | 2011-10-06 18:21:19 +0200 | [diff] [blame] | 132 | sys_cfg.lo |= SYSCFG_MSR_TOM2En; |
Elyes HAOUAS | cbe7464c | 2016-08-23 21:07:28 +0200 | [diff] [blame] | 133 | if (has_tom2wb) |
Oskar Enoksson | 07bf911 | 2011-10-06 18:21:19 +0200 | [diff] [blame] | 134 | sys_cfg.lo |= SYSCFG_MSR_TOM2WB; |
Yinghai Lu | 3057660 | 2005-12-14 20:16:49 +0000 | [diff] [blame] | 135 | } |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 136 | |
| 137 | /* zero the IORR's before we enable to prevent |
| 138 | * undefined side effects. |
| 139 | */ |
| 140 | msr.lo = msr.hi = 0; |
Elyes HAOUAS | d35c7fe | 2018-10-30 07:07:00 +0100 | [diff] [blame] | 141 | for (i = MTRR_IORR0_BASE; i <= MTRR_IORR1_MASK; i++) |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 142 | wrmsr(i, msr); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 143 | |
Stefan Reinauer | 14e2277 | 2010-04-27 06:56:47 +0000 | [diff] [blame] | 144 | /* Enable Variable Mtrrs |
Eric Biederman | a1653cf | 2004-10-22 04:41:53 +0000 | [diff] [blame] | 145 | * Enable the RdMem and WrMem bits in the fixed mtrrs. |
| 146 | * Disable access to the RdMem and WrMem in the fixed mtrr. |
| 147 | */ |
Scott Duplichan | f3cce2f | 2010-11-13 19:07:59 +0000 | [diff] [blame] | 148 | sys_cfg.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_MtrrFixDramEn; |
| 149 | sys_cfg.lo &= ~SYSCFG_MSR_MtrrFixDramModEn; |
| 150 | wrmsr(SYSCFG_MSR, sys_cfg); |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 151 | |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 152 | enable_fixed_mtrr(); |
| 153 | |
Eric Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 154 | enable_cache(); |
Eric Biederman | a1653cf | 2004-10-22 04:41:53 +0000 | [diff] [blame] | 155 | |
Evelyn Huang | ccc5513 | 2017-06-07 12:02:48 -0600 | [diff] [blame] | 156 | //K8 could be 40, and GH could be 48 |
| 157 | address_bits = CONFIG_CPU_ADDR_BITS; |
Yinghai Lu | 13f1c2a | 2005-07-08 02:49:49 +0000 | [diff] [blame] | 158 | |
Tobias Diedrich | c292467 | 2010-11-09 22:31:11 +0000 | [diff] [blame] | 159 | /* AMD specific cpuid function to query number of address bits */ |
Evelyn Huang | ccc5513 | 2017-06-07 12:02:48 -0600 | [diff] [blame] | 160 | if (cpuid_eax(0x80000000) >= 0x80000008) |
Tobias Diedrich | c292467 | 2010-11-09 22:31:11 +0000 | [diff] [blame] | 161 | address_bits = cpuid_eax(0x80000008) & 0xff; |
Tobias Diedrich | c292467 | 2010-11-09 22:31:11 +0000 | [diff] [blame] | 162 | |
Eric Biederman | a1653cf | 2004-10-22 04:41:53 +0000 | [diff] [blame] | 163 | /* Now that I have mapped what is memory and what is not |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 164 | * Set up the mtrrs so we can cache the memory. |
Eric Biederman | a1653cf | 2004-10-22 04:41:53 +0000 | [diff] [blame] | 165 | */ |
Oskar Enoksson | 07bf911 | 2011-10-06 18:21:19 +0200 | [diff] [blame] | 166 | |
Martin Roth | 4c3ab73 | 2013-07-08 16:23:54 -0600 | [diff] [blame] | 167 | // Rev. F K8 supports has SYSCFG_MSR_TOM2WB and doesn't need |
Oskar Enoksson | 07bf911 | 2011-10-06 18:21:19 +0200 | [diff] [blame] | 168 | // 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 Biederman | fcd5ace | 2004-10-14 19:29:29 +0000 | [diff] [blame] | 171 | } |