virtio-serial-bus.c 28.7 KB
Newer Older
1 2 3
/*
 * A bus for connecting virtio serial and console ports
 *
4
 * Copyright (C) 2009, 2010 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15
 *
 * Author(s):
 *  Amit Shah <amit.shah@redhat.com>
 *
 * Some earlier parts are:
 *  Copyright IBM, Corp. 2008
 * authored by
 *  Christian Ehrhardt <ehrhardt@linux.vnet.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
16 17 18
 *
 * Contributions after 2012-01-13 are licensed under the terms of the
 * GNU GPL, version 2 or (at your option) any later version.
19 20
 */

21
#include "qemu/iov.h"
22
#include "monitor/monitor.h"
23
#include "qemu/queue.h"
24
#include "hw/sysbus.h"
A
Amit Shah 已提交
25
#include "trace.h"
P
Paolo Bonzini 已提交
26
#include "hw/virtio/virtio-serial.h"
27 28 29 30 31

static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
{
    VirtIOSerialPort *port;

32 33 34 35
    if (id == VIRTIO_CONSOLE_BAD_ID) {
        return NULL;
    }

36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
    QTAILQ_FOREACH(port, &vser->ports, next) {
        if (port->id == id)
            return port;
    }
    return NULL;
}

static VirtIOSerialPort *find_port_by_vq(VirtIOSerial *vser, VirtQueue *vq)
{
    VirtIOSerialPort *port;

    QTAILQ_FOREACH(port, &vser->ports, next) {
        if (port->ivq == vq || port->ovq == vq)
            return port;
    }
    return NULL;
}

54 55
static bool use_multiport(VirtIOSerial *vser)
{
56 57
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
    return vdev->guest_features & (1 << VIRTIO_CONSOLE_F_MULTIPORT);
58 59
}

60 61 62 63 64
static size_t write_to_port(VirtIOSerialPort *port,
                            const uint8_t *buf, size_t size)
{
    VirtQueueElement elem;
    VirtQueue *vq;
65
    size_t offset;
66 67 68 69 70 71

    vq = port->ivq;
    if (!virtio_queue_ready(vq)) {
        return 0;
    }

72
    offset = 0;
73
    while (offset < size) {
74
        size_t len;
75 76 77 78 79

        if (!virtqueue_pop(vq, &elem)) {
            break;
        }

80 81
        len = iov_from_buf(elem.in_sg, elem.in_num, 0,
                           buf + offset, size - offset);
82
        offset += len;
83 84 85 86

        virtqueue_push(vq, &elem, len);
    }

87
    virtio_notify(VIRTIO_DEVICE(port->vser), vq);
88 89 90
    return offset;
}

91
static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
92 93 94
{
    VirtQueueElement elem;

95 96 97
    if (!virtio_queue_ready(vq)) {
        return;
    }
98 99 100 101 102 103
    while (virtqueue_pop(vq, &elem)) {
        virtqueue_push(vq, &elem, 0);
    }
    virtio_notify(vdev, vq);
}

104
static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
105
                                 VirtIODevice *vdev)
106
{
107
    VirtIOSerialPortClass *vsc;
108

109
    assert(port);
110
    assert(virtio_queue_ready(vq));
111

112
    vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
113

114
    while (!port->throttled) {
115
        unsigned int i;
116

117 118 119 120 121 122 123 124
        /* Pop an elem only if we haven't left off a previous one mid-way */
        if (!port->elem.out_num) {
            if (!virtqueue_pop(vq, &port->elem)) {
                break;
            }
            port->iov_idx = 0;
            port->iov_offset = 0;
        }
125

126 127 128 129 130
        for (i = port->iov_idx; i < port->elem.out_num; i++) {
            size_t buf_size;
            ssize_t ret;

            buf_size = port->elem.out_sg[i].iov_len - port->iov_offset;
131
            ret = vsc->have_data(port,
132 133 134
                                  port->elem.out_sg[i].iov_base
                                  + port->iov_offset,
                                  buf_size);
135
            if (port->throttled) {
136 137 138 139 140 141 142
                port->iov_idx = i;
                if (ret > 0) {
                    port->iov_offset += ret;
                }
                break;
            }
            port->iov_offset = 0;
143
        }
144 145 146 147 148
        if (port->throttled) {
            break;
        }
        virtqueue_push(vq, &port->elem, 0);
        port->elem.out_num = 0;
149 150 151 152
    }
    virtio_notify(vdev, vq);
}

