amd_bus.c (9776B)
1// SPDX-License-Identifier: GPL-2.0 2#include <linux/init.h> 3#include <linux/pci.h> 4#include <linux/topology.h> 5#include <linux/cpu.h> 6#include <linux/range.h> 7 8#include <asm/amd_nb.h> 9#include <asm/pci_x86.h> 10 11#include <asm/pci-direct.h> 12 13#include "bus_numa.h" 14 15#define AMD_NB_F0_NODE_ID 0x60 16#define AMD_NB_F0_UNIT_ID 0x64 17#define AMD_NB_F1_CONFIG_MAP_REG 0xe0 18 19#define RANGE_NUM 16 20#define AMD_NB_F1_CONFIG_MAP_RANGES 4 21 22struct amd_hostbridge { 23 u32 bus; 24 u32 slot; 25 u32 device; 26}; 27 28/* 29 * IMPORTANT NOTE: 30 * hb_probes[] and early_root_info_init() is in maintenance mode. 31 * It only supports K8, Fam10h, Fam11h, and Fam15h_00h-0fh . 32 * Future processor will rely on information in ACPI. 33 */ 34static struct amd_hostbridge hb_probes[] __initdata = { 35 { 0, 0x18, 0x1100 }, /* K8 */ 36 { 0, 0x18, 0x1200 }, /* Family10h */ 37 { 0xff, 0, 0x1200 }, /* Family10h */ 38 { 0, 0x18, 0x1300 }, /* Family11h */ 39 { 0, 0x18, 0x1600 }, /* Family15h */ 40}; 41 42static struct pci_root_info __init *find_pci_root_info(int node, int link) 43{ 44 struct pci_root_info *info; 45 46 /* find the position */ 47 list_for_each_entry(info, &pci_root_infos, list) 48 if (info->node == node && info->link == link) 49 return info; 50 51 return NULL; 52} 53 54/** 55 * early_root_info_init() 56 * called before pcibios_scan_root and pci_scan_bus 57 * fills the mp_bus_to_cpumask array based according 58 * to the LDT Bus Number Registers found in the northbridge. 59 */ 60static int __init early_root_info_init(void) 61{ 62 int i; 63 unsigned bus; 64 unsigned slot; 65 int node; 66 int link; 67 int def_node; 68 int def_link; 69 struct pci_root_info *info; 70 u32 reg; 71 u64 start; 72 u64 end; 73 struct range range[RANGE_NUM]; 74 u64 val; 75 u32 address; 76 bool found; 77 struct resource fam10h_mmconf_res, *fam10h_mmconf; 78 u64 fam10h_mmconf_start; 79 u64 fam10h_mmconf_end; 80 81 if (!early_pci_allowed()) 82 return -1; 83 84 found = false; 85 for (i = 0; i < ARRAY_SIZE(hb_probes); i++) { 86 u32 id; 87 u16 device; 88 u16 vendor; 89 90 bus = hb_probes[i].bus; 91 slot = hb_probes[i].slot; 92 id = read_pci_config(bus, slot, 0, PCI_VENDOR_ID); 93 vendor = id & 0xffff; 94 device = (id>>16) & 0xffff; 95 96 if (vendor != PCI_VENDOR_ID_AMD && 97 vendor != PCI_VENDOR_ID_HYGON) 98 continue; 99 100 if (hb_probes[i].device == device) { 101 found = true; 102 break; 103 } 104 } 105 106 if (!found) 107 return 0; 108 109 /* 110 * We should learn topology and routing information from _PXM and 111 * _CRS methods in the ACPI namespace. We extract node numbers 112 * here to work around BIOSes that don't supply _PXM. 113 */ 114 for (i = 0; i < AMD_NB_F1_CONFIG_MAP_RANGES; i++) { 115 int min_bus; 116 int max_bus; 117 reg = read_pci_config(bus, slot, 1, 118 AMD_NB_F1_CONFIG_MAP_REG + (i << 2)); 119 120 /* Check if that register is enabled for bus range */ 121 if ((reg & 7) != 3) 122 continue; 123 124 min_bus = (reg >> 16) & 0xff; 125 max_bus = (reg >> 24) & 0xff; 126 node = (reg >> 4) & 0x07; 127 link = (reg >> 8) & 0x03; 128 129 alloc_pci_root_info(min_bus, max_bus, node, link); 130 } 131 132 /* 133 * The following code extracts routing information for use on old 134 * systems where Linux doesn't automatically use host bridge _CRS 135 * methods (or when the user specifies "pci=nocrs"). 136 * 137 * We only do this through Fam11h, because _CRS should be enough on 138 * newer systems. 139 */ 140 if (boot_cpu_data.x86 > 0x11) 141 return 0; 142 143 /* get the default node and link for left over res */ 144 reg = read_pci_config(bus, slot, 0, AMD_NB_F0_NODE_ID); 145 def_node = (reg >> 8) & 0x07; 146 reg = read_pci_config(bus, slot, 0, AMD_NB_F0_UNIT_ID); 147 def_link = (reg >> 8) & 0x03; 148 149 memset(range, 0, sizeof(range)); 150 add_range(range, RANGE_NUM, 0, 0, 0xffff + 1); 151 /* io port resource */ 152 for (i = 0; i < 4; i++) { 153 reg = read_pci_config(bus, slot, 1, 0xc0 + (i << 3)); 154 if (!(reg & 3)) 155 continue; 156 157 start = reg & 0xfff000; 158 reg = read_pci_config(bus, slot, 1, 0xc4 + (i << 3)); 159 node = reg & 0x07; 160 link = (reg >> 4) & 0x03; 161 end = (reg & 0xfff000) | 0xfff; 162 163 info = find_pci_root_info(node, link); 164 if (!info) 165 continue; /* not found */ 166 167 printk(KERN_DEBUG "node %d link %d: io port [%llx, %llx]\n", 168 node, link, start, end); 169 170 /* kernel only handle 16 bit only */ 171 if (end > 0xffff) 172 end = 0xffff; 173 update_res(info, start, end, IORESOURCE_IO, 1); 174 subtract_range(range, RANGE_NUM, start, end + 1); 175 } 176 /* add left over io port range to def node/link, [0, 0xffff] */ 177 /* find the position */ 178 info = find_pci_root_info(def_node, def_link); 179 if (info) { 180 for (i = 0; i < RANGE_NUM; i++) { 181 if (!range[i].end) 182 continue; 183 184 update_res(info, range[i].start, range[i].end - 1, 185 IORESOURCE_IO, 1); 186 } 187 } 188 189 memset(range, 0, sizeof(range)); 190 /* 0xfd00000000-0xffffffffff for HT */ 191 end = cap_resource((0xfdULL<<32) - 1); 192 end++; 193 add_range(range, RANGE_NUM, 0, 0, end); 194 195 /* need to take out [0, TOM) for RAM*/ 196 address = MSR_K8_TOP_MEM1; 197 rdmsrl(address, val); 198 end = (val & 0xffffff800000ULL); 199 printk(KERN_INFO "TOM: %016llx aka %lldM\n", end, end>>20); 200 if (end < (1ULL<<32)) 201 subtract_range(range, RANGE_NUM, 0, end); 202 203 /* get mmconfig */ 204 fam10h_mmconf = amd_get_mmconfig_range(&fam10h_mmconf_res); 205 /* need to take out mmconf range */ 206 if (fam10h_mmconf) { 207 printk(KERN_DEBUG "Fam 10h mmconf %pR\n", fam10h_mmconf); 208 fam10h_mmconf_start = fam10h_mmconf->start; 209 fam10h_mmconf_end = fam10h_mmconf->end; 210 subtract_range(range, RANGE_NUM, fam10h_mmconf_start, 211 fam10h_mmconf_end + 1); 212 } else { 213 fam10h_mmconf_start = 0; 214 fam10h_mmconf_end = 0; 215 } 216 217 /* mmio resource */ 218 for (i = 0; i < 8; i++) { 219 reg = read_pci_config(bus, slot, 1, 0x80 + (i << 3)); 220 if (!(reg & 3)) 221 continue; 222 223 start = reg & 0xffffff00; /* 39:16 on 31:8*/ 224 start <<= 8; 225 reg = read_pci_config(bus, slot, 1, 0x84 + (i << 3)); 226 node = reg & 0x07; 227 link = (reg >> 4) & 0x03; 228 end = (reg & 0xffffff00); 229 end <<= 8; 230 end |= 0xffff; 231 232 info = find_pci_root_info(node, link); 233 234 if (!info) 235 continue; 236 237 printk(KERN_DEBUG "node %d link %d: mmio [%llx, %llx]", 238 node, link, start, end); 239 /* 240 * some sick allocation would have range overlap with fam10h 241 * mmconf range, so need to update start and end. 242 */ 243 if (fam10h_mmconf_end) { 244 int changed = 0; 245 u64 endx = 0; 246 if (start >= fam10h_mmconf_start && 247 start <= fam10h_mmconf_end) { 248 start = fam10h_mmconf_end + 1; 249 changed = 1; 250 } 251 252 if (end >= fam10h_mmconf_start && 253 end <= fam10h_mmconf_end) { 254 end = fam10h_mmconf_start - 1; 255 changed = 1; 256 } 257 258 if (start < fam10h_mmconf_start && 259 end > fam10h_mmconf_end) { 260 /* we got a hole */ 261 endx = fam10h_mmconf_start - 1; 262 update_res(info, start, endx, IORESOURCE_MEM, 0); 263 subtract_range(range, RANGE_NUM, start, 264 endx + 1); 265 printk(KERN_CONT " ==> [%llx, %llx]", start, endx); 266 start = fam10h_mmconf_end + 1; 267 changed = 1; 268 } 269 if (changed) { 270 if (start <= end) { 271 printk(KERN_CONT " %s [%llx, %llx]", endx ? "and" : "==>", start, end); 272 } else { 273 printk(KERN_CONT "%s\n", endx?"":" ==> none"); 274 continue; 275 } 276 } 277 } 278 279 update_res(info, cap_resource(start), cap_resource(end), 280 IORESOURCE_MEM, 1); 281 subtract_range(range, RANGE_NUM, start, end + 1); 282 printk(KERN_CONT "\n"); 283 } 284 285 /* need to take out [4G, TOM2) for RAM*/ 286 /* SYS_CFG */ 287 address = MSR_AMD64_SYSCFG; 288 rdmsrl(address, val); 289 /* TOP_MEM2 is enabled? */ 290 if (val & (1<<21)) { 291 /* TOP_MEM2 */ 292 address = MSR_K8_TOP_MEM2; 293 rdmsrl(address, val); 294 end = (val & 0xffffff800000ULL); 295 printk(KERN_INFO "TOM2: %016llx aka %lldM\n", end, end>>20); 296 subtract_range(range, RANGE_NUM, 1ULL<<32, end); 297 } 298 299 /* 300 * add left over mmio range to def node/link ? 301 * that is tricky, just record range in from start_min to 4G 302 */ 303 info = find_pci_root_info(def_node, def_link); 304 if (info) { 305 for (i = 0; i < RANGE_NUM; i++) { 306 if (!range[i].end) 307 continue; 308 309 update_res(info, cap_resource(range[i].start), 310 cap_resource(range[i].end - 1), 311 IORESOURCE_MEM, 1); 312 } 313 } 314 315 list_for_each_entry(info, &pci_root_infos, list) { 316 int busnum; 317 struct pci_root_res *root_res; 318 319 busnum = info->busn.start; 320 printk(KERN_DEBUG "bus: %pR on node %x link %x\n", 321 &info->busn, info->node, info->link); 322 list_for_each_entry(root_res, &info->resources, list) 323 printk(KERN_DEBUG "bus: %02x %pR\n", 324 busnum, &root_res->res); 325 } 326 327 return 0; 328} 329 330#define ENABLE_CF8_EXT_CFG (1ULL << 46) 331 332static int amd_bus_cpu_online(unsigned int cpu) 333{ 334 u64 reg; 335 336 rdmsrl(MSR_AMD64_NB_CFG, reg); 337 if (!(reg & ENABLE_CF8_EXT_CFG)) { 338 reg |= ENABLE_CF8_EXT_CFG; 339 wrmsrl(MSR_AMD64_NB_CFG, reg); 340 } 341 return 0; 342} 343 344static void __init pci_enable_pci_io_ecs(void) 345{ 346#ifdef CONFIG_AMD_NB 347 unsigned int i, n; 348 349 for (n = i = 0; !n && amd_nb_bus_dev_ranges[i].dev_limit; ++i) { 350 u8 bus = amd_nb_bus_dev_ranges[i].bus; 351 u8 slot = amd_nb_bus_dev_ranges[i].dev_base; 352 u8 limit = amd_nb_bus_dev_ranges[i].dev_limit; 353 354 for (; slot < limit; ++slot) { 355 u32 val = read_pci_config(bus, slot, 3, 0); 356 357 if (!early_is_amd_nb(val)) 358 continue; 359 360 val = read_pci_config(bus, slot, 3, 0x8c); 361 if (!(val & (ENABLE_CF8_EXT_CFG >> 32))) { 362 val |= ENABLE_CF8_EXT_CFG >> 32; 363 write_pci_config(bus, slot, 3, 0x8c, val); 364 } 365 ++n; 366 } 367 } 368#endif 369} 370 371static int __init pci_io_ecs_init(void) 372{ 373 int ret; 374 375 /* assume all cpus from fam10h have IO ECS */ 376 if (boot_cpu_data.x86 < 0x10) 377 return 0; 378 379 /* Try the PCI method first. */ 380 if (early_pci_allowed()) 381 pci_enable_pci_io_ecs(); 382 383 ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "pci/amd_bus:online", 384 amd_bus_cpu_online, NULL); 385 WARN_ON(ret < 0); 386 387 pci_probe |= PCI_HAS_IO_ECS; 388 389 return 0; 390} 391 392static int __init amd_postcore_init(void) 393{ 394 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD && 395 boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) 396 return 0; 397 398 early_root_info_init(); 399 pci_io_ecs_init(); 400 401 return 0; 402} 403 404postcore_initcall(amd_postcore_init);