Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_passthru.c
| Show First 20 Lines • Show All 53 Lines • ▼ Show 20 Lines | |||||
| #include <err.h> | #include <err.h> | ||||
| #include <errno.h> | #include <errno.h> | ||||
| #include <fcntl.h> | #include <fcntl.h> | ||||
| #include <sysexits.h> | #include <sysexits.h> | ||||
| #include <unistd.h> | #include <unistd.h> | ||||
| #include <machine/vmm.h> | #include <machine/vmm.h> | ||||
| #include <vmmapi.h> | #include <vmmapi.h> | ||||
| #include "config.h" | |||||
| #include "debug.h" | |||||
| #include "pci_emul.h" | #include "pci_emul.h" | ||||
| #include "mem.h" | #include "mem.h" | ||||
| #ifndef _PATH_DEVPCI | #ifndef _PATH_DEVPCI | ||||
| #define _PATH_DEVPCI "/dev/pci" | #define _PATH_DEVPCI "/dev/pci" | ||||
| #endif | #endif | ||||
| #ifndef _PATH_DEVIO | #ifndef _PATH_DEVIO | ||||
| ▲ Show 20 Lines • Show All 573 Lines • ▼ Show 20 Lines | pci_set_cfgdata16(pi, PCIR_COMMAND, read_config(&sc->psc_sel, | ||||
| PCIR_COMMAND, 2)); | PCIR_COMMAND, 2)); | ||||
| error = 0; /* success */ | error = 0; /* success */ | ||||
| done: | done: | ||||
| return (error); | return (error); | ||||
| } | } | ||||
| static int | static int | ||||
| passthru_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | passthru_legacy_config(nvlist_t *nvl, const char *opts) | ||||
| { | { | ||||
| char value[16]; | |||||
| int bus, slot, func; | |||||
| if (opts == NULL) | |||||
| return (0); | |||||
| if (sscanf(opts, "%d/%d/%d", &bus, &slot, &func) != 3) { | |||||
| EPRINTLN("passthru: invalid options \"%s\"", opts); | |||||
| return (-1); | |||||
| } | |||||
| snprintf(value, sizeof(value), "%d", bus); | |||||
| set_config_value_node(nvl, "bus", value); | |||||
| snprintf(value, sizeof(value), "%d", slot); | |||||
| set_config_value_node(nvl, "slot", value); | |||||
| snprintf(value, sizeof(value), "%d", func); | |||||
| set_config_value_node(nvl, "func", value); | |||||
| return (0); | |||||
| } | |||||
| static int | |||||
| passthru_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | |||||
| { | |||||
| int bus, slot, func, error, memflags; | int bus, slot, func, error, memflags; | ||||
| struct passthru_softc *sc; | struct passthru_softc *sc; | ||||
| const char *value; | |||||
| #ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
| cap_rights_t rights; | cap_rights_t rights; | ||||
| cap_ioctl_t pci_ioctls[] = { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR }; | cap_ioctl_t pci_ioctls[] = { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR }; | ||||
| cap_ioctl_t io_ioctls[] = { IODEV_PIO }; | cap_ioctl_t io_ioctls[] = { IODEV_PIO }; | ||||
| #endif | #endif | ||||
| sc = NULL; | sc = NULL; | ||||
| error = 1; | error = 1; | ||||
| ▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
| #ifndef WITHOUT_CAPSICUM | #ifndef WITHOUT_CAPSICUM | ||||
| cap_rights_clear(&rights, CAP_IOCTL); | cap_rights_clear(&rights, CAP_IOCTL); | ||||
| cap_rights_set(&rights, CAP_MMAP_RW); | cap_rights_set(&rights, CAP_MMAP_RW); | ||||
| if (caph_rights_limit(memfd, &rights) == -1) | if (caph_rights_limit(memfd, &rights) == -1) | ||||
| errx(EX_OSERR, "Unable to apply rights for sandbox"); | errx(EX_OSERR, "Unable to apply rights for sandbox"); | ||||
| #endif | #endif | ||||
| if (opts == NULL || | #define GET_INT_CONFIG(var, name) do { \ | ||||
| sscanf(opts, "%d/%d/%d", &bus, &slot, &func) != 3) { | value = get_config_value_node(nvl, name); \ | ||||
| warnx("invalid passthru options"); | if (value == NULL) { \ | ||||
| return (error); | EPRINTLN("passthru: missing required %s setting", name); \ | ||||
| } | return (error); \ | ||||
| } \ | |||||
| var = atoi(value); \ | |||||
| } while (0) | |||||
| GET_INT_CONFIG(bus, "bus"); | |||||
| GET_INT_CONFIG(slot, "slot"); | |||||
| GET_INT_CONFIG(func, "func"); | |||||
| if (vm_assign_pptdev(ctx, bus, slot, func) != 0) { | if (vm_assign_pptdev(ctx, bus, slot, func) != 0) { | ||||
| warnx("PCI device at %d/%d/%d is not using the ppt(4) driver", | warnx("PCI device at %d/%d/%d is not using the ppt(4) driver", | ||||
| bus, slot, func); | bus, slot, func); | ||||
| goto done; | goto done; | ||||
| } | } | ||||
| sc = calloc(1, sizeof(struct passthru_softc)); | sc = calloc(1, sizeof(struct passthru_softc)); | ||||
| ▲ Show 20 Lines • Show All 219 Lines • ▼ Show 20 Lines | passthru_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, int baridx, | ||||
| } | } | ||||
| return (val); | return (val); | ||||
| } | } | ||||
| struct pci_devemu passthru = { | struct pci_devemu passthru = { | ||||
| .pe_emu = "passthru", | .pe_emu = "passthru", | ||||
| .pe_init = passthru_init, | .pe_init = passthru_init, | ||||
| .pe_legacy_config = passthru_legacy_config, | |||||
| .pe_cfgwrite = passthru_cfgwrite, | .pe_cfgwrite = passthru_cfgwrite, | ||||
| .pe_cfgread = passthru_cfgread, | .pe_cfgread = passthru_cfgread, | ||||
| .pe_barwrite = passthru_write, | .pe_barwrite = passthru_write, | ||||
| .pe_barread = passthru_read, | .pe_barread = passthru_read, | ||||
| }; | }; | ||||
| PCI_EMUL_SET(passthru); | PCI_EMUL_SET(passthru); | ||||