diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 198b2a89c0..172c72d06c 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -187,6 +187,26 @@ static int chr_be_change(void *opaque) return 0; } +static void virtconsole_enable_backend(VirtIOSerialPort *port, bool enable) +{ + VirtConsole *vcon = VIRTIO_CONSOLE(port); + + if (!qemu_chr_fe_backend_connected(&vcon->chr)) { + return; + } + + if (enable) { + VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port); + + qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read, + k->is_console ? NULL : chr_event, + chr_be_change, vcon, NULL, false); + } else { + qemu_chr_fe_set_handlers(&vcon->chr, NULL, NULL, NULL, + NULL, NULL, NULL, false); + } +} + static void virtconsole_realize(DeviceState *dev, Error **errp) { VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev); @@ -258,6 +278,7 @@ static void virtserialport_class_init(ObjectClass *klass, void *data) k->unrealize = virtconsole_unrealize; k->have_data = flush_buf; k->set_guest_connected = set_guest_connected; + k->enable_backend = virtconsole_enable_backend; k->guest_writable = guest_writable; dc->props = virtserialport_properties; } diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index 17a1bb008a..9470bd7be7 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -637,6 +637,13 @@ static void set_status(VirtIODevice *vdev, uint8_t status) if (!(status & VIRTIO_CONFIG_S_DRIVER_OK)) { guest_reset(vser); } + + QTAILQ_FOREACH(port, &vser->ports, next) { + VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port); + if (vsc->enable_backend) { + vsc->enable_backend(port, vdev->vm_running); + } + } } static void vser_reset(VirtIODevice *vdev) diff --git a/include/hw/virtio/virtio-serial.h b/include/hw/virtio/virtio-serial.h index b19c44727f..12657a9f39 100644 --- a/include/hw/virtio/virtio-serial.h +++ b/include/hw/virtio/virtio-serial.h @@ -58,6 +58,9 @@ typedef struct VirtIOSerialPortClass { /* Guest opened/closed device. */ void (*set_guest_connected)(VirtIOSerialPort *port, int guest_connected); + /* Enable/disable backend for virtio serial port */ + void (*enable_backend)(VirtIOSerialPort *port, bool enable); + /* Guest is now ready to accept data (virtqueues set up). */ void (*guest_ready)(VirtIOSerialPort *port);