]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bhyve/pci_passthru.c
bhyve: set EV_CLEAR for EVFILT_VNODE mevents
[FreeBSD/FreeBSD.git] / usr.sbin / bhyve / pci_passthru.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2011 NetApp, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $FreeBSD$
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include <sys/param.h>
35 #ifndef WITHOUT_CAPSICUM
36 #include <sys/capsicum.h>
37 #endif
38 #include <sys/types.h>
39 #include <sys/mman.h>
40 #include <sys/pciio.h>
41 #include <sys/ioctl.h>
42
43 #include <dev/io/iodev.h>
44 #include <dev/pci/pcireg.h>
45
46 #include <vm/vm.h>
47
48 #include <machine/iodev.h>
49 #include <machine/vm.h>
50
51 #ifndef WITHOUT_CAPSICUM
52 #include <capsicum_helpers.h>
53 #endif
54 #include <stdio.h>
55 #include <stdlib.h>
56 #include <string.h>
57 #include <err.h>
58 #include <errno.h>
59 #include <fcntl.h>
60 #include <sysexits.h>
61 #include <unistd.h>
62
63 #include <machine/vmm.h>
64 #include <vmmapi.h>
65
66 #include "config.h"
67 #include "debug.h"
68 #include "pci_emul.h"
69 #include "mem.h"
70
71 #ifndef _PATH_DEVPCI
72 #define _PATH_DEVPCI    "/dev/pci"
73 #endif
74
75 #define LEGACY_SUPPORT  1
76
77 #define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1)
78 #define MSIX_CAPLEN 12
79
80 static int pcifd = -1;
81
82 struct passthru_softc {
83         struct pci_devinst *psc_pi;
84         struct pcibar psc_bar[PCI_BARMAX + 1];
85         struct {
86                 int             capoff;
87                 int             msgctrl;
88                 int             emulated;
89         } psc_msi;
90         struct {
91                 int             capoff;
92         } psc_msix;
93         struct pcisel psc_sel;
94 };
95
96 static int
97 msi_caplen(int msgctrl)
98 {
99         int len;
100         
101         len = 10;               /* minimum length of msi capability */
102
103         if (msgctrl & PCIM_MSICTRL_64BIT)
104                 len += 4;
105
106 #if 0
107         /*
108          * Ignore the 'mask' and 'pending' bits in the MSI capability.
109          * We'll let the guest manipulate them directly.
110          */
111         if (msgctrl & PCIM_MSICTRL_VECTOR)
112                 len += 10;
113 #endif
114
115         return (len);
116 }
117
118 static uint32_t
119 read_config(const struct pcisel *sel, long reg, int width)
120 {
121         struct pci_io pi;
122
123         bzero(&pi, sizeof(pi));
124         pi.pi_sel = *sel;
125         pi.pi_reg = reg;
126         pi.pi_width = width;
127
128         if (ioctl(pcifd, PCIOCREAD, &pi) < 0)
129                 return (0);                             /* XXX */
130         else
131                 return (pi.pi_data);
132 }
133
134 static void
135 write_config(const struct pcisel *sel, long reg, int width, uint32_t data)
136 {
137         struct pci_io pi;
138
139         bzero(&pi, sizeof(pi));
140         pi.pi_sel = *sel;
141         pi.pi_reg = reg;
142         pi.pi_width = width;
143         pi.pi_data = data;
144
145         (void)ioctl(pcifd, PCIOCWRITE, &pi);            /* XXX */
146 }
147
148 #ifdef LEGACY_SUPPORT
149 static int
150 passthru_add_msicap(struct pci_devinst *pi, int msgnum, int nextptr)
151 {
152         int capoff, i;
153         struct msicap msicap;
154         u_char *capdata;
155
156         pci_populate_msicap(&msicap, msgnum, nextptr);
157
158         /*
159          * XXX
160          * Copy the msi capability structure in the last 16 bytes of the
161          * config space. This is wrong because it could shadow something
162          * useful to the device.
163          */
164         capoff = 256 - roundup(sizeof(msicap), 4);
165         capdata = (u_char *)&msicap;
166         for (i = 0; i < sizeof(msicap); i++)
167                 pci_set_cfgdata8(pi, capoff + i, capdata[i]);
168
169         return (capoff);
170 }
171 #endif  /* LEGACY_SUPPORT */
172
173 static int
174 cfginitmsi(struct passthru_softc *sc)
175 {
176         int i, ptr, capptr, cap, sts, caplen, table_size;
177         uint32_t u32;
178         struct pcisel sel;
179         struct pci_devinst *pi;
180         struct msixcap msixcap;
181         uint32_t *msixcap_ptr;
182
183         pi = sc->psc_pi;
184         sel = sc->psc_sel;
185
186         /*
187          * Parse the capabilities and cache the location of the MSI
188          * and MSI-X capabilities.
189          */
190         sts = read_config(&sel, PCIR_STATUS, 2);
191         if (sts & PCIM_STATUS_CAPPRESENT) {
192                 ptr = read_config(&sel, PCIR_CAP_PTR, 1);
193                 while (ptr != 0 && ptr != 0xff) {
194                         cap = read_config(&sel, ptr + PCICAP_ID, 1);
195                         if (cap == PCIY_MSI) {
196                                 /*
197                                  * Copy the MSI capability into the config
198                                  * space of the emulated pci device
199                                  */
200                                 sc->psc_msi.capoff = ptr;
201                                 sc->psc_msi.msgctrl = read_config(&sel,
202                                                                   ptr + 2, 2);
203                                 sc->psc_msi.emulated = 0;
204                                 caplen = msi_caplen(sc->psc_msi.msgctrl);
205                                 capptr = ptr;
206                                 while (caplen > 0) {
207                                         u32 = read_config(&sel, capptr, 4);
208                                         pci_set_cfgdata32(pi, capptr, u32);
209                                         caplen -= 4;
210                                         capptr += 4;
211                                 }
212                         } else if (cap == PCIY_MSIX) {
213                                 /*
214                                  * Copy the MSI-X capability 
215                                  */
216                                 sc->psc_msix.capoff = ptr;
217                                 caplen = 12;
218                                 msixcap_ptr = (uint32_t*) &msixcap;
219                                 capptr = ptr;
220                                 while (caplen > 0) {
221                                         u32 = read_config(&sel, capptr, 4);
222                                         *msixcap_ptr = u32;
223                                         pci_set_cfgdata32(pi, capptr, u32);
224                                         caplen -= 4;
225                                         capptr += 4;
226                                         msixcap_ptr++;
227                                 }
228                         }
229                         ptr = read_config(&sel, ptr + PCICAP_NEXTPTR, 1);
230                 }
231         }
232
233         if (sc->psc_msix.capoff != 0) {
234                 pi->pi_msix.pba_bar =
235                     msixcap.pba_info & PCIM_MSIX_BIR_MASK;
236                 pi->pi_msix.pba_offset =
237                     msixcap.pba_info & ~PCIM_MSIX_BIR_MASK;
238                 pi->pi_msix.table_bar =
239                     msixcap.table_info & PCIM_MSIX_BIR_MASK;
240                 pi->pi_msix.table_offset =
241                     msixcap.table_info & ~PCIM_MSIX_BIR_MASK;
242                 pi->pi_msix.table_count = MSIX_TABLE_COUNT(msixcap.msgctrl);
243                 pi->pi_msix.pba_size = PBA_SIZE(pi->pi_msix.table_count);
244
245                 /* Allocate the emulated MSI-X table array */
246                 table_size = pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
247                 pi->pi_msix.table = calloc(1, table_size);
248
249                 /* Mask all table entries */
250                 for (i = 0; i < pi->pi_msix.table_count; i++) {
251                         pi->pi_msix.table[i].vector_control |=
252                                                 PCIM_MSIX_VCTRL_MASK;
253                 }
254         }
255
256 #ifdef LEGACY_SUPPORT
257         /*
258          * If the passthrough device does not support MSI then craft a
259          * MSI capability for it. We link the new MSI capability at the
260          * head of the list of capabilities.
261          */
262         if ((sts & PCIM_STATUS_CAPPRESENT) != 0 && sc->psc_msi.capoff == 0) {
263                 int origptr, msiptr;
264                 origptr = read_config(&sel, PCIR_CAP_PTR, 1);
265                 msiptr = passthru_add_msicap(pi, 1, origptr);
266                 sc->psc_msi.capoff = msiptr;
267                 sc->psc_msi.msgctrl = pci_get_cfgdata16(pi, msiptr + 2);
268                 sc->psc_msi.emulated = 1;
269                 pci_set_cfgdata8(pi, PCIR_CAP_PTR, msiptr);
270         }
271 #endif
272
273         /* Make sure one of the capabilities is present */
274         if (sc->psc_msi.capoff == 0 && sc->psc_msix.capoff == 0) 
275                 return (-1);
276         else
277                 return (0);
278 }
279
280 static uint64_t
281 msix_table_read(struct passthru_softc *sc, uint64_t offset, int size)
282 {
283         struct pci_devinst *pi;
284         struct msix_table_entry *entry;
285         uint8_t *src8;
286         uint16_t *src16;
287         uint32_t *src32;
288         uint64_t *src64;
289         uint64_t data;
290         size_t entry_offset;
291         uint32_t table_offset;
292         int index, table_count;
293
294         pi = sc->psc_pi;
295
296         table_offset = pi->pi_msix.table_offset;
297         table_count = pi->pi_msix.table_count;
298         if (offset < table_offset ||
299             offset >= table_offset + table_count * MSIX_TABLE_ENTRY_SIZE) {
300                 switch (size) {
301                 case 1:
302                         src8 = (uint8_t *)(pi->pi_msix.mapped_addr + offset);
303                         data = *src8;
304                         break;
305                 case 2:
306                         src16 = (uint16_t *)(pi->pi_msix.mapped_addr + offset);
307                         data = *src16;
308                         break;
309                 case 4:
310                         src32 = (uint32_t *)(pi->pi_msix.mapped_addr + offset);
311                         data = *src32;
312                         break;
313                 case 8:
314                         src64 = (uint64_t *)(pi->pi_msix.mapped_addr + offset);
315                         data = *src64;
316                         break;
317                 default:
318                         return (-1);
319                 }
320                 return (data);
321         }
322
323         offset -= table_offset;
324         index = offset / MSIX_TABLE_ENTRY_SIZE;
325         assert(index < table_count);
326
327         entry = &pi->pi_msix.table[index];
328         entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
329
330         switch (size) {
331         case 1:
332                 src8 = (uint8_t *)((uint8_t *)entry + entry_offset);
333                 data = *src8;
334                 break;
335         case 2:
336                 src16 = (uint16_t *)((uint8_t *)entry + entry_offset);
337                 data = *src16;
338                 break;
339         case 4:
340                 src32 = (uint32_t *)((uint8_t *)entry + entry_offset);
341                 data = *src32;
342                 break;
343         case 8:
344                 src64 = (uint64_t *)((uint8_t *)entry + entry_offset);
345                 data = *src64;
346                 break;
347         default:
348                 return (-1);
349         }
350
351         return (data);
352 }
353
354 static void
355 msix_table_write(struct vmctx *ctx, int vcpu, struct passthru_softc *sc,
356                  uint64_t offset, int size, uint64_t data)
357 {
358         struct pci_devinst *pi;
359         struct msix_table_entry *entry;
360         uint8_t *dest8;
361         uint16_t *dest16;
362         uint32_t *dest32;
363         uint64_t *dest64;
364         size_t entry_offset;
365         uint32_t table_offset, vector_control;
366         int index, table_count;
367
368         pi = sc->psc_pi;
369
370         table_offset = pi->pi_msix.table_offset;
371         table_count = pi->pi_msix.table_count;
372         if (offset < table_offset ||
373             offset >= table_offset + table_count * MSIX_TABLE_ENTRY_SIZE) {
374                 switch (size) {
375                 case 1:
376                         dest8 = (uint8_t *)(pi->pi_msix.mapped_addr + offset);
377                         *dest8 = data;
378                         break;
379                 case 2:
380                         dest16 = (uint16_t *)(pi->pi_msix.mapped_addr + offset);
381                         *dest16 = data;
382                         break;
383                 case 4:
384                         dest32 = (uint32_t *)(pi->pi_msix.mapped_addr + offset);
385                         *dest32 = data;
386                         break;
387                 case 8:
388                         dest64 = (uint64_t *)(pi->pi_msix.mapped_addr + offset);
389                         *dest64 = data;
390                         break;
391                 }
392                 return;
393         }
394
395         offset -= table_offset;
396         index = offset / MSIX_TABLE_ENTRY_SIZE;
397         assert(index < table_count);
398
399         entry = &pi->pi_msix.table[index];
400         entry_offset = offset % MSIX_TABLE_ENTRY_SIZE;
401
402         /* Only 4 byte naturally-aligned writes are supported */
403         assert(size == 4);
404         assert(entry_offset % 4 == 0);
405
406         vector_control = entry->vector_control;
407         dest32 = (uint32_t *)((void *)entry + entry_offset);
408         *dest32 = data;
409         /* If MSI-X hasn't been enabled, do nothing */
410         if (pi->pi_msix.enabled) {
411                 /* If the entry is masked, don't set it up */
412                 if ((entry->vector_control & PCIM_MSIX_VCTRL_MASK) == 0 ||
413                     (vector_control & PCIM_MSIX_VCTRL_MASK) == 0) {
414                         (void)vm_setup_pptdev_msix(ctx, vcpu,
415                             sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
416                             sc->psc_sel.pc_func, index, entry->addr,
417                             entry->msg_data, entry->vector_control);
418                 }
419         }
420 }
421
422 static int
423 init_msix_table(struct vmctx *ctx, struct passthru_softc *sc)
424 {
425         struct pci_devinst *pi = sc->psc_pi;
426         struct pci_bar_mmap pbm;
427         int b, s, f;
428         uint32_t table_size, table_offset;
429
430         assert(pci_msix_table_bar(pi) >= 0 && pci_msix_pba_bar(pi) >= 0);
431
432         b = sc->psc_sel.pc_bus;
433         s = sc->psc_sel.pc_dev;
434         f = sc->psc_sel.pc_func;
435
436         /*
437          * Map the region of the BAR containing the MSI-X table.  This is
438          * necessary for two reasons:
439          * 1. The PBA may reside in the first or last page containing the MSI-X
440          *    table.
441          * 2. While PCI devices are not supposed to use the page(s) containing
442          *    the MSI-X table for other purposes, some do in practice.
443          */
444         memset(&pbm, 0, sizeof(pbm));
445         pbm.pbm_sel = sc->psc_sel;
446         pbm.pbm_flags = PCIIO_BAR_MMAP_RW;
447         pbm.pbm_reg = PCIR_BAR(pi->pi_msix.table_bar);
448         pbm.pbm_memattr = VM_MEMATTR_DEVICE;
449
450         if (ioctl(pcifd, PCIOCBARMMAP, &pbm) != 0) {
451                 warn("Failed to map MSI-X table BAR on %d/%d/%d", b, s, f);
452                 return (-1);
453         }
454         assert(pbm.pbm_bar_off == 0);
455         pi->pi_msix.mapped_addr = (uint8_t *)(uintptr_t)pbm.pbm_map_base;
456         pi->pi_msix.mapped_size = pbm.pbm_map_length;
457
458         table_offset = rounddown2(pi->pi_msix.table_offset, 4096);
459
460         table_size = pi->pi_msix.table_offset - table_offset;
461         table_size += pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
462         table_size = roundup2(table_size, 4096);
463
464         /*
465          * Unmap any pages not containing the table, we do not need to emulate
466          * accesses to them.  Avoid releasing address space to help ensure that
467          * a buggy out-of-bounds access causes a crash.
468          */
469         if (table_offset != 0)
470                 if (mprotect(pi->pi_msix.mapped_addr, table_offset,
471                     PROT_NONE) != 0)
472                         warn("Failed to unmap MSI-X table BAR region");
473         if (table_offset + table_size != pi->pi_msix.mapped_size)
474                 if (mprotect(
475                     pi->pi_msix.mapped_addr + table_offset + table_size,
476                     pi->pi_msix.mapped_size - (table_offset + table_size),
477                     PROT_NONE) != 0)
478                         warn("Failed to unmap MSI-X table BAR region");
479
480         return (0);
481 }
482
483 static int
484 cfginitbar(struct vmctx *ctx, struct passthru_softc *sc)
485 {
486         int i, error;
487         struct pci_devinst *pi;
488         struct pci_bar_io bar;
489         enum pcibar_type bartype;
490         uint64_t base, size;
491
492         pi = sc->psc_pi;
493
494         /*
495          * Initialize BAR registers
496          */
497         for (i = 0; i <= PCI_BARMAX; i++) {
498                 bzero(&bar, sizeof(bar));
499                 bar.pbi_sel = sc->psc_sel;
500                 bar.pbi_reg = PCIR_BAR(i);
501
502                 if (ioctl(pcifd, PCIOCGETBAR, &bar) < 0)
503                         continue;
504
505                 if (PCI_BAR_IO(bar.pbi_base)) {
506                         bartype = PCIBAR_IO;
507                         base = bar.pbi_base & PCIM_BAR_IO_BASE;
508                 } else {
509                         switch (bar.pbi_base & PCIM_BAR_MEM_TYPE) {
510                         case PCIM_BAR_MEM_64:
511                                 bartype = PCIBAR_MEM64;
512                                 break;
513                         default:
514                                 bartype = PCIBAR_MEM32;
515                                 break;
516                         }
517                         base = bar.pbi_base & PCIM_BAR_MEM_BASE;
518                 }
519                 size = bar.pbi_length;
520
521                 if (bartype != PCIBAR_IO) {
522                         if (((base | size) & PAGE_MASK) != 0) {
523                                 warnx("passthru device %d/%d/%d BAR %d: "
524                                     "base %#lx or size %#lx not page aligned\n",
525                                     sc->psc_sel.pc_bus, sc->psc_sel.pc_dev,
526                                     sc->psc_sel.pc_func, i, base, size);
527                                 return (-1);
528                         }
529                 }
530
531                 /* Cache information about the "real" BAR */
532                 sc->psc_bar[i].type = bartype;
533                 sc->psc_bar[i].size = size;
534                 sc->psc_bar[i].addr = base;
535                 sc->psc_bar[i].lobits = 0;
536
537                 /* Allocate the BAR in the guest I/O or MMIO space */
538                 error = pci_emul_alloc_bar(pi, i, bartype, size);
539                 if (error)
540                         return (-1);
541
542                 /* Use same lobits as physical bar */
543                 uint8_t lobits = read_config(&sc->psc_sel, PCIR_BAR(i), 0x01);
544                 if (bartype == PCIBAR_MEM32 || bartype == PCIBAR_MEM64) {
545                         lobits &= ~PCIM_BAR_MEM_BASE;
546                 } else {
547                         lobits &= ~PCIM_BAR_IO_BASE;
548                 }
549                 sc->psc_bar[i].lobits = lobits;
550                 pi->pi_bar[i].lobits = lobits;
551
552                 /* The MSI-X table needs special handling */
553                 if (i == pci_msix_table_bar(pi)) {
554                         error = init_msix_table(ctx, sc);
555                         if (error) 
556                                 return (-1);
557                 }
558
559                 /*
560                  * 64-bit BAR takes up two slots so skip the next one.
561                  */
562                 if (bartype == PCIBAR_MEM64) {
563                         i++;
564                         assert(i <= PCI_BARMAX);
565                         sc->psc_bar[i].type = PCIBAR_MEMHI64;
566                 }
567         }
568         return (0);
569 }
570
571 static int
572 cfginit(struct vmctx *ctx, struct pci_devinst *pi, int bus, int slot, int func)
573 {
574         int error;
575         struct passthru_softc *sc;
576
577         error = 1;
578         sc = pi->pi_arg;
579
580         bzero(&sc->psc_sel, sizeof(struct pcisel));
581         sc->psc_sel.pc_bus = bus;
582         sc->psc_sel.pc_dev = slot;
583         sc->psc_sel.pc_func = func;
584
585         if (cfginitmsi(sc) != 0) {
586                 warnx("failed to initialize MSI for PCI %d/%d/%d",
587                     bus, slot, func);
588                 goto done;
589         }
590
591         if (cfginitbar(ctx, sc) != 0) {
592                 warnx("failed to initialize BARs for PCI %d/%d/%d",
593                     bus, slot, func);
594                 goto done;
595         }
596
597         write_config(&sc->psc_sel, PCIR_COMMAND, 2,
598             pci_get_cfgdata16(pi, PCIR_COMMAND));
599
600         /*
601          * We need to do this after PCIR_COMMAND got possibly updated, e.g.,
602          * a BAR was enabled, as otherwise the PCIOCBARMMAP might fail on us.
603          */
604         if (pci_msix_table_bar(pi) >= 0) {
605                 error = init_msix_table(ctx, sc);
606                 if (error != 0) {
607                         warnx(
608                             "failed to initialize MSI-X table for PCI %d/%d/%d: %d",
609                             bus, slot, func, error);
610                         goto done;
611                 }
612         }
613
614         error = 0;                              /* success */
615 done:
616         return (error);
617 }
618
619 static int
620 passthru_legacy_config(nvlist_t *nvl, const char *opts)
621 {
622         char value[16];
623         int bus, slot, func;
624
625         if (opts == NULL)
626                 return (0);
627
628         if (sscanf(opts, "%d/%d/%d", &bus, &slot, &func) != 3) {
629                 EPRINTLN("passthru: invalid options \"%s\"", opts);
630                 return (-1);
631         }
632
633         snprintf(value, sizeof(value), "%d", bus);
634         set_config_value_node(nvl, "bus", value);
635         snprintf(value, sizeof(value), "%d", slot);
636         set_config_value_node(nvl, "slot", value);
637         snprintf(value, sizeof(value), "%d", func);
638         set_config_value_node(nvl, "func", value);
639         return (0);
640 }
641
642 static int
643 passthru_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
644 {
645         int bus, slot, func, error, memflags;
646         struct passthru_softc *sc;
647         const char *value;
648 #ifndef WITHOUT_CAPSICUM
649         cap_rights_t rights;
650         cap_ioctl_t pci_ioctls[] =
651             { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR, PCIOCBARIO, PCIOCBARMMAP };
652 #endif
653
654         sc = NULL;
655         error = 1;
656
657 #ifndef WITHOUT_CAPSICUM
658         cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_WRITE);
659 #endif
660
661         memflags = vm_get_memflags(ctx);
662         if (!(memflags & VM_MEM_F_WIRED)) {
663                 warnx("passthru requires guest memory to be wired");
664                 return (error);
665         }
666
667         if (pcifd < 0) {
668                 pcifd = open(_PATH_DEVPCI, O_RDWR, 0);
669                 if (pcifd < 0) {
670                         warn("failed to open %s", _PATH_DEVPCI);
671                         return (error);
672                 }
673         }
674
675 #ifndef WITHOUT_CAPSICUM
676         if (caph_rights_limit(pcifd, &rights) == -1)
677                 errx(EX_OSERR, "Unable to apply rights for sandbox");
678         if (caph_ioctls_limit(pcifd, pci_ioctls, nitems(pci_ioctls)) == -1)
679                 errx(EX_OSERR, "Unable to apply rights for sandbox");
680 #endif
681
682 #define GET_INT_CONFIG(var, name) do {                                  \
683         value = get_config_value_node(nvl, name);                       \
684         if (value == NULL) {                                            \
685                 EPRINTLN("passthru: missing required %s setting", name); \
686                 return (error);                                         \
687         }                                                               \
688         var = atoi(value);                                              \
689 } while (0)
690
691         GET_INT_CONFIG(bus, "bus");
692         GET_INT_CONFIG(slot, "slot");
693         GET_INT_CONFIG(func, "func");
694
695         if (vm_assign_pptdev(ctx, bus, slot, func) != 0) {
696                 warnx("PCI device at %d/%d/%d is not using the ppt(4) driver",
697                     bus, slot, func);
698                 goto done;
699         }
700
701         sc = calloc(1, sizeof(struct passthru_softc));
702
703         pi->pi_arg = sc;
704         sc->psc_pi = pi;
705
706         /* initialize config space */
707         error = cfginit(ctx, pi, bus, slot, func);
708 done:
709         if (error) {
710                 free(sc);
711                 vm_unassign_pptdev(ctx, bus, slot, func);
712         }
713         return (error);
714 }
715
716 static int
717 bar_access(int coff)
718 {
719         if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1))
720                 return (1);
721         else
722                 return (0);
723 }
724
725 static int
726 msicap_access(struct passthru_softc *sc, int coff)
727 {
728         int caplen;
729
730         if (sc->psc_msi.capoff == 0)
731                 return (0);
732
733         caplen = msi_caplen(sc->psc_msi.msgctrl);
734
735         if (coff >= sc->psc_msi.capoff && coff < sc->psc_msi.capoff + caplen)
736                 return (1);
737         else
738                 return (0);
739 }
740
741 static int 
742 msixcap_access(struct passthru_softc *sc, int coff)
743 {
744         if (sc->psc_msix.capoff == 0) 
745                 return (0);
746
747         return (coff >= sc->psc_msix.capoff && 
748                 coff < sc->psc_msix.capoff + MSIX_CAPLEN);
749 }
750
751 static int
752 passthru_cfgread(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
753                  int coff, int bytes, uint32_t *rv)
754 {
755         struct passthru_softc *sc;
756
757         sc = pi->pi_arg;
758
759         /*
760          * PCI BARs and MSI capability is emulated.
761          */
762         if (bar_access(coff) || msicap_access(sc, coff) ||
763             msixcap_access(sc, coff))
764                 return (-1);
765
766 #ifdef LEGACY_SUPPORT
767         /*
768          * Emulate PCIR_CAP_PTR if this device does not support MSI capability
769          * natively.
770          */
771         if (sc->psc_msi.emulated) {
772                 if (coff >= PCIR_CAP_PTR && coff < PCIR_CAP_PTR + 4)
773                         return (-1);
774         }
775 #endif
776
777         /*
778          * Emulate the command register.  If a single read reads both the
779          * command and status registers, read the status register from the
780          * device's config space.
781          */
782         if (coff == PCIR_COMMAND) {
783                 if (bytes <= 2)
784                         return (-1);
785                 *rv = read_config(&sc->psc_sel, PCIR_STATUS, 2) << 16 |
786                     pci_get_cfgdata16(pi, PCIR_COMMAND);
787                 return (0);
788         }
789
790         /* Everything else just read from the device's config space */
791         *rv = read_config(&sc->psc_sel, coff, bytes);
792
793         return (0);
794 }
795
796 static int
797 passthru_cfgwrite(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
798                   int coff, int bytes, uint32_t val)
799 {
800         int error, msix_table_entries, i;
801         struct passthru_softc *sc;
802         uint16_t cmd_old;
803
804         sc = pi->pi_arg;
805
806         /*
807          * PCI BARs are emulated
808          */
809         if (bar_access(coff))
810                 return (-1);
811
812         /*
813          * MSI capability is emulated
814          */
815         if (msicap_access(sc, coff)) {
816                 pci_emul_capwrite(pi, coff, bytes, val, sc->psc_msi.capoff,
817                     PCIY_MSI);
818                 error = vm_setup_pptdev_msi(ctx, vcpu, sc->psc_sel.pc_bus,
819                         sc->psc_sel.pc_dev, sc->psc_sel.pc_func,
820                         pi->pi_msi.addr, pi->pi_msi.msg_data,
821                         pi->pi_msi.maxmsgnum);
822                 if (error != 0)
823                         err(1, "vm_setup_pptdev_msi");
824                 return (0);
825         }
826
827         if (msixcap_access(sc, coff)) {
828                 pci_emul_capwrite(pi, coff, bytes, val, sc->psc_msix.capoff,
829                     PCIY_MSIX);
830                 if (pi->pi_msix.enabled) {
831                         msix_table_entries = pi->pi_msix.table_count;
832                         for (i = 0; i < msix_table_entries; i++) {
833                                 error = vm_setup_pptdev_msix(ctx, vcpu,
834                                     sc->psc_sel.pc_bus, sc->psc_sel.pc_dev, 
835                                     sc->psc_sel.pc_func, i, 
836                                     pi->pi_msix.table[i].addr,
837                                     pi->pi_msix.table[i].msg_data,
838                                     pi->pi_msix.table[i].vector_control);
839                 
840                                 if (error)
841                                         err(1, "vm_setup_pptdev_msix");
842                         }
843                 } else {
844                         error = vm_disable_pptdev_msix(ctx, sc->psc_sel.pc_bus,
845                             sc->psc_sel.pc_dev, sc->psc_sel.pc_func);
846                         if (error)
847                                 err(1, "vm_disable_pptdev_msix");
848                 }
849                 return (0);
850         }
851
852 #ifdef LEGACY_SUPPORT
853         /*
854          * If this device does not support MSI natively then we cannot let
855          * the guest disable legacy interrupts from the device. It is the
856          * legacy interrupt that is triggering the virtual MSI to the guest.
857          */
858         if (sc->psc_msi.emulated && pci_msi_enabled(pi)) {
859                 if (coff == PCIR_COMMAND && bytes == 2)
860                         val &= ~PCIM_CMD_INTxDIS;
861         }
862 #endif
863
864         write_config(&sc->psc_sel, coff, bytes, val);
865         if (coff == PCIR_COMMAND) {
866                 cmd_old = pci_get_cfgdata16(pi, PCIR_COMMAND);
867                 if (bytes == 1)
868                         pci_set_cfgdata8(pi, PCIR_COMMAND, val);
869                 else if (bytes == 2)
870                         pci_set_cfgdata16(pi, PCIR_COMMAND, val);
871                 pci_emul_cmd_changed(pi, cmd_old);
872         }
873
874         return (0);
875 }
876
877 static void
878 passthru_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
879                uint64_t offset, int size, uint64_t value)
880 {
881         struct passthru_softc *sc;
882         struct pci_bar_ioreq pio;
883
884         sc = pi->pi_arg;
885
886         if (baridx == pci_msix_table_bar(pi)) {
887                 msix_table_write(ctx, vcpu, sc, offset, size, value);
888         } else {
889                 assert(pi->pi_bar[baridx].type == PCIBAR_IO);
890                 assert(size == 1 || size == 2 || size == 4);
891                 assert(offset <= UINT32_MAX && offset + size <= UINT32_MAX);
892
893                 bzero(&pio, sizeof(pio));
894                 pio.pbi_sel = sc->psc_sel;
895                 pio.pbi_op = PCIBARIO_WRITE;
896                 pio.pbi_bar = baridx;
897                 pio.pbi_offset = (uint32_t)offset;
898                 pio.pbi_width = size;
899                 pio.pbi_value = (uint32_t)value;
900
901                 (void)ioctl(pcifd, PCIOCBARIO, &pio);
902         }
903 }
904
905 static uint64_t
906 passthru_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx,
907               uint64_t offset, int size)
908 {
909         struct passthru_softc *sc;
910         struct pci_bar_ioreq pio;
911         uint64_t val;
912
913         sc = pi->pi_arg;
914
915         if (baridx == pci_msix_table_bar(pi)) {
916                 val = msix_table_read(sc, offset, size);
917         } else {
918                 assert(pi->pi_bar[baridx].type == PCIBAR_IO);
919                 assert(size == 1 || size == 2 || size == 4);
920                 assert(offset <= UINT32_MAX && offset + size <= UINT32_MAX);
921
922                 bzero(&pio, sizeof(pio));
923                 pio.pbi_sel = sc->psc_sel;
924                 pio.pbi_op = PCIBARIO_READ;
925                 pio.pbi_bar = baridx;
926                 pio.pbi_offset = (uint32_t)offset;
927                 pio.pbi_width = size;
928
929                 (void)ioctl(pcifd, PCIOCBARIO, &pio);
930
931                 val = pio.pbi_value;
932         }
933
934         return (val);
935 }
936
937 static void
938 passthru_msix_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
939                    int enabled, uint64_t address)
940 {
941         struct passthru_softc *sc;
942         size_t remaining;
943         uint32_t table_size, table_offset;
944
945         sc = pi->pi_arg;
946         table_offset = rounddown2(pi->pi_msix.table_offset, 4096);
947         if (table_offset > 0) {
948                 if (!enabled) {
949                         if (vm_unmap_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
950                                                  sc->psc_sel.pc_dev,
951                                                  sc->psc_sel.pc_func, address,
952                                                  table_offset) != 0)
953                                 warnx("pci_passthru: unmap_pptdev_mmio failed");
954                 } else {
955                         if (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
956                                                sc->psc_sel.pc_dev,
957                                                sc->psc_sel.pc_func, address,
958                                                table_offset,
959                                                sc->psc_bar[baridx].addr) != 0)
960                                 warnx("pci_passthru: map_pptdev_mmio failed");
961                 }
962         }
963         table_size = pi->pi_msix.table_offset - table_offset;
964         table_size += pi->pi_msix.table_count * MSIX_TABLE_ENTRY_SIZE;
965         table_size = roundup2(table_size, 4096);
966         remaining = pi->pi_bar[baridx].size - table_offset - table_size;
967         if (remaining > 0) {
968                 address += table_offset + table_size;
969                 if (!enabled) {
970                         if (vm_unmap_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
971                                                  sc->psc_sel.pc_dev,
972                                                  sc->psc_sel.pc_func, address,
973                                                  remaining) != 0)
974                                 warnx("pci_passthru: unmap_pptdev_mmio failed");
975                 } else {
976                         if (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
977                                                sc->psc_sel.pc_dev,
978                                                sc->psc_sel.pc_func, address,
979                                                remaining,
980                                                sc->psc_bar[baridx].addr +
981                                                table_offset + table_size) != 0)
982                                 warnx("pci_passthru: map_pptdev_mmio failed");
983                 }
984         }
985 }
986
987 static void
988 passthru_mmio_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
989                    int enabled, uint64_t address)
990 {
991         struct passthru_softc *sc;
992
993         sc = pi->pi_arg;
994         if (!enabled) {
995                 if (vm_unmap_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
996                                          sc->psc_sel.pc_dev,
997                                          sc->psc_sel.pc_func, address,
998                                          sc->psc_bar[baridx].size) != 0)
999                         warnx("pci_passthru: unmap_pptdev_mmio failed");
1000         } else {
1001                 if (vm_map_pptdev_mmio(ctx, sc->psc_sel.pc_bus,
1002                                        sc->psc_sel.pc_dev,
1003                                        sc->psc_sel.pc_func, address,
1004                                        sc->psc_bar[baridx].size,
1005                                        sc->psc_bar[baridx].addr) != 0)
1006                         warnx("pci_passthru: map_pptdev_mmio failed");
1007         }
1008 }
1009
1010 static void
1011 passthru_addr(struct vmctx *ctx, struct pci_devinst *pi, int baridx,
1012               int enabled, uint64_t address)
1013 {
1014
1015         if (pi->pi_bar[baridx].type == PCIBAR_IO)
1016                 return;
1017         if (baridx == pci_msix_table_bar(pi))
1018                 passthru_msix_addr(ctx, pi, baridx, enabled, address);
1019         else
1020                 passthru_mmio_addr(ctx, pi, baridx, enabled, address);
1021 }
1022
1023 struct pci_devemu passthru = {
1024         .pe_emu         = "passthru",
1025         .pe_init        = passthru_init,
1026         .pe_legacy_config = passthru_legacy_config,
1027         .pe_cfgwrite    = passthru_cfgwrite,
1028         .pe_cfgread     = passthru_cfgread,
1029         .pe_barwrite    = passthru_write,
1030         .pe_barread     = passthru_read,
1031         .pe_baraddr     = passthru_addr,
1032 };
1033 PCI_EMUL_SET(passthru);