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