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