qemu

Форк
0
/
virtio-serial-bus.c 
1206 строк · 34.1 Кб
1
/*
2
 * A bus for connecting virtio serial and console ports
3
 *
4
 * Copyright (C) 2009, 2010 Red Hat, Inc.
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.
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.
19
 */
20

21
#include "qemu/osdep.h"
22
#include "qapi/error.h"
23
#include "qemu/iov.h"
24
#include "qemu/main-loop.h"
25
#include "qemu/module.h"
26
#include "migration/qemu-file-types.h"
27
#include "monitor/monitor.h"
28
#include "qemu/error-report.h"
29
#include "qemu/queue.h"
30
#include "hw/qdev-properties.h"
31
#include "trace.h"
32
#include "hw/virtio/virtio-serial.h"
33
#include "hw/virtio/virtio-access.h"
34

35
static struct VirtIOSerialDevices {
36
    QLIST_HEAD(, VirtIOSerial) devices;
37
} vserdevices;
38

39
static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
40
{
41
    VirtIOSerialPort *port;
42

43
    if (id == VIRTIO_CONSOLE_BAD_ID) {
44
        return NULL;
45
    }
46

47
    QTAILQ_FOREACH(port, &vser->ports, next) {
48
        if (port->id == id)
49
            return port;
50
    }
51
    return NULL;
52
}
53

54
static VirtIOSerialPort *find_port_by_vq(VirtIOSerial *vser, VirtQueue *vq)
55
{
56
    VirtIOSerialPort *port;
57

58
    QTAILQ_FOREACH(port, &vser->ports, next) {
59
        if (port->ivq == vq || port->ovq == vq)
60
            return port;
61
    }
62
    return NULL;
63
}
64

65
static VirtIOSerialPort *find_port_by_name(char *name)
66
{
67
    VirtIOSerial *vser;
68

69
    QLIST_FOREACH(vser, &vserdevices.devices, next) {
70
        VirtIOSerialPort *port;
71

72
        QTAILQ_FOREACH(port, &vser->ports, next) {
73
            if (port->name && !strcmp(port->name, name)) {
74
                return port;
75
            }
76
        }
77
    }
78
    return NULL;
79
}
80

81
static VirtIOSerialPort *find_first_connected_console(VirtIOSerial *vser)
82
{
83
    VirtIOSerialPort *port;
84

85
    QTAILQ_FOREACH(port, &vser->ports, next) {
86
        VirtIOSerialPortClass const *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
87
        if (vsc->is_console && port->host_connected) {
88
            return port;
89
        }
90
    }
91
    return NULL;
92
}
93

94
static bool use_multiport(VirtIOSerial *vser)
95
{
96
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
97
    return virtio_vdev_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT);
98
}
99

100
static size_t write_to_port(VirtIOSerialPort *port,
101
                            const uint8_t *buf, size_t size)
102
{
103
    VirtQueueElement *elem;
104
    VirtQueue *vq;
105
    size_t offset;
106

107
    vq = port->ivq;
108
    if (!virtio_queue_ready(vq)) {
109
        return 0;
110
    }
111

112
    offset = 0;
113
    while (offset < size) {
114
        size_t len;
115

116
        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
117
        if (!elem) {
118
            break;
119
        }
120

121
        len = iov_from_buf(elem->in_sg, elem->in_num, 0,
122
                           buf + offset, size - offset);
123
        offset += len;
124

125
        virtqueue_push(vq, elem, len);
126
        g_free(elem);
127
    }
128

129
    virtio_notify(VIRTIO_DEVICE(port->vser), vq);
130
    return offset;
131
}
132

133
static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev)
134
{
135
    VirtQueueElement *elem;
136

137
    if (!virtio_queue_ready(vq)) {
138
        return;
139
    }
140
    for (;;) {
141
        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
142
        if (!elem) {
143
            break;
144
        }
145
        virtqueue_push(vq, elem, 0);
146
        g_free(elem);
147
    }
148
    virtio_notify(vdev, vq);
149
}
150

151
static void discard_throttle_data(VirtIOSerialPort *port)
152
{
153
    if (port->elem) {
154
        virtqueue_detach_element(port->ovq, port->elem, 0);
155
        g_free(port->elem);
156
        port->elem = NULL;
157
    }
158
}
159

160
static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq,
161
                                 VirtIODevice *vdev)
