1*ebaf145fSbluhm /* $OpenBSD: vmm.h,v 1.7 2024/08/27 09:16:03 bluhm Exp $ */ 23a0db596Smlarkin /* 33a0db596Smlarkin * Copyright (c) 2014-2023 Mike Larkin <mlarkin@openbsd.org> 43a0db596Smlarkin * 53a0db596Smlarkin * Permission to use, copy, modify, and distribute this software for any 63a0db596Smlarkin * purpose with or without fee is hereby granted, provided that the above 73a0db596Smlarkin * copyright notice and this permission notice appear in all copies. 83a0db596Smlarkin * 93a0db596Smlarkin * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 103a0db596Smlarkin * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 113a0db596Smlarkin * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 123a0db596Smlarkin * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 133a0db596Smlarkin * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 143a0db596Smlarkin * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 153a0db596Smlarkin * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 163a0db596Smlarkin */ 173a0db596Smlarkin 183a0db596Smlarkin #include <sys/rwlock.h> 193a0db596Smlarkin #include <sys/refcnt.h> 203a0db596Smlarkin 213a0db596Smlarkin #include <uvm/uvm_extern.h> 223a0db596Smlarkin 23ba66f564Sdv #include <machine/vmmvar.h> 24ba66f564Sdv 2525f7c0b5Smlarkin #ifndef DEV_VMM_H 2625f7c0b5Smlarkin #define DEV_VMM_H 2725f7c0b5Smlarkin 28ba66f564Sdv #define VMM_MAX_MEM_RANGES 16 29ba66f564Sdv #define VMM_MAX_DISKS_PER_VM 4 30ba66f564Sdv #define VMM_MAX_NAME_LEN 64 31ba66f564Sdv #define VMM_MAX_VCPUS 512 32ba66f564Sdv #define VMM_MAX_VCPUS_PER_VM 64 33ba66f564Sdv #define VMM_MAX_VM_MEM_SIZE 128L * 1024 * 1024 * 1024 34ba66f564Sdv #define VMM_MAX_NICS_PER_VM 4 35ba66f564Sdv 3625f7c0b5Smlarkin struct vm_mem_range { 3725f7c0b5Smlarkin paddr_t vmr_gpa; 3825f7c0b5Smlarkin vaddr_t vmr_va; 3925f7c0b5Smlarkin size_t vmr_size; 4025f7c0b5Smlarkin int vmr_type; 4125f7c0b5Smlarkin #define VM_MEM_RAM 0 /* Presented as usable system memory. */ 4225f7c0b5Smlarkin #define VM_MEM_RESERVED 1 /* Reserved for BIOS, etc. */ 4325f7c0b5Smlarkin #define VM_MEM_MMIO 2 /* Special region for device mmio. */ 4425f7c0b5Smlarkin }; 4525f7c0b5Smlarkin 4625f7c0b5Smlarkin struct vm_create_params { 4725f7c0b5Smlarkin /* Input parameters to VMM_IOC_CREATE */ 4825f7c0b5Smlarkin size_t vcp_nmemranges; 4925f7c0b5Smlarkin size_t vcp_ncpus; 5025f7c0b5Smlarkin struct vm_mem_range vcp_memranges[VMM_MAX_MEM_RANGES]; 5125f7c0b5Smlarkin char vcp_name[VMM_MAX_NAME_LEN]; 52*ebaf145fSbluhm int vcp_sev; 5325f7c0b5Smlarkin 5425f7c0b5Smlarkin /* Output parameter from VMM_IOC_CREATE */ 5525f7c0b5Smlarkin uint32_t vcp_id; 56*ebaf145fSbluhm uint32_t vcp_poscbit; 57*ebaf145fSbluhm uint32_t vcp_asid[VMM_MAX_VCPUS]; 5825f7c0b5Smlarkin }; 5925f7c0b5Smlarkin 6025f7c0b5Smlarkin struct vm_info_result { 6125f7c0b5Smlarkin /* Output parameters from VMM_IOC_INFO */ 6225f7c0b5Smlarkin size_t vir_memory_size; 6325f7c0b5Smlarkin size_t vir_used_size; 6425f7c0b5Smlarkin size_t vir_ncpus; 6525f7c0b5Smlarkin uint8_t vir_vcpu_state[VMM_MAX_VCPUS_PER_VM]; 6625f7c0b5Smlarkin pid_t vir_creator_pid; 6725f7c0b5Smlarkin uint32_t vir_id; 6825f7c0b5Smlarkin char vir_name[VMM_MAX_NAME_LEN]; 6925f7c0b5Smlarkin }; 7025f7c0b5Smlarkin 7125f7c0b5Smlarkin struct vm_info_params { 7225f7c0b5Smlarkin /* Input parameters to VMM_IOC_INFO */ 7325f7c0b5Smlarkin size_t vip_size; /* Output buffer size */ 7425f7c0b5Smlarkin 7525f7c0b5Smlarkin /* Output Parameters from VMM_IOC_INFO */ 7625f7c0b5Smlarkin size_t vip_info_ct; /* # of entries returned */ 7725f7c0b5Smlarkin struct vm_info_result *vip_info; /* Output buffer */ 7825f7c0b5Smlarkin }; 7925f7c0b5Smlarkin 8025f7c0b5Smlarkin struct vm_terminate_params { 8125f7c0b5Smlarkin /* Input parameters to VMM_IOC_TERM */ 8225f7c0b5Smlarkin uint32_t vtp_vm_id; 8325f7c0b5Smlarkin }; 8425f7c0b5Smlarkin 8525f7c0b5Smlarkin struct vm_resetcpu_params { 8625f7c0b5Smlarkin /* Input parameters to VMM_IOC_RESETCPU */ 8725f7c0b5Smlarkin uint32_t vrp_vm_id; 8825f7c0b5Smlarkin uint32_t vrp_vcpu_id; 8925f7c0b5Smlarkin struct vcpu_reg_state vrp_init_state; 9025f7c0b5Smlarkin }; 9125f7c0b5Smlarkin 923c817da7Sdv struct vm_sharemem_params { 933c817da7Sdv /* Input parameters to VMM_IOC_SHAREMEM */ 943c817da7Sdv uint32_t vsp_vm_id; 953c817da7Sdv size_t vsp_nmemranges; 963c817da7Sdv struct vm_mem_range vsp_memranges[VMM_MAX_MEM_RANGES]; 973c817da7Sdv }; 983c817da7Sdv 99ba66f564Sdv struct vm_run_params { 100ba66f564Sdv /* Input parameters to VMM_IOC_RUN */ 101ba66f564Sdv uint32_t vrp_vm_id; 102ba66f564Sdv uint32_t vrp_vcpu_id; 103ba66f564Sdv struct vcpu_inject_event vrp_inject; 104ba66f564Sdv uint8_t vrp_intr_pending; /* Additional intrs pending? */ 105ba66f564Sdv 106ba66f564Sdv /* Input/output parameter to VMM_IOC_RUN */ 107ba66f564Sdv struct vm_exit *vrp_exit; /* updated exit data */ 108ba66f564Sdv 109ba66f564Sdv /* Output parameter from VMM_IOC_RUN */ 110ba66f564Sdv uint16_t vrp_exit_reason; /* exit reason */ 111ba66f564Sdv uint8_t vrp_irqready; /* ready for IRQ on entry */ 112ba66f564Sdv }; 113ba66f564Sdv 114234ee546Sdv #define VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA 0x1 /* read/write pvclock gpa */ 115234ee546Sdv #define VM_RWVMPARAMS_PVCLOCK_VERSION 0x2 /* read/write pvclock version */ 116234ee546Sdv #define VM_RWVMPARAMS_ALL (VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA | \ 117234ee546Sdv VM_RWVMPARAMS_PVCLOCK_VERSION) 118234ee546Sdv 119234ee546Sdv struct vm_rwvmparams_params { 120234ee546Sdv /* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */ 121234ee546Sdv uint32_t vpp_vm_id; 122234ee546Sdv uint32_t vpp_vcpu_id; 123234ee546Sdv uint32_t vpp_mask; 124234ee546Sdv paddr_t vpp_pvclock_system_gpa; 125234ee546Sdv uint32_t vpp_pvclock_version; 126234ee546Sdv }; 127234ee546Sdv 12825f7c0b5Smlarkin /* IOCTL definitions */ 12925f7c0b5Smlarkin #define VMM_IOC_CREATE _IOWR('V', 1, struct vm_create_params) /* Create VM */ 13025f7c0b5Smlarkin #define VMM_IOC_RUN _IOWR('V', 2, struct vm_run_params) /* Run VCPU */ 13125f7c0b5Smlarkin #define VMM_IOC_INFO _IOWR('V', 3, struct vm_info_params) /* Get VM Info */ 13225f7c0b5Smlarkin #define VMM_IOC_TERM _IOW('V', 4, struct vm_terminate_params) /* Terminate VM */ 13325f7c0b5Smlarkin #define VMM_IOC_RESETCPU _IOW('V', 5, struct vm_resetcpu_params) /* Reset */ 13425f7c0b5Smlarkin #define VMM_IOC_READREGS _IOWR('V', 7, struct vm_rwregs_params) /* Get regs */ 13525f7c0b5Smlarkin #define VMM_IOC_WRITEREGS _IOW('V', 8, struct vm_rwregs_params) /* Set regs */ 13625f7c0b5Smlarkin /* Get VM params */ 13725f7c0b5Smlarkin #define VMM_IOC_READVMPARAMS _IOWR('V', 9, struct vm_rwvmparams_params) 13825f7c0b5Smlarkin /* Set VM params */ 13925f7c0b5Smlarkin #define VMM_IOC_WRITEVMPARAMS _IOW('V', 10, struct vm_rwvmparams_params) 1403c817da7Sdv #define VMM_IOC_SHAREMEM _IOW('V', 11, struct vm_sharemem_params) 14125f7c0b5Smlarkin 14225f7c0b5Smlarkin #ifdef _KERNEL 14325f7c0b5Smlarkin 1443a0db596Smlarkin /* #define VMM_DEBUG */ 1453a0db596Smlarkin 1463a0db596Smlarkin #ifdef VMM_DEBUG 1473a0db596Smlarkin #define DPRINTF(x...) do { printf(x); } while(0) 1483a0db596Smlarkin #else 1493a0db596Smlarkin #define DPRINTF(x...) 1503a0db596Smlarkin #endif /* VMM_DEBUG */ 1513a0db596Smlarkin enum { 1523a0db596Smlarkin VCPU_STATE_STOPPED, 1533a0db596Smlarkin VCPU_STATE_RUNNING, 1543a0db596Smlarkin VCPU_STATE_REQTERM, 1553a0db596Smlarkin VCPU_STATE_TERMINATED, 1563a0db596Smlarkin VCPU_STATE_UNKNOWN, 1573a0db596Smlarkin }; 1583a0db596Smlarkin 1593a0db596Smlarkin /* 1603a0db596Smlarkin * Virtual Machine 1613a0db596Smlarkin * 1623a0db596Smlarkin * Methods used to protect vm struct members: 1633a0db596Smlarkin * a atomic operations 1643a0db596Smlarkin * I immutable after create 1653a0db596Smlarkin * K kernel lock 1663a0db596Smlarkin * r reference count 1673a0db596Smlarkin * v vcpu list rwlock (vm_vcpu_list) 1683a0db596Smlarkin * V vmm_softc's vm_lock 1693a0db596Smlarkin */ 1703a0db596Smlarkin struct vm { 1713a0db596Smlarkin struct vmspace *vm_vmspace; /* [K] */ 1723a0db596Smlarkin vm_map_t vm_map; /* [K] */ 1733a0db596Smlarkin uint32_t vm_id; /* [I] */ 1743a0db596Smlarkin pid_t vm_creator_pid; /* [I] */ 1753a0db596Smlarkin size_t vm_nmemranges; /* [I] */ 1763a0db596Smlarkin size_t vm_memory_size; /* [I] */ 1773a0db596Smlarkin char vm_name[VMM_MAX_NAME_LEN]; 1783a0db596Smlarkin struct vm_mem_range vm_memranges[VMM_MAX_MEM_RANGES]; 1793a0db596Smlarkin struct refcnt vm_refcnt; /* [a] */ 1803a0db596Smlarkin 1813a0db596Smlarkin struct vcpu_head vm_vcpu_list; /* [v] */ 1823a0db596Smlarkin uint32_t vm_vcpu_ct; /* [v] */ 1833a0db596Smlarkin struct rwlock vm_vcpu_lock; 1843a0db596Smlarkin 1853a0db596Smlarkin SLIST_ENTRY(vm) vm_link; /* [V] */ 1863a0db596Smlarkin }; 1873a0db596Smlarkin 1883a0db596Smlarkin SLIST_HEAD(vmlist_head, vm); 1893a0db596Smlarkin 1903a0db596Smlarkin /* 1913a0db596Smlarkin * Virtual Machine Monitor 1923a0db596Smlarkin * 1933a0db596Smlarkin * Methods used to protect struct members in the global vmm device: 1943a0db596Smlarkin * a atomic opererations 1953a0db596Smlarkin * I immutable operations 1963a0db596Smlarkin * K kernel lock 1973a0db596Smlarkin * p virtual process id (vpid/asid) rwlock 1983a0db596Smlarkin * r reference count 1993a0db596Smlarkin * v vm list rwlock (vm_lock) 2003a0db596Smlarkin */ 2013a0db596Smlarkin struct vmm_softc { 2023a0db596Smlarkin struct device sc_dev; /* [r] */ 2033a0db596Smlarkin 2043a0db596Smlarkin /* Suspend/Resume Synchronization */ 2053a0db596Smlarkin struct rwlock sc_slock; 2063a0db596Smlarkin struct refcnt sc_refcnt; 2073a0db596Smlarkin volatile unsigned int sc_status; /* [a] */ 2083a0db596Smlarkin #define VMM_SUSPENDED (unsigned int) 0 2093a0db596Smlarkin #define VMM_ACTIVE (unsigned int) 1 2103a0db596Smlarkin 2113a0db596Smlarkin struct vmm_softc_md sc_md; 2123a0db596Smlarkin 2133a0db596Smlarkin /* Managed VMs */ 2143a0db596Smlarkin struct vmlist_head vm_list; /* [v] */ 2153a0db596Smlarkin 2163a0db596Smlarkin int mode; /* [I] */ 2173a0db596Smlarkin 2183a0db596Smlarkin size_t vcpu_ct; /* [v] */ 2193a0db596Smlarkin size_t vcpu_max; /* [I] */ 2203a0db596Smlarkin 2213a0db596Smlarkin struct rwlock vm_lock; 2223a0db596Smlarkin size_t vm_ct; /* [v] no. of in-memory VMs */ 2233a0db596Smlarkin size_t vm_idx; /* [a] next unique VM index */ 2243a0db596Smlarkin 2253a0db596Smlarkin struct rwlock vpid_lock; 2263a0db596Smlarkin uint16_t max_vpid; /* [I] */ 2273a0db596Smlarkin uint8_t vpids[512]; /* [p] bitmap of VPID/ASIDs */ 2283a0db596Smlarkin }; 2293a0db596Smlarkin 2303a0db596Smlarkin int vmm_probe(struct device *, void *, void *); 2313a0db596Smlarkin int vmm_activate(struct device *, int); 2323a0db596Smlarkin void vmm_attach(struct device *, struct device *, void *); 2333a0db596Smlarkin int vmmopen(dev_t, int, int, struct proc *); 2343a0db596Smlarkin int vmmclose(dev_t, int, int, struct proc *); 2353a0db596Smlarkin int vm_find(uint32_t, struct vm **); 2363a0db596Smlarkin int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *); 2373a0db596Smlarkin int pledge_ioctl_vmm(struct proc *, long); 2383a0db596Smlarkin struct vcpu *vm_find_vcpu(struct vm *, uint32_t); 2393a0db596Smlarkin int vm_create(struct vm_create_params *, struct proc *); 2403a0db596Smlarkin size_t vm_create_check_mem_ranges(struct vm_create_params *); 2413a0db596Smlarkin void vm_teardown(struct vm **); 2423a0db596Smlarkin int vm_get_info(struct vm_info_params *); 2433a0db596Smlarkin int vm_terminate(struct vm_terminate_params *); 2443a0db596Smlarkin int vm_resetcpu(struct vm_resetcpu_params *); 245234ee546Sdv int vm_rwvmparams(struct vm_rwvmparams_params *, int); 2463a0db596Smlarkin int vcpu_must_stop(struct vcpu *); 2473c817da7Sdv int vm_share_mem(struct vm_sharemem_params *, struct proc *); 248ba66f564Sdv int vm_run(struct vm_run_params *); 2493a0db596Smlarkin 2503aa75afeSjan #ifdef VMM_DEBUG 2513aa75afeSjan void dump_vcpu(struct vcpu *); 2523aa75afeSjan #endif 2533aa75afeSjan 25425f7c0b5Smlarkin #endif /* _KERNEL */ 25525f7c0b5Smlarkin #endif /* DEV_VMM_H */ 256