1/* 2 * Copyright (c) 2018, Damien Zammit 3 * Copyright (c) 2017, Joan Lledó 4 * Copyright (c) 2009, 2012 Samuel Thibault 5 * Heavily inspired from the freebsd, netbsd, and openbsd backends 6 * (C) Copyright Eric Anholt 2006 7 * (C) Copyright IBM Corporation 2006 8 * Copyright (c) 2008 Juan Romero Pardines 9 * Copyright (c) 2008 Mark Kettenis 10 * 11 * Permission to use, copy, modify, and distribute this software for any 12 * purpose with or without fee is hereby granted, provided that the above 13 * copyright notice and this permission notice appear in all copies. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 */ 23 24#define _GNU_SOURCE 25#include <unistd.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <errno.h> 29#include <sys/types.h> 30#include <sys/stat.h> 31#include <fcntl.h> 32#include <dirent.h> 33#include <sys/mman.h> 34#include <string.h> 35#include <strings.h> 36#include <mach.h> 37#include <hurd.h> 38#include <hurd/pci.h> 39#include <hurd/paths.h> 40#include <hurd/fs.h> 41#include <device/device.h> 42 43#include "x86_pci.h" 44#include "pciaccess.h" 45#include "pciaccess_private.h" 46 47/* 48 * Hurd PCI access using RPCs. 49 * 50 * Some functions are shared with the x86 module to avoid repeating code. 51 */ 52 53/* Server path */ 54#define _SERVERS_BUS_PCI _SERVERS_BUS "/pci" 55 56/* File names */ 57#define FILE_CONFIG_NAME "config" 58#define FILE_REGION_NAME "region" 59#define FILE_ROM_NAME "rom" 60 61#define LEGACY_REGION -1 62 63/* Level in the fs tree */ 64typedef enum { 65 LEVEL_NONE, 66 LEVEL_DOMAIN, 67 LEVEL_BUS, 68 LEVEL_DEV, 69 LEVEL_FUNC 70} tree_level; 71 72struct pci_system_hurd { 73 struct pci_system system; 74 mach_port_t root; 75}; 76 77static int 78pci_device_hurd_probe(struct pci_device *dev) 79{ 80 uint8_t irq; 81 int err, i; 82 struct pci_bar regions[6]; 83 struct pci_xrom_bar rom; 84 struct pci_device_private *d; 85 mach_msg_type_number_t size; 86 char *buf; 87 88 /* Many of the fields were filled in during initial device enumeration. 89 * At this point, we need to fill in regions, rom_size, and irq. 90 */ 91 92 err = pci_device_cfg_read_u8(dev, &irq, PCI_IRQ); 93 if (err) 94 return err; 95 dev->irq = irq; 96 97 /* Get regions */ 98 buf = (char *)®ions; 99 size = sizeof(regions); 100 d = (struct pci_device_private *)dev; 101 err = pci_get_dev_regions(d->device_port, &buf, &size); 102 if(err) 103 return err; 104 105 if((char*)®ions != buf) 106 { 107 /* Sanity check for bogus server. */ 108 if(size > sizeof(regions)) 109 { 110 vm_deallocate(mach_task_self(), (vm_address_t) buf, size); 111 return EGRATUITOUS; 112 } 113 114 memcpy(®ions, buf, size); 115 vm_deallocate(mach_task_self(), (vm_address_t) buf, size); 116 } 117 118 for(i=0; i<6; i++) 119 { 120 if(regions[i].size == 0) 121 continue; 122 123 dev->regions[i].base_addr = regions[i].base_addr; 124 dev->regions[i].size = regions[i].size; 125 dev->regions[i].is_IO = regions[i].is_IO; 126 dev->regions[i].is_prefetchable = regions[i].is_prefetchable; 127 dev->regions[i].is_64 = regions[i].is_64; 128 } 129 130 /* Get rom info */ 131 buf = (char *)&rom; 132 size = sizeof(rom); 133 err = pci_get_dev_rom(d->device_port, &buf, &size); 134 if(err) 135 return err; 136 137 if((char*)&rom != buf) 138 { 139 /* Sanity check for bogus server. */ 140 if(size > sizeof(rom)) 141 { 142 vm_deallocate(mach_task_self(), (vm_address_t) buf, size); 143 return EGRATUITOUS; 144 } 145 146 memcpy(&rom, buf, size); 147 vm_deallocate(mach_task_self(), (vm_address_t) buf, size); 148 } 149 150 d->rom_base = rom.base_addr; 151 dev->rom_size = rom.size; 152 153 return 0; 154} 155 156static void 157pci_system_hurd_destroy(void) 158{ 159 struct pci_system_hurd *pci_sys_hurd = (struct pci_system_hurd *)pci_sys; 160 161 x86_disable_io(); 162 mach_port_deallocate(mach_task_self(), pci_sys_hurd->root); 163} 164 165static int 166pci_device_hurd_map_range(struct pci_device *dev, 167 struct pci_device_mapping *map) 168{ 169#if 0 170 struct pci_device_private *d = (struct pci_device_private *)dev; 171#endif 172 struct pci_system_hurd *pci_sys_hurd = (struct pci_system_hurd *)pci_sys; 173 int err = 0; 174 file_t file = MACH_PORT_NULL; 175 memory_object_t robj, wobj, pager; 176 vm_offset_t offset; 177 vm_prot_t prot = VM_PROT_READ; 178 const struct pci_mem_region *region; 179 const struct pci_mem_region rom_region = { 180#if 0 181 /* FIXME: We should be doing this: */ 182 .base_addr = d->rom_base, 183 /* But currently pci-arbiter cannot get rom_base from libpciaccess, so we 184 are here assuming the caller is mapping from the rom base */ 185#else 186 .base_addr = map->base, 187#endif 188 .size = dev->rom_size, 189 }; 190 int flags = O_RDONLY; 191 char server[NAME_MAX]; 192 193 if (map->flags & PCI_DEV_MAP_FLAG_WRITABLE) { 194 prot |= VM_PROT_WRITE; 195 flags = O_RDWR; 196 } 197 198 if (map->region != LEGACY_REGION) { 199 region = &dev->regions[map->region]; 200 snprintf(server, NAME_MAX, "%04x/%02x/%02x/%01u/%s%01u", 201 dev->domain, dev->bus, dev->dev, dev->func, 202 FILE_REGION_NAME, map->region); 203 } else { 204 region = &rom_region; 205 snprintf(server, NAME_MAX, "%04x/%02x/%02x/%01u/%s", 206 dev->domain, dev->bus, dev->dev, dev->func, 207 FILE_ROM_NAME); 208 if (map->base < region->base_addr || 209 map->base + map->size > region->base_addr + region->size) 210 return EINVAL; 211 } 212 213 file = file_name_lookup_under (pci_sys_hurd->root, server, flags, 0); 214 if (! MACH_PORT_VALID (file)) { 215 return errno; 216 } 217 218 err = io_map (file, &robj, &wobj); 219 mach_port_deallocate (mach_task_self(), file); 220 if (err) 221 return err; 222 223 switch (prot & (VM_PROT_READ|VM_PROT_WRITE)) { 224 case VM_PROT_READ: 225 pager = robj; 226 if (wobj != MACH_PORT_NULL) 227 mach_port_deallocate (mach_task_self(), wobj); 228 break; 229 case VM_PROT_READ|VM_PROT_WRITE: 230 if (robj == wobj) { 231 if (robj == MACH_PORT_NULL) 232 return EPERM; 233 234 pager = wobj; 235 /* Remove extra reference. */ 236 mach_port_deallocate (mach_task_self (), pager); 237 } 238 else { 239 if (robj != MACH_PORT_NULL) 240 mach_port_deallocate (mach_task_self (), robj); 241 if (wobj != MACH_PORT_NULL) 242 mach_port_deallocate (mach_task_self (), wobj); 243 244 return EPERM; 245 } 246 break; 247 default: 248 return EINVAL; 249 } 250 251 offset = map->base - region->base_addr; 252 err = vm_map (mach_task_self (), (vm_address_t *)&map->memory, map->size, 253 0, 1, 254 pager, /* a memory object proxy containing only the region */ 255 offset, /* offset from region start */ 256 0, prot, VM_PROT_ALL, VM_INHERIT_SHARE); 257 mach_port_deallocate (mach_task_self(), pager); 258 259 return err; 260} 261 262static int 263pci_device_hurd_unmap_range(struct pci_device *dev, 264 struct pci_device_mapping *map) 265{ 266 int err; 267 err = pci_device_generic_unmap_range(dev, map); 268 map->memory = NULL; 269 270 return err; 271} 272 273static int 274pci_device_hurd_map_legacy(struct pci_device *dev, pciaddr_t base, 275 pciaddr_t size, unsigned map_flags, void **addr) 276{ 277 struct pci_device_mapping map; 278 int err; 279 280 if (base >= 0xC0000 && base < 0x100000) { 281 /* FIXME: We would rather know for sure from d->rom_base whether this is 282 the ROM or not but currently pci-arbiter cannot get rom_base from 283 libpciaccess, so we are here assuming the caller is mapping from the 284 rom base */ 285 map.base = base; 286 map.size = size; 287 map.flags = map_flags; 288 map.region = LEGACY_REGION; 289 err = pci_device_hurd_map_range(dev, &map); 290 *addr = map.memory; 291 292 if (!err) 293 return 0; 294 } 295 296 /* This is probably not the ROM, this is probably something like VRam or 297 the interrupt table, just map it by hand. */ 298 return pci_system_x86_map_dev_mem(addr, base, size, !!(map_flags & PCI_DEV_MAP_FLAG_WRITABLE)); 299} 300 301static int 302pci_device_hurd_unmap_legacy(struct pci_device *dev, void *addr, 303 pciaddr_t size) 304{ 305 struct pci_device_mapping map; 306 307 map.size = size; 308 map.flags = 0; 309 map.region = LEGACY_REGION; 310 map.memory = addr; 311 312 return pci_device_hurd_unmap_range(dev, &map); 313} 314 315/* 316 * Read `nbytes' bytes from `reg' in device's configuration space 317 * and store them in `buf'. 318 * 319 * It's assumed that `nbytes' bytes are allocated in `buf' 320 */ 321static int 322pciclient_cfg_read(mach_port_t device_port, int reg, char *buf, 323 size_t * nbytes) 324{ 325 int err; 326 mach_msg_type_number_t nread; 327 char *data; 328 329 data = buf; 330 nread = *nbytes; 331 err = __pci_conf_read(device_port, reg, &data, &nread, *nbytes); 332 if (err) 333 return err; 334 335 if (data != buf) { 336 if (nread > *nbytes) /* Sanity check for bogus server. */ { 337 vm_deallocate(mach_task_self(), (vm_address_t) data, nread); 338 return EGRATUITOUS; 339 } 340 341 memcpy(buf, data, nread); 342 vm_deallocate(mach_task_self(), (vm_address_t)data, nread); 343 } 344 345 *nbytes = nread; 346 347 return 0; 348} 349 350/* Write `nbytes' bytes from `buf' to `reg' in device's configuration space */ 351static int 352pciclient_cfg_write(mach_port_t device_port, int reg, char *buf, 353 size_t * nbytes) 354{ 355 int err; 356 size_t nwrote; 357 358 err = __pci_conf_write(device_port, reg, buf, *nbytes, &nwrote); 359 360 if (!err) 361 *nbytes = nwrote; 362 363 return err; 364} 365 366/* 367 * Read up to `size' bytes from `dev' configuration space to `data' starting 368 * at `offset'. Write the amount on read bytes in `bytes_read'. 369 */ 370static int 371pci_device_hurd_read(struct pci_device *dev, void *data, 372 pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_read) 373{ 374 int err; 375 struct pci_device_private *d; 376 377 *bytes_read = 0; 378 d = (struct pci_device_private *)dev; 379 while (size > 0) { 380 size_t toread = 1 << (ffs(0x4 + (offset & 0x03)) - 1); 381 if (toread > size) 382 toread = size; 383 384 err = pciclient_cfg_read(d->device_port, offset, (char*)data, 385 &toread); 386 if (err) 387 return err; 388 389 offset += toread; 390 data = (char*)data + toread; 391 size -= toread; 392 *bytes_read += toread; 393 } 394 return 0; 395} 396 397/* 398 * Write up to `size' bytes from `data' to `dev' configuration space starting 399 * at `offset'. Write the amount on written bytes in `bytes_written'. 400 */ 401static int 402pci_device_hurd_write(struct pci_device *dev, const void *data, 403 pciaddr_t offset, pciaddr_t size, pciaddr_t *bytes_written) 404{ 405 int err; 406 struct pci_device_private *d; 407 408 *bytes_written = 0; 409 d = (struct pci_device_private *)dev; 410 while (size > 0) { 411 size_t towrite = 4; 412 if (towrite > size) 413 towrite = size; 414 if (towrite > 4 - (offset & 0x3)) 415 towrite = 4 - (offset & 0x3); 416 417 err = pciclient_cfg_write(d->device_port, offset, (char*)data, 418 &towrite); 419 if (err) 420 return err; 421 422 offset += towrite; 423 data = (const char*)data + towrite; 424 size -= towrite; 425 *bytes_written += towrite; 426 } 427 return 0; 428} 429 430/* 431 * Copy the device's firmware in `buffer' 432 */ 433static int 434pci_device_hurd_read_rom(struct pci_device * dev, void * buffer) 435{ 436 ssize_t rd; 437 int romfd; 438 char server[NAME_MAX]; 439 440 snprintf(server, NAME_MAX, "%s/%04x/%02x/%02x/%01u/%s", _SERVERS_BUS_PCI, 441 dev->domain, dev->bus, dev->dev, dev->func, FILE_ROM_NAME); 442 443 romfd = open(server, O_RDONLY | O_CLOEXEC); 444 if (romfd == -1) 445 return errno; 446 447 rd = read(romfd, buffer, dev->rom_size); 448 if (rd != dev->rom_size) { 449 close(romfd); 450 return errno; 451 } 452 453 close(romfd); 454 455 return 0; 456} 457 458/* 459 * Each device has its own server where send RPC's to. 460 * 461 * Deallocate the port before destroying the device. 462 */ 463static void 464pci_device_hurd_destroy_device(struct pci_device *dev) 465{ 466 struct pci_device_private *d = (struct pci_device_private*) dev; 467 468 mach_port_deallocate (mach_task_self (), d->device_port); 469} 470 471static struct dirent64 * 472simple_readdir(mach_port_t port, uint32_t *first_entry) 473{ 474 char *data; 475 int nentries = 0; 476 mach_msg_type_number_t size; 477 478 dir_readdir (port, &data, &size, *first_entry, 1, 0, &nentries); 479 480 if (nentries == 0) { 481 return NULL; 482 } 483 484 *first_entry = *first_entry + 1; 485 return (struct dirent64 *)data; 486} 487 488/* Walk through the FS tree to see what is allowed for us */ 489static int 490enum_devices(mach_port_t pci_port, const char *parent, int domain, 491 int bus, int dev, int func, tree_level lev) 492{ 493 int err, ret; 494 struct dirent64 *entry = NULL; 495 char path[NAME_MAX]; 496 char server[NAME_MAX]; 497 uint32_t reg, count = 0; 498 size_t toread; 499 mach_port_t cwd_port, device_port; 500 struct pci_device_private *d, *devices; 501 502 if (lev > LEVEL_FUNC + 1) { 503 return 0; 504 } 505 cwd_port = file_name_lookup_under (pci_port, parent, 506 O_DIRECTORY | O_RDONLY | O_EXEC, 0); 507 if (cwd_port == MACH_PORT_NULL) { 508 return 0; 509 } 510 511 while ((entry = simple_readdir(cwd_port, &count)) != NULL) { 512 snprintf(path, NAME_MAX, "%s/%s", parent, entry->d_name); 513 if (entry->d_type == DT_DIR) { 514 if (!strncmp(entry->d_name, ".", NAME_MAX) 515 || !strncmp(entry->d_name, "..", NAME_MAX)) 516 continue; 517 518 errno = 0; 519 ret = strtol(entry->d_name, 0, 16); 520 if (errno) { 521 return errno; 522 } 523 524 /* 525 * We found a valid directory. 526 * Update the address and switch to the next level. 527 */ 528 switch (lev) { 529 case LEVEL_DOMAIN: 530 domain = ret; 531 break; 532 case LEVEL_BUS: 533 bus = ret; 534 break; 535 case LEVEL_DEV: 536 dev = ret; 537 break; 538 case LEVEL_FUNC: 539 func = ret; 540 break; 541 default: 542 return 0; 543 } 544 545 err = enum_devices(pci_port, path, domain, bus, dev, func, lev+1); 546 if (err && err != EPERM && err != EACCES) { 547 return 0; 548 } 549 } else { 550 if (strncmp(entry->d_name, FILE_CONFIG_NAME, NAME_MAX)) 551 /* We are looking for the config file */ 552 continue; 553 554 /* We found an available virtual device, add it to our list */ 555 snprintf(server, NAME_MAX, "./%04x/%02x/%02x/%01u/%s", 556 domain, bus, dev, func, 557 entry->d_name); 558 device_port = file_name_lookup_under(pci_port, server, O_RDONLY, 0); 559 if (device_port == MACH_PORT_NULL) { 560 return 0; 561 } 562 563 toread = sizeof(reg); 564 err = pciclient_cfg_read(device_port, PCI_VENDOR_ID, (char*)®, 565 &toread); 566 if (err) { 567 mach_port_deallocate (mach_task_self (), device_port); 568 return err; 569 } 570 if (toread != sizeof(reg)) { 571 mach_port_deallocate (mach_task_self (), device_port); 572 return -1; 573 } 574 575 devices = realloc(pci_sys->devices, (pci_sys->num_devices + 1) 576 * sizeof(struct pci_device_private)); 577 if (!devices) { 578 mach_port_deallocate (mach_task_self (), device_port); 579 return ENOMEM; 580 } 581 582 d = devices + pci_sys->num_devices; 583 memset(d, 0, sizeof(struct pci_device_private)); 584 585 d->base.domain = domain; 586 d->base.bus = bus; 587 d->base.dev = dev; 588 d->base.func = func; 589 d->base.vendor_id = PCI_VENDOR(reg); 590 d->base.device_id = PCI_DEVICE(reg); 591 592 toread = sizeof(reg); 593 err = pciclient_cfg_read(device_port, PCI_CLASS, (char*)®, 594 &toread); 595 if (err) { 596 mach_port_deallocate (mach_task_self (), device_port); 597 return err; 598 } 599 if (toread != sizeof(reg)) { 600 mach_port_deallocate (mach_task_self (), device_port); 601 return -1; 602 } 603 604 d->base.device_class = reg >> 8; 605 d->base.revision = reg & 0xFF; 606 607 toread = sizeof(reg); 608 err = pciclient_cfg_read(device_port, PCI_SUB_VENDOR_ID, 609 (char*)®, &toread); 610 if (err) { 611 mach_port_deallocate (mach_task_self (), device_port); 612 return err; 613 } 614 if (toread != sizeof(reg)) { 615 mach_port_deallocate (mach_task_self (), device_port); 616 return -1; 617 } 618 619 d->base.subvendor_id = PCI_VENDOR(reg); 620 d->base.subdevice_id = PCI_DEVICE(reg); 621 622 d->device_port = device_port; 623 624 pci_sys->devices = devices; 625 pci_sys->num_devices++; 626 } 627 } 628 mach_port_deallocate (mach_task_self (), cwd_port); 629 630 return 0; 631} 632 633static const struct pci_system_methods hurd_pci_methods = { 634 .destroy = pci_system_hurd_destroy, 635 .destroy_device = pci_device_hurd_destroy_device, 636 .read_rom = pci_device_hurd_read_rom, 637 .probe = pci_device_hurd_probe, 638 .map_range = pci_device_hurd_map_range, 639 .unmap_range = pci_device_hurd_unmap_range, 640 .read = pci_device_hurd_read, 641 .write = pci_device_hurd_write, 642 .fill_capabilities = pci_fill_capabilities_generic, 643 .open_legacy_io = pci_device_x86_open_legacy_io, 644 .close_io = pci_device_x86_close_io, 645 .read32 = pci_device_x86_read32, 646 .read16 = pci_device_x86_read16, 647 .read8 = pci_device_x86_read8, 648 .write32 = pci_device_x86_write32, 649 .write16 = pci_device_x86_write16, 650 .write8 = pci_device_x86_write8, 651 .map_legacy = pci_device_hurd_map_legacy, 652 .unmap_legacy = pci_device_hurd_unmap_legacy, 653}; 654 655/* Get the name of the server using libpciaccess if any */ 656extern char *netfs_server_name; 657#pragma weak netfs_server_name 658 659_pci_hidden int 660pci_system_hurd_create(void) 661{ 662 int err; 663 struct pci_system_hurd *pci_sys_hurd; 664 mach_port_t device_master; 665 mach_port_t pci_port = MACH_PORT_NULL; 666 mach_port_t root = MACH_PORT_NULL; 667 668 if (&netfs_server_name && netfs_server_name 669 && !strcmp(netfs_server_name, "pci-arbiter")) { 670 /* We are a PCI arbiter, try the x86 way */ 671 err = pci_system_x86_create(); 672 if (!err) 673 return 0; 674 } 675 676 /* 677 * From this point on, we are either a client or a nested arbiter. 678 * Both will connect to a master arbiter. 679 */ 680 681 pci_sys_hurd = calloc(1, sizeof(struct pci_system_hurd)); 682 if (pci_sys_hurd == NULL) { 683 x86_disable_io(); 684 return ENOMEM; 685 } 686 pci_sys = &pci_sys_hurd->system; 687 688 pci_sys->methods = &hurd_pci_methods; 689 690 pci_sys->num_devices = 0; 691 692 err = get_privileged_ports (NULL, &device_master); 693 694 if(!err && device_master != MACH_PORT_NULL) { 695 err = device_open (device_master, D_READ, "pci", &pci_port); 696 mach_port_deallocate (mach_task_self (), device_master); 697 } 698 699 if (!err && pci_port != MACH_PORT_NULL) { 700 root = file_name_lookup_under (pci_port, ".", O_DIRECTORY | O_RDONLY | O_EXEC, 0); 701 device_close (pci_port); 702 mach_port_deallocate (mach_task_self (), pci_port); 703 } 704 705 if (root == MACH_PORT_NULL) { 706 root = file_name_lookup (_SERVERS_BUS_PCI, O_RDONLY, 0); 707 } 708 709 if (root == MACH_PORT_NULL) { 710 pci_system_cleanup(); 711 return errno; 712 } 713 714 pci_sys_hurd->root = root; 715 err = enum_devices (root, ".", -1, -1, -1, -1, LEVEL_DOMAIN); 716 if (err) { 717 pci_system_cleanup(); 718 return err; 719 } 720 721 return 0; 722} 723