[SLOF] [PATCH slof] virtio-serial: Close device completely

Alexey Kardashevskiy aik at ozlabs.ru
Fri Mar 6 15:39:33 AEDT 2020


Linux closes stdout at the end of prom_init which triggers the FW quiesce
code which closes the virtio-serial instance. This misses stopping
the virtio queues, clearing the "emit" token and other things. However
this seemed working for a little longer (until the Linux driver took over)
till 0cdb2dd13c3e which moved the VQ descriptors around which caused
use-after-free corruption.

This adds virtio_queue_term_vq(), cleanup in the forth driver, few checks
and reverts emit to hvterm-emit.

Fixes: 0cdb2dd13c3e ("virtio: Store queue descriptors in virtio_device")
Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
---

Turns out it is close(stdout) what triggers quiesce, not the client
interface's "quiesce".

This helps with iommu_platform=off but iommu_platform=on still does not work.
Debugging...

/home/aik/pbuild/qemu-localhost-ppc64/ppc64-softmmu/qemu-system-ppc64 \
-device virtio-serial,id=virtio-serial0,iommu_platform=on,disable-modern=off,disable-legacy=on,ioeventfd=off \
-nodefaults \
-chardev stdio,id=STDIO0,signal=off,mux=on \
-device virtconsole,id=virtconsole0,chardev=STDIO0 \
-mon id=MON0,chardev=STDIO0,mode=readline \
-nographic \
-vga none \
-machine pseries,cap-cfpc=broken,cap-sbbc=broken,cap-ibs=broken,cap-ccf-assist=off,ic-mode=xics \
-m 2G \
-smp 1 \
-bios p/slof/boot_rom.bin \
-enable-kvm \
-initrd t/le.cpio \
-kernel t/vml4120le \
-L /home/aik/t/qemu-ppc64-bios/ \
-trace events=qemu_trace_events \
-d guest_errors \
-chardev socket,id=SOCKET0,server,nowait,path=qemu.mon.ssh55056 \
-mon chardev=SOCKET0,mode=control


---
 lib/libvirtio/virtio-serial.c    |  7 +++++++
 board-qemu/slof/virtio-serial.fs | 11 ++++++++++-
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/lib/libvirtio/virtio-serial.c b/lib/libvirtio/virtio-serial.c
index d1503a44f433..92afb02014b2 100644
--- a/lib/libvirtio/virtio-serial.c
+++ b/lib/libvirtio/virtio-serial.c
@@ -102,6 +102,10 @@ void virtio_serial_shutdown(struct virtio_device *dev)
 	/* Quiesce device */
 	virtio_set_status(dev, VIRTIO_STAT_FAILED);
 
+	/* Stop queues */
+	virtio_queue_term_vq(dev, &dev->vq[TX_Q], TX_Q);
+	virtio_queue_term_vq(dev, &dev->vq[RX_Q], RX_Q);
+
 	/* Reset device */
 	virtio_reset_device(dev);
 }
@@ -114,6 +118,9 @@ int virtio_serial_putchar(struct virtio_device *dev, char c)
 	uint16_t last_used_idx, avail_idx;
 	struct vqs *vq = &dev->vq[TX_Q];
 
+	if (!vq->desc)
+		return 0;
+
 	avail_idx = virtio_modern16_to_cpu(dev, vq->avail->idx);
 
 	last_used_idx = vq->used->idx;
diff --git a/board-qemu/slof/virtio-serial.fs b/board-qemu/slof/virtio-serial.fs
index 42ab3e2ccc9c..5293ab1f6341 100644
--- a/board-qemu/slof/virtio-serial.fs
+++ b/board-qemu/slof/virtio-serial.fs
@@ -25,6 +25,8 @@ virtio-setup-vd VALUE virtiodev
             close-dev
         THEN
         FALSE to initialized?
+	['] hvterm-emit to emit
+	0 to virtiodev
     THEN
 ;
 
@@ -61,12 +63,18 @@ virtiodev virtio-serial-init drop
 : close
     open-count 0> IF
         open-count 1 - dup to open-count
-        0= IF close THEN
+        0= IF
+	    close
+	    FALSE to initialized?
+	    ['] hvterm-emit to emit
+	    0 to virtiodev
+	THEN
     THEN
     close
 ;
 
 : write ( addr len -- actual )
+    virtiodev 0= IF nip EXIT THEN
     tuck
     0 ?DO
         dup c@ virtiodev SWAP virtio-serial-putchar
@@ -77,6 +85,7 @@ virtiodev virtio-serial-init drop
 
 : read ( addr len -- actual )
     0= IF drop 0 EXIT THEN
+    virtiodev 0= IF nip EXIT THEN
     virtiodev virtio-serial-haschar 0= IF 0 swap c! -2 EXIT THEN
     virtiodev virtio-serial-getchar swap c! 1
 ;
-- 
2.17.1



More information about the SLOF mailing list