Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_passthru.c
Show First 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | |||||
#include <string.h> | #include <string.h> | ||||
#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 "config.h" | #include "config.h" | ||||
#include "debug.h" | #include "debug.h" | ||||
#include "pci_emul.h" | |||||
#include "mem.h" | #include "mem.h" | ||||
#include "pci_passthru.h" | |||||
#ifndef _PATH_DEVPCI | #ifndef _PATH_DEVPCI | ||||
#define _PATH_DEVPCI "/dev/pci" | #define _PATH_DEVPCI "/dev/pci" | ||||
#endif | #endif | ||||
#define LEGACY_SUPPORT 1 | #define LEGACY_SUPPORT 1 | ||||
#define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1) | #define MSIX_TABLE_COUNT(ctrl) (((ctrl) & PCIM_MSIXCTRL_TABLE_SIZE) + 1) | ||||
Show All 32 Lines | #if 0 | ||||
*/ | */ | ||||
if (msgctrl & PCIM_MSICTRL_VECTOR) | if (msgctrl & PCIM_MSICTRL_VECTOR) | ||||
len += 10; | len += 10; | ||||
#endif | #endif | ||||
return (len); | return (len); | ||||
} | } | ||||
static uint32_t | static int | ||||
pcifd_init() { | |||||
pcifd = open(_PATH_DEVPCI, O_RDWR, 0); | |||||
if (pcifd < 0) { | |||||
warn("failed to open %s", _PATH_DEVPCI); | |||||
return (1); | |||||
} | |||||
#ifndef WITHOUT_CAPSICUM | |||||
cap_rights_t pcifd_rights; | |||||
cap_rights_init(&pcifd_rights, CAP_IOCTL, CAP_READ, CAP_WRITE); | |||||
if (caph_rights_limit(pcifd, &pcifd_rights) == -1) | |||||
errx(EX_OSERR, "Unable to apply rights for sandbox"); | |||||
const cap_ioctl_t pcifd_ioctls[] = { PCIOCREAD, PCIOCWRITE, PCIOCGETBAR, | |||||
PCIOCBARIO, PCIOCBARMMAP }; | |||||
if (caph_ioctls_limit(pcifd, pcifd_ioctls, nitems(pcifd_ioctls)) == -1) | |||||
errx(EX_OSERR, "Unable to apply rights for sandbox"); | |||||
#endif | |||||
return (0); | |||||
} | |||||
uint32_t | |||||
read_config(const struct pcisel *sel, long reg, int width) | read_config(const struct pcisel *sel, long reg, int width) | ||||
{ | { | ||||
if (pcifd < 0 && pcifd_init()) { | |||||
return (0); | |||||
} | |||||
struct pci_io pi; | struct pci_io pi; | ||||
bzero(&pi, sizeof(pi)); | bzero(&pi, sizeof(pi)); | ||||
pi.pi_sel = *sel; | pi.pi_sel = *sel; | ||||
pi.pi_reg = reg; | pi.pi_reg = reg; | ||||
pi.pi_width = width; | pi.pi_width = width; | ||||
if (ioctl(pcifd, PCIOCREAD, &pi) < 0) | if (ioctl(pcifd, PCIOCREAD, &pi) < 0) | ||||
return (0); /* XXX */ | return (0); /* XXX */ | ||||
else | else | ||||
return (pi.pi_data); | return (pi.pi_data); | ||||
} | } | ||||
static void | void | ||||
write_config(const struct pcisel *sel, long reg, int width, uint32_t data) | write_config(const struct pcisel *sel, long reg, int width, uint32_t data) | ||||
{ | { | ||||
if (pcifd < 0 && pcifd_init()) { | |||||
return; | |||||
} | |||||
struct pci_io pi; | struct pci_io pi; | ||||
bzero(&pi, sizeof(pi)); | bzero(&pi, sizeof(pi)); | ||||
pi.pi_sel = *sel; | pi.pi_sel = *sel; | ||||
pi.pi_reg = reg; | pi.pi_reg = reg; | ||||
pi.pi_width = width; | pi.pi_width = width; | ||||
pi.pi_data = data; | pi.pi_data = data; | ||||
▲ Show 20 Lines • Show All 488 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
static int | static int | ||||
passthru_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | 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; | const char *value; | ||||
#ifndef WITHOUT_CAPSICUM | |||||
cap_rights_t rights; | |||||
cap_ioctl_t pci_ioctls[] = | |||||
{ PCIOCREAD, PCIOCWRITE, PCIOCGETBAR, PCIOCBARIO, PCIOCBARMMAP }; | |||||
#endif | |||||
sc = NULL; | sc = NULL; | ||||
error = 1; | error = 1; | ||||
#ifndef WITHOUT_CAPSICUM | |||||
cap_rights_init(&rights, CAP_IOCTL, CAP_READ, CAP_WRITE); | |||||
#endif | |||||
memflags = vm_get_memflags(ctx); | memflags = vm_get_memflags(ctx); | ||||
if (!(memflags & VM_MEM_F_WIRED)) { | if (!(memflags & VM_MEM_F_WIRED)) { | ||||
warnx("passthru requires guest memory to be wired"); | warnx("passthru requires guest memory to be wired"); | ||||
return (error); | return (error); | ||||
} | } | ||||
if (pcifd < 0) { | if (pcifd < 0 && pcifd_init()) { | ||||
pcifd = open(_PATH_DEVPCI, O_RDWR, 0); | |||||
if (pcifd < 0) { | |||||
warn("failed to open %s", _PATH_DEVPCI); | |||||
return (error); | return (error); | ||||
} | } | ||||
} | |||||
#ifndef WITHOUT_CAPSICUM | |||||
if (caph_rights_limit(pcifd, &rights) == -1) | |||||
errx(EX_OSERR, "Unable to apply rights for sandbox"); | |||||
if (caph_ioctls_limit(pcifd, pci_ioctls, nitems(pci_ioctls)) == -1) | |||||
errx(EX_OSERR, "Unable to apply rights for sandbox"); | |||||
#endif | |||||
#define GET_INT_CONFIG(var, name) do { \ | #define GET_INT_CONFIG(var, name) do { \ | ||||
value = get_config_value_node(nvl, name); \ | value = get_config_value_node(nvl, name); \ | ||||
if (value == NULL) { \ | if (value == NULL) { \ | ||||
EPRINTLN("passthru: missing required %s setting", name); \ | EPRINTLN("passthru: missing required %s setting", name); \ | ||||
return (error); \ | return (error); \ | ||||
} \ | } \ | ||||
var = atoi(value); \ | var = atoi(value); \ | ||||
▲ Show 20 Lines • Show All 345 Lines • Show Last 20 Lines |