ed85203fb7
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
167 lines
4.9 KiB
C
167 lines
4.9 KiB
C
/*-
|
|
* 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 <sys/_cpuset.h>
|
|
|
|
#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)
|
|
|
|
extern int vmm_ipinum;
|
|
|
|
int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
|
|
int vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
|
|
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);
|
|
void vcpu_notify_event(struct vcpu *vcpu);
|
|
void vcpu_notify_event_locked(struct vcpu *vcpu);
|
|
int vcpu_debugged(struct vcpu *vcpu);
|
|
|
|
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);
|
|
int vm_handle_rendezvous(struct vcpu *vcpu);
|
|
|
|
/*
|
|
* 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.
|
|
*/
|
|
int vm_smp_rendezvous(struct vcpu *vcpu, cpuset_t dest,
|
|
vm_rendezvous_func_t func, 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;
|
|
};
|
|
|
|
int vm_create(const char *name, struct vm **retvm);
|
|
struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
|
|
void vm_destroy(struct vm *vm);
|
|
int vm_reinit(struct vm *vm);
|
|
void vm_reset(struct vm *vm);
|
|
|
|
void vm_lock_vcpus(struct vm *vm);
|
|
void vm_unlock_vcpus(struct vm *vm);
|
|
void vm_disable_vcpu_creation(struct vm *vm);
|
|
|
|
int vm_suspend(struct vm *vm, enum vm_suspend_how how);
|
|
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);
|
|
|
|
cpuset_t vm_active_cpus(struct vm *vm);
|
|
cpuset_t vm_debug_cpus(struct vm *vm);
|
|
cpuset_t vm_suspended_cpus(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);
|
|
#endif /* _KERNEL */
|
|
|
|
#endif /* !_DEV_VMM_VM_H_ */
|