summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorDave Voutila <dv@cvs.openbsd.org>2023-01-30 21:43:13 +0000
committerDave Voutila <dv@cvs.openbsd.org>2023-01-30 21:43:13 +0000
commit5e49cce84bbae151f792ee7b3e02ed888dac2ee2 (patch)
treeda7ac67d98f6da8f65024d07a97af7feae32b182 /usr.sbin
parent04da052954425aebad15c530d9ca81bb70e5685c (diff)
vmd(8): fix an interrupt storm in ns8250.
On slower hosts, such as those in a nested virtualization scenario of OpenBSD guest inside OpenBSD atop Linux KVM, ns8250 can cause a race between the kevent firing and the vcpu being kicked by an assert/deassert of the irq. The end user experiences a "stuck" serial console and the host will see a vmd process peg the cpu. This change only toggles the irq if we were in a position of being ready to receive data on the device so while the kevent might continuously fire, the vcpu will not be kicked repeatedly. OK mlarkin@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/vmd/ns8250.c15
1 files changed, 8 insertions, 7 deletions
diff --git a/usr.sbin/vmd/ns8250.c b/usr.sbin/vmd/ns8250.c
index dbb6568714c..f9d14338323 100644
--- a/usr.sbin/vmd/ns8250.c
+++ b/usr.sbin/vmd/ns8250.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns8250.c,v 1.34 2022/12/28 21:30:19 jmc Exp $ */
+/* $OpenBSD: ns8250.c,v 1.35 2023/01/30 21:43:12 dv Exp $ */
/*
* Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
*
@@ -153,14 +153,15 @@ com_rcv_event(int fd, short kind, void *arg)
return;
}
- if ((com1_dev.regs.lsr & LSR_RXRDY) == 0)
+ if ((com1_dev.regs.lsr & LSR_RXRDY) == 0) {
com_rcv(&com1_dev, (uintptr_t)arg, 0);
- /* If pending interrupt, inject */
- 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);
+ /* If pending interrupt, inject */
+ 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);
+ }
}
mutex_unlock(&com1_dev.mutex);