Date: Thu, 08 Jan 2026 21:58:09 +0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: ed85203fb7a0 - main - vmm: Deduplicate VM and vCPU state management code Message-ID: <69602871.24594.50721050@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=ed85203fb7a0334041db6da07e45ddda4caef13d commit ed85203fb7a0334041db6da07e45ddda4caef13d Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2026-01-08 21:54:06 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-01-08 21:54:06 +0000 vmm: Deduplicate VM and vCPU state management code Now that the machine-independent fields of struct vm and struct vcpu are available in a header, we can move lots of duplicated code into sys/dev/vmm/vmm_vm.c. This change does exactly that. No functional change intended. MFC after: 2 months Sponsored by: The FreeBSD Foundation Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D53585 --- sys/amd64/include/vmm.h | 37 ---- sys/amd64/vmm/io/vioapic.c | 1 + sys/amd64/vmm/io/vlapic.c | 1 + sys/amd64/vmm/vmm.c | 483 +-------------------------------------------- sys/amd64/vmm/vmm_lapic.c | 1 + sys/amd64/vmm/x86.c | 1 + sys/arm64/include/vmm.h | 26 --- sys/arm64/vmm/io/vgic_v3.c | 1 + sys/arm64/vmm/vmm.c | 317 +---------------------------- sys/dev/vmm/vmm_dev.c | 32 --- sys/dev/vmm/vmm_vm.c | 476 ++++++++++++++++++++++++++++++++++++++++++++ sys/dev/vmm/vmm_vm.h | 49 ++++- sys/modules/vmm/Makefile | 3 +- sys/riscv/include/vmm.h | 28 +-- sys/riscv/vmm/vmm.c | 317 +---------------------------- sys/riscv/vmm/vmm_aplic.c | 1 + sys/riscv/vmm/vmm_sbi.c | 2 + sys/riscv/vmm/vmm_vtimer.c | 2 + 18 files changed, 551 insertions(+), 1227 deletions(-) diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h index e1df85aa91b6..baf2cf42ad6c 100644 --- a/sys/amd64/include/vmm.h +++ b/sys/amd64/include/vmm.h @@ -233,19 +233,7 @@ struct vmm_ops { extern const struct vmm_ops vmm_ops_intel; extern const struct vmm_ops vmm_ops_amd; -int vm_create(const char *name, struct vm **retvm); -struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid); -void vm_disable_vcpu_creation(struct vm *vm); -void vm_lock_vcpus(struct vm *vm); -void vm_unlock_vcpus(struct vm *vm); -void vm_destroy(struct vm *vm); -int vm_reinit(struct vm *vm); const char *vm_name(struct vm *vm); -uint16_t vm_get_maxcpus(struct vm *vm); -void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, - uint16_t *threads, uint16_t *maxcpus); -int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, - uint16_t threads, uint16_t maxcpus); int vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa); int vm_unmap_mmio(struct vm *vm, vm_paddr_t gpa, size_t len); @@ -259,7 +247,6 @@ int vm_get_seg_desc(struct vcpu *vcpu, int reg, int vm_set_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *desc); 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); void vm_nmi_clear(struct vcpu *vcpu); @@ -277,9 +264,6 @@ int vm_set_capability(struct vcpu *vcpu, int type, int val); int vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state); int vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state); int vm_apicid2vcpuid(struct vm *vm, int apicid); -int vm_activate_cpu(struct vcpu *vcpu); -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); @@ -292,24 +276,6 @@ int vm_snapshot_req(struct vm *vm, struct vm_snapshot_meta *meta); int vm_restore_time(struct vm *vm); #ifdef _SYS__CPUSET_H_ -/* - * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'. - * The rendezvous 'func(arg)' is not allowed to do anything that will - * cause the thread to be put to sleep. - * - * The caller cannot hold any locks when initiating the rendezvous. - * - * The implementation of this API may cause vcpus other than those specified - * by 'dest' to be stalled. The caller should not rely on any vcpus making - * forward progress when the rendezvous is in progress. - */ -typedef void (*vm_rendezvous_func_t)(struct vcpu *vcpu, void *arg); -int vm_smp_rendezvous(struct vcpu *vcpu, 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); -cpuset_t vm_suspended_cpus(struct vm *vm); cpuset_t vm_start_cpus(struct vm *vm, const cpuset_t *tostart); void vm_await_start(struct vm *vm, const cpuset_t *waiting); #endif /* _SYS__CPUSET_H_ */ @@ -341,8 +307,6 @@ vcpu_reqidle(struct vm_eventinfo *info) return (*info->iptr); } -int vcpu_debugged(struct vcpu *vcpu); - /* * Return true if device indicated by bus/slot/func is supposed to be a * pci passthrough device. @@ -354,7 +318,6 @@ bool vmm_is_pptdev(int bus, int slot, int func); void *vm_iommu_domain(struct vm *vm); void *vcpu_stats(struct vcpu *vcpu); -void vcpu_notify_event(struct vcpu *vcpu); void vcpu_notify_lapic(struct vcpu *vcpu); struct vm_mem *vm_mem(struct vm *vm); struct vatpic *vm_atpic(struct vm *vm); diff --git a/sys/amd64/vmm/io/vioapic.c b/sys/amd64/vmm/io/vioapic.c index 7df6193d6dc0..a3956785d049 100644 --- a/sys/amd64/vmm/io/vioapic.c +++ b/sys/amd64/vmm/io/vioapic.c @@ -43,6 +43,7 @@ #include <machine/vmm_snapshot.h> #include <dev/vmm/vmm_ktr.h> +#include <dev/vmm/vmm_vm.h> #include "vmm_lapic.h" #include "vlapic.h" diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c index afd5045de574..6849ef7aa589 100644 --- a/sys/amd64/vmm/io/vlapic.c +++ b/sys/amd64/vmm/io/vlapic.c @@ -47,6 +47,7 @@ #include <machine/vmm_snapshot.h> #include <dev/vmm/vmm_ktr.h> +#include <dev/vmm/vmm_vm.h> #include "vmm_lapic.h" #include "vmm_stat.h" diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c index 4b93e020f8dc..b0712c3eb6ac 100644 --- a/sys/amd64/vmm/vmm.c +++ b/sys/amd64/vmm/vmm.c @@ -161,8 +161,7 @@ static MALLOC_DEFINE(M_VM, "vm", "vm"); /* statistics */ static VMM_STAT(VCPU_TOTAL_RUNTIME, "vcpu total runtime"); -SYSCTL_NODE(_hw, OID_AUTO, vmm, CTLFLAG_RW | CTLFLAG_MPSAFE, NULL, - NULL); +SYSCTL_DECL(_hw_vmm); /* * Halt the guest if all vcpus are executing a HLT instruction with @@ -173,10 +172,6 @@ SYSCTL_INT(_hw_vmm, OID_AUTO, halt_detection, CTLFLAG_RDTUN, &halt_detection_enabled, 0, "Halt VM if all vcpus execute HLT with interrupts disabled"); -static int vmm_ipinum; -SYSCTL_INT(_hw_vmm, OID_AUTO, ipinum, CTLFLAG_RD, &vmm_ipinum, 0, - "IPI vector used for vcpu notifications"); - static int trace_guest_exceptions; SYSCTL_INT(_hw_vmm, OID_AUTO, trace_guest_exceptions, CTLFLAG_RDTUN, &trace_guest_exceptions, 0, @@ -186,8 +181,6 @@ static int trap_wbinvd; SYSCTL_INT(_hw_vmm, OID_AUTO, trap_wbinvd, CTLFLAG_RDTUN, &trap_wbinvd, 0, "WBINVD triggers a VM-exit"); -static void vcpu_notify_event_locked(struct vcpu *vcpu); - /* global statistics */ VMM_STAT(VCPU_MIGRATIONS, "vcpu migration across host cpus"); VMM_STAT(VMEXIT_COUNT, "total number of vm exits"); @@ -284,7 +277,6 @@ vcpu_init(struct vcpu *vcpu) int vcpu_trace_exceptions(struct vcpu *vcpu) { - return (trace_guest_exceptions); } @@ -364,14 +356,6 @@ vm_init(struct vm *vm, bool create) } } -void -vm_disable_vcpu_creation(struct vm *vm) -{ - sx_xlock(&vm->vcpus_init_lock); - vm->dying = true; - sx_xunlock(&vm->vcpus_init_lock); -} - struct vcpu * vm_alloc_vcpu(struct vm *vm, int vcpuid) { @@ -402,18 +386,6 @@ vm_alloc_vcpu(struct vm *vm, int vcpuid) return (vcpu); } -void -vm_lock_vcpus(struct vm *vm) -{ - sx_xlock(&vm->vcpus_init_lock); -} - -void -vm_unlock_vcpus(struct vm *vm) -{ - sx_unlock(&vm->vcpus_init_lock); -} - int vm_create(const char *name, struct vm **retvm) { @@ -443,35 +415,6 @@ vm_create(const char *name, struct vm **retvm) return (0); } -void -vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, - uint16_t *threads, uint16_t *maxcpus) -{ - *sockets = vm->sockets; - *cores = vm->cores; - *threads = vm->threads; - *maxcpus = vm->maxcpus; -} - -uint16_t -vm_get_maxcpus(struct vm *vm) -{ - return (vm->maxcpus); -} - -int -vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, - uint16_t threads, uint16_t maxcpus __unused) -{ - /* Ignore maxcpus. */ - if ((sockets * cores * threads) > vm->maxcpus) - return (EINVAL); - vm->sockets = sockets; - vm->cores = cores; - vm->threads = threads; - return(0); -} - static void vm_cleanup(struct vm *vm, bool destroy) { @@ -520,23 +463,11 @@ vm_destroy(struct vm *vm) free(vm, M_VM); } -int -vm_reinit(struct vm *vm) +void +vm_reset(struct vm *vm) { - int error; - - /* - * A virtual machine can be reset only if all vcpus are suspended. - */ - if (CPU_CMP(&vm->suspended_cpus, &vm->active_cpus) == 0) { - vm_cleanup(vm, false); - vm_init(vm, false); - error = 0; - } else { - error = EBUSY; - } - - return (error); + vm_cleanup(vm, false); + vm_init(vm, false); } const char * @@ -810,210 +741,6 @@ save_guest_fpustate(struct vcpu *vcpu) static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle"); -/* - * Invoke the rendezvous function on the specified vcpu if applicable. Return - * true if the rendezvous is finished, false otherwise. - */ -static bool -vm_rendezvous(struct vcpu *vcpu) -{ - struct vm *vm = vcpu->vm; - int vcpuid; - - mtx_assert(&vcpu->vm->rendezvous_mtx, MA_OWNED); - KASSERT(vcpu->vm->rendezvous_func != NULL, - ("vm_rendezvous: no rendezvous pending")); - - /* 'rendezvous_req_cpus' must be a subset of 'active_cpus' */ - CPU_AND(&vm->rendezvous_req_cpus, &vm->rendezvous_req_cpus, - &vm->active_cpus); - - vcpuid = vcpu->vcpuid; - if (CPU_ISSET(vcpuid, &vm->rendezvous_req_cpus) && - !CPU_ISSET(vcpuid, &vm->rendezvous_done_cpus)) { - VMM_CTR0(vcpu, "Calling rendezvous func"); - (*vm->rendezvous_func)(vcpu, vm->rendezvous_arg); - CPU_SET(vcpuid, &vm->rendezvous_done_cpus); - } - if (CPU_CMP(&vm->rendezvous_req_cpus, - &vm->rendezvous_done_cpus) == 0) { - VMM_CTR0(vcpu, "Rendezvous completed"); - CPU_ZERO(&vm->rendezvous_req_cpus); - vm->rendezvous_func = NULL; - wakeup(&vm->rendezvous_func); - return (true); - } - return (false); -} - -static void -vcpu_wait_idle(struct vcpu *vcpu) -{ - KASSERT(vcpu->state != VCPU_IDLE, ("vcpu already idle")); - - vcpu->reqidle = 1; - vcpu_notify_event_locked(vcpu); - VMM_CTR1(vcpu, "vcpu state change from %s to " - "idle requested", vcpu_state2str(vcpu->state)); - msleep_spin(&vcpu->state, &vcpu->mtx, "vmstat", hz); -} - -static int -vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate, - bool from_idle) -{ - int error; - - vcpu_assert_locked(vcpu); - - /* - * State transitions from the vmmdev_ioctl() must always begin from - * the VCPU_IDLE state. This guarantees that there is only a single - * ioctl() operating on a vcpu at any point. - */ - if (from_idle) { - while (vcpu->state != VCPU_IDLE) - vcpu_wait_idle(vcpu); - } else { - KASSERT(vcpu->state != VCPU_IDLE, ("invalid transition from " - "vcpu idle state")); - } - - if (vcpu->state == VCPU_RUNNING) { - KASSERT(vcpu->hostcpu == curcpu, ("curcpu %d and hostcpu %d " - "mismatch for running vcpu", curcpu, vcpu->hostcpu)); - } else { - KASSERT(vcpu->hostcpu == NOCPU, ("Invalid hostcpu %d for a " - "vcpu that is not running", vcpu->hostcpu)); - } - - /* - * The following state transitions are allowed: - * IDLE -> FROZEN -> IDLE - * FROZEN -> RUNNING -> FROZEN - * FROZEN -> SLEEPING -> FROZEN - */ - switch (vcpu->state) { - case VCPU_IDLE: - case VCPU_RUNNING: - case VCPU_SLEEPING: - error = (newstate != VCPU_FROZEN); - break; - case VCPU_FROZEN: - error = (newstate == VCPU_FROZEN); - break; - default: - error = 1; - break; - } - - if (error) - return (EBUSY); - - VMM_CTR2(vcpu, "vcpu state changed from %s to %s", - vcpu_state2str(vcpu->state), vcpu_state2str(newstate)); - - vcpu->state = newstate; - if (newstate == VCPU_RUNNING) - vcpu->hostcpu = curcpu; - else - vcpu->hostcpu = NOCPU; - - if (newstate == VCPU_IDLE) - wakeup(&vcpu->state); - - return (0); -} - -/* - * Try to lock all of the vCPUs in the VM while taking care to avoid deadlocks - * with vm_smp_rendezvous(). - * - * The complexity here suggests that the rendezvous mechanism needs a rethink. - */ -int -vcpu_set_state_all(struct vm *vm, enum vcpu_state newstate) -{ - cpuset_t locked; - struct vcpu *vcpu; - int error, i; - uint16_t maxcpus; - - KASSERT(newstate != VCPU_IDLE, - ("vcpu_set_state_all: invalid target state %d", newstate)); - - error = 0; - CPU_ZERO(&locked); - maxcpus = vm->maxcpus; - - mtx_lock(&vm->rendezvous_mtx); -restart: - if (vm->rendezvous_func != NULL) { - /* - * If we have a pending rendezvous, then the initiator may be - * blocked waiting for other vCPUs to execute the callback. The - * current thread may be a vCPU thread so we must not block - * waiting for the initiator, otherwise we get a deadlock. - * Thus, execute the callback on behalf of any idle vCPUs. - */ - for (i = 0; i < maxcpus; i++) { - vcpu = vm_vcpu(vm, i); - if (vcpu == NULL) - continue; - vcpu_lock(vcpu); - if (vcpu->state == VCPU_IDLE) { - (void)vcpu_set_state_locked(vcpu, VCPU_FROZEN, - true); - CPU_SET(i, &locked); - } - if (CPU_ISSET(i, &locked)) { - /* - * We can safely execute the callback on this - * vCPU's behalf. - */ - vcpu_unlock(vcpu); - (void)vm_rendezvous(vcpu); - vcpu_lock(vcpu); - } - vcpu_unlock(vcpu); - } - } - - /* - * Now wait for remaining vCPUs to become idle. This may include the - * initiator of a rendezvous that is currently blocked on the rendezvous - * mutex. - */ - CPU_FOREACH_ISCLR(i, &locked) { - if (i >= maxcpus) - break; - vcpu = vm_vcpu(vm, i); - if (vcpu == NULL) - continue; - vcpu_lock(vcpu); - while (vcpu->state != VCPU_IDLE) { - mtx_unlock(&vm->rendezvous_mtx); - vcpu_wait_idle(vcpu); - vcpu_unlock(vcpu); - mtx_lock(&vm->rendezvous_mtx); - if (vm->rendezvous_func != NULL) - goto restart; - vcpu_lock(vcpu); - } - error = vcpu_set_state_locked(vcpu, newstate, true); - vcpu_unlock(vcpu); - if (error != 0) { - /* Roll back state changes. */ - CPU_FOREACH_ISSET(i, &locked) - (void)vcpu_set_state(vcpu, VCPU_IDLE, false); - break; - } - CPU_SET(i, &locked); - } - mtx_unlock(&vm->rendezvous_mtx); - return (error); -} - static void vcpu_require_state(struct vcpu *vcpu, enum vcpu_state newstate) { @@ -1032,37 +759,6 @@ vcpu_require_state_locked(struct vcpu *vcpu, enum vcpu_state newstate) panic("Error %d setting state to %d", error, newstate); } -static int -vm_handle_rendezvous(struct vcpu *vcpu) -{ - struct vm *vm; - struct thread *td; - - td = curthread; - vm = vcpu->vm; - - mtx_lock(&vm->rendezvous_mtx); - while (vm->rendezvous_func != NULL) { - if (vm_rendezvous(vcpu)) - break; - - VMM_CTR0(vcpu, "Wait for rendezvous completion"); - mtx_sleep(&vm->rendezvous_func, &vm->rendezvous_mtx, 0, - "vmrndv", hz); - if (td_ast_pending(td, TDA_SUSPEND)) { - int error; - - 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); -} - /* * Emulate a guest 'hlt' by sleeping until the vcpu is ready to run. */ @@ -1386,33 +1082,6 @@ vm_handle_db(struct vcpu *vcpu, struct vm_exit *vme, bool *retu) return (0); } -int -vm_suspend(struct vm *vm, enum vm_suspend_how how) -{ - int i; - - if (how <= VM_SUSPEND_NONE || how >= VM_SUSPEND_LAST) - return (EINVAL); - - if (atomic_cmpset_int(&vm->suspend, 0, how) == 0) { - VM_CTR2(vm, "virtual machine already suspended %d/%d", - vm->suspend, how); - return (EALREADY); - } - - VM_CTR1(vm, "virtual machine successfully suspended %d", how); - - /* - * Notify all active vcpus that they are now suspended. - */ - for (i = 0; i < vm->maxcpus; i++) { - if (CPU_ISSET(i, &vm->active_cpus)) - vcpu_notify_event(vm_vcpu(vm, i)); - } - - return (0); -} - void vm_exit_suspended(struct vcpu *vcpu, uint64_t rip) { @@ -2039,107 +1708,6 @@ vm_iommu_domain(struct vm *vm) return (vm->iommu); } -int -vcpu_set_state(struct vcpu *vcpu, enum vcpu_state newstate, bool from_idle) -{ - int error; - - vcpu_lock(vcpu); - error = vcpu_set_state_locked(vcpu, newstate, from_idle); - vcpu_unlock(vcpu); - - return (error); -} - -enum vcpu_state -vcpu_get_state(struct vcpu *vcpu, int *hostcpu) -{ - enum vcpu_state state; - - vcpu_lock(vcpu); - state = vcpu->state; - if (hostcpu != NULL) - *hostcpu = vcpu->hostcpu; - vcpu_unlock(vcpu); - - return (state); -} - -int -vm_activate_cpu(struct vcpu *vcpu) -{ - struct vm *vm = vcpu->vm; - - if (CPU_ISSET(vcpu->vcpuid, &vm->active_cpus)) - return (EBUSY); - - VMM_CTR0(vcpu, "activated"); - CPU_SET_ATOMIC(vcpu->vcpuid, &vm->active_cpus); - return (0); -} - -int -vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu) -{ - if (vcpu == NULL) { - vm->debug_cpus = vm->active_cpus; - for (int i = 0; i < vm->maxcpus; i++) { - if (CPU_ISSET(i, &vm->active_cpus)) - vcpu_notify_event(vm_vcpu(vm, i)); - } - } else { - if (!CPU_ISSET(vcpu->vcpuid, &vm->active_cpus)) - return (EINVAL); - - CPU_SET_ATOMIC(vcpu->vcpuid, &vm->debug_cpus); - vcpu_notify_event(vcpu); - } - return (0); -} - -int -vm_resume_cpu(struct vm *vm, struct vcpu *vcpu) -{ - - if (vcpu == NULL) { - CPU_ZERO(&vm->debug_cpus); - } else { - if (!CPU_ISSET(vcpu->vcpuid, &vm->debug_cpus)) - return (EINVAL); - - CPU_CLR_ATOMIC(vcpu->vcpuid, &vm->debug_cpus); - } - return (0); -} - -int -vcpu_debugged(struct vcpu *vcpu) -{ - - return (CPU_ISSET(vcpu->vcpuid, &vcpu->vm->debug_cpus)); -} - -cpuset_t -vm_active_cpus(struct vm *vm) -{ - - return (vm->active_cpus); -} - -cpuset_t -vm_debug_cpus(struct vm *vm) -{ - - return (vm->debug_cpus); -} - -cpuset_t -vm_suspended_cpus(struct vm *vm) -{ - - return (vm->suspended_cpus); -} - /* * Returns the subset of vCPUs in tostart that are awaiting startup. * These vCPUs are also marked as no longer awaiting startup. @@ -2192,47 +1760,6 @@ vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state) return (0); } -/* - * This function is called to ensure that a vcpu "sees" a pending event - * as soon as possible: - * - If the vcpu thread is sleeping then it is woken up. - * - If the vcpu is running on a different host_cpu then an IPI will be directed - * to the host_cpu to cause the vcpu to trap into the hypervisor. - */ -static void -vcpu_notify_event_locked(struct vcpu *vcpu) -{ - int hostcpu; - - hostcpu = vcpu->hostcpu; - if (vcpu->state == VCPU_RUNNING) { - KASSERT(hostcpu != NOCPU, ("vcpu running on invalid hostcpu")); - if (hostcpu != curcpu) { - ipi_cpu(hostcpu, vmm_ipinum); - } else { - /* - * If the 'vcpu' is running on 'curcpu' then it must - * be sending a notification to itself (e.g. SELF_IPI). - * The pending event will be picked up when the vcpu - * transitions back to guest context. - */ - } - } else { - KASSERT(hostcpu == NOCPU, ("vcpu state %d not consistent " - "with hostcpu %d", vcpu->state, hostcpu)); - if (vcpu->state == VCPU_SLEEPING) - wakeup_one(vcpu); - } -} - -void -vcpu_notify_event(struct vcpu *vcpu) -{ - vcpu_lock(vcpu); - vcpu_notify_event_locked(vcpu); - vcpu_unlock(vcpu); -} - void vcpu_notify_lapic(struct vcpu *vcpu) { diff --git a/sys/amd64/vmm/vmm_lapic.c b/sys/amd64/vmm/vmm_lapic.c index 63bdee69bb59..44bae5da31e5 100644 --- a/sys/amd64/vmm/vmm_lapic.c +++ b/sys/amd64/vmm/vmm_lapic.c @@ -34,6 +34,7 @@ #include <x86/apicreg.h> #include <dev/vmm/vmm_ktr.h> +#include <dev/vmm/vmm_vm.h> #include <machine/vmm.h> #include "vmm_lapic.h" diff --git a/sys/amd64/vmm/x86.c b/sys/amd64/vmm/x86.c index 2e2224595ab4..f32107124eb8 100644 --- a/sys/amd64/vmm/x86.c +++ b/sys/amd64/vmm/x86.c @@ -39,6 +39,7 @@ #include <machine/vmm.h> #include <dev/vmm/vmm_ktr.h> +#include <dev/vmm/vmm_vm.h> #include "vmm_host.h" #include "vmm_util.h" diff --git a/sys/arm64/include/vmm.h b/sys/arm64/include/vmm.h index 16292dd42f28..14b4d1be10a3 100644 --- a/sys/arm64/include/vmm.h +++ b/sys/arm64/include/vmm.h @@ -181,24 +181,11 @@ DECLARE_VMMOPS_FUNC(int, restore_tsc, (void *vcpui, uint64_t now)); #endif #endif -int vm_create(const char *name, struct vm **retvm); -struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid); -void vm_disable_vcpu_creation(struct vm *vm); -void vm_lock_vcpus(struct vm *vm); -void vm_unlock_vcpus(struct vm *vm); -void vm_destroy(struct vm *vm); -int vm_reinit(struct vm *vm); const char *vm_name(struct vm *vm); -uint16_t vm_get_maxcpus(struct vm *vm); -void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, - uint16_t *threads, uint16_t *maxcpus); -int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, - uint16_t threads, uint16_t maxcpus); int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval); int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val); int vm_run(struct vcpu *vcpu); -int vm_suspend(struct vm *vm, enum vm_suspend_how how); void* vm_get_cookie(struct vm *vm); int vcpu_vcpuid(struct vcpu *vcpu); void *vcpu_get_cookie(struct vcpu *vcpu); @@ -206,9 +193,6 @@ struct vm *vcpu_vm(struct vcpu *vcpu); struct vcpu *vm_vcpu(struct vm *vm, int cpu); int vm_get_capability(struct vcpu *vcpu, int type, int *val); int vm_set_capability(struct vcpu *vcpu, int type, int val); -int vm_activate_cpu(struct vcpu *vcpu); -int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); -int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); int vm_inject_exception(struct vcpu *vcpu, uint64_t esr, uint64_t far); int vm_attach_vgic(struct vm *vm, struct vm_vgic_descr *descr); int vm_assert_irq(struct vm *vm, uint32_t irq); @@ -218,13 +202,8 @@ int vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot, struct vm_exit *vm_exitinfo(struct vcpu *vcpu); void vm_exit_suspended(struct vcpu *vcpu, uint64_t pc); void vm_exit_debug(struct vcpu *vcpu, uint64_t pc); -void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t pc); void vm_exit_astpending(struct vcpu *vcpu, uint64_t pc); -cpuset_t vm_active_cpus(struct vm *vm); -cpuset_t vm_debug_cpus(struct vm *vm); -cpuset_t vm_suspended_cpus(struct vm *vm); - static __inline int vcpu_rendezvous_pending(struct vm_eventinfo *info) { @@ -239,14 +218,9 @@ vcpu_suspended(struct vm_eventinfo *info) return (*info->sptr); } -int vcpu_debugged(struct vcpu *vcpu); - void *vcpu_stats(struct vcpu *vcpu); -void vcpu_notify_event(struct vcpu *vcpu); struct vm_mem *vm_mem(struct vm *vm); -enum vm_reg_name vm_segment_name(int seg_encoding); - struct vm_copyinfo { uint64_t gpa; size_t len; diff --git a/sys/arm64/vmm/io/vgic_v3.c b/sys/arm64/vmm/io/vgic_v3.c index e4f7bb2af3ee..22cd06b09d7d 100644 --- a/sys/arm64/vmm/io/vgic_v3.c +++ b/sys/arm64/vmm/io/vgic_v3.c @@ -69,6 +69,7 @@ #include <arm64/vmm/vmm_handlers.h> #include <dev/vmm/vmm_dev.h> +#include <dev/vmm/vmm_vm.h> #include "vgic.h" #include "vgic_v3.h" diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c index 75f7f2fcaaf7..92500aa9febc 100644 --- a/sys/arm64/vmm/vmm.c +++ b/sys/arm64/vmm/vmm.c @@ -40,7 +40,6 @@ #include <sys/rwlock.h> #include <sys/sched.h> #include <sys/smp.h> -#include <sys/sysctl.h> #include <vm/vm.h> #include <vm/vm_object.h> @@ -74,20 +73,11 @@ #include "io/vgic.h" #include "io/vtimer.h" -static int vm_handle_wfi(struct vcpu *vcpu, - struct vm_exit *vme, bool *retu); - static MALLOC_DEFINE(M_VMM, "vmm", "vmm"); /* statistics */ static VMM_STAT(VCPU_TOTAL_RUNTIME, "vcpu total runtime"); -SYSCTL_NODE(_hw, OID_AUTO, vmm, CTLFLAG_RW, NULL, NULL); - -static int vmm_ipinum; -SYSCTL_INT(_hw_vmm, OID_AUTO, ipinum, CTLFLAG_RD, &vmm_ipinum, 0, - "IPI vector used for vcpu notifications"); - struct vmm_regs { uint64_t id_aa64afr0; uint64_t id_aa64afr1; @@ -142,8 +132,6 @@ static const struct vmm_regs vmm_arch_regs_masks = { /* Host registers masked by vmm_arch_regs_masks. */ static struct vmm_regs vmm_arch_regs; -static void vcpu_notify_event_locked(struct vcpu *vcpu); - /* global statistics */ VMM_STAT(VMEXIT_COUNT, "total number of vm exits"); VMM_STAT(VMEXIT_UNKNOWN, "number of vmexits for the unknown exception"); @@ -294,14 +282,6 @@ vm_init(struct vm *vm, bool create) } } -void -vm_disable_vcpu_creation(struct vm *vm) -{ - sx_xlock(&vm->vcpus_init_lock); - vm->dying = true; - sx_xunlock(&vm->vcpus_init_lock); -} - struct vcpu * vm_alloc_vcpu(struct vm *vm, int vcpuid) { @@ -338,18 +318,6 @@ vm_alloc_vcpu(struct vm *vm, int vcpuid) return (vcpu); } -void -vm_lock_vcpus(struct vm *vm) -{ - sx_xlock(&vm->vcpus_init_lock); -} - -void -vm_unlock_vcpus(struct vm *vm) -{ - sx_unlock(&vm->vcpus_init_lock); -} - int vm_create(const char *name, struct vm **retvm) { @@ -363,6 +331,7 @@ vm_create(const char *name, struct vm **retvm) return (error); } strcpy(vm->name, name); + mtx_init(&vm->rendezvous_mtx, "vm rendezvous lock", 0, MTX_DEF); sx_init(&vm->vcpus_init_lock, "vm vcpus"); vm->sockets = 1; @@ -379,35 +348,6 @@ vm_create(const char *name, struct vm **retvm) return (0); } -void -vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, - uint16_t *threads, uint16_t *maxcpus) -{ - *sockets = vm->sockets; - *cores = vm->cores; - *threads = vm->threads; - *maxcpus = vm->maxcpus; -} - -uint16_t -vm_get_maxcpus(struct vm *vm) -{ - return (vm->maxcpus); -} - -int -vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, - uint16_t threads, uint16_t maxcpus) -{ - /* Ignore maxcpus. */ - if ((sockets * cores * threads) > vm->maxcpus) - return (EINVAL); - vm->sockets = sockets; - vm->cores = cores; - vm->threads = threads; - return(0); -} - static void vm_cleanup(struct vm *vm, bool destroy) { @@ -452,23 +392,11 @@ vm_destroy(struct vm *vm) free(vm, M_VMM); } -int -vm_reinit(struct vm *vm) +void +vm_reset(struct vm *vm) { - int error; - - /* - * A virtual machine can be reset only if all vcpus are suspended. - */ - if (CPU_CMP(&vm->suspended_cpus, &vm->active_cpus) == 0) { - vm_cleanup(vm, false); - vm_init(vm, false); - error = 0; - } else { - error = EBUSY; - } - - return (error); + vm_cleanup(vm, false); + vm_init(vm, false); } const char * @@ -765,33 +693,6 @@ out_user: return (0); } -int *** 1405 LINES SKIPPED ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69602871.24594.50721050>