153
static void flush_queued_data(VirtIOSerialPort *port)
154
{
155
    assert(port);
156

157 158 159
    if (!virtio_queue_ready(port->ovq)) {
        return;
    }
160
    do_flush_queued_data(port, port->ovq, VIRTIO_DEVICE(port->vser));
161 162
}

163
static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
164 165 166 167
{
    VirtQueueElement elem;
    VirtQueue *vq;

168
    vq = vser->c_ivq;
169 170 171 172 173 174 175 176 177 178
    if (!virtio_queue_ready(vq)) {
        return 0;
    }
    if (!virtqueue_pop(vq, &elem)) {
        return 0;
    }

    memcpy(elem.in_sg[0].iov_base, buf, len);

    virtqueue_push(vq, &elem, len);
179
    virtio_notify(VIRTIO_DEVICE(vser), vq);
180 181 182
    return len;
}

183 184
static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id,
                                 uint16_t event, uint16_t value)
185 186 187
{
    struct virtio_console_control cpkt;

188
    stl_p(&cpkt.id, port_id);
189 190 191
    stw_p(&cpkt.event, event);
    stw_p(&cpkt.value, value);

192 193
    trace_virtio_serial_send_control_event(port_id, event, value);
    return send_control_msg(vser, &cpkt, sizeof(cpkt));
194 195 196 197 198
}

/* Functions for use inside qemu to open and read from/write to ports */
int virtio_serial_open(VirtIOSerialPort *port)
{
199 200 201 202 203 204
    /* Don't allow opening an already-open port */
    if (port->host_connected) {
        return 0;
    }
    /* Send port open notification to the guest */
    port->host_connected = true;
205
    send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
206

207 208 209 210 211
    return 0;
}

int virtio_serial_close(VirtIOSerialPort *port)
{
212
    port->host_connected = false;
213 214 215 216 217
    /*
     * If there's any data the guest sent which the app didn't
     * consume, reset the throttling flag and discard the data.
     */
    port->throttled = false;
218
    discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser));
219

220
    send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0);
221

222 223 224 225 226 227 228
    return 0;
}

/* Individual ports/apps call this function to write to the guest. */
ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
                            size_t size)
{
229 230 231
    if (!port || !port->host_connected || !port->guest_connected) {
        return 0;
    }
232 233 234 235 236 237 238 239 240
    return write_to_port(port, buf, size);
}

/*
 * Readiness of the guest to accept data on a port.
 * Returns max. data the guest can receive
 */
size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
{
241
    VirtIODevice *vdev = VIRTIO_DEVICE(port->vser);
242
    VirtQueue *vq = port->ivq;
243
    unsigned int bytes;
244 245

    if (!virtio_queue_ready(vq) ||
246
        !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) ||
247 248 249
        virtio_queue_empty(vq)) {
        return 0;
    }
250 251 252
    if (use_multiport(port->vser) && !port->guest_connected) {
        return 0;
    }
253
    virtqueue_get_avail_bytes(vq, &bytes, NULL, 4096, 0);
254
    return bytes;
255 256
}

257 258 259 260 261 262 263
static void flush_queued_data_bh(void *opaque)
{
    VirtIOSerialPort *port = opaque;

    flush_queued_data(port);
}

264 265 266 267 268 269
void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
{
    if (!port) {
        return;
    }

A
Amit Shah 已提交
270
    trace_virtio_serial_throttle_port(port->id, throttle);
271 272 273 274
    port->throttled = throttle;
    if (throttle) {
        return;
    }
275
    qemu_bh_schedule(port->bh);
276 277
}

278
/* Guest wants to notify us of some event */
279
static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
280 281
{
    struct VirtIOSerialPort *port;
282
    VirtIOSerialPortClass *vsc;
283
    struct virtio_console_control cpkt, *gcpkt;
284 285
    uint8_t *buffer;
    size_t buffer_len;
286 287 288

    gcpkt = buf;

289 290 291 292 293
    if (len < sizeof(cpkt)) {
        /* The guest sent an invalid control packet */
        return;
    }

294 295 296
    cpkt.event = lduw_p(&gcpkt->event);
    cpkt.value = lduw_p(&gcpkt->value);

A
Amit Shah 已提交
297 298
    trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);