162
{
163
    VirtIOSerialPortClass *vsc;
164

165
    assert(port);
166
    assert(virtio_queue_ready(vq));
167

168
    vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
169

170
    while (!port->throttled) {
171
        unsigned int i;
172

173
        /* Pop an elem only if we haven't left off a previous one mid-way */
174
        if (!port->elem) {
175
            port->elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
176
            if (!port->elem) {
177
                break;
178
            }
179
            port->iov_idx = 0;
180
            port->iov_offset = 0;
181
        }
182

183
        for (i = port->iov_idx; i < port->elem->out_num; i++) {
184
            size_t buf_size;
185
            ssize_t ret;
186

187
            buf_size = port->elem->out_sg[i].iov_len - port->iov_offset;
188
            ret = vsc->have_data(port,
189
                                  port->elem->out_sg[i].iov_base
190
                                  + port->iov_offset,
191
                                  buf_size);
192
            if (!port->elem) { /* bail if we got disconnected */
193
                return;
194
            }
195
            if (port->throttled) {
196
                port->iov_idx = i;
197
                if (ret > 0) {
198
                    port->iov_offset += ret;
199
                }
200
                break;
201
            }
202
            port->iov_offset = 0;
203
        }
204
        if (port->throttled) {
205
            break;
206
        }
207
        virtqueue_push(vq, port->elem, 0);
208
        g_free(port->elem);
209
        port->elem = NULL;
210
    }
211
    virtio_notify(vdev, vq);
212
}
213

214
static void flush_queued_data(VirtIOSerialPort *port)
215
{
216
    assert(port);
217

218
    if (!virtio_queue_ready(port->ovq)) {
219
        return;
220
    }
221
    do_flush_queued_data(port, port->ovq, VIRTIO_DEVICE(port->vser));
222
}
223

224
static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
225
{
226
    VirtQueueElement *elem;
227
    VirtQueue *vq;
228

229
    vq = vser->c_ivq;
230
    if (!virtio_queue_ready(vq)) {
231
        return 0;
232
    }
233

234
    elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
235
    if (!elem) {
236
        return 0;
237
    }
238

239
    /* TODO: detect a buffer that's too short, set NEEDS_RESET */
240
    iov_from_buf(elem->in_sg, elem->in_num, 0, buf, len);
241

242
    virtqueue_push(vq, elem, len);
243
    virtio_notify(VIRTIO_DEVICE(vser), vq);
244
    g_free(elem);
245

246
    return len;
247
}
248

249
static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id,
250
                                 uint16_t event, uint16_t value)
251
{
252
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
253
    struct virtio_console_control cpkt;
254

255
    virtio_stl_p(vdev, &cpkt.id, port_id);
256
    virtio_stw_p(vdev, &cpkt.event, event);
257
    virtio_stw_p(vdev, &cpkt.value, value);
258

259
    trace_virtio_serial_send_control_event(port_id, event, value);
260
    return send_control_msg(vser, &cpkt, sizeof(cpkt));
261
}
262

263
/* Functions for use inside qemu to open and read from/write to ports */
264
int virtio_serial_open(VirtIOSerialPort *port)
265
{
266
    /* Don't allow opening an already-open port */
267
    if (port->host_connected) {
268
        return 0;
269
    }
270
    /* Send port open notification to the guest */
271
    port->host_connected = true;
272
    send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
273

274
    return 0;
275
}
276

277
int virtio_serial_close(VirtIOSerialPort *port)
278
{
279
    port->host_connected = false;
280
    /*
281
     * If there's any data the guest sent which the app didn't
282
     * consume, reset the throttling flag and discard the data.
283
     */
284
    port->throttled = false;
285
    discard_throttle_data(port);
286
    discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser));
287

288
    send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0);
289

290
    return 0;
291
}
292

293
/* Individual ports/apps call this function to write to the guest. */
294
ssize_t virtio_serial_write(VirtIOSerialPort *port, const uint8_t *buf,
295
                            size_t size)
296
{
297
    if (!port || !port->host_connected || !port->guest_connected) {
298
        return 0;
299
    }
300
    return write_to_port(port, buf, size);
301
}
302

303
/*
304
 * Readiness of the guest to accept data on a port.
305
 * Returns max. data the guest can receive
306
 */
307
size_t virtio_serial_guest_ready(VirtIOSerialPort *port)
308
{
309
    VirtIODevice *vdev = VIRTIO_DEVICE(port->vser);
310
    VirtQueue *vq = port->ivq;
311
    unsigned int bytes;
312

313
    if (!virtio_queue_ready(vq) ||
314
        !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK) ||
315
        virtio_queue_empty(vq)) {
316
        return 0;
317
    }
318
    if (use_multiport(port->vser) && !port->guest_connected) {
319
        return 0;
320
    }
321
    virtqueue_get_avail_bytes(vq, &bytes, NULL, 4096, 0);
322
    return bytes;
323
}
324

325
static void flush_queued_data_bh(void *opaque)
326
{
327
    VirtIOSerialPort *port = opaque;
328

329
    flush_queued_data(port);
330
}
331

332
void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
333
{
334
    if (!port) {
335
        return;
336
    }
337

338
    trace_virtio_serial_throttle_port(port->id, throttle);
339
    port->throttled = throttle;
340
    if (throttle) {
341
        return;
342
    }
343
    qemu_bh_schedule(port->bh);
344
}
345

346
/* Guest wants to notify us of some event */
347
static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
348
{
349
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
350
    struct VirtIOSerialPort *port;
351
    VirtIOSerialPortClass *vsc;
352
    struct virtio_console_control cpkt, *gcpkt;
353
    uint8_t *buffer;
354
    size_t buffer_len;
355

356
    gcpkt = buf;
357

358
    if (len < sizeof(cpkt)) {
359
        /* The guest sent an invalid control packet */
360
        return;
361
    }
362

363
    cpkt.event = virtio_lduw_p(vdev, &gcpkt->event);
364
    cpkt.value = virtio_lduw_p(vdev, &gcpkt->value);
365

366
    trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);
