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
This commit is contained in:
Mark Johnston
2026-01-08 21:53:31 +00:00
parent 90b9a77ebe
commit a6411f6b7d
20 changed files with 239 additions and 302 deletions
+27 -28
View File
@@ -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);
+1 -1
View File
@@ -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"
+1 -1
View File
@@ -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"
+2 -1
View File
@@ -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"
+1 -82
View File
@@ -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)
+36 -35
View File
@@ -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);
+8
View File
@@ -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.
*/
+2 -1
View File
@@ -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"
+2 -65
View File
@@ -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);
+1 -1
View File
@@ -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"
+1
View File
@@ -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
+1
View File
@@ -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);
+3
View File
@@ -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;
+121
View File
@@ -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_ */
+17 -27
View File
@@ -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);
+6
View File
@@ -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.
*/
+1 -55
View File
@@ -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 */
+2 -1
View File
@@ -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");
+5 -3
View File
@@ -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);
}
+1 -1
View File
@@ -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"