299
    if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
300
        if (!cpkt.value) {
301
            error_report("virtio-serial-bus: Guest failure in adding device %s",
302
                         vser->bus.qbus.name);
303
            return;
304
        }
305 306 307 308 309
        /*
         * The device is up, we can now tell the device about all the
         * ports we have here.
         */
        QTAILQ_FOREACH(port, &vser->ports, next) {
310
            send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_ADD, 1);
311
        }
312 313
        return;
    }
314

315 316
    port = find_port_by_id(vser, ldl_p(&gcpkt->id));
    if (!port) {
317
        error_report("virtio-serial-bus: Unexpected port id %u for device %s",
318 319 320 321
                     ldl_p(&gcpkt->id), vser->bus.qbus.name);
        return;
    }

A
Amit Shah 已提交
322 323
    trace_virtio_serial_handle_control_message_port(port->id);

324
    vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
325 326

    switch(cpkt.event) {
327
    case VIRTIO_CONSOLE_PORT_READY:
328
        if (!cpkt.value) {
329
            error_report("virtio-serial-bus: Guest failure in adding port %u for device %s",
330
                         port->id, vser->bus.qbus.name);
331 332
            break;
        }
333 334 335 336 337 338 339
        /*
         * Now that we know the guest asked for the port name, we're
         * sure the guest has initialised whatever state is necessary
         * for this port. Now's a good time to let the guest know if
         * this port is a console port so that the guest can hook it
         * up to hvc.
         */
340
        if (vsc->is_console) {
341
            send_control_event(vser, port->id, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
342
        }
343

344
        if (port->name) {
345
            stl_p(&cpkt.id, port->id);
346 347 348 349
            stw_p(&cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
            stw_p(&cpkt.value, 1);

            buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
350
            buffer = g_malloc(buffer_len);
351 352 353 354 355

            memcpy(buffer, &cpkt, sizeof(cpkt));
            memcpy(buffer + sizeof(cpkt), port->name, strlen(port->name));
            buffer[buffer_len - 1] = 0;

356
            send_control_msg(vser, buffer, buffer_len);
357
            g_free(buffer);
358 359
        }

360
        if (port->host_connected) {
361
            send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
362 363
        }

364 365 366 367 368 369
        /*
         * When the guest has asked us for this information it means
         * the guest is all setup and has its virtqueues
         * initialised. If some app is interested in knowing about
         * this event, let it know.
         */
370 371
        if (vsc->guest_ready) {
            vsc->guest_ready(port);
372 373
        }
        break;
374 375 376

    case VIRTIO_CONSOLE_PORT_OPEN:
        port->guest_connected = cpkt.value;
377
        if (vsc->set_guest_connected) {
378
            /* Send the guest opened notification if an app is interested */
379
            vsc->set_guest_connected(port, cpkt.value);
380 381
        }
        break;
382 383 384 385 386 387 388 389 390 391 392
    }
}

static void control_in(VirtIODevice *vdev, VirtQueue *vq)
{
}

static void control_out(VirtIODevice *vdev, VirtQueue *vq)
{
    VirtQueueElement elem;
    VirtIOSerial *vser;
393 394
    uint8_t *buf;
    size_t len;
395

396
    vser = VIRTIO_SERIAL(vdev);
397

398 399
    len = 0;
    buf = NULL;
400
    while (virtqueue_pop(vq, &elem)) {
401
        size_t cur_len;
402 403 404 405 406 407 408

        cur_len = iov_size(elem.out_sg, elem.out_num);
        /*
         * Allocate a new buf only if we didn't have one previously or
         * if the size of the buf differs
         */
        if (cur_len > len) {
409
            g_free(buf);
410

411
            buf = g_malloc(cur_len);
412 413
            len = cur_len;
        }
414
        iov_to_buf(elem.out_sg, elem.out_num, 0, buf, cur_len);
415

416
        handle_control_message(vser, buf, cur_len);
417
        virtqueue_push(vq, &elem, 0);
418
    }
419
    g_free(buf);
420 421 422 423 424 425 426
    virtio_notify(vdev, vq);
}

/* Guest wrote something to some port. */
static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
{
    VirtIOSerial *vser;
427
    VirtIOSerialPort *port;
428

429
    vser = VIRTIO_SERIAL(vdev);
430
    port = find_port_by_vq(vser, vq);
431

432
    if (!port || !port->host_connected) {
433 434 435
        discard_vq_data(vq, vdev);
        return;
    }
436 437 438

    if (!port->throttled) {
        do_flush_queued_data(port, vq, vdev);
439 440
        return;
    }
441 442 443 444 445 446 447 448
}

static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
{
}

static uint32_t get_features(VirtIODevice *vdev, uint32_t features)
{
449 450
    VirtIOSerial *vser;

451
    vser = VIRTIO_SERIAL(vdev);
452

453
    if (vser->bus.max_nr_ports > 1) {
454 455
        features |= (1 << VIRTIO_CONSOLE_F_MULTIPORT);
    }
456 457 458 459 460 461 462 463
    return features;
}

/* Guest requested config info */
static void get_config(VirtIODevice *vdev, uint8_t *config_data)
{
    VirtIOSerial *vser;

464
    vser = VIRTIO_SERIAL(vdev);
465 466 467 468 469 470 471 472 473 474
    memcpy(config_data, &vser->config, sizeof(struct virtio_console_config));
}

static void set_config(VirtIODevice *vdev, const uint8_t *config_data)
{
    struct virtio_console_config config;

    memcpy(&config, config_data, sizeof(config));
}

475 476 477 478 479 480 481 482 483
static void guest_reset(VirtIOSerial *vser)
{
    VirtIOSerialPort *port;
    VirtIOSerialPortClass *vsc;

    QTAILQ_FOREACH(port, &vser->ports, next) {
        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
        if (port->guest_connected) {
            port->guest_connected = false;
484 485 486
            if (vsc->set_guest_connected) {
                vsc->set_guest_connected(port, false);
            }
487 488 489 490
        }
    }
}

491 492 493 494 495
static void set_status(VirtIODevice *vdev, uint8_t status)
{
    VirtIOSerial *vser;
    VirtIOSerialPort *port;

496
    vser = VIRTIO_SERIAL(vdev);
497 498 499 500 501 502 503 504 505 506 507 508
    port = find_port_by_id(vser, 0);

    if (port && !use_multiport(port->vser)
        && (status & VIRTIO_CONFIG_S_DRIVER_OK)) {
        /*
         * Non-multiport guests won't be able to tell us guest
         * open/close status.  Such guests can only have a port at id
         * 0, so set guest_connected for such ports as soon as guest
         * is up.
         */
        port->guest_connected = true;
    }
509 510 511 512 513 514 515 516 517
    if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
        guest_reset(vser);
    }
}

