255 lines
7.4 KiB
C
255 lines
7.4 KiB
C
/* $OpenBSD: vmm.h,v 1.7 2024/08/27 09:16:03 bluhm Exp $ */
|
|
/*
|
|
* Copyright (c) 2014-2023 Mike Larkin <mlarkin@openbsd.org>
|
|
*
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
* copyright notice and this permission notice appear in all copies.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
*/
|
|
|
|
#include <sys/rwlock.h>
|
|
#include <sys/refcnt.h>
|
|
|
|
#include <uvm/uvm_extern.h>
|
|
|
|
#include <machine/vmmvar.h>
|
|
|
|
#ifndef DEV_VMM_H
|
|
#define DEV_VMM_H
|
|
|
|
#define VMM_MAX_MEM_RANGES 16
|
|
#define VMM_MAX_DISKS_PER_VM 4
|
|
#define VMM_MAX_NAME_LEN 64
|
|
#define VMM_MAX_VCPUS 512
|
|
#define VMM_MAX_VCPUS_PER_VM 64
|
|
#define VMM_MAX_VM_MEM_SIZE 128L * 1024 * 1024 * 1024
|
|
#define VMM_MAX_NICS_PER_VM 4
|
|
|
|
struct vm_mem_range {
|
|
paddr_t vmr_gpa;
|
|
vaddr_t vmr_va;
|
|
size_t vmr_size;
|
|
int vmr_type;
|
|
#define VM_MEM_RAM 0 /* Presented as usable system memory. */
|
|
#define VM_MEM_RESERVED 1 /* Reserved for BIOS, etc. */
|
|
#define VM_MEM_MMIO 2 /* Special region for device mmio. */
|
|
};
|
|
|
|
struct vm_create_params {
|
|
/* Input parameters to VMM_IOC_CREATE */
|
|
size_t vcp_nmemranges;
|
|
size_t vcp_ncpus;
|
|
struct vm_mem_range vcp_memranges[VMM_MAX_MEM_RANGES];
|
|
char vcp_name[VMM_MAX_NAME_LEN];
|
|
int vcp_sev;
|
|
|
|
/* Output parameter from VMM_IOC_CREATE */
|
|
uint32_t vcp_id;
|
|
uint32_t vcp_poscbit;
|
|
uint32_t vcp_asid[VMM_MAX_VCPUS];
|
|
};
|
|
|
|
struct vm_info_result {
|
|
/* Output parameters from VMM_IOC_INFO */
|
|
size_t vir_memory_size;
|
|
size_t vir_used_size;
|
|
size_t vir_ncpus;
|
|
uint8_t vir_vcpu_state[VMM_MAX_VCPUS_PER_VM];
|
|
pid_t vir_creator_pid;
|
|
uint32_t vir_id;
|
|
char vir_name[VMM_MAX_NAME_LEN];
|
|
};
|
|
|
|
struct vm_info_params {
|
|
/* Input parameters to VMM_IOC_INFO */
|
|
size_t vip_size; /* Output buffer size */
|
|
|
|
/* Output Parameters from VMM_IOC_INFO */
|
|
size_t vip_info_ct; /* # of entries returned */
|
|
struct vm_info_result *vip_info; /* Output buffer */
|
|
};
|
|
|
|
struct vm_terminate_params {
|
|
/* Input parameters to VMM_IOC_TERM */
|
|
uint32_t vtp_vm_id;
|
|
};
|
|
|
|
struct vm_resetcpu_params {
|
|
/* Input parameters to VMM_IOC_RESETCPU */
|
|
uint32_t vrp_vm_id;
|
|
uint32_t vrp_vcpu_id;
|
|
struct vcpu_reg_state vrp_init_state;
|
|
};
|
|
|
|
struct vm_sharemem_params {
|
|
/* Input parameters to VMM_IOC_SHAREMEM */
|
|
uint32_t vsp_vm_id;
|
|
size_t vsp_nmemranges;
|
|
struct vm_mem_range vsp_memranges[VMM_MAX_MEM_RANGES];
|
|
};
|
|
|
|
struct vm_run_params {
|
|
/* Input parameters to VMM_IOC_RUN */
|
|
uint32_t vrp_vm_id;
|
|
uint32_t vrp_vcpu_id;
|
|
struct vcpu_inject_event vrp_inject;
|
|
uint8_t vrp_intr_pending; /* Additional intrs pending? */
|
|
|
|
/* Input/output parameter to VMM_IOC_RUN */
|
|
struct vm_exit *vrp_exit; /* updated exit data */
|
|
|
|
/* Output parameter from VMM_IOC_RUN */
|
|
uint16_t vrp_exit_reason; /* exit reason */
|
|
uint8_t vrp_irqready; /* ready for IRQ on entry */
|
|
};
|
|
|
|
#define VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA 0x1 /* read/write pvclock gpa */
|
|
#define VM_RWVMPARAMS_PVCLOCK_VERSION 0x2 /* read/write pvclock version */
|
|
#define VM_RWVMPARAMS_ALL (VM_RWVMPARAMS_PVCLOCK_SYSTEM_GPA | \
|
|
VM_RWVMPARAMS_PVCLOCK_VERSION)
|
|
|
|
struct vm_rwvmparams_params {
|
|
/* Input parameters to VMM_IOC_READVMPARAMS/VMM_IOC_WRITEVMPARAMS */
|
|
uint32_t vpp_vm_id;
|
|
uint32_t vpp_vcpu_id;
|
|
uint32_t vpp_mask;
|
|
paddr_t vpp_pvclock_system_gpa;
|
|
uint32_t vpp_pvclock_version;
|
|
};
|
|
|
|
/* IOCTL definitions */
|
|
#define VMM_IOC_CREATE _IOWR('V', 1, struct vm_create_params) /* Create VM */
|
|
#define VMM_IOC_RUN _IOWR('V', 2, struct vm_run_params) /* Run VCPU */
|
|
#define VMM_IOC_INFO _IOWR('V', 3, struct vm_info_params) /* Get VM Info */
|
|
#define VMM_IOC_TERM _IOW('V', 4, struct vm_terminate_params) /* Terminate VM */
|
|
#define VMM_IOC_RESETCPU _IOW('V', 5, struct vm_resetcpu_params) /* Reset */
|
|
#define VMM_IOC_READREGS _IOWR('V', 7, struct vm_rwregs_params) /* Get regs */
|
|
#define VMM_IOC_WRITEREGS _IOW('V', 8, struct vm_rwregs_params) /* Set regs */
|
|
/* Get VM params */
|
|
#define VMM_IOC_READVMPARAMS _IOWR('V', 9, struct vm_rwvmparams_params)
|
|
/* Set VM params */
|
|
#define VMM_IOC_WRITEVMPARAMS _IOW('V', 10, struct vm_rwvmparams_params)
|
|
#define VMM_IOC_SHAREMEM _IOW('V', 11, struct vm_sharemem_params)
|
|
|
|
#ifdef _KERNEL
|
|
|
|
/* #define VMM_DEBUG */
|
|
|
|
#ifdef VMM_DEBUG
|
|
#define DPRINTF(x...) do { printf(x); } while(0)
|
|
#else
|
|
#define DPRINTF(x...)
|
|
#endif /* VMM_DEBUG */
|
|
enum {
|
|
VCPU_STATE_STOPPED,
|
|
VCPU_STATE_RUNNING,
|
|
VCPU_STATE_REQTERM,
|
|
VCPU_STATE_TERMINATED,
|
|
VCPU_STATE_UNKNOWN,
|
|
};
|
|
|
|
/*
|
|
* Virtual Machine
|
|
*
|
|
* Methods used to protect vm struct members:
|
|
* a atomic operations
|
|
* I immutable after create
|
|
* K kernel lock
|
|
* r reference count
|
|
* v vcpu list rwlock (vm_vcpu_list)
|
|
* V vmm_softc's vm_lock
|
|
*/
|
|
struct vm {
|
|
struct vmspace *vm_vmspace; /* [K] */
|
|
vm_map_t vm_map; /* [K] */
|
|
uint32_t vm_id; /* [I] */
|
|
pid_t vm_creator_pid; /* [I] */
|
|
size_t vm_nmemranges; /* [I] */
|
|
size_t vm_memory_size; /* [I] */
|
|
char vm_name[VMM_MAX_NAME_LEN];
|
|
struct vm_mem_range vm_memranges[VMM_MAX_MEM_RANGES];
|
|
struct refcnt vm_refcnt; /* [a] */
|
|
|
|
struct vcpu_head vm_vcpu_list; /* [v] */
|
|
uint32_t vm_vcpu_ct; /* [v] */
|
|
struct rwlock vm_vcpu_lock;
|
|
|
|
SLIST_ENTRY(vm) vm_link; /* [V] */
|
|
};
|
|
|
|
SLIST_HEAD(vmlist_head, vm);
|
|
|
|
/*
|
|
* Virtual Machine Monitor
|
|
*
|
|
* Methods used to protect struct members in the global vmm device:
|
|
* a atomic opererations
|
|
* I immutable operations
|
|
* K kernel lock
|
|
* p virtual process id (vpid/asid) rwlock
|
|
* r reference count
|
|
* v vm list rwlock (vm_lock)
|
|
*/
|
|
struct vmm_softc {
|
|
struct device sc_dev; /* [r] */
|
|
|
|
/* Suspend/Resume Synchronization */
|
|
struct rwlock sc_slock;
|
|
struct refcnt sc_refcnt;
|
|
volatile unsigned int sc_status; /* [a] */
|
|
#define VMM_SUSPENDED (unsigned int) 0
|
|
#define VMM_ACTIVE (unsigned int) 1
|
|
|
|
struct vmm_softc_md sc_md;
|
|
|
|
/* Managed VMs */
|
|
struct vmlist_head vm_list; /* [v] */
|
|
|
|
int mode; /* [I] */
|
|
|
|
size_t vcpu_ct; /* [v] */
|
|
size_t vcpu_max; /* [I] */
|
|
|
|
struct rwlock vm_lock;
|
|
size_t vm_ct; /* [v] no. of in-memory VMs */
|
|
size_t vm_idx; /* [a] next unique VM index */
|
|
|
|
struct rwlock vpid_lock;
|
|
uint16_t max_vpid; /* [I] */
|
|
uint8_t vpids[512]; /* [p] bitmap of VPID/ASIDs */
|
|
};
|
|
|
|
int vmm_probe(struct device *, void *, void *);
|
|
int vmm_activate(struct device *, int);
|
|
void vmm_attach(struct device *, struct device *, void *);
|
|
int vmmopen(dev_t, int, int, struct proc *);
|
|
int vmmclose(dev_t, int, int, struct proc *);
|
|
int vm_find(uint32_t, struct vm **);
|
|
int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *);
|
|
int pledge_ioctl_vmm(struct proc *, long);
|
|
struct vcpu *vm_find_vcpu(struct vm *, uint32_t);
|
|
int vm_create(struct vm_create_params *, struct proc *);
|
|
size_t vm_create_check_mem_ranges(struct vm_create_params *);
|
|
void vm_teardown(struct vm **);
|
|
int vm_get_info(struct vm_info_params *);
|
|
int vm_terminate(struct vm_terminate_params *);
|
|
int vm_resetcpu(struct vm_resetcpu_params *);
|
|
int vm_rwvmparams(struct vm_rwvmparams_params *, int);
|
|
int vcpu_must_stop(struct vcpu *);
|
|
int vm_share_mem(struct vm_sharemem_params *, struct proc *);
|
|
int vm_run(struct vm_run_params *);
|
|
|
|
#ifdef VMM_DEBUG
|
|
void dump_vcpu(struct vcpu *);
|
|
#endif
|
|
|
|
#endif /* _KERNEL */
|
|
#endif /* DEV_VMM_H */
|