From nobody Wed May 24 01:17:52 2023 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4QQtbN61KWz4TJ5q; Wed, 24 May 2023 01:17:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4QQtbN5fRpz3CQ0; Wed, 24 May 2023 01:17:52 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1684891072; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LDgfgpBJ7E77xYpGlDKdixDMBPZGUKSlqf2PtLs+yLc=; b=UmXOkluTmOJdWKjunBvioVyd5NdO5jsptY4gOx8aYMPqbMsSEfRsWhvA1um+5r39AvKvdf w6Y5PD2lxO310uzWDHZtGPhscH3fXSAMP/40FvQYfbqtrZN7CE8Fe4prIAq2pwHXCKbCKu 5yRNoUM2bn+OhCxudfOIwq+qRZRgO0rjHe3BOIc43q45BIxxLpWonnllgPGiw2hbt1wTyz tOG5a8G1vABtes0ouhq0QLY/15JPiWsvBw3BeKHQZtLElcaRg7m40okCTO0/fA7Rb60WXy qXmEvxU76L9riVVg5XcOTyNlzpMJIYFf6FY5vM8XlmooZvkrrFlGoRpgOFWWXg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1684891072; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=LDgfgpBJ7E77xYpGlDKdixDMBPZGUKSlqf2PtLs+yLc=; b=USp7+e5yKIicZX2IkSoPnxm64pE1vq29tMqGQxAGQhhbrh6sBnDAXNy2tx3YXZTFXc2YH9 2BfNXGo6KBj0qPiBSdeCZ4RypQ0KmthfR1+51L2XUnqefNlhXVMOmbFdDG6MdAdwhgektT iSvPmakKT3wI8TWFDKiE9Y0aUG/TlrLc8SNUac0WkEFrx+Q2GzfEyxJA+R5hnY6DYUQiXv 1xaT1T9rfjwqLhoJWac6t0bj5vunCfed3K4K7nvP36mGiGceUPePPWDzIAMrWBUcAmTBmp 3pL/3duLki/iyxdp4Q5BIN9GG5a1mJFuG0WL74FLw36FDG6QQ9FtA0XdtpWEaw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1684891072; a=rsa-sha256; cv=none; b=qB3olA+g5f3aY+AvKRqkF5GNU7GBfvK4Y+1ZR+y8Na10LLe5srUWX1WRJEl7p+F7txGu3M C/fav+KS91xF7HeNMttE9Re6FuUy8Q3Hf5XYhyiK2g4dFVMerlh/wv9ImM3hTYyrKPYWWv UxxfBHwYeNTaobNCEHNc/wdu5CtZvkSvQCJWCEqZ6+8gIezH7GiRUZ+V6BEHKgmSvnR+Ww uxesLItv760IJGyZgBSNTKV8RI844Djsa9wO2EyDqCy3mAJH3s5ZC6Vhlnmlv2Hs7S2aSj 1yVBTwuSfFfFE3jsCvsxhk5cRjN0jkoxp6bodjSxmqo+X4sDFfr3gfZ5D1+u6w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4QQtbN4hJnzNKP; Wed, 24 May 2023 01:17:52 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 34O1HqD4087001; Wed, 24 May 2023 01:17:52 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 34O1Hqbf086999; Wed, 24 May 2023 01:17:52 GMT (envelope-from git) Date: Wed, 24 May 2023 01:17:52 GMT Message-Id: <202305240117.34O1Hqbf086999@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Mark Johnston Subject: git: e17eca327633 - main - vmm: Avoid embedding cpuset_t ioctl ABIs List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: markj X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e17eca327633efc511450310afb5e4a662724e3d Auto-Submitted: auto-generated X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=e17eca327633efc511450310afb5e4a662724e3d commit e17eca327633efc511450310afb5e4a662724e3d Author: Mark Johnston AuthorDate: 2023-05-24 01:13:33 +0000 Commit: Mark Johnston CommitDate: 2023-05-24 01:15:59 +0000 vmm: Avoid embedding cpuset_t ioctl ABIs Commit 0bda8d3e9f7a ("vmm: permit some IPIs to be handled by userspace") embedded cpuset_t into the vmm(4) ioctl ABI. This was a mistake since we otherwise have some leeway to change the cpuset_t for the whole system, but we want to keep the vmm ioctl ABI stable. Rework IPI reporting to avoid this problem. Along the way, make VM_RUN a bit more efficient: - Split vmexit metadata out of the main VM_RUN structure. This data is only written by the kernel. - Have userspace pass a cpuset_t pointer and cpusetsize in the VM_RUN structure, as is done for cpuset syscalls. - Have the destination CPU mask for VM_EXITCODE_IPIs live outside the vmexit info structure, and make VM_RUN copy it out separately. Zero out any extra bytes in the CPU mask, like cpuset syscalls do. - Modify the vmexit handler prototype to take a full VM_RUN structure. PR: 271330 Reviewed by: corvink, jhb (previous versions) Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D40113 --- lib/libvmmapi/vmmapi.c | 11 +---- lib/libvmmapi/vmmapi.h | 2 +- sys/amd64/include/vmm.h | 9 +++- sys/amd64/include/vmm_dev.h | 6 ++- sys/amd64/vmm/io/vlapic.c | 4 +- sys/amd64/vmm/vmm.c | 11 +++-- sys/amd64/vmm/vmm_dev.c | 98 ++++++++++++++++++++++++++++++++++++++++++-- usr.sbin/bhyve/bhyverun.c | 91 +++++++++++++++++++++++++--------------- usr.sbin/bhyve/bhyverun.h | 4 +- usr.sbin/bhyve/task_switch.c | 4 +- 10 files changed, 182 insertions(+), 58 deletions(-) diff --git a/lib/libvmmapi/vmmapi.c b/lib/libvmmapi/vmmapi.c index 05b0d1135fd1..25e19c0d9931 100644 --- a/lib/libvmmapi/vmmapi.c +++ b/lib/libvmmapi/vmmapi.c @@ -721,16 +721,9 @@ vm_get_register_set(struct vcpu *vcpu, unsigned int count, } int -vm_run(struct vcpu *vcpu, struct vm_exit *vmexit) +vm_run(struct vcpu *vcpu, struct vm_run *vmrun) { - int error; - struct vm_run vmrun; - - bzero(&vmrun, sizeof(vmrun)); - - error = vcpu_ioctl(vcpu, VM_RUN, &vmrun); - bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit)); - return (error); + return (vcpu_ioctl(vcpu, VM_RUN, vmrun)); } int diff --git a/lib/libvmmapi/vmmapi.h b/lib/libvmmapi/vmmapi.h index e75f5e471d77..00d48a61fda2 100644 --- a/lib/libvmmapi/vmmapi.h +++ b/lib/libvmmapi/vmmapi.h @@ -155,7 +155,7 @@ int vm_set_register_set(struct vcpu *vcpu, unsigned int count, const int *regnums, uint64_t *regvals); int vm_get_register_set(struct vcpu *vcpu, unsigned int count, const int *regnums, uint64_t *regvals); -int vm_run(struct vcpu *vcpu, struct vm_exit *ret_vmexit); +int vm_run(struct vcpu *vcpu, struct vm_run *vmrun); int vm_suspend(struct vmctx *ctx, enum vm_suspend_how how); int vm_reinit(struct vmctx *ctx); int vm_apicid2vcpu(struct vmctx *ctx, int apicid); diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index ca7ed25506b0..163fcf669ae0 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -273,7 +273,7 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *ret_desc); int vm_set_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *desc); -int vm_run(struct vcpu *vcpu, struct vm_exit *vme_user); +int vm_run(struct vcpu *vcpu); int vm_suspend(struct vm *vm, enum vm_suspend_how how); int vm_inject_nmi(struct vcpu *vcpu); int vm_nmi_pending(struct vcpu *vcpu); @@ -297,6 +297,7 @@ int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); int vm_restart_instruction(struct vcpu *vcpu); struct vm_exit *vm_exitinfo(struct vcpu *vcpu); +cpuset_t *vm_exitinfo_cpuset(struct vcpu *vcpu); void vm_exit_suspended(struct vcpu *vcpu, uint64_t rip); void vm_exit_debug(struct vcpu *vcpu, uint64_t rip); void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t rip); @@ -754,9 +755,13 @@ struct vm_exit { enum vm_suspend_how how; } suspended; struct { + /* + * The destination vCPU mask is saved in vcpu->cpuset + * and is copied out to userspace separately to avoid + * ABI concerns. + */ uint32_t mode; uint8_t vector; - cpuset_t dmask; } ipi; struct vm_task_switch task_switch; } u; diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h index def48a9f86fe..42406b115933 100644 --- a/sys/amd64/include/vmm_dev.h +++ b/sys/amd64/include/vmm_dev.h @@ -89,7 +89,9 @@ struct vm_register_set { struct vm_run { int cpuid; - struct vm_exit vm_exit; + cpuset_t *cpuset; /* CPU set storage */ + size_t cpusetsize; + struct vm_exit *vm_exit; }; struct vm_exception { @@ -349,7 +351,7 @@ enum { }; #define VM_RUN \ - _IOWR('v', IOCNUM_RUN, struct vm_run) + _IOW('v', IOCNUM_RUN, struct vm_run) #define VM_SUSPEND \ _IOW('v', IOCNUM_SUSPEND, struct vm_suspend) #define VM_REINIT \ diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index 45a70e494e62..d36a7738278e 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -1146,7 +1146,7 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu) vmexit->exitcode = VM_EXITCODE_IPI; vmexit->u.ipi.mode = mode; vmexit->u.ipi.vector = vec; - vmexit->u.ipi.dmask = ipimask; + *vm_exitinfo_cpuset(vlapic->vcpu) = ipimask; *retu = true; } @@ -1166,7 +1166,7 @@ int vm_handle_ipi(struct vcpu *vcpu, struct vm_exit *vme, bool *retu) { struct vlapic *vlapic = vm_lapic(vcpu); - cpuset_t *dmask = &vme->u.ipi.dmask; + cpuset_t *dmask = vm_exitinfo_cpuset(vcpu); uint8_t vec = vme->u.ipi.vector; *retu = true; diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 81d5212ec744..0f29a6845f9e 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -123,6 +123,7 @@ struct vcpu { uint64_t guest_xcr0; /* (i) guest %xcr0 register */ void *stats; /* (a,i) statistics */ struct vm_exit exitinfo; /* (x) exit reason and collateral */ + cpuset_t exitinfo_cpuset; /* (x) storage for vmexit handlers */ uint64_t nextrip; /* (x) next instruction to execute */ uint64_t tsc_offset; /* (o) TSC offsetting */ }; @@ -399,6 +400,12 @@ vm_exitinfo(struct vcpu *vcpu) return (&vcpu->exitinfo); } +cpuset_t * +vm_exitinfo_cpuset(struct vcpu *vcpu) +{ + return (&vcpu->exitinfo_cpuset); +} + static int vmm_init(void) { @@ -1837,7 +1844,7 @@ vm_exit_astpending(struct vcpu *vcpu, uint64_t rip) } int -vm_run(struct vcpu *vcpu, struct vm_exit *vme_user) +vm_run(struct vcpu *vcpu) { struct vm *vm = vcpu->vm; struct vm_eventinfo evinfo; @@ -1938,8 +1945,6 @@ restart: vmm_stat_incr(vcpu, VMEXIT_USERSPACE, 1); VMM_CTR2(vcpu, "retu %d/%d", error, vme->exitcode); - /* copy the exit information */ - *vme_user = *vme; return (error); } diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c index 85b5bac9efe1..f9fcb32d8e28 100644 --- a/sys/amd64/vmm/vmm_dev.c +++ b/sys/amd64/vmm/vmm_dev.c @@ -93,7 +93,29 @@ struct vm_snapshot_meta_old { #define VM_SNAPSHOT_REQ_OLD \ _IOWR('v', IOCNUM_SNAPSHOT_REQ, struct vm_snapshot_meta_old) -#endif + +struct vm_exit_ipi_13 { + uint32_t mode; + uint8_t vector; + __BITSET_DEFINE(, 256) dmask; +}; + +struct vm_exit_13 { + uint32_t exitcode; + int32_t inst_length; + uint64_t rip; + uint64_t u[120 / sizeof(uint64_t)]; +}; + +struct vm_run_13 { + int cpuid; + struct vm_exit_13 vm_exit; +}; + +#define VM_RUN_13 \ + _IOWR('v', IOCNUM_RUN, struct vm_run_13) + +#endif /* COMPAT_FREEBSD13 */ struct devmem_softc { int segid; @@ -396,6 +418,9 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, struct vm_seg_desc *vmsegdesc; struct vm_register_set *vmregset; struct vm_run *vmrun; +#ifdef COMPAT_FREEBSD13 + struct vm_run_13 *vmrun_13; +#endif struct vm_exception *vmexc; struct vm_lapic_irq *vmirq; struct vm_lapic_msi *vmmsi; @@ -459,6 +484,9 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, */ switch (cmd) { case VM_RUN: +#ifdef COMPAT_FREEBSD13 + case VM_RUN_13: +#endif case VM_GET_REGISTER: case VM_SET_REGISTER: case VM_GET_SEGMENT_DESCRIPTOR: @@ -579,11 +607,73 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, break; } - switch(cmd) { - case VM_RUN: + switch (cmd) { + case VM_RUN: { + struct vm_exit *vme; + vmrun = (struct vm_run *)data; - error = vm_run(vcpu, &vmrun->vm_exit); + vme = vm_exitinfo(vcpu); + + error = vm_run(vcpu); + if (error != 0) + break; + + error = copyout(vme, vmrun->vm_exit, sizeof(*vme)); + if (error != 0) + break; + if (vme->exitcode == VM_EXITCODE_IPI) { + error = copyout(vm_exitinfo_cpuset(vcpu), + vmrun->cpuset, + min(vmrun->cpusetsize, sizeof(cpuset_t))); + if (error != 0) + break; + if (sizeof(cpuset_t) < vmrun->cpusetsize) { + uint8_t *p; + + p = (uint8_t *)vmrun->cpuset + + sizeof(cpuset_t); + while (error == 0 && + p < (uint8_t *)vmrun->cpuset + + vmrun->cpusetsize) { + error = subyte(p++, 0); + } + } + } break; + } +#ifdef COMPAT_FREEBSD13 + case VM_RUN_13: { + struct vm_exit *vme; + struct vm_exit_13 *vme_13; + + vmrun_13 = (struct vm_run_13 *)data; + vme_13 = &vmrun_13->vm_exit; + vme = vm_exitinfo(vcpu); + + error = vm_run(vcpu); + if (error == 0) { + vme_13->exitcode = vme->exitcode; + vme_13->inst_length = vme->inst_length; + vme_13->rip = vme->rip; + memcpy(vme_13->u, &vme->u, sizeof(vme_13->u)); + if (vme->exitcode == VM_EXITCODE_IPI) { + struct vm_exit_ipi_13 *ipi; + cpuset_t *dmask; + int cpu; + + dmask = vm_exitinfo_cpuset(vcpu); + ipi = (struct vm_exit_ipi_13 *)&vme_13->u[0]; + BIT_ZERO(256, &ipi->dmask); + CPU_FOREACH_ISSET(cpu, dmask) { + if (cpu >= 256) + break; + BIT_SET(256, cpu, &ipi->dmask); + } + } + } + break; + } +#endif case VM_SUSPEND: vmsuspend = (struct vm_suspend *)data; error = vm_suspend(sc->vm, vmsuspend->how); diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c index 25d8937138e6..7be97ecedfdc 100644 --- a/usr.sbin/bhyve/bhyverun.c +++ b/usr.sbin/bhyve/bhyverun.c @@ -184,7 +184,7 @@ static const char * const vmx_exit_reason_desc[] = { [EXIT_REASON_XRSTORS] = "XRSTORS" }; -typedef int (*vmexit_handler_t)(struct vmctx *, struct vcpu *, struct vm_exit *); +typedef int (*vmexit_handler_t)(struct vmctx *, struct vcpu *, struct vm_run *); int guest_ncpus; uint16_t cpu_cores, cpu_sockets, cpu_threads; @@ -592,11 +592,13 @@ vmexit_handle_notify(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, } static int -vmexit_inout(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vme) +vmexit_inout(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun) { + struct vm_exit *vme; int error; int bytes, port, in, out; + vme = vmrun->vm_exit; port = vme->u.inout.port; bytes = vme->u.inout.bytes; in = vme->u.inout.in; @@ -621,12 +623,16 @@ vmexit_inout(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vme) } static int -vmexit_rdmsr(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_exit *vme) +vmexit_rdmsr(struct vmctx *ctx __unused, struct vcpu *vcpu, + struct vm_run *vmrun) { + struct vm_exit *vme; uint64_t val; uint32_t eax, edx; int error; + vme = vmrun->vm_exit; + val = 0; error = emulate_rdmsr(vcpu, vme->u.msr.code, &val); if (error != 0) { @@ -650,10 +656,14 @@ vmexit_rdmsr(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_exit *vme) } static int -vmexit_wrmsr(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_exit *vme) +vmexit_wrmsr(struct vmctx *ctx __unused, struct vcpu *vcpu, + struct vm_run *vmrun) { + struct vm_exit *vme; int error; + vme = vmrun->vm_exit; + error = emulate_wrmsr(vcpu, vme->u.msr.code, vme->u.msr.wval); if (error != 0) { fprintf(stderr, "wrmsr to register %#x(%#lx) on vcpu %d\n", @@ -685,8 +695,11 @@ vmexit_vmx_desc(uint32_t exit_reason) } static int -vmexit_vmx(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vme) +vmexit_vmx(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun) { + struct vm_exit *vme; + + vme = vmrun->vm_exit; fprintf(stderr, "vm exit[%d]\n", vcpu_id(vcpu)); fprintf(stderr, "\treason\t\tVMX\n"); @@ -718,8 +731,11 @@ vmexit_vmx(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vme) } static int -vmexit_svm(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_exit *vme) +vmexit_svm(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_run *vmrun) { + struct vm_exit *vme; + + vme = vmrun->vm_exit; fprintf(stderr, "vm exit[%d]\n", vcpu_id(vcpu)); fprintf(stderr, "\treason\t\tSVM\n"); @@ -733,10 +749,9 @@ vmexit_svm(struct vmctx *ctx __unused, struct vcpu *vcpu, struct vm_exit *vme) static int vmexit_bogus(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, - struct vm_exit *vme) + struct vm_run *vmrun) { - - assert(vme->inst_length == 0); + assert(vmrun->vm_exit->inst_length == 0); stats.vmexit_bogus++; @@ -745,10 +760,9 @@ vmexit_bogus(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, static int vmexit_reqidle(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, - struct vm_exit *vme) + struct vm_run *vmrun) { - - assert(vme->inst_length == 0); + assert(vmrun->vm_exit->inst_length == 0); stats.vmexit_reqidle++; @@ -757,9 +771,8 @@ vmexit_reqidle(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, static int vmexit_hlt(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, - struct vm_exit *vme __unused) + struct vm_run *vmrun __unused) { - stats.vmexit_hlt++; /* @@ -772,9 +785,8 @@ vmexit_hlt(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, static int vmexit_pause(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, - struct vm_exit *vme __unused) + struct vm_run *vmrun __unused) { - stats.vmexit_pause++; return (VMEXIT_CONTINUE); @@ -782,10 +794,9 @@ vmexit_pause(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, static int vmexit_mtrap(struct vmctx *ctx __unused, struct vcpu *vcpu, - struct vm_exit *vme) + struct vm_run *vmrun) { - - assert(vme->inst_length == 0); + assert(vmrun->vm_exit->inst_length == 0); stats.vmexit_mtrap++; @@ -802,12 +813,15 @@ vmexit_mtrap(struct vmctx *ctx __unused, struct vcpu *vcpu, static int vmexit_inst_emul(struct vmctx *ctx __unused, struct vcpu *vcpu, - struct vm_exit *vme) + struct vm_run *vmrun) { - int err, i, cs_d; + struct vm_exit *vme; struct vie *vie; + int err, i, cs_d; enum vm_cpu_mode mode; + vme = vmrun->vm_exit; + stats.vmexit_inst_emul++; vie = &vme->u.inst_emul.vie; @@ -852,11 +866,14 @@ static pthread_mutex_t resetcpu_mtx = PTHREAD_MUTEX_INITIALIZER; static pthread_cond_t resetcpu_cond = PTHREAD_COND_INITIALIZER; static int -vmexit_suspend(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vme) +vmexit_suspend(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun) { + struct vm_exit *vme; enum vm_suspend_how how; int vcpuid = vcpu_id(vcpu); + vme = vmrun->vm_exit; + how = vme->u.suspended.how; fbsdrun_deletecpu(vcpuid); @@ -894,7 +911,7 @@ vmexit_suspend(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vme) static int vmexit_debug(struct vmctx *ctx __unused, struct vcpu *vcpu, - struct vm_exit *vme __unused) + struct vm_run *vmrun __unused) { #ifdef BHYVE_SNAPSHOT @@ -914,22 +931,27 @@ vmexit_debug(struct vmctx *ctx __unused, struct vcpu *vcpu, static int vmexit_breakpoint(struct vmctx *ctx __unused, struct vcpu *vcpu, - struct vm_exit *vme) + struct vm_run *vmrun) { - - gdb_cpu_breakpoint(vcpu, vme); + gdb_cpu_breakpoint(vcpu, vmrun->vm_exit); return (VMEXIT_CONTINUE); } static int vmexit_ipi(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, - struct vm_exit *vme) + struct vm_run *vmrun) { + struct vm_exit *vme; + cpuset_t *dmask; int error = -1; int i; + + dmask = vmrun->cpuset; + vme = vmrun->vm_exit; + switch (vme->u.ipi.mode) { case APIC_DELMODE_INIT: - CPU_FOREACH_ISSET(i, &vme->u.ipi.dmask) { + CPU_FOREACH_ISSET(i, dmask) { error = vm_suspend_cpu(vcpu_info[i].vcpu); if (error) { warnx("%s: failed to suspend cpu %d\n", @@ -939,7 +961,7 @@ vmexit_ipi(struct vmctx *ctx __unused, struct vcpu *vcpu __unused, } break; case APIC_DELMODE_STARTUP: - CPU_FOREACH_ISSET(i, &vme->u.ipi.dmask) { + CPU_FOREACH_ISSET(i, dmask) { spinup_ap(vcpu_info[i].vcpu, vme->u.ipi.vector << PAGE_SHIFT); } @@ -974,15 +996,20 @@ static void vm_loop(struct vmctx *ctx, struct vcpu *vcpu) { struct vm_exit vme; + struct vm_run vmrun; int error, rc; enum vm_exitcode exitcode; - cpuset_t active_cpus; + cpuset_t active_cpus, dmask; error = vm_active_cpus(ctx, &active_cpus); assert(CPU_ISSET(vcpu_id(vcpu), &active_cpus)); + vmrun.vm_exit = &vme; + vmrun.cpuset = &dmask; + vmrun.cpusetsize = sizeof(dmask); + while (1) { - error = vm_run(vcpu, &vme); + error = vm_run(vcpu, &vmrun); if (error != 0) break; @@ -993,7 +1020,7 @@ vm_loop(struct vmctx *ctx, struct vcpu *vcpu) exit(4); } - rc = (*handler[exitcode])(ctx, vcpu, &vme); + rc = (*handler[exitcode])(ctx, vcpu, &vmrun); switch (rc) { case VMEXIT_CONTINUE: diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h index f45b97e779c8..47f9d5071044 100644 --- a/usr.sbin/bhyve/bhyverun.h +++ b/usr.sbin/bhyve/bhyverun.h @@ -39,7 +39,7 @@ extern uint16_t cpu_cores, cpu_sockets, cpu_threads; struct vcpu; struct vmctx; -struct vm_exit; +struct vm_run; void *paddr_guest2host(struct vmctx *ctx, uintptr_t addr, size_t len); #ifdef BHYVE_SNAPSHOT @@ -48,6 +48,6 @@ uintptr_t paddr_host2guest(struct vmctx *ctx, void *addr); int fbsdrun_virtio_msix(void); -int vmexit_task_switch(struct vmctx *, struct vcpu *, struct vm_exit *); +int vmexit_task_switch(struct vmctx *, struct vcpu *, struct vm_run *); #endif diff --git a/usr.sbin/bhyve/task_switch.c b/usr.sbin/bhyve/task_switch.c index cf4c2356e155..17b311d8f211 100644 --- a/usr.sbin/bhyve/task_switch.c +++ b/usr.sbin/bhyve/task_switch.c @@ -704,7 +704,7 @@ push_errcode(struct vcpu *vcpu, struct vm_guest_paging *paging, } while (0) int -vmexit_task_switch(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vmexit) +vmexit_task_switch(struct vmctx *ctx, struct vcpu *vcpu, struct vm_run *vmrun) { struct seg_desc nt; struct tss32 oldtss, newtss; @@ -712,12 +712,14 @@ vmexit_task_switch(struct vmctx *ctx, struct vcpu *vcpu, struct vm_exit *vmexit) struct vm_guest_paging *paging, sup_paging; struct user_segment_descriptor nt_desc, ot_desc; struct iovec nt_iov[2], ot_iov[2]; + struct vm_exit *vmexit; uint64_t cr0, ot_base; uint32_t eip, ot_lim, access; int error, ext, fault, minlimit, nt_type, ot_type; enum task_switch_reason reason; uint16_t nt_sel, ot_sel; + vmexit = vmrun->vm_exit; task_switch = &vmexit->u.task_switch; nt_sel = task_switch->tsssel; ext = vmexit->u.task_switch.ext;