From 71ab85de86c9965af0a2d6132e10736e2dd4e37f Mon Sep 17 00:00:00 2001 From: dv Date: Tue, 26 Sep 2023 01:23:02 +0000 Subject: [PATCH] vmd(8): fix vm pause deadlock. When vcpu threads pause, they are holding the run mutex lock. If the event thread is asked to assert an irq on the pic and interrupts are pending, it will try to take the run mutex lock on the vcpu. This deadlocks. Release the lock in the vcpu thread before waiting on the pause condition variable. ok mlarkin@ --- usr.sbin/vmd/vm.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index fe804b4e3b9..115a60c3683 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm.c,v 1.92 2023/09/23 12:27:21 dv Exp $ */ +/* $OpenBSD: vm.c,v 1.93 2023/09/26 01:23:02 dv Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -1565,6 +1565,8 @@ vcpu_run_loop(void *arg) return ((void *)ret); } + /* i8259 may be firing as we pause, release run mtx. */ + mutex_unlock(&vcpu_run_mtx[n]); ret = pthread_cond_wait(&vcpu_unpause_cond[n], &vcpu_unpause_mtx[n]); if (ret) { @@ -1573,6 +1575,8 @@ vcpu_run_loop(void *arg) __func__, (int)ret); break; } + mutex_lock(&vcpu_run_mtx[n]); + ret = pthread_mutex_unlock(&vcpu_unpause_mtx[n]); if (ret) { log_warnx("%s: can't unlock unpause mtx (%d)", @@ -2136,18 +2140,12 @@ vcpu_assert_pic_irq(uint32_t vm_id, uint32_t vcpu_id, int irq) if (i8259_is_pending()) { if (vcpu_pic_intr(vm_id, vcpu_id, 1)) fatalx("%s: can't assert INTR", __func__); - - ret = pthread_mutex_lock(&vcpu_run_mtx[vcpu_id]); - if (ret) - fatalx("%s: can't lock vcpu mtx (%d)", __func__, ret); - + mutex_lock(&vcpu_run_mtx[vcpu_id]); vcpu_hlt[vcpu_id] = 0; ret = pthread_cond_signal(&vcpu_run_cond[vcpu_id]); if (ret) fatalx("%s: can't signal (%d)", __func__, ret); - ret = pthread_mutex_unlock(&vcpu_run_mtx[vcpu_id]); - if (ret) - fatalx("%s: can't unlock vcpu mtx (%d)", __func__, ret); + mutex_unlock(&vcpu_run_mtx[vcpu_id]); } } -- 2.20.1