xref: /freebsd/sys/riscv/include/vmm.h (revision c76c2a19ae3763d17aa6a60a5831ed24cbc16e83)
1d3916eacSRuslan Bukin /*
2d3916eacSRuslan Bukin  * SPDX-License-Identifier: BSD-2-Clause
3d3916eacSRuslan Bukin  *
4d3916eacSRuslan Bukin  * Copyright (c) 2015 Mihai Carabas <mihai.carabas@gmail.com>
5d3916eacSRuslan Bukin  * Copyright (c) 2024 Ruslan Bukin <br@bsdpad.com>
6d3916eacSRuslan Bukin  *
7d3916eacSRuslan Bukin  * This software was developed by the University of Cambridge Computer
8d3916eacSRuslan Bukin  * Laboratory (Department of Computer Science and Technology) under Innovate
9d3916eacSRuslan Bukin  * UK project 105694, "Digital Security by Design (DSbD) Technology Platform
10d3916eacSRuslan Bukin  * Prototype".
11d3916eacSRuslan Bukin  *
12d3916eacSRuslan Bukin  * Redistribution and use in source and binary forms, with or without
13d3916eacSRuslan Bukin  * modification, are permitted provided that the following conditions
14d3916eacSRuslan Bukin  * are met:
15d3916eacSRuslan Bukin  * 1. Redistributions of source code must retain the above copyright
16d3916eacSRuslan Bukin  *    notice, this list of conditions and the following disclaimer.
17d3916eacSRuslan Bukin  * 2. Redistributions in binary form must reproduce the above copyright
18d3916eacSRuslan Bukin  *    notice, this list of conditions and the following disclaimer in the
19d3916eacSRuslan Bukin  *    documentation and/or other materials provided with the distribution.
20d3916eacSRuslan Bukin  *
21d3916eacSRuslan Bukin  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22d3916eacSRuslan Bukin  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23d3916eacSRuslan Bukin  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24d3916eacSRuslan Bukin  * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
25d3916eacSRuslan Bukin  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26d3916eacSRuslan Bukin  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27d3916eacSRuslan Bukin  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28d3916eacSRuslan Bukin  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29d3916eacSRuslan Bukin  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30d3916eacSRuslan Bukin  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31d3916eacSRuslan Bukin  * SUCH DAMAGE.
32d3916eacSRuslan Bukin  */
33d3916eacSRuslan Bukin 
34d3916eacSRuslan Bukin #ifndef _VMM_H_
35d3916eacSRuslan Bukin #define	_VMM_H_
36d3916eacSRuslan Bukin 
37d3916eacSRuslan Bukin #include <sys/param.h>
38d3916eacSRuslan Bukin #include <sys/cpuset.h>
39d3916eacSRuslan Bukin #include <vm/vm.h>
40d3916eacSRuslan Bukin #include <vm/pmap.h>
41d3916eacSRuslan Bukin 
42d3916eacSRuslan Bukin #include "pte.h"
43d3916eacSRuslan Bukin #include "pmap.h"
44d3916eacSRuslan Bukin 
45d3916eacSRuslan Bukin struct vcpu;
46d3916eacSRuslan Bukin 
47d3916eacSRuslan Bukin enum vm_suspend_how {
48d3916eacSRuslan Bukin 	VM_SUSPEND_NONE,
49d3916eacSRuslan Bukin 	VM_SUSPEND_RESET,
50d3916eacSRuslan Bukin 	VM_SUSPEND_POWEROFF,
51d3916eacSRuslan Bukin 	VM_SUSPEND_HALT,
52d3916eacSRuslan Bukin 	VM_SUSPEND_LAST
53d3916eacSRuslan Bukin };
54d3916eacSRuslan Bukin 
55d3916eacSRuslan Bukin /*
56d3916eacSRuslan Bukin  * Identifiers for architecturally defined registers.
57d3916eacSRuslan Bukin  */
58d3916eacSRuslan Bukin enum vm_reg_name {
59d3916eacSRuslan Bukin 	VM_REG_GUEST_ZERO = 0,
60d3916eacSRuslan Bukin 	VM_REG_GUEST_RA,
61d3916eacSRuslan Bukin 	VM_REG_GUEST_SP,
62d3916eacSRuslan Bukin 	VM_REG_GUEST_GP,
63d3916eacSRuslan Bukin 	VM_REG_GUEST_TP,
64d3916eacSRuslan Bukin 	VM_REG_GUEST_T0,
65d3916eacSRuslan Bukin 	VM_REG_GUEST_T1,
66d3916eacSRuslan Bukin 	VM_REG_GUEST_T2,
67d3916eacSRuslan Bukin 	VM_REG_GUEST_S0,
68d3916eacSRuslan Bukin 	VM_REG_GUEST_S1,
69d3916eacSRuslan Bukin 	VM_REG_GUEST_A0,
70d3916eacSRuslan Bukin 	VM_REG_GUEST_A1,
71d3916eacSRuslan Bukin 	VM_REG_GUEST_A2,
72d3916eacSRuslan Bukin 	VM_REG_GUEST_A3,
73d3916eacSRuslan Bukin 	VM_REG_GUEST_A4,
74d3916eacSRuslan Bukin 	VM_REG_GUEST_A5,
75d3916eacSRuslan Bukin 	VM_REG_GUEST_A6,
76d3916eacSRuslan Bukin 	VM_REG_GUEST_A7,
77d3916eacSRuslan Bukin 	VM_REG_GUEST_S2,
78d3916eacSRuslan Bukin 	VM_REG_GUEST_S3,
79d3916eacSRuslan Bukin 	VM_REG_GUEST_S4,
80d3916eacSRuslan Bukin 	VM_REG_GUEST_S5,
81d3916eacSRuslan Bukin 	VM_REG_GUEST_S6,
82d3916eacSRuslan Bukin 	VM_REG_GUEST_S7,
83d3916eacSRuslan Bukin 	VM_REG_GUEST_S8,
84d3916eacSRuslan Bukin 	VM_REG_GUEST_S9,
85d3916eacSRuslan Bukin 	VM_REG_GUEST_S10,
86d3916eacSRuslan Bukin 	VM_REG_GUEST_S11,
87d3916eacSRuslan Bukin 	VM_REG_GUEST_T3,
88d3916eacSRuslan Bukin 	VM_REG_GUEST_T4,
89d3916eacSRuslan Bukin 	VM_REG_GUEST_T5,
90d3916eacSRuslan Bukin 	VM_REG_GUEST_T6,
91d3916eacSRuslan Bukin 	VM_REG_GUEST_SEPC,
92d3916eacSRuslan Bukin 	VM_REG_LAST
93d3916eacSRuslan Bukin };
94d3916eacSRuslan Bukin 
95d3916eacSRuslan Bukin #define	VM_INTINFO_VECTOR(info)	((info) & 0xff)
96d3916eacSRuslan Bukin #define	VM_INTINFO_DEL_ERRCODE	0x800
97d3916eacSRuslan Bukin #define	VM_INTINFO_RSVD		0x7ffff000
98d3916eacSRuslan Bukin #define	VM_INTINFO_VALID	0x80000000
99d3916eacSRuslan Bukin #define	VM_INTINFO_TYPE		0x700
100d3916eacSRuslan Bukin #define	VM_INTINFO_HWINTR	(0 << 8)
101d3916eacSRuslan Bukin #define	VM_INTINFO_NMI		(2 << 8)
102d3916eacSRuslan Bukin #define	VM_INTINFO_HWEXCEPTION	(3 << 8)
103d3916eacSRuslan Bukin #define	VM_INTINFO_SWINTR	(4 << 8)
104d3916eacSRuslan Bukin 
105043999b1SMark Johnston #define	VM_MAX_NAMELEN	32
106d3916eacSRuslan Bukin #define VM_MAX_SUFFIXLEN 15
107d3916eacSRuslan Bukin 
108d3916eacSRuslan Bukin #ifdef _KERNEL
109d3916eacSRuslan Bukin 
110d3916eacSRuslan Bukin struct vm;
111d3916eacSRuslan Bukin struct vm_exception;
112d3916eacSRuslan Bukin struct vm_exit;
113d3916eacSRuslan Bukin struct vm_run;
114d3916eacSRuslan Bukin struct vm_object;
115d3916eacSRuslan Bukin struct vm_guest_paging;
116d3916eacSRuslan Bukin struct vm_aplic_descr;
117d3916eacSRuslan Bukin struct pmap;
118d3916eacSRuslan Bukin 
119d3916eacSRuslan Bukin struct vm_eventinfo {
120d3916eacSRuslan Bukin 	void	*rptr;		/* rendezvous cookie */
121d3916eacSRuslan Bukin 	int	*sptr;		/* suspend cookie */
122d3916eacSRuslan Bukin 	int	*iptr;		/* reqidle cookie */
123d3916eacSRuslan Bukin };
124d3916eacSRuslan Bukin 
125d3916eacSRuslan Bukin int vm_create(const char *name, struct vm **retvm);
126d3916eacSRuslan Bukin struct vcpu *vm_alloc_vcpu(struct vm *vm, int vcpuid);
127d3916eacSRuslan Bukin void vm_disable_vcpu_creation(struct vm *vm);
128d3916eacSRuslan Bukin void vm_slock_vcpus(struct vm *vm);
129d3916eacSRuslan Bukin void vm_unlock_vcpus(struct vm *vm);
130d3916eacSRuslan Bukin void vm_destroy(struct vm *vm);
131d3916eacSRuslan Bukin int vm_reinit(struct vm *vm);
132d3916eacSRuslan Bukin const char *vm_name(struct vm *vm);
133d3916eacSRuslan Bukin 
134d3916eacSRuslan Bukin uint16_t vm_get_maxcpus(struct vm *vm);
135d3916eacSRuslan Bukin void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores,
136d3916eacSRuslan Bukin     uint16_t *threads, uint16_t *maxcpus);
137d3916eacSRuslan Bukin int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores,
138d3916eacSRuslan Bukin     uint16_t threads, uint16_t maxcpus);
139d3916eacSRuslan Bukin int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval);
140d3916eacSRuslan Bukin int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val);
141d3916eacSRuslan Bukin int vm_run(struct vcpu *vcpu);
142d3916eacSRuslan Bukin int vm_suspend(struct vm *vm, enum vm_suspend_how how);
143d3916eacSRuslan Bukin void* vm_get_cookie(struct vm *vm);
144d3916eacSRuslan Bukin int vcpu_vcpuid(struct vcpu *vcpu);
145d3916eacSRuslan Bukin void *vcpu_get_cookie(struct vcpu *vcpu);
146d3916eacSRuslan Bukin struct vm *vcpu_vm(struct vcpu *vcpu);
147d3916eacSRuslan Bukin struct vcpu *vm_vcpu(struct vm *vm, int cpu);
148d3916eacSRuslan Bukin int vm_get_capability(struct vcpu *vcpu, int type, int *val);
149d3916eacSRuslan Bukin int vm_set_capability(struct vcpu *vcpu, int type, int val);
150d3916eacSRuslan Bukin int vm_activate_cpu(struct vcpu *vcpu);
151d3916eacSRuslan Bukin int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu);
152d3916eacSRuslan Bukin int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu);
153d3916eacSRuslan Bukin int vm_inject_exception(struct vcpu *vcpu, uint64_t scause);
154d3916eacSRuslan Bukin int vm_attach_aplic(struct vm *vm, struct vm_aplic_descr *descr);
155d3916eacSRuslan Bukin int vm_assert_irq(struct vm *vm, uint32_t irq);
156d3916eacSRuslan Bukin int vm_deassert_irq(struct vm *vm, uint32_t irq);
157d3916eacSRuslan Bukin int vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot,
158d3916eacSRuslan Bukin     int func);
159d3916eacSRuslan Bukin struct vm_exit *vm_exitinfo(struct vcpu *vcpu);
160d3916eacSRuslan Bukin void vm_exit_suspended(struct vcpu *vcpu, uint64_t pc);
161d3916eacSRuslan Bukin void vm_exit_debug(struct vcpu *vcpu, uint64_t pc);
162d3916eacSRuslan Bukin void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t pc);
163d3916eacSRuslan Bukin void vm_exit_astpending(struct vcpu *vcpu, uint64_t pc);
164d3916eacSRuslan Bukin 
165d3916eacSRuslan Bukin cpuset_t vm_active_cpus(struct vm *vm);
166d3916eacSRuslan Bukin cpuset_t vm_debug_cpus(struct vm *vm);
167d3916eacSRuslan Bukin cpuset_t vm_suspended_cpus(struct vm *vm);
168d3916eacSRuslan Bukin 
169d3916eacSRuslan Bukin static __inline int
vcpu_rendezvous_pending(struct vm_eventinfo * info)170d3916eacSRuslan Bukin vcpu_rendezvous_pending(struct vm_eventinfo *info)
171d3916eacSRuslan Bukin {
172d3916eacSRuslan Bukin 
173d3916eacSRuslan Bukin 	return (*((uintptr_t *)(info->rptr)) != 0);
174d3916eacSRuslan Bukin }
175d3916eacSRuslan Bukin 
176d3916eacSRuslan Bukin static __inline int
vcpu_suspended(struct vm_eventinfo * info)177d3916eacSRuslan Bukin vcpu_suspended(struct vm_eventinfo *info)
178d3916eacSRuslan Bukin {
179d3916eacSRuslan Bukin 
180d3916eacSRuslan Bukin 	return (*info->sptr);
181d3916eacSRuslan Bukin }
182d3916eacSRuslan Bukin 
183d3916eacSRuslan Bukin int vcpu_debugged(struct vcpu *vcpu);
184d3916eacSRuslan Bukin 
185d3916eacSRuslan Bukin enum vcpu_state {
186d3916eacSRuslan Bukin 	VCPU_IDLE,
187d3916eacSRuslan Bukin 	VCPU_FROZEN,
188d3916eacSRuslan Bukin 	VCPU_RUNNING,
189d3916eacSRuslan Bukin 	VCPU_SLEEPING,
190d3916eacSRuslan Bukin };
191d3916eacSRuslan Bukin 
192d3916eacSRuslan Bukin int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle);
193d3916eacSRuslan Bukin enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu);
194d3916eacSRuslan Bukin 
195d3916eacSRuslan Bukin static int __inline
vcpu_is_running(struct vcpu * vcpu,int * hostcpu)196d3916eacSRuslan Bukin vcpu_is_running(struct vcpu *vcpu, int *hostcpu)
197d3916eacSRuslan Bukin {
198d3916eacSRuslan Bukin 	return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING);
199d3916eacSRuslan Bukin }
200d3916eacSRuslan Bukin 
201d3916eacSRuslan Bukin #ifdef _SYS_PROC_H_
202d3916eacSRuslan Bukin static int __inline
vcpu_should_yield(struct vcpu * vcpu)203d3916eacSRuslan Bukin vcpu_should_yield(struct vcpu *vcpu)
204d3916eacSRuslan Bukin {
205d3916eacSRuslan Bukin 	struct thread *td;
206d3916eacSRuslan Bukin 
207d3916eacSRuslan Bukin 	td = curthread;
208d3916eacSRuslan Bukin 	return (td->td_ast != 0 || td->td_owepreempt != 0);
209d3916eacSRuslan Bukin }
210d3916eacSRuslan Bukin #endif
211d3916eacSRuslan Bukin 
212d3916eacSRuslan Bukin void *vcpu_stats(struct vcpu *vcpu);
213d3916eacSRuslan Bukin void vcpu_notify_event(struct vcpu *vcpu);
214*c76c2a19SMark Johnston struct vmspace *vm_vmspace(struct vm *vm);
215*c76c2a19SMark Johnston struct vm_mem *vm_mem(struct vm *vm);
216d3916eacSRuslan Bukin 
217d3916eacSRuslan Bukin enum vm_reg_name vm_segment_name(int seg_encoding);
218d3916eacSRuslan Bukin 
219d3916eacSRuslan Bukin #endif	/* _KERNEL */
220d3916eacSRuslan Bukin 
221d3916eacSRuslan Bukin #define	VM_DIR_READ	0
222d3916eacSRuslan Bukin #define	VM_DIR_WRITE	1
223d3916eacSRuslan Bukin 
224d3916eacSRuslan Bukin #define	VM_GP_M_MASK		0x1f
225d3916eacSRuslan Bukin #define	VM_GP_MMU_ENABLED	(1 << 5)
226d3916eacSRuslan Bukin 
227d3916eacSRuslan Bukin struct vm_guest_paging {
228d3916eacSRuslan Bukin 	int		flags;
229d3916eacSRuslan Bukin 	int		padding;
230d3916eacSRuslan Bukin };
231d3916eacSRuslan Bukin 
232d3916eacSRuslan Bukin struct vie {
233d3916eacSRuslan Bukin 	uint8_t access_size:4, sign_extend:1, dir:1, unused:2;
234d3916eacSRuslan Bukin 	enum vm_reg_name reg;
235d3916eacSRuslan Bukin };
236d3916eacSRuslan Bukin 
237d3916eacSRuslan Bukin struct vre {
238d3916eacSRuslan Bukin 	uint32_t inst_syndrome;
239d3916eacSRuslan Bukin 	uint8_t dir:1, unused:7;
240d3916eacSRuslan Bukin 	enum vm_reg_name reg;
241d3916eacSRuslan Bukin };
242d3916eacSRuslan Bukin 
243d3916eacSRuslan Bukin /*
244d3916eacSRuslan Bukin  * Identifiers for optional vmm capabilities
245d3916eacSRuslan Bukin  */
246d3916eacSRuslan Bukin enum vm_cap_type {
247d3916eacSRuslan Bukin 	VM_CAP_UNRESTRICTED_GUEST,
248a7bf553dSRuslan Bukin 	VM_CAP_SSTC,
249d3916eacSRuslan Bukin 	VM_CAP_MAX
250d3916eacSRuslan Bukin };
251d3916eacSRuslan Bukin 
252d3916eacSRuslan Bukin enum vm_exitcode {
253d3916eacSRuslan Bukin 	VM_EXITCODE_BOGUS,
254d3916eacSRuslan Bukin 	VM_EXITCODE_ECALL,
255d3916eacSRuslan Bukin 	VM_EXITCODE_HYP,
256d3916eacSRuslan Bukin 	VM_EXITCODE_PAGING,
257d3916eacSRuslan Bukin 	VM_EXITCODE_SUSPENDED,
258d3916eacSRuslan Bukin 	VM_EXITCODE_DEBUG,
259d3916eacSRuslan Bukin 	VM_EXITCODE_INST_EMUL,
260d3916eacSRuslan Bukin 	VM_EXITCODE_WFI,
261d3916eacSRuslan Bukin 	VM_EXITCODE_MAX
262d3916eacSRuslan Bukin };
263d3916eacSRuslan Bukin 
264d3916eacSRuslan Bukin struct vm_exit {
265d3916eacSRuslan Bukin 	uint64_t scause;
266d3916eacSRuslan Bukin 	uint64_t sepc;
267d3916eacSRuslan Bukin 	uint64_t stval;
268d3916eacSRuslan Bukin 	uint64_t htval;
269d3916eacSRuslan Bukin 	uint64_t htinst;
270d3916eacSRuslan Bukin 	enum vm_exitcode exitcode;
271d3916eacSRuslan Bukin 	int inst_length;
272d3916eacSRuslan Bukin 	uint64_t pc;
273d3916eacSRuslan Bukin 	union {
274d3916eacSRuslan Bukin 		struct {
275d3916eacSRuslan Bukin 			uint64_t gpa;
276d3916eacSRuslan Bukin 		} paging;
277d3916eacSRuslan Bukin 
278d3916eacSRuslan Bukin 		struct {
279d3916eacSRuslan Bukin 			uint64_t gpa;
280d3916eacSRuslan Bukin 			struct vm_guest_paging paging;
281d3916eacSRuslan Bukin 			struct vie vie;
282d3916eacSRuslan Bukin 		} inst_emul;
283d3916eacSRuslan Bukin 
284d3916eacSRuslan Bukin 		struct {
285d3916eacSRuslan Bukin 			uint64_t args[8];
286d3916eacSRuslan Bukin 		} ecall;
287d3916eacSRuslan Bukin 
288d3916eacSRuslan Bukin 		struct {
289d3916eacSRuslan Bukin 			enum vm_suspend_how how;
290d3916eacSRuslan Bukin 		} suspended;
291d3916eacSRuslan Bukin 
292d3916eacSRuslan Bukin 		struct {
293d3916eacSRuslan Bukin 			uint64_t scause;
294d3916eacSRuslan Bukin 		} hyp;
295d3916eacSRuslan Bukin 	} u;
296d3916eacSRuslan Bukin };
297d3916eacSRuslan Bukin 
298d3916eacSRuslan Bukin #endif	/* _VMM_H_ */
299