Changeset View
Changeset View
Standalone View
Standalone View
usr.sbin/bhyve/pci_virtio_9p.c
Show First 20 Lines • Show All 45 Lines • ▼ Show 20 Lines | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <assert.h> | #include <assert.h> | ||||
#include <pthread.h> | #include <pthread.h> | ||||
#include <lib9p.h> | #include <lib9p.h> | ||||
#include <backend/fs.h> | #include <backend/fs.h> | ||||
#include "bhyverun.h" | #include "bhyverun.h" | ||||
#include "config.h" | |||||
#include "debug.h" | |||||
#include "pci_emul.h" | #include "pci_emul.h" | ||||
#include "virtio.h" | #include "virtio.h" | ||||
#define VT9P_MAX_IOV 128 | #define VT9P_MAX_IOV 128 | ||||
#define VT9P_RINGSZ 256 | #define VT9P_RINGSZ 256 | ||||
#define VT9P_MAXTAGSZ 256 | #define VT9P_MAXTAGSZ 256 | ||||
#define VT9P_CONFIGSPACESZ (VT9P_MAXTAGSZ + sizeof(uint16_t)) | #define VT9P_CONFIGSPACESZ (VT9P_MAXTAGSZ + sizeof(uint16_t)) | ||||
▲ Show 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | for (int i = 0; i < n; i++) { | ||||
"len=%zu, flags=0x%04x\r\n", i, iov[i].iov_base, | "len=%zu, flags=0x%04x\r\n", i, iov[i].iov_base, | ||||
iov[i].iov_len, flags[i])); | iov[i].iov_len, flags[i])); | ||||
} | } | ||||
l9p_connection_recv(sc->vsc_conn, iov, preq->vsr_respidx, preq); | l9p_connection_recv(sc->vsc_conn, iov, preq->vsr_respidx, preq); | ||||
} | } | ||||
} | } | ||||
static int | |||||
pci_vt9p_legacy_config(nvlist_t *nvl, const char *opts) | |||||
{ | |||||
char *sharename, *tofree, *token, *tokens; | |||||
if (opts == NULL) | |||||
return (0); | |||||
tokens = tofree = strdup(opts); | |||||
while ((token = strsep(&tokens, ",")) != NULL) { | |||||
if (strchr(token, '=') != NULL) { | |||||
if (sharename != NULL) { | |||||
EPRINTLN( | |||||
"virtio-9p: more than one share name given"); | |||||
return (-1); | |||||
} | |||||
sharename = strsep(&token, "="); | |||||
set_config_value_node(nvl, "sharename", sharename); | |||||
set_config_value_node(nvl, "path", token); | |||||
} else | |||||
set_config_bool_node(nvl, token, true); | |||||
} | |||||
free(tofree); | |||||
return (0); | |||||
} | |||||
static int | static int | ||||
pci_vt9p_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) | pci_vt9p_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl) | ||||
{ | { | ||||
struct pci_vt9p_softc *sc; | struct pci_vt9p_softc *sc; | ||||
char *opt; | const char *value; | ||||
char *sharename = NULL; | const char *sharename; | ||||
char *rootpath = NULL; | |||||
int rootfd; | int rootfd; | ||||
bool ro = false; | bool ro; | ||||
cap_rights_t rootcap; | cap_rights_t rootcap; | ||||
if (opts == NULL) { | ro = get_config_bool_node_default(nvl, "ro", false); | ||||
printf("virtio-9p: share name and path required\n"); | |||||
return (1); | |||||
} | |||||
while ((opt = strsep(&opts, ",")) != NULL) { | value = get_config_value_node(nvl, "path"); | ||||
if (strchr(opt, '=') != NULL) { | if (value == NULL) { | ||||
if (sharename != NULL) { | EPRINTLN("virtio-9p: path required"); | ||||
printf("virtio-9p: more than one share name given\n"); | |||||
return (1); | return (1); | ||||
} | } | ||||
rootfd = open(value, O_DIRECTORY); | |||||
sharename = strsep(&opt, "="); | if (rootfd < 0) { | ||||
rootpath = opt; | EPRINTLN("virtio-9p: failed to open '%s': %s", value, | ||||
continue; | strerror(errno)); | ||||
return (-1); | |||||
} | } | ||||
if (strcmp(opt, "ro") == 0) { | sharename = get_config_value_node(nvl, "sharename"); | ||||
DPRINTF(("read-only mount requested\r\n")); | if (sharename == NULL) { | ||||
ro = true; | EPRINTLN("virtio-9p: share name required"); | ||||
continue; | |||||
} | |||||
printf("virtio-9p: invalid option '%s'\n", opt); | |||||
return (1); | return (1); | ||||
} | } | ||||
if (strlen(sharename) > VT9P_MAXTAGSZ) { | if (strlen(sharename) > VT9P_MAXTAGSZ) { | ||||
printf("virtio-9p: share name too long\n"); | EPRINTLN("virtio-9p: share name too long"); | ||||
return (1); | return (1); | ||||
} | } | ||||
rootfd = open(rootpath, O_DIRECTORY); | |||||
if (rootfd < 0) | |||||
return (-1); | |||||
sc = calloc(1, sizeof(struct pci_vt9p_softc)); | sc = calloc(1, sizeof(struct pci_vt9p_softc)); | ||||
sc->vsc_config = calloc(1, sizeof(struct pci_vt9p_config) + | sc->vsc_config = calloc(1, sizeof(struct pci_vt9p_config) + | ||||
VT9P_MAXTAGSZ); | VT9P_MAXTAGSZ); | ||||
pthread_mutex_init(&sc->vsc_mtx, NULL); | pthread_mutex_init(&sc->vsc_mtx, NULL); | ||||
cap_rights_init(&rootcap, | cap_rights_init(&rootcap, | ||||
CAP_LOOKUP, CAP_ACL_CHECK, CAP_ACL_DELETE, CAP_ACL_GET, | CAP_LOOKUP, CAP_ACL_CHECK, CAP_ACL_DELETE, CAP_ACL_GET, | ||||
▲ Show 20 Lines • Show All 46 Lines • ▼ Show 20 Lines | if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix())) | ||||
return (1); | return (1); | ||||
vi_set_io_bar(&sc->vsc_vs, 0); | vi_set_io_bar(&sc->vsc_vs, 0); | ||||
return (0); | return (0); | ||||
} | } | ||||
struct pci_devemu pci_de_v9p = { | struct pci_devemu pci_de_v9p = { | ||||
.pe_emu = "virtio-9p", | .pe_emu = "virtio-9p", | ||||
.pe_legacy_config = pci_vt9p_legacy_config, | |||||
.pe_init = pci_vt9p_init, | .pe_init = pci_vt9p_init, | ||||
.pe_barwrite = vi_pci_write, | .pe_barwrite = vi_pci_write, | ||||
.pe_barread = vi_pci_read | .pe_barread = vi_pci_read | ||||
}; | }; | ||||
PCI_EMUL_SET(pci_de_v9p); | PCI_EMUL_SET(pci_de_v9p); |