367

368
    if (cpkt.event == VIRTIO_CONSOLE_DEVICE_READY) {
369
        if (!cpkt.value) {
370
            error_report("virtio-serial-bus: Guest failure in adding device %s",
371
                         vser->bus.qbus.name);
372
            return;
373
        }
374
        /*
375
         * The device is up, we can now tell the device about all the
376
         * ports we have here.
377
         */
378
        QTAILQ_FOREACH(port, &vser->ports, next) {
379
            send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_ADD, 1);
380
        }
381
        return;
382
    }
383

384
    port = find_port_by_id(vser, virtio_ldl_p(vdev, &gcpkt->id));
385
    if (!port) {
386
        error_report("virtio-serial-bus: Unexpected port id %u for device %s",
387
                     virtio_ldl_p(vdev, &gcpkt->id), vser->bus.qbus.name);
388
        return;
389
    }
390

391
    trace_virtio_serial_handle_control_message_port(port->id);
392

393
    vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
394

395
    switch(cpkt.event) {
396
    case VIRTIO_CONSOLE_PORT_READY:
397
        if (!cpkt.value) {
398
            error_report("virtio-serial-bus: Guest failure in adding port %u for device %s",
399
                         port->id, vser->bus.qbus.name);
400
            break;
401
        }
402
        /*
403
         * Now that we know the guest asked for the port name, we're
404
         * sure the guest has initialised whatever state is necessary
405
         * for this port. Now's a good time to let the guest know if
406
         * this port is a console port so that the guest can hook it
407
         * up to hvc.
408
         */
409
        if (vsc->is_console) {
410
            send_control_event(vser, port->id, VIRTIO_CONSOLE_CONSOLE_PORT, 1);
411
        }
412

413
        if (port->name) {
414
            virtio_stl_p(vdev, &cpkt.id, port->id);
415
            virtio_stw_p(vdev, &cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
416
            virtio_stw_p(vdev, &cpkt.value, 1);
417

418
            buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
419
            buffer = g_malloc(buffer_len);
420

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

425
            send_control_msg(vser, buffer, buffer_len);
426
            g_free(buffer);
427
        }
428

429
        if (port->host_connected) {
430
            send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 1);
431
        }
432

433
        /*
434
         * When the guest has asked us for this information it means
435
         * the guest is all setup and has its virtqueues
436
         * initialised. If some app is interested in knowing about
437
         * this event, let it know.
438
         */
439
        if (vsc->guest_ready) {
440
            vsc->guest_ready(port);
441
        }
442
        break;
443

444
    case VIRTIO_CONSOLE_PORT_OPEN:
445
        port->guest_connected = cpkt.value;
446
        if (vsc->set_guest_connected) {
447
            /* Send the guest opened notification if an app is interested */
448
            vsc->set_guest_connected(port, cpkt.value);
449
        }
450
        break;
451
    }
452
}
453

454
static void control_in(VirtIODevice *vdev, VirtQueue *vq)
455
{
456
}
457

458
static void control_out(VirtIODevice *vdev, VirtQueue *vq)
459
{
460
    VirtQueueElement *elem;
461
    VirtIOSerial *vser;
462
    uint8_t *buf;
463
    size_t len;
464

465
    vser = VIRTIO_SERIAL(vdev);
466

467
    len = 0;
468
    buf = NULL;
469
    for (;;) {
470
        size_t cur_len;
471

472
        elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
473
        if (!elem) {
474
            break;
475
        }
476

477
        cur_len = iov_size(elem->out_sg, elem->out_num);
478
        /*
479
         * Allocate a new buf only if we didn't have one previously or
480
         * if the size of the buf differs
481
         */
482
        if (cur_len > len) {
483
            g_free(buf);
484

485
            buf = g_malloc(cur_len);
486
            len = cur_len;
487
        }
488
        iov_to_buf(elem->out_sg, elem->out_num, 0, buf, cur_len);
489

490
        handle_control_message(vser, buf, cur_len);
491
        virtqueue_push(vq, elem, 0);
492
        g_free(elem);
493
    }
494
    g_free(buf);
495
    virtio_notify(vdev, vq);
496
}
497

498
/* Guest wrote something to some port. */
499
static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
500
{
501
    VirtIOSerial *vser;
502
    VirtIOSerialPort *port;
503

504
    vser = VIRTIO_SERIAL(vdev);
505
    port = find_port_by_vq(vser, vq);
506

507
    if (!port || !port->host_connected) {
508
        discard_vq_data(vq, vdev);
509
        return;
510
    }
511

512
    if (!port->throttled) {
513
        do_flush_queued_data(port, vq, vdev);
514
        return;
515
    }
516
}
517

