1 /* $NetBSD: pci_resource.c,v 1.5 2024/06/30 09:30:45 jmcneill Exp $ */ 2 3 /*- 4 * Copyright (c) 2022 Jared McNeill <jmcneill@invisible.ca> 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * pci_resource.c -- 31 * 32 * Scan current PCI resource allocations and attempt to assign resources 33 * to devices that are not configured WITHOUT changing any configuration 34 * performed by system firmware. 35 */ 36 37 #include <sys/cdefs.h> 38 __KERNEL_RCSID(0, "$NetBSD: pci_resource.c,v 1.5 2024/06/30 09:30:45 jmcneill Exp $"); 39 40 #include <sys/param.h> 41 #include <sys/bus.h> 42 #include <sys/systm.h> 43 #include <sys/kmem.h> 44 #include <sys/vmem.h> 45 46 #include <dev/pci/pcireg.h> 47 #include <dev/pci/pcivar.h> 48 #include <dev/pci/pcidevs.h> 49 #include <dev/pci/pci_resource.h> 50 51 #define DPRINT aprint_debug 52 53 #if defined(PCI_RESOURCE_TEST_VENDOR_ID) && \ 54 defined(PCI_RESOURCE_TEST_PRODUCT_ID) 55 #define IS_TEST_DEVICE(_pd) \ 56 (PCI_VENDOR(pd->pd_id) == PCI_RESOURCE_TEST_VENDOR_ID && \ 57 PCI_PRODUCT(pd->pd_id) == PCI_RESOURCE_TEST_PRODUCT_ID) 58 #else 59 #define IS_TEST_DEVICE(_pd) 0 60 #endif 61 62 #define PCI_MAX_DEVICE 32 63 #define PCI_MAX_FUNC 8 64 65 #define PCI_MAX_IORES 6 66 67 #define PCI_RANGE_FOREACH(_type) \ 68 for (u_int _type = PCI_RANGE_BUS; _type < NUM_PCI_RANGES; _type++) 69 70 static const char *pci_range_typenames[NUM_PCI_RANGES] = { 71 [PCI_RANGE_BUS] = "bus", 72 [PCI_RANGE_IO] = "io", 73 [PCI_RANGE_MEM] = "mem", 74 [PCI_RANGE_PMEM] = "pmem", 75 }; 76 77 struct pci_bus; 78 79 struct pci_iores { 80 uint64_t pi_base; /* Base address */ 81 uint64_t pi_size; /* Resource size */ 82 uint8_t pi_type; /* PCI_MAPREG_TYPE_* */ 83 u_int pi_bar; /* PCI bar number */ 84 union { 85 struct { 86 uint8_t memtype; 87 bool prefetch; 88 } pi_mem; 89 }; 90 }; 91 92 struct pci_device { 93 bool pd_present; /* Device is present */ 94 bool pd_configured; /* Device is configured */ 95 struct pci_bus *pd_bus; /* Parent bus */ 96 uint8_t pd_devno; /* Device number */ 97 uint8_t pd_funcno; /* Function number */ 98 pcitag_t pd_tag; /* PCI tag */ 99 100 pcireg_t pd_id; /* Vendor ID, Device ID */ 101 pcireg_t pd_class; /* Revision ID, Class Code */ 102 pcireg_t pd_bhlc; /* BIST, Header Type, Primary Latency 103 * Timer, Cache Line Size */ 104 105 struct pci_iores pd_iores[PCI_MAX_IORES]; 106 u_int pd_niores; 107 108 bool pd_ppb; /* PCI-PCI bridge */ 109 union { 110 struct { 111 pcireg_t bridge_bus; 112 struct pci_resource_range ranges[NUM_PCI_RANGES]; 113 } pd_bridge; 114 }; 115 }; 116 117 struct pci_bus { 118 uint8_t pb_busno; /* Bus number */ 119 struct pci_device *pb_bridge; /* Parent bridge, or NULL */ 120 121 struct pci_device pb_device[PCI_MAX_DEVICE * PCI_MAX_FUNC]; 122 /* Devices on bus */ 123 u_int pb_lastdevno; /* Last device found */ 124 125 struct pci_resource_range pb_ranges[NUM_PCI_RANGES]; 126 vmem_t *pb_res[NUM_PCI_RANGES]; 127 }; 128 129 struct pci_resources { 130 struct pci_bus **pr_bus; /* Bus list */ 131 pci_chipset_tag_t pr_pc; /* Chipset tag */ 132 uint8_t pr_startbus; /* First bus number */ 133 uint8_t pr_endbus; /* Last bus number */ 134 135 struct pci_resource_range pr_ranges[NUM_PCI_RANGES]; 136 vmem_t *pr_res[NUM_PCI_RANGES]; 137 }; 138 139 static int pci_resource_scan_bus(struct pci_resources *, 140 struct pci_device *, uint8_t); 141 142 #define PCI_SBDF_FMT "%04x:%02x:%02x.%u" 143 #define PCI_SBDF_FMT_ARGS(_pr, _pd) \ 144 pci_get_segment((_pr)->pr_pc), \ 145 (_pd)->pd_bus->pb_busno, \ 146 (_pd)->pd_devno, \ 147 (_pd)->pd_funcno 148 149 #define PCICONF_RES_BUS(_pr, _busno) \ 150 ((_pr)->pr_bus[(_busno) - (_pr)->pr_startbus]) 151 #define PCICONF_BUS_DEVICE(_pb, _devno, _funcno) \ 152 (&(_pb)->pb_device[(_devno) * PCI_MAX_FUNC + (_funcno)]) 153 154 /* 155 * pci_create_vmem -- 156 * 157 * Create a vmem arena covering the specified range, used for tracking 158 * PCI resources. 159 */ 160 static vmem_t * 161 pci_create_vmem(const char *name, bus_addr_t start, bus_addr_t end) 162 { 163 vmem_t *arena; 164 int error __diagused; 165 166 arena = vmem_create(name, 0, 0, 1, NULL, NULL, NULL, 0, VM_SLEEP, 167 IPL_NONE); 168 error = vmem_add(arena, start, end - start + 1, VM_SLEEP); 169 KASSERTMSG(error == 0, "error=%d", error); 170 171 return arena; 172 } 173 174 /* 175 * pci_new_bus -- 176 * 177 * Create a new PCI bus and initialize its resource ranges. 178 */ 179 static struct pci_bus * 180 pci_new_bus(struct pci_resources *pr, uint8_t busno, struct pci_device *bridge) 181 { 182 struct pci_bus *pb; 183 struct pci_resource_range *ranges; 184 185 pb = kmem_zalloc(sizeof(*pb), KM_SLEEP); 186 pb->pb_busno = busno; 187 pb->pb_bridge = bridge; 188 if (bridge == NULL) { 189 /* 190 * No additional constraints on resource allocations for 191 * the root bus. 192 */ 193 ranges = pr->pr_ranges; 194 } else { 195 /* 196 * Resource allocations for this bus are constrained by the 197 * bridge forwarding settings. 198 */ 199 ranges = bridge->pd_bridge.ranges; 200 } 201 memcpy(pb->pb_ranges, ranges, sizeof(pb->pb_ranges)); 202 203 return pb; 204 } 205 206 /* 207 * pci_resource_device_functions -- 208 * 209 * Returns the number of PCI functions for a a given bus and device. 210 */ 211 static uint8_t 212 pci_resource_device_functions(struct pci_resources *pr, 213 uint8_t busno, uint8_t devno) 214 { 215 struct pci_bus *pb; 216 struct pci_device *pd; 217 218 pb = PCICONF_RES_BUS(pr, busno); 219 pd = PCICONF_BUS_DEVICE(pb, devno, 0); 220 if (!pd->pd_present) { 221 return 0; 222 } 223 224 return PCI_HDRTYPE_MULTIFN(pd->pd_bhlc) ? 8 : 1; 225 } 226 227 /* 228 * pci_resource_device_print -- 229 * 230 * Log details about a device. 231 */ 232 static void 233 pci_resource_device_print(struct pci_resources *pr, 234 struct pci_device *pd) 235 { 236 struct pci_iores *pi; 237 u_int res; 238 239 DPRINT("PCI: " PCI_SBDF_FMT " %04x:%04x %02x 0x%06x", 240 PCI_SBDF_FMT_ARGS(pr, pd), 241 PCI_VENDOR(pd->pd_id), PCI_PRODUCT(pd->pd_id), 242 PCI_REVISION(pd->pd_class), (pd->pd_class >> 8) & 0xffffff); 243 244 switch (PCI_HDRTYPE_TYPE(pd->pd_bhlc)) { 245 case PCI_HDRTYPE_DEVICE: 246 DPRINT(" (device)\n"); 247 break; 248 case PCI_HDRTYPE_PPB: 249 DPRINT(" (bridge %u -> %u-%u)\n", 250 PCI_BRIDGE_BUS_NUM_PRIMARY(pd->pd_bridge.bridge_bus), 251 PCI_BRIDGE_BUS_NUM_SECONDARY(pd->pd_bridge.bridge_bus), 252 PCI_BRIDGE_BUS_NUM_SUBORDINATE(pd->pd_bridge.bridge_bus)); 253 254 if (pd->pd_bridge.ranges[PCI_RANGE_IO].end) { 255 DPRINT("PCI: " PCI_SBDF_FMT 256 " [bridge] window io %#" PRIx64 "-%#" PRIx64 257 "\n", 258 PCI_SBDF_FMT_ARGS(pr, pd), 259 pd->pd_bridge.ranges[PCI_RANGE_IO].start, 260 pd->pd_bridge.ranges[PCI_RANGE_IO].end); 261 } 262 if (pd->pd_bridge.ranges[PCI_RANGE_MEM].end) { 263 DPRINT("PCI: " PCI_SBDF_FMT 264 " [bridge] window mem %#" PRIx64 "-%#" PRIx64 265 " (non-prefetchable)\n", 266 PCI_SBDF_FMT_ARGS(pr, pd), 267 pd->pd_bridge.ranges[PCI_RANGE_MEM].start, 268 pd->pd_bridge.ranges[PCI_RANGE_MEM].end); 269 } 270 if (pd->pd_bridge.ranges[PCI_RANGE_PMEM].end) { 271 DPRINT("PCI: " PCI_SBDF_FMT 272 " [bridge] window mem %#" PRIx64 "-%#" PRIx64 273 " (prefetchable)\n", 274 PCI_SBDF_FMT_ARGS(pr, pd), 275 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start, 276 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end); 277 } 278 279 break; 280 default: 281 DPRINT(" (0x%02x)\n", PCI_HDRTYPE_TYPE(pd->pd_bhlc)); 282 } 283 284 for (res = 0; res < pd->pd_niores; res++) { 285 pi = &pd->pd_iores[res]; 286 287 DPRINT("PCI: " PCI_SBDF_FMT 288 " [device] resource BAR%u: %s @ %#" PRIx64 " size %#" 289 PRIx64, 290 PCI_SBDF_FMT_ARGS(pr, pd), pi->pi_bar, 291 pi->pi_type == PCI_MAPREG_TYPE_MEM ? "mem" : "io ", 292 pi->pi_base, pi->pi_size); 293 294 if (pi->pi_type == PCI_MAPREG_TYPE_MEM) { 295 switch (pi->pi_mem.memtype) { 296 case PCI_MAPREG_MEM_TYPE_32BIT: 297 DPRINT(", 32-bit"); 298 break; 299 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 300 DPRINT(", 32-bit (1M)"); 301 break; 302 case PCI_MAPREG_MEM_TYPE_64BIT: 303 DPRINT(", 64-bit"); 304 break; 305 } 306 DPRINT(" %sprefetchable", 307 pi->pi_mem.prefetch ? "" : "non-"); 308 } 309 DPRINT("\n"); 310 } 311 } 312 313 /* 314 * pci_resource_scan_bar -- 315 * 316 * Determine the current BAR configuration for a given device. 317 */ 318 static void 319 pci_resource_scan_bar(struct pci_resources *pr, 320 struct pci_device *pd, pcireg_t mapreg_start, pcireg_t mapreg_end, 321 bool is_ppb) 322 { 323 pci_chipset_tag_t pc = pr->pr_pc; 324 pcitag_t tag = pd->pd_tag; 325 pcireg_t mapreg = mapreg_start; 326 pcireg_t ocmd, cmd, bar[2], mask[2]; 327 uint64_t addr, size; 328 struct pci_iores *pi; 329 330 if (!is_ppb) { 331 ocmd = cmd = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG); 332 cmd &= ~(PCI_COMMAND_MASTER_ENABLE | 333 PCI_COMMAND_MEM_ENABLE | 334 PCI_COMMAND_IO_ENABLE); 335 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmd); 336 } 337 338 while (mapreg < mapreg_end) { 339 u_int width = 4; 340 341 bar[0] = pci_conf_read(pc, tag, mapreg); 342 pci_conf_write(pc, tag, mapreg, 0xffffffff); 343 mask[0] = pci_conf_read(pc, tag, mapreg); 344 pci_conf_write(pc, tag, mapreg, bar[0]); 345 346 switch (PCI_MAPREG_TYPE(mask[0])) { 347 case PCI_MAPREG_TYPE_MEM: 348 switch (PCI_MAPREG_MEM_TYPE(mask[0])) { 349 case PCI_MAPREG_MEM_TYPE_32BIT: 350 case PCI_MAPREG_MEM_TYPE_32BIT_1M: 351 size = PCI_MAPREG_MEM_SIZE(mask[0]); 352 addr = PCI_MAPREG_MEM_ADDR(bar[0]); 353 break; 354 case PCI_MAPREG_MEM_TYPE_64BIT: 355 bar[1] = pci_conf_read(pc, tag, mapreg + 4); 356 pci_conf_write(pc, tag, mapreg + 4, 0xffffffff); 357 mask[1] = pci_conf_read(pc, tag, mapreg + 4); 358 pci_conf_write(pc, tag, mapreg + 4, bar[1]); 359 360 size = PCI_MAPREG_MEM64_SIZE( 361 ((uint64_t)mask[1] << 32) | mask[0]); 362 addr = PCI_MAPREG_MEM64_ADDR( 363 ((uint64_t)bar[1] << 32) | bar[0]); 364 width = 8; 365 break; 366 default: 367 size = 0; 368 } 369 if (size > 0) { 370 pi = &pd->pd_iores[pd->pd_niores++]; 371 pi->pi_type = PCI_MAPREG_TYPE_MEM; 372 pi->pi_base = addr; 373 pi->pi_size = size; 374 pi->pi_bar = (mapreg - mapreg_start) / 4; 375 pi->pi_mem.memtype = 376 PCI_MAPREG_MEM_TYPE(mask[0]); 377 pi->pi_mem.prefetch = 378 PCI_MAPREG_MEM_PREFETCHABLE(mask[0]); 379 } 380 break; 381 case PCI_MAPREG_TYPE_IO: 382 size = PCI_MAPREG_IO_SIZE(mask[0] | 0xffff0000); 383 addr = PCI_MAPREG_IO_ADDR(bar[0]); 384 if (size > 0) { 385 pi = &pd->pd_iores[pd->pd_niores++]; 386 pi->pi_type = PCI_MAPREG_TYPE_IO; 387 pi->pi_base = addr; 388 pi->pi_size = size; 389 pi->pi_bar = (mapreg - mapreg_start) / 4; 390 } 391 break; 392 } 393 394 KASSERT(pd->pd_niores <= PCI_MAX_IORES); 395 396 mapreg += width; 397 } 398 399 if (!is_ppb) { 400 pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, ocmd); 401 } 402 } 403 404 /* 405 * pci_resource_scan_bridge -- 406 * 407 * Determine the current configuration of a PCI-PCI bridge. 408 */ 409 static void 410 pci_resource_scan_bridge(struct pci_resources *pr, 411 struct pci_device *pd) 412 { 413 pci_chipset_tag_t pc = pr->pr_pc; 414 pcitag_t tag = pd->pd_tag; 415 pcireg_t res, reshigh; 416 417 pd->pd_ppb = true; 418 419 res = pci_conf_read(pc, tag, PCI_BRIDGE_BUS_REG); 420 pd->pd_bridge.bridge_bus = res; 421 pd->pd_bridge.ranges[PCI_RANGE_BUS].start = 422 PCI_BRIDGE_BUS_NUM_SECONDARY(res); 423 pd->pd_bridge.ranges[PCI_RANGE_BUS].end = 424 PCI_BRIDGE_BUS_NUM_SUBORDINATE(res); 425 426 res = pci_conf_read(pc, tag, PCI_BRIDGE_STATIO_REG); 427 pd->pd_bridge.ranges[PCI_RANGE_IO].start = 428 PCI_BRIDGE_STATIO_IOBASE_ADDR(res); 429 pd->pd_bridge.ranges[PCI_RANGE_IO].end = 430 PCI_BRIDGE_STATIO_IOLIMIT_ADDR(res); 431 if (PCI_BRIDGE_IO_32BITS(res)) { 432 reshigh = pci_conf_read(pc, tag, PCI_BRIDGE_IOHIGH_REG); 433 pd->pd_bridge.ranges[PCI_RANGE_IO].start |= 434 __SHIFTOUT(reshigh, PCI_BRIDGE_IOHIGH_BASE) << 16; 435 pd->pd_bridge.ranges[PCI_RANGE_IO].end |= 436 __SHIFTOUT(reshigh, PCI_BRIDGE_IOHIGH_LIMIT) << 16; 437 } 438 if (pd->pd_bridge.ranges[PCI_RANGE_IO].start >= 439 pd->pd_bridge.ranges[PCI_RANGE_IO].end) { 440 pd->pd_bridge.ranges[PCI_RANGE_IO].start = 0; 441 pd->pd_bridge.ranges[PCI_RANGE_IO].end = 0; 442 } 443 444 res = pci_conf_read(pc, tag, PCI_BRIDGE_MEMORY_REG); 445 pd->pd_bridge.ranges[PCI_RANGE_MEM].start = 446 PCI_BRIDGE_MEMORY_BASE_ADDR(res); 447 pd->pd_bridge.ranges[PCI_RANGE_MEM].end = 448 PCI_BRIDGE_MEMORY_LIMIT_ADDR(res); 449 if (pd->pd_bridge.ranges[PCI_RANGE_MEM].start >= 450 pd->pd_bridge.ranges[PCI_RANGE_MEM].end) { 451 pd->pd_bridge.ranges[PCI_RANGE_MEM].start = 0; 452 pd->pd_bridge.ranges[PCI_RANGE_MEM].end = 0; 453 } 454 455 res = pci_conf_read(pc, tag, PCI_BRIDGE_PREFETCHMEM_REG); 456 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start = 457 PCI_BRIDGE_PREFETCHMEM_BASE_ADDR(res); 458 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end = 459 PCI_BRIDGE_PREFETCHMEM_LIMIT_ADDR(res); 460 if (PCI_BRIDGE_PREFETCHMEM_64BITS(res)) { 461 reshigh = pci_conf_read(pc, tag, 462 PCI_BRIDGE_PREFETCHBASEUP32_REG); 463 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start |= 464 (uint64_t)reshigh << 32; 465 reshigh = pci_conf_read(pc, tag, 466 PCI_BRIDGE_PREFETCHLIMITUP32_REG); 467 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end |= 468 (uint64_t)reshigh << 32; 469 } 470 if (pd->pd_bridge.ranges[PCI_RANGE_PMEM].start >= 471 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end) { 472 pd->pd_bridge.ranges[PCI_RANGE_PMEM].start = 0; 473 pd->pd_bridge.ranges[PCI_RANGE_PMEM].end = 0; 474 } 475 } 476 477 /* 478 * pci_resource_scan_device -- 479 * 480 * Determine the current configuration of a PCI device. 481 */ 482 static bool 483 pci_resource_scan_device(struct pci_resources *pr, 484 struct pci_bus *parent_bus, uint8_t devno, uint8_t funcno) 485 { 486 struct pci_device *pd; 487 pcitag_t tag; 488 pcireg_t id, bridge_bus; 489 uint8_t sec_bus; 490 491 tag = pci_make_tag(pr->pr_pc, parent_bus->pb_busno, devno, funcno); 492 id = pci_conf_read(pr->pr_pc, tag, PCI_ID_REG); 493 if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) { 494 return false; 495 } 496 497 pd = PCICONF_BUS_DEVICE(parent_bus, devno, funcno); 498 pd->pd_present = true; 499 pd->pd_bus = parent_bus; 500 pd->pd_tag = tag; 501 pd->pd_devno = devno; 502 pd->pd_funcno = funcno; 503 pd->pd_id = id; 504 pd->pd_class = pci_conf_read(pr->pr_pc, tag, PCI_CLASS_REG); 505 pd->pd_bhlc = pci_conf_read(pr->pr_pc, tag, PCI_BHLC_REG); 506 507 switch (PCI_HDRTYPE_TYPE(pd->pd_bhlc)) { 508 case PCI_HDRTYPE_DEVICE: 509 pci_resource_scan_bar(pr, pd, PCI_MAPREG_START, 510 PCI_MAPREG_END, false); 511 break; 512 case PCI_HDRTYPE_PPB: 513 pci_resource_scan_bar(pr, pd, PCI_MAPREG_START, 514 PCI_MAPREG_PPB_END, true); 515 pci_resource_scan_bridge(pr, pd); 516 break; 517 } 518 519 pci_resource_device_print(pr, pd); 520 521 if (PCI_HDRTYPE_TYPE(pd->pd_bhlc) == PCI_HDRTYPE_PPB && 522 PCI_CLASS(pd->pd_class) == PCI_CLASS_BRIDGE && 523 PCI_SUBCLASS(pd->pd_class) == PCI_SUBCLASS_BRIDGE_PCI) { 524 bridge_bus = pci_conf_read(pr->pr_pc, tag, PCI_BRIDGE_BUS_REG); 525 sec_bus = PCI_BRIDGE_BUS_NUM_SECONDARY(bridge_bus); 526 if (sec_bus <= pr->pr_endbus) { 527 if (pci_resource_scan_bus(pr, pd, sec_bus) != 0) { 528 DPRINT("PCI: " PCI_SBDF_FMT " bus %u " 529 "already scanned (firmware bug!)\n", 530 PCI_SBDF_FMT_ARGS(pr, pd), sec_bus); 531 } 532 } 533 } 534 535 return true; 536 } 537 538 /* 539 * pci_resource_scan_bus -- 540 * 541 * Enumerate devices on a bus, recursively. 542 */ 543 static int 544 pci_resource_scan_bus(struct pci_resources *pr, 545 struct pci_device *bridge_dev, uint8_t busno) 546 { 547 struct pci_bus *pb; 548 uint8_t devno, funcno; 549 uint8_t nfunc; 550 551 KASSERT(busno >= pr->pr_startbus); 552 KASSERT(busno <= pr->pr_endbus); 553 554 if (PCICONF_RES_BUS(pr, busno) != NULL) { 555 /* 556 * Firmware has configured more than one bridge with the 557 * same secondary bus number. 558 */ 559 return EINVAL; 560 } 561 562 pb = pci_new_bus(pr, busno, bridge_dev); 563 PCICONF_RES_BUS(pr, busno) = pb; 564 565 for (devno = 0; devno < PCI_MAX_DEVICE; devno++) { 566 if (!pci_resource_scan_device(pr, pb, devno, 0)) { 567 continue; 568 } 569 pb->pb_lastdevno = devno; 570 571 nfunc = pci_resource_device_functions(pr, busno, devno); 572 for (funcno = 1; funcno < nfunc; funcno++) { 573 pci_resource_scan_device(pr, pb, devno, funcno); 574 } 575 } 576 577 return 0; 578 } 579 580 /* 581 * pci_resource_claim -- 582 * 583 * Claim a resource from a vmem arena. This is called to inform the 584 * resource manager about resources already configured by system firmware. 585 */ 586 static int 587 pci_resource_claim(vmem_t *arena, vmem_addr_t start, vmem_addr_t end) 588 { 589 KASSERT(end >= start); 590 591 return vmem_xalloc(arena, end - start + 1, 0, 0, 0, start, end, 592 VM_BESTFIT | VM_NOSLEEP, NULL); 593 } 594 595 /* 596 * pci_resource_alloc -- 597 * 598 * Allocate a resource from a vmem arena. This is called when configuring 599 * devices that were not already configured by system firmware. 600 */ 601 static int 602 pci_resource_alloc(vmem_t *arena, vmem_size_t size, vmem_size_t align, 603 uint64_t *base) 604 { 605 vmem_addr_t addr; 606 int error; 607 608 KASSERT(size != 0); 609 610 error = vmem_xalloc(arena, size, align, 0, 0, VMEM_ADDR_MIN, 611 VMEM_ADDR_MAX, VM_BESTFIT | VM_NOSLEEP, &addr); 612 if (error == 0) { 613 *base = (uint64_t)addr; 614 } 615 616 return error; 617 } 618 619 /* 620 * pci_resource_init_device -- 621 * 622 * Discover resources assigned by system firmware, notify the resource 623 * manager of these ranges, and determine if the device has additional 624 * resources that need to be allocated. 625 */ 626 static void 627 pci_resource_init_device(struct pci_resources *pr, 628 struct pci_device *pd) 629 { 630 struct pci_iores *pi; 631 struct pci_bus *pb = pd->pd_bus; 632 vmem_t *res_io = pb->pb_res[PCI_RANGE_IO]; 633 vmem_t *res_mem = pb->pb_res[PCI_RANGE_MEM]; 634 vmem_t *res_pmem = pb->pb_res[PCI_RANGE_PMEM]; 635 pcireg_t cmd; 636 u_int enabled, required; 637 u_int iores; 638 int error; 639 640 KASSERT(pd->pd_present); 641 642 if (IS_TEST_DEVICE(pd)) { 643 cmd = pci_conf_read(pr->pr_pc, pd->pd_tag, 644 PCI_COMMAND_STATUS_REG); 645 cmd &= ~(PCI_COMMAND_MEM_ENABLE|PCI_COMMAND_IO_ENABLE| 646 PCI_COMMAND_MASTER_ENABLE); 647 pci_conf_write(pr->pr_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG, 648 cmd); 649 } 650 651 enabled = required = 0; 652 cmd = pci_conf_read(pr->pr_pc, pd->pd_tag, PCI_COMMAND_STATUS_REG); 653 if ((cmd & PCI_COMMAND_MEM_ENABLE) != 0) { 654 enabled |= __BIT(PCI_MAPREG_TYPE_MEM); 655 } 656 if ((cmd & PCI_COMMAND_IO_ENABLE) != 0) { 657 enabled |= __BIT(PCI_MAPREG_TYPE_IO); 658 } 659 660 for (iores = 0; iores < pd->pd_niores; iores++) { 661 pi = &pd->pd_iores[iores]; 662 663 required |= __BIT(pi->pi_type); 664 665 if (IS_TEST_DEVICE(pd)) { 666 pci_conf_write(pr->pr_pc, pd->pd_tag, 667 PCI_BAR(pi->pi_bar), 0); 668 continue; 669 } 670 if ((enabled & __BIT(pi->pi_type)) == 0) { 671 continue; 672 } 673 674 if (pi->pi_type == PCI_MAPREG_TYPE_IO) { 675 error = res_io == NULL ? ERANGE : 676 pci_resource_claim(res_io, pi->pi_base, 677 pi->pi_base + pi->pi_size - 1); 678 if (error) { 679 DPRINT("PCI: " PCI_SBDF_FMT " [device] io " 680 " %#" PRIx64 "-%#" PRIx64 681 " invalid (%d)\n", 682 PCI_SBDF_FMT_ARGS(pr, pd), 683 pi->pi_base, 684 pi->pi_base + pi->pi_size - 1, 685 error); 686 } 687 continue; 688 } 689 690 KASSERT(pi->pi_type == PCI_MAPREG_TYPE_MEM); 691 error = ERANGE; 692 if (pi->pi_mem.prefetch) { 693 /* 694 * Prefetchable memory must be allocated from the 695 * bridge's prefetchable region. 696 */ 697 if (res_pmem != NULL) { 698 error = pci_resource_claim(res_pmem, pi->pi_base, 699 pi->pi_base + pi->pi_size - 1); 700 } 701 } else if (pi->pi_mem.memtype == PCI_MAPREG_MEM_TYPE_64BIT) { 702 /* 703 * Non-prefetchable 64-bit memory can be allocated from 704 * any range. Prefer allocations from the prefetchable 705 * region to save 32-bit only resources for 32-bit BARs. 706 */ 707 if (res_pmem != NULL) { 708 error = pci_resource_claim(res_pmem, pi->pi_base, 709 pi->pi_base + pi->pi_size - 1); 710 } 711 if (error && res_mem != NULL) { 712 error = pci_resource_claim(res_mem, pi->pi_base, 713 pi->pi_base + pi->pi_size - 1); 714 } 715 } else { 716 /* 717 * Non-prefetchable 32-bit memory can be allocated from 718 * any range, provided that the range is below 4GB. Try 719 * the non-prefetchable range first, and if that fails, 720 * make one last attempt at allocating from the 721 * prefetchable range in case the platform provides 722 * memory below 4GB. 723 */ 724 if (res_mem != NULL) { 725 error = pci_resource_claim(res_mem, pi->pi_base, 726 pi->pi_base + pi->pi_size - 1); 727 } 728 if (error && res_pmem != NULL) { 729 error = pci_resource_claim(res_pmem, pi->pi_base, 730 pi->pi_base + pi->pi_size - 1); 731 } 732 } 733 if (error) { 734 DPRINT("PCI: " PCI_SBDF_FMT " [device] mem" 735 " (%sprefetchable)" 736 " %#" PRIx64 "-%#" PRIx64 737 " invalid (%d)\n", 738 PCI_SBDF_FMT_ARGS(pr, pd), 739 pi->pi_mem.prefetch ? "" : "non-", 740 pi->pi_base, 741 pi->pi_base + pi->pi_size - 1, 742 error); 743 } 744 } 745 746 pd->pd_configured = (enabled & required) == required; 747 748 if (!pd->pd_configured) { 749 DPRINT("PCI: " PCI_SBDF_FMT " [device] " 750 "not configured by firmware\n", 751 PCI_SBDF_FMT_ARGS(pr, pd)); 752 } 753 } 754 755 /* 756 * pci_resource_init_bus -- 757 * 758 * Discover resources in use on a given bus, recursively. 759 */ 760 static void 761 pci_resource_init_bus(struct pci_resources *pr, uint8_t busno) 762 { 763 struct pci_bus *pb, *parent_bus; 764 struct pci_device *pd, *bridge; 765 uint8_t devno, funcno; 766 uint8_t nfunc; 767 int error; 768 769 KASSERT(busno >= pr->pr_startbus); 770 KASSERT(busno <= pr->pr_endbus); 771 772 pb = PCICONF_RES_BUS(pr, busno); 773 bridge = pb->pb_bridge; 774 775 KASSERT(pb != NULL); 776 KASSERT((busno == pr->pr_startbus) == (bridge == NULL)); 777 778 if (bridge == NULL) { 779 /* Use resources provided by firmware. */ 780 PCI_RANGE_FOREACH(prtype) { 781 pb->pb_res[prtype] = pr->pr_res[prtype]; 782 pr->pr_res[prtype] = NULL; 783 } 784 } else { 785 /* 786 * Using the resources configured in to the bridge by 787 * firmware, claim the resources on the parent bus and 788 * create a new vmem arena for the secondary bus. 789 */ 790 KASSERT(bridge->pd_bus != NULL); 791 parent_bus = bridge->pd_bus; 792 PCI_RANGE_FOREACH(prtype) { 793 if (parent_bus->pb_res[prtype] == NULL || 794 !bridge->pd_bridge.ranges[prtype].end) { 795 continue; 796 } 797 error = pci_resource_claim( 798 parent_bus->pb_res[prtype], 799 bridge->pd_bridge.ranges[prtype].start, 800 bridge->pd_bridge.ranges[prtype].end); 801 if (error == 0) { 802 pb->pb_res[prtype] = pci_create_vmem( 803 pci_resource_typename(prtype), 804 bridge->pd_bridge.ranges[prtype].start, 805 bridge->pd_bridge.ranges[prtype].end); 806 KASSERT(pb->pb_res[prtype] != NULL); 807 } else { 808 DPRINT("PCI: " PCI_SBDF_FMT " bridge (bus %u)" 809 " %-4s %#" PRIx64 "-%#" PRIx64 810 " invalid\n", 811 PCI_SBDF_FMT_ARGS(pr, bridge), busno, 812 pci_resource_typename(prtype), 813 bridge->pd_bridge.ranges[prtype].start, 814 bridge->pd_bridge.ranges[prtype].end); 815 } 816 } 817 } 818 819 for (devno = 0; devno <= pb->pb_lastdevno; devno++) { 820 KASSERT(devno < PCI_MAX_DEVICE); 821 nfunc = pci_resource_device_functions(pr, busno, devno); 822 for (funcno = 0; funcno < nfunc; funcno++) { 823 pd = PCICONF_BUS_DEVICE(pb, devno, funcno); 824 if (!pd->pd_present) { 825 continue; 826 } 827 if (pd->pd_ppb) { 828 uint8_t sec_bus = PCI_BRIDGE_BUS_NUM_SECONDARY( 829 pd->pd_bridge.bridge_bus); 830 pci_resource_init_bus(pr, sec_bus); 831 } 832 pci_resource_init_device(pr, pd); 833 } 834 } 835 } 836 837 /* 838 * pci_resource_probe -- 839 * 840 * Scan for PCI devices and initialize the resource manager. 841 */ 842 static void 843 pci_resource_probe(struct pci_resources *pr, 844 const struct pci_resource_info *info) 845 { 846 uint8_t startbus = (uint8_t)info->ranges[PCI_RANGE_BUS].start; 847 uint8_t endbus = (uint8_t)info->ranges[PCI_RANGE_BUS].end; 848 u_int nbus; 849 850 KASSERT(startbus <= endbus); 851 KASSERT(pr->pr_bus == NULL); 852 853 nbus = endbus - startbus + 1; 854 855 pr->pr_pc = info->pc; 856 pr->pr_startbus = startbus; 857 pr->pr_endbus = endbus; 858 pr->pr_bus = kmem_zalloc(nbus * sizeof(struct pci_bus *), KM_SLEEP); 859 memcpy(pr->pr_ranges, info->ranges, sizeof(pr->pr_ranges)); 860 PCI_RANGE_FOREACH(prtype) { 861 if (prtype == PCI_RANGE_BUS || info->ranges[prtype].end) { 862 pr->pr_res[prtype] = pci_create_vmem( 863 pci_resource_typename(prtype), 864 info->ranges[prtype].start, 865 info->ranges[prtype].end); 866 KASSERT(pr->pr_res[prtype] != NULL); 867 } 868 } 869 870 /* Scan devices */ 871 pci_resource_scan_bus(pr, NULL, pr->pr_startbus); 872 873 /* 874 * Create per-bus resource pools and remove ranges that are already 875 * in use by devices and downstream bridges. 876 */ 877 pci_resource_init_bus(pr, pr->pr_startbus); 878 } 879 880 /* 881 * pci_resource_alloc_device -- 882 * 883 * Attempt to allocate resources for a given device. 884 */ 885 static void 886 pci_resource_alloc_device(struct pci_resources *pr, struct pci_device *pd) 887 { 888 struct pci_iores *pi; 889 vmem_t *arena; 890 pcireg_t cmd, ocmd, base; 891 uint64_t addr; 892 u_int enabled; 893 u_int res; 894 u_int align; 895 int error; 896 897 enabled = 0; 898 ocmd = cmd = pci_conf_read(pr->pr_pc, pd->pd_tag, 899 PCI_COMMAND_STATUS_REG); 900 if ((cmd & PCI_COMMAND_MEM_ENABLE) != 0) { 901 enabled |= __BIT(PCI_MAPREG_TYPE_MEM); 902 } 903 if ((cmd & PCI_COMMAND_IO_ENABLE) != 0) { 904 enabled |= __BIT(PCI_MAPREG_TYPE_IO); 905 } 906 907 for (res = 0; res < pd->pd_niores; res++) { 908 pi = &pd->pd_iores[res]; 909 910 if ((enabled & __BIT(pi->pi_type)) != 0) { 911 continue; 912 } 913 914 if (pi->pi_type == PCI_MAPREG_TYPE_IO) { 915 arena = pd->pd_bus->pb_res[PCI_RANGE_IO]; 916 align = uimax(pi->pi_size, 4); 917 } else { 918 KASSERT(pi->pi_type == PCI_MAPREG_TYPE_MEM); 919 arena = NULL; 920 align = uimax(pi->pi_size, 16); 921 if (pi->pi_mem.prefetch) { 922 arena = pd->pd_bus->pb_res[PCI_RANGE_PMEM]; 923 } 924 if (arena == NULL) { 925 arena = pd->pd_bus->pb_res[PCI_RANGE_MEM]; 926 } 927 } 928 if (arena == NULL) { 929 DPRINT("PCI: " PCI_SBDF_FMT " BAR%u failed to" 930 " allocate %#" PRIx64 " bytes (no arena)\n", 931 PCI_SBDF_FMT_ARGS(pr, pd), 932 pi->pi_bar, pi->pi_size); 933 return; 934 } 935 error = pci_resource_alloc(arena, pi->pi_size, align, &addr); 936 if (error != 0) { 937 DPRINT("PCI: " PCI_SBDF_FMT " BAR%u failed to" 938 " allocate %#" PRIx64 " bytes (no space)\n", 939 PCI_SBDF_FMT_ARGS(pr, pd), 940 pi->pi_bar, pi->pi_size); 941 return; 942 } 943 DPRINT("PCI: " PCI_SBDF_FMT " BAR%u assigned range" 944 " 0x%#" PRIx64 "-0x%#" PRIx64 "\n", 945 PCI_SBDF_FMT_ARGS(pr, pd), 946 pi->pi_bar, addr, addr + pi->pi_size - 1); 947 948 if (pi->pi_type == PCI_MAPREG_TYPE_IO) { 949 cmd |= PCI_COMMAND_IO_ENABLE; 950 pci_conf_write(pr->pr_pc, pd->pd_tag, 951 PCI_BAR(pi->pi_bar), 952 PCI_MAPREG_IO_ADDR(addr) | PCI_MAPREG_TYPE_IO); 953 } else { 954 cmd |= PCI_COMMAND_MEM_ENABLE; 955 base = pci_conf_read(pr->pr_pc, pd->pd_tag, 956 PCI_BAR(pi->pi_bar)); 957 base = PCI_MAPREG_MEM_ADDR(addr) | 958 PCI_MAPREG_MEM_TYPE(base); 959 pci_conf_write(pr->pr_pc, pd->pd_tag, 960 PCI_BAR(pi->pi_bar), base); 961 if (pi->pi_mem.memtype == PCI_MAPREG_MEM_TYPE_64BIT) { 962 base = (pcireg_t) 963 (PCI_MAPREG_MEM64_ADDR(addr) >> 32); 964 pci_conf_write(pr->pr_pc, pd->pd_tag, 965 PCI_BAR(pi->pi_bar + 1), base); 966 } 967 } 968 } 969 970 if (ocmd != cmd) { 971 pci_conf_write(pr->pr_pc, pd->pd_tag, 972 PCI_COMMAND_STATUS_REG, cmd); 973 } 974 } 975 976 /* 977 * pci_resource_alloc_bus -- 978 * 979 * Attempt to assign resources to all devices on a given bus, recursively. 980 */ 981 static void 982 pci_resource_alloc_bus(struct pci_resources *pr, uint8_t busno) 983 { 984 struct pci_bus *pb = PCICONF_RES_BUS(pr, busno); 985 struct pci_device *pd; 986 uint8_t devno, funcno; 987 988 for (devno = 0; devno <= pb->pb_lastdevno; devno++) { 989 for (funcno = 0; funcno < 8; funcno++) { 990 pd = PCICONF_BUS_DEVICE(pb, devno, funcno); 991 if (!pd->pd_present) { 992 if (funcno == 0) { 993 break; 994 } 995 continue; 996 } 997 if (!pd->pd_configured) { 998 pci_resource_alloc_device(pr, pd); 999 } 1000 if (pd->pd_ppb) { 1001 uint8_t sec_bus = PCI_BRIDGE_BUS_NUM_SECONDARY( 1002 pd->pd_bridge.bridge_bus); 1003 pci_resource_alloc_bus(pr, sec_bus); 1004 } 1005 } 1006 } 1007 } 1008 1009 /* 1010 * pci_resource_init -- 1011 * 1012 * Public interface to PCI resource manager. Scans for available devices 1013 * and assigns resources. 1014 */ 1015 void 1016 pci_resource_init(const struct pci_resource_info *info) 1017 { 1018 struct pci_resources pr = {}; 1019 1020 pci_resource_probe(&pr, info); 1021 pci_resource_alloc_bus(&pr, pr.pr_startbus); 1022 } 1023 1024 /* 1025 * pci_resource_typename -- 1026 * 1027 * Return a string description of a PCI range type. 1028 */ 1029 const char * 1030 pci_resource_typename(enum pci_range_type prtype) 1031 { 1032 KASSERT(prtype < NUM_PCI_RANGES); 1033 return pci_range_typenames[prtype]; 1034 } 1035