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