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 105*043999b1SMark 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 /* 135d3916eacSRuslan Bukin * APIs that modify the guest memory map require all vcpus to be frozen. 136d3916eacSRuslan Bukin */ 137d3916eacSRuslan Bukin void vm_slock_memsegs(struct vm *vm); 138d3916eacSRuslan Bukin void vm_xlock_memsegs(struct vm *vm); 139d3916eacSRuslan Bukin void vm_unlock_memsegs(struct vm *vm); 140d3916eacSRuslan Bukin int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off, 141d3916eacSRuslan Bukin size_t len, int prot, int flags); 142d3916eacSRuslan Bukin int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len); 143d3916eacSRuslan Bukin int vm_alloc_memseg(struct vm *vm, int ident, size_t len, bool sysmem); 144d3916eacSRuslan Bukin void vm_free_memseg(struct vm *vm, int ident); 145d3916eacSRuslan Bukin 146d3916eacSRuslan Bukin /* 147d3916eacSRuslan Bukin * APIs that inspect the guest memory map require only a *single* vcpu to 148d3916eacSRuslan Bukin * be frozen. This acts like a read lock on the guest memory map since any 149d3916eacSRuslan Bukin * modification requires *all* vcpus to be frozen. 150d3916eacSRuslan Bukin */ 151d3916eacSRuslan Bukin int vm_mmap_getnext(struct vm *vm, vm_paddr_t *gpa, int *segid, 152d3916eacSRuslan Bukin vm_ooffset_t *segoff, size_t *len, int *prot, int *flags); 153d3916eacSRuslan Bukin int vm_get_memseg(struct vm *vm, int ident, size_t *len, bool *sysmem, 154d3916eacSRuslan Bukin struct vm_object **objptr); 155d3916eacSRuslan Bukin vm_paddr_t vmm_sysmem_maxaddr(struct vm *vm); 156d3916eacSRuslan Bukin void *vm_gpa_hold(struct vcpu *vcpu, vm_paddr_t gpa, size_t len, 157d3916eacSRuslan Bukin int prot, void **cookie); 158d3916eacSRuslan Bukin void *vm_gpa_hold_global(struct vm *vm, vm_paddr_t gpa, size_t len, 159d3916eacSRuslan Bukin int prot, void **cookie); 160d3916eacSRuslan Bukin void vm_gpa_release(void *cookie); 161d3916eacSRuslan Bukin bool vm_mem_allocated(struct vcpu *vcpu, vm_paddr_t gpa); 162d3916eacSRuslan Bukin 163d3916eacSRuslan Bukin int vm_gla2gpa_nofault(struct vcpu *vcpu, struct vm_guest_paging *paging, 164d3916eacSRuslan Bukin uint64_t gla, int prot, uint64_t *gpa, int *is_fault); 165d3916eacSRuslan Bukin 166d3916eacSRuslan Bukin uint16_t vm_get_maxcpus(struct vm *vm); 167d3916eacSRuslan Bukin void vm_get_topology(struct vm *vm, uint16_t *sockets, uint16_t *cores, 168d3916eacSRuslan Bukin uint16_t *threads, uint16_t *maxcpus); 169d3916eacSRuslan Bukin int vm_set_topology(struct vm *vm, uint16_t sockets, uint16_t cores, 170d3916eacSRuslan Bukin uint16_t threads, uint16_t maxcpus); 171d3916eacSRuslan Bukin int vm_get_register(struct vcpu *vcpu, int reg, uint64_t *retval); 172d3916eacSRuslan Bukin int vm_set_register(struct vcpu *vcpu, int reg, uint64_t val); 173d3916eacSRuslan Bukin int vm_run(struct vcpu *vcpu); 174d3916eacSRuslan Bukin int vm_suspend(struct vm *vm, enum vm_suspend_how how); 175d3916eacSRuslan Bukin void* vm_get_cookie(struct vm *vm); 176d3916eacSRuslan Bukin int vcpu_vcpuid(struct vcpu *vcpu); 177d3916eacSRuslan Bukin void *vcpu_get_cookie(struct vcpu *vcpu); 178d3916eacSRuslan Bukin struct vm *vcpu_vm(struct vcpu *vcpu); 179d3916eacSRuslan Bukin struct vcpu *vm_vcpu(struct vm *vm, int cpu); 180d3916eacSRuslan Bukin int vm_get_capability(struct vcpu *vcpu, int type, int *val); 181d3916eacSRuslan Bukin int vm_set_capability(struct vcpu *vcpu, int type, int val); 182d3916eacSRuslan Bukin int vm_activate_cpu(struct vcpu *vcpu); 183d3916eacSRuslan Bukin int vm_suspend_cpu(struct vm *vm, struct vcpu *vcpu); 184d3916eacSRuslan Bukin int vm_resume_cpu(struct vm *vm, struct vcpu *vcpu); 185d3916eacSRuslan Bukin int vm_inject_exception(struct vcpu *vcpu, uint64_t scause); 186d3916eacSRuslan Bukin int vm_attach_aplic(struct vm *vm, struct vm_aplic_descr *descr); 187d3916eacSRuslan Bukin int vm_assert_irq(struct vm *vm, uint32_t irq); 188d3916eacSRuslan Bukin int vm_deassert_irq(struct vm *vm, uint32_t irq); 189d3916eacSRuslan Bukin int vm_raise_msi(struct vm *vm, uint64_t msg, uint64_t addr, int bus, int slot, 190d3916eacSRuslan Bukin int func); 191d3916eacSRuslan Bukin struct vm_exit *vm_exitinfo(struct vcpu *vcpu); 192d3916eacSRuslan Bukin void vm_exit_suspended(struct vcpu *vcpu, uint64_t pc); 193d3916eacSRuslan Bukin void vm_exit_debug(struct vcpu *vcpu, uint64_t pc); 194d3916eacSRuslan Bukin void vm_exit_rendezvous(struct vcpu *vcpu, uint64_t pc); 195d3916eacSRuslan Bukin void vm_exit_astpending(struct vcpu *vcpu, uint64_t pc); 196d3916eacSRuslan Bukin 197d3916eacSRuslan Bukin cpuset_t vm_active_cpus(struct vm *vm); 198d3916eacSRuslan Bukin cpuset_t vm_debug_cpus(struct vm *vm); 199d3916eacSRuslan Bukin cpuset_t vm_suspended_cpus(struct vm *vm); 200d3916eacSRuslan Bukin 201d3916eacSRuslan Bukin static __inline int 202d3916eacSRuslan Bukin vcpu_rendezvous_pending(struct vm_eventinfo *info) 203d3916eacSRuslan Bukin { 204d3916eacSRuslan Bukin 205d3916eacSRuslan Bukin return (*((uintptr_t *)(info->rptr)) != 0); 206d3916eacSRuslan Bukin } 207d3916eacSRuslan Bukin 208d3916eacSRuslan Bukin static __inline int 209d3916eacSRuslan Bukin vcpu_suspended(struct vm_eventinfo *info) 210d3916eacSRuslan Bukin { 211d3916eacSRuslan Bukin 212d3916eacSRuslan Bukin return (*info->sptr); 213d3916eacSRuslan Bukin } 214d3916eacSRuslan Bukin 215d3916eacSRuslan Bukin int vcpu_debugged(struct vcpu *vcpu); 216d3916eacSRuslan Bukin 217d3916eacSRuslan Bukin enum vcpu_state { 218d3916eacSRuslan Bukin VCPU_IDLE, 219d3916eacSRuslan Bukin VCPU_FROZEN, 220d3916eacSRuslan Bukin VCPU_RUNNING, 221d3916eacSRuslan Bukin VCPU_SLEEPING, 222d3916eacSRuslan Bukin }; 223d3916eacSRuslan Bukin 224d3916eacSRuslan Bukin int vcpu_set_state(struct vcpu *vcpu, enum vcpu_state state, bool from_idle); 225d3916eacSRuslan Bukin enum vcpu_state vcpu_get_state(struct vcpu *vcpu, int *hostcpu); 226d3916eacSRuslan Bukin 227d3916eacSRuslan Bukin static int __inline 228d3916eacSRuslan Bukin vcpu_is_running(struct vcpu *vcpu, int *hostcpu) 229d3916eacSRuslan Bukin { 230d3916eacSRuslan Bukin return (vcpu_get_state(vcpu, hostcpu) == VCPU_RUNNING); 231d3916eacSRuslan Bukin } 232d3916eacSRuslan Bukin 233d3916eacSRuslan Bukin #ifdef _SYS_PROC_H_ 234d3916eacSRuslan Bukin static int __inline 235d3916eacSRuslan Bukin vcpu_should_yield(struct vcpu *vcpu) 236d3916eacSRuslan Bukin { 237d3916eacSRuslan Bukin struct thread *td; 238d3916eacSRuslan Bukin 239d3916eacSRuslan Bukin td = curthread; 240d3916eacSRuslan Bukin return (td->td_ast != 0 || td->td_owepreempt != 0); 241d3916eacSRuslan Bukin } 242d3916eacSRuslan Bukin #endif 243d3916eacSRuslan Bukin 244d3916eacSRuslan Bukin void *vcpu_stats(struct vcpu *vcpu); 245d3916eacSRuslan Bukin void vcpu_notify_event(struct vcpu *vcpu); 246d3916eacSRuslan Bukin 247d3916eacSRuslan Bukin enum vm_reg_name vm_segment_name(int seg_encoding); 248d3916eacSRuslan Bukin 249d3916eacSRuslan Bukin #endif /* _KERNEL */ 250d3916eacSRuslan Bukin 251d3916eacSRuslan Bukin #define VM_DIR_READ 0 252d3916eacSRuslan Bukin #define VM_DIR_WRITE 1 253d3916eacSRuslan Bukin 254d3916eacSRuslan Bukin #define VM_GP_M_MASK 0x1f 255d3916eacSRuslan Bukin #define VM_GP_MMU_ENABLED (1 << 5) 256d3916eacSRuslan Bukin 257d3916eacSRuslan Bukin struct vm_guest_paging { 258d3916eacSRuslan Bukin int flags; 259d3916eacSRuslan Bukin int padding; 260d3916eacSRuslan Bukin }; 261d3916eacSRuslan Bukin 262d3916eacSRuslan Bukin struct vie { 263d3916eacSRuslan Bukin uint8_t access_size:4, sign_extend:1, dir:1, unused:2; 264d3916eacSRuslan Bukin enum vm_reg_name reg; 265d3916eacSRuslan Bukin }; 266d3916eacSRuslan Bukin 267d3916eacSRuslan Bukin struct vre { 268d3916eacSRuslan Bukin uint32_t inst_syndrome; 269d3916eacSRuslan Bukin uint8_t dir:1, unused:7; 270d3916eacSRuslan Bukin enum vm_reg_name reg; 271d3916eacSRuslan Bukin }; 272d3916eacSRuslan Bukin 273d3916eacSRuslan Bukin /* 274d3916eacSRuslan Bukin * Identifiers for optional vmm capabilities 275d3916eacSRuslan Bukin */ 276d3916eacSRuslan Bukin enum vm_cap_type { 277d3916eacSRuslan Bukin VM_CAP_UNRESTRICTED_GUEST, 278d3916eacSRuslan Bukin VM_CAP_MAX 279d3916eacSRuslan Bukin }; 280d3916eacSRuslan Bukin 281d3916eacSRuslan Bukin enum vm_exitcode { 282d3916eacSRuslan Bukin VM_EXITCODE_BOGUS, 283d3916eacSRuslan Bukin VM_EXITCODE_ECALL, 284d3916eacSRuslan Bukin VM_EXITCODE_HYP, 285d3916eacSRuslan Bukin VM_EXITCODE_PAGING, 286d3916eacSRuslan Bukin VM_EXITCODE_SUSPENDED, 287d3916eacSRuslan Bukin VM_EXITCODE_DEBUG, 288d3916eacSRuslan Bukin VM_EXITCODE_INST_EMUL, 289d3916eacSRuslan Bukin VM_EXITCODE_WFI, 290d3916eacSRuslan Bukin VM_EXITCODE_MAX 291d3916eacSRuslan Bukin }; 292d3916eacSRuslan Bukin 293d3916eacSRuslan Bukin struct vm_exit { 294d3916eacSRuslan Bukin uint64_t scause; 295d3916eacSRuslan Bukin uint64_t sepc; 296d3916eacSRuslan Bukin uint64_t stval; 297d3916eacSRuslan Bukin uint64_t htval; 298d3916eacSRuslan Bukin uint64_t htinst; 299d3916eacSRuslan Bukin enum vm_exitcode exitcode; 300d3916eacSRuslan Bukin int inst_length; 301d3916eacSRuslan Bukin uint64_t pc; 302d3916eacSRuslan Bukin union { 303d3916eacSRuslan Bukin struct { 304d3916eacSRuslan Bukin uint64_t gpa; 305d3916eacSRuslan Bukin } paging; 306d3916eacSRuslan Bukin 307d3916eacSRuslan Bukin struct { 308d3916eacSRuslan Bukin uint64_t gpa; 309d3916eacSRuslan Bukin struct vm_guest_paging paging; 310d3916eacSRuslan Bukin struct vie vie; 311d3916eacSRuslan Bukin } inst_emul; 312d3916eacSRuslan Bukin 313d3916eacSRuslan Bukin struct { 314d3916eacSRuslan Bukin uint64_t args[8]; 315d3916eacSRuslan Bukin } ecall; 316d3916eacSRuslan Bukin 317d3916eacSRuslan Bukin struct { 318d3916eacSRuslan Bukin enum vm_suspend_how how; 319d3916eacSRuslan Bukin } suspended; 320d3916eacSRuslan Bukin 321d3916eacSRuslan Bukin struct { 322d3916eacSRuslan Bukin uint64_t scause; 323d3916eacSRuslan Bukin } hyp; 324d3916eacSRuslan Bukin } u; 325d3916eacSRuslan Bukin }; 326d3916eacSRuslan Bukin 327d3916eacSRuslan Bukin #endif /* _VMM_H_ */ 328