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