Home | History | Annotate | Line # | Download | only in xen
      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