518
static void handle_input(VirtIODevice *vdev, VirtQueue *vq)
519
{
520
    /*
521
     * Users of virtio-serial would like to know when guest becomes
522
     * writable again -- i.e. if a vq had stuff queued up and the
523
     * guest wasn't reading at all, the host would not be able to
524
     * write to the vq anymore.  Once the guest reads off something,
525
     * we can start queueing things up again.  However, this call is
526
     * made for each buffer addition by the guest -- even though free
527
     * buffers existed prior to the current buffer addition.  This is
528
     * done so as not to maintain previous state, which will need
529
     * additional live-migration-related changes.
530
     */
531
    VirtIOSerial *vser;
532
    VirtIOSerialPort *port;
533
    VirtIOSerialPortClass *vsc;
534

535
    vser = VIRTIO_SERIAL(vdev);
536
    port = find_port_by_vq(vser, vq);
537

538
    if (!port) {
539
        return;
540
    }
541
    vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
542

543
    /*
544
     * If guest_connected is false, this call is being made by the
545
     * early-boot queueing up of descriptors, which is just noise for
546
     * the host apps -- don't disturb them in that case.
547
     */
548
    if (port->guest_connected && port->host_connected && vsc->guest_writable) {
549
        vsc->guest_writable(port);
550
    }
551
}
552

553
static uint64_t get_features(VirtIODevice *vdev, uint64_t features,
554
                             Error **errp)
555
{
556
    VirtIOSerial *vser;
557

558
    vser = VIRTIO_SERIAL(vdev);
559

560
    features |= vser->host_features;
561
    if (vser->bus.max_nr_ports > 1) {
562
        virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT);
563
    }
564
    return features;
565
}
566

567
/* Guest requested config info */
568
static void get_config(VirtIODevice *vdev, uint8_t *config_data)
569
{
570
    VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
571
    struct virtio_console_config *config =
572
        (struct virtio_console_config *)config_data;
573

574
    config->cols = 0;
575
    config->rows = 0;
576
    config->max_nr_ports = virtio_tswap32(vdev,
577
                                          vser->serial.max_virtserial_ports);
578
}
579

580
/* Guest sent new config info */
581
static void set_config(VirtIODevice *vdev, const uint8_t *config_data)
582
{
583
    VirtIOSerial *vser = VIRTIO_SERIAL(vdev);
584
    struct virtio_console_config *config =
585
        (struct virtio_console_config *)config_data;
586
    VirtIOSerialPort *port = find_first_connected_console(vser);
587
    VirtIOSerialPortClass *vsc;
588
    uint8_t emerg_wr_lo;
589

590
    if (!virtio_has_feature(vser->host_features,
591
        VIRTIO_CONSOLE_F_EMERG_WRITE) || !config->emerg_wr) {
592
        return;
593
    }
594

595
    emerg_wr_lo = le32_to_cpu(config->emerg_wr);
596
    /* Make sure we don't misdetect an emergency write when the guest
597
     * does a short config write after an emergency write. */
598
    config->emerg_wr = 0;
599
    if (!port) {
600
        return;
601
    }
602
    vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
603
    (void)vsc->have_data(port, &emerg_wr_lo, 1);
604
}
605

606
static void guest_reset(VirtIOSerial *vser)
607
{
608
    VirtIOSerialPort *port;
609
    VirtIOSerialPortClass *vsc;
610

611
    QTAILQ_FOREACH(port, &vser->ports, next) {
612
        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
613

614
        discard_throttle_data(port);
615

616
        if (port->guest_connected) {
617
            port->guest_connected = false;
618
            if (vsc->set_guest_connected) {
619
                vsc->set_guest_connected(port, false);
620
            }
621
        }
622
    }
623
}
624

625
static void set_status(VirtIODevice *vdev, uint8_t status)
626
{
627
    VirtIOSerial *vser;
628
    VirtIOSerialPort *port;
629

630
    vser = VIRTIO_SERIAL(vdev);
631
    port = find_port_by_id(vser, 0);
632

633
    if (port && !use_multiport(port->vser)
634
        && (status & VIRTIO_CONFIG_S_DRIVER_OK)) {
635
        /*
636
         * Non-multiport guests won't be able to tell us guest
637
         * open/close status.  Such guests can only have a port at id
638
         * 0, so set guest_connected for such ports as soon as guest
639
         * is up.
640
         */
641
        port->guest_connected = true;
642
    }
643
    if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) {
644
        guest_reset(vser);
645
    }
646

647
    QTAILQ_FOREACH(port, &vser->ports, next) {
648
        VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
649
        if (vsc->enable_backend) {
650
            vsc->enable_backend(port, vdev->vm_running);
651
        }
652
    }
653
}
654

655
static void vser_reset(VirtIODevice *vdev)
656
{
657
    VirtIOSerial *vser;
658

659
    vser = VIRTIO_SERIAL(vdev);
660
    guest_reset(vser);
661
}
662

