1 /* $NetBSD: pciback.c,v 1.23 2022/09/01 15:33:23 bouyer Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Manuel Bouyer. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: pciback.c,v 1.23 2022/09/01 15:33:23 bouyer Exp $"); 30 31 #include <sys/types.h> 32 #include <sys/param.h> 33 #include <sys/systm.h> 34 #include <sys/errno.h> 35 #include <sys/kernel.h> 36 #include <sys/bus.h> 37 #include <sys/queue.h> 38 39 #include <uvm/uvm_extern.h> 40 41 #include <machine/bus_private.h> 42 43 #include <dev/isa/isareg.h> 44 45 #include <xen/hypervisor.h> 46 #include <xen/evtchn.h> 47 #include <xen/granttables.h> 48 #include <xen/xen_shm.h> 49 #include <xen/include/public/io/pciif.h> 50 #include <xen/xenbus.h> 51 52 #include <sys/stat.h> 53 #include <sys/dirent.h> 54 #include <miscfs/specfs/specdev.h> 55 #include <miscfs/kernfs/kernfs.h> 56 #include <xen/kernfs_machdep.h> 57 58 #include "locators.h" 59 60 #include <dev/pci/pcivar.h> 61 #include <machine/i82093var.h> 62 63 struct pciback_pci_softc; 64 struct pb_xenbus_instance; 65 /* list of devices we handle */ 66 struct pciback_pci_dev { 67 SLIST_ENTRY(pciback_pci_dev) pb_devlist_next; /* global list of pbd */ 68 SLIST_ENTRY(pciback_pci_dev) pb_guest_next; /* per-guest list of pbd */ 69 u_int pb_bus; /* our location */ 70 u_int pb_device; 71 u_int pb_function; 72 pci_chipset_tag_t pb_pc; 73 pcitag_t pb_tag; 74 struct pciback_pci_softc *pb_pci_softc; 75 struct pb_xenbus_instance *pbx_instance; 76 }; 77 78 /* list of devices we want to match */ 79 static SLIST_HEAD(pciback_pci_devlist, pciback_pci_dev) 80 pciback_pci_devlist_head = 81 SLIST_HEAD_INITIALIZER(pciback_pci_devlist_head); 82 83 /* PCI-related functions and definitions */ 84 85 #define PCI_NBARS ((PCI_MAPREG_END - PCI_MAPREG_START) / 4) 86 87 struct pciback_pci_softc { 88 device_t sc_dev; 89 void *sc_ih; /* our interrupt; */ 90 struct pciback_pci_dev *sc_pb; /* our location */ 91 struct pci_bar { 92 bus_space_tag_t b_t; 93 bus_space_handle_t b_h; 94 bus_addr_t b_addr; 95 bus_size_t b_size; 96 int b_type; 97 int b_valid; 98 } sc_bars[PCI_NBARS]; 99 pci_intr_handle_t sc_intrhandle; 100 int sc_irq; 101 pcireg_t sc_id; 102 pcireg_t sc_subid; 103 char sc_kernfsname[16]; 104 }; 105 106 int pciback_pci_match(device_t, cfdata_t, void *); 107 void pciback_pci_attach(device_t, device_t, void *); 108 static struct pciback_pci_dev* pciback_pci_lookup(u_int, u_int, u_int); 109 static void pciback_pci_init(void); 110 111 static int pciback_parse_pci(const char *, u_int *, u_int *, u_int *); 112 113 /* kernfs-related functions and definitions */ 114 115 static kernfs_parentdir_t *pciback_kern_pkt; 116 static int pciback_kernfs_read(void *); 117 118 #define DIR_MODE (S_IRUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH) 119 #define FILE_MODE (S_IRUSR) 120 static const struct kernfs_fileop pciback_dev_fileops[] = { 121 { .kf_fileop = KERNFS_FILEOP_READ, .kf_vop = pciback_kernfs_read }, 122 }; 123 124 /* xenbus-related functions and definitions */ 125 126 static int pciback_xenbus_create(struct xenbus_device *); 127 static int pciback_xenbus_destroy(void *); 128 static void pciback_xenbus_frontend_changed(void *, XenbusState); 129 static bool pbxif_lookup(domid_t); 130 static void pciback_xenbus_export_device(struct pb_xenbus_instance *, char *); 131 static void pciback_xenbus_export_roots(struct pb_xenbus_instance *); 132 133 static int pciback_xenbus_evthandler(void *); 134 135 /* emulate byte and word access to PCI config space */ 136 static inline u_int8_t 137 pciback_read_byte(pci_chipset_tag_t pc, pcitag_t pa, int reg) 138 { 139 140 return (pci_conf_read(pc, pa, (reg & ~0x03)) >> 141 ((reg & 0x03) * 8) & 0xff); 142 } 143 144 static inline u_int16_t 145 pciback_read_word(pci_chipset_tag_t pc, pcitag_t pa, int reg) 146 { 147 return (pci_conf_read(pc, pa, (reg & ~0x03)) >> 148 ((reg & 0x03) * 8) & 0xffff); 149 } 150 151 static inline void 152 pciback_write_byte(pci_chipset_tag_t pc, pcitag_t pa, int reg, uint8_t val) 153 { 154 pcireg_t pcival; 155 156 pcival = pci_conf_read(pc, pa, (reg & ~0x03)); 157 pcival &= ~(0xff << ((reg & 0x03) * 8)); 158 pcival |= (val << ((reg & 0x03) * 8)); 159 pci_conf_write(pc, pa, (reg & ~0x03), pcival); 160 } 161 162 static inline void 163 pciback_write_word(pci_chipset_tag_t pc, pcitag_t pa, int reg, uint16_t val) 164 { 165 pcireg_t pcival; 166 167 pcival = pci_conf_read(pc, pa, (reg & ~0x03)); 168 pcival &= ~(0xffff << ((reg & 0x03) * 8)); 169 pcival |= (val << ((reg & 0x03) * 8)); 170 pci_conf_write(pc, pa, (reg & ~0x03), pcival); 171 } 172 173 174 175 CFATTACH_DECL_NEW(pciback, sizeof(struct pciback_pci_softc), 176 pciback_pci_match, pciback_pci_attach, NULL, NULL); 177 178 static int pciback_pci_inited = 0; 179 180 /* a xenbus PCI backend instance */ 181 struct pb_xenbus_instance { 182 SLIST_ENTRY(pb_xenbus_instance) pbx_next; /* list of backend instances*/ 183 struct xenbus_device *pbx_xbusd; 184 domid_t pbx_domid; 185 struct pciback_pci_devlist pbx_pb_pci_dev; /* list of exported PCI devices */ 186 /* communication with the domU */ 187 unsigned int pbx_evtchn; /* our even channel */ 188 struct intrhand *pbx_ih; 189 struct xen_pci_sharedinfo *pbx_sh_info; 190 struct xen_pci_op op; 191 grant_handle_t pbx_shinfo_handle; /* to unmap shared page */ 192 }; 193 194 static SLIST_HEAD(, pb_xenbus_instance) pb_xenbus_instances; 195 static kmutex_t pb_xenbus_lock; 196 197 static struct xenbus_backend_driver pci_backend_driver = { 198 .xbakd_create = pciback_xenbus_create, 199 .xbakd_type = "pci" 200 }; 201 202 int 203 pciback_pci_match(device_t parent, cfdata_t match, void *aux) 204 { 205 struct pci_attach_args *pa = aux; 206 if (pciback_pci_inited == 0) { 207 pciback_pci_init(); 208 pciback_pci_inited = 1; 209 } 210 if (pciback_pci_lookup(pa->pa_bus, pa->pa_device, pa->pa_function)) 211 return 500; /* we really want to take over anything else */ 212 return 0; 213 } 214 215 void 216 pciback_pci_attach(device_t parent, device_t self, void *aux) 217 { 218 struct pci_attach_args *pa = aux; 219 struct pciback_pci_softc *sc = device_private(self); 220 char devinfo[256]; 221 int i; 222 const char *intrstr; 223 kernfs_entry_t *dkt; 224 kfstype kfst; 225 pcireg_t reg; 226 char buf[PCI_INTRSTR_LEN]; 227 228 sc->sc_dev = self; 229 sc->sc_pb = pciback_pci_lookup(pa->pa_bus, pa->pa_device, pa->pa_function); 230 if (sc->sc_pb == NULL) 231 panic("pciback_pci_attach: pciback_lookup"); 232 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo)); 233 aprint_normal(": %s (rev. 0x%02x)\n", devinfo, 234 PCI_REVISION(pa->pa_class)); 235 sc->sc_pb->pb_pci_softc = sc; 236 sc->sc_pb->pb_pc = pa->pa_pc; 237 sc->sc_pb->pb_tag = pa->pa_tag; 238 239 sc->sc_id = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ID_REG); 240 sc->sc_subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 241 242 for (i = 0; i < PCI_NBARS;) { 243 sc->sc_bars[i].b_type = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 244 PCI_MAPREG_START + i * 4); 245 if (pci_mapreg_map(pa, PCI_MAPREG_START + i * 4, 246 sc->sc_bars[i].b_type, 0, 247 &sc->sc_bars[i].b_t, &sc->sc_bars[i].b_h, 248 &sc->sc_bars[i].b_addr, &sc->sc_bars[i].b_size) == 0) 249 sc->sc_bars[i].b_valid = 1; 250 if (sc->sc_bars[i].b_valid) { 251 aprint_verbose_dev(self, "%s: 0x%08jx - 0x%08jx\n", 252 (sc->sc_bars[i].b_type == PCI_MAPREG_TYPE_IO) ? 253 "I/O" : "mem", 254 (uintmax_t)sc->sc_bars[i].b_addr, 255 (uintmax_t)sc->sc_bars[i].b_size); 256 } 257 258 if (sc->sc_bars[i].b_type == 259 (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT)) 260 i += 2; 261 else 262 i += 1; 263 } 264 /* map the irq so interrupt routing is done */ 265 if (pci_intr_map(pa, &sc->sc_intrhandle) != 0) { 266 aprint_error_dev(self, "couldn't map interrupt\n"); 267 } else { 268 intrstr = pci_intr_string(pa->pa_pc, sc->sc_intrhandle, 269 buf, sizeof(buf)); 270 aprint_normal_dev(self, "interrupting at %s\n", intrstr); 271 } 272 unbind_pirq_from_evtch(APIC_IRQ_LEGACY_IRQ(sc->sc_intrhandle)); 273 sc->sc_irq = APIC_IRQ_LEGACY_IRQ(sc->sc_intrhandle); 274 /* XXX should be done elsewhere ? */ 275 reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_INTERRUPT_REG); 276 reg &= ~ (PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT); 277 reg |= (sc->sc_irq << PCI_INTERRUPT_LINE_SHIFT); 278 pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_INTERRUPT_REG, reg); 279 printf("irq line %d pin %d sc %p\n", 280 PCI_INTERRUPT_LINE(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_INTERRUPT_REG)), 281 PCI_INTERRUPT_PIN(pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_INTERRUPT_REG)), sc); 282 /* 283 * don't establish the interrupt, we're not interested in 284 * getting it here. 285 */ 286 /* publish the informations about this device to /kern/xen/pci */ 287 snprintf(sc->sc_kernfsname, sizeof(sc->sc_kernfsname), 288 "0000:%02x:%02x.%x", pa->pa_bus, pa->pa_device, pa->pa_function); 289 kfst = KERNFS_ALLOCTYPE(pciback_dev_fileops); 290 KERNFS_ALLOCENTRY(dkt, KM_SLEEP); 291 KERNFS_INITENTRY(dkt, DT_REG, sc->sc_kernfsname, sc, 292 kfst, VREG, FILE_MODE); 293 kernfs_addentry(pciback_kern_pkt, dkt); 294 } 295 296 static int 297 pciback_kernfs_read(void *v) 298 { 299 struct vop_read_args /* { 300 struct vnode *a_vp; 301 struct uio *a_uio; 302 int a_ioflag; 303 struct ucred *a_cred; 304 } */ *ap = v; 305 struct kernfs_node *kfs = VTOKERN(ap->a_vp); 306 struct uio *uio = ap->a_uio; 307 struct pciback_pci_softc *sc = kfs->kfs_kt->kt_data; 308 #define PCIBACK_KERNFS_SIZE 512 309 static char buf[PCIBACK_KERNFS_SIZE]; 310 off_t off; 311 off_t len; 312 int error, i; 313 314 off = uio->uio_offset; 315 len = 0; 316 len += snprintf(&buf[len], sizeof(buf) - len, 317 "vendor: 0x%04x\nproduct: 0x%04x\n", 318 PCI_VENDOR(sc->sc_id), PCI_PRODUCT(sc->sc_id)); 319 if (len > sizeof(buf)) 320 return ENOSPC; 321 len += snprintf(&buf[len], sizeof(buf) - len, 322 "subsys_vendor: 0x%04x\nsubsys_product: 0x%04x\n", 323 PCI_VENDOR(sc->sc_subid), PCI_PRODUCT(sc->sc_subid)); 324 if (len > sizeof(buf)) 325 return ENOSPC; 326 for(i = 0; i < PCI_NBARS; i++) { 327 if (sc->sc_bars[i].b_valid) { 328 len += snprintf(&buf[len], sizeof(buf) - len, 329 "%s: 0x%08jx - 0x%08jx\n", 330 (sc->sc_bars[i].b_type == PCI_MAPREG_TYPE_IO) ? 331 "I/O" : "mem", 332 (uintmax_t)sc->sc_bars[i].b_addr, 333 (uintmax_t)(sc->sc_bars[i].b_addr + sc->sc_bars[i].b_size)); 334 if (len > sizeof(buf)) 335 return ENOSPC; 336 } 337 } 338 if (len > sizeof(buf)) 339 return ENOSPC; 340 len += snprintf(&buf[len], sizeof(buf) - len, 341 "irq: %d\n", sc->sc_irq); 342 if (off >= len) { 343 error = uiomove(buf, 0, uio); 344 } else { 345 error = uiomove(&buf[off], len - off, uio); 346 } 347 return error; 348 } 349 350 static struct pciback_pci_dev* 351 pciback_pci_lookup(u_int bus, u_int dev, u_int func) 352 { 353 struct pciback_pci_dev *pbd; 354 /* Safe without lock, only written during init */ 355 SLIST_FOREACH(pbd, &pciback_pci_devlist_head, pb_devlist_next) { 356 if (pbd->pb_bus == bus && 357 pbd->pb_device == dev && 358 pbd->pb_function == func) 359 return pbd; 360 } 361 return NULL; 362 } 363 364 static void 365 pciback_pci_init(void) 366 { 367 union xen_cmdline_parseinfo xi; 368 char *pcidevs, *c; 369 u_int bus, dev, func; 370 struct pciback_pci_dev *pb; 371 kernfs_entry_t *dkt; 372 373 memset(&xi, 0, sizeof(xi)); 374 xen_parse_cmdline(XEN_PARSE_PCIBACK, &xi); 375 if (strlen(xi.xcp_pcidevs) == 0) 376 return; 377 pcidevs = xi.xcp_pcidevs; 378 for (pcidevs = xi.xcp_pcidevs; *pcidevs != '\0';) { 379 if (*pcidevs != '(') 380 goto error; 381 pcidevs++; 382 /* parse location */ 383 c = strchr(pcidevs, ')'); 384 if (c == NULL) 385 goto error; 386 *c = '\0'; 387 if (pciback_parse_pci(pcidevs, &bus, &dev, &func) == 0) { 388 pb = kmem_zalloc(sizeof(*pb), KM_SLEEP); 389 pb->pb_bus = bus; 390 pb->pb_device = dev; 391 pb->pb_function = func; 392 aprint_verbose("pciback_pci_init: hide claim device " 393 "%x:%x:%x\n", bus, dev, func); 394 SLIST_INSERT_HEAD(&pciback_pci_devlist_head, pb, 395 pb_devlist_next); 396 } 397 pcidevs = c + 1; 398 } 399 400 SLIST_INIT(&pb_xenbus_instances); 401 mutex_init(&pb_xenbus_lock, MUTEX_DEFAULT, IPL_NONE); 402 403 xenbus_backend_register(&pci_backend_driver); 404 405 KERNFS_ALLOCENTRY(dkt, KM_SLEEP); 406 KERNFS_INITENTRY(dkt, DT_DIR, "pci", NULL, KFSsubdir, VDIR, DIR_MODE); 407 kernfs_addentry(kernxen_pkt, dkt); 408 pciback_kern_pkt = KERNFS_ENTOPARENTDIR(dkt); 409 return; 410 error: 411 aprint_error("pciback_pci_init: syntax error at %s\n", pcidevs); 412 return; 413 } 414 415 static int 416 pciback_parse_pci(const char *str, u_int *busp, u_int *devp, u_int *funcp) 417 { 418 char *c; 419 420 /* parse location */ 421 c = strchr(str, ':'); 422 if (c == NULL) 423 goto error; 424 if (strncmp("0000", str, 4) == 0) { 425 /* must be domain number, get next */ 426 str = c + 1; 427 } 428 *busp = strtoul(str, &c, 16); 429 if (*c != ':') 430 goto error; 431 str = c + 1; 432 *devp = strtoul(str, &c, 16); 433 if (*c != '.') 434 goto error; 435 str = c + 1; 436 *funcp = strtoul(str, &c, 16); 437 if (*c != '\0') 438 goto error; 439 return 0; 440 error: 441 aprint_error("pciback_pci_init: syntax error at char %c\n", *c); 442 return EINVAL; 443 } 444 445 static int 446 pciback_xenbus_create(struct xenbus_device *xbusd) 447 { 448 struct pb_xenbus_instance *pbxi; 449 long domid; 450 char path[10]; 451 int i, err; 452 u_long num_devs; 453 454 if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path, 455 "frontend-id", &domid, 10)) != 0) { 456 aprint_error("pciback: can' read %s/frontend-id: %d\n", 457 xbusd->xbusd_path, err); 458 return err; 459 } 460 461 if (pbxif_lookup(domid)) { 462 return EEXIST; 463 } 464 pbxi = kmem_zalloc(sizeof(*pbxi), KM_SLEEP); 465 pbxi->pbx_domid = domid; 466 467 xbusd->xbusd_u.b.b_cookie = pbxi; 468 xbusd->xbusd_u.b.b_detach = pciback_xenbus_destroy; 469 pbxi->pbx_xbusd = xbusd; 470 471 SLIST_INIT(&pbxi->pbx_pb_pci_dev); 472 473 mutex_enter(&pb_xenbus_lock); 474 SLIST_INSERT_HEAD(&pb_xenbus_instances, pbxi, pbx_next); 475 mutex_exit(&pb_xenbus_lock); 476 477 xbusd->xbusd_otherend_changed = pciback_xenbus_frontend_changed; 478 479 err = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait); 480 if (err) { 481 printf("failed to switch state on %s: %d\n", 482 xbusd->xbusd_path, err); 483 goto fail; 484 } 485 if ((err = xenbus_read_ul(NULL, xbusd->xbusd_path, "num_devs", 486 &num_devs, 10)) != 0) { 487 aprint_error("pciback: can' read %s/num_devs %d\n", 488 xbusd->xbusd_path, err); 489 goto fail; 490 } 491 for (i = 0; i < num_devs; i++) { 492 char dev[64]; 493 snprintf(path, sizeof(path), "dev-%d", i); 494 if ((err = xenbus_read(NULL, xbusd->xbusd_path, path, 495 dev, sizeof(dev))) != 0) { 496 aprint_error("pciback: can' read %s/%s: %d\n", 497 xbusd->xbusd_path, path, err); 498 goto fail; 499 } 500 pciback_xenbus_export_device(pbxi, dev); 501 } 502 pciback_xenbus_export_roots(pbxi); 503 if ((err = xenbus_switch_state(xbusd, NULL, XenbusStateInitialised))) { 504 printf("failed to switch state on %s: %d\n", 505 xbusd->xbusd_path, err); 506 goto fail; 507 } 508 509 return 0; 510 fail: 511 kmem_free(pbxi, sizeof(*pbxi)); 512 return err; 513 } 514 515 static int 516 pciback_xenbus_destroy(void *arg) 517 { 518 struct pb_xenbus_instance *pbxi = arg; 519 struct pciback_pci_dev *pbd; 520 521 hypervisor_mask_event(pbxi->pbx_evtchn); 522 xen_intr_disestablish(pbxi->pbx_ih); 523 mutex_enter(&pb_xenbus_lock); 524 SLIST_REMOVE(&pb_xenbus_instances, 525 pbxi, pb_xenbus_instance, pbx_next); 526 mutex_exit(&pb_xenbus_lock); 527 528 529 if (pbxi->pbx_sh_info) { 530 xen_shm_unmap((vaddr_t)pbxi->pbx_sh_info, 1, 531 &pbxi->pbx_shinfo_handle); 532 uvm_km_free(kernel_map, (vaddr_t)pbxi->pbx_sh_info, 533 PAGE_SIZE, UVM_KMF_VAONLY); 534 } 535 SLIST_FOREACH(pbd, &pbxi->pbx_pb_pci_dev, pb_guest_next) { 536 pbd->pbx_instance = NULL; 537 } 538 kmem_free(pbxi, sizeof(*pbxi)); 539 return 0; 540 } 541 542 static void 543 pciback_xenbus_frontend_changed(void *arg, XenbusState new_state) 544 { 545 struct pb_xenbus_instance *pbxi = arg; 546 struct xenbus_device *xbusd = pbxi->pbx_xbusd; 547 int err; 548 evtchn_op_t evop; 549 u_long shared_ref; 550 grant_ref_t gshared_ref; 551 u_long revtchn; 552 553 /* do it only once */ 554 if (xenbus_read_driver_state(xbusd->xbusd_path) != 555 XenbusStateInitialised) 556 return; 557 558 switch(new_state) { 559 case XenbusStateInitialising: 560 case XenbusStateConnected: 561 break; 562 case XenbusStateInitialised: 563 /* read comunication informations */ 564 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 565 "pci-op-ref", &shared_ref, 10); 566 if (err) { 567 xenbus_dev_fatal(xbusd, err, "reading %s/pci-op-ref", 568 xbusd->xbusd_otherend); 569 break; 570 } 571 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 572 "event-channel", &revtchn, 10); 573 if (err) { 574 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", 575 xbusd->xbusd_otherend); 576 break; 577 } 578 /* allocate VA space and map rings */ 579 pbxi->pbx_sh_info = (void *)uvm_km_alloc(kernel_map, 580 PAGE_SIZE, 0, UVM_KMF_VAONLY); 581 if (pbxi->pbx_sh_info == 0) { 582 xenbus_dev_fatal(xbusd, ENOMEM, 583 "can't get VA for shared infos", 584 xbusd->xbusd_otherend); 585 break; 586 } 587 gshared_ref = shared_ref; 588 if (xen_shm_map(1, pbxi->pbx_domid, &gshared_ref, 589 (vaddr_t)pbxi->pbx_sh_info, 590 &pbxi->pbx_shinfo_handle, 0) != 0) { 591 aprint_error("pciback: can't map shared grant ref\n"); 592 goto err2; 593 } 594 595 evop.cmd = EVTCHNOP_bind_interdomain; 596 evop.u.bind_interdomain.remote_dom = pbxi->pbx_domid; 597 evop.u.bind_interdomain.remote_port = revtchn; 598 err = HYPERVISOR_event_channel_op(&evop); 599 if (err) { 600 printf("pciback: can't get event channel: %d\n", err); 601 goto err1; 602 } 603 pbxi->pbx_evtchn = evop.u.bind_interdomain.local_port; 604 x86_sfence(); 605 xenbus_switch_state(xbusd, NULL, XenbusStateConnected); 606 x86_sfence(); 607 pbxi->pbx_ih = xen_intr_establish_xname(-1, &xen_pic, pbxi->pbx_evtchn, 608 IST_LEVEL, IPL_BIO, pciback_xenbus_evthandler, pbxi, true, "pciback"); 609 KASSERT(pbxi->pbx_ih != NULL); 610 hypervisor_unmask_event(pbxi->pbx_evtchn); 611 hypervisor_notify_via_evtchn(pbxi->pbx_evtchn); 612 break; 613 614 case XenbusStateClosing: 615 xenbus_switch_state(xbusd, NULL, XenbusStateClosing); 616 break; 617 618 case XenbusStateClosed: 619 /* otherend_changed() should handle it for us */ 620 panic("pciback_xenbus_frontend_changed: closed\n"); 621 case XenbusStateUnknown: 622 case XenbusStateInitWait: 623 default: 624 aprint_error("pciback: invalid frontend state %d\n", 625 new_state); 626 break; 627 } 628 return; 629 err1: 630 xen_shm_unmap((vaddr_t)pbxi->pbx_sh_info, 1, &pbxi->pbx_shinfo_handle); 631 err2: 632 uvm_km_free(kernel_map, (vaddr_t)pbxi->pbx_sh_info, 633 PAGE_SIZE, UVM_KMF_VAONLY); 634 } 635 636 /* lookup a pbxi based on domain id and interface handle */ 637 static bool 638 pbxif_lookup(domid_t dom) 639 { 640 struct pb_xenbus_instance *pbxi; 641 bool found = false; 642 643 mutex_enter(&pb_xenbus_lock); 644 SLIST_FOREACH(pbxi, &pb_xenbus_instances, pbx_next) { 645 if (pbxi->pbx_domid == dom) { 646 found = true; 647 break; 648 } 649 } 650 mutex_exit(&pb_xenbus_lock); 651 652 return found; 653 } 654 655 static void 656 pciback_xenbus_export_device(struct pb_xenbus_instance *pbxi, char *val) 657 { 658 u_int bus, dev, func; 659 struct pciback_pci_dev *pbd; 660 if (pciback_parse_pci(val, &bus, &dev, &func)) { 661 aprint_error("pciback: can't parse %s\n", val); 662 return; 663 } 664 pbd = pciback_pci_lookup(bus, dev, func); 665 if (pbd == NULL) { 666 aprint_error("pciback: can't locate 0x%02x:0x%02x.0x%02x\n", 667 bus, dev, func); 668 return; 669 } 670 if (pbd->pb_pci_softc == NULL) { 671 aprint_error("pciback: 0x%02x:0x%02x.0x%02x not detected\n", 672 bus, dev, func); 673 return; 674 } 675 pbd->pbx_instance = pbxi; 676 SLIST_INSERT_HEAD(&pbxi->pbx_pb_pci_dev, pbd, pb_guest_next); 677 return; 678 } 679 680 static void 681 pciback_xenbus_export_roots(struct pb_xenbus_instance *pbxi) 682 { 683 char bus[256]; 684 char root[10]; 685 struct pciback_pci_dev *pbd; 686 int num_roots = 0; 687 int err; 688 689 memset(bus, 0, sizeof(bus)); 690 691 SLIST_FOREACH(pbd, &pbxi->pbx_pb_pci_dev, pb_guest_next) { 692 if (bus[pbd->pb_bus] == 0) { 693 /* not published yet */ 694 snprintf(root, sizeof(root), "root-%d", num_roots); 695 err = xenbus_printf(NULL, 696 pbxi->pbx_xbusd->xbusd_path, 697 root, "0000:%02x", pbd->pb_bus); 698 if (err) { 699 aprint_error("pciback: can't write to %s/%s: " 700 "%d\n", pbxi->pbx_xbusd->xbusd_path, root, 701 err); 702 } 703 num_roots++; 704 bus[pbd->pb_bus]++; 705 } 706 } 707 err = xenbus_printf(NULL, pbxi->pbx_xbusd->xbusd_path, "root_num", 708 "%d", num_roots); 709 if (err) { 710 aprint_error("pciback: can't write to %s/root_num: " 711 "%d\n", pbxi->pbx_xbusd->xbusd_path, err); 712 } 713 } 714 715 static int 716 pciback_xenbus_evthandler(void * arg) 717 { 718 struct pb_xenbus_instance *pbxi = arg; 719 struct pciback_pci_dev *pbd; 720 struct xen_pci_op *op = &pbxi->op; 721 u_int bus, dev, func; 722 723 hypervisor_clear_event(pbxi->pbx_evtchn); 724 if (xen_atomic_test_bit(&pbxi->pbx_sh_info->flags, 725 _XEN_PCIF_active) == 0) 726 return 0; 727 728 memcpy(op, &pbxi->pbx_sh_info->op, sizeof (struct xen_pci_op)); 729 __insn_barrier(); 730 if (op->domain != 0) { 731 aprint_error("pciback: domain %d != 0", op->domain); 732 op->err = XEN_PCI_ERR_dev_not_found; 733 goto end; 734 } 735 bus = op->bus; 736 dev = (op->devfn >> 3) & 0xff; 737 func = (op->devfn) & 0x7; 738 SLIST_FOREACH(pbd, &pbxi->pbx_pb_pci_dev, pb_guest_next) { 739 if (pbd->pb_bus == bus && 740 pbd->pb_device == dev && 741 pbd->pb_function == func) 742 break; 743 } 744 if (pbd == NULL) { 745 aprint_debug("pciback: %02x:%02x.%x not found\n", 746 bus, dev, func); 747 op->err = XEN_PCI_ERR_dev_not_found; 748 goto end; 749 } 750 switch(op->cmd) { 751 case XEN_PCI_OP_conf_read: 752 op->err = XEN_PCI_ERR_success; 753 switch (op->size) { 754 case 1: 755 op->value = pciback_read_byte(pbd->pb_pc, pbd->pb_tag, 756 op->offset); 757 break; 758 case 2: 759 op->value = pciback_read_word(pbd->pb_pc, pbd->pb_tag, 760 op->offset); 761 break; 762 case 4: 763 op->value = pci_conf_read(pbd->pb_pc, pbd->pb_tag, 764 op->offset); 765 break; 766 default: 767 aprint_error("pciback: bad size %d\n", op->size); 768 break; 769 } 770 break; 771 case XEN_PCI_OP_conf_write: 772 op->err = XEN_PCI_ERR_success; 773 switch(op->size) { 774 case 1: 775 pciback_write_byte(pbd->pb_pc, pbd->pb_tag, 776 op->offset, op->value); 777 break; 778 case 2: 779 pciback_write_word(pbd->pb_pc, pbd->pb_tag, 780 op->offset, op->value); 781 break; 782 case 4: 783 pci_conf_write(pbd->pb_pc, pbd->pb_tag, 784 op->offset, op->value); 785 break; 786 default: 787 aprint_error("pciback: bad size %d\n", op->size); 788 op->err = XEN_PCI_ERR_invalid_offset; 789 break; 790 } 791 break; 792 default: 793 aprint_error("pciback: unknown cmd %d\n", op->cmd); 794 op->err = XEN_PCI_ERR_not_implemented; 795 } 796 pbxi->pbx_sh_info->op.value = op->value; 797 pbxi->pbx_sh_info->op.err = op->err; 798 end: 799 xen_atomic_clear_bit(&pbxi->pbx_sh_info->flags, _XEN_PCIF_active); 800 hypervisor_notify_via_evtchn(pbxi->pbx_evtchn); 801 return 1; 802 } 803