summaryrefslogtreecommitdiffstats
path: root/usr.sbin/vmd
diff options
context:
space:
mode:
authorpd <pd@openbsd.org>2020-06-16 06:23:51 +0000
committerpd <pd@openbsd.org>2020-06-16 06:23:51 +0000
commit234862b993eae6eece64b5046479f88bd7ae4ef0 (patch)
treee99e057981b90f70cb63507154ecc2d1e85abf67 /usr.sbin/vmd
parentconfigure toeplitz using the kernel stoeplitz key if needed. (diff)
downloadwireguard-openbsd-234862b993eae6eece64b5046479f88bd7ae4ef0.tar.xz
wireguard-openbsd-234862b993eae6eece64b5046479f88bd7ae4ef0.zip
vmd(8): fix ns8250 lockup due to race condition
Inject pending interrupt if com has receive pending. This was previously accidently checked in with an unrelated change by Mike Larkin and was backed out as it didn't fix the intended problem. Also, protect com ratelimit handler with mutexes to avoid corruption of the device state. These changes help preventing linux vm crashes when the return key is held on boot. Discovered by and patch from Dave Voutila <dave@sisu.io>
Diffstat (limited to 'usr.sbin/vmd')
-rw-r--r--usr.sbin/vmd/ns8250.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/usr.sbin/vmd/ns8250.c b/usr.sbin/vmd/ns8250.c
index 497e6fad550..44b7e20c5d1 100644
--- a/usr.sbin/vmd/ns8250.c
+++ b/usr.sbin/vmd/ns8250.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ns8250.c,v 1.25 2019/12/11 06:45:16 pd Exp $ */
+/* $OpenBSD: ns8250.c,v 1.26 2020/06/16 06:23:51 pd Exp $ */
/*
* Copyright (c) 2016 Mike Larkin <mlarkin@openbsd.org>
*
@@ -55,10 +55,13 @@ static void
ratelimit(int fd, short type, void *arg)
{
/* Set TXRDY and clear "no pending interrupt" */
+ mutex_lock(&com1_dev.mutex);
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);
+ mutex_unlock(&com1_dev.mutex);
}
void
@@ -130,21 +133,26 @@ com_rcv_event(int fd, short kind, void *arg)
* has become available now will be moved to the com port later.
*/
if (com1_dev.rcv_pending) {
- mutex_unlock(&com1_dev.mutex);
- return;
+ goto end;
}
if (com1_dev.regs.lsr & LSR_RXRDY)
com1_dev.rcv_pending = 1;
else {
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);
- }
+end:
+ if (com1_dev.regs.ier & IER_ERXRDY) {
+ com1_dev.regs.iir |= IIR_RXRDY;
+ com1_dev.regs.iir &= ~IIR_NOPEND;
+ }
+
+ /* 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);