663
static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f)
664
{
665
    VirtIOSerial *s = VIRTIO_SERIAL(vdev);
666
    VirtIOSerialPort *port;
667
    uint32_t nr_active_ports;
668
    unsigned int i, max_nr_ports;
669
    struct virtio_console_config config;
670

671
    /* The config space (ignored on the far end in current versions) */
672
    get_config(vdev, (uint8_t *)&config);
673
    qemu_put_be16(f, config.cols);
674
    qemu_put_be16(f, config.rows);
675
    qemu_put_be32(f, config.max_nr_ports);
676

677
    /* The ports map */
678
    max_nr_ports = s->serial.max_virtserial_ports;
679
    for (i = 0; i < DIV_ROUND_UP(max_nr_ports, 32); i++) {
680
        qemu_put_be32s(f, &s->ports_map[i]);
681
    }
682

683
    /* Ports */
684

685
    nr_active_ports = 0;
686
    QTAILQ_FOREACH(port, &s->ports, next) {
687
        nr_active_ports++;
688
    }
689

690
    qemu_put_be32s(f, &nr_active_ports);
691

692
    /*
693
     * Items in struct VirtIOSerialPort.
694
     */
695
    QTAILQ_FOREACH(port, &s->ports, next) {
696
        uint32_t elem_popped;
697

698
        qemu_put_be32s(f, &port->id);
699
        qemu_put_byte(f, port->guest_connected);
700
        qemu_put_byte(f, port->host_connected);
701

702
        elem_popped = 0;
703
        if (port->elem) {
704
            elem_popped = 1;
705
        }
706
        qemu_put_be32s(f, &elem_popped);
707
        if (elem_popped) {
708
            qemu_put_be32s(f, &port->iov_idx);
709
            qemu_put_be64s(f, &port->iov_offset);
710
            qemu_put_virtqueue_element(vdev, f, port->elem);
711
        }
712
    }
713
}
714

715
static void virtio_serial_post_load_timer_cb(void *opaque)
716
{
717
    uint32_t i;
718
    VirtIOSerial *s = VIRTIO_SERIAL(opaque);
719
    VirtIOSerialPort *port;
720
    uint8_t host_connected;
721
    VirtIOSerialPortClass *vsc;
722

723
    if (!s->post_load) {
724
        return;
725
    }
726
    for (i = 0 ; i < s->post_load->nr_active_ports; ++i) {
727
        port = s->post_load->connected[i].port;
728
        host_connected = s->post_load->connected[i].host_connected;
729
        if (host_connected != port->host_connected) {
730
            /*
731
             * We have to let the guest know of the host connection
732
             * status change
733
             */
734
            send_control_event(s, port->id, VIRTIO_CONSOLE_PORT_OPEN,
735
                               port->host_connected);
736
        }
737
        vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
738
        if (vsc->set_guest_connected) {
739
            vsc->set_guest_connected(port, port->guest_connected);
740
        }
741
    }
742
    g_free(s->post_load->connected);
743
    timer_free(s->post_load->timer);
744
    g_free(s->post_load);
745
    s->post_load = NULL;
746
}
747

748
static int fetch_active_ports_list(QEMUFile *f,
749
                                   VirtIOSerial *s, uint32_t nr_active_ports)
750
{
751
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
752
    uint32_t i;
753

754
    s->post_load = g_malloc0(sizeof(*s->post_load));
755
    s->post_load->nr_active_ports = nr_active_ports;
756
    s->post_load->connected =
757
        g_malloc0(sizeof(*s->post_load->connected) * nr_active_ports);
758

759
    s->post_load->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
760
                                            virtio_serial_post_load_timer_cb,
761
                                            s);
762

763
    /* Items in struct VirtIOSerialPort */
764
    for (i = 0; i < nr_active_ports; i++) {
765
        VirtIOSerialPort *port;
766
        uint32_t elem_popped;
767
        uint32_t id;
768

769
        id = qemu_get_be32(f);
770
        port = find_port_by_id(s, id);
771
        if (!port) {
772
            return -EINVAL;
773
        }
774

775
        port->guest_connected = qemu_get_byte(f);
776
        s->post_load->connected[i].port = port;
777
        s->post_load->connected[i].host_connected = qemu_get_byte(f);
778

779
        qemu_get_be32s(f, &elem_popped);
780
        if (elem_popped) {
781
            qemu_get_be32s(f, &port->iov_idx);
782
            qemu_get_be64s(f, &port->iov_offset);
783

784
            port->elem =
785
                qemu_get_virtqueue_element(vdev, f, sizeof(VirtQueueElement));
786

787
            /*
788
             *  Port was throttled on source machine.  Let's
789
             *  unthrottle it here so data starts flowing again.
790
             */
791
            virtio_serial_throttle_port(port, false);
792
        }
793
    }
794
    timer_mod(s->post_load->timer, 1);
795
    return 0;
796
}
797

798
static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
799
                                     int version_id)