static void vser_reset(VirtIODevice *vdev)
{
    VirtIOSerial *vser;

518
    vser = VIRTIO_SERIAL(vdev);
519
    guest_reset(vser);
520 521
}

522 523
static void virtio_serial_save(QEMUFile *f, void *opaque)
{
524
    VirtIOSerial *s = VIRTIO_SERIAL(opaque);
525 526
    VirtIOSerialPort *port;
    uint32_t nr_active_ports;
527
    unsigned int i, max_nr_ports;
528 529

    /* The virtio device */
530
    virtio_save(VIRTIO_DEVICE(s), f);
531 532 533 534

    /* The config space */
    qemu_put_be16s(f, &s->config.cols);
    qemu_put_be16s(f, &s->config.rows);
535

536 537 538
    qemu_put_be32s(f, &s->config.max_nr_ports);

    /* The ports map */
539 540
    max_nr_ports = tswap32(s->config.max_nr_ports);
    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
541 542
        qemu_put_be32s(f, &s->ports_map[i]);
    }
543

544
    /* Ports */
545

546
    nr_active_ports = 0;
547
    QTAILQ_FOREACH(port, &s->ports, next) {
548
        nr_active_ports++;
549
    }
550 551 552 553 554 555 556

    qemu_put_be32s(f, &nr_active_ports);

    /*
     * Items in struct VirtIOSerialPort.
     */
    QTAILQ_FOREACH(port, &s->ports, next) {
557 558
        uint32_t elem_popped;

559 560
        qemu_put_be32s(f, &port->id);
        qemu_put_byte(f, port->guest_connected);
561
        qemu_put_byte(f, port->host_connected);
562 563 564 565 566 567 568 569 570 571 572 573 574

	elem_popped = 0;
        if (port->elem.out_num) {
            elem_popped = 1;
        }
        qemu_put_be32s(f, &elem_popped);
        if (elem_popped) {
            qemu_put_be32s(f, &port->iov_idx);
            qemu_put_be64s(f, &port->iov_offset);

            qemu_put_buffer(f, (unsigned char *)&port->elem,
                            sizeof(port->elem));
        }
575
    }
