]> git.proxmox.com Git - qemu.git/blame - hw/virtio-serial-bus.c
virtio-serial: delete timer if active during exit
[qemu.git] / hw / virtio-serial-bus.c
CommitLineData
98b19252
AS
1/*
2 * A bus for connecting virtio serial and console ports
3 *
71c092e9 4 * Copyright (C) 2009, 2010 Red Hat, Inc.
98b19252
AS
5 *
6 * Author(s):
7 * Amit Shah <amit.shah@redhat.com>
8 *
9 * Some earlier parts are:
10 * Copyright IBM, Corp. 2008
11 * authored by
12 * Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
13 *
14 * This work is licensed under the terms of the GNU GPL, version 2. See
15 * the COPYING file in the top-level directory.
6b620ca3
PB
16 *
17 * Contributions after 2012-01-13 are licensed under the terms of the
18 * GNU GPL, version 2 or (at your option) any later version.
98b19252
AS
19 */
20
e4d5639d 21#include "iov.h"
98b19252
AS
22#include "monitor.h"
23#include "qemu-queue.h"
24#include "sysbus.h"
49e3fdd7 25#include "trace.h"
98b19252
AS
26#include "virtio-serial.h"
27
28/* The virtio-serial bus on top of which the ports will ride as devices */
29struct VirtIOSerialBus {
30 BusState qbus;
31
32 /* This is the parent device that provides the bus for ports. */
33 VirtIOSerial *vser;
34
35 /* The maximum number of ports that can ride on top of this bus */
36 uint32_t max_nr_ports;
37};
38
bdb917bf
AS
39typedef struct VirtIOSerialPostLoad {
40 QEMUTimer *timer;
41 uint32_t nr_active_ports;
42 struct {
43 VirtIOSerialPort *port;
44 uint8_t host_connected;
45 } *connected;
46} VirtIOSerialPostLoad;
47
98b19252
AS
48struct VirtIOSerial {
49 VirtIODevice vdev;
50
51 VirtQueue *c_ivq, *c_ovq;
52 /* Arrays of ivqs and ovqs: one per port */
53 VirtQueue **ivqs, **ovqs;
54
5e52e5f9 55 VirtIOSerialBus bus;
98b19252 56
8b53a865
AS
57 DeviceState *qdev;
58
98b19252 59 QTAILQ_HEAD(, VirtIOSerialPort) ports;
055b889f
AS
60
61 /* bitmap for identifying active ports */
62 uint32_t *ports_map;
63
98b19252 64 struct virtio_console_config config;
80dcfb85 65
bdb917bf 66 struct VirtIOSerialPostLoad *post_load;
98b19252
AS
67};
68
69static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
70{
71 VirtIOSerialPort *port;
72
055b889f
AS
73 if (id == VIRTIO_CONSOLE_BAD_ID) {
74 return NULL;
75 }
76
98b19252
AS
77 QTAILQ_FOREACH(port, &vser->ports, next) {
78 if (port->id == id)
79 return port;
80 }
81 return NULL;
82}
83
84static VirtIOSerialPort *find_port_by_vq(VirtIOSerial *vser, VirtQueue *vq)
85{
86 VirtIOSerialPort *port;
87
88 QTAILQ_FOREACH(port, &vser->ports, next) {
89 if (port->ivq == vq || port->ovq == vq)
90 return port;
91 }
92 return NULL;
93}
94
6663a195
AS
95static bool use_multiport(VirtIOSerial *vser)
96{
97 return vser->vdev.guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
98}
99
98b19252
AS
100static size_t write_to_port(VirtIOSerialPort *port,
101 const uint8_t *buf, size_t size)
102{
103 VirtQueueElement elem;
104 VirtQueue *vq;
e4d5639d 105 size_t offset;
98b19252
AS
106
107 vq = port->ivq;
108 if (!virtio_queue_ready(vq)) {
109 return 0;
110 }
98b19252 111
e4d5639d 112 offset = 0;
98b19252 113 while (offset < size) {
e4d5639d 114 size_t len;
98b19252
AS
115
116 if (!virtqueue_pop(vq, &elem)) {
117 break;
118 }
119
dcf6f5e1
MT
120 len = iov_from_buf(elem.in_sg, elem.in_num, 0,
121 buf + offset, size - offset);
e4d5639d 122 offset += len;
98b19252 123
98b19252
AS
124 virtqueue_push(vq, &elem, len);
125 }
126
127 virtio_notify(&port->vser->vdev, vq);
128 return offset;
129}
130
6bff8656 131static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
a69c7600
AS
132{
133 VirtQueueElement elem;
134
7185f931
AS
135 if (!virtio_queue_ready(vq)) {
136 return;
137 }
6bff8656
AS
138 while (virtqueue_pop(vq, &elem)) {
139 virtqueue_push(vq, &elem, 0);
140 }
141 virtio_notify(vdev, vq);
142}
143
9ed7b059 144static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
6bff8656 145 VirtIODevice *vdev)
a69c7600 146{
f82e35e3 147 VirtIOSerialPortClass *vsc;
a15bb0d6 148
6bff8656 149 assert(port);
fd11a78b 150 assert(virtio_queue_ready(vq));
a69c7600 151
f82e35e3 152 vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
a15bb0d6 153
f1925dff 154 while (!port->throttled) {
471344db 155 unsigned int i;
a69c7600 156
f1925dff
AS
157 /* Pop an elem only if we haven't left off a previous one mid-way */
158 if (!port->elem.out_num) {
159 if (!virtqueue_pop(vq, &port->elem)) {
160 break;
161 }
162 port->iov_idx = 0;
163 port->iov_offset = 0;
164 }
a69c7600 165
f1925dff
AS
166 for (i = port->iov_idx; i < port->elem.out_num; i++) {
167 size_t buf_size;
168 ssize_t ret;
169
170 buf_size = port->elem.out_sg[i].iov_len - port->iov_offset;
f82e35e3 171 ret = vsc->have_data(port,
a15bb0d6
MA
172 port->elem.out_sg[i].iov_base
173 + port->iov_offset,
174 buf_size);
f1925dff
AS
175 if (ret < 0 && ret != -EAGAIN) {
176 /* We don't handle any other type of errors here */
177 abort();
178 }
179 if (ret == -EAGAIN || (ret >= 0 && ret < buf_size)) {
ed8e5a85
CB
180 /*
181 * this is a temporary check until chardevs can signal to
182 * frontends that they are writable again. This prevents
183 * the console from going into throttled mode (forever)
184 * if virtio-console is connected to a pty without a
185 * listener. Otherwise the guest spins forever.
186 * We can revert this if
187 * 1: chardevs can notify frondends
188 * 2: the guest driver does not spin in these cases
189 */
f82e35e3 190 if (!vsc->is_console) {
ed8e5a85
CB
191 virtio_serial_throttle_port(port, true);
192 }
f1925dff
AS
193 port->iov_idx = i;
194 if (ret > 0) {
195 port->iov_offset += ret;
196 }
197 break;
198 }
199 port->iov_offset = 0;
a69c7600 200 }
f1925dff
AS
201 if (port->throttled) {
202 break;
203 }
204 virtqueue_push(vq, &port->elem, 0);
205 port->elem.out_num = 0;
a69c7600
AS
206 }
207 virtio_notify(vdev, vq);
208}
209
6bff8656 210static void flush_queued_data(VirtIOSerialPort *port)
9ed7b059 211{
a1c59752 212 assert(port);
9ed7b059 213
6b611d3a
AS
214 if (!virtio_queue_ready(port->ovq)) {
215 return;
216 }
6bff8656 217 do_flush_queued_data(port, port->ovq, &port->vser->vdev);
9ed7b059
AS
218}
219
98b19252
AS
220static size_t send_control_msg(VirtIOSerialPort *port, void *buf, size_t len)
221{
222 VirtQueueElement elem;
223 VirtQueue *vq;
224 struct virtio_console_control *cpkt;
225
226 vq = port->vser->c_ivq;
227 if (!virtio_queue_ready(vq)) {
228 return 0;
229 }
230 if (!virtqueue_pop(vq, &elem)) {
231 return 0;
232 }
233
234 cpkt = (struct virtio_console_control *)buf;
235 stl_p(&cpkt->id, port->id);
236 memcpy(elem.in_sg[0].iov_base, buf, len);
237
238 virtqueue_push(vq, &elem, len);
239 virtio_notify(&port->vser->vdev, vq);
240 return len;
241}
242
243static size_t send_control_event(VirtIOSerialPort *port, uint16_t event,
244 uint16_t value)
245{
246 struct virtio_console_control cpkt;
247
248 stw_p(&cpkt.event, event);
249 stw_p(&cpkt.value, value);
250
49e3fdd7 251 trace_virtio_serial_send_control_event(port->id, event, value);
98b19252
AS
252 return send_control_msg(port, &cpkt, sizeof(cpkt));
253}
254
255/* Functions for use inside qemu to open and read from/write to ports */
256int virtio_serial_open(VirtIOSerialPort *port)
257{
6663a195
AS
258 /* Don't allow opening an already-open port */
259 if (port->host_connected) {
260 return 0;
261 }
262 /* Send port open notification to the guest */
263 port->host_connected = true;
264 send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
265
98b19252
AS
266 return 0;
267}
268
269int virtio_serial_close(VirtIOSerialPort *port)
270{
6663a195 271 port->host_connected = false;
9ed7b059
AS
272 /*
273 * If there's any data the guest sent which the app didn't
274 * consume, reset the throttling flag and discard the data.
275 */
276 port->throttled = false;
6bff8656 277 discard_vq_data(port->ovq, &port->vser->vdev);
9ed7b059 278
6663a195
AS
279 send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
280
98b19252
AS
281 return 0;
282}
283
284/* Individual ports/apps call this function to write to the guest. */
285ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
286 size_t size)
287{
6663a195
AS
288 if (!port || !port->host_connected || !port->guest_connected) {
289 return 0;
290 }
98b19252
AS
291 return write_to_port(port, buf, size);
292}
293
294/*
295 * Readiness of the guest to accept data on a port.
296 * Returns max. data the guest can receive
297 */
298size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
299{
300 VirtQueue *vq = port->ivq;
ad3005ad 301 unsigned int bytes;
98b19252
AS
302
303 if (!virtio_queue_ready(vq) ||
304 !(port->vser->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK) ||
305 virtio_queue_empty(vq)) {
306 return 0;
307 }
6663a195
AS
308 if (use_multiport(port->vser) && !port->guest_connected) {
309 return 0;
310 }
e1f7b481 311 virtqueue_get_avail_bytes(vq, &bytes, NULL, 4096, 0);
ad3005ad 312 return bytes;
98b19252
AS
313}
314
199646d8
AL
315static void flush_queued_data_bh(void *opaque)
316{
317 VirtIOSerialPort *port = opaque;
318
319 flush_queued_data(port);
320}
321
9ed7b059
AS
322void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
323{
324 if (!port) {
325 return;
326 }
327
49e3fdd7 328 trace_virtio_serial_throttle_port(port->id, throttle);
9ed7b059
AS
329 port->throttled = throttle;
330 if (throttle) {
331 return;
332 }
199646d8 333 qemu_bh_schedule(port->bh);
9ed7b059
AS
334}
335
98b19252 336/* Guest wants to notify us of some event */
e61da14d 337static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
98b19252
AS
338{
339 struct VirtIOSerialPort *port;
f82e35e3 340 VirtIOSerialPortClass *vsc;
98b19252 341 struct virtio_console_control cpkt, *gcpkt;
160600fd
AS
342 uint8_t *buffer;
343 size_t buffer_len;
98b19252
AS
344
345 gcpkt = buf;
98b19252 346
e61da14d
AS
347 if (len < sizeof(cpkt)) {
348 /* The guest sent an invalid control packet */
349 return;
350 }
351
98b19252
AS
352 cpkt.event = lduw_p(&gcpkt->event);
353 cpkt.value = lduw_p(&gcpkt->value);
354
49e3fdd7
AS
355 trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);
356
d2e4d08b 357 if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
4048c7c3 358 if (!cpkt.value) {
6daf194d 359 error_report("virtio-serial-bus: Guest failure in adding device %s",
5e52e5f9 360 vser->bus.qbus.name);
d2e4d08b 361 return;
4048c7c3 362 }
055b889f
AS
363 /*
364 * The device is up, we can now tell the device about all the
365 * ports we have here.
366 */
367 QTAILQ_FOREACH(port, &vser->ports, next) {
368 send_control_event(port, VIRTIO_CONSOLE_PORT_ADD, 1);
369 }
d2e4d08b
LC
370 return;
371 }
055b889f 372
d2e4d08b
LC
373 port = find_port_by_id(vser, ldl_p(&gcpkt->id));
374 if (!port) {
95c9cde2 375 error_report("virtio-serial-bus: Unexpected port id %u for device %s",
d2e4d08b
LC
376 ldl_p(&gcpkt->id), vser->bus.qbus.name);
377 return;
378 }
379
49e3fdd7
AS
380 trace_virtio_serial_handle_control_message_port(port->id);
381
f82e35e3 382 vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
d2e4d08b
LC
383
384 switch(cpkt.event) {
98b19252 385 case VIRTIO_CONSOLE_PORT_READY:
4048c7c3 386 if (!cpkt.value) {
6daf194d 387 error_report("virtio-serial-bus: Guest failure in adding port %u for device %s",
5e52e5f9 388 port->id, vser->bus.qbus.name);
4048c7c3
AS
389 break;
390 }
98b19252
AS
391 /*
392 * Now that we know the guest asked for the port name, we're
393 * sure the guest has initialised whatever state is necessary
394 * for this port. Now's a good time to let the guest know if
395 * this port is a console port so that the guest can hook it
396 * up to hvc.
397 */
f82e35e3 398 if (vsc->is_console) {
98b19252
AS
399 send_control_event(port, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
400 }
6663a195 401
160600fd
AS
402 if (port->name) {
403 stw_p(&cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
404 stw_p(&cpkt.value, 1);
405
406 buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
7267c094 407 buffer = g_malloc(buffer_len);
160600fd
AS
408
409 memcpy(buffer, &cpkt, sizeof(cpkt));
410 memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name));
411 buffer[buffer_len - 1] = 0;
412
413 send_control_msg(port, buffer, buffer_len);
7267c094 414 g_free(buffer);
160600fd
AS
415 }
416
6663a195
AS
417 if (port->host_connected) {
418 send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
419 }
420
98b19252
AS
421 /*
422 * When the guest has asked us for this information it means
423 * the guest is all setup and has its virtqueues
424 * initialised. If some app is interested in knowing about
425 * this event, let it know.
426 */
f82e35e3
AL
427 if (vsc->guest_ready) {
428 vsc->guest_ready(port);
98b19252
AS
429 }
430 break;
6663a195
AS
431
432 case VIRTIO_CONSOLE_PORT_OPEN:
433 port->guest_connected = cpkt.value;
f82e35e3 434 if (cpkt.value && vsc->guest_open) {
6663a195 435 /* Send the guest opened notification if an app is interested */
f82e35e3 436 vsc->guest_open(port);
6663a195
AS
437 }
438
f82e35e3 439 if (!cpkt.value && vsc->guest_close) {
6663a195 440 /* Send the guest closed notification if an app is interested */
f82e35e3 441 vsc->guest_close(port);
6663a195
AS
442 }
443 break;
98b19252
AS
444 }
445}
446
447static void control_in(VirtIODevice *vdev, VirtQueue *vq)
448{
449}
450
451static void control_out(VirtIODevice *vdev, VirtQueue *vq)
452{
453 VirtQueueElement elem;
454 VirtIOSerial *vser;
e61da14d
AS
455 uint8_t *buf;
456 size_t len;
98b19252
AS
457
458 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
459
e61da14d
AS
460 len = 0;
461 buf = NULL;
98b19252 462 while (virtqueue_pop(vq, &elem)) {
45270ad8 463 size_t cur_len;
e61da14d
AS
464
465 cur_len = iov_size(elem.out_sg, elem.out_num);
466 /*
467 * Allocate a new buf only if we didn't have one previously or
468 * if the size of the buf differs
469 */
470 if (cur_len > len) {
7267c094 471 g_free(buf);
e61da14d 472
7267c094 473 buf = g_malloc(cur_len);
e61da14d
AS
474 len = cur_len;
475 }
dcf6f5e1 476 iov_to_buf(elem.out_sg, elem.out_num, 0, buf, cur_len);
e61da14d 477
45270ad8 478 handle_control_message(vser, buf, cur_len);
1e4476aa 479 virtqueue_push(vq, &elem, 0);
98b19252 480 }
7267c094 481 g_free(buf);
98b19252
AS
482 virtio_notify(vdev, vq);
483}
484
485/* Guest wrote something to some port. */
486static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
487{
488 VirtIOSerial *vser;
a69c7600 489 VirtIOSerialPort *port;
98b19252
AS
490
491 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
a69c7600 492 port = find_port_by_vq(vser, vq);
98b19252 493
03ecd2c8 494 if (!port || !port->host_connected) {
6bff8656
AS
495 discard_vq_data(vq, vdev);
496 return;
497 }
e9b382b0
AS
498
499 if (!port->throttled) {
500 do_flush_queued_data(port, vq, vdev);
9ed7b059
AS
501 return;
502 }
98b19252
AS
503}
504
505static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
506{
507}
508
509static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
510{
306eb457
AS
511 VirtIOSerial *vser;
512
513 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
514
5e52e5f9 515 if (vser->bus.max_nr_ports > 1) {
ee4d45be
MT
516 features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
517 }
98b19252
AS
518 return features;
519}
520
521/* Guest requested config info */
522static void get_config(VirtIODevice *vdev, uint8_t *config_data)
523{
524 VirtIOSerial *vser;
525
526 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
527 memcpy(config_data, &vser->config, sizeof(struct virtio_console_config));
528}
529
530static void set_config(VirtIODevice *vdev, const uint8_t *config_data)
531{
532 struct virtio_console_config config;
533
534 memcpy(&config, config_data, sizeof(config));
535}
536
43997225
AS
537static void guest_reset(VirtIOSerial *vser)
538{
539 VirtIOSerialPort *port;
540 VirtIOSerialPortClass *vsc;
541
542 QTAILQ_FOREACH(port, &vser->ports, next) {
543 vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
544 if (port->guest_connected) {
545 port->guest_connected = false;
546
547 if (vsc->guest_close)
548 vsc->guest_close(port);
549 }
550 }
551}
552
62a9fbf7
AL
553static void set_status(VirtIODevice *vdev, uint8_t status)
554{
555 VirtIOSerial *vser;
556 VirtIOSerialPort *port;
557
558 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
559 port = find_port_by_id(vser, 0);
560
561 if (port && !use_multiport(port->vser)
562 && (status & VIRTIO_CONFIG_S_DRIVER_OK)) {
563 /*
564 * Non-multiport guests won't be able to tell us guest
565 * open/close status. Such guests can only have a port at id
566 * 0, so set guest_connected for such ports as soon as guest
567 * is up.
568 */
569 port->guest_connected = true;
570 }
43997225
AS
571 if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
572 guest_reset(vser);
573 }
574}
575
576static void vser_reset(VirtIODevice *vdev)
577{
578 VirtIOSerial *vser;
579
580 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
581 guest_reset(vser);
62a9fbf7
AL
582}
583
98b19252
AS
584static void virtio_serial_save(QEMUFile *f, void *opaque)
585{
586 VirtIOSerial *s = opaque;
6663a195
AS
587 VirtIOSerialPort *port;
588 uint32_t nr_active_ports;
5c1c9bb2 589 unsigned int i, max_nr_ports;
98b19252
AS
590
591 /* The virtio device */
592 virtio_save(&s->vdev, f);
593
594 /* The config space */
595 qemu_put_be16s(f, &s->config.cols);
596 qemu_put_be16s(f, &s->config.rows);
6663a195 597
055b889f
AS
598 qemu_put_be32s(f, &s->config.max_nr_ports);
599
600 /* The ports map */
5c1c9bb2
AK
601 max_nr_ports = tswap32(s->config.max_nr_ports);
602 for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
055b889f
AS
603 qemu_put_be32s(f, &s->ports_map[i]);
604 }
6663a195 605
055b889f 606 /* Ports */
e245795b 607
6663a195 608 nr_active_ports = 0;
e245795b 609 QTAILQ_FOREACH(port, &s->ports, next) {
6663a195 610 nr_active_ports++;
e245795b 611 }
6663a195
AS
612
613 qemu_put_be32s(f, &nr_active_ports);
614
615 /*
616 * Items in struct VirtIOSerialPort.
617 */
618 QTAILQ_FOREACH(port, &s->ports, next) {
37f95bf3
AS
619 uint32_t elem_popped;
620
6663a195
AS
621 qemu_put_be32s(f, &port->id);
622 qemu_put_byte(f, port->guest_connected);
31abe21f 623 qemu_put_byte(f, port->host_connected);
37f95bf3
AS
624
625 elem_popped = 0;
626 if (port->elem.out_num) {
627 elem_popped = 1;
628 }
629 qemu_put_be32s(f, &elem_popped);
630 if (elem_popped) {
631 qemu_put_be32s(f, &port->iov_idx);
632 qemu_put_be64s(f, &port->iov_offset);
633
634 qemu_put_buffer(f, (unsigned char *)&port->elem,
635 sizeof(port->elem));
636 }
6663a195 637 }
98b19252
AS
638}
639
80dcfb85
AL
640static void virtio_serial_post_load_timer_cb(void *opaque)
641{
c3587ca1 642 uint32_t i;
80dcfb85
AL
643 VirtIOSerial *s = opaque;
644 VirtIOSerialPort *port;
645 uint8_t host_connected;
646
bdb917bf
AS
647 if (!s->post_load) {
648 return;
649 }
650 for (i = 0 ; i < s->post_load->nr_active_ports; ++i) {
651 port = s->post_load->connected[i].port;
652 host_connected = s->post_load->connected[i].host_connected;
80dcfb85
AL
653 if (host_connected != port->host_connected) {
654 /*
655 * We have to let the guest know of the host connection
656 * status change
657 */
658 send_control_event(port, VIRTIO_CONSOLE_PORT_OPEN,
659 port->host_connected);
660 }
661 }
bdb917bf
AS
662 g_free(s->post_load->connected);
663 qemu_free_timer(s->post_load->timer);
664 g_free(s->post_load);
665 s->post_load = NULL;
80dcfb85
AL
666}
667
2e575a86
AS
668static int fetch_active_ports_list(QEMUFile *f, int version_id,
669 VirtIOSerial *s, uint32_t nr_active_ports)
670{
671 uint32_t i;
672
bdb917bf
AS
673 s->post_load = g_malloc0(sizeof(*s->post_load));
674 s->post_load->nr_active_ports = nr_active_ports;
675 s->post_load->connected =
676 g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);
677
678 s->post_load->timer = qemu_new_timer_ns(vm_clock,
679 virtio_serial_post_load_timer_cb,
680 s);
2e575a86
AS
681
682 /* Items in struct VirtIOSerialPort */
683 for (i = 0; i < nr_active_ports; i++) {
684 VirtIOSerialPort *port;
685 uint32_t id;
686
687 id = qemu_get_be32(f);
688 port = find_port_by_id(s, id);
689 if (!port) {
690 return -EINVAL;
691 }
692
693 port->guest_connected = qemu_get_byte(f);
bdb917bf
AS
694 s->post_load->connected[i].port = port;
695 s->post_load->connected[i].host_connected = qemu_get_byte(f);
2e575a86
AS
696
697 if (version_id > 2) {
698 uint32_t elem_popped;
699
700 qemu_get_be32s(f, &elem_popped);
701 if (elem_popped) {
702 qemu_get_be32s(f, &port->iov_idx);
703 qemu_get_be64s(f, &port->iov_offset);
704
705 qemu_get_buffer(f, (unsigned char *)&port->elem,
706 sizeof(port->elem));
707 virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
708 port->elem.in_num, 1);
709 virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
710 port->elem.out_num, 1);
711
712 /*
713 * Port was throttled on source machine. Let's
714 * unthrottle it here so data starts flowing again.
715 */
716 virtio_serial_throttle_port(port, false);
717 }
718 }
719 }
bdb917bf 720 qemu_mod_timer(s->post_load->timer, 1);
2e575a86
AS
721 return 0;
722}
723
98b19252
AS
724static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
725{
726 VirtIOSerial *s = opaque;
f83ccb3e 727 uint32_t max_nr_ports, nr_active_ports, ports_map;
6663a195 728 unsigned int i;
2a633c46 729 int ret;
98b19252 730
37f95bf3 731 if (version_id > 3) {
98b19252
AS
732 return -EINVAL;
733 }
6663a195 734
98b19252 735 /* The virtio device */
2a633c46
OW
736 ret = virtio_load(&s->vdev, f);
737 if (ret) {
738 return ret;
739 }
98b19252
AS
740
741 if (version_id < 2) {
742 return 0;
743 }
744
745 /* The config space */
746 qemu_get_be16s(f, &s->config.cols);
747 qemu_get_be16s(f, &s->config.rows);
295587f7 748
055b889f 749 qemu_get_be32s(f, &max_nr_ports);
5c1c9bb2
AK
750 tswap32s(&max_nr_ports);
751 if (max_nr_ports > tswap32(s->config.max_nr_ports)) {
055b889f 752 /* Source could have had more ports than us. Fail migration. */
295587f7
AS
753 return -EINVAL;
754 }
98b19252 755
055b889f 756 for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
f83ccb3e 757 qemu_get_be32s(f, &ports_map);
055b889f 758
f83ccb3e 759 if (ports_map != s->ports_map[i]) {
055b889f
AS
760 /*
761 * Ports active on source and destination don't
762 * match. Fail migration.
763 */
055b889f
AS
764 return -EINVAL;
765 }
e245795b
AS
766 }
767
6663a195
AS
768 qemu_get_be32s(f, &nr_active_ports);
769
2e575a86
AS
770 if (nr_active_ports) {
771 ret = fetch_active_ports_list(f, version_id, s, nr_active_ports);
772 if (ret) {
773 return ret;
37f95bf3 774 }
6663a195 775 }
98b19252
AS
776 return 0;
777}
778
779static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);
780
3cb75a7c
PB
781static Property virtser_props[] = {
782 DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
783 DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
784 DEFINE_PROP_END_OF_LIST()
785};
786
0d936928
AL
787#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
788#define VIRTIO_SERIAL_BUS(obj) \
789 OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS)
790
791static void virtser_bus_class_init(ObjectClass *klass, void *data)
792{
793 BusClass *k = BUS_CLASS(klass);
794 k->print_dev = virtser_bus_dev_print;
795}
796
797static const TypeInfo virtser_bus_info = {
798 .name = TYPE_VIRTIO_SERIAL_BUS,
799 .parent = TYPE_BUS,
800 .instance_size = sizeof(VirtIOSerialBus),
801 .class_init = virtser_bus_class_init,
98b19252
AS
802};
803
98b19252
AS
804static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
805{
a43f9c90 806 VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
98b19252 807
021a1318
MA
808 monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n",
809 indent, "", port->id,
810 port->guest_connected ? "on" : "off",
811 port->host_connected ? "on" : "off",
812 port->throttled ? "on" : "off");
98b19252
AS
813}
814
055b889f
AS
815/* This function is only used if a port id is not provided by the user */
816static uint32_t find_free_port_id(VirtIOSerial *vser)
817{
5c1c9bb2 818 unsigned int i, max_nr_ports;
055b889f 819
5c1c9bb2
AK
820 max_nr_ports = tswap32(vser->config.max_nr_ports);
821 for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
055b889f
AS
822 uint32_t map, bit;
823
824 map = vser->ports_map[i];
825 bit = ffs(~map);
826 if (bit) {
827 return (bit - 1) + i * 32;
828 }
829 }
830 return VIRTIO_CONSOLE_BAD_ID;
831}
832
833static void mark_port_added(VirtIOSerial *vser, uint32_t port_id)
834{
835 unsigned int i;
836
837 i = port_id / 32;
838 vser->ports_map[i] |= 1U << (port_id % 32);
839}
840
841static void add_port(VirtIOSerial *vser, uint32_t port_id)
842{
843 mark_port_added(vser, port_id);
844
845 send_control_event(find_port_by_id(vser, port_id),
846 VIRTIO_CONSOLE_PORT_ADD, 1);
847}
848
849static void remove_port(VirtIOSerial *vser, uint32_t port_id)
850{
9ed7b059 851 VirtIOSerialPort *port;
055b889f
AS
852 unsigned int i;
853
854 i = port_id / 32;
855 vser->ports_map[i] &= ~(1U << (port_id % 32));
856
9ed7b059
AS
857 port = find_port_by_id(vser, port_id);
858 /* Flush out any unconsumed buffers first */
6bff8656 859 discard_vq_data(port->ovq, &port->vser->vdev);
9ed7b059
AS
860
861 send_control_event(port, VIRTIO_CONSOLE_PORT_REMOVE, 1);
055b889f
AS
862}
863
d307af79 864static int virtser_port_qdev_init(DeviceState *qdev)
98b19252 865{
a43f9c90 866 VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
f82e35e3 867 VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
98b19252 868 VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus);
5c1c9bb2 869 int ret, max_nr_ports;
98b19252
AS
870 bool plugging_port0;
871
872 port->vser = bus->vser;
199646d8 873 port->bh = qemu_bh_new(flush_queued_data_bh, port);
98b19252 874
f82e35e3 875 assert(vsc->have_data);
03ecd2c8 876
98b19252
AS
877 /*
878 * Is the first console port we're seeing? If so, put it up at
879 * location 0. This is done for backward compatibility (old
880 * kernel, new qemu).
881 */
f82e35e3 882 plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
98b19252 883
055b889f 884 if (find_port_by_id(port->vser, port->id)) {
6daf194d 885 error_report("virtio-serial-bus: A port already exists at id %u",
055b889f 886 port->id);
98b19252
AS
887 return -1;
888 }
98b19252 889
055b889f
AS
890 if (port->id == VIRTIO_CONSOLE_BAD_ID) {
891 if (plugging_port0) {
892 port->id = 0;
893 } else {
894 port->id = find_free_port_id(port->vser);
895 if (port->id == VIRTIO_CONSOLE_BAD_ID) {
6daf194d 896 error_report("virtio-serial-bus: Maximum port limit for this device reached");
055b889f
AS
897 return -1;
898 }
899 }
900 }
901
5c1c9bb2
AK
902 max_nr_ports = tswap32(port->vser->config.max_nr_ports);
903 if (port->id >= max_nr_ports) {
6daf194d 904 error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u",
5c1c9bb2 905 max_nr_ports - 1);
055b889f
AS
906 return -1;
907 }
908
f82e35e3 909 ret = vsc->init(port);
98b19252
AS
910 if (ret) {
911 return ret;
912 }
913
f1925dff
AS
914 port->elem.out_num = 0;
915
98b19252
AS
916 QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
917 port->ivq = port->vser->ivqs[port->id];
918 port->ovq = port->vser->ovqs[port->id];
919
055b889f
AS
920 add_port(port->vser, port->id);
921
98b19252
AS
922 /* Send an update to the guest about this new port added */
923 virtio_notify_config(&port->vser->vdev);
924
925 return ret;
926}
927
928static int virtser_port_qdev_exit(DeviceState *qdev)
929{
a43f9c90 930 VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
f82e35e3 931 VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
98b19252
AS
932 VirtIOSerial *vser = port->vser;
933
199646d8 934 qemu_bh_delete(port->bh);
055b889f 935 remove_port(port->vser, port->id);
f146ec9a 936
98b19252
AS
937 QTAILQ_REMOVE(&vser->ports, port, next);
938
f82e35e3
AL
939 if (vsc->exit) {
940 vsc->exit(port);
a15bb0d6 941 }
98b19252
AS
942 return 0;
943}
944
6b331efb 945VirtIODevice *virtio_serial_init(DeviceState *dev, virtio_serial_conf *conf)
98b19252
AS
946{
947 VirtIOSerial *vser;
948 VirtIODevice *vdev;
5ab4bb59 949 uint32_t i, max_supported_ports;
98b19252 950
6b331efb 951 if (!conf->max_virtserial_ports)
98b19252
AS
952 return NULL;
953
5ab4bb59
AS
954 /* Each port takes 2 queues, and one pair is for the control queue */
955 max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;
956
6b331efb 957 if (conf->max_virtserial_ports > max_supported_ports) {
5ab4bb59
AS
958 error_report("maximum ports supported: %u", max_supported_ports);
959 return NULL;
960 }
961
98b19252
AS
962 vdev = virtio_common_init("virtio-serial", VIRTIO_ID_CONSOLE,
963 sizeof(struct virtio_console_config),
964 sizeof(VirtIOSerial));
965
966 vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
967
968 /* Spawn a new virtio-serial bus on which the ports will ride as devices */
0d936928 969 qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, dev, NULL);
5e52e5f9
MA
970 vser->bus.qbus.allow_hotplug = 1;
971 vser->bus.vser = vser;
98b19252
AS
972 QTAILQ_INIT(&vser->ports);
973
5e52e5f9 974 vser->bus.max_nr_ports = conf->max_virtserial_ports;
7267c094
AL
975 vser->ivqs = g_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
976 vser->ovqs = g_malloc(conf->max_virtserial_ports * sizeof(VirtQueue *));
98b19252
AS
977
978 /* Add a queue for host to guest transfers for port 0 (backward compat) */
979 vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
980 /* Add a queue for guest to host transfers for port 0 (backward compat) */
981 vser->ovqs[0] = virtio_add_queue(vdev, 128, handle_output);
982
a01a9cb8
AS
983 /* TODO: host to guest notifications can get dropped
984 * if the queue fills up. Implement queueing in host,
985 * this might also make it possible to reduce the control
986 * queue size: as guest preposts buffers there,
987 * this will save 4Kbyte of guest memory per entry. */
988
98b19252 989 /* control queue: host to guest */
a01a9cb8 990 vser->c_ivq = virtio_add_queue(vdev, 32, control_in);
98b19252 991 /* control queue: guest to host */
a01a9cb8 992 vser->c_ovq = virtio_add_queue(vdev, 32, control_out);
98b19252 993
5e52e5f9 994 for (i = 1; i < vser->bus.max_nr_ports; i++) {
98b19252
AS
995 /* Add a per-port queue for host to guest transfers */
996 vser->ivqs[i] = virtio_add_queue(vdev, 128, handle_input);
997 /* Add a per-per queue for guest to host transfers */
998 vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
999 }
1000
5c1c9bb2 1001 vser->config.max_nr_ports = tswap32(conf->max_virtserial_ports);
7267c094 1002 vser->ports_map = g_malloc0(((conf->max_virtserial_ports + 31) / 32)
a132a679 1003 * sizeof(vser->ports_map[0]));
98b19252
AS
1004 /*
1005 * Reserve location 0 for a console port for backward compat
1006 * (old kernel, new qemu)
1007 */
055b889f 1008 mark_port_added(vser, 0);
98b19252
AS
1009
1010 vser->vdev.get_features = get_features;
1011 vser->vdev.get_config = get_config;
1012 vser->vdev.set_config = set_config;
62a9fbf7 1013 vser->vdev.set_status = set_status;
43997225 1014 vser->vdev.reset = vser_reset;
98b19252 1015
8b53a865
AS
1016 vser->qdev = dev;
1017
bdb917bf
AS
1018 vser->post_load = NULL;
1019
98b19252
AS
1020 /*
1021 * Register for the savevm section with the virtio-console name
1022 * to preserve backward compat
1023 */
37f95bf3 1024 register_savevm(dev, "virtio-console", -1, 3, virtio_serial_save,
98b19252
AS
1025 virtio_serial_load, vser);
1026
1027 return vdev;
1028}
8b53a865
AS
1029
1030void virtio_serial_exit(VirtIODevice *vdev)
1031{
1032 VirtIOSerial *vser = DO_UPCAST(VirtIOSerial, vdev, vdev);
1033
1034 unregister_savevm(vser->qdev, "virtio-console", vser);
1035
7267c094
AL
1036 g_free(vser->ivqs);
1037 g_free(vser->ovqs);
1038 g_free(vser->ports_map);
bdb917bf
AS
1039 if (vser->post_load) {
1040 g_free(vser->post_load->connected);
a75bf146 1041 qemu_del_timer(vser->post_load->timer);
bdb917bf
AS
1042 qemu_free_timer(vser->post_load->timer);
1043 g_free(vser->post_load);
1044 }
8b53a865
AS
1045 virtio_cleanup(vdev);
1046}
f82e35e3 1047
39bffca2
AL
1048static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
1049{
1050 DeviceClass *k = DEVICE_CLASS(klass);
1051 k->init = virtser_port_qdev_init;
0d936928 1052 k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
39bffca2
AL
1053 k->exit = virtser_port_qdev_exit;
1054 k->unplug = qdev_simple_unplug_cb;
bce54474 1055 k->props = virtser_props;
39bffca2
AL
1056}
1057
f82e35e3
AL
1058static TypeInfo virtio_serial_port_type_info = {
1059 .name = TYPE_VIRTIO_SERIAL_PORT,
1060 .parent = TYPE_DEVICE,
1061 .instance_size = sizeof(VirtIOSerialPort),
1062 .abstract = true,
1063 .class_size = sizeof(VirtIOSerialPortClass),
39bffca2 1064 .class_init = virtio_serial_port_class_init,
f82e35e3
AL
1065};
1066
83f7d43a 1067static void virtio_serial_register_types(void)
f82e35e3 1068{
0d936928 1069 type_register_static(&virtser_bus_info);
f82e35e3
AL
1070 type_register_static(&virtio_serial_port_type_info);
1071}
1072
83f7d43a 1073type_init(virtio_serial_register_types)