1 /* $OpenBSD: vmm.h,v 1.7 2024/08/27 09:16:03 bluhm Exp $ */ 2 /* 3 * Copyright (c) 2014-2023 Mike Larkin <mlarkin@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/rwlock.h> 19 #include <sys/refcnt.h> 20 21 #include <uvm/uvm_extern.h> 22 23 #include <machine/vmmvar.h> 24 25 #ifndef DEV_VMM_H 26 #define DEV_VMM_H 27 28 #define VMM_MAX_MEM_RANGES 16 29 #define VMM_MAX_DISKS_PER_VM 4 30 #define VMM_MAX_NAME_LEN 64 31 #define VMM_MAX_VCPUS 512 32 #define VMM_MAX_VCPUS_PER_VM 64 33 #define VMM_MAX_VM_MEM_SIZE 128L * 1024 * 1024 * 1024 34 #define VMM_MAX_NICS_PER_VM 4 35 36 struct vm_mem_range { 37 paddr_t vmr_gpa; 38 vaddr_t vmr_va; 39 size_t vmr_size; 40 int vmr_type; 41 #define VM_MEM_RAM 0 /* Presented as usable system memory. */ 42 #define VM_MEM_RESERVED 1 /* Reserved for BIOS, etc. */ 43 #define VM_MEM_MMIO 2 /* Special region for device mmio. */ 44 }; 45 46 struct vm_create_params { 47 /* Input parameters to VMM_IOC_CREATE */ 48 size_t vcp_nmemranges; 49 size_t vcp_ncpus; 50 struct vm_mem_range vcp_memranges[VMM_MAX_MEM_RANGES]; 51 char vcp_name[VMM_MAX_NAME_LEN]; 52 int vcp_sev; 53 54 /* Output parameter from VMM_IOC_CREATE */ 55 uint32_t vcp_id; 56 uint32_t vcp_poscbit; 57 uint32_t vcp_asid[VMM_MAX_VCPUS]; 58 }; 59 60 struct vm_info_result { 61 /* Output parameters from VMM_IOC_INFO */ 62 size_t vir_memory_size; 63 size_t vir_used_size; 64 size_t vir_ncpus; 65 uint8_t vir_vcpu_state[VMM_MAX_VCPUS_PER_VM]; 66 pid_t vir_creator_pid; 67 uint32_t vir_id; 68 char vir_name[VMM_MAX_NAME_LEN]; 69 }; 70 71 struct vm_info_params { 72 /* Input parameters to VMM_IOC_INFO */ 73 size_t vip_size; /* Output buffer size */ 74 75 /* Output Parameters from VMM_IOC_INFO */ 76 size_t vip_info_ct; /* # of entries returned */ 77 struct vm_info_result *vip_info; /* Output buffer */ 78 }; 79 80 struct vm_terminate_params { 81 /* Input parameters to VMM_IOC_TERM */ 82 uint32_t vtp_vm_id; 83 }; 84 85 struct vm_resetcpu_params { 86 /* Input parameters to VMM_IOC_RESETCPU */ 87 uint32_t vrp_vm_id; 88 uint32_t vrp_vcpu_id; 89 struct vcpu_reg_state vrp_init_state; 90 }; 91 92 struct vm_sharemem_params { 93 /* Input parameters to VMM_IOC_SHAREMEM */ 94 uint32_t vsp_vm_id; 95 size_t vsp_nmemranges; 96 struct vm_mem_range vsp_memranges[VMM_MAX_MEM_RANGES]; 97 }; 98 99 struct vm_run_params { 100 /* Input parameters to VMM_IOC_RUN */ 101 uint32_t vrp_vm_id; 102 uint32_t vrp_vcpu_id; 103 struct vcpu_inject_event vrp_inject; 104 uint8_t vrp_intr_pending; /* Additional intrs pending? */ 105 106 /* Input/output parameter to VMM_IOC_RUN */ 107 struct vm_exit *vrp_exit; /* updated exit data */ 108 109 /* Output parameter from VMM_IOC_RUN */ 110 uint16_t vrp_exit_reason; /* exit reason */ 111 uint8_t vrp_irqready; /* ready for IRQ on entry */ 112 }; 113 114 #define VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA 0x1 /* read/write pvclock gpa */ 115 #define VM_RWVMPARAMS_PVCLOCK_VERSION 0x2 /* read/write pvclock version */ 116 #define VM_RWVMPARAMS_ALL (VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA | \ 117 VM_RWVMPARAMS_PVCLOCK_VERSION) 118 119 struct vm_rwvmparams_params { 120 /* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */ 121 uint32_t vpp_vm_id; 122 uint32_t vpp_vcpu_id; 123 uint32_t vpp_mask; 124 paddr_t vpp_pvclock_system_gpa; 125 uint32_t vpp_pvclock_version; 126 }; 127 128 /* IOCTL definitions */ 129 #define VMM_IOC_CREATE _IOWR('V', 1, struct vm_create_params) /* Create VM */ 130 #define VMM_IOC_RUN _IOWR('V', 2, struct vm_run_params) /* Run VCPU */ 131 #define VMM_IOC_INFO _IOWR('V', 3, struct vm_info_params) /* Get VM Info */ 132 #define VMM_IOC_TERM _IOW('V', 4, struct vm_terminate_params) /* Terminate VM */ 133 #define VMM_IOC_RESETCPU _IOW('V', 5, struct vm_resetcpu_params) /* Reset */ 134 #define VMM_IOC_READREGS _IOWR('V', 7, struct vm_rwregs_params) /* Get regs */ 135 #define VMM_IOC_WRITEREGS _IOW('V', 8, struct vm_rwregs_params) /* Set regs */ 136 /* Get VM params */ 137 #define VMM_IOC_READVMPARAMS _IOWR('V', 9, struct vm_rwvmparams_params) 138 /* Set VM params */ 139 #define VMM_IOC_WRITEVMPARAMS _IOW('V', 10, struct vm_rwvmparams_params) 140 #define VMM_IOC_SHAREMEM _IOW('V', 11, struct vm_sharemem_params) 141 142 #ifdef _KERNEL 143 144 /* #define VMM_DEBUG */ 145 146 #ifdef VMM_DEBUG 147 #define DPRINTF(x...) do { printf(x); } while(0) 148 #else 149 #define DPRINTF(x...) 150 #endif /* VMM_DEBUG */ 151 enum { 152 VCPU_STATE_STOPPED, 153 VCPU_STATE_RUNNING, 154 VCPU_STATE_REQTERM, 155 VCPU_STATE_TERMINATED, 156 VCPU_STATE_UNKNOWN, 157 }; 158 159 /* 160 * Virtual Machine 161 * 162 * Methods used to protect vm struct members: 163 * a atomic operations 164 * I immutable after create 165 * K kernel lock 166 * r reference count 167 * v vcpu list rwlock (vm_vcpu_list) 168 * V vmm_softc's vm_lock 169 */ 170 struct vm { 171 struct vmspace *vm_vmspace; /* [K] */ 172 vm_map_t vm_map; /* [K] */ 173 uint32_t vm_id; /* [I] */ 174 pid_t vm_creator_pid; /* [I] */ 175 size_t vm_nmemranges; /* [I] */ 176 size_t vm_memory_size; /* [I] */ 177 char vm_name[VMM_MAX_NAME_LEN]; 178 struct vm_mem_range vm_memranges[VMM_MAX_MEM_RANGES]; 179 struct refcnt vm_refcnt; /* [a] */ 180 181 struct vcpu_head vm_vcpu_list; /* [v] */ 182 uint32_t vm_vcpu_ct; /* [v] */ 183 struct rwlock vm_vcpu_lock; 184 185 SLIST_ENTRY(vm) vm_link; /* [V] */ 186 }; 187 188 SLIST_HEAD(vmlist_head, vm); 189 190 /* 191 * Virtual Machine Monitor 192 * 193 * Methods used to protect struct members in the global vmm device: 194 * a atomic opererations 195 * I immutable operations 196 * K kernel lock 197 * p virtual process id (vpid/asid) rwlock 198 * r reference count 199 * v vm list rwlock (vm_lock) 200 */ 201 struct vmm_softc { 202 struct device sc_dev; /* [r] */ 203 204 /* Suspend/Resume Synchronization */ 205 struct rwlock sc_slock; 206 struct refcnt sc_refcnt; 207 volatile unsigned int sc_status; /* [a] */ 208 #define VMM_SUSPENDED (unsigned int) 0 209 #define VMM_ACTIVE (unsigned int) 1 210 211 struct vmm_softc_md sc_md; 212 213 /* Managed VMs */ 214 struct vmlist_head vm_list; /* [v] */ 215 216 int mode; /* [I] */ 217 218 size_t vcpu_ct; /* [v] */ 219 size_t vcpu_max; /* [I] */ 220 221 struct rwlock vm_lock; 222 size_t vm_ct; /* [v] no. of in-memory VMs */ 223 size_t vm_idx; /* [a] next unique VM index */ 224 225 struct rwlock vpid_lock; 226 uint16_t max_vpid; /* [I] */ 227 uint8_t vpids[512]; /* [p] bitmap of VPID/ASIDs */ 228 }; 229 230 int vmm_probe(struct device *, void *, void *); 231 int vmm_activate(struct device *, int); 232 void vmm_attach(struct device *, struct device *, void *); 233 int vmmopen(dev_t, int, int, struct proc *); 234 int vmmclose(dev_t, int, int, struct proc *); 235 int vm_find(uint32_t, struct vm **); 236 int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *); 237 int pledge_ioctl_vmm(struct proc *, long); 238 struct vcpu *vm_find_vcpu(struct vm *, uint32_t); 239 int vm_create(struct vm_create_params *, struct proc *); 240 size_t vm_create_check_mem_ranges(struct vm_create_params *); 241 void vm_teardown(struct vm **); 242 int vm_get_info(struct vm_info_params *); 243 int vm_terminate(struct vm_terminate_params *); 244 int vm_resetcpu(struct vm_resetcpu_params *); 245 int vm_rwvmparams(struct vm_rwvmparams_params *, int); 246 int vcpu_must_stop(struct vcpu *); 247 int vm_share_mem(struct vm_sharemem_params *, struct proc *); 248 int vm_run(struct vm_run_params *); 249 250 #ifdef VMM_DEBUG 251 void dump_vcpu(struct vcpu *); 252 #endif 253 254 #endif /* _KERNEL */ 255 #endif /* DEV_VMM_H */ 256