virtio_console.c revision 275273
1/*-
2 * Copyright (c) 2014, Bryan Venteicher <bryanv@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice unmodified, this list of conditions, and the following
10 *    disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27/* Driver for VirtIO console devices. */
28
29#include <sys/cdefs.h>
30__FBSDID("$FreeBSD: stable/10/sys/dev/virtio/console/virtio_console.c 275273 2014-11-29 22:48:40Z bryanv $");
31
32#include <sys/param.h>
33#include <sys/systm.h>
34#include <sys/kernel.h>
35#include <sys/malloc.h>
36#include <sys/module.h>
37#include <sys/kdb.h>
38#include <sys/lock.h>
39#include <sys/mutex.h>
40#include <sys/sglist.h>
41#include <sys/sysctl.h>
42#include <sys/taskqueue.h>
43#include <sys/queue.h>
44
45#include <sys/conf.h>
46#include <sys/cons.h>
47#include <sys/tty.h>
48
49#include <machine/bus.h>
50#include <machine/resource.h>
51#include <sys/bus.h>
52
53#include <dev/virtio/virtio.h>
54#include <dev/virtio/virtqueue.h>
55#include <dev/virtio/console/virtio_console.h>
56
57#include "virtio_if.h"
58
59#define VTCON_MAX_PORTS 32
60#define VTCON_TTY_PREFIX "V"
61#define VTCON_BULK_BUFSZ 128
62
63/*
64 * The buffer cannot cross more than one page boundary due to the
65 * size of the sglist segment array used.
66 */
67CTASSERT(VTCON_BULK_BUFSZ <= PAGE_SIZE);
68
69struct vtcon_softc;
70struct vtcon_softc_port;
71
72struct vtcon_port {
73	struct mtx			 vtcport_mtx;
74	struct vtcon_softc		*vtcport_sc;
75	struct vtcon_softc_port		*vtcport_scport;
76	struct tty			*vtcport_tty;
77	struct virtqueue		*vtcport_invq;
78	struct virtqueue		*vtcport_outvq;
79	int				 vtcport_id;
80	int				 vtcport_flags;
81#define VTCON_PORT_FLAG_GONE	0x01
82#define VTCON_PORT_FLAG_CONSOLE	0x02
83
84#if defined(KDB)
85	int				 vtcport_alt_break_state;
86#endif
87};
88
89#define VTCON_PORT_LOCK(_port)		mtx_lock(&(_port)->vtcport_mtx)
90#define VTCON_PORT_UNLOCK(_port)	mtx_unlock(&(_port)->vtcport_mtx)
91
92struct vtcon_softc_port {
93	struct vtcon_softc	*vcsp_sc;
94	struct vtcon_port	*vcsp_port;
95	struct virtqueue	*vcsp_invq;
96	struct virtqueue	*vcsp_outvq;
97};
98
99struct vtcon_softc {
100	device_t		 vtcon_dev;
101	struct mtx		 vtcon_mtx;
102	uint64_t		 vtcon_features;
103	uint32_t		 vtcon_max_ports;
104	uint32_t		 vtcon_flags;
105#define VTCON_FLAG_DETACHED	0x01
106#define VTCON_FLAG_SIZE		0x02
107#define VTCON_FLAG_MULTIPORT	0x04
108
109	/*
110	 * Ports can be added and removed during runtime, but we have
111	 * to allocate all the virtqueues during attach. This array is
112	 * indexed by the port ID.
113	 */
114	struct vtcon_softc_port	*vtcon_ports;
115
116	struct task		 vtcon_ctrl_task;
117	struct virtqueue	*vtcon_ctrl_rxvq;
118	struct virtqueue	*vtcon_ctrl_txvq;
119	struct mtx		 vtcon_ctrl_tx_mtx;
120};
121
122#define VTCON_LOCK(_sc)			mtx_lock(&(_sc)->vtcon_mtx)
123#define VTCON_UNLOCK(_sc)		mtx_unlock(&(_sc)->vtcon_mtx)
124#define VTCON_LOCK_ASSERT(_sc)		\
125    mtx_assert(&(_sc)->vtcon_mtx, MA_OWNED)
126#define VTCON_LOCK_ASSERT_NOTOWNED(_sc)	\
127    mtx_assert(&(_sc)->vtcon_mtx, MA_NOTOWNED)
128
129#define VTCON_CTRL_TX_LOCK(_sc)		mtx_lock(&(_sc)->vtcon_ctrl_tx_mtx)
130#define VTCON_CTRL_TX_UNLOCK(_sc)	mtx_unlock(&(_sc)->vtcon_ctrl_tx_mtx)
131
132#define VTCON_ASSERT_VALID_PORTID(_sc, _id)			\
133    KASSERT((_id) >= 0 && (_id) < (_sc)->vtcon_max_ports,	\
134        ("%s: port ID %d out of range", __func__, _id))
135
136#define VTCON_FEATURES  VIRTIO_CONSOLE_F_MULTIPORT
137
138static struct virtio_feature_desc vtcon_feature_desc[] = {
139	{ VIRTIO_CONSOLE_F_SIZE,	"ConsoleSize"	},
140	{ VIRTIO_CONSOLE_F_MULTIPORT,	"MultiplePorts"	},
141	{ VIRTIO_CONSOLE_F_EMERG_WRITE,	"EmergencyWrite" },
142
143	{ 0, NULL }
144};
145
146static int	 vtcon_modevent(module_t, int, void *);
147static void	 vtcon_drain_all(void);
148
149static int	 vtcon_probe(device_t);
150static int	 vtcon_attach(device_t);
151static int	 vtcon_detach(device_t);
152static int	 vtcon_config_change(device_t);
153
154static void	 vtcon_setup_features(struct vtcon_softc *);
155static void	 vtcon_negotiate_features(struct vtcon_softc *);
156static int	 vtcon_alloc_scports(struct vtcon_softc *);
157static int	 vtcon_alloc_virtqueues(struct vtcon_softc *);
158static void	 vtcon_read_config(struct vtcon_softc *,
159		     struct virtio_console_config *);
160
161static void	 vtcon_determine_max_ports(struct vtcon_softc *,
162		     struct virtio_console_config *);
163static void	 vtcon_destroy_ports(struct vtcon_softc *);
164static void	 vtcon_stop(struct vtcon_softc *);
165
166static int	 vtcon_ctrl_event_enqueue(struct vtcon_softc *,
167		     struct virtio_console_control *);
168static int	 vtcon_ctrl_event_create(struct vtcon_softc *);
169static void	 vtcon_ctrl_event_requeue(struct vtcon_softc *,
170		     struct virtio_console_control *);
171static int	 vtcon_ctrl_event_populate(struct vtcon_softc *);
172static void	 vtcon_ctrl_event_drain(struct vtcon_softc *);
173static int	 vtcon_ctrl_init(struct vtcon_softc *);
174static void	 vtcon_ctrl_deinit(struct vtcon_softc *);
175static void	 vtcon_ctrl_port_add_event(struct vtcon_softc *, int);
176static void	 vtcon_ctrl_port_remove_event(struct vtcon_softc *, int);
177static void	 vtcon_ctrl_port_console_event(struct vtcon_softc *, int);
178static void	 vtcon_ctrl_port_open_event(struct vtcon_softc *, int);
179static void	 vtcon_ctrl_process_event(struct vtcon_softc *,
180		     struct virtio_console_control *);
181static void	 vtcon_ctrl_task_cb(void *, int);
182static void	 vtcon_ctrl_event_intr(void *);
183static void	 vtcon_ctrl_poll(struct vtcon_softc *,
184		     struct virtio_console_control *control);
185static void	 vtcon_ctrl_send_control(struct vtcon_softc *, uint32_t,
186		     uint16_t, uint16_t);
187
188static int	 vtcon_port_enqueue_buf(struct vtcon_port *, void *, size_t);
189static int	 vtcon_port_create_buf(struct vtcon_port *);
190static void	 vtcon_port_requeue_buf(struct vtcon_port *, void *);
191static int	 vtcon_port_populate(struct vtcon_port *);
192static void	 vtcon_port_destroy(struct vtcon_port *);
193static int	 vtcon_port_create(struct vtcon_softc *, int);
194static void	 vtcon_port_drain_bufs(struct virtqueue *);
195static void	 vtcon_port_drain(struct vtcon_port *);
196static void	 vtcon_port_teardown(struct vtcon_port *);
197static void	 vtcon_port_change_size(struct vtcon_port *, uint16_t,
198		     uint16_t);
199static void	 vtcon_port_update_console_size(struct vtcon_softc *);
200static void	 vtcon_port_enable_intr(struct vtcon_port *);
201static void	 vtcon_port_disable_intr(struct vtcon_port *);
202static void	 vtcon_port_in(struct vtcon_port *);
203static void	 vtcon_port_intr(void *);
204static void	 vtcon_port_out(struct vtcon_port *, void *, int);
205static void	 vtcon_port_submit_event(struct vtcon_port *, uint16_t,
206		     uint16_t);
207
208static int	 vtcon_tty_open(struct tty *);
209static void	 vtcon_tty_close(struct tty *);
210static void	 vtcon_tty_outwakeup(struct tty *);
211static void	 vtcon_tty_free(void *);
212
213static void	 vtcon_get_console_size(struct vtcon_softc *, uint16_t *,
214		     uint16_t *);
215
216static void	 vtcon_enable_interrupts(struct vtcon_softc *);
217static void	 vtcon_disable_interrupts(struct vtcon_softc *);
218
219static int	 vtcon_pending_free;
220
221static struct ttydevsw vtcon_tty_class = {
222	.tsw_flags	= 0,
223	.tsw_open	= vtcon_tty_open,
224	.tsw_close	= vtcon_tty_close,
225	.tsw_outwakeup	= vtcon_tty_outwakeup,
226	.tsw_free	= vtcon_tty_free,
227};
228
229static device_method_t vtcon_methods[] = {
230	/* Device methods. */
231	DEVMETHOD(device_probe,		vtcon_probe),
232	DEVMETHOD(device_attach,	vtcon_attach),
233	DEVMETHOD(device_detach,	vtcon_detach),
234
235	/* VirtIO methods. */
236	DEVMETHOD(virtio_config_change,	vtcon_config_change),
237
238	DEVMETHOD_END
239};
240
241static driver_t vtcon_driver = {
242	"vtcon",
243	vtcon_methods,
244	sizeof(struct vtcon_softc)
245};
246static devclass_t vtcon_devclass;
247
248DRIVER_MODULE(virtio_console, virtio_pci, vtcon_driver, vtcon_devclass,
249    vtcon_modevent, 0);
250MODULE_VERSION(virtio_console, 1);
251MODULE_DEPEND(virtio_console, virtio, 1, 1, 1);
252
253static int
254vtcon_modevent(module_t mod, int type, void *unused)
255{
256	int error;
257
258	switch (type) {
259	case MOD_LOAD:
260		error = 0;
261		break;
262	case MOD_QUIESCE:
263		error = 0;
264		break;
265	case MOD_UNLOAD:
266		vtcon_drain_all();
267		error = 0;
268		break;
269	case MOD_SHUTDOWN:
270		error = 0;
271		break;
272	default:
273		error = EOPNOTSUPP;
274		break;
275	}
276
277	return (error);
278}
279
280static void
281vtcon_drain_all(void)
282{
283	int first;
284
285	for (first = 1; vtcon_pending_free != 0; first = 0) {
286		if (first != 0) {
287			printf("virtio_console: Waiting for all detached TTY "
288			    "devices to have open fds closed.\n");
289		}
290		pause("vtcondra", hz);
291	}
292}
293
294static int
295vtcon_probe(device_t dev)
296{
297
298	if (virtio_get_device_type(dev) != VIRTIO_ID_CONSOLE)
299		return (ENXIO);
300
301	device_set_desc(dev, "VirtIO Console Adapter");
302
303	return (BUS_PROBE_DEFAULT);
304}
305
306static int
307vtcon_attach(device_t dev)
308{
309	struct vtcon_softc *sc;
310	struct virtio_console_config concfg;
311	int error;
312
313	sc = device_get_softc(dev);
314	sc->vtcon_dev = dev;
315
316	mtx_init(&sc->vtcon_mtx, "vtconmtx", NULL, MTX_DEF);
317	mtx_init(&sc->vtcon_ctrl_tx_mtx, "vtconctrlmtx", NULL, MTX_DEF);
318
319	virtio_set_feature_desc(dev, vtcon_feature_desc);
320	vtcon_setup_features(sc);
321
322	vtcon_read_config(sc, &concfg);
323	vtcon_determine_max_ports(sc, &concfg);
324
325	error = vtcon_alloc_scports(sc);
326	if (error) {
327		device_printf(dev, "cannot allocate softc port structures\n");
328		goto fail;
329	}
330
331	error = vtcon_alloc_virtqueues(sc);
332	if (error) {
333		device_printf(dev, "cannot allocate virtqueues\n");
334		goto fail;
335	}
336
337	if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) {
338		TASK_INIT(&sc->vtcon_ctrl_task, 0, vtcon_ctrl_task_cb, sc);
339		error = vtcon_ctrl_init(sc);
340		if (error)
341			goto fail;
342	} else {
343		error = vtcon_port_create(sc, 0);
344		if (error)
345			goto fail;
346		if (sc->vtcon_flags & VTCON_FLAG_SIZE)
347			vtcon_port_update_console_size(sc);
348	}
349
350	error = virtio_setup_intr(dev, INTR_TYPE_TTY);
351	if (error) {
352		device_printf(dev, "cannot setup virtqueue interrupts\n");
353		goto fail;
354	}
355
356	vtcon_enable_interrupts(sc);
357
358	vtcon_ctrl_send_control(sc, VIRTIO_CONSOLE_BAD_ID,
359	    VIRTIO_CONSOLE_DEVICE_READY, 1);
360
361fail:
362	if (error)
363		vtcon_detach(dev);
364
365	return (error);
366}
367
368static int
369vtcon_detach(device_t dev)
370{
371	struct vtcon_softc *sc;
372
373	sc = device_get_softc(dev);
374
375	VTCON_LOCK(sc);
376	sc->vtcon_flags |= VTCON_FLAG_DETACHED;
377	if (device_is_attached(dev))
378		vtcon_stop(sc);
379	VTCON_UNLOCK(sc);
380
381	if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) {
382		taskqueue_drain(taskqueue_thread, &sc->vtcon_ctrl_task);
383		vtcon_ctrl_deinit(sc);
384	}
385
386	vtcon_destroy_ports(sc);
387	mtx_destroy(&sc->vtcon_mtx);
388	mtx_destroy(&sc->vtcon_ctrl_tx_mtx);
389
390	return (0);
391}
392
393static int
394vtcon_config_change(device_t dev)
395{
396	struct vtcon_softc *sc;
397
398	sc = device_get_softc(dev);
399
400	/*
401	 * When the multiport feature is negotiated, all configuration
402	 * changes are done through control virtqueue events.
403	 */
404	if ((sc->vtcon_flags & VTCON_FLAG_MULTIPORT) == 0) {
405		if (sc->vtcon_flags & VTCON_FLAG_SIZE)
406			vtcon_port_update_console_size(sc);
407	}
408
409	return (0);
410}
411
412static void
413vtcon_negotiate_features(struct vtcon_softc *sc)
414{
415	device_t dev;
416	uint64_t features;
417
418	dev = sc->vtcon_dev;
419	features = VTCON_FEATURES;
420
421	sc->vtcon_features = virtio_negotiate_features(dev, features);
422}
423
424static void
425vtcon_setup_features(struct vtcon_softc *sc)
426{
427	device_t dev;
428
429	dev = sc->vtcon_dev;
430
431	vtcon_negotiate_features(sc);
432
433	if (virtio_with_feature(dev, VIRTIO_CONSOLE_F_SIZE))
434		sc->vtcon_flags |= VTCON_FLAG_SIZE;
435	if (virtio_with_feature(dev, VIRTIO_CONSOLE_F_MULTIPORT))
436		sc->vtcon_flags |= VTCON_FLAG_MULTIPORT;
437}
438
439#define VTCON_GET_CONFIG(_dev, _feature, _field, _cfg)			\
440	if (virtio_with_feature(_dev, _feature)) {			\
441		virtio_read_device_config(_dev,				\
442		    offsetof(struct virtio_console_config, _field),	\
443		    &(_cfg)->_field, sizeof((_cfg)->_field));		\
444	}
445
446static void
447vtcon_read_config(struct vtcon_softc *sc, struct virtio_console_config *concfg)
448{
449	device_t dev;
450
451	dev = sc->vtcon_dev;
452
453	bzero(concfg, sizeof(struct virtio_console_config));
454
455	VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_SIZE, cols, concfg);
456	VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_SIZE, rows, concfg);
457	VTCON_GET_CONFIG(dev, VIRTIO_CONSOLE_F_MULTIPORT, max_nr_ports, concfg);
458}
459
460#undef VTCON_GET_CONFIG
461
462static int
463vtcon_alloc_scports(struct vtcon_softc *sc)
464{
465	struct vtcon_softc_port *scport;
466	int max, i;
467
468	max = sc->vtcon_max_ports;
469
470	sc->vtcon_ports = malloc(sizeof(struct vtcon_softc_port) * max,
471	    M_DEVBUF, M_NOWAIT | M_ZERO);
472	if (sc->vtcon_ports == NULL)
473		return (ENOMEM);
474
475	for (i = 0; i < max; i++) {
476		scport = &sc->vtcon_ports[i];
477		scport->vcsp_sc = sc;
478	}
479
480	return (0);
481}
482
483static int
484vtcon_alloc_virtqueues(struct vtcon_softc *sc)
485{
486	device_t dev;
487	struct vq_alloc_info *info;
488	struct vtcon_softc_port *scport;
489	int i, idx, portidx, nvqs, error;
490
491	dev = sc->vtcon_dev;
492
493	nvqs = sc->vtcon_max_ports * 2;
494	if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT)
495		nvqs += 2;
496
497	info = malloc(sizeof(struct vq_alloc_info) * nvqs, M_TEMP, M_NOWAIT);
498	if (info == NULL)
499		return (ENOMEM);
500
501	for (i = 0, idx = 0, portidx = 0; i < nvqs / 2; i++, idx += 2) {
502
503		if (i == 1) {
504			/* The control virtqueues are after the first port. */
505			VQ_ALLOC_INFO_INIT(&info[idx], 0,
506			    vtcon_ctrl_event_intr, sc, &sc->vtcon_ctrl_rxvq,
507			    "%s-control rx", device_get_nameunit(dev));
508			VQ_ALLOC_INFO_INIT(&info[idx+1], 0,
509			    NULL, sc, &sc->vtcon_ctrl_txvq,
510			    "%s-control tx", device_get_nameunit(dev));
511			continue;
512		}
513
514		scport = &sc->vtcon_ports[portidx];
515
516		VQ_ALLOC_INFO_INIT(&info[idx], 0, vtcon_port_intr,
517		    scport, &scport->vcsp_invq, "%s-port%d in",
518		    device_get_nameunit(dev), i);
519		VQ_ALLOC_INFO_INIT(&info[idx+1], 0, NULL,
520		    NULL, &scport->vcsp_outvq, "%s-port%d out",
521		    device_get_nameunit(dev), i);
522
523		portidx++;
524	}
525
526	error = virtio_alloc_virtqueues(dev, 0, nvqs, info);
527	free(info, M_TEMP);
528
529	return (error);
530}
531
532static void
533vtcon_determine_max_ports(struct vtcon_softc *sc,
534    struct virtio_console_config *concfg)
535{
536
537	if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT) {
538		sc->vtcon_max_ports =
539		    min(concfg->max_nr_ports, VTCON_MAX_PORTS);
540		if (sc->vtcon_max_ports == 0)
541			sc->vtcon_max_ports = 1;
542	} else
543		sc->vtcon_max_ports = 1;
544}
545
546static void
547vtcon_destroy_ports(struct vtcon_softc *sc)
548{
549	struct vtcon_softc_port *scport;
550	struct vtcon_port *port;
551	struct virtqueue *vq;
552	int i;
553
554	if (sc->vtcon_ports == NULL)
555		return;
556
557	VTCON_LOCK(sc);
558	for (i = 0; i < sc->vtcon_max_ports; i++) {
559		scport = &sc->vtcon_ports[i];
560
561		port = scport->vcsp_port;
562		if (port != NULL) {
563			scport->vcsp_port = NULL;
564			VTCON_PORT_LOCK(port);
565			VTCON_UNLOCK(sc);
566			vtcon_port_teardown(port);
567			VTCON_LOCK(sc);
568		}
569
570		vq = scport->vcsp_invq;
571		if (vq != NULL)
572			vtcon_port_drain_bufs(vq);
573	}
574	VTCON_UNLOCK(sc);
575
576	free(sc->vtcon_ports, M_DEVBUF);
577	sc->vtcon_ports = NULL;
578}
579
580static void
581vtcon_stop(struct vtcon_softc *sc)
582{
583
584	vtcon_disable_interrupts(sc);
585	virtio_stop(sc->vtcon_dev);
586}
587
588static int
589vtcon_ctrl_event_enqueue(struct vtcon_softc *sc,
590    struct virtio_console_control *control)
591{
592	struct sglist_seg segs[2];
593	struct sglist sg;
594	struct virtqueue *vq;
595	int error;
596
597	vq = sc->vtcon_ctrl_rxvq;
598
599	sglist_init(&sg, 2, segs);
600	error = sglist_append(&sg, control,
601	    sizeof(struct virtio_console_control));
602	KASSERT(error == 0, ("%s: error %d adding control to sglist",
603	    __func__, error));
604
605	return (virtqueue_enqueue(vq, control, &sg, 0, sg.sg_nseg));
606}
607
608static int
609vtcon_ctrl_event_create(struct vtcon_softc *sc)
610{
611	struct virtio_console_control *control;
612	int error;
613
614	control = malloc(sizeof(struct virtio_console_control), M_DEVBUF,
615	    M_ZERO | M_NOWAIT);
616	if (control == NULL)
617		return (ENOMEM);
618
619	error = vtcon_ctrl_event_enqueue(sc, control);
620	if (error)
621		free(control, M_DEVBUF);
622
623	return (error);
624}
625
626static void
627vtcon_ctrl_event_requeue(struct vtcon_softc *sc,
628    struct virtio_console_control *control)
629{
630	int error;
631
632	bzero(control, sizeof(struct virtio_console_control));
633
634	error = vtcon_ctrl_event_enqueue(sc, control);
635	KASSERT(error == 0,
636	    ("%s: cannot requeue control buffer %d", __func__, error));
637}
638
639static int
640vtcon_ctrl_event_populate(struct vtcon_softc *sc)
641{
642	struct virtqueue *vq;
643	int nbufs, error;
644
645	vq = sc->vtcon_ctrl_rxvq;
646	error = ENOSPC;
647
648	for (nbufs = 0; !virtqueue_full(vq); nbufs++) {
649		error = vtcon_ctrl_event_create(sc);
650		if (error)
651			break;
652	}
653
654	if (nbufs > 0) {
655		virtqueue_notify(vq);
656		error = 0;
657	}
658
659	return (error);
660}
661
662static void
663vtcon_ctrl_event_drain(struct vtcon_softc *sc)
664{
665	struct virtio_console_control *control;
666	struct virtqueue *vq;
667	int last;
668
669	vq = sc->vtcon_ctrl_rxvq;
670	last = 0;
671
672	if (vq == NULL)
673		return;
674
675	VTCON_LOCK(sc);
676	while ((control = virtqueue_drain(vq, &last)) != NULL)
677		free(control, M_DEVBUF);
678	VTCON_UNLOCK(sc);
679}
680
681static int
682vtcon_ctrl_init(struct vtcon_softc *sc)
683{
684	int error;
685
686	error = vtcon_ctrl_event_populate(sc);
687
688	return (error);
689}
690
691static void
692vtcon_ctrl_deinit(struct vtcon_softc *sc)
693{
694
695	vtcon_ctrl_event_drain(sc);
696}
697
698static void
699vtcon_ctrl_port_add_event(struct vtcon_softc *sc, int id)
700{
701	device_t dev;
702	int error;
703
704	dev = sc->vtcon_dev;
705
706	/* This single thread only way for ports to be created. */
707	if (sc->vtcon_ports[id].vcsp_port != NULL) {
708		device_printf(dev, "%s: adding port %d, but already exists\n",
709		    __func__, id);
710		return;
711	}
712
713	error = vtcon_port_create(sc, id);
714	if (error) {
715		device_printf(dev, "%s: cannot create port %d: %d\n",
716		    __func__, id, error);
717		vtcon_ctrl_send_control(sc, id, VIRTIO_CONSOLE_PORT_READY, 0);
718		return;
719	}
720}
721
722static void
723vtcon_ctrl_port_remove_event(struct vtcon_softc *sc, int id)
724{
725	device_t dev;
726	struct vtcon_softc_port *scport;
727	struct vtcon_port *port;
728
729	dev = sc->vtcon_dev;
730	scport = &sc->vtcon_ports[id];
731
732	VTCON_LOCK(sc);
733	port = scport->vcsp_port;
734	if (port == NULL) {
735		VTCON_UNLOCK(sc);
736		device_printf(dev, "%s: remove port %d, but does not exist\n",
737		    __func__, id);
738		return;
739	}
740
741	scport->vcsp_port = NULL;
742	VTCON_PORT_LOCK(port);
743	VTCON_UNLOCK(sc);
744	vtcon_port_teardown(port);
745}
746
747static void
748vtcon_ctrl_port_console_event(struct vtcon_softc *sc, int id)
749{
750	device_t dev;
751	struct vtcon_softc_port *scport;
752	struct vtcon_port *port;
753
754	dev = sc->vtcon_dev;
755	scport = &sc->vtcon_ports[id];
756
757	VTCON_LOCK(sc);
758	port = scport->vcsp_port;
759	if (port == NULL) {
760		VTCON_UNLOCK(sc);
761		device_printf(dev, "%s: console port %d, but does not exist\n",
762		    __func__, id);
763		return;
764	}
765
766	VTCON_PORT_LOCK(port);
767	VTCON_UNLOCK(sc);
768	port->vtcport_flags |= VTCON_PORT_FLAG_CONSOLE;
769	vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
770	VTCON_PORT_UNLOCK(port);
771}
772
773static void
774vtcon_ctrl_port_open_event(struct vtcon_softc *sc, int id)
775{
776	device_t dev;
777	struct vtcon_softc_port *scport;
778	struct vtcon_port *port;
779
780	dev = sc->vtcon_dev;
781	scport = &sc->vtcon_ports[id];
782
783	VTCON_LOCK(sc);
784	port = scport->vcsp_port;
785	if (port == NULL) {
786		VTCON_UNLOCK(sc);
787		device_printf(dev, "%s: open port %d, but does not exist\n",
788		    __func__, id);
789		return;
790	}
791
792	VTCON_PORT_LOCK(port);
793	VTCON_UNLOCK(sc);
794	vtcon_port_enable_intr(port);
795	VTCON_PORT_UNLOCK(port);
796}
797
798static void
799vtcon_ctrl_process_event(struct vtcon_softc *sc,
800    struct virtio_console_control *control)
801{
802	device_t dev;
803	int id;
804
805	dev = sc->vtcon_dev;
806	id = control->id;
807
808	if (id < 0 || id >= sc->vtcon_max_ports) {
809		device_printf(dev, "%s: invalid port ID %d\n", __func__, id);
810		return;
811	}
812
813	switch (control->event) {
814	case VIRTIO_CONSOLE_PORT_ADD:
815		vtcon_ctrl_port_add_event(sc, id);
816		break;
817
818	case VIRTIO_CONSOLE_PORT_REMOVE:
819		vtcon_ctrl_port_remove_event(sc, id);
820		break;
821
822	case VIRTIO_CONSOLE_CONSOLE_PORT:
823		vtcon_ctrl_port_console_event(sc, id);
824		break;
825
826	case VIRTIO_CONSOLE_RESIZE:
827		break;
828
829	case VIRTIO_CONSOLE_PORT_OPEN:
830		vtcon_ctrl_port_open_event(sc, id);
831		break;
832
833	case VIRTIO_CONSOLE_PORT_NAME:
834		break;
835	}
836}
837
838static void
839vtcon_ctrl_task_cb(void *xsc, int pending)
840{
841	struct vtcon_softc *sc;
842	struct virtqueue *vq;
843	struct virtio_console_control *control;
844	int detached;
845
846	sc = xsc;
847	vq = sc->vtcon_ctrl_rxvq;
848
849	VTCON_LOCK(sc);
850
851	while ((detached = (sc->vtcon_flags & VTCON_FLAG_DETACHED)) == 0) {
852		control = virtqueue_dequeue(vq, NULL);
853		if (control == NULL)
854			break;
855
856		VTCON_UNLOCK(sc);
857		vtcon_ctrl_process_event(sc, control);
858		VTCON_LOCK(sc);
859		vtcon_ctrl_event_requeue(sc, control);
860	}
861
862	if (!detached) {
863		virtqueue_notify(vq);
864		if (virtqueue_enable_intr(vq) != 0)
865			taskqueue_enqueue(taskqueue_thread,
866			    &sc->vtcon_ctrl_task);
867	}
868
869	VTCON_UNLOCK(sc);
870}
871
872static void
873vtcon_ctrl_event_intr(void *xsc)
874{
875	struct vtcon_softc *sc;
876
877	sc = xsc;
878
879	/*
880	 * Only some events require us to potentially block, but it
881	 * easier to just defer all event handling to the taskqueue.
882	 */
883	taskqueue_enqueue(taskqueue_thread, &sc->vtcon_ctrl_task);
884}
885
886static void
887vtcon_ctrl_poll(struct vtcon_softc *sc,
888    struct virtio_console_control *control)
889{
890	struct sglist_seg segs[2];
891	struct sglist sg;
892	struct virtqueue *vq;
893	int error;
894
895	vq = sc->vtcon_ctrl_txvq;
896
897	sglist_init(&sg, 2, segs);
898	error = sglist_append(&sg, control,
899	    sizeof(struct virtio_console_control));
900	KASSERT(error == 0, ("%s: error %d adding control to sglist",
901	    __func__, error));
902
903	/*
904	 * We cannot use the softc lock to serialize access to this
905	 * virtqueue since this is called from the tty layer with the
906	 * port lock held. Acquiring the softc would violate our lock
907	 * ordering.
908	 */
909	VTCON_CTRL_TX_LOCK(sc);
910	KASSERT(virtqueue_empty(vq),
911	    ("%s: virtqueue is not emtpy", __func__));
912	error = virtqueue_enqueue(vq, control, &sg, sg.sg_nseg, 0);
913	if (error == 0) {
914		virtqueue_notify(vq);
915		virtqueue_poll(vq, NULL);
916	}
917	VTCON_CTRL_TX_UNLOCK(sc);
918}
919
920static void
921vtcon_ctrl_send_control(struct vtcon_softc *sc, uint32_t portid,
922    uint16_t event, uint16_t value)
923{
924	struct virtio_console_control control;
925
926	if ((sc->vtcon_flags & VTCON_FLAG_MULTIPORT) == 0)
927		return;
928
929	control.id = portid;
930	control.event = event;
931	control.value = value;
932
933	vtcon_ctrl_poll(sc, &control);
934}
935
936static int
937vtcon_port_enqueue_buf(struct vtcon_port *port, void *buf, size_t len)
938{
939	struct sglist_seg segs[2];
940	struct sglist sg;
941	struct virtqueue *vq;
942	int error;
943
944	vq = port->vtcport_invq;
945
946	sglist_init(&sg, 2, segs);
947	error = sglist_append(&sg, buf, len);
948	KASSERT(error == 0,
949	    ("%s: error %d adding buffer to sglist", __func__, error));
950
951	error = virtqueue_enqueue(vq, buf, &sg, 0, sg.sg_nseg);
952
953	return (error);
954}
955
956static int
957vtcon_port_create_buf(struct vtcon_port *port)
958{
959	void *buf;
960	int error;
961
962	buf = malloc(VTCON_BULK_BUFSZ, M_DEVBUF, M_ZERO | M_NOWAIT);
963	if (buf == NULL)
964		return (ENOMEM);
965
966	error = vtcon_port_enqueue_buf(port, buf, VTCON_BULK_BUFSZ);
967	if (error)
968		free(buf, M_DEVBUF);
969
970	return (error);
971}
972
973static void
974vtcon_port_requeue_buf(struct vtcon_port *port, void *buf)
975{
976	int error;
977
978	error = vtcon_port_enqueue_buf(port, buf, VTCON_BULK_BUFSZ);
979	KASSERT(error == 0,
980	    ("%s: cannot requeue input buffer %d", __func__, error));
981}
982
983static int
984vtcon_port_populate(struct vtcon_port *port)
985{
986	struct virtqueue *vq;
987	int nbufs, error;
988
989	vq = port->vtcport_invq;
990	error = ENOSPC;
991
992	for (nbufs = 0; !virtqueue_full(vq); nbufs++) {
993		error = vtcon_port_create_buf(port);
994		if (error)
995			break;
996	}
997
998	if (nbufs > 0) {
999		virtqueue_notify(vq);
1000		error = 0;
1001	}
1002
1003	return (error);
1004}
1005
1006static void
1007vtcon_port_destroy(struct vtcon_port *port)
1008{
1009
1010	port->vtcport_sc = NULL;
1011	port->vtcport_scport = NULL;
1012	port->vtcport_invq = NULL;
1013	port->vtcport_outvq = NULL;
1014	port->vtcport_id = -1;
1015	mtx_destroy(&port->vtcport_mtx);
1016	free(port, M_DEVBUF);
1017}
1018
1019static int
1020vtcon_port_init_vqs(struct vtcon_port *port)
1021{
1022	struct vtcon_softc_port *scport;
1023	int error;
1024
1025	scport = port->vtcport_scport;
1026
1027	port->vtcport_invq = scport->vcsp_invq;
1028	port->vtcport_outvq = scport->vcsp_outvq;
1029
1030	/*
1031	 * Free any data left over from when this virtqueue was in use by a
1032	 * prior port. We have not yet notified the host that the port is
1033	 * ready, so assume nothing in the virtqueue can be for us.
1034	 */
1035	vtcon_port_drain(port);
1036
1037	KASSERT(virtqueue_empty(port->vtcport_invq),
1038	    ("%s: in virtqueue is not empty", __func__));
1039	KASSERT(virtqueue_empty(port->vtcport_outvq),
1040	    ("%s: out virtqueue is not empty", __func__));
1041
1042	error = vtcon_port_populate(port);
1043	if (error)
1044		return (error);
1045
1046	return (0);
1047}
1048
1049static int
1050vtcon_port_create(struct vtcon_softc *sc, int id)
1051{
1052	device_t dev;
1053	struct vtcon_softc_port *scport;
1054	struct vtcon_port *port;
1055	int error;
1056
1057	dev = sc->vtcon_dev;
1058	scport = &sc->vtcon_ports[id];
1059
1060	VTCON_ASSERT_VALID_PORTID(sc, id);
1061	MPASS(scport->vcsp_port == NULL);
1062
1063	port = malloc(sizeof(struct vtcon_port), M_DEVBUF, M_NOWAIT | M_ZERO);
1064	if (port == NULL)
1065		return (ENOMEM);
1066
1067	port->vtcport_sc = sc;
1068	port->vtcport_scport = scport;
1069	port->vtcport_id = id;
1070	mtx_init(&port->vtcport_mtx, "vtcpmtx", NULL, MTX_DEF);
1071	port->vtcport_tty = tty_alloc_mutex(&vtcon_tty_class, port,
1072	    &port->vtcport_mtx);
1073
1074	error = vtcon_port_init_vqs(port);
1075	if (error) {
1076		VTCON_PORT_LOCK(port);
1077		vtcon_port_teardown(port);
1078		return (error);
1079	}
1080
1081	VTCON_LOCK(sc);
1082	VTCON_PORT_LOCK(port);
1083	scport->vcsp_port = port;
1084	vtcon_port_enable_intr(port);
1085	vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_READY, 1);
1086	VTCON_PORT_UNLOCK(port);
1087	VTCON_UNLOCK(sc);
1088
1089	tty_makedev(port->vtcport_tty, NULL, "%s%r.%r", VTCON_TTY_PREFIX,
1090	    device_get_unit(dev), id);
1091
1092	return (0);
1093}
1094
1095static void
1096vtcon_port_drain_bufs(struct virtqueue *vq)
1097{
1098	void *buf;
1099	int last;
1100
1101	last = 0;
1102
1103	while ((buf = virtqueue_drain(vq, &last)) != NULL)
1104		free(buf, M_DEVBUF);
1105}
1106
1107static void
1108vtcon_port_drain(struct vtcon_port *port)
1109{
1110
1111	vtcon_port_drain_bufs(port->vtcport_invq);
1112}
1113
1114static void
1115vtcon_port_teardown(struct vtcon_port *port)
1116{
1117	struct tty *tp;
1118
1119	tp = port->vtcport_tty;
1120
1121	port->vtcport_flags |= VTCON_PORT_FLAG_GONE;
1122
1123	if (tp != NULL) {
1124		atomic_add_int(&vtcon_pending_free, 1);
1125		tty_rel_gone(tp);
1126	} else
1127		vtcon_port_destroy(port);
1128}
1129
1130static void
1131vtcon_port_change_size(struct vtcon_port *port, uint16_t cols, uint16_t rows)
1132{
1133	struct tty *tp;
1134	struct winsize sz;
1135
1136	tp = port->vtcport_tty;
1137
1138	if (tp == NULL)
1139		return;
1140
1141	bzero(&sz, sizeof(struct winsize));
1142	sz.ws_col = cols;
1143	sz.ws_row = rows;
1144
1145	tty_set_winsize(tp, &sz);
1146}
1147
1148static void
1149vtcon_port_update_console_size(struct vtcon_softc *sc)
1150{
1151	struct vtcon_port *port;
1152	struct vtcon_softc_port *scport;
1153	uint16_t cols, rows;
1154
1155	vtcon_get_console_size(sc, &cols, &rows);
1156
1157	/*
1158	 * For now, assume the first (only) port is the console. Note
1159	 * QEMU does not implement this feature yet.
1160	 */
1161	scport = &sc->vtcon_ports[0];
1162
1163	VTCON_LOCK(sc);
1164	port = scport->vcsp_port;
1165
1166	if (port != NULL) {
1167		VTCON_PORT_LOCK(port);
1168		VTCON_UNLOCK(sc);
1169		vtcon_port_change_size(port, cols, rows);
1170		VTCON_PORT_UNLOCK(port);
1171	} else
1172		VTCON_UNLOCK(sc);
1173}
1174
1175static void
1176vtcon_port_enable_intr(struct vtcon_port *port)
1177{
1178
1179	/*
1180	 * NOTE: The out virtqueue is always polled, so its interupt
1181	 * kept disabled.
1182	 */
1183	virtqueue_enable_intr(port->vtcport_invq);
1184}
1185
1186static void
1187vtcon_port_disable_intr(struct vtcon_port *port)
1188{
1189
1190	if (port->vtcport_invq != NULL)
1191		virtqueue_disable_intr(port->vtcport_invq);
1192	if (port->vtcport_outvq != NULL)
1193		virtqueue_disable_intr(port->vtcport_outvq);
1194}
1195
1196static void
1197vtcon_port_in(struct vtcon_port *port)
1198{
1199	struct virtqueue *vq;
1200	struct tty *tp;
1201	char *buf;
1202	uint32_t len;
1203	int i, deq;
1204
1205	tp = port->vtcport_tty;
1206	vq = port->vtcport_invq;
1207
1208again:
1209	deq = 0;
1210
1211	while ((buf = virtqueue_dequeue(vq, &len)) != NULL) {
1212		for (i = 0; i < len; i++) {
1213#if defined(KDB)
1214			if (port->vtcport_flags & VTCON_PORT_FLAG_CONSOLE)
1215				kdb_alt_break(buf[i],
1216				    &port->vtcport_alt_break_state);
1217#endif
1218			ttydisc_rint(tp, buf[i], 0);
1219		}
1220		vtcon_port_requeue_buf(port, buf);
1221		deq++;
1222	}
1223	ttydisc_rint_done(tp);
1224
1225	if (deq > 0)
1226		virtqueue_notify(vq);
1227
1228	if (virtqueue_enable_intr(vq) != 0)
1229		goto again;
1230}
1231
1232static void
1233vtcon_port_intr(void *scportx)
1234{
1235	struct vtcon_softc_port *scport;
1236	struct vtcon_softc *sc;
1237	struct vtcon_port *port;
1238
1239	scport = scportx;
1240	sc = scport->vcsp_sc;
1241
1242	VTCON_LOCK(sc);
1243	port = scport->vcsp_port;
1244	if (port == NULL) {
1245		VTCON_UNLOCK(sc);
1246		return;
1247	}
1248	VTCON_PORT_LOCK(port);
1249	VTCON_UNLOCK(sc);
1250	if ((port->vtcport_flags & VTCON_PORT_FLAG_GONE) == 0)
1251		vtcon_port_in(port);
1252	VTCON_PORT_UNLOCK(port);
1253}
1254
1255static void
1256vtcon_port_out(struct vtcon_port *port, void *buf, int bufsize)
1257{
1258	struct sglist_seg segs[2];
1259	struct sglist sg;
1260	struct virtqueue *vq;
1261	int error;
1262
1263	vq = port->vtcport_outvq;
1264	KASSERT(virtqueue_empty(vq),
1265	    ("%s: port %p out virtqueue not emtpy", __func__, port));
1266
1267	sglist_init(&sg, 2, segs);
1268	error = sglist_append(&sg, buf, bufsize);
1269	KASSERT(error == 0, ("%s: error %d adding buffer to sglist",
1270	    __func__, error));
1271
1272	error = virtqueue_enqueue(vq, buf, &sg, sg.sg_nseg, 0);
1273	if (error == 0) {
1274		virtqueue_notify(vq);
1275		virtqueue_poll(vq, NULL);
1276	}
1277}
1278
1279static void
1280vtcon_port_submit_event(struct vtcon_port *port, uint16_t event,
1281    uint16_t value)
1282{
1283	struct vtcon_softc *sc;
1284
1285	sc = port->vtcport_sc;
1286
1287	vtcon_ctrl_send_control(sc, port->vtcport_id, event, value);
1288}
1289
1290static int
1291vtcon_tty_open(struct tty *tp)
1292{
1293	struct vtcon_port *port;
1294
1295	port = tty_softc(tp);
1296
1297	if (port->vtcport_flags & VTCON_PORT_FLAG_GONE)
1298		return (ENXIO);
1299
1300	vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
1301
1302	return (0);
1303}
1304
1305static void
1306vtcon_tty_close(struct tty *tp)
1307{
1308	struct vtcon_port *port;
1309
1310	port = tty_softc(tp);
1311
1312	if (port->vtcport_flags & VTCON_PORT_FLAG_GONE)
1313		return;
1314
1315	vtcon_port_submit_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
1316}
1317
1318static void
1319vtcon_tty_outwakeup(struct tty *tp)
1320{
1321	struct vtcon_port *port;
1322	char buf[VTCON_BULK_BUFSZ];
1323	int len;
1324
1325	port = tty_softc(tp);
1326
1327	if (port->vtcport_flags & VTCON_PORT_FLAG_GONE)
1328		return;
1329
1330	while ((len = ttydisc_getc(tp, buf, sizeof(buf))) != 0)
1331		vtcon_port_out(port, buf, len);
1332}
1333
1334static void
1335vtcon_tty_free(void *xport)
1336{
1337	struct vtcon_port *port;
1338
1339	port = xport;
1340
1341	vtcon_port_destroy(port);
1342	atomic_subtract_int(&vtcon_pending_free, 1);
1343}
1344
1345static void
1346vtcon_get_console_size(struct vtcon_softc *sc, uint16_t *cols, uint16_t *rows)
1347{
1348	struct virtio_console_config concfg;
1349
1350	KASSERT(sc->vtcon_flags & VTCON_FLAG_SIZE,
1351	    ("%s: size feature not negotiated", __func__));
1352
1353	vtcon_read_config(sc, &concfg);
1354
1355	*cols = concfg.cols;
1356	*rows = concfg.rows;
1357}
1358
1359static void
1360vtcon_enable_interrupts(struct vtcon_softc *sc)
1361{
1362	struct vtcon_softc_port *scport;
1363	struct vtcon_port *port;
1364	int i;
1365
1366	VTCON_LOCK(sc);
1367
1368	if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT)
1369		virtqueue_enable_intr(sc->vtcon_ctrl_rxvq);
1370
1371	for (i = 0; i < sc->vtcon_max_ports; i++) {
1372		scport = &sc->vtcon_ports[i];
1373
1374		port = scport->vcsp_port;
1375		if (port == NULL)
1376			continue;
1377
1378		VTCON_PORT_LOCK(port);
1379		vtcon_port_enable_intr(port);
1380		VTCON_PORT_UNLOCK(port);
1381	}
1382
1383	VTCON_UNLOCK(sc);
1384}
1385
1386static void
1387vtcon_disable_interrupts(struct vtcon_softc *sc)
1388{
1389	struct vtcon_softc_port *scport;
1390	struct vtcon_port *port;
1391	int i;
1392
1393	VTCON_LOCK_ASSERT(sc);
1394
1395	if (sc->vtcon_flags & VTCON_FLAG_MULTIPORT)
1396		virtqueue_disable_intr(sc->vtcon_ctrl_rxvq);
1397
1398	for (i = 0; i < sc->vtcon_max_ports; i++) {
1399		scport = &sc->vtcon_ports[i];
1400
1401		port = scport->vcsp_port;
1402		if (port == NULL)
1403			continue;
1404
1405		VTCON_PORT_LOCK(port);
1406		vtcon_port_disable_intr(port);
1407		VTCON_PORT_UNLOCK(port);
1408	}
1409}
1410