Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 9 Jan 2020 08:29:31 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r356543 - in stable/12/sys/amd64: include vmm vmm/io
Message-ID:  <202001090829.0098TV4a014246@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Thu Jan  9 08:29:31 2020
New Revision: 356543
URL: https://svnweb.freebsd.org/changeset/base/356543

Log:
  MFC r356296:
  bhyve: terminate waiting loops if thread suspension is requested.
  
  PR:	242724

Modified:
  stable/12/sys/amd64/include/vmm.h
  stable/12/sys/amd64/vmm/io/vioapic.c
  stable/12/sys/amd64/vmm/vmm.c
  stable/12/sys/amd64/vmm/vmm_dev.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/amd64/include/vmm.h
==============================================================================
--- stable/12/sys/amd64/include/vmm.h	Thu Jan  9 08:24:09 2020	(r356542)
+++ stable/12/sys/amd64/include/vmm.h	Thu Jan  9 08:29:31 2020	(r356543)
@@ -267,7 +267,7 @@ void vm_exit_reqidle(struct vm *vm, int vcpuid, uint64
  * forward progress when the rendezvous is in progress.
  */
 typedef void (*vm_rendezvous_func_t)(struct vm *vm, int vcpuid, void *arg);
-void vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
+int vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
     vm_rendezvous_func_t func, void *arg);
 cpuset_t vm_active_cpus(struct vm *vm);
 cpuset_t vm_debug_cpus(struct vm *vm);

Modified: stable/12/sys/amd64/vmm/io/vioapic.c
==============================================================================
--- stable/12/sys/amd64/vmm/io/vioapic.c	Thu Jan  9 08:24:09 2020	(r356542)
+++ stable/12/sys/amd64/vmm/io/vioapic.c	Thu Jan  9 08:29:31 2020	(r356543)
@@ -353,7 +353,7 @@ vioapic_write(struct vioapic *vioapic, int vcpuid, uin
 			    "vlapic trigger-mode register", pin);
 			VIOAPIC_UNLOCK(vioapic);
 			allvcpus = vm_active_cpus(vioapic->vm);
-			vm_smp_rendezvous(vioapic->vm, vcpuid, allvcpus,
+			(void)vm_smp_rendezvous(vioapic->vm, vcpuid, allvcpus,
 			    vioapic_update_tmr, NULL);
 			VIOAPIC_LOCK(vioapic);
 		}

Modified: stable/12/sys/amd64/vmm/vmm.c
==============================================================================
--- stable/12/sys/amd64/vmm/vmm.c	Thu Jan  9 08:24:09 2020	(r356542)
+++ stable/12/sys/amd64/vmm/vmm.c	Thu Jan  9 08:29:31 2020	(r356543)
@@ -1244,13 +1244,17 @@ vcpu_require_state_locked(struct vm *vm, int vcpuid, e
 			VM_CTR0(vm, fmt);				\
 	} while (0)
 
-static void
+static int
 vm_handle_rendezvous(struct vm *vm, int vcpuid)
 {
+	struct thread *td;
+	int error;
 
 	KASSERT(vcpuid == -1 || (vcpuid >= 0 && vcpuid < vm->maxcpus),
 	    ("vm_handle_rendezvous: invalid vcpuid %d", vcpuid));
 
+	error = 0;
+	td = curthread;
 	mtx_lock(&vm->rendezvous_mtx);
 	while (vm->rendezvous_func != NULL) {
 		/* 'rendezvous_req_cpus' must be a subset of 'active_cpus' */
@@ -1272,9 +1276,17 @@ vm_handle_rendezvous(struct vm *vm, int vcpuid)
 		}
 		RENDEZVOUS_CTR0(vm, vcpuid, "Wait for rendezvous completion");
 		mtx_sleep(&vm->rendezvous_func, &vm->rendezvous_mtx, 0,
-		    "vmrndv", 0);
+		    "vmrndv", hz);
+		if ((td->td_flags & TDF_NEEDSUSPCHK) != 0) {
+			mtx_unlock(&vm->rendezvous_mtx);
+			error = thread_check_susp(td, true);
+			if (error != 0)
+				return (error);
+			mtx_lock(&vm->rendezvous_mtx);
+		}
 	}
 	mtx_unlock(&vm->rendezvous_mtx);
