summaryrefslogtreecommitdiff
path: root/sys/dev/vmm/vmm.h
blob: 38b4a3f85f1e7777014dcdfe04de524d655b6474 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
/* $OpenBSD: vmm.h,v 1.3 2023/05/13 23:15:28 dv 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>

#ifndef DEV_VMM_H
#define DEV_VMM_H

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];

        /* Output parameter from VMM_IOC_CREATE */
        uint32_t		vcp_id;
};

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];
};

/* 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 vcpu_must_stop(struct vcpu *);
int vm_share_mem(struct vm_sharemem_params *, struct proc *);

#endif /* _KERNEL */
#endif /* DEV_VMM_H */