1221828Sgrehan/*-
2221828Sgrehan * Copyright (c) 2011 NetApp, Inc.
3221828Sgrehan * All rights reserved.
4221828Sgrehan *
5221828Sgrehan * Redistribution and use in source and binary forms, with or without
6221828Sgrehan * modification, are permitted provided that the following conditions
7221828Sgrehan * are met:
8221828Sgrehan * 1. Redistributions of source code must retain the above copyright
9221828Sgrehan *    notice, this list of conditions and the following disclaimer.
10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright
11221828Sgrehan *    notice, this list of conditions and the following disclaimer in the
12221828Sgrehan *    documentation and/or other materials provided with the distribution.
13221828Sgrehan *
14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17221828Sgrehan * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24221828Sgrehan * SUCH DAMAGE.
25221828Sgrehan *
26221828Sgrehan * $FreeBSD: stable/11/lib/libvmmapi/vmmapi.c 348201 2019-05-23 21:23:18Z rgrimes $
27221828Sgrehan */
28221828Sgrehan
29221828Sgrehan#include <sys/cdefs.h>
30221828Sgrehan__FBSDID("$FreeBSD: stable/11/lib/libvmmapi/vmmapi.c 348201 2019-05-23 21:23:18Z rgrimes $");
31221828Sgrehan
32266933Sneel#include <sys/param.h>
33221828Sgrehan#include <sys/sysctl.h>
34221828Sgrehan#include <sys/ioctl.h>
35221828Sgrehan#include <sys/mman.h>
36266708Sneel#include <sys/_iovec.h>
37266933Sneel#include <sys/cpuset.h>
38221828Sgrehan
39269008Sneel#include <x86/segments.h>
40221828Sgrehan#include <machine/specialreg.h>
41221828Sgrehan
42282558Sneel#include <errno.h>
43221828Sgrehan#include <stdio.h>
44221828Sgrehan#include <stdlib.h>
45221828Sgrehan#include <assert.h>
46221828Sgrehan#include <string.h>
47221828Sgrehan#include <fcntl.h>
48221828Sgrehan#include <unistd.h>
49221828Sgrehan
50256176Sneel#include <libutil.h>
51256176Sneel
52221828Sgrehan#include <machine/vmm.h>
53221828Sgrehan#include <machine/vmm_dev.h>
54221828Sgrehan
55221828Sgrehan#include "vmmapi.h"
56221828Sgrehan
57256176Sneel#define	MB	(1024 * 1024UL)
58248477Sneel#define	GB	(1024 * 1024 * 1024UL)
59248477Sneel
60284539Sneel/*
61284539Sneel * Size of the guard region before and after the virtual address space
62284539Sneel * mapping the guest physical memory. This must be a multiple of the
63284539Sneel * superpage size for performance reasons.
64284539Sneel */
65284539Sneel#define	VM_MMAP_GUARD_SIZE	(4 * MB)
66284539Sneel
67284539Sneel#define	PROT_RW		(PROT_READ | PROT_WRITE)
68284539Sneel#define	PROT_ALL	(PROT_READ | PROT_WRITE | PROT_EXEC)
69284539Sneel
70221828Sgrehanstruct vmctx {
71221828Sgrehan	int	fd;
72248477Sneel	uint32_t lowmem_limit;
73265951Sneel	int	memflags;
74248477Sneel	size_t	lowmem;
75248477Sneel	size_t	highmem;
76284539Sneel	char	*baseaddr;
77221828Sgrehan	char	*name;
78221828Sgrehan};
79221828Sgrehan
80221828Sgrehan#define	CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
81221828Sgrehan#define	DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
82221828Sgrehan
83221828Sgrehanstatic int
84221828Sgrehanvm_device_open(const char *name)
85221828Sgrehan{
86336161Saraujo	int fd, len;
87336161Saraujo	char *vmfile;
88221828Sgrehan
89221828Sgrehan	len = strlen("/dev/vmm/") + strlen(name) + 1;
90221828Sgrehan	vmfile = malloc(len);
91221828Sgrehan	assert(vmfile != NULL);
92221828Sgrehan	snprintf(vmfile, len, "/dev/vmm/%s", name);
93221828Sgrehan
94336161Saraujo	/* Open the device file */
95336161Saraujo	fd = open(vmfile, O_RDWR, 0);
96221828Sgrehan
97221828Sgrehan	free(vmfile);
98336161Saraujo	return (fd);
99221828Sgrehan}
100221828Sgrehan
101221828Sgrehanint
102221828Sgrehanvm_create(const char *name)
103221828Sgrehan{
104221828Sgrehan
105221828Sgrehan	return (CREATE((char *)name));
106221828Sgrehan}
107221828Sgrehan
108221828Sgrehanstruct vmctx *
109221828Sgrehanvm_open(const char *name)
110221828Sgrehan{
111221828Sgrehan	struct vmctx *vm;
112221828Sgrehan
113221828Sgrehan	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
114221828Sgrehan	assert(vm != NULL);
115221828Sgrehan
116221828Sgrehan	vm->fd = -1;
117265951Sneel	vm->memflags = 0;
118248477Sneel	vm->lowmem_limit = 3 * GB;
119221828Sgrehan	vm->name = (char *)(vm + 1);
120221828Sgrehan	strcpy(vm->name, name);
121221828Sgrehan
122221828Sgrehan	if ((vm->fd = vm_device_open(vm->name)) < 0)
123221828Sgrehan		goto err;
124221828Sgrehan
125221828Sgrehan	return (vm);
126221828Sgrehanerr:
127221828Sgrehan	vm_destroy(vm);
128221828Sgrehan	return (NULL);
129221828Sgrehan}
130221828Sgrehan
131221828Sgrehanvoid
132221828Sgrehanvm_destroy(struct vmctx *vm)
133221828Sgrehan{
134221828Sgrehan	assert(vm != NULL);
135221828Sgrehan
136221828Sgrehan	if (vm->fd >= 0)
137221828Sgrehan		close(vm->fd);
138241178Sneel	DESTROY(vm->name);
139241178Sneel
140221828Sgrehan	free(vm);
141221828Sgrehan}
142221828Sgrehan
143221828Sgrehanint
144256176Sneelvm_parse_memsize(const char *optarg, size_t *ret_memsize)
145256176Sneel{
146256176Sneel	char *endptr;
147256176Sneel	size_t optval;
148256176Sneel	int error;
149256176Sneel
150256176Sneel	optval = strtoul(optarg, &endptr, 0);
151256176Sneel	if (*optarg != '\0' && *endptr == '\0') {
152256176Sneel		/*
153256176Sneel		 * For the sake of backward compatibility if the memory size
154256176Sneel		 * specified on the command line is less than a megabyte then
155256176Sneel		 * it is interpreted as being in units of MB.
156256176Sneel		 */
157256176Sneel		if (optval < MB)
158256176Sneel			optval *= MB;
159256176Sneel		*ret_memsize = optval;
160256176Sneel		error = 0;
161256176Sneel	} else
162256176Sneel		error = expand_number(optarg, ret_memsize);
163256176Sneel
164256176Sneel	return (error);
165256176Sneel}
166256176Sneel
167248477Sneeluint32_t
168248477Sneelvm_get_lowmem_limit(struct vmctx *ctx)
169221828Sgrehan{
170248477Sneel
171248477Sneel	return (ctx->lowmem_limit);
172248477Sneel}
173248477Sneel
174248477Sneelvoid
175248477Sneelvm_set_lowmem_limit(struct vmctx *ctx, uint32_t limit)
176248477Sneel{
177248477Sneel
178248477Sneel	ctx->lowmem_limit = limit;
179248477Sneel}
180248477Sneel
181265951Sneelvoid
182265951Sneelvm_set_memflags(struct vmctx *ctx, int flags)
183265951Sneel{
184265951Sneel
185265951Sneel	ctx->memflags = flags;
186265951Sneel}
187265951Sneel
188284539Sneelint
189284539Sneelvm_get_memflags(struct vmctx *ctx)
190284539Sneel{
191284539Sneel
192284539Sneel	return (ctx->memflags);
193284539Sneel}
194284539Sneel
195284539Sneel/*
196284539Sneel * Map segment 'segid' starting at 'off' into guest address range [gpa,gpa+len).
197284539Sneel */
198284539Sneelint
199284539Sneelvm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, vm_ooffset_t off,
200284539Sneel    size_t len, int prot)
201284539Sneel{
202284539Sneel	struct vm_memmap memmap;
203284539Sneel	int error, flags;
204284539Sneel
205284539Sneel	memmap.gpa = gpa;
206284539Sneel	memmap.segid = segid;
207284539Sneel	memmap.segoff = off;
208284539Sneel	memmap.len = len;
209284539Sneel	memmap.prot = prot;
210284539Sneel	memmap.flags = 0;
211284539Sneel
212284539Sneel	if (ctx->memflags & VM_MEM_F_WIRED)
213284539Sneel		memmap.flags |= VM_MEMMAP_F_WIRED;
214284539Sneel
215284539Sneel	/*
216284539Sneel	 * If this mapping already exists then don't create it again. This
217284539Sneel	 * is the common case for SYSMEM mappings created by bhyveload(8).
218284539Sneel	 */
219284539Sneel	error = vm_mmap_getnext(ctx, &gpa, &segid, &off, &len, &prot, &flags);
220284539Sneel	if (error == 0 && gpa == memmap.gpa) {
221284539Sneel		if (segid != memmap.segid || off != memmap.segoff ||
222284539Sneel		    prot != memmap.prot || flags != memmap.flags) {
223284539Sneel			errno = EEXIST;
224284539Sneel			return (-1);
225284539Sneel		} else {
226284539Sneel			return (0);
227284539Sneel		}
228284539Sneel	}
229284539Sneel
230284539Sneel	error = ioctl(ctx->fd, VM_MMAP_MEMSEG, &memmap);
231284539Sneel	return (error);
232284539Sneel}
233284539Sneel
234284539Sneelint
235284539Sneelvm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
236284539Sneel    vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
237284539Sneel{
238284539Sneel	struct vm_memmap memmap;
239284539Sneel	int error;
240284539Sneel
241284539Sneel	bzero(&memmap, sizeof(struct vm_memmap));
242284539Sneel	memmap.gpa = *gpa;
243284539Sneel	error = ioctl(ctx->fd, VM_MMAP_GETNEXT, &memmap);
244284539Sneel	if (error == 0) {
245284539Sneel		*gpa = memmap.gpa;
246284539Sneel		*segid = memmap.segid;
247284539Sneel		*segoff = memmap.segoff;
248284539Sneel		*len = memmap.len;
249284539Sneel		*prot = memmap.prot;
250284539Sneel		*flags = memmap.flags;
251284539Sneel	}
252284539Sneel	return (error);
253284539Sneel}
254284539Sneel
255284539Sneel/*
256284539Sneel * Return 0 if the segments are identical and non-zero otherwise.
257284539Sneel *
258284539Sneel * This is slightly complicated by the fact that only device memory segments
259284539Sneel * are named.
260284539Sneel */
261248477Sneelstatic int
262284539Sneelcmpseg(size_t len, const char *str, size_t len2, const char *str2)
263248477Sneel{
264221828Sgrehan
265284539Sneel	if (len == len2) {
266284539Sneel		if ((!str && !str2) || (str && str2 && !strcmp(str, str2)))
267284539Sneel			return (0);
268284539Sneel	}
269284539Sneel	return (-1);
270284539Sneel}
271284539Sneel
272284539Sneelstatic int
273284539Sneelvm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
274284539Sneel{
275284539Sneel	struct vm_memseg memseg;
276284539Sneel	size_t n;
277284539Sneel	int error;
278284539Sneel
279221828Sgrehan	/*
280284539Sneel	 * If the memory segment has already been created then just return.
281284539Sneel	 * This is the usual case for the SYSMEM segment created by userspace
282284539Sneel	 * loaders like bhyveload(8).
283221828Sgrehan	 */
284284539Sneel	error = vm_get_memseg(ctx, segid, &memseg.len, memseg.name,
285284539Sneel	    sizeof(memseg.name));
286284539Sneel	if (error)
287284539Sneel		return (error);
288284539Sneel
289284539Sneel	if (memseg.len != 0) {
290284539Sneel		if (cmpseg(len, name, memseg.len, VM_MEMSEG_NAME(&memseg))) {
291284539Sneel			errno = EINVAL;
292284539Sneel			return (-1);
293284539Sneel		} else {
294284539Sneel			return (0);
295284539Sneel		}
296221828Sgrehan	}
297284539Sneel
298284539Sneel	bzero(&memseg, sizeof(struct vm_memseg));
299284539Sneel	memseg.segid = segid;
300284539Sneel	memseg.len = len;
301284539Sneel	if (name != NULL) {
302284539Sneel		n = strlcpy(memseg.name, name, sizeof(memseg.name));
303284539Sneel		if (n >= sizeof(memseg.name)) {
304284539Sneel			errno = ENAMETOOLONG;
305284539Sneel			return (-1);
306284539Sneel		}
307284539Sneel	}
308284539Sneel
309284539Sneel	error = ioctl(ctx->fd, VM_ALLOC_MEMSEG, &memseg);
310221828Sgrehan	return (error);
311221828Sgrehan}
312221828Sgrehan
313248477Sneelint
314284539Sneelvm_get_memseg(struct vmctx *ctx, int segid, size_t *lenp, char *namebuf,
315284539Sneel    size_t bufsize)
316221828Sgrehan{
317284539Sneel	struct vm_memseg memseg;
318284539Sneel	size_t n;
319248477Sneel	int error;
320221828Sgrehan
321284539Sneel	memseg.segid = segid;
322284539Sneel	error = ioctl(ctx->fd, VM_GET_MEMSEG, &memseg);
323284539Sneel	if (error == 0) {
324284539Sneel		*lenp = memseg.len;
325284539Sneel		n = strlcpy(namebuf, memseg.name, bufsize);
326284539Sneel		if (n >= bufsize) {
327284539Sneel			errno = ENAMETOOLONG;
328284539Sneel			error = -1;
329284539Sneel		}
330284539Sneel	}
331284539Sneel	return (error);
332284539Sneel}
333248477Sneel
334284539Sneelstatic int
335284539Sneelsetup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
336284539Sneel{
337284539Sneel	char *ptr;
338284539Sneel	int error, flags;
339284539Sneel
340284539Sneel	/* Map 'len' bytes starting at 'gpa' in the guest address space */
341284539Sneel	error = vm_mmap_memseg(ctx, gpa, VM_SYSMEM, gpa, len, PROT_ALL);
342284539Sneel	if (error)
343284539Sneel		return (error);
344284539Sneel
345284539Sneel	flags = MAP_SHARED | MAP_FIXED;
346284539Sneel	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
347284539Sneel		flags |= MAP_NOCORE;
348284539Sneel
349284539Sneel	/* mmap into the process address space on the host */
350284539Sneel	ptr = mmap(base + gpa, len, PROT_RW, flags, ctx->fd, gpa);
351284539Sneel	if (ptr == MAP_FAILED)
352284539Sneel		return (-1);
353284539Sneel
354284539Sneel	return (0);
355284539Sneel}
356284539Sneel
357284539Sneelint
358284539Sneelvm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
359284539Sneel{
360284539Sneel	size_t objsize, len;
361284539Sneel	vm_paddr_t gpa;
362284539Sneel	char *baseaddr, *ptr;
363340534Sjhb	int error;
364284539Sneel
365284539Sneel	assert(vms == VM_MMAP_ALL);
366284539Sneel
367248477Sneel	/*
368248477Sneel	 * If 'memsize' cannot fit entirely in the 'lowmem' segment then
369248477Sneel	 * create another 'highmem' segment above 4GB for the remainder.
370248477Sneel	 */
371248477Sneel	if (memsize > ctx->lowmem_limit) {
372248477Sneel		ctx->lowmem = ctx->lowmem_limit;
373284539Sneel		ctx->highmem = memsize - ctx->lowmem_limit;
374284539Sneel		objsize = 4*GB + ctx->highmem;
375248477Sneel	} else {
376248477Sneel		ctx->lowmem = memsize;
377248477Sneel		ctx->highmem = 0;
378284539Sneel		objsize = ctx->lowmem;
379248477Sneel	}
380248477Sneel
381284539Sneel	error = vm_alloc_memseg(ctx, VM_SYSMEM, objsize, NULL);
382284539Sneel	if (error)
383284539Sneel		return (error);
384284539Sneel
385284539Sneel	/*
386284539Sneel	 * Stake out a contiguous region covering the guest physical memory
387284539Sneel	 * and the adjoining guard regions.
388284539Sneel	 */
389284539Sneel	len = VM_MMAP_GUARD_SIZE + objsize + VM_MMAP_GUARD_SIZE;
390340534Sjhb	ptr = mmap(NULL, len, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1, 0);
391284539Sneel	if (ptr == MAP_FAILED)
392284539Sneel		return (-1);
393284539Sneel
394284539Sneel	baseaddr = ptr + VM_MMAP_GUARD_SIZE;
395284539Sneel	if (ctx->highmem > 0) {
396284539Sneel		gpa = 4*GB;
397284539Sneel		len = ctx->highmem;
398284539Sneel		error = setup_memory_segment(ctx, gpa, len, baseaddr);
399248477Sneel		if (error)
400248477Sneel			return (error);
401248477Sneel	}
402248477Sneel
403284539Sneel	if (ctx->lowmem > 0) {
404284539Sneel		gpa = 0;
405284539Sneel		len = ctx->lowmem;
406284539Sneel		error = setup_memory_segment(ctx, gpa, len, baseaddr);
407248477Sneel		if (error)
408248477Sneel			return (error);
409248477Sneel	}
410248477Sneel
411284539Sneel	ctx->baseaddr = baseaddr;
412284539Sneel
413248477Sneel	return (0);
414221828Sgrehan}
415221828Sgrehan
416284688Sneel/*
417284688Sneel * Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
418284688Sneel * the lowmem or highmem regions.
419284688Sneel *
420284688Sneel * In particular return NULL if [gaddr, gaddr+len) falls in guest MMIO region.
421284688Sneel * The instruction emulation code depends on this behavior.
422284688Sneel */
423248477Sneelvoid *
424248477Sneelvm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
425248477Sneel{
426248477Sneel
427284688Sneel	if (ctx->lowmem > 0) {
428309647Sglebius		if (gaddr < ctx->lowmem && len <= ctx->lowmem &&
429309647Sglebius		    gaddr + len <= ctx->lowmem)
430284688Sneel			return (ctx->baseaddr + gaddr);
431284688Sneel	}
432248477Sneel
433284688Sneel	if (ctx->highmem > 0) {
434309647Sglebius                if (gaddr >= 4*GB) {
435309647Sglebius			if (gaddr < 4*GB + ctx->highmem &&
436309647Sglebius			    len <= ctx->highmem &&
437309647Sglebius			    gaddr + len <= 4*GB + ctx->highmem)
438309647Sglebius				return (ctx->baseaddr + gaddr);
439309647Sglebius		}
440284688Sneel	}
441284688Sneel
442284688Sneel	return (NULL);
443248477Sneel}
444248477Sneel
445267811Sneelsize_t
446267811Sneelvm_get_lowmem_size(struct vmctx *ctx)
447267811Sneel{
448267811Sneel
449267811Sneel	return (ctx->lowmem);
450267811Sneel}
451267811Sneel
452267811Sneelsize_t
453267811Sneelvm_get_highmem_size(struct vmctx *ctx)
454267811Sneel{
455267811Sneel
456267811Sneel	return (ctx->highmem);
457267811Sneel}
458267811Sneel
459284539Sneelvoid *
460284539Sneelvm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
461284539Sneel{
462284539Sneel	char pathname[MAXPATHLEN];
463284539Sneel	size_t len2;
464284539Sneel	char *base, *ptr;
465284539Sneel	int fd, error, flags;
466284539Sneel
467284539Sneel	fd = -1;
468284539Sneel	ptr = MAP_FAILED;
469284539Sneel	if (name == NULL || strlen(name) == 0) {
470284539Sneel		errno = EINVAL;
471284539Sneel		goto done;
472284539Sneel	}
473284539Sneel
474284539Sneel	error = vm_alloc_memseg(ctx, segid, len, name);
475284539Sneel	if (error)
476284539Sneel		goto done;
477284539Sneel
478285218Sneel	strlcpy(pathname, "/dev/vmm.io/", sizeof(pathname));
479284539Sneel	strlcat(pathname, ctx->name, sizeof(pathname));
480284539Sneel	strlcat(pathname, ".", sizeof(pathname));
481284539Sneel	strlcat(pathname, name, sizeof(pathname));
482284539Sneel
483284539Sneel	fd = open(pathname, O_RDWR);
484284539Sneel	if (fd < 0)
485284539Sneel		goto done;
486284539Sneel
487284539Sneel	/*
488284539Sneel	 * Stake out a contiguous region covering the device memory and the
489284539Sneel	 * adjoining guard regions.
490284539Sneel	 */
491284539Sneel	len2 = VM_MMAP_GUARD_SIZE + len + VM_MMAP_GUARD_SIZE;
492340534Sjhb	base = mmap(NULL, len2, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1,
493340534Sjhb	    0);
494284539Sneel	if (base == MAP_FAILED)
495284539Sneel		goto done;
496284539Sneel
497284539Sneel	flags = MAP_SHARED | MAP_FIXED;
498284539Sneel	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
499284539Sneel		flags |= MAP_NOCORE;
500284539Sneel
501284539Sneel	/* mmap the devmem region in the host address space */
502284539Sneel	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, fd, 0);
503284539Sneeldone:
504284539Sneel	if (fd >= 0)
505284539Sneel		close(fd);
506284539Sneel	return (ptr);
507284539Sneel}
508284539Sneel
509221828Sgrehanint
510221828Sgrehanvm_set_desc(struct vmctx *ctx, int vcpu, int reg,
511221828Sgrehan	    uint64_t base, uint32_t limit, uint32_t access)
512221828Sgrehan{
513221828Sgrehan	int error;
514221828Sgrehan	struct vm_seg_desc vmsegdesc;
515221828Sgrehan
516221828Sgrehan	bzero(&vmsegdesc, sizeof(vmsegdesc));
517221828Sgrehan	vmsegdesc.cpuid = vcpu;
518221828Sgrehan	vmsegdesc.regnum = reg;
519221828Sgrehan	vmsegdesc.desc.base = base;
520221828Sgrehan	vmsegdesc.desc.limit = limit;
521221828Sgrehan	vmsegdesc.desc.access = access;
522221828Sgrehan
523221828Sgrehan	error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
524221828Sgrehan	return (error);
525221828Sgrehan}
526221828Sgrehan
527221828Sgrehanint
528221828Sgrehanvm_get_desc(struct vmctx *ctx, int vcpu, int reg,
529221828Sgrehan	    uint64_t *base, uint32_t *limit, uint32_t *access)
530221828Sgrehan{
531221828Sgrehan	int error;
532221828Sgrehan	struct vm_seg_desc vmsegdesc;
533221828Sgrehan
534221828Sgrehan	bzero(&vmsegdesc, sizeof(vmsegdesc));
535221828Sgrehan	vmsegdesc.cpuid = vcpu;
536221828Sgrehan	vmsegdesc.regnum = reg;
537221828Sgrehan
538221828Sgrehan	error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
539221828Sgrehan	if (error == 0) {
540221828Sgrehan		*base = vmsegdesc.desc.base;
541221828Sgrehan		*limit = vmsegdesc.desc.limit;
542221828Sgrehan		*access = vmsegdesc.desc.access;
543221828Sgrehan	}
544221828Sgrehan	return (error);
545221828Sgrehan}
546221828Sgrehan
547221828Sgrehanint
548269008Sneelvm_get_seg_desc(struct vmctx *ctx, int vcpu, int reg, struct seg_desc *seg_desc)
549269008Sneel{
550269008Sneel	int error;
551269008Sneel
552269008Sneel	error = vm_get_desc(ctx, vcpu, reg, &seg_desc->base, &seg_desc->limit,
553269008Sneel	    &seg_desc->access);
554269008Sneel	return (error);
555269008Sneel}
556269008Sneel
557269008Sneelint
558221828Sgrehanvm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
559221828Sgrehan{
560221828Sgrehan	int error;
561221828Sgrehan	struct vm_register vmreg;
562221828Sgrehan
563221828Sgrehan	bzero(&vmreg, sizeof(vmreg));
564221828Sgrehan	vmreg.cpuid = vcpu;
565221828Sgrehan	vmreg.regnum = reg;
566221828Sgrehan	vmreg.regval = val;
567221828Sgrehan
568221828Sgrehan	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
569221828Sgrehan	return (error);
570221828Sgrehan}
571221828Sgrehan
572221828Sgrehanint
573221828Sgrehanvm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
574221828Sgrehan{
575221828Sgrehan	int error;
576221828Sgrehan	struct vm_register vmreg;
577221828Sgrehan
578221828Sgrehan	bzero(&vmreg, sizeof(vmreg));
579221828Sgrehan	vmreg.cpuid = vcpu;
580221828Sgrehan	vmreg.regnum = reg;
581221828Sgrehan
582221828Sgrehan	error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
583221828Sgrehan	*ret_val = vmreg.regval;
584221828Sgrehan	return (error);
585221828Sgrehan}
586221828Sgrehan
587221828Sgrehanint
588277310Sneelvm_run(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit)
589221828Sgrehan{
590221828Sgrehan	int error;
591221828Sgrehan	struct vm_run vmrun;
592221828Sgrehan
593221828Sgrehan	bzero(&vmrun, sizeof(vmrun));
594221828Sgrehan	vmrun.cpuid = vcpu;
595221828Sgrehan
596221828Sgrehan	error = ioctl(ctx->fd, VM_RUN, &vmrun);
597221828Sgrehan	bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit));
598221828Sgrehan	return (error);
599221828Sgrehan}
600221828Sgrehan
601263780Sneelint
602265062Sneelvm_suspend(struct vmctx *ctx, enum vm_suspend_how how)
603263780Sneel{
604265062Sneel	struct vm_suspend vmsuspend;
605263780Sneel
606265062Sneel	bzero(&vmsuspend, sizeof(vmsuspend));
607265062Sneel	vmsuspend.how = how;
608265062Sneel	return (ioctl(ctx->fd, VM_SUSPEND, &vmsuspend));
609263780Sneel}
610263780Sneel
611267216Sneelint
612267216Sneelvm_reinit(struct vmctx *ctx)
613267216Sneel{
614267216Sneel
615267216Sneel	return (ioctl(ctx->fd, VM_REINIT, 0));
616267216Sneel}
617267216Sneel
618277310Sneelint
619277310Sneelvm_inject_exception(struct vmctx *ctx, int vcpu, int vector, int errcode_valid,
620277310Sneel    uint32_t errcode, int restart_instruction)
621221828Sgrehan{
622262506Sneel	struct vm_exception exc;
623221828Sgrehan
624262506Sneel	exc.cpuid = vcpu;
625262506Sneel	exc.vector = vector;
626277310Sneel	exc.error_code = errcode;
627277310Sneel	exc.error_code_valid = errcode_valid;
628277310Sneel	exc.restart_instruction = restart_instruction;
629221828Sgrehan
630262506Sneel	return (ioctl(ctx->fd, VM_INJECT_EXCEPTION, &exc));
631221828Sgrehan}
632221828Sgrehan
633221828Sgrehanint
634239026Sneelvm_apicid2vcpu(struct vmctx *ctx, int apicid)
635239026Sneel{
636239026Sneel	/*
637239026Sneel	 * The apic id associated with the 'vcpu' has the same numerical value
638239026Sneel	 * as the 'vcpu' itself.
639239026Sneel	 */
640239026Sneel	return (apicid);
641239026Sneel}
642239026Sneel
643239026Sneelint
644221828Sgrehanvm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
645221828Sgrehan{
646221828Sgrehan	struct vm_lapic_irq vmirq;
647221828Sgrehan
648221828Sgrehan	bzero(&vmirq, sizeof(vmirq));
649221828Sgrehan	vmirq.cpuid = vcpu;
650221828Sgrehan	vmirq.vector = vector;
651221828Sgrehan
652221828Sgrehan	return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
653221828Sgrehan}
654221828Sgrehan
655221828Sgrehanint
656259779Sjhbvm_lapic_local_irq(struct vmctx *ctx, int vcpu, int vector)
657259779Sjhb{
658259779Sjhb	struct vm_lapic_irq vmirq;
659259779Sjhb
660259779Sjhb	bzero(&vmirq, sizeof(vmirq));
661259779Sjhb	vmirq.cpuid = vcpu;
662259779Sjhb	vmirq.vector = vector;
663259779Sjhb
664259779Sjhb	return (ioctl(ctx->fd, VM_LAPIC_LOCAL_IRQ, &vmirq));
665259779Sjhb}
666259779Sjhb
667259779Sjhbint
668259482Sneelvm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg)
669259482Sneel{
670259482Sneel	struct vm_lapic_msi vmmsi;
671259482Sneel
672259482Sneel	bzero(&vmmsi, sizeof(vmmsi));
673259482Sneel	vmmsi.addr = addr;
674259482Sneel	vmmsi.msg = msg;
675259482Sneel
676259482Sneel	return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi));
677259482Sneel}
678259482Sneel
679259482Sneelint
680258075Sneelvm_ioapic_assert_irq(struct vmctx *ctx, int irq)
681258075Sneel{
682258075Sneel	struct vm_ioapic_irq ioapic_irq;
683258075Sneel
684258075Sneel	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
685258075Sneel	ioapic_irq.irq = irq;
686258075Sneel
687258075Sneel	return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
688258075Sneel}
689258075Sneel
690258075Sneelint
691258075Sneelvm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
692258075Sneel{
693258075Sneel	struct vm_ioapic_irq ioapic_irq;
694258075Sneel
695258075Sneel	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
696258075Sneel	ioapic_irq.irq = irq;
697258075Sneel
698258075Sneel	return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
699258075Sneel}
700258075Sneel
701258075Sneelint
702258494Sneelvm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
703258494Sneel{
704258494Sneel	struct vm_ioapic_irq ioapic_irq;
705258494Sneel
706258494Sneel	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
707258494Sneel	ioapic_irq.irq = irq;
708258494Sneel
709258494Sneel	return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
710258494Sneel}
711258494Sneel
712258494Sneelint
713261268Sjhbvm_ioapic_pincount(struct vmctx *ctx, int *pincount)
714261268Sjhb{
715261268Sjhb
716261268Sjhb	return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
717261268Sjhb}
718261268Sjhb
719261268Sjhbint
720263035Stychonvm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
721263035Stychon{
722263035Stychon	struct vm_isa_irq isa_irq;
723263035Stychon
724263035Stychon	bzero(&isa_irq, sizeof(struct vm_isa_irq));
725263035Stychon	isa_irq.atpic_irq = atpic_irq;
726263035Stychon	isa_irq.ioapic_irq = ioapic_irq;
727263035Stychon
728263035Stychon	return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq));
729263035Stychon}
730263035Stychon
731263035Stychonint
732263035Stychonvm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
733263035Stychon{
734263035Stychon	struct vm_isa_irq isa_irq;
735263035Stychon
736263035Stychon	bzero(&isa_irq, sizeof(struct vm_isa_irq));
737263035Stychon	isa_irq.atpic_irq = atpic_irq;
738263035Stychon	isa_irq.ioapic_irq = ioapic_irq;
739263035Stychon
740263035Stychon	return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq));
741263035Stychon}
742263035Stychon
743263035Stychonint
744263035Stychonvm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
745263035Stychon{
746263035Stychon	struct vm_isa_irq isa_irq;
747266125Sjhb
748263035Stychon	bzero(&isa_irq, sizeof(struct vm_isa_irq));
749263035Stychon	isa_irq.atpic_irq = atpic_irq;
750263035Stychon	isa_irq.ioapic_irq = ioapic_irq;
751263035Stychon
752263035Stychon	return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq));
753263035Stychon}
754263035Stychon
755263035Stychonint
756266125Sjhbvm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq,
757266125Sjhb    enum vm_intr_trigger trigger)
758266125Sjhb{
759266125Sjhb	struct vm_isa_irq_trigger isa_irq_trigger;
760266125Sjhb
761266125Sjhb	bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger));
762266125Sjhb	isa_irq_trigger.atpic_irq = atpic_irq;
763266125Sjhb	isa_irq_trigger.trigger = trigger;
764266125Sjhb
765266125Sjhb	return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger));
766266125Sjhb}
767266125Sjhb
768266125Sjhbint
769221828Sgrehanvm_inject_nmi(struct vmctx *ctx, int vcpu)
770221828Sgrehan{
771221828Sgrehan	struct vm_nmi vmnmi;
772221828Sgrehan
773221828Sgrehan	bzero(&vmnmi, sizeof(vmnmi));
774221828Sgrehan	vmnmi.cpuid = vcpu;
775221828Sgrehan
776221828Sgrehan	return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
777221828Sgrehan}
778221828Sgrehan
779241486Sneelstatic struct {
780241486Sneel	const char	*name;
781241486Sneel	int		type;
782241486Sneel} capstrmap[] = {
783241486Sneel	{ "hlt_exit",		VM_CAP_HALT_EXIT },
784241486Sneel	{ "mtrap_exit",		VM_CAP_MTRAP_EXIT },
785241486Sneel	{ "pause_exit",		VM_CAP_PAUSE_EXIT },
786241486Sneel	{ "unrestricted_guest",	VM_CAP_UNRESTRICTED_GUEST },
787256645Sneel	{ "enable_invpcid",	VM_CAP_ENABLE_INVPCID },
788241486Sneel	{ 0 }
789241486Sneel};
790241486Sneel
791221828Sgrehanint
792221828Sgrehanvm_capability_name2type(const char *capname)
793221828Sgrehan{
794221828Sgrehan	int i;
795221828Sgrehan
796221828Sgrehan	for (i = 0; capstrmap[i].name != NULL && capname != NULL; i++) {
797221828Sgrehan		if (strcmp(capstrmap[i].name, capname) == 0)
798221828Sgrehan			return (capstrmap[i].type);
799221828Sgrehan	}
800221828Sgrehan
801221828Sgrehan	return (-1);
802221828Sgrehan}
803221828Sgrehan
804241486Sneelconst char *
805241486Sneelvm_capability_type2name(int type)
806241486Sneel{
807241486Sneel	int i;
808241486Sneel
809241486Sneel	for (i = 0; capstrmap[i].name != NULL; i++) {
810241486Sneel		if (capstrmap[i].type == type)
811241486Sneel			return (capstrmap[i].name);
812241486Sneel	}
813241486Sneel
814241486Sneel	return (NULL);
815241486Sneel}
816241486Sneel
817221828Sgrehanint
818221828Sgrehanvm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
819221828Sgrehan		  int *retval)
820221828Sgrehan{
821221828Sgrehan	int error;
822221828Sgrehan	struct vm_capability vmcap;
823221828Sgrehan
824221828Sgrehan	bzero(&vmcap, sizeof(vmcap));
825221828Sgrehan	vmcap.cpuid = vcpu;
826221828Sgrehan	vmcap.captype = cap;
827221828Sgrehan
828221828Sgrehan	error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
829221828Sgrehan	*retval = vmcap.capval;
830221828Sgrehan	return (error);
831221828Sgrehan}
832221828Sgrehan
833221828Sgrehanint
834221828Sgrehanvm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
835221828Sgrehan{
836221828Sgrehan	struct vm_capability vmcap;
837221828Sgrehan
838221828Sgrehan	bzero(&vmcap, sizeof(vmcap));
839221828Sgrehan	vmcap.cpuid = vcpu;
840221828Sgrehan	vmcap.captype = cap;
841221828Sgrehan	vmcap.capval = val;
842336161Saraujo
843221828Sgrehan	return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
844221828Sgrehan}
845221828Sgrehan
846221828Sgrehanint
847221828Sgrehanvm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
848221828Sgrehan{
849221828Sgrehan	struct vm_pptdev pptdev;
850221828Sgrehan
851221828Sgrehan	bzero(&pptdev, sizeof(pptdev));
852221828Sgrehan	pptdev.bus = bus;
853221828Sgrehan	pptdev.slot = slot;
854221828Sgrehan	pptdev.func = func;
855221828Sgrehan
856221828Sgrehan	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
857221828Sgrehan}
858221828Sgrehan
859221828Sgrehanint
860221828Sgrehanvm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
861221828Sgrehan{
862221828Sgrehan	struct vm_pptdev pptdev;
863221828Sgrehan
864221828Sgrehan	bzero(&pptdev, sizeof(pptdev));
865221828Sgrehan	pptdev.bus = bus;
866221828Sgrehan	pptdev.slot = slot;
867221828Sgrehan	pptdev.func = func;
868221828Sgrehan
869221828Sgrehan	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
870221828Sgrehan}
871221828Sgrehan
872221828Sgrehanint
873221828Sgrehanvm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
874221828Sgrehan		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
875221828Sgrehan{
876221828Sgrehan	struct vm_pptdev_mmio pptmmio;
877221828Sgrehan
878221828Sgrehan	bzero(&pptmmio, sizeof(pptmmio));
879221828Sgrehan	pptmmio.bus = bus;
880221828Sgrehan	pptmmio.slot = slot;
881221828Sgrehan	pptmmio.func = func;
882221828Sgrehan	pptmmio.gpa = gpa;
883221828Sgrehan	pptmmio.len = len;
884221828Sgrehan	pptmmio.hpa = hpa;
885221828Sgrehan
886221828Sgrehan	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
887221828Sgrehan}
888221828Sgrehan
889221828Sgrehanint
890259537Sneelvm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
891259537Sneel    uint64_t addr, uint64_t msg, int numvec)
892221828Sgrehan{
893221828Sgrehan	struct vm_pptdev_msi pptmsi;
894221828Sgrehan
895221828Sgrehan	bzero(&pptmsi, sizeof(pptmsi));
896221828Sgrehan	pptmsi.vcpu = vcpu;
897221828Sgrehan	pptmsi.bus = bus;
898221828Sgrehan	pptmsi.slot = slot;
899221828Sgrehan	pptmsi.func = func;
900259482Sneel	pptmsi.msg = msg;
901259482Sneel	pptmsi.addr = addr;
902221828Sgrehan	pptmsi.numvec = numvec;
903221828Sgrehan
904221828Sgrehan	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
905221828Sgrehan}
906221828Sgrehan
907234761Sgrehanint
908259537Sneelvm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
909259537Sneel    int idx, uint64_t addr, uint64_t msg, uint32_t vector_control)
910234761Sgrehan{
911234761Sgrehan	struct vm_pptdev_msix pptmsix;
912234761Sgrehan
913234761Sgrehan	bzero(&pptmsix, sizeof(pptmsix));
914234761Sgrehan	pptmsix.vcpu = vcpu;
915234761Sgrehan	pptmsix.bus = bus;
916234761Sgrehan	pptmsix.slot = slot;
917234761Sgrehan	pptmsix.func = func;
918234761Sgrehan	pptmsix.idx = idx;
919234761Sgrehan	pptmsix.msg = msg;
920234761Sgrehan	pptmsix.addr = addr;
921234761Sgrehan	pptmsix.vector_control = vector_control;
922234761Sgrehan
923234761Sgrehan	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
924234761Sgrehan}
925234761Sgrehan
926221828Sgrehanuint64_t *
927221828Sgrehanvm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
928221828Sgrehan	     int *ret_entries)
929221828Sgrehan{
930221828Sgrehan	int error;
931221828Sgrehan
932221828Sgrehan	static struct vm_stats vmstats;
933221828Sgrehan
934221828Sgrehan	vmstats.cpuid = vcpu;
935221828Sgrehan
936221828Sgrehan	error = ioctl(ctx->fd, VM_STATS, &vmstats);
937221828Sgrehan	if (error == 0) {
938221828Sgrehan		if (ret_entries)
939221828Sgrehan			*ret_entries = vmstats.num_entries;
940221828Sgrehan		if (ret_tv)
941221828Sgrehan			*ret_tv = vmstats.tv;
942221828Sgrehan		return (vmstats.statbuf);
943221828Sgrehan	} else
944221828Sgrehan		return (NULL);
945221828Sgrehan}
946221828Sgrehan
947221828Sgrehanconst char *
948221828Sgrehanvm_get_stat_desc(struct vmctx *ctx, int index)
949221828Sgrehan{
950221828Sgrehan	static struct vm_stat_desc statdesc;
951221828Sgrehan
952221828Sgrehan	statdesc.index = index;
953221828Sgrehan	if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
954221828Sgrehan		return (statdesc.desc);
955221828Sgrehan	else
956221828Sgrehan		return (NULL);
957221828Sgrehan}
958221828Sgrehan
959240922Sneelint
960240922Sneelvm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *state)
961240922Sneel{
962240922Sneel	int error;
963240922Sneel	struct vm_x2apic x2apic;
964240922Sneel
965240922Sneel	bzero(&x2apic, sizeof(x2apic));
966240922Sneel	x2apic.cpuid = vcpu;
967240922Sneel
968240922Sneel	error = ioctl(ctx->fd, VM_GET_X2APIC_STATE, &x2apic);
969240922Sneel	*state = x2apic.state;
970240922Sneel	return (error);
971240922Sneel}
972240922Sneel
973240922Sneelint
974240922Sneelvm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state state)
975240922Sneel{
976240922Sneel	int error;
977240922Sneel	struct vm_x2apic x2apic;
978240922Sneel
979240922Sneel	bzero(&x2apic, sizeof(x2apic));
980240922Sneel	x2apic.cpuid = vcpu;
981240922Sneel	x2apic.state = state;
982240922Sneel
983240922Sneel	error = ioctl(ctx->fd, VM_SET_X2APIC_STATE, &x2apic);
984240922Sneel
985240922Sneel	return (error);
986240922Sneel}
987240922Sneel
988221828Sgrehan/*
989221828Sgrehan * From Intel Vol 3a:
990221828Sgrehan * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
991221828Sgrehan */
992221828Sgrehanint
993221828Sgrehanvcpu_reset(struct vmctx *vmctx, int vcpu)
994221828Sgrehan{
995221828Sgrehan	int error;
996221828Sgrehan	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
997221828Sgrehan	uint32_t desc_access, desc_limit;
998221828Sgrehan	uint16_t sel;
999221828Sgrehan
1000221828Sgrehan	zero = 0;
1001221828Sgrehan
1002221828Sgrehan	rflags = 0x2;
1003221828Sgrehan	error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
1004221828Sgrehan	if (error)
1005221828Sgrehan		goto done;
1006221828Sgrehan
1007221828Sgrehan	rip = 0xfff0;
1008221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
1009221828Sgrehan		goto done;
1010221828Sgrehan
1011221828Sgrehan	cr0 = CR0_NE;
1012221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
1013221828Sgrehan		goto done;
1014221828Sgrehan
1015221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0)
1016221828Sgrehan		goto done;
1017221828Sgrehan
1018239025Sneel	cr4 = 0;
1019221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
1020221828Sgrehan		goto done;
1021221828Sgrehan
1022221828Sgrehan	/*
1023221828Sgrehan	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
1024221828Sgrehan	 */
1025221828Sgrehan	desc_base = 0xffff0000;
1026221828Sgrehan	desc_limit = 0xffff;
1027221828Sgrehan	desc_access = 0x0093;
1028221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
1029221828Sgrehan			    desc_base, desc_limit, desc_access);
1030221828Sgrehan	if (error)
1031221828Sgrehan		goto done;
1032221828Sgrehan
1033221828Sgrehan	sel = 0xf000;
1034221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, sel)) != 0)
1035221828Sgrehan		goto done;
1036221828Sgrehan
1037221828Sgrehan	/*
1038221828Sgrehan	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
1039221828Sgrehan	 */
1040221828Sgrehan	desc_base = 0;
1041221828Sgrehan	desc_limit = 0xffff;
1042221828Sgrehan	desc_access = 0x0093;
1043221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
1044221828Sgrehan			    desc_base, desc_limit, desc_access);
1045221828Sgrehan	if (error)
1046221828Sgrehan		goto done;
1047221828Sgrehan
1048221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
1049221828Sgrehan			    desc_base, desc_limit, desc_access);
1050221828Sgrehan	if (error)
1051221828Sgrehan		goto done;
1052221828Sgrehan
1053221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
1054221828Sgrehan			    desc_base, desc_limit, desc_access);
1055221828Sgrehan	if (error)
1056221828Sgrehan		goto done;
1057221828Sgrehan
1058221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
1059221828Sgrehan			    desc_base, desc_limit, desc_access);
1060221828Sgrehan	if (error)
1061221828Sgrehan		goto done;
1062221828Sgrehan
1063221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
1064221828Sgrehan			    desc_base, desc_limit, desc_access);
1065221828Sgrehan	if (error)
1066221828Sgrehan		goto done;
1067221828Sgrehan
1068221828Sgrehan	sel = 0;
1069221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, sel)) != 0)
1070221828Sgrehan		goto done;
1071221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, sel)) != 0)
1072221828Sgrehan		goto done;
1073221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, sel)) != 0)
1074221828Sgrehan		goto done;
1075221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, sel)) != 0)
1076221828Sgrehan		goto done;
1077221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0)
1078221828Sgrehan		goto done;
1079221828Sgrehan
1080221828Sgrehan	/* General purpose registers */
1081221828Sgrehan	rdx = 0xf00;
1082221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0)
1083221828Sgrehan		goto done;
1084221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBX, zero)) != 0)
1085221828Sgrehan		goto done;
1086221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RCX, zero)) != 0)
1087221828Sgrehan		goto done;
1088221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
1089221828Sgrehan		goto done;
1090221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSI, zero)) != 0)
1091221828Sgrehan		goto done;
1092221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDI, zero)) != 0)
1093221828Sgrehan		goto done;
1094221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBP, zero)) != 0)
1095221828Sgrehan		goto done;
1096221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0)
1097221828Sgrehan		goto done;
1098221828Sgrehan
1099221828Sgrehan	/* GDTR, IDTR */
1100221828Sgrehan	desc_base = 0;
1101221828Sgrehan	desc_limit = 0xffff;
1102221828Sgrehan	desc_access = 0;
1103221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
1104221828Sgrehan			    desc_base, desc_limit, desc_access);
1105221828Sgrehan	if (error != 0)
1106221828Sgrehan		goto done;
1107221828Sgrehan
1108221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_IDTR,
1109221828Sgrehan			    desc_base, desc_limit, desc_access);
1110221828Sgrehan	if (error != 0)
1111221828Sgrehan		goto done;
1112221828Sgrehan
1113221828Sgrehan	/* TR */
1114221828Sgrehan	desc_base = 0;
1115221828Sgrehan	desc_limit = 0xffff;
1116221828Sgrehan	desc_access = 0x0000008b;
1117221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
1118221828Sgrehan	if (error)
1119221828Sgrehan		goto done;
1120221828Sgrehan
1121221828Sgrehan	sel = 0;
1122221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, sel)) != 0)
1123221828Sgrehan		goto done;
1124221828Sgrehan
1125221828Sgrehan	/* LDTR */
1126221828Sgrehan	desc_base = 0;
1127221828Sgrehan	desc_limit = 0xffff;
1128221828Sgrehan	desc_access = 0x00000082;
1129221828Sgrehan	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, desc_base,
1130221828Sgrehan			    desc_limit, desc_access);
1131221828Sgrehan	if (error)
1132221828Sgrehan		goto done;
1133221828Sgrehan
1134221828Sgrehan	sel = 0;
1135221828Sgrehan	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
1136221828Sgrehan		goto done;
1137221828Sgrehan
1138221828Sgrehan	/* XXX cr2, debug registers */
1139221828Sgrehan
1140221828Sgrehan	error = 0;
1141221828Sgrehandone:
1142221828Sgrehan	return (error);
1143221828Sgrehan}
1144256072Sneel
1145256072Sneelint
1146256072Sneelvm_get_gpa_pmap(struct vmctx *ctx, uint64_t gpa, uint64_t *pte, int *num)
1147256072Sneel{
1148256072Sneel	int error, i;
1149256072Sneel	struct vm_gpa_pte gpapte;
1150256072Sneel
1151256072Sneel	bzero(&gpapte, sizeof(gpapte));
1152256072Sneel	gpapte.gpa = gpa;
1153256072Sneel
1154256072Sneel	error = ioctl(ctx->fd, VM_GET_GPA_PMAP, &gpapte);
1155256072Sneel
1156256072Sneel	if (error == 0) {
1157256072Sneel		*num = gpapte.ptenum;
1158256072Sneel		for (i = 0; i < gpapte.ptenum; i++)
1159256072Sneel			pte[i] = gpapte.pte[i];
1160256072Sneel	}
1161256072Sneel
1162256072Sneel	return (error);
1163256072Sneel}
1164258579Sneel
1165258579Sneelint
1166258579Sneelvm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
1167258579Sneel{
1168258579Sneel	int error;
1169258579Sneel	struct vm_hpet_cap cap;
1170258579Sneel
1171258579Sneel	bzero(&cap, sizeof(struct vm_hpet_cap));
1172258579Sneel	error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap);
1173258579Sneel	if (capabilities != NULL)
1174258579Sneel		*capabilities = cap.capabilities;
1175258579Sneel	return (error);
1176258579Sneel}
1177266633Sneel
1178282558Sneelint
1179282558Sneelvm_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
1180282558Sneel    uint64_t gla, int prot, uint64_t *gpa, int *fault)
1181266633Sneel{
1182266633Sneel	struct vm_gla2gpa gg;
1183266633Sneel	int error;
1184266633Sneel
1185266633Sneel	bzero(&gg, sizeof(struct vm_gla2gpa));
1186266633Sneel	gg.vcpuid = vcpu;
1187266633Sneel	gg.prot = prot;
1188266633Sneel	gg.gla = gla;
1189266633Sneel	gg.paging = *paging;
1190266633Sneel
1191266633Sneel	error = ioctl(ctx->fd, VM_GLA2GPA, &gg);
1192266633Sneel	if (error == 0) {
1193266633Sneel		*fault = gg.fault;
1194266633Sneel		*gpa = gg.gpa;
1195266633Sneel	}
1196266633Sneel	return (error);
1197266633Sneel}
1198266633Sneel
1199266633Sneel#ifndef min
1200266633Sneel#define	min(a,b)	(((a) < (b)) ? (a) : (b))
1201266633Sneel#endif
1202266633Sneel
1203266633Sneelint
1204269008Sneelvm_copy_setup(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
1205282558Sneel    uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt,
1206282558Sneel    int *fault)
1207266633Sneel{
1208277359Sneel	void *va;
1209266633Sneel	uint64_t gpa;
1210282558Sneel	int error, i, n, off;
1211266633Sneel
1212266708Sneel	for (i = 0; i < iovcnt; i++) {
1213266708Sneel		iov[i].iov_base = 0;
1214266708Sneel		iov[i].iov_len = 0;
1215266708Sneel	}
1216266708Sneel
1217266633Sneel	while (len) {
1218266708Sneel		assert(iovcnt > 0);
1219282558Sneel		error = vm_gla2gpa(ctx, vcpu, paging, gla, prot, &gpa, fault);
1220282558Sneel		if (error || *fault)
1221282558Sneel			return (error);
1222266633Sneel
1223266633Sneel		off = gpa & PAGE_MASK;
1224266633Sneel		n = min(len, PAGE_SIZE - off);
1225266708Sneel
1226277359Sneel		va = vm_map_gpa(ctx, gpa, n);
1227277359Sneel		if (va == NULL)
1228282558Sneel			return (EFAULT);
1229277359Sneel
1230277359Sneel		iov->iov_base = va;
1231266708Sneel		iov->iov_len = n;
1232266708Sneel		iov++;
1233266708Sneel		iovcnt--;
1234266708Sneel
1235266708Sneel		gla += n;
1236266708Sneel		len -= n;
1237266708Sneel	}
1238266708Sneel	return (0);
1239266708Sneel}
1240266708Sneel
1241266708Sneelvoid
1242277359Sneelvm_copy_teardown(struct vmctx *ctx, int vcpu, struct iovec *iov, int iovcnt)
1243277359Sneel{
1244277359Sneel
1245277359Sneel	return;
1246277359Sneel}
1247277359Sneel
1248277359Sneelvoid
1249266708Sneelvm_copyin(struct vmctx *ctx, int vcpu, struct iovec *iov, void *vp, size_t len)
1250266708Sneel{
1251266708Sneel	const char *src;
1252266708Sneel	char *dst;
1253266708Sneel	size_t n;
1254266708Sneel
1255266708Sneel	dst = vp;
1256266708Sneel	while (len) {
1257266708Sneel		assert(iov->iov_len);
1258266708Sneel		n = min(len, iov->iov_len);
1259277359Sneel		src = iov->iov_base;
1260266633Sneel		bcopy(src, dst, n);
1261266633Sneel
1262266708Sneel		iov++;
1263266633Sneel		dst += n;
1264266633Sneel		len -= n;
1265266633Sneel	}
1266266633Sneel}
1267266633Sneel
1268266708Sneelvoid
1269266708Sneelvm_copyout(struct vmctx *ctx, int vcpu, const void *vp, struct iovec *iov,
1270266708Sneel    size_t len)
1271266633Sneel{
1272266708Sneel	const char *src;
1273266708Sneel	char *dst;
1274266708Sneel	size_t n;
1275266633Sneel
1276266633Sneel	src = vp;
1277266633Sneel	while (len) {
1278266708Sneel		assert(iov->iov_len);
1279266708Sneel		n = min(len, iov->iov_len);
1280277359Sneel		dst = iov->iov_base;
1281266633Sneel		bcopy(src, dst, n);
1282266633Sneel
1283266708Sneel		iov++;
1284266633Sneel		src += n;
1285266633Sneel		len -= n;
1286266633Sneel	}
1287266633Sneel}
1288266933Sneel
1289266933Sneelstatic int
1290266933Sneelvm_get_cpus(struct vmctx *ctx, int which, cpuset_t *cpus)
1291266933Sneel{
1292266933Sneel	struct vm_cpuset vm_cpuset;
1293266933Sneel	int error;
1294266933Sneel
1295266933Sneel	bzero(&vm_cpuset, sizeof(struct vm_cpuset));
1296266933Sneel	vm_cpuset.which = which;
1297266933Sneel	vm_cpuset.cpusetsize = sizeof(cpuset_t);
1298266933Sneel	vm_cpuset.cpus = cpus;
1299266933Sneel
1300266933Sneel	error = ioctl(ctx->fd, VM_GET_CPUS, &vm_cpuset);
1301266933Sneel	return (error);
1302266933Sneel}
1303266933Sneel
1304266933Sneelint
1305266933Sneelvm_active_cpus(struct vmctx *ctx, cpuset_t *cpus)
1306266933Sneel{
1307266933Sneel
1308266933Sneel	return (vm_get_cpus(ctx, VM_ACTIVE_CPUS, cpus));
1309266933Sneel}
1310266933Sneel
1311266933Sneelint
1312266933Sneelvm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus)
1313266933Sneel{
1314266933Sneel
1315266933Sneel	return (vm_get_cpus(ctx, VM_SUSPENDED_CPUS, cpus));
1316266933Sneel}
1317266933Sneel
1318266933Sneelint
1319266933Sneelvm_activate_cpu(struct vmctx *ctx, int vcpu)
1320266933Sneel{
1321266933Sneel	struct vm_activate_cpu ac;
1322266933Sneel	int error;
1323266933Sneel
1324266933Sneel	bzero(&ac, sizeof(struct vm_activate_cpu));
1325266933Sneel	ac.vcpuid = vcpu;
1326266933Sneel	error = ioctl(ctx->fd, VM_ACTIVATE_CPU, &ac);
1327266933Sneel	return (error);
1328266933Sneel}
1329268889Sneel
1330268889Sneelint
1331268889Sneelvm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *info1, uint64_t *info2)
1332268889Sneel{
1333268889Sneel	struct vm_intinfo vmii;
1334268889Sneel	int error;
1335268889Sneel
1336268889Sneel	bzero(&vmii, sizeof(struct vm_intinfo));
1337268889Sneel	vmii.vcpuid = vcpu;
1338268889Sneel	error = ioctl(ctx->fd, VM_GET_INTINFO, &vmii);
1339268889Sneel	if (error == 0) {
1340268889Sneel		*info1 = vmii.info1;
1341268889Sneel		*info2 = vmii.info2;
1342268889Sneel	}
1343268889Sneel	return (error);
1344268889Sneel}
1345268889Sneel
1346268889Sneelint
1347268889Sneelvm_set_intinfo(struct vmctx *ctx, int vcpu, uint64_t info1)
1348268889Sneel{
1349268889Sneel	struct vm_intinfo vmii;
1350268889Sneel	int error;
1351268889Sneel
1352268889Sneel	bzero(&vmii, sizeof(struct vm_intinfo));
1353268889Sneel	vmii.vcpuid = vcpu;
1354268889Sneel	vmii.info1 = info1;
1355268889Sneel	error = ioctl(ctx->fd, VM_SET_INTINFO, &vmii);
1356268889Sneel	return (error);
1357268889Sneel}
1358276428Sneel
1359276428Sneelint
1360276428Sneelvm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
1361276428Sneel{
1362276428Sneel	struct vm_rtc_data rtcdata;
1363276428Sneel	int error;
1364276428Sneel
1365276428Sneel	bzero(&rtcdata, sizeof(struct vm_rtc_data));
1366276428Sneel	rtcdata.offset = offset;
1367276428Sneel	rtcdata.value = value;
1368276428Sneel	error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
1369276428Sneel	return (error);
1370276428Sneel}
1371276428Sneel
1372276428Sneelint
1373276428Sneelvm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
1374276428Sneel{
1375276428Sneel	struct vm_rtc_data rtcdata;
1376276428Sneel	int error;
1377276428Sneel
1378276428Sneel	bzero(&rtcdata, sizeof(struct vm_rtc_data));
1379276428Sneel	rtcdata.offset = offset;
1380276428Sneel	error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
1381276428Sneel	if (error == 0)
1382276428Sneel		*retval = rtcdata.value;
1383276428Sneel	return (error);
1384276428Sneel}
1385276428Sneel
1386276428Sneelint
1387276428Sneelvm_rtc_settime(struct vmctx *ctx, time_t secs)
1388276428Sneel{
1389276428Sneel	struct vm_rtc_time rtctime;
1390276428Sneel	int error;
1391276428Sneel
1392276428Sneel	bzero(&rtctime, sizeof(struct vm_rtc_time));
1393276428Sneel	rtctime.secs = secs;
1394276428Sneel	error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
1395276428Sneel	return (error);
1396276428Sneel}
1397276428Sneel
1398276428Sneelint
1399276428Sneelvm_rtc_gettime(struct vmctx *ctx, time_t *secs)
1400276428Sneel{
1401276428Sneel	struct vm_rtc_time rtctime;
1402276428Sneel	int error;
1403276428Sneel
1404276428Sneel	bzero(&rtctime, sizeof(struct vm_rtc_time));
1405276428Sneel	error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
1406276428Sneel	if (error == 0)
1407276428Sneel		*secs = rtctime.secs;
1408276428Sneel	return (error);
1409276428Sneel}
1410277310Sneel
1411277310Sneelint
1412277310Sneelvm_restart_instruction(void *arg, int vcpu)
1413277310Sneel{
1414277310Sneel	struct vmctx *ctx = arg;
1415277310Sneel
1416277310Sneel	return (ioctl(ctx->fd, VM_RESTART_INSTRUCTION, &vcpu));
1417277310Sneel}
1418320866Sgrehan
1419320866Sgrehanint
1420348201Srgrimesvm_set_topology(struct vmctx *ctx,
1421348201Srgrimes    uint16_t sockets, uint16_t cores, uint16_t threads, uint16_t maxcpus)
1422348201Srgrimes{
1423348201Srgrimes	struct vm_cpu_topology topology;
1424348201Srgrimes
1425348201Srgrimes	bzero(&topology, sizeof (struct vm_cpu_topology));
1426348201Srgrimes	topology.sockets = sockets;
1427348201Srgrimes	topology.cores = cores;
1428348201Srgrimes	topology.threads = threads;
1429348201Srgrimes	topology.maxcpus = maxcpus;
1430348201Srgrimes	return (ioctl(ctx->fd, VM_SET_TOPOLOGY, &topology));
1431348201Srgrimes}
1432348201Srgrimes
1433348201Srgrimesint
1434348201Srgrimesvm_get_topology(struct vmctx *ctx,
1435348201Srgrimes    uint16_t *sockets, uint16_t *cores, uint16_t *threads, uint16_t *maxcpus)
1436348201Srgrimes{
1437348201Srgrimes	struct vm_cpu_topology topology;
1438348201Srgrimes	int error;
1439348201Srgrimes
1440348201Srgrimes	bzero(&topology, sizeof (struct vm_cpu_topology));
1441348201Srgrimes	error = ioctl(ctx->fd, VM_GET_TOPOLOGY, &topology);
1442348201Srgrimes	if (error == 0) {
1443348201Srgrimes		*sockets = topology.sockets;
1444348201Srgrimes		*cores = topology.cores;
1445348201Srgrimes		*threads = topology.threads;
1446348201Srgrimes		*maxcpus = topology.maxcpus;
1447348201Srgrimes	}
1448348201Srgrimes	return (error);
1449348201Srgrimes}
1450348201Srgrimes
1451348201Srgrimesint
1452320866Sgrehanvm_get_device_fd(struct vmctx *ctx)
1453320866Sgrehan{
1454320866Sgrehan
1455320866Sgrehan	return (ctx->fd);
1456320866Sgrehan}
1457320866Sgrehan
1458320866Sgrehanconst cap_ioctl_t *
1459320866Sgrehanvm_get_ioctls(size_t *len)
1460320866Sgrehan{
1461320866Sgrehan	cap_ioctl_t *cmds;
1462320866Sgrehan	/* keep in sync with machine/vmm_dev.h */
1463320866Sgrehan	static const cap_ioctl_t vm_ioctl_cmds[] = { VM_RUN, VM_SUSPEND, VM_REINIT,
1464320866Sgrehan	    VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
1465320866Sgrehan	    VM_MMAP_GETNEXT, VM_SET_REGISTER, VM_GET_REGISTER,
1466320866Sgrehan	    VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
1467320866Sgrehan	    VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
1468320866Sgrehan	    VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
1469320866Sgrehan	    VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,
1470320866Sgrehan	    VM_ISA_DEASSERT_IRQ, VM_ISA_PULSE_IRQ, VM_ISA_SET_IRQ_TRIGGER,
1471320866Sgrehan	    VM_SET_CAPABILITY, VM_GET_CAPABILITY, VM_BIND_PPTDEV,
1472320866Sgrehan	    VM_UNBIND_PPTDEV, VM_MAP_PPTDEV_MMIO, VM_PPTDEV_MSI,
1473320866Sgrehan	    VM_PPTDEV_MSIX, VM_INJECT_NMI, VM_STATS, VM_STAT_DESC,
1474320866Sgrehan	    VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
1475320866Sgrehan	    VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
1476320866Sgrehan	    VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SET_INTINFO, VM_GET_INTINFO,
1477320866Sgrehan	    VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
1478348201Srgrimes	    VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY };
1479320866Sgrehan
1480320866Sgrehan	if (len == NULL) {
1481320866Sgrehan		cmds = malloc(sizeof(vm_ioctl_cmds));
1482320866Sgrehan		if (cmds == NULL)
1483320866Sgrehan			return (NULL);
1484320866Sgrehan		bcopy(vm_ioctl_cmds, cmds, sizeof(vm_ioctl_cmds));
1485320866Sgrehan		return (cmds);
1486320866Sgrehan	}
1487320866Sgrehan
1488320866Sgrehan	*len = nitems(vm_ioctl_cmds);
1489320866Sgrehan	return (NULL);
1490320866Sgrehan}
1491