+	return (0);
 }
 
 /*
@@ -1285,13 +1297,16 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_dis
 {
 	struct vcpu *vcpu;
 	const char *wmesg;
-	int t, vcpu_halted, vm_halted;
+	struct thread *td;
+	int error, t, vcpu_halted, vm_halted;
 
 	KASSERT(!CPU_ISSET(vcpuid, &vm->halted_cpus), ("vcpu already halted"));
 
 	vcpu = &vm->vcpu[vcpuid];
 	vcpu_halted = 0;
 	vm_halted = 0;
+	error = 0;
+	td = curthread;
 
 	vcpu_lock(vcpu);
 	while (1) {
@@ -1352,6 +1367,13 @@ vm_handle_hlt(struct vm *vm, int vcpuid, bool intr_dis
 		msleep_spin(vcpu, &vcpu->mtx, wmesg, hz);
 		vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN);
 		vmm_stat_incr(vm, vcpuid, VCPU_IDLE_TICKS, ticks - t);
+		if ((td->td_flags & TDF_NEEDSUSPCHK) != 0) {
+			vcpu_unlock(vcpu);
+			error = thread_check_susp(td, false);
+			if (error != 0)
+				return (error);
+			vcpu_lock(vcpu);
+		}
 	}
 
 	if (vcpu_halted)
@@ -1488,11 +1510,13 @@ vm_handle_inst_emul(struct vm *vm, int vcpuid, bool *r
 static int
 vm_handle_suspend(struct vm *vm, int vcpuid, bool *retu)
 {
-	int i, done;
+	int error, i;
 	struct vcpu *vcpu;
+	struct thread *td;
 
-	done = 0;
+	error = 0;
 	vcpu = &vm->vcpu[vcpuid];
+	td = curthread;
 
 	CPU_SET_ATOMIC(vcpuid, &vm->suspended_cpus);
 
@@ -1504,7 +1528,7 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *ret
 	 * handler while we are waiting to prevent a deadlock.
 	 */
 	vcpu_lock(vcpu);
-	while (1) {
+	while (error == 0) {
 		if (CPU_CMP(&vm->suspended_cpus, &vm->active_cpus) == 0) {
 			VCPU_CTR0(vm, vcpuid, "All vcpus suspended");
 			break;
@@ -1515,10 +1539,15 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *ret
 			vcpu_require_state_locked(vm, vcpuid, VCPU_SLEEPING);
 			msleep_spin(vcpu, &vcpu->mtx, "vmsusp", hz);
 			vcpu_require_state_locked(vm, vcpuid, VCPU_FROZEN);
+			if ((td->td_flags & TDF_NEEDSUSPCHK) != 0) {
+				vcpu_unlock(vcpu);
+				error = thread_check_susp(td, false);
+				vcpu_lock(vcpu);
+			}
 		} else {
 			VCPU_CTR0(vm, vcpuid, "Rendezvous during suspend");
 			vcpu_unlock(vcpu);
-			vm_handle_rendezvous(vm, vcpuid);
+			error = vm_handle_rendezvous(vm, vcpuid);
 			vcpu_lock(vcpu);
 		}
 	}
@@ -1534,7 +1563,7 @@ vm_handle_suspend(struct vm *vm, int vcpuid, bool *ret
 	}
 
 	*retu = true;
-	return (0);
+	return (error);
 }
 
 static int
@@ -1708,8 +1737,7 @@ restart:
 			    vme->u.ioapic_eoi.vector);
 			break;
 		case VM_EXITCODE_RENDEZVOUS:
-			vm_handle_rendezvous(vm, vcpuid);
-			error = 0;
+			error = vm_handle_rendezvous(vm, vcpuid);
 			break;
 		case VM_EXITCODE_HLT:
 			intr_disabled = ((vme->u.hlt.rflags & PSL_I) == 0);
@@ -2487,11 +2515,11 @@ vm_apicid2vcpuid(struct vm *vm, int apicid)
 	return (apicid);
 }
 
-void
+int
 vm_smp_rendezvous(struct vm *vm, int vcpuid, cpuset_t dest,
     vm_rendezvous_func_t func, void *arg)
 {
-	int i;
+	int error, i;
 
 	/*
 	 * Enforce that this function is called without any locks
@@ -2510,7 +2538,9 @@ restart:
 		 */
 		RENDEZVOUS_CTR0(vm, vcpuid, "Rendezvous already in progress");
 		mtx_unlock(&vm->rendezvous_mtx);
-		vm_handle_rendezvous(vm, vcpuid);
+		error = vm_handle_rendezvous(vm, vcpuid);
+		if (error != 0)
+			return (error);
 		goto restart;
 	}
 	KASSERT(vm->rendezvous_func == NULL, ("vm_smp_rendezvous: previous "
@@ -2532,7 +2562,7 @@ restart:
 			vcpu_notify_event(vm, i, false);
 	}
 
-	vm_handle_rendezvous(vm, vcpuid);
+	return (vm_handle_rendezvous(vm, vcpuid));
 }
 
 struct vatpic *

Modified: stable/12/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- stable/12/sys/amd64/vmm/vmm_dev.c	Thu Jan  9 08:24:09 2020	(r356542)
+++ stable/12/sys/amd64/vmm/vmm_dev.c	Thu Jan  9 08:29:31 2020	(r356543)
@@ -790,8 +790,12 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t da
 		vcpu_unlock_all(sc);
 
 done:
-	/* Make sure that no handler returns a bogus value like ERESTART */
-	KASSERT(error >= 0, ("vmmdev_ioctl: invalid error return %d", error));
+	/*
+	 * Make sure that no handler returns a kernel-internal
+	 * error value to userspace.
+	 */
+	KASSERT(error == ERESTART || error >= 0,
+	    ("vmmdev_ioctl: invalid error return %d", error));
 	return (error);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202001090829.0098TV4a014246>