1/* $OpenBSD: vmm.h,v 1.4 2024/01/11 17:13:48 jan 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#ifndef DEV_VMM_H
24#define DEV_VMM_H
25
26struct vm_mem_range {
27	paddr_t vmr_gpa;
28	vaddr_t vmr_va;
29	size_t  vmr_size;
30	int     vmr_type;
31#define VM_MEM_RAM		0	/* Presented as usable system memory. */
32#define VM_MEM_RESERVED		1	/* Reserved for BIOS, etc. */
33#define VM_MEM_MMIO		2	/* Special region for device mmio. */
34};
35
36struct vm_create_params {
37/* Input parameters to VMM_IOC_CREATE */
38	size_t			vcp_nmemranges;
39	size_t			vcp_ncpus;
40	struct vm_mem_range	vcp_memranges[VMM_MAX_MEM_RANGES];
41	char			vcp_name[VMM_MAX_NAME_LEN];
42
43        /* Output parameter from VMM_IOC_CREATE */
44        uint32_t		vcp_id;
45};
46
47struct vm_info_result {
48	/* Output parameters from VMM_IOC_INFO */
49	size_t		vir_memory_size;
50	size_t		vir_used_size;
51	size_t		vir_ncpus;
52	uint8_t		vir_vcpu_state[VMM_MAX_VCPUS_PER_VM];
53	pid_t		vir_creator_pid;
54	uint32_t	vir_id;
55	char		vir_name[VMM_MAX_NAME_LEN];
56};
57
58struct vm_info_params {
59	/* Input parameters to VMM_IOC_INFO */
60	size_t			 vip_size;	/* Output buffer size */
61
62	/* Output Parameters from VMM_IOC_INFO */
63	size_t			 vip_info_ct;	/* # of entries returned */
64	struct vm_info_result	*vip_info;	/* Output buffer */
65};
66
67struct vm_terminate_params {
68	/* Input parameters to VMM_IOC_TERM */
69	uint32_t		vtp_vm_id;
70};
71
72struct vm_resetcpu_params {
73	/* Input parameters to VMM_IOC_RESETCPU */
74	uint32_t		vrp_vm_id;
75	uint32_t		vrp_vcpu_id;
76	struct vcpu_reg_state	vrp_init_state;
77};
78
79struct vm_sharemem_params {
80	/* Input parameters to VMM_IOC_SHAREMEM */
81	uint32_t		vsp_vm_id;
82	size_t			vsp_nmemranges;
83	struct vm_mem_range	vsp_memranges[VMM_MAX_MEM_RANGES];
84};
85
86/* IOCTL definitions */
87#define VMM_IOC_CREATE _IOWR('V', 1, struct vm_create_params) /* Create VM */
88#define VMM_IOC_RUN _IOWR('V', 2, struct vm_run_params) /* Run VCPU */
89#define VMM_IOC_INFO _IOWR('V', 3, struct vm_info_params) /* Get VM Info */
90#define VMM_IOC_TERM _IOW('V', 4, struct vm_terminate_params) /* Terminate VM */
91#define VMM_IOC_RESETCPU _IOW('V', 5, struct vm_resetcpu_params) /* Reset */
92#define VMM_IOC_READREGS _IOWR('V', 7, struct vm_rwregs_params) /* Get regs */
93#define VMM_IOC_WRITEREGS _IOW('V', 8, struct vm_rwregs_params) /* Set regs */
94/* Get VM params */
95#define VMM_IOC_READVMPARAMS _IOWR('V', 9, struct vm_rwvmparams_params)
96/* Set VM params */
97#define VMM_IOC_WRITEVMPARAMS _IOW('V', 10, struct vm_rwvmparams_params)
98#define VMM_IOC_SHAREMEM _IOW('V', 11, struct vm_sharemem_params)
99
100#ifdef _KERNEL
101
102/* #define VMM_DEBUG */
103
104#ifdef VMM_DEBUG
105#define DPRINTF(x...)   do { printf(x); } while(0)
106#else
107#define DPRINTF(x...)
108#endif /* VMM_DEBUG */
109enum {
110	VCPU_STATE_STOPPED,
111	VCPU_STATE_RUNNING,
112	VCPU_STATE_REQTERM,
113	VCPU_STATE_TERMINATED,
114	VCPU_STATE_UNKNOWN,
115};
116
117/*
118 * Virtual Machine
119 *
120 * Methods used to protect vm struct members:
121 *	a	atomic operations
122 *	I	immutable after create
123 *	K	kernel lock
124 *	r	reference count
125 *	v	vcpu list rwlock (vm_vcpu_list)
126 *	V	vmm_softc's vm_lock
127 */
128struct vm {
129	struct vmspace		 *vm_vmspace;		/* [K] */
130	vm_map_t		 vm_map;		/* [K] */
131	uint32_t		 vm_id;			/* [I] */
132	pid_t			 vm_creator_pid;	/* [I] */
133	size_t			 vm_nmemranges;		/* [I] */
134	size_t			 vm_memory_size;	/* [I] */
135	char			 vm_name[VMM_MAX_NAME_LEN];
136	struct vm_mem_range	 vm_memranges[VMM_MAX_MEM_RANGES];
137	struct refcnt		 vm_refcnt;		/* [a] */
138
139	struct vcpu_head	 vm_vcpu_list;		/* [v] */
140	uint32_t		 vm_vcpu_ct;		/* [v] */
141	struct rwlock		 vm_vcpu_lock;
142
143	SLIST_ENTRY(vm)		 vm_link;		/* [V] */
144};
145
146SLIST_HEAD(vmlist_head, vm);
147
148/*
149 * Virtual Machine Monitor
150 *
151 * Methods used to protect struct members in the global vmm device:
152 *	a	atomic opererations
153 *	I	immutable operations
154 *	K	kernel lock
155 *	p	virtual process id (vpid/asid) rwlock
156 *	r	reference count
157 *	v	vm list rwlock (vm_lock)
158 */
159struct vmm_softc {
160	struct device		sc_dev;		/* [r] */
161
162	/* Suspend/Resume Synchronization */
163	struct rwlock		sc_slock;
164	struct refcnt		sc_refcnt;
165	volatile unsigned int	sc_status;	/* [a] */
166#define VMM_SUSPENDED		(unsigned int) 0
167#define VMM_ACTIVE		(unsigned int) 1
168
169	struct vmm_softc_md	sc_md;
170
171	/* Managed VMs */
172	struct vmlist_head	vm_list;	/* [v] */
173
174	int			mode;		/* [I] */
175
176	size_t			vcpu_ct;	/* [v] */
177	size_t			vcpu_max;	/* [I] */
178
179	struct rwlock		vm_lock;
180	size_t			vm_ct;		/* [v] no. of in-memory VMs */
181	size_t			vm_idx;		/* [a] next unique VM index */
182
183	struct rwlock		vpid_lock;
184	uint16_t		max_vpid;	/* [I] */
185	uint8_t			vpids[512];	/* [p] bitmap of VPID/ASIDs */
186};
187
188int vmm_probe(struct device *, void *, void *);
189int vmm_activate(struct device *, int);
190void vmm_attach(struct device *, struct device *,  void *);
191int vmmopen(dev_t, int, int, struct proc *);
192int vmmclose(dev_t, int, int, struct proc *);
193int vm_find(uint32_t, struct vm **);
194int vmmioctl_machdep(dev_t, u_long, caddr_t, int, struct proc *);
195int pledge_ioctl_vmm(struct proc *, long);
196struct vcpu *vm_find_vcpu(struct vm *, uint32_t);
197int vm_create(struct vm_create_params *, struct proc *);
198size_t vm_create_check_mem_ranges(struct vm_create_params *);
199void vm_teardown(struct vm **);
200int vm_get_info(struct vm_info_params *);
201int vm_terminate(struct vm_terminate_params *);
202int vm_resetcpu(struct vm_resetcpu_params *);
203int vcpu_must_stop(struct vcpu *);
204int vm_share_mem(struct vm_sharemem_params *, struct proc *);
205
206#ifdef VMM_DEBUG
207void dump_vcpu(struct vcpu *);
208#endif
209
210#endif /* _KERNEL */
211#endif /* DEV_VMM_H */
212