800
{
801
    VirtIOSerial *s = VIRTIO_SERIAL(vdev);
802
    uint32_t max_nr_ports, nr_active_ports, ports_map;
803
    unsigned int i;
804
    int ret;
805
    uint32_t tmp;
806

807
    /* Unused */
808
    qemu_get_be16s(f, (uint16_t *) &tmp);
809
    qemu_get_be16s(f, (uint16_t *) &tmp);
810
    qemu_get_be32s(f, &tmp);
811

812
    max_nr_ports = s->serial.max_virtserial_ports;
813
    for (i = 0; i < DIV_ROUND_UP(max_nr_ports, 32); i++) {
814
        qemu_get_be32s(f, &ports_map);
815

816
        if (ports_map != s->ports_map[i]) {
817
            /*
818
             * Ports active on source and destination don't
819
             * match. Fail migration.
820
             */
821
            return -EINVAL;
822
        }
823
    }
824

825
    qemu_get_be32s(f, &nr_active_ports);
826

827
    if (nr_active_ports) {
828
        ret = fetch_active_ports_list(f, s, nr_active_ports);
829
        if (ret) {
830
            return ret;
831
        }
832
    }
833
    return 0;
834
}
835

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

838
static Property virtser_props[] = {
839
    DEFINE_PROP_UINT32("nr", VirtIOSerialPort, id, VIRTIO_CONSOLE_BAD_ID),
840
    DEFINE_PROP_STRING("name", VirtIOSerialPort, name),
841
    DEFINE_PROP_END_OF_LIST()
842
};
843

844
static void virtser_bus_class_init(ObjectClass *klass, void *data)
845
{
846
    BusClass *k = BUS_CLASS(klass);
847
    k->print_dev = virtser_bus_dev_print;
848
}
849

850
static const TypeInfo virtser_bus_info = {
851
    .name = TYPE_VIRTIO_SERIAL_BUS,
852
    .parent = TYPE_BUS,
853
    .instance_size = sizeof(VirtIOSerialBus),
854
    .class_init = virtser_bus_class_init,
855
};
856

857
static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
858
{
859
    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(qdev);
860

861
    monitor_printf(mon, "%*sport %d, guest %s, host %s, throttle %s\n",
862
                   indent, "", port->id,
863
                   port->guest_connected ? "on" : "off",
864
                   port->host_connected ? "on" : "off",
865
                   port->throttled ? "on" : "off");
866
}
867

868
/* This function is only used if a port id is not provided by the user */
869
static uint32_t find_free_port_id(VirtIOSerial *vser)
870
{
871
    unsigned int i, max_nr_ports;
872

873
    max_nr_ports = vser->serial.max_virtserial_ports;
874
    for (i = 0; i < DIV_ROUND_UP(max_nr_ports, 32); i++) {
875
        uint32_t map, zeroes;
876

877
        map = vser->ports_map[i];
878
        zeroes = ctz32(~map);
879
        if (zeroes != 32) {
880
            return zeroes + i * 32;
881
        }
882
    }
883
    return VIRTIO_CONSOLE_BAD_ID;
884
}
885

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

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

894
static void add_port(VirtIOSerial *vser, uint32_t port_id)
895
{
896
    mark_port_added(vser, port_id);
897
    send_control_event(vser, port_id, VIRTIO_CONSOLE_PORT_ADD, 1);
898
}
899

900
static void remove_port(VirtIOSerial *vser, uint32_t port_id)
901
{
902
    VirtIOSerialPort *port;
903

904
    /*
905
     * Don't mark port 0 removed -- we explicitly reserve it for
906
     * backward compat with older guests, ensure a virtconsole device
907
     * unplug retains the reservation.
908
     */
909
    if (port_id) {
910
        unsigned int i;
911

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

916
    port = find_port_by_id(vser, port_id);
917
    /*
918
     * This function is only called from qdev's unplug callback; if we
919
     * get a NULL port here, we're in trouble.
920
     */
921
    assert(port);
922

923
    /* Flush out any unconsumed buffers first */
924
    discard_throttle_data(port);
925
    discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser));
926

927
    send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1);
928
}
929

930
static void virtser_port_device_realize(DeviceState *dev, Error **errp)
931
{
932
    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
933
    VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
934
    VirtIOSerialBus *bus = VIRTIO_SERIAL_BUS(qdev_get_parent_bus(dev));
935
    int max_nr_ports;
936
    bool plugging_port0;
937
    Error *err = NULL;
938

939
    port->vser = bus->vser;
940

941
    assert(vsc->have_data);
942

943
    /*
944
     * Is the first console port we're seeing? If so, put it up at
945
     * location 0. This is done for backward compatibility (old
946
     * kernel, new qemu).
947
     */
948
    plugging_port0 = vsc->is_console && !find_port_by_id(port->vser, 0);
949

950
    if (find_port_by_id(port->vser, port->id)) {
951
        error_setg(errp, "virtio-serial-bus: A port already exists at id %u",
952
                   port->id);
953
        return;
954
    }
955

956
    if (port->name != NULL && find_port_by_name(port->name)) {
957
        error_setg(errp, "virtio-serial-bus: A port already exists by name %s",
958
                   port->name);
959
        return;
960
    }
961

962
    if (port->id == VIRTIO_CONSOLE_BAD_ID) {
963
        if (plugging_port0) {
964
            port->id = 0;
965
        } else {
966
            port->id = find_free_port_id(port->vser);
967
            if (port->id == VIRTIO_CONSOLE_BAD_ID) {
968
                error_setg(errp, "virtio-serial-bus: Maximum port limit for "
969
                                 "this device reached");
970
                return;
971
            }
972
        }
973
    }
974

975
    max_nr_ports = port->vser->serial.max_virtserial_ports;
976
    if (port->id >= max_nr_ports) {
977
        error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, "
978
                         "max. allowed: %u", max_nr_ports - 1);
979
        return;
980
    }
