1 /* 2 * mmconfig-shared.c - Low-level direct PCI config space access via 3 * MMCONFIG - common code between i386 and x86-64. 4 * 5 * This code does: 6 * - known chipset handling 7 * - ACPI decoding and validation 8 * 9 * Per-architecture code takes care of the mappings and accesses 10 * themselves. 11 */ 12 13 #include <linux/pci.h> 14 #include <linux/init.h> 15 #include <linux/acpi.h> 16 #include <linux/bitmap.h> 17 #include <asm/e820.h> 18 19 #include "pci.h" 20 21 /* aperture is up to 256MB but BIOS may reserve less */ 22 #define MMCONFIG_APER_MIN (2 * 1024*1024) 23 #define MMCONFIG_APER_MAX (256 * 1024*1024) 24 25 /* Indicate if the mmcfg resources have been placed into the resource table. */ 26 static int __initdata pci_mmcfg_resources_inserted; 27 28 static const char __init *pci_mmcfg_e7520(void) 29 { 30 u32 win; 31 pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0xce, 2, &win); 32 33 win = win & 0xf000; 34 if(win == 0x0000 || win == 0xf000) 35 pci_mmcfg_config_num = 0; 36 else { 37 pci_mmcfg_config_num = 1; 38 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL); 39 if (!pci_mmcfg_config) 40 return NULL; 41 pci_mmcfg_config[0].address = win << 16; 42 pci_mmcfg_config[0].pci_segment = 0; 43 pci_mmcfg_config[0].start_bus_number = 0; 44 pci_mmcfg_config[0].end_bus_number = 255; 45 } 46 47 return "Intel Corporation E7520 Memory Controller Hub"; 48 } 49 50 static const char __init *pci_mmcfg_intel_945(void) 51 { 52 u32 pciexbar, mask = 0, len = 0; 53 54 pci_mmcfg_config_num = 1; 55 56 pci_direct_conf1.read(0, 0, PCI_DEVFN(0,0), 0x48, 4, &pciexbar); 57 58 /* Enable bit */ 59 if (!(pciexbar & 1)) 60 pci_mmcfg_config_num = 0; 61 62 /* Size bits */ 63 switch ((pciexbar >> 1) & 3) { 64 case 0: 65 mask = 0xf0000000U; 66 len = 0x10000000U; 67 break; 68 case 1: 69 mask = 0xf8000000U; 70 len = 0x08000000U; 71 break; 72 case 2: 73 mask = 0xfc000000U; 74 len = 0x04000000U; 75 break; 76 default: 77 pci_mmcfg_config_num = 0; 78 } 79 80 /* Errata #2, things break when not aligned on a 256Mb boundary */ 81 /* Can only happen in 64M/128M mode */ 82 83 if ((pciexbar & mask) & 0x0fffffffU) 84 pci_mmcfg_config_num = 0; 85 86 /* Don't hit the APIC registers and their friends */ 87 if ((pciexbar & mask) >= 0xf0000000U) 88 pci_mmcfg_config_num = 0; 89 90 if (pci_mmcfg_config_num) { 91 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]), GFP_KERNEL); 92 if (!pci_mmcfg_config) 93 return NULL; 94 pci_mmcfg_config[0].address = pciexbar & mask; 95 pci_mmcfg_config[0].pci_segment = 0; 96 pci_mmcfg_config[0].start_bus_number = 0; 97 pci_mmcfg_config[0].end_bus_number = (len >> 20) - 1; 98 } 99 100 return "Intel Corporation 945G/GZ/P/PL Express Memory Controller Hub"; 101 } 102 103 static const char __init *pci_mmcfg_amd_fam10h(void) 104 { 105 u32 low, high, address; 106 u64 base, msr; 107 int i; 108 unsigned segnbits = 0, busnbits; 109 110 address = MSR_FAM10H_MMIO_CONF_BASE; 111 if (rdmsr_safe(address, &low, &high)) 112 return NULL; 113 114 msr = high; 115 msr <<= 32; 116 msr |= low; 117 118 /* mmconfig is not enable */ 119 if (!(msr & FAM10H_MMIO_CONF_ENABLE)) 120 return NULL; 121 122 base = msr & (FAM10H_MMIO_CONF_BASE_MASK<<FAM10H_MMIO_CONF_BASE_SHIFT); 123 124 busnbits = (msr >> FAM10H_MMIO_CONF_BUSRANGE_SHIFT) & 125 FAM10H_MMIO_CONF_BUSRANGE_MASK; 126 127 /* 128 * only handle bus 0 ? 129 * need to skip it 130 */ 131 if (!busnbits) 132 return NULL; 133 134 if (busnbits > 8) { 135 segnbits = busnbits - 8; 136 busnbits = 8; 137 } 138 139 pci_mmcfg_config_num = (1 << segnbits); 140 pci_mmcfg_config = kzalloc(sizeof(pci_mmcfg_config[0]) * 141 pci_mmcfg_config_num, GFP_KERNEL); 142 if (!pci_mmcfg_config) 143 return NULL; 144 145 for (i = 0; i < (1 << segnbits); i++) { 146 pci_mmcfg_config[i].address = base + (1<<28) * i; 147 pci_mmcfg_config[i].pci_segment = i; 148 pci_mmcfg_config[i].start_bus_number = 0; 149 pci_mmcfg_config[i].end_bus_number = (1 << busnbits) - 1; 150 } 151 152 return "AMD Family 10h NB"; 153 } 154 155 struct pci_mmcfg_hostbridge_probe { 156 u32 bus; 157 u32 devfn; 158 u32 vendor; 159 u32 device; 160 const char *(*probe)(void); 161 }; 162 163 static struct pci_mmcfg_hostbridge_probe pci_mmcfg_probes[] __initdata = { 164 { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, 165 PCI_DEVICE_ID_INTEL_E7520_MCH, pci_mmcfg_e7520 }, 166 { 0, PCI_DEVFN(0, 0), PCI_VENDOR_ID_INTEL, 167 PCI_DEVICE_ID_INTEL_82945G_HB, pci_mmcfg_intel_945 }, 168 { 0, PCI_DEVFN(0x18, 0), PCI_VENDOR_ID_AMD, 169 0x1200, pci_mmcfg_amd_fam10h }, 170 { 0xff, PCI_DEVFN(0, 0), PCI_VENDOR_ID_AMD, 171 0x1200, pci_mmcfg_amd_fam10h }, 172 }; 173 174 static int __init pci_mmcfg_check_hostbridge(void) 175 { 176 u32 l; 177 u32 bus, devfn; 178 u16 vendor, device; 179 int i; 180 const char *name; 181 182 pci_mmcfg_config_num = 0; 183 pci_mmcfg_config = NULL; 184 name = NULL; 185 186 for (i = 0; !name && i < ARRAY_SIZE(pci_mmcfg_probes); i++) { 187 bus = pci_mmcfg_probes[i].bus; 188 devfn = pci_mmcfg_probes[i].devfn; 189 pci_direct_conf1.read(0, bus, devfn, 0, 4, &l); 190 vendor = l & 0xffff; 191 device = (l >> 16) & 0xffff; 192 193 if (pci_mmcfg_probes[i].vendor == vendor && 194 pci_mmcfg_probes[i].device == device) 195 name = pci_mmcfg_probes[i].probe(); 196 } 197 198 if (name) { 199 printk(KERN_INFO "PCI: Found %s %s MMCONFIG support.\n", 200 name, pci_mmcfg_config_num ? "with" : "without"); 201 } 202 203 return name != NULL; 204 } 205 206 static void __init pci_mmcfg_insert_resources(unsigned long resource_flags) 207 { 208 #define PCI_MMCFG_RESOURCE_NAME_LEN 19 209 int i; 210 struct resource *res; 211 char *names; 212 unsigned num_buses; 213 214 res = kcalloc(PCI_MMCFG_RESOURCE_NAME_LEN + sizeof(*res), 215 pci_mmcfg_config_num, GFP_KERNEL); 216 if (!res) { 217 printk(KERN_ERR "PCI: Unable to allocate MMCONFIG resources\n"); 218 return; 219 } 220 221 names = (void *)&res[pci_mmcfg_config_num]; 222 for (i = 0; i < pci_mmcfg_config_num; i++, res++) { 223 struct acpi_mcfg_allocation *cfg = &pci_mmcfg_config[i]; 224 num_buses = cfg->end_bus_number - cfg->start_bus_number + 1; 225 res->name = names; 226 snprintf(names, PCI_MMCFG_RESOURCE_NAME_LEN, "PCI MMCONFIG %u", 227 cfg->pci_segment); 228 res->start = cfg->address; 229 res->end = res->start + (num_buses << 20) - 1; 230 res->flags = IORESOURCE_MEM | resource_flags; 231 insert_resource(&iomem_resource, res); 232 names += PCI_MMCFG_RESOURCE_NAME_LEN; 233 } 234 235 /* Mark that the resources have been inserted. */ 236 pci_mmcfg_resources_inserted = 1; 237 } 238 239 static acpi_status __init check_mcfg_resource(struct acpi_resource *res, 240 void *data) 241 { 242 struct resource *mcfg_res = data; 243 struct acpi_resource_address64 address; 244 acpi_status status; 245 246 if (res->type == ACPI_RESOURCE_TYPE_FIXED_MEMORY32) { 247 struct acpi_resource_fixed_memory32 *fixmem32 = 248 &res->data.fixed_memory32; 249 if (!fixmem32) 250 return AE_OK; 251 if ((mcfg_res->start >= fixmem32->address) && 252 (mcfg_res->end < (fixmem32->address + 253 fixmem32->address_length))) { 254 mcfg_res->flags = 1; 255 return AE_CTRL_TERMINATE; 256 } 257 } 258 if ((res->type != ACPI_RESOURCE_TYPE_ADDRESS32) && 259 (res->type != ACPI_RESOURCE_TYPE_ADDRESS64)) 260 return AE_OK; 261 262 status = acpi_resource_to_address64(res, &address); 263 if (ACPI_FAILURE(status) || 264 (address.address_length <= 0) || 265 (address.resource_type != ACPI_MEMORY_RANGE)) 266 return AE_OK; 267 268 if ((mcfg_res->start >= address.minimum) && 269 (mcfg_res->end < (address.minimum + address.address_length))) { 270 mcfg_res->flags = 1; 271 return AE_CTRL_TERMINATE; 272 } 273 return AE_OK; 274 } 275 276 static acpi_status __init find_mboard_resource(acpi_handle handle, u32 lvl, 277 void *context, void **rv) 278 { 279 struct resource *mcfg_res = context; 280 281 acpi_walk_resources(handle, METHOD_NAME__CRS, 282 check_mcfg_resource, context); 283 284 if (mcfg_res->flags) 285 return AE_CTRL_TERMINATE; 286 287 return AE_OK; 288 } 289 290 static int __init is_acpi_reserved(unsigned long start, unsigned long end) 291 { 292 struct resource mcfg_res; 293 294 mcfg_res.start = start; 295 mcfg_res.end = end; 296 mcfg_res.flags = 0; 297 298 acpi_get_devices("PNP0C01", find_mboard_resource, &mcfg_res, NULL); 299 300 if (!mcfg_res.flags) 301 acpi_get_devices("PNP0C02", find_mboard_resource, &mcfg_res, 302 NULL); 303 304 return mcfg_res.flags; 305 } 306 307 static void __init pci_mmcfg_reject_broken(int type, int early) 308 { 309 typeof(pci_mmcfg_config[0]) *cfg; 310 int i; 311 312 if ((pci_mmcfg_config_num == 0) || 313 (pci_mmcfg_config == NULL) || 314 (pci_mmcfg_config[0].address == 0)) 315 return; 316 317 cfg = &pci_mmcfg_config[0]; 318 319 /* 320 * Handle more broken MCFG tables on Asus etc. 321 * They only contain a single entry for bus 0-0. 322 */ 323 if (pci_mmcfg_config_num == 1 && 324 cfg->pci_segment == 0 && 325 (cfg->start_bus_number | cfg->end_bus_number) == 0) { 326 printk(KERN_ERR "PCI: start and end of bus number is 0. " 327 "Rejected as broken MCFG.\n"); 328 goto reject; 329 } 330 331 for (i = 0; i < pci_mmcfg_config_num; i++) { 332 int valid = 0; 333 u32 size = (cfg->end_bus_number + 1) << 20; 334 cfg = &pci_mmcfg_config[i]; 335 printk(KERN_NOTICE "PCI: MCFG configuration %d: base %lx " 336 "segment %hu buses %u - %u\n", 337 i, (unsigned long)cfg->address, cfg->pci_segment, 338 (unsigned int)cfg->start_bus_number, 339 (unsigned int)cfg->end_bus_number); 340 341 if (!early && 342 is_acpi_reserved(cfg->address, cfg->address + size - 1)) { 343 printk(KERN_NOTICE "PCI: MCFG area at %Lx reserved " 344 "in ACPI motherboard resources\n", 345 cfg->address); 346 valid = 1; 347 } 348 349 if (valid) 350 continue; 351 352 if (!early) 353 printk(KERN_ERR "PCI: BIOS Bug: MCFG area at %Lx is not" 354 " reserved in ACPI motherboard resources\n", 355 cfg->address); 356 /* Don't try to do this check unless configuration 357 type 1 is available. */ 358 if (type == 1 && e820_all_mapped(cfg->address, 359 cfg->address + size - 1, 360 E820_RESERVED)) { 361 printk(KERN_NOTICE 362 "PCI: MCFG area at %Lx reserved in E820\n", 363 cfg->address); 364 valid = 1; 365 } 366 367 if (!valid) 368 goto reject; 369 } 370 371 return; 372 373 reject: 374 printk(KERN_ERR "PCI: Not using MMCONFIG.\n"); 375 pci_mmcfg_arch_free(); 376 kfree(pci_mmcfg_config); 377 pci_mmcfg_config = NULL; 378 pci_mmcfg_config_num = 0; 379 } 380 381 static int __initdata known_bridge; 382 383 void __init __pci_mmcfg_init(int type, int early) 384 { 385 /* MMCONFIG disabled */ 386 if ((pci_probe & PCI_PROBE_MMCONF) == 0) 387 return; 388 389 /* MMCONFIG already enabled */ 390 if (!early && !(pci_probe & PCI_PROBE_MASK & ~PCI_PROBE_MMCONF)) 391 return; 392 393 /* for late to exit */ 394 if (known_bridge) 395 return; 396 397 if (early && type == 1) { 398 if (pci_mmcfg_check_hostbridge()) 399 known_bridge = 1; 400 } 401 402 if (!known_bridge) { 403 acpi_table_parse(ACPI_SIG_MCFG, acpi_parse_mcfg); 404 pci_mmcfg_reject_broken(type, early); 405 } 406 407 if ((pci_mmcfg_config_num == 0) || 408 (pci_mmcfg_config == NULL) || 409 (pci_mmcfg_config[0].address == 0)) 410 return; 411 412 if (pci_mmcfg_arch_init()) { 413 if (known_bridge) 414 pci_mmcfg_insert_resources(IORESOURCE_BUSY); 415 pci_probe = (pci_probe & ~PCI_PROBE_MASK) | PCI_PROBE_MMCONF; 416 } else { 417 /* 418 * Signal not to attempt to insert mmcfg resources because 419 * the architecture mmcfg setup could not initialize. 420 */ 421 pci_mmcfg_resources_inserted = 1; 422 } 423 } 424 425 void __init pci_mmcfg_early_init(int type) 426 { 427 __pci_mmcfg_init(type, 1); 428 } 429 430 void __init pci_mmcfg_late_init(void) 431 { 432 int type = 0; 433 434 if (pci_probe & PCI_PROBE_CONF1) 435 type = 1; 436 437 __pci_mmcfg_init(type, 0); 438 } 439 440 static int __init pci_mmcfg_late_insert_resources(void) 441 { 442 /* 443 * If resources are already inserted or we are not using MMCONFIG, 444 * don't insert the resources. 445 */ 446 if ((pci_mmcfg_resources_inserted == 1) || 447 (pci_probe & PCI_PROBE_MMCONF) == 0 || 448 (pci_mmcfg_config_num == 0) || 449 (pci_mmcfg_config == NULL) || 450 (pci_mmcfg_config[0].address == 0)) 451 return 1; 452 453 /* 454 * Attempt to insert the mmcfg resources but not with the busy flag 455 * marked so it won't cause request errors when __request_region is 456 * called. 457 */ 458 pci_mmcfg_insert_resources(0); 459 460 return 0; 461 } 462 463 /* 464 * Perform MMCONFIG resource insertion after PCI initialization to allow for 465 * misprogrammed MCFG tables that state larger sizes but actually conflict 466 * with other system resources. 467 */ 468 late_initcall(pci_mmcfg_late_insert_resources); 469