vmd(8): deassert interrupt pins in the PIC at the right times. Helps fix
authormlarkin <mlarkin@openbsd.org>
Mon, 9 Jul 2018 16:11:37 +0000 (16:11 +0000)
committermlarkin <mlarkin@openbsd.org>
Mon, 9 Jul 2018 16:11:37 +0000 (16:11 +0000)
situations where vmd gets stuck at 100% cpu usage because the guest VM
is constantly trying to ack interrupts that already occurred.

tested by phessler on a VM that used to exhibit the issue.

ok phessler

usr.sbin/vmd/i8253.c
usr.sbin/vmd/mc146818.c
usr.sbin/vmd/ns8250.c
usr.sbin/vmd/virtio.c

index 4d4943a..14c10f3 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: i8253.c,v 1.26 2018/06/19 17:12:34 reyk Exp $ */
+/* $OpenBSD: i8253.c,v 1.27 2018/07/09 16:11:37 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -339,6 +339,7 @@ i8253_fire(int fd, short type, void *arg)
        struct i8253_channel *ctr = (struct i8253_channel *)arg;
 
        vcpu_assert_pic_irq(ctr->vm_id, 0, 0);
+       vcpu_deassert_pic_irq(ctr->vm_id, 0, 0);
 
        if (ctr->mode != TIMER_INTTC) {
                timerclear(&tv);
index 8e77b63..4392af5 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: mc146818.c,v 1.16 2018/02/28 06:53:25 pd Exp $ */
+/* $OpenBSD: mc146818.c,v 1.17 2018/07/09 16:11:37 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -129,6 +129,7 @@ rtc_fireper(int fd, short type, void *arg)
        rtc.regs[MC_REGC] |= MC_REGC_PF;
 
        vcpu_assert_pic_irq((ptrdiff_t)arg, 0, 8);
+       vcpu_deassert_pic_irq((ptrdiff_t)arg, 0, 8);
 
        evtimer_add(&rtc.per, &rtc.per_tv);
 }
index a893a43..2348422 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns8250.c,v 1.15 2018/06/19 17:12:34 reyk Exp $ */
+/* $OpenBSD: ns8250.c,v 1.16 2018/07/09 16:11:37 mlarkin Exp $ */
 /*
  * Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
  *
@@ -58,6 +58,7 @@ ratelimit(int fd, short type, void *arg)
        com1_dev.regs.iir |= IIR_TXRDY;
        com1_dev.regs.iir &= ~IIR_NOPEND;
        vcpu_assert_pic_irq(com1_dev.vmid, 0, com1_dev.irq);
+       vcpu_deassert_pic_irq(com1_dev.vmid, 0, com1_dev.irq);
 }
 
 void
@@ -127,6 +128,7 @@ com_rcv_event(int fd, short kind, void *arg)
                if ((com1_dev.regs.iir & IIR_NOPEND) == 0) {
                        /* XXX: vcpu_id */
                        vcpu_assert_pic_irq((uintptr_t)arg, 0, com1_dev.irq);
+                       vcpu_deassert_pic_irq((uintptr_t)arg, 0, com1_dev.irq);
                }
        }
 
@@ -592,11 +594,6 @@ vcpu_exit_com(struct vm_run_params *vrp)
 
        mutex_unlock(&com1_dev.mutex);
 
-       if ((com1_dev.regs.iir & IIR_NOPEND)) {
-               /* XXX: vcpu_id */
-               vcpu_deassert_pic_irq(com1_dev.vmid, 0, com1_dev.irq);
-       }
-
        return (intr);
 }
 
index 599dda4..4622ef4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: virtio.c,v 1.62 2018/07/09 08:43:09 mlarkin Exp $     */
+/*     $OpenBSD: virtio.c,v 1.63 2018/07/09 16:11:37 mlarkin Exp $     */
 
 /*
  * Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
@@ -308,6 +308,7 @@ virtio_rnd_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
                case VIRTIO_CONFIG_ISR_STATUS:
                        *data = viornd.cfg.isr_status;
                        viornd.cfg.isr_status = 0;
+                       vcpu_deassert_pic_irq(viornd.vm_id, 0, viornd.irq);
                        break;
                }
        }
@@ -759,6 +760,7 @@ virtio_blk_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
                                dev->cfg.queue_notify = 0;
                                dev->cfg.isr_status = 0;
                                dev->vq[0].last_avail = 0;
+                               vcpu_deassert_pic_irq(dev->vm_id, 0, dev->irq);
                        }
                        break;
                default:
@@ -927,6 +929,7 @@ virtio_blk_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
                case VIRTIO_CONFIG_ISR_STATUS:
                        *data = dev->cfg.isr_status;
                        dev->cfg.isr_status = 0;
+                       vcpu_deassert_pic_irq(dev->vm_id, 0, dev->irq);
                        break;
                }
        }
@@ -982,6 +985,7 @@ virtio_net_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
                                dev->vq[RXQ].notified_avail = 0;
                                dev->vq[TXQ].last_avail = 0;
                                dev->vq[TXQ].notified_avail = 0;
+                               vcpu_deassert_pic_irq(dev->vm_id, 0, dev->irq);
                        }
                        break;
                default:
@@ -1022,6 +1026,7 @@ virtio_net_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
                case VIRTIO_CONFIG_ISR_STATUS:
                        *data = dev->cfg.isr_status;
                        dev->cfg.isr_status = 0;
+                       vcpu_deassert_pic_irq(dev->vm_id, 0, dev->irq);
                        break;
                }
        }
@@ -1727,6 +1732,7 @@ vmmci_io(int dir, uint16_t reg, uint32_t *data, uint8_t *intr,
                case VIRTIO_CONFIG_ISR_STATUS:
                        *data = vmmci.cfg.isr_status;
                        vmmci.cfg.isr_status = 0;
+                       vcpu_deassert_pic_irq(vmmci.vm_id, 0, vmmci.irq);
                        break;
                }
        }
@@ -1770,6 +1776,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
            + sizeof(uint16_t) * (2 + VIORND_QUEUE_SIZE));
        viornd.pci_id = id;
        viornd.irq = pci_get_dev_irq(id);
+       viornd.vm_id = vcp->vcp_id;
 
        if (vcp->vcp_ndisks > 0) {
                nr_vioblk = vcp->vcp_ndisks;
@@ -1813,6 +1820,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
                        vioblk[i].cfg.device_feature = VIRTIO_BLK_F_SIZE_MAX;
                        vioblk[i].max_xfer = 1048576;
                        vioblk[i].pci_id = id;
+                       vioblk[i].vm_id = vcp->vcp_id;
                        vioblk[i].irq = pci_get_dev_irq(id);
                }
        }
@@ -1944,6 +1952,7 @@ virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
                vioscsi->n_blocks = sz >> 11; /* num of 2048 blocks in file */
                vioscsi->max_xfer = VIOSCSI_BLOCK_SIZE_CDROM;
                vioscsi->pci_id = id;
+               vioscsi->vm_id = vcp->vcp_id;
                vioscsi->irq = pci_get_dev_irq(id);
        }