981

982
    vsc->realize(dev, &err);
983
    if (err != NULL) {
984
        error_propagate(errp, err);
985
        return;
986
    }
987

988
    port->bh = virtio_bh_new_guarded(dev, flush_queued_data_bh, port);
989
    port->elem = NULL;
990
}
991

992
static void virtser_port_device_plug(HotplugHandler *hotplug_dev,
993
                                     DeviceState *dev, Error **errp)
994
{
995
    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
996

997
    QTAILQ_INSERT_TAIL(&port->vser->ports, port, next);
998
    port->ivq = port->vser->ivqs[port->id];
999
    port->ovq = port->vser->ovqs[port->id];
1000

1001
    add_port(port->vser, port->id);
1002

1003
    /* Send an update to the guest about this new port added */
1004
    virtio_notify_config(VIRTIO_DEVICE(hotplug_dev));
1005
}
1006

1007
static void virtser_port_device_unrealize(DeviceState *dev)
1008
{
1009
    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
1010
    VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
1011
    VirtIOSerial *vser = port->vser;
1012

1013
    qemu_bh_delete(port->bh);
1014
    remove_port(port->vser, port->id);
1015

1016
    QTAILQ_REMOVE(&vser->ports, port, next);
1017

1018
    if (vsc->unrealize) {
1019
        vsc->unrealize(dev);
1020
    }
1021
}
1022

1023
static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
1024
{
1025
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1026
    VirtIOSerial *vser = VIRTIO_SERIAL(dev);
1027
    uint32_t i, max_supported_ports;
1028
    size_t config_size = sizeof(struct virtio_console_config);
1029

1030
    if (!vser->serial.max_virtserial_ports) {
1031
        error_setg(errp, "Maximum number of serial ports not specified");
1032
        return;
1033
    }
1034

1035
    /* Each port takes 2 queues, and one pair is for the control queue */
1036
    max_supported_ports = VIRTIO_QUEUE_MAX / 2 - 1;
1037

1038
    if (vser->serial.max_virtserial_ports > max_supported_ports) {
1039
        error_setg(errp, "maximum ports supported: %u", max_supported_ports);
1040
        return;
1041
    }
1042

1043
    if (!virtio_has_feature(vser->host_features,
1044
                            VIRTIO_CONSOLE_F_EMERG_WRITE)) {
1045
        config_size = offsetof(struct virtio_console_config, emerg_wr);
1046
    }
1047
    virtio_init(vdev, VIRTIO_ID_CONSOLE, config_size);
1048

1049
    /* Spawn a new virtio-serial bus on which the ports will ride as devices */
1050
    qbus_init(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS,
1051
              dev, vdev->bus_name);
1052
    qbus_set_hotplug_handler(BUS(&vser->bus), OBJECT(vser));
1053
    vser->bus.vser = vser;
1054
    QTAILQ_INIT(&vser->ports);
1055

1056
    vser->bus.max_nr_ports = vser->serial.max_virtserial_ports;
1057
    vser->ivqs = g_new(VirtQueue *, vser->serial.max_virtserial_ports);
1058
    vser->ovqs = g_new(VirtQueue *, vser->serial.max_virtserial_ports);
1059

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

1065
    /* TODO: host to guest notifications can get dropped
1066
     * if the queue fills up. Implement queueing in host,
1067
     * this might also make it possible to reduce the control
1068
     * queue size: as guest preposts buffers there,
1069
     * this will save 4Kbyte of guest memory per entry. */
1070

1071
    /* control queue: host to guest */
1072
    vser->c_ivq = virtio_add_queue(vdev, 32, control_in);
1073
    /* control queue: guest to host */
1074
    vser->c_ovq = virtio_add_queue(vdev, 32, control_out);
1075

1076
    for (i = 1; i < vser->bus.max_nr_ports; i++) {
1077
        /* Add a per-port queue for host to guest transfers */
1078
        vser->ivqs[i] = virtio_add_queue(vdev, 128, handle_input);
1079
        /* Add a per-per queue for guest to host transfers */
1080
        vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
1081
    }
1082

1083
    vser->ports_map = g_malloc0((DIV_ROUND_UP(vser->serial.max_virtserial_ports, 32))
1084
        * sizeof(vser->ports_map[0]));
1085
    /*
1086
     * Reserve location 0 for a console port for backward compat
1087
     * (old kernel, new qemu)
1088
     */
1089
    mark_port_added(vser, 0);
1090

1091
    vser->post_load = NULL;
1092

1093
    QLIST_INSERT_HEAD(&vserdevices.devices, vser, next);
1094
}
1095