576 577
}

578 579
static void virtio_serial_post_load_timer_cb(void *opaque)
{
580
    uint32_t i;
581
    VirtIOSerial *s = VIRTIO_SERIAL(opaque);
582 583
    VirtIOSerialPort *port;
    uint8_t host_connected;
584
    VirtIOSerialPortClass *vsc;
585

586 587 588 589 590 591
    if (!s->post_load) {
        return;
    }
    for (i = 0 ; i < s->post_load->nr_active_ports; ++i) {
        port = s->post_load->connected[i].port;
        host_connected = s->post_load->connected[i].host_connected;
592 593 594 595 596
        if (host_connected != port->host_connected) {
            /*
             * We have to let the guest know of the host connection
             * status change
             */
597
            send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
598 599
                               port->host_connected);
        }
600 601 602 603
        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
        if (vsc->set_guest_connected) {
            vsc->set_guest_connected(port, port->guest_connected);
        }
604
    }
605 606 607 608
    g_free(s->post_load->connected);
    qemu_free_timer(s->post_load->timer);
    g_free(s->post_load);
    s->post_load = NULL;
609 610
}

611 612 613 614 615
static int fetch_active_ports_list(QEMUFile *f, int version_id,
                                   VirtIOSerial *s, uint32_t nr_active_ports)
{
    uint32_t i;

616 617 618 619 620 621 622 623
    s->post_load = g_malloc0(sizeof(*s->post_load));
    s->post_load->nr_active_ports = nr_active_ports;
    s->post_load->connected =
        g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);

    s->post_load->timer = qemu_new_timer_ns(vm_clock,
                                            virtio_serial_post_load_timer_cb,
                                            s);
624 625 626 627 628 629 630 631 632 633 634 635 636

    /* Items in struct VirtIOSerialPort */
    for (i = 0; i < nr_active_ports; i++) {
        VirtIOSerialPort *port;
        uint32_t id;

        id = qemu_get_be32(f);
        port = find_port_by_id(s, id);
        if (!port) {
            return -EINVAL;
        }

        port->guest_connected = qemu_get_byte(f);
637 638
        s->post_load->connected[i].port = port;
        s->post_load->connected[i].host_connected = qemu_get_byte(f);
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662

        if (version_id > 2) {
            uint32_t elem_popped;

            qemu_get_be32s(f, &elem_popped);
            if (elem_popped) {
                qemu_get_be32s(f, &port->iov_idx);
                qemu_get_be64s(f, &port->iov_offset);

                qemu_get_buffer(f, (unsigned char *)&port->elem,
                                sizeof(port->elem));
                virtqueue_map_sg(port->elem.in_sg, port->elem.in_addr,
                                 port->elem.in_num, 1);
                virtqueue_map_sg(port->elem.out_sg, port->elem.out_addr,
                                 port->elem.out_num, 1);

                /*
                 *  Port was throttled on source machine.  Let's
                 *  unthrottle it here so data starts flowing again.
                 */
                virtio_serial_throttle_port(port, false);
            }
        }
    }
663
    qemu_mod_timer(s->post_load->timer, 1);
664 665 666
    return 0;
}

667 668
static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
669
    VirtIOSerial *s = VIRTIO_SERIAL(opaque);
670
    uint32_t max_nr_ports, nr_active_ports, ports_map;
671
    unsigned int i;
672
    int ret;
673

674
    if (version_id > 3) {
675 676
        return -EINVAL;
    }
677

678
    /* The virtio device */
679
    ret = virtio_load(VIRTIO_DEVICE(s), f);
680 681 682
    if (ret) {
        return ret;
    }
