1*4c87aefeSPatrick Mooney /*- 2*4c87aefeSPatrick Mooney * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*4c87aefeSPatrick Mooney * 4*4c87aefeSPatrick Mooney * Copyright (c) 2016 iXsystems Inc. 5*4c87aefeSPatrick Mooney * All rights reserved. 6*4c87aefeSPatrick Mooney * 7*4c87aefeSPatrick Mooney * This software was developed by Jakub Klama <jceel@FreeBSD.org> 8*4c87aefeSPatrick Mooney * under sponsorship from iXsystems Inc. 9*4c87aefeSPatrick Mooney * 10*4c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without 11*4c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions 12*4c87aefeSPatrick Mooney * are met: 13*4c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright 14*4c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer 15*4c87aefeSPatrick Mooney * in this position and unchanged. 16*4c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright 17*4c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the 18*4c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution. 19*4c87aefeSPatrick Mooney * 20*4c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21*4c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*4c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*4c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24*4c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25*4c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26*4c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27*4c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28*4c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29*4c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30*4c87aefeSPatrick Mooney * SUCH DAMAGE. 31*4c87aefeSPatrick Mooney */ 32*4c87aefeSPatrick Mooney 33*4c87aefeSPatrick Mooney /* 34*4c87aefeSPatrick Mooney * Copyright 2018 Joyent, Inc. 35*4c87aefeSPatrick Mooney */ 36*4c87aefeSPatrick Mooney 37*4c87aefeSPatrick Mooney #include <sys/cdefs.h> 38*4c87aefeSPatrick Mooney __FBSDID("$FreeBSD$"); 39*4c87aefeSPatrick Mooney 40*4c87aefeSPatrick Mooney #include <sys/param.h> 41*4c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 42*4c87aefeSPatrick Mooney #include <sys/capsicum.h> 43*4c87aefeSPatrick Mooney #endif 44*4c87aefeSPatrick Mooney #include <sys/linker_set.h> 45*4c87aefeSPatrick Mooney #include <sys/uio.h> 46*4c87aefeSPatrick Mooney #include <sys/types.h> 47*4c87aefeSPatrick Mooney #include <sys/socket.h> 48*4c87aefeSPatrick Mooney #include <sys/un.h> 49*4c87aefeSPatrick Mooney 50*4c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 51*4c87aefeSPatrick Mooney #include <capsicum_helpers.h> 52*4c87aefeSPatrick Mooney #endif 53*4c87aefeSPatrick Mooney #include <err.h> 54*4c87aefeSPatrick Mooney #include <errno.h> 55*4c87aefeSPatrick Mooney #include <fcntl.h> 56*4c87aefeSPatrick Mooney #include <stdio.h> 57*4c87aefeSPatrick Mooney #include <stdlib.h> 58*4c87aefeSPatrick Mooney #include <stdbool.h> 59*4c87aefeSPatrick Mooney #include <string.h> 60*4c87aefeSPatrick Mooney #include <unistd.h> 61*4c87aefeSPatrick Mooney #include <assert.h> 62*4c87aefeSPatrick Mooney #include <pthread.h> 63*4c87aefeSPatrick Mooney #include <libgen.h> 64*4c87aefeSPatrick Mooney #include <sysexits.h> 65*4c87aefeSPatrick Mooney 66*4c87aefeSPatrick Mooney #include "bhyverun.h" 67*4c87aefeSPatrick Mooney #include "pci_emul.h" 68*4c87aefeSPatrick Mooney #include "virtio.h" 69*4c87aefeSPatrick Mooney #include "mevent.h" 70*4c87aefeSPatrick Mooney #include "sockstream.h" 71*4c87aefeSPatrick Mooney 72*4c87aefeSPatrick Mooney #define VTCON_RINGSZ 64 73*4c87aefeSPatrick Mooney #define VTCON_MAXPORTS 16 74*4c87aefeSPatrick Mooney #define VTCON_MAXQ (VTCON_MAXPORTS * 2 + 2) 75*4c87aefeSPatrick Mooney 76*4c87aefeSPatrick Mooney #define VTCON_DEVICE_READY 0 77*4c87aefeSPatrick Mooney #define VTCON_DEVICE_ADD 1 78*4c87aefeSPatrick Mooney #define VTCON_DEVICE_REMOVE 2 79*4c87aefeSPatrick Mooney #define VTCON_PORT_READY 3 80*4c87aefeSPatrick Mooney #define VTCON_CONSOLE_PORT 4 81*4c87aefeSPatrick Mooney #define VTCON_CONSOLE_RESIZE 5 82*4c87aefeSPatrick Mooney #define VTCON_PORT_OPEN 6 83*4c87aefeSPatrick Mooney #define VTCON_PORT_NAME 7 84*4c87aefeSPatrick Mooney 85*4c87aefeSPatrick Mooney #define VTCON_F_SIZE 0 86*4c87aefeSPatrick Mooney #define VTCON_F_MULTIPORT 1 87*4c87aefeSPatrick Mooney #define VTCON_F_EMERG_WRITE 2 88*4c87aefeSPatrick Mooney #define VTCON_S_HOSTCAPS \ 89*4c87aefeSPatrick Mooney (VTCON_F_SIZE | VTCON_F_MULTIPORT | VTCON_F_EMERG_WRITE) 90*4c87aefeSPatrick Mooney 91*4c87aefeSPatrick Mooney static int pci_vtcon_debug; 92*4c87aefeSPatrick Mooney #define DPRINTF(params) if (pci_vtcon_debug) printf params 93*4c87aefeSPatrick Mooney #define WPRINTF(params) printf params 94*4c87aefeSPatrick Mooney 95*4c87aefeSPatrick Mooney struct pci_vtcon_softc; 96*4c87aefeSPatrick Mooney struct pci_vtcon_port; 97*4c87aefeSPatrick Mooney struct pci_vtcon_config; 98*4c87aefeSPatrick Mooney typedef void (pci_vtcon_cb_t)(struct pci_vtcon_port *, void *, struct iovec *, 99*4c87aefeSPatrick Mooney int); 100*4c87aefeSPatrick Mooney 101*4c87aefeSPatrick Mooney struct pci_vtcon_port { 102*4c87aefeSPatrick Mooney struct pci_vtcon_softc * vsp_sc; 103*4c87aefeSPatrick Mooney int vsp_id; 104*4c87aefeSPatrick Mooney const char * vsp_name; 105*4c87aefeSPatrick Mooney bool vsp_enabled; 106*4c87aefeSPatrick Mooney bool vsp_console; 107*4c87aefeSPatrick Mooney bool vsp_rx_ready; 108*4c87aefeSPatrick Mooney bool vsp_open; 109*4c87aefeSPatrick Mooney int vsp_rxq; 110*4c87aefeSPatrick Mooney int vsp_txq; 111*4c87aefeSPatrick Mooney void * vsp_arg; 112*4c87aefeSPatrick Mooney pci_vtcon_cb_t * vsp_cb; 113*4c87aefeSPatrick Mooney }; 114*4c87aefeSPatrick Mooney 115*4c87aefeSPatrick Mooney struct pci_vtcon_sock 116*4c87aefeSPatrick Mooney { 117*4c87aefeSPatrick Mooney struct pci_vtcon_port * vss_port; 118*4c87aefeSPatrick Mooney const char * vss_path; 119*4c87aefeSPatrick Mooney struct mevent * vss_server_evp; 120*4c87aefeSPatrick Mooney struct mevent * vss_conn_evp; 121*4c87aefeSPatrick Mooney int vss_server_fd; 122*4c87aefeSPatrick Mooney int vss_conn_fd; 123*4c87aefeSPatrick Mooney bool vss_open; 124*4c87aefeSPatrick Mooney }; 125*4c87aefeSPatrick Mooney 126*4c87aefeSPatrick Mooney struct pci_vtcon_softc { 127*4c87aefeSPatrick Mooney struct virtio_softc vsc_vs; 128*4c87aefeSPatrick Mooney struct vqueue_info vsc_queues[VTCON_MAXQ]; 129*4c87aefeSPatrick Mooney pthread_mutex_t vsc_mtx; 130*4c87aefeSPatrick Mooney uint64_t vsc_cfg; 131*4c87aefeSPatrick Mooney uint64_t vsc_features; 132*4c87aefeSPatrick Mooney char * vsc_rootdir; 133*4c87aefeSPatrick Mooney int vsc_kq; 134*4c87aefeSPatrick Mooney int vsc_nports; 135*4c87aefeSPatrick Mooney bool vsc_ready; 136*4c87aefeSPatrick Mooney struct pci_vtcon_port vsc_control_port; 137*4c87aefeSPatrick Mooney struct pci_vtcon_port vsc_ports[VTCON_MAXPORTS]; 138*4c87aefeSPatrick Mooney struct pci_vtcon_config *vsc_config; 139*4c87aefeSPatrick Mooney }; 140*4c87aefeSPatrick Mooney 141*4c87aefeSPatrick Mooney struct pci_vtcon_config { 142*4c87aefeSPatrick Mooney uint16_t cols; 143*4c87aefeSPatrick Mooney uint16_t rows; 144*4c87aefeSPatrick Mooney uint32_t max_nr_ports; 145*4c87aefeSPatrick Mooney uint32_t emerg_wr; 146*4c87aefeSPatrick Mooney } __attribute__((packed)); 147*4c87aefeSPatrick Mooney 148*4c87aefeSPatrick Mooney struct pci_vtcon_control { 149*4c87aefeSPatrick Mooney uint32_t id; 150*4c87aefeSPatrick Mooney uint16_t event; 151*4c87aefeSPatrick Mooney uint16_t value; 152*4c87aefeSPatrick Mooney } __attribute__((packed)); 153*4c87aefeSPatrick Mooney 154*4c87aefeSPatrick Mooney struct pci_vtcon_console_resize { 155*4c87aefeSPatrick Mooney uint16_t cols; 156*4c87aefeSPatrick Mooney uint16_t rows; 157*4c87aefeSPatrick Mooney } __attribute__((packed)); 158*4c87aefeSPatrick Mooney 159*4c87aefeSPatrick Mooney static void pci_vtcon_reset(void *); 160*4c87aefeSPatrick Mooney static void pci_vtcon_notify_rx(void *, struct vqueue_info *); 161*4c87aefeSPatrick Mooney static void pci_vtcon_notify_tx(void *, struct vqueue_info *); 162*4c87aefeSPatrick Mooney static int pci_vtcon_cfgread(void *, int, int, uint32_t *); 163*4c87aefeSPatrick Mooney static int pci_vtcon_cfgwrite(void *, int, int, uint32_t); 164*4c87aefeSPatrick Mooney static void pci_vtcon_neg_features(void *, uint64_t); 165*4c87aefeSPatrick Mooney static void pci_vtcon_sock_accept(int, enum ev_type, void *); 166*4c87aefeSPatrick Mooney static void pci_vtcon_sock_rx(int, enum ev_type, void *); 167*4c87aefeSPatrick Mooney static void pci_vtcon_sock_tx(struct pci_vtcon_port *, void *, struct iovec *, 168*4c87aefeSPatrick Mooney int); 169*4c87aefeSPatrick Mooney static void pci_vtcon_control_send(struct pci_vtcon_softc *, 170*4c87aefeSPatrick Mooney struct pci_vtcon_control *, const void *, size_t); 171*4c87aefeSPatrick Mooney static void pci_vtcon_announce_port(struct pci_vtcon_port *); 172*4c87aefeSPatrick Mooney static void pci_vtcon_open_port(struct pci_vtcon_port *, bool); 173*4c87aefeSPatrick Mooney 174*4c87aefeSPatrick Mooney static struct virtio_consts vtcon_vi_consts = { 175*4c87aefeSPatrick Mooney "vtcon", /* our name */ 176*4c87aefeSPatrick Mooney VTCON_MAXQ, /* we support VTCON_MAXQ virtqueues */ 177*4c87aefeSPatrick Mooney sizeof(struct pci_vtcon_config), /* config reg size */ 178*4c87aefeSPatrick Mooney pci_vtcon_reset, /* reset */ 179*4c87aefeSPatrick Mooney NULL, /* device-wide qnotify */ 180*4c87aefeSPatrick Mooney pci_vtcon_cfgread, /* read virtio config */ 181*4c87aefeSPatrick Mooney pci_vtcon_cfgwrite, /* write virtio config */ 182*4c87aefeSPatrick Mooney pci_vtcon_neg_features, /* apply negotiated features */ 183*4c87aefeSPatrick Mooney VTCON_S_HOSTCAPS, /* our capabilities */ 184*4c87aefeSPatrick Mooney }; 185*4c87aefeSPatrick Mooney 186*4c87aefeSPatrick Mooney 187*4c87aefeSPatrick Mooney static void 188*4c87aefeSPatrick Mooney pci_vtcon_reset(void *vsc) 189*4c87aefeSPatrick Mooney { 190*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc; 191*4c87aefeSPatrick Mooney 192*4c87aefeSPatrick Mooney sc = vsc; 193*4c87aefeSPatrick Mooney 194*4c87aefeSPatrick Mooney DPRINTF(("vtcon: device reset requested!\n")); 195*4c87aefeSPatrick Mooney vi_reset_dev(&sc->vsc_vs); 196*4c87aefeSPatrick Mooney } 197*4c87aefeSPatrick Mooney 198*4c87aefeSPatrick Mooney static void 199*4c87aefeSPatrick Mooney pci_vtcon_neg_features(void *vsc, uint64_t negotiated_features) 200*4c87aefeSPatrick Mooney { 201*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc = vsc; 202*4c87aefeSPatrick Mooney 203*4c87aefeSPatrick Mooney sc->vsc_features = negotiated_features; 204*4c87aefeSPatrick Mooney } 205*4c87aefeSPatrick Mooney 206*4c87aefeSPatrick Mooney static int 207*4c87aefeSPatrick Mooney pci_vtcon_cfgread(void *vsc, int offset, int size, uint32_t *retval) 208*4c87aefeSPatrick Mooney { 209*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc = vsc; 210*4c87aefeSPatrick Mooney void *ptr; 211*4c87aefeSPatrick Mooney 212*4c87aefeSPatrick Mooney ptr = (uint8_t *)sc->vsc_config + offset; 213*4c87aefeSPatrick Mooney memcpy(retval, ptr, size); 214*4c87aefeSPatrick Mooney return (0); 215*4c87aefeSPatrick Mooney } 216*4c87aefeSPatrick Mooney 217*4c87aefeSPatrick Mooney static int 218*4c87aefeSPatrick Mooney pci_vtcon_cfgwrite(void *vsc, int offset, int size, uint32_t val) 219*4c87aefeSPatrick Mooney { 220*4c87aefeSPatrick Mooney 221*4c87aefeSPatrick Mooney return (0); 222*4c87aefeSPatrick Mooney } 223*4c87aefeSPatrick Mooney 224*4c87aefeSPatrick Mooney static inline struct pci_vtcon_port * 225*4c87aefeSPatrick Mooney pci_vtcon_vq_to_port(struct pci_vtcon_softc *sc, struct vqueue_info *vq) 226*4c87aefeSPatrick Mooney { 227*4c87aefeSPatrick Mooney uint16_t num = vq->vq_num; 228*4c87aefeSPatrick Mooney 229*4c87aefeSPatrick Mooney if (num == 0 || num == 1) 230*4c87aefeSPatrick Mooney return (&sc->vsc_ports[0]); 231*4c87aefeSPatrick Mooney 232*4c87aefeSPatrick Mooney if (num == 2 || num == 3) 233*4c87aefeSPatrick Mooney return (&sc->vsc_control_port); 234*4c87aefeSPatrick Mooney 235*4c87aefeSPatrick Mooney return (&sc->vsc_ports[(num / 2) - 1]); 236*4c87aefeSPatrick Mooney } 237*4c87aefeSPatrick Mooney 238*4c87aefeSPatrick Mooney static inline struct vqueue_info * 239*4c87aefeSPatrick Mooney pci_vtcon_port_to_vq(struct pci_vtcon_port *port, bool tx_queue) 240*4c87aefeSPatrick Mooney { 241*4c87aefeSPatrick Mooney int qnum; 242*4c87aefeSPatrick Mooney 243*4c87aefeSPatrick Mooney qnum = tx_queue ? port->vsp_txq : port->vsp_rxq; 244*4c87aefeSPatrick Mooney return (&port->vsp_sc->vsc_queues[qnum]); 245*4c87aefeSPatrick Mooney } 246*4c87aefeSPatrick Mooney 247*4c87aefeSPatrick Mooney static struct pci_vtcon_port * 248*4c87aefeSPatrick Mooney pci_vtcon_port_add(struct pci_vtcon_softc *sc, const char *name, 249*4c87aefeSPatrick Mooney pci_vtcon_cb_t *cb, void *arg) 250*4c87aefeSPatrick Mooney { 251*4c87aefeSPatrick Mooney struct pci_vtcon_port *port; 252*4c87aefeSPatrick Mooney 253*4c87aefeSPatrick Mooney if (sc->vsc_nports == VTCON_MAXPORTS) { 254*4c87aefeSPatrick Mooney errno = EBUSY; 255*4c87aefeSPatrick Mooney return (NULL); 256*4c87aefeSPatrick Mooney } 257*4c87aefeSPatrick Mooney 258*4c87aefeSPatrick Mooney port = &sc->vsc_ports[sc->vsc_nports++]; 259*4c87aefeSPatrick Mooney port->vsp_id = sc->vsc_nports - 1; 260*4c87aefeSPatrick Mooney port->vsp_sc = sc; 261*4c87aefeSPatrick Mooney port->vsp_name = name; 262*4c87aefeSPatrick Mooney port->vsp_cb = cb; 263*4c87aefeSPatrick Mooney port->vsp_arg = arg; 264*4c87aefeSPatrick Mooney 265*4c87aefeSPatrick Mooney if (port->vsp_id == 0) { 266*4c87aefeSPatrick Mooney /* port0 */ 267*4c87aefeSPatrick Mooney port->vsp_txq = 0; 268*4c87aefeSPatrick Mooney port->vsp_rxq = 1; 269*4c87aefeSPatrick Mooney } else { 270*4c87aefeSPatrick Mooney port->vsp_txq = sc->vsc_nports * 2; 271*4c87aefeSPatrick Mooney port->vsp_rxq = port->vsp_txq + 1; 272*4c87aefeSPatrick Mooney } 273*4c87aefeSPatrick Mooney 274*4c87aefeSPatrick Mooney port->vsp_enabled = true; 275*4c87aefeSPatrick Mooney return (port); 276*4c87aefeSPatrick Mooney } 277*4c87aefeSPatrick Mooney 278*4c87aefeSPatrick Mooney static int 279*4c87aefeSPatrick Mooney pci_vtcon_sock_add(struct pci_vtcon_softc *sc, const char *name, 280*4c87aefeSPatrick Mooney const char *path) 281*4c87aefeSPatrick Mooney { 282*4c87aefeSPatrick Mooney struct pci_vtcon_sock *sock; 283*4c87aefeSPatrick Mooney #ifdef __FreeBSD__ 284*4c87aefeSPatrick Mooney struct sockaddr_un sun; 285*4c87aefeSPatrick Mooney char *pathcopy; 286*4c87aefeSPatrick Mooney #else 287*4c87aefeSPatrick Mooney /* Our compiler #defines 'sun' as '1'. Awesome. */ 288*4c87aefeSPatrick Mooney struct sockaddr_un addr; 289*4c87aefeSPatrick Mooney #endif 290*4c87aefeSPatrick Mooney int s = -1, fd = -1, error = 0; 291*4c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 292*4c87aefeSPatrick Mooney cap_rights_t rights; 293*4c87aefeSPatrick Mooney #endif 294*4c87aefeSPatrick Mooney 295*4c87aefeSPatrick Mooney sock = calloc(1, sizeof(struct pci_vtcon_sock)); 296*4c87aefeSPatrick Mooney if (sock == NULL) { 297*4c87aefeSPatrick Mooney error = -1; 298*4c87aefeSPatrick Mooney goto out; 299*4c87aefeSPatrick Mooney } 300*4c87aefeSPatrick Mooney 301*4c87aefeSPatrick Mooney s = socket(AF_UNIX, SOCK_STREAM, 0); 302*4c87aefeSPatrick Mooney if (s < 0) { 303*4c87aefeSPatrick Mooney error = -1; 304*4c87aefeSPatrick Mooney goto out; 305*4c87aefeSPatrick Mooney } 306*4c87aefeSPatrick Mooney 307*4c87aefeSPatrick Mooney #ifdef __FreeBSD__ 308*4c87aefeSPatrick Mooney pathcopy = strdup(path); 309*4c87aefeSPatrick Mooney if (pathcopy == NULL) { 310*4c87aefeSPatrick Mooney error = -1; 311*4c87aefeSPatrick Mooney goto out; 312*4c87aefeSPatrick Mooney } 313*4c87aefeSPatrick Mooney 314*4c87aefeSPatrick Mooney fd = open(dirname(pathcopy), O_RDONLY | O_DIRECTORY); 315*4c87aefeSPatrick Mooney if (fd < 0) { 316*4c87aefeSPatrick Mooney free(pathcopy); 317*4c87aefeSPatrick Mooney error = -1; 318*4c87aefeSPatrick Mooney goto out; 319*4c87aefeSPatrick Mooney } 320*4c87aefeSPatrick Mooney 321*4c87aefeSPatrick Mooney sun.sun_family = AF_UNIX; 322*4c87aefeSPatrick Mooney sun.sun_len = sizeof(struct sockaddr_un); 323*4c87aefeSPatrick Mooney strcpy(pathcopy, path); 324*4c87aefeSPatrick Mooney strlcpy(sun.sun_path, basename(pathcopy), sizeof(sun.sun_path)); 325*4c87aefeSPatrick Mooney free(pathcopy); 326*4c87aefeSPatrick Mooney 327*4c87aefeSPatrick Mooney if (bindat(fd, s, (struct sockaddr *)&sun, sun.sun_len) < 0) { 328*4c87aefeSPatrick Mooney error = -1; 329*4c87aefeSPatrick Mooney goto out; 330*4c87aefeSPatrick Mooney } 331*4c87aefeSPatrick Mooney #else /* __FreeBSD__ */ 332*4c87aefeSPatrick Mooney /* Do a simple bind rather than the FreeBSD bindat() */ 333*4c87aefeSPatrick Mooney addr.sun_family = AF_UNIX; 334*4c87aefeSPatrick Mooney (void) strlcpy(addr.sun_path, path, sizeof (addr.sun_path)); 335*4c87aefeSPatrick Mooney if (bind(fd, (struct sockaddr *)&addr, sizeof (addr)) < 0) { 336*4c87aefeSPatrick Mooney error = -1; 337*4c87aefeSPatrick Mooney goto out; 338*4c87aefeSPatrick Mooney } 339*4c87aefeSPatrick Mooney #endif /* __FreeBSD__ */ 340*4c87aefeSPatrick Mooney 341*4c87aefeSPatrick Mooney if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) { 342*4c87aefeSPatrick Mooney error = -1; 343*4c87aefeSPatrick Mooney goto out; 344*4c87aefeSPatrick Mooney } 345*4c87aefeSPatrick Mooney 346*4c87aefeSPatrick Mooney if (listen(s, 1) < 0) { 347*4c87aefeSPatrick Mooney error = -1; 348*4c87aefeSPatrick Mooney goto out; 349*4c87aefeSPatrick Mooney } 350*4c87aefeSPatrick Mooney 351*4c87aefeSPatrick Mooney #ifndef WITHOUT_CAPSICUM 352*4c87aefeSPatrick Mooney cap_rights_init(&rights, CAP_ACCEPT, CAP_EVENT, CAP_READ, CAP_WRITE); 353*4c87aefeSPatrick Mooney if (caph_rights_limit(s, &rights) == -1) 354*4c87aefeSPatrick Mooney errx(EX_OSERR, "Unable to apply rights for sandbox"); 355*4c87aefeSPatrick Mooney #endif 356*4c87aefeSPatrick Mooney 357*4c87aefeSPatrick Mooney sock->vss_port = pci_vtcon_port_add(sc, name, pci_vtcon_sock_tx, sock); 358*4c87aefeSPatrick Mooney if (sock->vss_port == NULL) { 359*4c87aefeSPatrick Mooney error = -1; 360*4c87aefeSPatrick Mooney goto out; 361*4c87aefeSPatrick Mooney } 362*4c87aefeSPatrick Mooney 363*4c87aefeSPatrick Mooney sock->vss_open = false; 364*4c87aefeSPatrick Mooney sock->vss_conn_fd = -1; 365*4c87aefeSPatrick Mooney sock->vss_server_fd = s; 366*4c87aefeSPatrick Mooney sock->vss_server_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_accept, 367*4c87aefeSPatrick Mooney sock); 368*4c87aefeSPatrick Mooney 369*4c87aefeSPatrick Mooney if (sock->vss_server_evp == NULL) { 370*4c87aefeSPatrick Mooney error = -1; 371*4c87aefeSPatrick Mooney goto out; 372*4c87aefeSPatrick Mooney } 373*4c87aefeSPatrick Mooney 374*4c87aefeSPatrick Mooney out: 375*4c87aefeSPatrick Mooney if (fd != -1) 376*4c87aefeSPatrick Mooney close(fd); 377*4c87aefeSPatrick Mooney 378*4c87aefeSPatrick Mooney if (error != 0 && s != -1) 379*4c87aefeSPatrick Mooney close(s); 380*4c87aefeSPatrick Mooney 381*4c87aefeSPatrick Mooney return (error); 382*4c87aefeSPatrick Mooney } 383*4c87aefeSPatrick Mooney 384*4c87aefeSPatrick Mooney static void 385*4c87aefeSPatrick Mooney pci_vtcon_sock_accept(int fd __unused, enum ev_type t __unused, void *arg) 386*4c87aefeSPatrick Mooney { 387*4c87aefeSPatrick Mooney struct pci_vtcon_sock *sock = (struct pci_vtcon_sock *)arg; 388*4c87aefeSPatrick Mooney int s; 389*4c87aefeSPatrick Mooney 390*4c87aefeSPatrick Mooney s = accept(sock->vss_server_fd, NULL, NULL); 391*4c87aefeSPatrick Mooney if (s < 0) 392*4c87aefeSPatrick Mooney return; 393*4c87aefeSPatrick Mooney 394*4c87aefeSPatrick Mooney if (sock->vss_open) { 395*4c87aefeSPatrick Mooney close(s); 396*4c87aefeSPatrick Mooney return; 397*4c87aefeSPatrick Mooney } 398*4c87aefeSPatrick Mooney 399*4c87aefeSPatrick Mooney sock->vss_open = true; 400*4c87aefeSPatrick Mooney sock->vss_conn_fd = s; 401*4c87aefeSPatrick Mooney sock->vss_conn_evp = mevent_add(s, EVF_READ, pci_vtcon_sock_rx, sock); 402*4c87aefeSPatrick Mooney 403*4c87aefeSPatrick Mooney pci_vtcon_open_port(sock->vss_port, true); 404*4c87aefeSPatrick Mooney } 405*4c87aefeSPatrick Mooney 406*4c87aefeSPatrick Mooney static void 407*4c87aefeSPatrick Mooney pci_vtcon_sock_rx(int fd __unused, enum ev_type t __unused, void *arg) 408*4c87aefeSPatrick Mooney { 409*4c87aefeSPatrick Mooney struct pci_vtcon_port *port; 410*4c87aefeSPatrick Mooney struct pci_vtcon_sock *sock = (struct pci_vtcon_sock *)arg; 411*4c87aefeSPatrick Mooney struct vqueue_info *vq; 412*4c87aefeSPatrick Mooney struct iovec iov; 413*4c87aefeSPatrick Mooney static char dummybuf[2048]; 414*4c87aefeSPatrick Mooney int len, n; 415*4c87aefeSPatrick Mooney uint16_t idx; 416*4c87aefeSPatrick Mooney 417*4c87aefeSPatrick Mooney port = sock->vss_port; 418*4c87aefeSPatrick Mooney vq = pci_vtcon_port_to_vq(port, true); 419*4c87aefeSPatrick Mooney 420*4c87aefeSPatrick Mooney if (!sock->vss_open || !port->vsp_rx_ready) { 421*4c87aefeSPatrick Mooney len = read(sock->vss_conn_fd, dummybuf, sizeof(dummybuf)); 422*4c87aefeSPatrick Mooney if (len == 0) 423*4c87aefeSPatrick Mooney goto close; 424*4c87aefeSPatrick Mooney 425*4c87aefeSPatrick Mooney return; 426*4c87aefeSPatrick Mooney } 427*4c87aefeSPatrick Mooney 428*4c87aefeSPatrick Mooney if (!vq_has_descs(vq)) { 429*4c87aefeSPatrick Mooney len = read(sock->vss_conn_fd, dummybuf, sizeof(dummybuf)); 430*4c87aefeSPatrick Mooney vq_endchains(vq, 1); 431*4c87aefeSPatrick Mooney if (len == 0) 432*4c87aefeSPatrick Mooney goto close; 433*4c87aefeSPatrick Mooney 434*4c87aefeSPatrick Mooney return; 435*4c87aefeSPatrick Mooney } 436*4c87aefeSPatrick Mooney 437*4c87aefeSPatrick Mooney do { 438*4c87aefeSPatrick Mooney n = vq_getchain(vq, &idx, &iov, 1, NULL); 439*4c87aefeSPatrick Mooney len = readv(sock->vss_conn_fd, &iov, n); 440*4c87aefeSPatrick Mooney 441*4c87aefeSPatrick Mooney if (len == 0 || (len < 0 && errno == EWOULDBLOCK)) { 442*4c87aefeSPatrick Mooney vq_retchain(vq); 443*4c87aefeSPatrick Mooney vq_endchains(vq, 0); 444*4c87aefeSPatrick Mooney if (len == 0) 445*4c87aefeSPatrick Mooney goto close; 446*4c87aefeSPatrick Mooney 447*4c87aefeSPatrick Mooney return; 448*4c87aefeSPatrick Mooney } 449*4c87aefeSPatrick Mooney 450*4c87aefeSPatrick Mooney vq_relchain(vq, idx, len); 451*4c87aefeSPatrick Mooney } while (vq_has_descs(vq)); 452*4c87aefeSPatrick Mooney 453*4c87aefeSPatrick Mooney vq_endchains(vq, 1); 454*4c87aefeSPatrick Mooney 455*4c87aefeSPatrick Mooney close: 456*4c87aefeSPatrick Mooney mevent_delete_close(sock->vss_conn_evp); 457*4c87aefeSPatrick Mooney sock->vss_conn_fd = -1; 458*4c87aefeSPatrick Mooney sock->vss_open = false; 459*4c87aefeSPatrick Mooney } 460*4c87aefeSPatrick Mooney 461*4c87aefeSPatrick Mooney static void 462*4c87aefeSPatrick Mooney pci_vtcon_sock_tx(struct pci_vtcon_port *port, void *arg, struct iovec *iov, 463*4c87aefeSPatrick Mooney int niov) 464*4c87aefeSPatrick Mooney { 465*4c87aefeSPatrick Mooney struct pci_vtcon_sock *sock; 466*4c87aefeSPatrick Mooney #ifdef __FreeBSD__ 467*4c87aefeSPatrick Mooney int i, ret; 468*4c87aefeSPatrick Mooney #else 469*4c87aefeSPatrick Mooney int i, ret = 0; 470*4c87aefeSPatrick Mooney #endif 471*4c87aefeSPatrick Mooney 472*4c87aefeSPatrick Mooney sock = (struct pci_vtcon_sock *)arg; 473*4c87aefeSPatrick Mooney 474*4c87aefeSPatrick Mooney if (sock->vss_conn_fd == -1) 475*4c87aefeSPatrick Mooney return; 476*4c87aefeSPatrick Mooney 477*4c87aefeSPatrick Mooney for (i = 0; i < niov; i++) { 478*4c87aefeSPatrick Mooney ret = stream_write(sock->vss_conn_fd, iov[i].iov_base, 479*4c87aefeSPatrick Mooney iov[i].iov_len); 480*4c87aefeSPatrick Mooney if (ret <= 0) 481*4c87aefeSPatrick Mooney break; 482*4c87aefeSPatrick Mooney } 483*4c87aefeSPatrick Mooney 484*4c87aefeSPatrick Mooney if (ret <= 0) { 485*4c87aefeSPatrick Mooney mevent_delete_close(sock->vss_conn_evp); 486*4c87aefeSPatrick Mooney sock->vss_conn_fd = -1; 487*4c87aefeSPatrick Mooney sock->vss_open = false; 488*4c87aefeSPatrick Mooney } 489*4c87aefeSPatrick Mooney } 490*4c87aefeSPatrick Mooney 491*4c87aefeSPatrick Mooney static void 492*4c87aefeSPatrick Mooney pci_vtcon_control_tx(struct pci_vtcon_port *port, void *arg, struct iovec *iov, 493*4c87aefeSPatrick Mooney int niov) 494*4c87aefeSPatrick Mooney { 495*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc; 496*4c87aefeSPatrick Mooney struct pci_vtcon_port *tmp; 497*4c87aefeSPatrick Mooney struct pci_vtcon_control resp, *ctrl; 498*4c87aefeSPatrick Mooney int i; 499*4c87aefeSPatrick Mooney 500*4c87aefeSPatrick Mooney assert(niov == 1); 501*4c87aefeSPatrick Mooney 502*4c87aefeSPatrick Mooney sc = port->vsp_sc; 503*4c87aefeSPatrick Mooney ctrl = (struct pci_vtcon_control *)iov->iov_base; 504*4c87aefeSPatrick Mooney 505*4c87aefeSPatrick Mooney switch (ctrl->event) { 506*4c87aefeSPatrick Mooney case VTCON_DEVICE_READY: 507*4c87aefeSPatrick Mooney sc->vsc_ready = true; 508*4c87aefeSPatrick Mooney /* set port ready events for registered ports */ 509*4c87aefeSPatrick Mooney for (i = 0; i < VTCON_MAXPORTS; i++) { 510*4c87aefeSPatrick Mooney tmp = &sc->vsc_ports[i]; 511*4c87aefeSPatrick Mooney if (tmp->vsp_enabled) 512*4c87aefeSPatrick Mooney pci_vtcon_announce_port(tmp); 513*4c87aefeSPatrick Mooney 514*4c87aefeSPatrick Mooney if (tmp->vsp_open) 515*4c87aefeSPatrick Mooney pci_vtcon_open_port(tmp, true); 516*4c87aefeSPatrick Mooney } 517*4c87aefeSPatrick Mooney break; 518*4c87aefeSPatrick Mooney 519*4c87aefeSPatrick Mooney case VTCON_PORT_READY: 520*4c87aefeSPatrick Mooney if (ctrl->id >= sc->vsc_nports) { 521*4c87aefeSPatrick Mooney WPRINTF(("VTCON_PORT_READY event for unknown port %d\n", 522*4c87aefeSPatrick Mooney ctrl->id)); 523*4c87aefeSPatrick Mooney return; 524*4c87aefeSPatrick Mooney } 525*4c87aefeSPatrick Mooney 526*4c87aefeSPatrick Mooney tmp = &sc->vsc_ports[ctrl->id]; 527*4c87aefeSPatrick Mooney if (tmp->vsp_console) { 528*4c87aefeSPatrick Mooney resp.event = VTCON_CONSOLE_PORT; 529*4c87aefeSPatrick Mooney resp.id = ctrl->id; 530*4c87aefeSPatrick Mooney resp.value = 1; 531*4c87aefeSPatrick Mooney pci_vtcon_control_send(sc, &resp, NULL, 0); 532*4c87aefeSPatrick Mooney } 533*4c87aefeSPatrick Mooney break; 534*4c87aefeSPatrick Mooney } 535*4c87aefeSPatrick Mooney } 536*4c87aefeSPatrick Mooney 537*4c87aefeSPatrick Mooney static void 538*4c87aefeSPatrick Mooney pci_vtcon_announce_port(struct pci_vtcon_port *port) 539*4c87aefeSPatrick Mooney { 540*4c87aefeSPatrick Mooney struct pci_vtcon_control event; 541*4c87aefeSPatrick Mooney 542*4c87aefeSPatrick Mooney event.id = port->vsp_id; 543*4c87aefeSPatrick Mooney event.event = VTCON_DEVICE_ADD; 544*4c87aefeSPatrick Mooney event.value = 1; 545*4c87aefeSPatrick Mooney pci_vtcon_control_send(port->vsp_sc, &event, NULL, 0); 546*4c87aefeSPatrick Mooney 547*4c87aefeSPatrick Mooney event.event = VTCON_PORT_NAME; 548*4c87aefeSPatrick Mooney pci_vtcon_control_send(port->vsp_sc, &event, port->vsp_name, 549*4c87aefeSPatrick Mooney strlen(port->vsp_name)); 550*4c87aefeSPatrick Mooney } 551*4c87aefeSPatrick Mooney 552*4c87aefeSPatrick Mooney static void 553*4c87aefeSPatrick Mooney pci_vtcon_open_port(struct pci_vtcon_port *port, bool open) 554*4c87aefeSPatrick Mooney { 555*4c87aefeSPatrick Mooney struct pci_vtcon_control event; 556*4c87aefeSPatrick Mooney 557*4c87aefeSPatrick Mooney if (!port->vsp_sc->vsc_ready) { 558*4c87aefeSPatrick Mooney port->vsp_open = true; 559*4c87aefeSPatrick Mooney return; 560*4c87aefeSPatrick Mooney } 561*4c87aefeSPatrick Mooney 562*4c87aefeSPatrick Mooney event.id = port->vsp_id; 563*4c87aefeSPatrick Mooney event.event = VTCON_PORT_OPEN; 564*4c87aefeSPatrick Mooney event.value = (int)open; 565*4c87aefeSPatrick Mooney pci_vtcon_control_send(port->vsp_sc, &event, NULL, 0); 566*4c87aefeSPatrick Mooney } 567*4c87aefeSPatrick Mooney 568*4c87aefeSPatrick Mooney static void 569*4c87aefeSPatrick Mooney pci_vtcon_control_send(struct pci_vtcon_softc *sc, 570*4c87aefeSPatrick Mooney struct pci_vtcon_control *ctrl, const void *payload, size_t len) 571*4c87aefeSPatrick Mooney { 572*4c87aefeSPatrick Mooney struct vqueue_info *vq; 573*4c87aefeSPatrick Mooney struct iovec iov; 574*4c87aefeSPatrick Mooney uint16_t idx; 575*4c87aefeSPatrick Mooney int n; 576*4c87aefeSPatrick Mooney 577*4c87aefeSPatrick Mooney vq = pci_vtcon_port_to_vq(&sc->vsc_control_port, true); 578*4c87aefeSPatrick Mooney 579*4c87aefeSPatrick Mooney if (!vq_has_descs(vq)) 580*4c87aefeSPatrick Mooney return; 581*4c87aefeSPatrick Mooney 582*4c87aefeSPatrick Mooney n = vq_getchain(vq, &idx, &iov, 1, NULL); 583*4c87aefeSPatrick Mooney 584*4c87aefeSPatrick Mooney assert(n == 1); 585*4c87aefeSPatrick Mooney 586*4c87aefeSPatrick Mooney memcpy(iov.iov_base, ctrl, sizeof(struct pci_vtcon_control)); 587*4c87aefeSPatrick Mooney if (payload != NULL && len > 0) 588*4c87aefeSPatrick Mooney memcpy(iov.iov_base + sizeof(struct pci_vtcon_control), 589*4c87aefeSPatrick Mooney payload, len); 590*4c87aefeSPatrick Mooney 591*4c87aefeSPatrick Mooney vq_relchain(vq, idx, sizeof(struct pci_vtcon_control) + len); 592*4c87aefeSPatrick Mooney vq_endchains(vq, 1); 593*4c87aefeSPatrick Mooney } 594*4c87aefeSPatrick Mooney 595*4c87aefeSPatrick Mooney 596*4c87aefeSPatrick Mooney static void 597*4c87aefeSPatrick Mooney pci_vtcon_notify_tx(void *vsc, struct vqueue_info *vq) 598*4c87aefeSPatrick Mooney { 599*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc; 600*4c87aefeSPatrick Mooney struct pci_vtcon_port *port; 601*4c87aefeSPatrick Mooney struct iovec iov[1]; 602*4c87aefeSPatrick Mooney uint16_t idx, n; 603*4c87aefeSPatrick Mooney uint16_t flags[8]; 604*4c87aefeSPatrick Mooney 605*4c87aefeSPatrick Mooney sc = vsc; 606*4c87aefeSPatrick Mooney port = pci_vtcon_vq_to_port(sc, vq); 607*4c87aefeSPatrick Mooney 608*4c87aefeSPatrick Mooney while (vq_has_descs(vq)) { 609*4c87aefeSPatrick Mooney n = vq_getchain(vq, &idx, iov, 1, flags); 610*4c87aefeSPatrick Mooney assert(n >= 1); 611*4c87aefeSPatrick Mooney if (port != NULL) 612*4c87aefeSPatrick Mooney port->vsp_cb(port, port->vsp_arg, iov, 1); 613*4c87aefeSPatrick Mooney 614*4c87aefeSPatrick Mooney /* 615*4c87aefeSPatrick Mooney * Release this chain and handle more 616*4c87aefeSPatrick Mooney */ 617*4c87aefeSPatrick Mooney vq_relchain(vq, idx, 0); 618*4c87aefeSPatrick Mooney } 619*4c87aefeSPatrick Mooney vq_endchains(vq, 1); /* Generate interrupt if appropriate. */ 620*4c87aefeSPatrick Mooney } 621*4c87aefeSPatrick Mooney 622*4c87aefeSPatrick Mooney static void 623*4c87aefeSPatrick Mooney pci_vtcon_notify_rx(void *vsc, struct vqueue_info *vq) 624*4c87aefeSPatrick Mooney { 625*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc; 626*4c87aefeSPatrick Mooney struct pci_vtcon_port *port; 627*4c87aefeSPatrick Mooney 628*4c87aefeSPatrick Mooney sc = vsc; 629*4c87aefeSPatrick Mooney port = pci_vtcon_vq_to_port(sc, vq); 630*4c87aefeSPatrick Mooney 631*4c87aefeSPatrick Mooney if (!port->vsp_rx_ready) { 632*4c87aefeSPatrick Mooney port->vsp_rx_ready = 1; 633*4c87aefeSPatrick Mooney vq->vq_used->vu_flags |= VRING_USED_F_NO_NOTIFY; 634*4c87aefeSPatrick Mooney } 635*4c87aefeSPatrick Mooney } 636*4c87aefeSPatrick Mooney 637*4c87aefeSPatrick Mooney static int 638*4c87aefeSPatrick Mooney pci_vtcon_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 639*4c87aefeSPatrick Mooney { 640*4c87aefeSPatrick Mooney struct pci_vtcon_softc *sc; 641*4c87aefeSPatrick Mooney char *portname = NULL; 642*4c87aefeSPatrick Mooney char *portpath = NULL; 643*4c87aefeSPatrick Mooney char *opt; 644*4c87aefeSPatrick Mooney int i; 645*4c87aefeSPatrick Mooney 646*4c87aefeSPatrick Mooney sc = calloc(1, sizeof(struct pci_vtcon_softc)); 647*4c87aefeSPatrick Mooney sc->vsc_config = calloc(1, sizeof(struct pci_vtcon_config)); 648*4c87aefeSPatrick Mooney sc->vsc_config->max_nr_ports = VTCON_MAXPORTS; 649*4c87aefeSPatrick Mooney sc->vsc_config->cols = 80; 650*4c87aefeSPatrick Mooney sc->vsc_config->rows = 25; 651*4c87aefeSPatrick Mooney 652*4c87aefeSPatrick Mooney vi_softc_linkup(&sc->vsc_vs, &vtcon_vi_consts, sc, pi, sc->vsc_queues); 653*4c87aefeSPatrick Mooney sc->vsc_vs.vs_mtx = &sc->vsc_mtx; 654*4c87aefeSPatrick Mooney 655*4c87aefeSPatrick Mooney for (i = 0; i < VTCON_MAXQ; i++) { 656*4c87aefeSPatrick Mooney sc->vsc_queues[i].vq_qsize = VTCON_RINGSZ; 657*4c87aefeSPatrick Mooney sc->vsc_queues[i].vq_notify = i % 2 == 0 658*4c87aefeSPatrick Mooney ? pci_vtcon_notify_rx 659*4c87aefeSPatrick Mooney : pci_vtcon_notify_tx; 660*4c87aefeSPatrick Mooney } 661*4c87aefeSPatrick Mooney 662*4c87aefeSPatrick Mooney /* initialize config space */ 663*4c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_DEVICE, VIRTIO_DEV_CONSOLE); 664*4c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_VENDOR, VIRTIO_VENDOR); 665*4c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM); 666*4c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_SUBDEV_0, VIRTIO_TYPE_CONSOLE); 667*4c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_SUBVEND_0, VIRTIO_VENDOR); 668*4c87aefeSPatrick Mooney 669*4c87aefeSPatrick Mooney if (vi_intr_init(&sc->vsc_vs, 1, fbsdrun_virtio_msix())) 670*4c87aefeSPatrick Mooney return (1); 671*4c87aefeSPatrick Mooney vi_set_io_bar(&sc->vsc_vs, 0); 672*4c87aefeSPatrick Mooney 673*4c87aefeSPatrick Mooney /* create control port */ 674*4c87aefeSPatrick Mooney sc->vsc_control_port.vsp_sc = sc; 675*4c87aefeSPatrick Mooney sc->vsc_control_port.vsp_txq = 2; 676*4c87aefeSPatrick Mooney sc->vsc_control_port.vsp_rxq = 3; 677*4c87aefeSPatrick Mooney sc->vsc_control_port.vsp_cb = pci_vtcon_control_tx; 678*4c87aefeSPatrick Mooney sc->vsc_control_port.vsp_enabled = true; 679*4c87aefeSPatrick Mooney 680*4c87aefeSPatrick Mooney while ((opt = strsep(&opts, ",")) != NULL) { 681*4c87aefeSPatrick Mooney portname = strsep(&opt, "="); 682*4c87aefeSPatrick Mooney portpath = opt; 683*4c87aefeSPatrick Mooney 684*4c87aefeSPatrick Mooney /* create port */ 685*4c87aefeSPatrick Mooney if (pci_vtcon_sock_add(sc, portname, portpath) < 0) { 686*4c87aefeSPatrick Mooney fprintf(stderr, "cannot create port %s: %s\n", 687*4c87aefeSPatrick Mooney portname, strerror(errno)); 688*4c87aefeSPatrick Mooney return (1); 689*4c87aefeSPatrick Mooney } 690*4c87aefeSPatrick Mooney } 691*4c87aefeSPatrick Mooney 692*4c87aefeSPatrick Mooney return (0); 693*4c87aefeSPatrick Mooney } 694*4c87aefeSPatrick Mooney 695*4c87aefeSPatrick Mooney struct pci_devemu pci_de_vcon = { 696*4c87aefeSPatrick Mooney .pe_emu = "virtio-console", 697*4c87aefeSPatrick Mooney .pe_init = pci_vtcon_init, 698*4c87aefeSPatrick Mooney .pe_barwrite = vi_pci_write, 699*4c87aefeSPatrick Mooney .pe_barread = vi_pci_read 700*4c87aefeSPatrick Mooney }; 701*4c87aefeSPatrick Mooney PCI_EMUL_SET(pci_de_vcon); 702