1096
static void virtio_serial_port_class_init(ObjectClass *klass, void *data)
1097
{
1098
    DeviceClass *k = DEVICE_CLASS(klass);
1099

1100
    set_bit(DEVICE_CATEGORY_INPUT, k->categories);
1101
    k->bus_type = TYPE_VIRTIO_SERIAL_BUS;
1102
    k->realize = virtser_port_device_realize;
1103
    k->unrealize = virtser_port_device_unrealize;
1104
    device_class_set_props(k, virtser_props);
1105
}
1106

1107
static const TypeInfo virtio_serial_port_type_info = {
1108
    .name = TYPE_VIRTIO_SERIAL_PORT,
1109
    .parent = TYPE_DEVICE,
1110
    .instance_size = sizeof(VirtIOSerialPort),
1111
    .abstract = true,
1112
    .class_size = sizeof(VirtIOSerialPortClass),
1113
    .class_init = virtio_serial_port_class_init,
1114
};
1115

1116
static void virtio_serial_device_unrealize(DeviceState *dev)
1117
{
1118
    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
1119
    VirtIOSerial *vser = VIRTIO_SERIAL(dev);
1120
    int i;
1121

1122
    QLIST_REMOVE(vser, next);
1123

1124
    virtio_delete_queue(vser->c_ivq);
1125
    virtio_delete_queue(vser->c_ovq);
1126
    for (i = 0; i < vser->bus.max_nr_ports; i++) {
1127
        virtio_delete_queue(vser->ivqs[i]);
1128
        virtio_delete_queue(vser->ovqs[i]);
1129
    }
1130

1131
    g_free(vser->ivqs);
1132
    g_free(vser->ovqs);
1133
    g_free(vser->ports_map);
1134
    if (vser->post_load) {
1135
        g_free(vser->post_load->connected);
1136
        timer_free(vser->post_load->timer);
1137
        g_free(vser->post_load);
1138
    }
1139

1140
    qbus_set_hotplug_handler(BUS(&vser->bus), NULL);
1141

1142
    virtio_cleanup(vdev);
1143
}
1144

1145
/* Note: 'console' is used for backwards compatibility */
1146
static const VMStateDescription vmstate_virtio_console = {
1147
    .name = "virtio-console",
1148
    .minimum_version_id = 3,
1149
    .version_id = 3,
1150
    .fields = (const VMStateField[]) {
1151
        VMSTATE_VIRTIO_DEVICE,
1152
        VMSTATE_END_OF_LIST()
1153
    },
1154
};
1155

1156
static Property virtio_serial_properties[] = {
1157
    DEFINE_PROP_UINT32("max_ports", VirtIOSerial, serial.max_virtserial_ports,
1158
                                                  31),
1159
    DEFINE_PROP_BIT64("emergency-write", VirtIOSerial, host_features,
1160
                      VIRTIO_CONSOLE_F_EMERG_WRITE, true),
1161
    DEFINE_PROP_END_OF_LIST(),
1162
};
1163

1164
static void virtio_serial_class_init(ObjectClass *klass, void *data)
1165
{
1166
    DeviceClass *dc = DEVICE_CLASS(klass);
1167
    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
1168
    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
1169

1170
    QLIST_INIT(&vserdevices.devices);
1171

1172
    device_class_set_props(dc, virtio_serial_properties);
1173
    dc->vmsd = &vmstate_virtio_console;
1174
    set_bit(DEVICE_CATEGORY_INPUT, dc->categories);
1175
    vdc->realize = virtio_serial_device_realize;
1176
    vdc->unrealize = virtio_serial_device_unrealize;
1177
    vdc->get_features = get_features;
1178
    vdc->get_config = get_config;
1179
    vdc->set_config = set_config;
1180
    vdc->set_status = set_status;
1181
    vdc->reset = vser_reset;
1182
    vdc->save = virtio_serial_save_device;
1183
    vdc->load = virtio_serial_load_device;
1184
    hc->plug = virtser_port_device_plug;
1185
    hc->unplug = qdev_simple_device_unplug_cb;
1186
}
1187

1188
static const TypeInfo virtio_device_info = {
1189
    .name = TYPE_VIRTIO_SERIAL,
1190
    .parent = TYPE_VIRTIO_DEVICE,
1191
    .instance_size = sizeof(VirtIOSerial),
1192
    .class_init = virtio_serial_class_init,
1193
    .interfaces = (InterfaceInfo[]) {
1194
        { TYPE_HOTPLUG_HANDLER },
1195
        { }
1196
    }
1197
};
1198

1199
static void virtio_serial_register_types(void)
1200
{
1201
    type_register_static(&virtser_bus_info);
1202
    type_register_static(&virtio_serial_port_type_info);
1203
    type_register_static(&virtio_device_info);
1204
}
1205

1206
type_init(virtio_serial_register_types)
1207

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.