git: a6411f6b7df4 - main - vmm: Consolidate vm and vcpu definitions
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 08 Jan 2026 21:58:07 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=a6411f6b7df46edc7167a7844ed443db7a91a031
commit a6411f6b7df46edc7167a7844ed443db7a91a031
Author: Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2026-01-08 21:53:31 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-01-08 21:53:31 +0000
vmm: Consolidate vm and vcpu definitions
There is quite a lot of duplication of code between amd64, arm64 and
riscv with respect to VM and vCPU state management. This is a bit
tricky to resolve since struct vm and struct vcpu are private to vmm.c
and both structures contain a mix of machine-dependent and
machine-independent fields.
To allow deduplication without also introducing a lot of churn, follow
the approach of struct pcpu and 1) lift the definitions of those
structures into a new header, sys/dev/vmm/vmm_vm.h, and 2) define
machine-dependent macros, VMM_VM_MD_FIELDS and VMM_VCPU_MD_FIELDS which
lay out the machine-dependent fields.
One disadvantage of this approach is that the two structures are no
longer private to vmm.c, but I think this is acceptable.
No functional change intended. A follow-up change will move a good deal
of machine/vmm/vmm.c into sys/dev/vmm/vmm_vm.c.
MFC after: 2 months
Sponsored by: The FreeBSD Foundation
Sponsored by: Klara, Inc.
Differential Revision: https://reviews.freebsd.org/D53584
---
sys/amd64/include/vmm.h | 55 +++++++-------
sys/amd64/vmm/amd/svm.c | 2 +-
sys/amd64/vmm/intel/vmx.c | 2 +-
sys/amd64/vmm/io/vhpet.c | 3 +-
sys/amd64/vmm/vmm.c | 83 +--------------------
sys/arm64/include/vmm.h | 71 +++++++++---------
sys/arm64/include/vmm_instruction_emul.h | 8 ++
sys/arm64/vmm/io/vgic_v3.c | 3 +-
sys/arm64/vmm/vmm.c | 67 +----------------
sys/arm64/vmm/vmm_arm64.c | 2 +-
sys/dev/vmm/vmm_dev.c | 1 +
sys/dev/vmm/vmm_mem.c | 1 +
sys/dev/vmm/vmm_mem.h | 3 +
sys/dev/vmm/vmm_vm.h | 121 +++++++++++++++++++++++++++++++
sys/riscv/include/vmm.h | 44 +++++------
sys/riscv/include/vmm_instruction_emul.h | 6 ++
sys/riscv/vmm/vmm.c | 56 +-------------
sys/riscv/vmm/vmm_aplic.c | 3 +-
sys/riscv/vmm/vmm_fence.c | 8 +-
sys/riscv/vmm/vmm_riscv.c | 2 +-
20 files changed, 239 insertions(+), 302 deletions(-)
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index 5cf1ae2d769c..e1df85aa91b6 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -123,6 +123,33 @@ enum x2apic_state {
#define VM_INTINFO_SWINTR (4 << 8)
#ifdef _KERNEL
+#define VMM_VCPU_MD_FIELDS \
+ struct vlapic *vlapic; /* (i) APIC device model */ \
+ enum x2apic_state x2apic_state; /* (i) APIC mode */ \
+ uint64_t exitintinfo; /* (i) events pending at VM exit */ \
+ int nmi_pending; /* (i) NMI pending */ \
+ int extint_pending; /* (i) INTR pending */ \
+ int exception_pending; /* (i) exception pending */ \
+ int exc_vector; /* (x) exception collateral */ \
+ int exc_errcode_valid; \
+ uint32_t exc_errcode; \
+ struct savefpu *guestfpu; /* (a,i) guest fpu state */ \
+ uint64_t guest_xcr0; /* (i) guest %xcr0 register */ \
+ 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 */
+
+#define VMM_VM_MD_FIELDS \
+ cpuset_t startup_cpus; /* (i) [r] waiting for startup */ \
+ void *iommu; /* (x) iommu-specific data */ \
+ struct vioapic *vioapic; /* (i) virtual ioapic */ \
+ struct vatpic *vatpic; /* (i) virtual atpic */ \
+ struct vatpit *vatpit; /* (i) virtual atpit */ \
+ struct vpmtmr *vpmtmr; /* (i) virtual ACPI PM timer */ \
+ struct vrtc *vrtc; /* (o) virtual RTC */ \
+ struct vhpet *vhpet /* (i) virtual HPET */
+
struct vm;
struct vm_exception;
struct vm_mem;
@@ -326,34 +353,6 @@ bool vmm_is_pptdev(int bus, int slot, int func);
void *vm_iommu_domain(struct vm *vm);
-enum vcpu_state {
- VCPU_IDLE,
- VCPU_FROZEN,
- VCPU_RUNNING,
- VCPU_SLEEPING,
-};
-
-int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
-int vcpu_set_state_all(struct vm *vm, enum vcpu_state state);
-enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
-
-static int __inline
-vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
-{
- return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
-}
-
-#ifdef _SYS_PROC_H_
-static int __inline
-vcpu_should_yield(struct vcpu *vcpu)
-{
- struct thread *td;
-
- td = curthread;
- return (td->td_ast != 0 || td->td_owepreempt != 0);
-}
-#endif
-
void *vcpu_stats(struct vcpu *vcpu);
void vcpu_notify_event(struct vcpu *vcpu);
void vcpu_notify_lapic(struct vcpu *vcpu);
diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c
index 2fe6a5bc3584..37c950cfbc5f 100644
--- a/sys/amd64/vmm/amd/svm.c
+++ b/sys/amd64/vmm/amd/svm.c
@@ -50,12 +50,12 @@
#include <machine/specialreg.h>
#include <machine/smp.h>
#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
#include <machine/vmm_instruction_emul.h>
#include <machine/vmm_snapshot.h>
#include <dev/vmm/vmm_ktr.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
#include "vmm_lapic.h"
#include "vmm_stat.h"
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 4189c1214b40..7a2d0de6beff 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -53,13 +53,13 @@
#include <machine/vmparam.h>
#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
#include <machine/vmm_instruction_emul.h>
#include <machine/vmm_snapshot.h>
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_ktr.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
#include "vmm_lapic.h"
#include "vmm_host.h"
diff --git a/sys/amd64/vmm/io/vhpet.c b/sys/amd64/vmm/io/vhpet.c
index 88063f2952e5..cdeb5e059128 100644
--- a/sys/amd64/vmm/io/vhpet.c
+++ b/sys/amd64/vmm/io/vhpet.c
@@ -38,10 +38,11 @@
#include <sys/systm.h>
#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
#include <machine/vmm_snapshot.h>
#include <dev/acpica/acpi_hpet.h>
+
+#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_ktr.h>
#include "vmm_lapic.h"
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index f3f9717129c9..4b93e020f8dc 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -71,6 +71,7 @@
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_ktr.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
#include "vmm_ioport.h"
#include "vmm_host.h"
@@ -91,88 +92,6 @@
struct vlapic;
-/*
- * Initialization:
- * (a) allocated when vcpu is created
- * (i) initialized when vcpu is created and when it is reinitialized
- * (o) initialized the first time the vcpu is created
- * (x) initialized before use
- */
-struct vcpu {
- struct mtx mtx; /* (o) protects 'state' and 'hostcpu' */
- enum vcpu_state state; /* (o) vcpu state */
- int vcpuid; /* (o) */
- int hostcpu; /* (o) vcpu's host cpu */
- int reqidle; /* (i) request vcpu to idle */
- struct vm *vm; /* (o) */
- void *cookie; /* (i) cpu-specific data */
- struct vlapic *vlapic; /* (i) APIC device model */
- enum x2apic_state x2apic_state; /* (i) APIC mode */
- uint64_t exitintinfo; /* (i) events pending at VM exit */
- int nmi_pending; /* (i) NMI pending */
- int extint_pending; /* (i) INTR pending */
- int exception_pending; /* (i) exception pending */
- int exc_vector; /* (x) exception collateral */
- int exc_errcode_valid;
- uint32_t exc_errcode;
- struct savefpu *guestfpu; /* (a,i) guest fpu state */
- 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 */
-};
-
-#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
-#define vcpu_lock_destroy(v) mtx_destroy(&((v)->mtx))
-#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx))
-#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx))
-#define vcpu_assert_locked(v) mtx_assert(&((v)->mtx), MA_OWNED)
-
-/*
- * Initialization:
- * (o) initialized the first time the VM is created
- * (i) initialized when VM is created and when it is reinitialized
- * (x) initialized before use
- *
- * Locking:
- * [m] mem_segs_lock
- * [r] rendezvous_mtx
- * [v] reads require one frozen vcpu, writes require freezing all vcpus
- */
-struct vm {
- void *cookie; /* (i) cpu-specific data */
- void *iommu; /* (x) iommu-specific data */
- struct vhpet *vhpet; /* (i) virtual HPET */
- struct vioapic *vioapic; /* (i) virtual ioapic */
- struct vatpic *vatpic; /* (i) virtual atpic */
- struct vatpit *vatpit; /* (i) virtual atpit */
- struct vpmtmr *vpmtmr; /* (i) virtual ACPI PM timer */
- struct vrtc *vrtc; /* (o) virtual RTC */
- volatile cpuset_t active_cpus; /* (i) active vcpus */
- volatile cpuset_t debug_cpus; /* (i) vcpus stopped for debug */
- cpuset_t startup_cpus; /* (i) [r] waiting for startup */
- int suspend; /* (i) stop VM execution */
- bool dying; /* (o) is dying */
- volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */
- volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */
- cpuset_t rendezvous_req_cpus; /* (x) [r] rendezvous requested */
- cpuset_t rendezvous_done_cpus; /* (x) [r] rendezvous finished */
- void *rendezvous_arg; /* (x) [r] rendezvous func/arg */
- vm_rendezvous_func_t rendezvous_func;
- struct mtx rendezvous_mtx; /* (o) rendezvous lock */
- struct vm_mem mem; /* (i) [m+v] guest memory */
- char name[VM_MAX_NAMELEN+1]; /* (o) virtual machine name */
- struct vcpu **vcpu; /* (o) guest vcpus */
- /* The following describe the vm cpu topology */
- uint16_t sockets; /* (o) num of sockets */
- uint16_t cores; /* (o) num of cores/socket */
- uint16_t threads; /* (o) num of threads/core */
- uint16_t maxcpus; /* (o) max pluggable cpus */
- struct sx vcpus_init_lock; /* (o) */
-};
-
#define VMM_CTR0(vcpu, format) \
VCPU_CTR0((vcpu)->vm, (vcpu)->vcpuid, format)
diff --git a/sys/arm64/include/vmm.h b/sys/arm64/include/vmm.h
index e67540eac66d..16292dd42f28 100644
--- a/sys/arm64/include/vmm.h
+++ b/sys/arm64/include/vmm.h
@@ -107,14 +107,33 @@ enum vm_reg_name {
#define VM_GUEST_BASE_IPA 0x80000000UL /* Guest kernel start ipa */
#ifdef _KERNEL
-struct vm;
-struct vm_exception;
-struct vm_exit;
-struct vm_run;
-struct vm_object;
-struct vm_guest_paging;
-struct vm_vgic_descr;
-struct pmap;
+#include <machine/vmm_instruction_emul.h>
+
+#define VMM_VCPU_MD_FIELDS \
+ struct vm_exit exitinfo; \
+ uint64_t nextpc; /* (x) next instruction to execute */ \
+ struct vfpstate *guestfpu /* (a,i) guest fpu state */
+
+#define VMM_VM_MD_FIELDS \
+ struct vmm_mmio_region mmio_region[VM_MAX_MMIO_REGIONS]; \
+ struct vmm_special_reg special_reg[VM_MAX_SPECIAL_REGS]
+
+struct vmm_mmio_region {
+ uint64_t start;
+ uint64_t end;
+ mem_region_read_t read;
+ mem_region_write_t write;
+};
+#define VM_MAX_MMIO_REGIONS 4
+
+struct vmm_special_reg {
+ uint32_t esr_iss;
+ uint32_t esr_mask;
+ reg_read_t reg_read;
+ reg_write_t reg_write;
+ void *arg;
+};
+#define VM_MAX_SPECIAL_REGS 16
struct vm_eventinfo {
void *rptr; /* rendezvous cookie */
@@ -125,6 +144,15 @@ struct vm_eventinfo {
#define DECLARE_VMMOPS_FUNC(ret_type, opname, args) \
ret_type vmmops_##opname args
+struct vm;
+struct vm_exception;
+struct vm_exit;
+struct vm_run;
+struct vm_object;
+struct vm_guest_paging;
+struct vm_vgic_descr;
+struct pmap;
+
DECLARE_VMMOPS_FUNC(int, modinit, (int ipinum));
DECLARE_VMMOPS_FUNC(int, modcleanup, (void));
DECLARE_VMMOPS_FUNC(void *, init, (struct vm *vm, struct pmap *pmap));
@@ -213,33 +241,6 @@ vcpu_suspended(struct vm_eventinfo *info)
int vcpu_debugged(struct vcpu *vcpu);
-enum vcpu_state {
- VCPU_IDLE,
- VCPU_FROZEN,
- VCPU_RUNNING,
- VCPU_SLEEPING,
-};
-
-int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
-enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
-
-static int __inline
-vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
-{
- return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
-}
-
-#ifdef _SYS_PROC_H_
-static int __inline
-vcpu_should_yield(struct vcpu *vcpu)
-{
- struct thread *td;
-
- td = curthread;
- return (td->td_ast != 0 || td->td_owepreempt != 0);
-}
-#endif
-
void *vcpu_stats(struct vcpu *vcpu);
void vcpu_notify_event(struct vcpu *vcpu);
struct vm_mem *vm_mem(struct vm *vm);
diff --git a/sys/arm64/include/vmm_instruction_emul.h b/sys/arm64/include/vmm_instruction_emul.h
index a295f7cce127..dc281f442543 100644
--- a/sys/arm64/include/vmm_instruction_emul.h
+++ b/sys/arm64/include/vmm_instruction_emul.h
@@ -27,6 +27,14 @@
#ifndef _VMM_INSTRUCTION_EMUL_H_
#define _VMM_INSTRUCTION_EMUL_H_
+#include <sys/types.h>
+
+struct vcpu;
+struct vm;
+struct vie;
+struct vre;
+struct vm_guest_paging;
+
/*
* Callback functions to read and write memory regions.
*/
diff --git a/sys/arm64/vmm/io/vgic_v3.c b/sys/arm64/vmm/io/vgic_v3.c
index 023406c64182..e4f7bb2af3ee 100644
--- a/sys/arm64/vmm/io/vgic_v3.c
+++ b/sys/arm64/vmm/io/vgic_v3.c
@@ -57,7 +57,6 @@
#include <machine/vmparam.h>
#include <machine/intr.h>
#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
#include <machine/vmm_instruction_emul.h>
#include <arm/arm/gic_common.h>
@@ -69,6 +68,8 @@
#include <arm64/vmm/arm64.h>
#include <arm64/vmm/vmm_handlers.h>
+#include <dev/vmm/vmm_dev.h>
+
#include "vgic.h"
#include "vgic_v3.h"
#include "vgic_v3_reg.h"
diff --git a/sys/arm64/vmm/vmm.c b/sys/arm64/vmm/vmm.c
index 31d2fb3f516b..75f7f2fcaaf7 100644
--- a/sys/arm64/vmm/vmm.c
+++ b/sys/arm64/vmm/vmm.c
@@ -61,10 +61,12 @@
#include <machine/vmm_instruction_emul.h>
#include <dev/pci/pcireg.h>
+
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_ktr.h>
#include <dev/vmm/vmm_mem.h>
#include <dev/vmm/vmm_stat.h>
+#include <dev/vmm/vmm_vm.h>
#include "arm64.h"
#include "mmu.h"
@@ -72,71 +74,6 @@
#include "io/vgic.h"
#include "io/vtimer.h"
-struct vcpu {
- int flags;
- enum vcpu_state state;
- struct mtx mtx;
- int hostcpu; /* host cpuid this vcpu last ran on */
- int vcpuid;
- void *stats;
- struct vm_exit exitinfo;
- uint64_t nextpc; /* (x) next instruction to execute */
- struct vm *vm; /* (o) */
- void *cookie; /* (i) cpu-specific data */
- struct vfpstate *guestfpu; /* (a,i) guest fpu state */
-};
-
-#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
-#define vcpu_lock_destroy(v) mtx_destroy(&((v)->mtx))
-#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx))
-#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx))
-#define vcpu_assert_locked(v) mtx_assert(&((v)->mtx), MA_OWNED)
-
-struct vmm_mmio_region {
- uint64_t start;
- uint64_t end;
- mem_region_read_t read;
- mem_region_write_t write;
-};
-#define VM_MAX_MMIO_REGIONS 4
-
-struct vmm_special_reg {
- uint32_t esr_iss;
- uint32_t esr_mask;
- reg_read_t reg_read;
- reg_write_t reg_write;
- void *arg;
-};
-#define VM_MAX_SPECIAL_REGS 16
-
-/*
- * Initialization:
- * (o) initialized the first time the VM is created
- * (i) initialized when VM is created and when it is reinitialized
- * (x) initialized before use
- */
-struct vm {
- void *cookie; /* (i) cpu-specific data */
- volatile cpuset_t active_cpus; /* (i) active vcpus */
- volatile cpuset_t debug_cpus; /* (i) vcpus stopped for debug */
- int suspend; /* (i) stop VM execution */
- bool dying; /* (o) is dying */
- volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */
- volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */
- struct vm_mem mem; /* (i) guest memory */
- char name[VM_MAX_NAMELEN + 1]; /* (o) virtual machine name */
- struct vcpu **vcpu; /* (i) guest vcpus */
- struct vmm_mmio_region mmio_region[VM_MAX_MMIO_REGIONS];
- /* (o) guest MMIO regions */
- struct vmm_special_reg special_reg[VM_MAX_SPECIAL_REGS];
- /* The following describe the vm cpu topology */
- uint16_t sockets; /* (o) num of sockets */
- uint16_t cores; /* (o) num of cores/socket */
- uint16_t threads; /* (o) num of threads/core */
- uint16_t maxcpus; /* (o) max pluggable cpus */
- struct sx vcpus_init_lock; /* (o) */
-};
-
static int vm_handle_wfi(struct vcpu *vcpu,
struct vm_exit *vme, bool *retu);
diff --git a/sys/arm64/vmm/vmm_arm64.c b/sys/arm64/vmm/vmm_arm64.c
index aa1361049f49..d529f000b828 100644
--- a/sys/arm64/vmm/vmm_arm64.c
+++ b/sys/arm64/vmm/vmm_arm64.c
@@ -52,12 +52,12 @@
#include <machine/cpu.h>
#include <machine/machdep.h>
#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
#include <machine/atomic.h>
#include <machine/hypervisor.h>
#include <machine/pmap.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
#include "mmu.h"
#include "arm64.h"
diff --git a/sys/dev/vmm/vmm_dev.c b/sys/dev/vmm/vmm_dev.c
index 840e810a39fb..eda15cc88b28 100644
--- a/sys/dev/vmm/vmm_dev.c
+++ b/sys/dev/vmm/vmm_dev.c
@@ -33,6 +33,7 @@
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_mem.h>
#include <dev/vmm/vmm_stat.h>
+#include <dev/vmm/vmm_vm.h>
#ifdef __amd64__
#ifdef COMPAT_FREEBSD12
diff --git a/sys/dev/vmm/vmm_mem.c b/sys/dev/vmm/vmm_mem.c
index 5ae944713c81..5a73cbf7fc5b 100644
--- a/sys/dev/vmm/vmm_mem.c
+++ b/sys/dev/vmm/vmm_mem.c
@@ -23,6 +23,7 @@
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
static void vm_free_memmap(struct vm *vm, int ident);
diff --git a/sys/dev/vmm/vmm_mem.h b/sys/dev/vmm/vmm_mem.h
index f3d22058c7b8..64bb29352a55 100644
--- a/sys/dev/vmm/vmm_mem.h
+++ b/sys/dev/vmm/vmm_mem.h
@@ -34,7 +34,10 @@ enum {
#include <sys/types.h>
#include <sys/_sx.h>
+struct domainset;
+struct vcpu;
struct vm;
+struct vm_guest_paging;
struct vm_object;
struct vmspace;
diff --git a/sys/dev/vmm/vmm_vm.h b/sys/dev/vmm/vmm_vm.h
new file mode 100644
index 000000000000..23f40e079da4
--- /dev/null
+++ b/sys/dev/vmm/vmm_vm.h
@@ -0,0 +1,121 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2011 NetApp, Inc.
+ * All rights reserved.
+ */
+
+#ifndef _DEV_VMM_VM_H_
+#define _DEV_VMM_VM_H_
+
+#ifdef _KERNEL
+
+#include <machine/vmm.h>
+
+#include <dev/vmm/vmm_param.h>
+#include <dev/vmm/vmm_mem.h>
+
+struct vcpu;
+
+enum vcpu_state {
+ VCPU_IDLE,
+ VCPU_FROZEN,
+ VCPU_RUNNING,
+ VCPU_SLEEPING,
+};
+
+/*
+ * Initialization:
+ * (a) allocated when vcpu is created
+ * (i) initialized when vcpu is created and when it is reinitialized
+ * (o) initialized the first time the vcpu is created
+ * (x) initialized before use
+ */
+struct vcpu {
+ struct mtx mtx; /* (o) protects 'state' and 'hostcpu' */
+ enum vcpu_state state; /* (o) vcpu state */
+ int vcpuid; /* (o) */
+ int hostcpu; /* (o) vcpu's host cpu */
+ int reqidle; /* (i) request vcpu to idle */
+ struct vm *vm; /* (o) */
+ void *cookie; /* (i) cpu-specific data */
+ void *stats; /* (a,i) statistics */
+
+ VMM_VCPU_MD_FIELDS;
+};
+
+#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
+#define vcpu_lock_destroy(v) mtx_destroy(&((v)->mtx))
+#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx))
+#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx))
+#define vcpu_assert_locked(v) mtx_assert(&((v)->mtx), MA_OWNED)
+
+int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
+#ifdef __amd64__
+int vcpu_set_state_all(struct vm *vm, enum vcpu_state state);
+#endif
+enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
+
+static int __inline
+vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
+{
+ return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
+}
+
+#ifdef _SYS_PROC_H_
+static int __inline
+vcpu_should_yield(struct vcpu *vcpu)
+{
+ struct thread *td;
+
+ td = curthread;
+ return (td->td_ast != 0 || td->td_owepreempt != 0);
+}
+#endif
+
+typedef void (*vm_rendezvous_func_t)(struct vcpu *vcpu, void *arg);
+
+/*
+ * Initialization:
+ * (o) initialized the first time the VM is created
+ * (i) initialized when VM is created and when it is reinitialized
+ * (x) initialized before use
+ *
+ * Locking:
+ * [m] mem_segs_lock
+ * [r] rendezvous_mtx
+ * [v] reads require one frozen vcpu, writes require freezing all vcpus
+ */
+struct vm {
+ void *cookie; /* (i) cpu-specific data */
+ struct vcpu **vcpu; /* (o) guest vcpus */
+ struct vm_mem mem; /* (i) [m+v] guest memory */
+
+ char name[VM_MAX_NAMELEN + 1]; /* (o) virtual machine name */
+ struct sx vcpus_init_lock; /* (o) */
+
+ bool dying; /* (o) is dying */
+ int suspend; /* (i) stop VM execution */
+
+ volatile cpuset_t active_cpus; /* (i) active vcpus */
+ volatile cpuset_t debug_cpus; /* (i) vcpus stopped for debug */
+ volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */
+ volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */
+
+ cpuset_t rendezvous_req_cpus; /* (x) [r] rendezvous requested */
+ cpuset_t rendezvous_done_cpus; /* (x) [r] rendezvous finished */
+ void *rendezvous_arg; /* (x) [r] rendezvous func/arg */
+ vm_rendezvous_func_t rendezvous_func;
+ struct mtx rendezvous_mtx; /* (o) rendezvous lock */
+
+ uint16_t sockets; /* (o) num of sockets */
+ uint16_t cores; /* (o) num of cores/socket */
+ uint16_t threads; /* (o) num of threads/core */
+ uint16_t maxcpus; /* (o) max pluggable cpus */
+
+ VMM_VM_MD_FIELDS;
+};
+
+#endif /* _KERNEL */
+
+#endif /* !_DEV_VMM_VM_H_ */
diff --git a/sys/riscv/include/vmm.h b/sys/riscv/include/vmm.h
index 361140834805..a7318294464c 100644
--- a/sys/riscv/include/vmm.h
+++ b/sys/riscv/include/vmm.h
@@ -104,6 +104,15 @@ enum vm_reg_name {
#define VM_INTINFO_SWINTR (4 << 8)
#ifdef _KERNEL
+#include <machine/vmm_instruction_emul.h>
+
+#define VMM_VCPU_MD_FIELDS \
+ struct vm_exit exitinfo; \
+ uint64_t nextpc; /* (x) next instruction to execute */ \
+ struct fpreg *guestfpu /* (a,i) guest fpu state */
+
+#define VMM_VM_MD_FIELDS \
+ struct vmm_mmio_region mmio_region[VM_MAX_MMIO_REGIONS]
struct vm;
struct vm_exception;
@@ -114,6 +123,14 @@ struct vm_guest_paging;
struct vm_aplic_descr;
struct pmap;
+struct vmm_mmio_region {
+ uint64_t start;
+ uint64_t end;
+ mem_region_read_t read;
+ mem_region_write_t write;
+};
+#define VM_MAX_MMIO_REGIONS 4
+
struct vm_eventinfo {
void *rptr; /* rendezvous cookie */
int *sptr; /* suspend cookie */
@@ -203,33 +220,6 @@ vcpu_suspended(struct vm_eventinfo *info)
int vcpu_debugged(struct vcpu *vcpu);
-enum vcpu_state {
- VCPU_IDLE,
- VCPU_FROZEN,
- VCPU_RUNNING,
- VCPU_SLEEPING,
-};
-
-int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
-enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
-
-static int __inline
-vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
-{
- return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
-}
-
-#ifdef _SYS_PROC_H_
-static int __inline
-vcpu_should_yield(struct vcpu *vcpu)
-{
- struct thread *td;
-
- td = curthread;
- return (td->td_ast != 0 || td->td_owepreempt != 0);
-}
-#endif
-
void *vcpu_stats(struct vcpu *vcpu);
void vcpu_notify_event(struct vcpu *vcpu);
struct vm_mem *vm_mem(struct vm *vm);
diff --git a/sys/riscv/include/vmm_instruction_emul.h b/sys/riscv/include/vmm_instruction_emul.h
index bee63d2f86ba..5041b10569f5 100644
--- a/sys/riscv/include/vmm_instruction_emul.h
+++ b/sys/riscv/include/vmm_instruction_emul.h
@@ -29,6 +29,12 @@
#ifndef _VMM_INSTRUCTION_EMUL_H_
#define _VMM_INSTRUCTION_EMUL_H_
+struct vcpu;
+struct vie;
+struct vre;
+struct vm;
+struct vm_guest_paging;
+
/*
* Callback functions to read and write memory regions.
*/
diff --git a/sys/riscv/vmm/vmm.c b/sys/riscv/vmm/vmm.c
index 23b57ad3b7aa..fea6421962dc 100644
--- a/sys/riscv/vmm/vmm.c
+++ b/sys/riscv/vmm/vmm.c
@@ -71,67 +71,13 @@
#include <dev/vmm/vmm_dev.h>
#include <dev/vmm/vmm_ktr.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
#include "vmm_stat.h"
#include "riscv.h"
#include "vmm_aplic.h"
-struct vcpu {
- int flags;
- enum vcpu_state state;
- struct mtx mtx;
- int hostcpu; /* host cpuid this vcpu last ran on */
- int vcpuid;
- void *stats;
- struct vm_exit exitinfo;
- uint64_t nextpc; /* (x) next instruction to execute */
- struct vm *vm; /* (o) */
- void *cookie; /* (i) cpu-specific data */
- struct fpreg *guestfpu; /* (a,i) guest fpu state */
-};
-
-#define vcpu_lock_init(v) mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
-#define vcpu_lock_destroy(v) mtx_destroy(&((v)->mtx))
-#define vcpu_lock(v) mtx_lock_spin(&((v)->mtx))
-#define vcpu_unlock(v) mtx_unlock_spin(&((v)->mtx))
-#define vcpu_assert_locked(v) mtx_assert(&((v)->mtx), MA_OWNED)
-
-struct vmm_mmio_region {
- uint64_t start;
- uint64_t end;
- mem_region_read_t read;
- mem_region_write_t write;
-};
-#define VM_MAX_MMIO_REGIONS 4
-
-/*
- * Initialization:
- * (o) initialized the first time the VM is created
- * (i) initialized when VM is created and when it is reinitialized
- * (x) initialized before use
- */
-struct vm {
- void *cookie; /* (i) cpu-specific data */
- volatile cpuset_t active_cpus; /* (i) active vcpus */
- volatile cpuset_t debug_cpus; /* (i) vcpus stopped for debug*/
- int suspend; /* (i) stop VM execution */
- bool dying; /* (o) is dying */
- volatile cpuset_t suspended_cpus; /* (i) suspended vcpus */
- volatile cpuset_t halted_cpus; /* (x) cpus in a hard halt */
- struct vm_mem mem; /* (i) [m+v] guest memory */
- char name[VM_MAX_NAMELEN + 1]; /* (o) virtual machine name */
- struct vcpu **vcpu; /* (i) guest vcpus */
- struct vmm_mmio_region mmio_region[VM_MAX_MMIO_REGIONS];
- /* (o) guest MMIO regions */
- /* The following describe the vm cpu topology */
- uint16_t sockets; /* (o) num of sockets */
- uint16_t cores; /* (o) num of cores/socket */
- uint16_t threads; /* (o) num of threads/core */
- uint16_t maxcpus; /* (o) max pluggable cpus */
- struct sx vcpus_init_lock; /* (o) */
-};
-
static MALLOC_DEFINE(M_VMM, "vmm", "vmm");
/* statistics */
diff --git a/sys/riscv/vmm/vmm_aplic.c b/sys/riscv/vmm/vmm_aplic.c
index 74cb4fef4273..eaf2caa4d313 100644
--- a/sys/riscv/vmm/vmm_aplic.c
+++ b/sys/riscv/vmm/vmm_aplic.c
@@ -46,7 +46,8 @@
#include <riscv/vmm/vmm_aplic.h>
#include <machine/vmm_instruction_emul.h>
-#include <machine/vmm_dev.h>
+
+#include <dev/vmm/vmm_dev.h>
MALLOC_DEFINE(M_APLIC, "RISC-V VMM APLIC", "RISC-V AIA APLIC");
diff --git a/sys/riscv/vmm/vmm_fence.c b/sys/riscv/vmm/vmm_fence.c
index f8b69aac77a9..ff7eabdb3d50 100644
--- a/sys/riscv/vmm/vmm_fence.c
+++ b/sys/riscv/vmm/vmm_fence.c
@@ -39,6 +39,10 @@
#include <sys/mutex.h>
#include <sys/bus.h>
+#include <machine/vmm.h>
+
+#include <dev/vmm/vmm_vm.h>
+
#include "riscv.h"
#include "vmm_fence.h"
@@ -145,7 +149,6 @@ vmm_fence_add(struct vm *vm, cpuset_t *cpus, struct vmm_fence *fence)
struct vcpu *vcpu;
uint16_t maxcpus;
int hostcpu;
- int state;
bool enq;
int i;
@@ -193,8 +196,7 @@ vmm_fence_add(struct vm *vm, cpuset_t *cpus, struct vmm_fence *fence)
mb();
- state = vcpu_get_state(vcpu, &hostcpu);
- if (state == VCPU_RUNNING)
+ if (vcpu_is_running(vcpu, &hostcpu))
CPU_SET(hostcpu, &running_cpus);
}
diff --git a/sys/riscv/vmm/vmm_riscv.c b/sys/riscv/vmm/vmm_riscv.c
index 0e46aca60fdf..cfd3decd8cfa 100644
--- a/sys/riscv/vmm/vmm_riscv.c
+++ b/sys/riscv/vmm/vmm_riscv.c
@@ -59,7 +59,6 @@
#include <machine/cpu.h>
#include <machine/machdep.h>
#include <machine/vmm.h>
-#include <machine/vmm_dev.h>
#include <machine/atomic.h>
#include <machine/pmap.h>
#include <machine/intr.h>
@@ -67,6 +66,7 @@
#include <machine/db_machdep.h>
#include <dev/vmm/vmm_mem.h>
+#include <dev/vmm/vmm_vm.h>
#include "riscv.h"
#include "vmm_aplic.h"