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:
+27
-28
@@ -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);
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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");
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user