diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2016-10-10 16:23:40 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2016-10-10 16:23:40 +0100 |
commit | 627eae7d729277c84f8e0ac07a8caab39c92c38d (patch) | |
tree | fe42de6f2cbeb5a5f2ab64f16eff5da7b3993ae9 /hw/char/virtio-serial-bus.c | |
parent | 0f183e679d85fec74fc83f35f973cf8e56d97861 (diff) | |
parent | dea651a95af6dad0997b840241a0bf6059d9a776 (diff) |
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
virtio, pc: fixes and features
more guest error handling for virtio devices
virtio migration rework
pc fixes
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Mon 10 Oct 2016 00:39:11 BST
# gpg: using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg: aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67
# Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469
* remotes/mst/tags/for_upstream: (33 commits)
intel-iommu: Check IOAPIC's Trigger Mode against the one in IRTE
virtio: cleanup VMSTATE_VIRTIO_DEVICE
vhost-vsock: convert VMSTATE_VIRTIO_DEVICE
virtio-rng: convert VMSTATE_VIRTIO_DEVICE
virtio-balloon: convert VMSTATE_VIRTIO_DEVICE
virtio-scsi: convert VMSTATE_VIRTIO_DEVICE
virtio-input: convert VMSTATE_VIRTIO_DEVICE
virtio-gpu: convert VMSTATE_VIRTIO_DEVICE
virtio-serial: convert VMSTATE_VIRTIO_DEVICE
virtio-9p: convert VMSTATE_VIRTIO_DEVICE
virtio-net: convert VMSTATE_VIRTIO_DEVICE
virtio-blk: convert VMSTATE_VIRTIO_DEVICE
virtio: prepare change VMSTATE_VIRTIO_DEVICE macro
net: don't poke at chardev internal QemuOpts
virtio-scsi: handle virtio_scsi_set_config() error
virtio-scsi: convert virtio_scsi_bad_req() to use virtio_error()
virtio-net: handle virtio_net_flush_tx() errors
virtio-net: handle virtio_net_receive() errors
virtio-net: handle virtio_net_handle_ctrl() error
virtio-blk: handle virtio_blk_handle_request() errors
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw/char/virtio-serial-bus.c')
-rw-r--r-- | hw/char/virtio-serial-bus.c | 79 |
1 files changed, 69 insertions, 10 deletions
diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index db57a38546..7975c2cda1 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -75,6 +75,19 @@ static VirtIOSerialPort *find_port_by_name(char *name) return NULL; } +static VirtIOSerialPort *find_first_connected_console(VirtIOSerial *vser) +{ + VirtIOSerialPort *port; + + QTAILQ_FOREACH(port, &vser->ports, next) { + VirtIOSerialPortClass const *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); + if (vsc->is_console && port->host_connected) { + return port; + } + } + return NULL; +} + static bool use_multiport(VirtIOSerial *vser) { VirtIODevice *vdev = VIRTIO_DEVICE(vser); @@ -132,6 +145,15 @@ static void discard_vq_data(VirtQueue *vq, VirtIODevice *vdev) virtio_notify(vdev, vq); } +static void discard_throttle_data(VirtIOSerialPort *port) +{ + if (port->elem) { + virtqueue_detach_element(port->ovq, port->elem, 0); + g_free(port->elem); + port->elem = NULL; + } +} + static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq, VirtIODevice *vdev) { @@ -254,6 +276,7 @@ int virtio_serial_close(VirtIOSerialPort *port) * consume, reset the throttling flag and discard the data. */ port->throttled = false; + discard_throttle_data(port); discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser)); send_control_event(port->vser, port->id, VIRTIO_CONSOLE_PORT_OPEN, 0); @@ -528,6 +551,7 @@ static uint64_t get_features(VirtIODevice *vdev, uint64_t features, vser = VIRTIO_SERIAL(vdev); + features |= vser->host_features; if (vser->bus.max_nr_ports > 1) { virtio_add_feature(&features, VIRTIO_CONSOLE_F_MULTIPORT); } @@ -547,6 +571,29 @@ static void get_config(VirtIODevice *vdev, uint8_t *config_data) vser->serial.max_virtserial_ports); } +/* Guest sent new config info */ +static void set_config(VirtIODevice *vdev, const uint8_t *config_data) +{ + VirtIOSerial *vser = VIRTIO_SERIAL(vdev); + struct virtio_console_config *config = + (struct virtio_console_config *)config_data; + uint8_t emerg_wr_lo = le32_to_cpu(config->emerg_wr); + VirtIOSerialPort *port = find_first_connected_console(vser); + VirtIOSerialPortClass *vsc; + + if (!config->emerg_wr) { + return; + } + /* Make sure we don't misdetect an emergency write when the guest + * does a short config write after an emergency write. */ + config->emerg_wr = 0; + if (!port) { + return; + } + vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); + (void)vsc->have_data(port, &emerg_wr_lo, 1); +} + static void guest_reset(VirtIOSerial *vser) { VirtIOSerialPort *port; @@ -554,6 +601,9 @@ static void guest_reset(VirtIOSerial *vser) QTAILQ_FOREACH(port, &vser->ports, next) { vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); + + discard_throttle_data(port); + if (port->guest_connected) { port->guest_connected = false; if (vsc->set_guest_connected) { @@ -728,12 +778,6 @@ static int fetch_active_ports_list(QEMUFile *f, return 0; } -static int virtio_serial_load(QEMUFile *f, void *opaque, size_t size) -{ - /* The virtio device */ - return virtio_load(VIRTIO_DEVICE(opaque), f, 3); -} - static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f, int version_id) { @@ -864,6 +908,7 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id) assert(port); /* Flush out any unconsumed buffers first */ + discard_throttle_data(port); discard_vq_data(port->ovq, VIRTIO_DEVICE(port->vser)); send_control_event(vser, port->id, VIRTIO_CONSOLE_PORT_REMOVE, 1); @@ -967,6 +1012,7 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIOSerial *vser = VIRTIO_SERIAL(dev); uint32_t i, max_supported_ports; + size_t config_size = sizeof(struct virtio_console_config); if (!vser->serial.max_virtserial_ports) { error_setg(errp, "Maximum number of serial ports not specified"); @@ -981,10 +1027,12 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp) return; } - /* We don't support emergency write, skip it for now. */ - /* TODO: cleaner fix, depending on host features. */ + if (!virtio_has_feature(vser->host_features, + VIRTIO_CONSOLE_F_EMERG_WRITE)) { + config_size = offsetof(struct virtio_console_config, emerg_wr); + } virtio_init(vdev, "virtio-serial", VIRTIO_ID_CONSOLE, - offsetof(struct virtio_console_config, emerg_wr)); + config_size); /* Spawn a new virtio-serial bus on which the ports will ride as devices */ qbus_create_inplace(&vser->bus, sizeof(vser->bus), TYPE_VIRTIO_SERIAL_BUS, @@ -1075,11 +1123,21 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) } /* Note: 'console' is used for backwards compatibility */ -VMSTATE_VIRTIO_DEVICE(console, 3, virtio_serial_load, virtio_vmstate_save); +static const VMStateDescription vmstate_virtio_console = { + .name = "virtio-console", + .minimum_version_id = 3, + .version_id = 3, + .fields = (VMStateField[]) { + VMSTATE_VIRTIO_DEVICE, + VMSTATE_END_OF_LIST() + }, +}; static Property virtio_serial_properties[] = { DEFINE_PROP_UINT32("max_ports", VirtIOSerial, serial.max_virtserial_ports, 31), + DEFINE_PROP_BIT64("emergency-write", VirtIOSerial, host_features, + VIRTIO_CONSOLE_F_EMERG_WRITE, true), DEFINE_PROP_END_OF_LIST(), }; @@ -1098,6 +1156,7 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data) vdc->unrealize = virtio_serial_device_unrealize; vdc->get_features = get_features; vdc->get_config = get_config; + vdc->set_config = set_config; vdc->set_status = set_status; vdc->reset = vser_reset; vdc->save = virtio_serial_save_device; |