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