xref: /netbsd-src/sys/arch/xen/xen/pciback.c (revision 4c8adaa46e22884122bcbf828a67069ea70c8683)
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
pciback_read_byte(pci_chipset_tag_t pc,pcitag_t pa,int reg)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
pciback_read_word(pci_chipset_tag_t pc,pcitag_t pa,int reg)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
pciback_write_byte(pci_chipset_tag_t pc,pcitag_t pa,int reg,uint8_t val)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
pciback_write_word(pci_chipset_tag_t pc,pcitag_t pa,int reg,uint16_t val)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
pciback_pci_match(device_t parent,cfdata_t match,void * aux)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
pciback_pci_attach(device_t parent,device_t self,void * aux)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
pciback_kernfs_read(void * v)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*
pciback_pci_lookup(u_int bus,u_int dev,u_int func)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
pciback_pci_init(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
pciback_parse_pci(const char * str,u_int * busp,u_int * devp,u_int * funcp)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
pciback_xenbus_create(struct xenbus_device * xbusd)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
pciback_xenbus_destroy(void * arg)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
pciback_xenbus_frontend_changed(void * arg,XenbusState new_state)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
pbxif_lookup(domid_t dom)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
pciback_xenbus_export_device(struct pb_xenbus_instance * pbxi,char * val)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
pciback_xenbus_export_roots(struct pb_xenbus_instance * pbxi)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
pciback_xenbus_evthandler(void * arg)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