683 684 685 686 687 688 689 690

    if (version_id < 2) {
        return 0;
    }

    /* The config space */
    qemu_get_be16s(f, &s->config.cols);
    qemu_get_be16s(f, &s->config.rows);
691

692
    qemu_get_be32s(f, &max_nr_ports);
693 694
    tswap32s(&max_nr_ports);
    if (max_nr_ports > tswap32(s->config.max_nr_ports)) {
695
        /* Source could have had more ports than us. Fail migration. */
696 697
        return -EINVAL;
    }
698

699
    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
700
        qemu_get_be32s(f, &ports_map);
701

702
        if (ports_map != s->ports_map[i]) {
703 704 705 706 707 708
            /*
             * Ports active on source and destination don't
             * match. Fail migration.
             */
            return -EINVAL;
        }
709 710
    }

711 712
    qemu_get_be32s(f, &nr_active_ports);

713 714 715 716
    if (nr_active_ports) {
        ret = fetch_active_ports_list(f, version_id, s, nr_active_ports);
        if (ret) {
            return ret;
717
        }
718
    }
719 720 721 722 723
    return 0;
}

static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent);

724 725 726 727 728 729
static Property virtser_props[] = {
    DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
    DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
    DEFINE_PROP_END_OF_LIST()
};

730 731 732 733 734 735 736 737 738 739 740 741 742 743 744
#define TYPE_VIRTIO_SERIAL_BUS "virtio-serial-bus"
#define VIRTIO_SERIAL_BUS(obj) \
      OBJECT_CHECK(VirtIOSerialBus, (obj), TYPE_VIRTIO_SERIAL_BUS)

static void virtser_bus_class_init(ObjectClass *klass, void *data)
{
    BusClass *k = BUS_CLASS(klass);
    k->print_dev = virtser_bus_dev_print;
}

static const TypeInfo virtser_bus_info = {
    .name = TYPE_VIRTIO_SERIAL_BUS,
    .parent = TYPE_BUS,
    .instance_size = sizeof(VirtIOSerialBus),
    .class_init = virtser_bus_class_init,
745 746 747 748
};

static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
{
749
    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
750

751 752 753 754 755
    monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n",
                   indent, "", port->id,
                   port->guest_connected ? "on" : "off",
                   port->host_connected ? "on" : "off",
                   port->throttled ? "on" : "off");
756 757
}

758 759 760
/* This function is only used if a port id is not provided by the user */
static uint32_t find_free_port_id(VirtIOSerial *vser)
{
761
    unsigned int i, max_nr_ports;
762

763 764
    max_nr_ports = tswap32(vser->config.max_nr_ports);
    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
        uint32_t map, bit;

        map = vser->ports_map[i];
        bit = ffs(~map);
        if (bit) {
            return (bit - 1) + i * 32;
        }
    }
    return VIRTIO_CONSOLE_BAD_ID;
}

static void mark_port_added(VirtIOSerial *vser, uint32_t port_id)
{
    unsigned int i;

    i = port_id / 32;
    vser->ports_map[i] |= 1U << (port_id % 32);
}

static void add_port(VirtIOSerial *vser, uint32_t port_id)
{
    mark_port_added(vser, port_id);
787
    send_control_event(vser, port_id, VIRTIO_CONSOLE_PORT_ADD, 1);
788 789 790 791
}

static void remove_port(VirtIOSerial *vser, uint32_t port_id)
{
792
    VirtIOSerialPort *port;
793 794 795 796 797
    unsigned int i;

    i = port_id / 32;
    vser->ports_map[i] &= ~(1U << (port_id % 32));

798
    port = find_port_by_id(vser, port_id);
799 800 801 802 803 804
    /*
     * This function is only called from qdev's unplug callback; if we
     * get a NULL port here, we're in trouble.
     */
    assert(port);

805
    /* Flush out any unconsumed buffers first */
806
    discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser));
807

808
    send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1);
809 810
}

