xref: /freebsd/sys/dev/vmm/vmm_vm.h (revision 5f13d6b60740c021951ae0e4d096903cfa1679e2)
1a6411f6bSMark Johnston /*-
2a6411f6bSMark Johnston  * SPDX-License-Identifier: BSD-2-Clause
3a6411f6bSMark Johnston  *
4a6411f6bSMark Johnston  * Copyright (c) 2011 NetApp, Inc.
5a6411f6bSMark Johnston  * All rights reserved.
6a6411f6bSMark Johnston  */
7a6411f6bSMark Johnston 
8a6411f6bSMark Johnston #ifndef _DEV_VMM_VM_H_
9a6411f6bSMark Johnston #define	_DEV_VMM_VM_H_
10a6411f6bSMark Johnston 
11a6411f6bSMark Johnston #ifdef _KERNEL
12ed85203fSMark Johnston #include <sys/_cpuset.h>
13a6411f6bSMark Johnston 
14a6411f6bSMark Johnston #include <machine/vmm.h>
15a6411f6bSMark Johnston 
16a6411f6bSMark Johnston #include <dev/vmm/vmm_param.h>
17a6411f6bSMark Johnston #include <dev/vmm/vmm_mem.h>
18a6411f6bSMark Johnston 
19a6411f6bSMark Johnston struct vcpu;
20a6411f6bSMark Johnston 
21a6411f6bSMark Johnston enum vcpu_state {
22a6411f6bSMark Johnston 	VCPU_IDLE,
23a6411f6bSMark Johnston 	VCPU_FROZEN,
24a6411f6bSMark Johnston 	VCPU_RUNNING,
25a6411f6bSMark Johnston 	VCPU_SLEEPING,
26a6411f6bSMark Johnston };
27a6411f6bSMark Johnston 
28a6411f6bSMark Johnston /*
29a6411f6bSMark Johnston  * Initialization:
30a6411f6bSMark Johnston  * (a) allocated when vcpu is created
31a6411f6bSMark Johnston  * (i) initialized when vcpu is created and when it is reinitialized
32a6411f6bSMark Johnston  * (o) initialized the first time the vcpu is created
33a6411f6bSMark Johnston  * (x) initialized before use
34a6411f6bSMark Johnston  */
35a6411f6bSMark Johnston struct vcpu {
36a6411f6bSMark Johnston 	struct mtx 	mtx;		/* (o) protects 'state' and 'hostcpu' */
37a6411f6bSMark Johnston 	enum vcpu_state	state;		/* (o) vcpu state */
38a6411f6bSMark Johnston 	int		vcpuid;		/* (o) */
39a6411f6bSMark Johnston 	int		hostcpu;	/* (o) vcpu's host cpu */
40a6411f6bSMark Johnston 	int		reqidle;	/* (i) request vcpu to idle */
41a6411f6bSMark Johnston 	struct vm	*vm;		/* (o) */
42a6411f6bSMark Johnston 	void		*cookie;	/* (i) cpu-specific data */
43a6411f6bSMark Johnston 	void		*stats;		/* (a,i) statistics */
44a6411f6bSMark Johnston 
45a6411f6bSMark Johnston 	VMM_VCPU_MD_FIELDS;
46a6411f6bSMark Johnston };
47a6411f6bSMark Johnston 
48a6411f6bSMark Johnston #define	vcpu_lock_init(v)	mtx_init(&((v)->mtx), "vcpu lock", 0, MTX_SPIN)
49a6411f6bSMark Johnston #define	vcpu_lock_destroy(v)	mtx_destroy(&((v)->mtx))
50a6411f6bSMark Johnston #define	vcpu_lock(v)		mtx_lock_spin(&((v)->mtx))
51a6411f6bSMark Johnston #define	vcpu_unlock(v)		mtx_unlock_spin(&((v)->mtx))
52a6411f6bSMark Johnston #define	vcpu_assert_locked(v)	mtx_assert(&((v)->mtx), MA_OWNED)
53a6411f6bSMark Johnston 
54ed85203fSMark Johnston extern int vmm_ipinum;
55ed85203fSMark Johnston 
56a6411f6bSMark Johnston int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
57ed85203fSMark Johnston int vcpu_set_state_locked(struct vcpu *vcpu, enum vcpu_state newstate,
58ed85203fSMark Johnston     bool from_idle);
59a6411f6bSMark Johnston int vcpu_set_state_all(struct vm *vm, enum vcpu_state state);
60a6411f6bSMark Johnston enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
61ed85203fSMark Johnston void vcpu_notify_event(struct vcpu *vcpu);
62ed85203fSMark Johnston void vcpu_notify_event_locked(struct vcpu *vcpu);
63ed85203fSMark Johnston int vcpu_debugged(struct vcpu *vcpu);
64a6411f6bSMark Johnston 
65*5f13d6b6SMark Johnston static inline void *
vcpu_stats(struct vcpu * vcpu)66*5f13d6b6SMark Johnston vcpu_stats(struct vcpu *vcpu)
67*5f13d6b6SMark Johnston {
68*5f13d6b6SMark Johnston 	return (vcpu->stats);
69*5f13d6b6SMark Johnston }
70*5f13d6b6SMark Johnston 
71*5f13d6b6SMark Johnston static inline struct vm *
vcpu_vm(struct vcpu * vcpu)72*5f13d6b6SMark Johnston vcpu_vm(struct vcpu *vcpu)
73*5f13d6b6SMark Johnston {
74*5f13d6b6SMark Johnston 	return (vcpu->vm);
75*5f13d6b6SMark Johnston }
76*5f13d6b6SMark Johnston 
77*5f13d6b6SMark Johnston static inline int
vcpu_vcpuid(struct vcpu * vcpu)78*5f13d6b6SMark Johnston vcpu_vcpuid(struct vcpu *vcpu)
79*5f13d6b6SMark Johnston {
80*5f13d6b6SMark Johnston 	return (vcpu->vcpuid);
81*5f13d6b6SMark Johnston }
82*5f13d6b6SMark Johnston 
83a6411f6bSMark Johnston static int __inline
vcpu_is_running(struct vcpu * vcpu,int * hostcpu)84a6411f6bSMark Johnston vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
85a6411f6bSMark Johnston {
86a6411f6bSMark Johnston 	return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
87a6411f6bSMark Johnston }
88a6411f6bSMark Johnston 
89a6411f6bSMark Johnston #ifdef _SYS_PROC_H_
90a6411f6bSMark Johnston static int __inline
vcpu_should_yield(struct vcpu * vcpu)91a6411f6bSMark Johnston vcpu_should_yield(struct vcpu *vcpu)
92a6411f6bSMark Johnston {
93a6411f6bSMark Johnston 	struct thread *td;
94a6411f6bSMark Johnston 
95a6411f6bSMark Johnston 	td = curthread;
96a6411f6bSMark Johnston 	return (td->td_ast != 0 || td->td_owepreempt != 0);
97a6411f6bSMark Johnston }
98a6411f6bSMark Johnston #endif
99a6411f6bSMark Johnston 
100a6411f6bSMark Johnston typedef void (*vm_rendezvous_func_t)(struct vcpu *vcpu, void *arg);
101ed85203fSMark Johnston int vm_handle_rendezvous(struct vcpu *vcpu);
102ed85203fSMark Johnston 
103ed85203fSMark Johnston /*
104ed85203fSMark Johnston  * Rendezvous all vcpus specified in 'dest' and execute 'func(arg)'.
105ed85203fSMark Johnston  * The rendezvous 'func(arg)' is not allowed to do anything that will
106ed85203fSMark Johnston  * cause the thread to be put to sleep.
107ed85203fSMark Johnston  *
108ed85203fSMark Johnston  * The caller cannot hold any locks when initiating the rendezvous.
109ed85203fSMark Johnston  *
110ed85203fSMark Johnston  * The implementation of this API may cause vcpus other than those specified
111ed85203fSMark Johnston  * by 'dest' to be stalled. The caller should not rely on any vcpus making
112ed85203fSMark Johnston  * forward progress when the rendezvous is in progress.
113ed85203fSMark Johnston  */
114ed85203fSMark Johnston int vm_smp_rendezvous(struct vcpu *vcpu, cpuset_t dest,
115ed85203fSMark Johnston     vm_rendezvous_func_t func, void *arg);
116a6411f6bSMark Johnston 
117a6411f6bSMark Johnston /*
118a6411f6bSMark Johnston  * Initialization:
119a6411f6bSMark Johnston  * (o) initialized the first time the VM is created
120a6411f6bSMark Johnston  * (i) initialized when VM is created and when it is reinitialized
121a6411f6bSMark Johnston  * (x) initialized before use
122a6411f6bSMark Johnston  *
123a6411f6bSMark Johnston  * Locking:
124a6411f6bSMark Johnston  * [m] mem_segs_lock
125a6411f6bSMark Johnston  * [r] rendezvous_mtx
126a6411f6bSMark Johnston  * [v] reads require one frozen vcpu, writes require freezing all vcpus
127a6411f6bSMark Johnston  */
128a6411f6bSMark Johnston struct vm {
129a6411f6bSMark Johnston 	void		*cookie;		/* (i) cpu-specific data */
130a6411f6bSMark Johnston 	struct vcpu	**vcpu;			/* (o) guest vcpus */
131a6411f6bSMark Johnston 	struct vm_mem	mem;			/* (i) [m+v] guest memory */
132a6411f6bSMark Johnston 
133a6411f6bSMark Johnston 	char		name[VM_MAX_NAMELEN + 1]; /* (o) virtual machine name */
134a6411f6bSMark Johnston 	struct sx	vcpus_init_lock;	/* (o) */
135a6411f6bSMark Johnston 
136a6411f6bSMark Johnston 	bool		dying;			/* (o) is dying */
137a6411f6bSMark Johnston 	int		suspend;		/* (i) stop VM execution */
138a6411f6bSMark Johnston 
139a6411f6bSMark Johnston 	volatile cpuset_t active_cpus;		/* (i) active vcpus */
140a6411f6bSMark Johnston 	volatile cpuset_t debug_cpus;		/* (i) vcpus stopped for debug */
141a6411f6bSMark Johnston 	volatile cpuset_t suspended_cpus; 	/* (i) suspended vcpus */
142a6411f6bSMark Johnston 	volatile cpuset_t halted_cpus;		/* (x) cpus in a hard halt */
143a6411f6bSMark Johnston 
144a6411f6bSMark Johnston 	cpuset_t	rendezvous_req_cpus;	/* (x) [r] rendezvous requested */
145a6411f6bSMark Johnston 	cpuset_t	rendezvous_done_cpus;	/* (x) [r] rendezvous finished */
146a6411f6bSMark Johnston 	void		*rendezvous_arg;	/* (x) [r] rendezvous func/arg */
147a6411f6bSMark Johnston 	vm_rendezvous_func_t rendezvous_func;
148a6411f6bSMark Johnston 	struct mtx	rendezvous_mtx;		/* (o) rendezvous lock */
149a6411f6bSMark Johnston 
150a6411f6bSMark Johnston 	uint16_t	sockets;		/* (o) num of sockets */
151a6411f6bSMark Johnston 	uint16_t	cores;			/* (o) num of cores/socket */
152a6411f6bSMark Johnston 	uint16_t	threads;		/* (o) num of threads/core */
153a6411f6bSMark Johnston 	uint16_t	maxcpus;		/* (o) max pluggable cpus */
154a6411f6bSMark Johnston 
155a6411f6bSMark Johnston 	VMM_VM_MD_FIELDS;
156a6411f6bSMark Johnston };
157a6411f6bSMark Johnston 
158ed85203fSMark Johnston int vm_create(const char *name, struct vm **retvm);
159ed85203fSMark Johnston struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
160ed85203fSMark Johnston void vm_destroy(struct vm *vm);
161ed85203fSMark Johnston int vm_reinit(struct vm *vm);
162ed85203fSMark Johnston void vm_reset(struct vm *vm);
163ed85203fSMark Johnston 
164ed85203fSMark Johnston void vm_lock_vcpus(struct vm *vm);
165ed85203fSMark Johnston void vm_unlock_vcpus(struct vm *vm);
166ed85203fSMark Johnston void vm_disable_vcpu_creation(struct vm *vm);
167ed85203fSMark Johnston 
168ed85203fSMark Johnston int vm_suspend(struct vm *vm, enum vm_suspend_how how);
169ed85203fSMark Johnston int vm_activate_cpu(struct vcpu *vcpu);
170ed85203fSMark Johnston int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu);
171ed85203fSMark Johnston int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu);
172ed85203fSMark Johnston 
173ed85203fSMark Johnston cpuset_t vm_active_cpus(struct vm *vm);
174ed85203fSMark Johnston cpuset_t vm_debug_cpus(struct vm *vm);
175ed85203fSMark Johnston cpuset_t vm_suspended_cpus(struct vm *vm);
176ed85203fSMark Johnston 
177ed85203fSMark Johnston uint16_t vm_get_maxcpus(struct vm *vm);
178ed85203fSMark Johnston void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores,
179ed85203fSMark Johnston     uint16_t *threads, uint16_t *maxcpus);
180ed85203fSMark Johnston int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores,
181ed85203fSMark Johnston     uint16_t threads, uint16_t maxcpus);
182*5f13d6b6SMark Johnston 
183*5f13d6b6SMark Johnston static inline const char *
vm_name(struct vm * vm)184*5f13d6b6SMark Johnston vm_name(struct vm *vm)
185*5f13d6b6SMark Johnston {
186*5f13d6b6SMark Johnston 	return (vm->name);
187*5f13d6b6SMark Johnston }
188*5f13d6b6SMark Johnston 
189*5f13d6b6SMark Johnston static inline struct vm_mem *
vm_mem(struct vm * vm)190*5f13d6b6SMark Johnston vm_mem(struct vm *vm)
191*5f13d6b6SMark Johnston {
192*5f13d6b6SMark Johnston 	return (&vm->mem);
193*5f13d6b6SMark Johnston }
194*5f13d6b6SMark Johnston 
195*5f13d6b6SMark Johnston static inline struct vcpu *
vm_vcpu(struct vm * vm,int vcpuid)196*5f13d6b6SMark Johnston vm_vcpu(struct vm *vm, int vcpuid)
197*5f13d6b6SMark Johnston {
198*5f13d6b6SMark Johnston 	return (vm->vcpu[vcpuid]);
199*5f13d6b6SMark Johnston }
200*5f13d6b6SMark Johnston 
201*5f13d6b6SMark Johnston struct vm_eventinfo {
202*5f13d6b6SMark Johnston 	cpuset_t *rptr;		/* rendezvous cookie */
203*5f13d6b6SMark Johnston 	int	*sptr;		/* suspend cookie */
204*5f13d6b6SMark Johnston 	int	*iptr;		/* reqidle cookie */
205*5f13d6b6SMark Johnston };
206*5f13d6b6SMark Johnston 
207*5f13d6b6SMark Johnston static inline int
vcpu_rendezvous_pending(struct vcpu * vcpu,struct vm_eventinfo * info)208*5f13d6b6SMark Johnston vcpu_rendezvous_pending(struct vcpu *vcpu, struct vm_eventinfo *info)
209*5f13d6b6SMark Johnston {
210*5f13d6b6SMark Johnston 	/*
211*5f13d6b6SMark Johnston 	 * This check isn't done with atomic operations or under a lock because
212*5f13d6b6SMark Johnston 	 * there's no need to. If the vcpuid bit is set, the vcpu is part of a
213*5f13d6b6SMark Johnston 	 * rendezvous and the bit won't be cleared until the vcpu enters the
214*5f13d6b6SMark Johnston 	 * rendezvous. On rendezvous exit, the cpuset is cleared and the vcpu
215*5f13d6b6SMark Johnston 	 * will see an empty cpuset. So, the races are harmless.
216*5f13d6b6SMark Johnston 	 */
217*5f13d6b6SMark Johnston 	return (CPU_ISSET(vcpu_vcpuid(vcpu), info->rptr));
218*5f13d6b6SMark Johnston }
219*5f13d6b6SMark Johnston 
220*5f13d6b6SMark Johnston static inline int
vcpu_suspended(struct vm_eventinfo * info)221*5f13d6b6SMark Johnston vcpu_suspended(struct vm_eventinfo *info)
222*5f13d6b6SMark Johnston {
223*5f13d6b6SMark Johnston 	return (*info->sptr);
224*5f13d6b6SMark Johnston }
225*5f13d6b6SMark Johnston 
226*5f13d6b6SMark Johnston static inline int
vcpu_reqidle(struct vm_eventinfo * info)227*5f13d6b6SMark Johnston vcpu_reqidle(struct vm_eventinfo *info)
228*5f13d6b6SMark Johnston {
229*5f13d6b6SMark Johnston 	return (*info->iptr);
230*5f13d6b6SMark Johnston }
231a6411f6bSMark Johnston #endif /* _KERNEL */
232a6411f6bSMark Johnston 
233a6411f6bSMark Johnston #endif /* !_DEV_VMM_VM_H_ */
234