A
Anthony Liguori 已提交
811
static int virtser_port_qdev_init(DeviceState *qdev)
812
{
813
    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
814
    VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
815
    VirtIOSerialBus *bus = DO_UPCAST(VirtIOSerialBus, qbus, qdev->parent_bus);
816
    int ret, max_nr_ports;
817 818 819
    bool plugging_port0;

    port->vser = bus->vser;
820
    port->bh = qemu_bh_new(flush_queued_data_bh, port);
821

822
    assert(vsc->have_data);
823

824 825 826 827 828
    /*
     * Is the first console port we're seeing? If so, put it up at
     * location 0. This is done for backward compatibility (old
     * kernel, new qemu).
     */
829
    plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
830

831
    if (find_port_by_id(port->vser, port->id)) {
832
        error_report("virtio-serial-bus: A port already exists at id %u",
833
                     port->id);
834 835 836
        return -1;
    }

837 838 839 840 841 842
    if (port->id == VIRTIO_CONSOLE_BAD_ID) {
        if (plugging_port0) {
            port->id = 0;
        } else {
            port->id = find_free_port_id(port->vser);
            if (port->id == VIRTIO_CONSOLE_BAD_ID) {
843
                error_report("virtio-serial-bus: Maximum port limit for this device reached");
844 845 846 847 848
                return -1;
            }
        }
    }

849 850
    max_nr_ports = tswap32(port->vser->config.max_nr_ports);
    if (port->id >= max_nr_ports) {
851
        error_report("virtio-serial-bus: Out-of-range port id specified, max. allowed: %u",
852
                     max_nr_ports - 1);
853 854 855
        return -1;
    }

856
    ret = vsc->init(port);
857 858 859 860
    if (ret) {
        return ret;
    }

861 862
    port->elem.out_num = 0;

863 864 865 866
    QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
    port->ivq = port->vser->ivqs[port->id];
    port->ovq = port->vser->ovqs[port->id];

867 868
    add_port(port->vser, port->id);

869
    /* Send an update to the guest about this new port added */
870
    virtio_notify_config(VIRTIO_DEVICE(port->vser));
871 872 873 874 875 876

    return ret;
}

static int virtser_port_qdev_exit(DeviceState *qdev)
{
877
    VirtIOSerialPort *port = DO_UPCAST(VirtIOSerialPort, dev, qdev);
878
    VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
879 880
    VirtIOSerial *vser = port->vser;

881
    qemu_bh_delete(port->bh);
882
    remove_port(port->vser, port->id);
883

884 885
    QTAILQ_REMOVE(&vser->ports, port, next);

886 887
    if (vsc->exit) {
        vsc->exit(port);
888
    }
889 890 891
    return 0;
}

892
static int virtio_serial_device_init(VirtIODevice *vdev)
893
{
894 895
    DeviceState *qdev = DEVICE(vdev);
    VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
896
    uint32_t i, max_supported_ports;
897

898 899 900
    if (!vser->serial.max_virtserial_ports) {
        return -1;
    }
901

902 903 904
    /* Each port takes 2 queues, and one pair is for the control queue */
    max_supported_ports = VIRTIO_PCI_QUEUE_MAX / 2 - 1;

905
    if (vser->serial.max_virtserial_ports > max_supported_ports) {
906
        error_report("maximum ports supported: %u", max_supported_ports);
907
        return -1;
908 909
    }

910 911
    virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE,
                sizeof(struct virtio_console_config));
912 913

    /* Spawn a new virtio-serial bus on which the ports will ride as devices */
914
    qbus_create_inplace(&vser->bus.qbus, TYPE_VIRTIO_SERIAL_BUS, qdev, NULL);
915 916
    vser->bus.qbus.allow_hotplug = 1;
    vser->bus.vser = vser;
917 918
    QTAILQ_INIT(&vser->ports);

919 920 921 922 923
    vser->bus.max_nr_ports = vser->serial.max_virtserial_ports;
    vser->ivqs = g_malloc(vser->serial.max_virtserial_ports
                          * sizeof(VirtQueue *));
    vser->ovqs = g_malloc(vser->serial.max_virtserial_ports
                          * sizeof(VirtQueue *));
924 925 926 927 928 929

    /* Add a queue for host to guest transfers for port 0 (backward compat) */
    vser->ivqs[0] = virtio_add_queue(vdev, 128, handle_input);
    /* Add a queue for guest to host transfers for port 0 (backward compat) */
    vser->ovqs[0] = virtio_add_queue(vdev, 128, handle_output);

930 931 932 933 934 935
    /* TODO: host to guest notifications can get dropped
     * if the queue fills up. Implement queueing in host,
     * this might also make it possible to reduce the control
     * queue size: as guest preposts buffers there,
     * this will save 4Kbyte of guest memory per entry. */

936
    /* control queue: host to guest */
937
    vser->c_ivq = virtio_add_queue(vdev, 32, control_in);
938
    /* control queue: guest to host */
939
    vser->c_ovq = virtio_add_queue(vdev, 32, control_out);
940

941
    for (i = 1; i < vser->bus.max_nr_ports; i++) {
942 943 944 945 946 947
        /* Add a per-port queue for host to guest transfers */
        vser->ivqs[i] = virtio_add_queue(vdev, 128, handle_input);
        /* Add a per-per queue for guest to host transfers */
        vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
    }

948 949
    vser->config.max_nr_ports = tswap32(vser->serial.max_virtserial_ports);
    vser->ports_map = g_malloc0(((vser->serial.max_virtserial_ports + 31) / 32)
950
        * sizeof(vser->ports_map[0]));
951 952 953 954
    /*
     * Reserve location 0 for a console port for backward compat
     * (old kernel, new qemu)
     */
955
    mark_port_added(vser, 0);
956

957 958 959 960 961
    vdev->get_features = get_features;
    vdev->get_config = get_config;
    vdev->set_config = set_config;
    vdev->set_status = set_status;
    vdev->reset = vser_reset;
962

963 964
    vser->post_load = NULL;

965 966 967 968
    /*
     * Register for the savevm section with the virtio-console name
     * to preserve backward compat
     */
969
    register_savevm(qdev, "virtio-console", -1, 3, virtio_serial_save,
970 971
                    virtio_serial_load, vser);

972
    return 0;
973
}
974

975 976 977 978
static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *k = DEVICE_CLASS(klass);
    k->init = virtser_port_qdev_init;
979
    k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
980 981
    k->exit = virtser_port_qdev_exit;
    k->unplug = qdev_simple_unplug_cb;
982
    k->props = virtser_props;
983 984
}

985
static const TypeInfo virtio_serial_port_type_info = {
986 987 988 989 990
    .name = TYPE_VIRTIO_SERIAL_PORT,
    .parent = TYPE_DEVICE,
    .instance_size = sizeof(VirtIOSerialPort),
    .abstract = true,
    .class_size = sizeof(VirtIOSerialPortClass),
991
    .class_init = virtio_serial_port_class_init,
992 993
};

994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
static int virtio_serial_device_exit(DeviceState *dev)
{
    VirtIOSerial *vser = VIRTIO_SERIAL(dev);
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);

    unregister_savevm(dev, "virtio-console", vser);

    g_free(vser->ivqs);
    g_free(vser->ovqs);
    g_free(vser->ports_map);
    if (vser->post_load) {
        g_free(vser->post_load->connected);
        qemu_del_timer(vser->post_load->timer);
        qemu_free_timer(vser->post_load->timer);
        g_free(vser->post_load);
    }
    virtio_common_cleanup(vdev);
    return 0;
}

static Property virtio_serial_properties[] = {
    DEFINE_VIRTIO_SERIAL_PROPERTIES(VirtIOSerial, serial),
    DEFINE_PROP_END_OF_LIST(),
};

static void virtio_serial_class_init(ObjectClass *klass, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(klass);
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
    dc->exit = virtio_serial_device_exit;
    dc->props = virtio_serial_properties;
    vdc->init = virtio_serial_device_init;
    vdc->get_features = get_features;
    vdc->get_config = get_config;
    vdc->set_config = set_config;
    vdc->set_status = set_status;
    vdc->reset = vser_reset;
}

static const TypeInfo virtio_device_info = {
    .name = TYPE_VIRTIO_SERIAL,
    .parent = TYPE_VIRTIO_DEVICE,
    .instance_size = sizeof(VirtIOSerial),
    .class_init = virtio_serial_class_init,
};

A
Andreas Färber 已提交
1040
static void virtio_serial_register_types(void)
1041
{
1042
    type_register_static(&virtser_bus_info);
1043
    type_register_static(&virtio_serial_port_type_info);
1044
    type_register_static(&virtio_device_info);
1045 1046
}

A
Andreas Färber 已提交
1047
type_init(virtio_serial_register_types)