xref: /freebsd/lib/libvmmapi/vmmapi.c (revision 0f735657aa762e3b226087a9be6edf95868bc62d)
1366f6083SPeter Grehan /*-
25e53a4f9SPedro F. Giffuni  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
35e53a4f9SPedro F. Giffuni  *
4366f6083SPeter Grehan  * Copyright (c) 2011 NetApp, Inc.
5366f6083SPeter Grehan  * All rights reserved.
6366f6083SPeter Grehan  *
7366f6083SPeter Grehan  * Redistribution and use in source and binary forms, with or without
8366f6083SPeter Grehan  * modification, are permitted provided that the following conditions
9366f6083SPeter Grehan  * are met:
10366f6083SPeter Grehan  * 1. Redistributions of source code must retain the above copyright
11366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer.
12366f6083SPeter Grehan  * 2. Redistributions in binary form must reproduce the above copyright
13366f6083SPeter Grehan  *    notice, this list of conditions and the following disclaimer in the
14366f6083SPeter Grehan  *    documentation and/or other materials provided with the distribution.
15366f6083SPeter Grehan  *
16366f6083SPeter Grehan  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17366f6083SPeter Grehan  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18366f6083SPeter Grehan  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19366f6083SPeter Grehan  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20366f6083SPeter Grehan  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21366f6083SPeter Grehan  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22366f6083SPeter Grehan  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23366f6083SPeter Grehan  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24366f6083SPeter Grehan  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25366f6083SPeter Grehan  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26366f6083SPeter Grehan  * SUCH DAMAGE.
27366f6083SPeter Grehan  *
28366f6083SPeter Grehan  * $FreeBSD$
29366f6083SPeter Grehan  */
30366f6083SPeter Grehan 
31366f6083SPeter Grehan #include <sys/cdefs.h>
32366f6083SPeter Grehan __FBSDID("$FreeBSD$");
33366f6083SPeter Grehan 
3495ebc360SNeel Natu #include <sys/param.h>
353e9b4532SMark Johnston #include <sys/capsicum.h>
36366f6083SPeter Grehan #include <sys/sysctl.h>
37366f6083SPeter Grehan #include <sys/ioctl.h>
38a71dc724SMarcelo Araujo #include <sys/linker.h>
39366f6083SPeter Grehan #include <sys/mman.h>
40a71dc724SMarcelo Araujo #include <sys/module.h>
416303b65dSNeel Natu #include <sys/_iovec.h>
4295ebc360SNeel Natu #include <sys/cpuset.h>
43366f6083SPeter Grehan 
44d665d229SNeel Natu #include <x86/segments.h>
45366f6083SPeter Grehan #include <machine/specialreg.h>
46366f6083SPeter Grehan 
473e9b4532SMark Johnston #include <capsicum_helpers.h>
489c4d5478SNeel Natu #include <errno.h>
49483d953aSJohn Baldwin #include <stdbool.h>
50366f6083SPeter Grehan #include <stdio.h>
51366f6083SPeter Grehan #include <stdlib.h>
52366f6083SPeter Grehan #include <assert.h>
53366f6083SPeter Grehan #include <string.h>
54366f6083SPeter Grehan #include <fcntl.h>
55366f6083SPeter Grehan #include <unistd.h>
56366f6083SPeter Grehan 
57200758f1SNeel Natu #include <libutil.h>
58200758f1SNeel Natu 
59483d953aSJohn Baldwin #include <vm/vm.h>
60366f6083SPeter Grehan #include <machine/vmm.h>
61366f6083SPeter Grehan #include <machine/vmm_dev.h>
62483d953aSJohn Baldwin #include <machine/vmm_snapshot.h>
63366f6083SPeter Grehan 
64366f6083SPeter Grehan #include "vmmapi.h"
657d9ef309SJohn Baldwin #include "internal.h"
66366f6083SPeter Grehan 
67200758f1SNeel Natu #define	MB	(1024 * 1024UL)
68b060ba50SNeel Natu #define	GB	(1024 * 1024 * 1024UL)
69b060ba50SNeel Natu 
709b1aa8d6SNeel Natu /*
719b1aa8d6SNeel Natu  * Size of the guard region before and after the virtual address space
729b1aa8d6SNeel Natu  * mapping the guest physical memory. This must be a multiple of the
739b1aa8d6SNeel Natu  * superpage size for performance reasons.
749b1aa8d6SNeel Natu  */
759b1aa8d6SNeel Natu #define	VM_MMAP_GUARD_SIZE	(4 * MB)
769b1aa8d6SNeel Natu 
779b1aa8d6SNeel Natu #define	PROT_RW		(PROT_READ | PROT_WRITE)
789b1aa8d6SNeel Natu #define	PROT_ALL	(PROT_READ | PROT_WRITE | PROT_EXEC)
799b1aa8d6SNeel Natu 
80366f6083SPeter Grehan struct vmctx {
81366f6083SPeter Grehan 	int	fd;
82b060ba50SNeel Natu 	uint32_t lowmem_limit;
830dd10c00SNeel Natu 	int	memflags;
84b060ba50SNeel Natu 	size_t	lowmem;
85b060ba50SNeel Natu 	size_t	highmem;
869b1aa8d6SNeel Natu 	char	*baseaddr;
87366f6083SPeter Grehan 	char	*name;
88366f6083SPeter Grehan };
89366f6083SPeter Grehan 
90366f6083SPeter Grehan #define	CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
91366f6083SPeter Grehan #define	DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
92366f6083SPeter Grehan 
93366f6083SPeter Grehan static int
94366f6083SPeter Grehan vm_device_open(const char *name)
95366f6083SPeter Grehan {
96366f6083SPeter Grehan 	int fd, len;
97366f6083SPeter Grehan 	char *vmfile;
98366f6083SPeter Grehan 
99366f6083SPeter Grehan 	len = strlen("/dev/vmm/") + strlen(name) + 1;
100366f6083SPeter Grehan 	vmfile = malloc(len);
101366f6083SPeter Grehan 	assert(vmfile != NULL);
102366f6083SPeter Grehan 	snprintf(vmfile, len, "/dev/vmm/%s", name);
103366f6083SPeter Grehan 
104366f6083SPeter Grehan 	/* Open the device file */
105366f6083SPeter Grehan 	fd = open(vmfile, O_RDWR, 0);
106366f6083SPeter Grehan 
107366f6083SPeter Grehan 	free(vmfile);
108366f6083SPeter Grehan 	return (fd);
109366f6083SPeter Grehan }
110366f6083SPeter Grehan 
111366f6083SPeter Grehan int
112366f6083SPeter Grehan vm_create(const char *name)
113366f6083SPeter Grehan {
114a71dc724SMarcelo Araujo 	/* Try to load vmm(4) module before creating a guest. */
115a71dc724SMarcelo Araujo 	if (modfind("vmm") < 0)
116a71dc724SMarcelo Araujo 		kldload("vmm");
11745cd18ecSMark Johnston 	return (CREATE(name));
118366f6083SPeter Grehan }
119366f6083SPeter Grehan 
120366f6083SPeter Grehan struct vmctx *
121366f6083SPeter Grehan vm_open(const char *name)
122366f6083SPeter Grehan {
123366f6083SPeter Grehan 	struct vmctx *vm;
124a7f81b48SRobert Wing 	int saved_errno;
125366f6083SPeter Grehan 
126366f6083SPeter Grehan 	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
127366f6083SPeter Grehan 	assert(vm != NULL);
128366f6083SPeter Grehan 
129366f6083SPeter Grehan 	vm->fd = -1;
1300dd10c00SNeel Natu 	vm->memflags = 0;
131b060ba50SNeel Natu 	vm->lowmem_limit = 3 * GB;
132366f6083SPeter Grehan 	vm->name = (char *)(vm + 1);
133366f6083SPeter Grehan 	strcpy(vm->name, name);
134366f6083SPeter Grehan 
135366f6083SPeter Grehan 	if ((vm->fd = vm_device_open(vm->name)) < 0)
136366f6083SPeter Grehan 		goto err;
137366f6083SPeter Grehan 
138366f6083SPeter Grehan 	return (vm);
139366f6083SPeter Grehan err:
140a7f81b48SRobert Wing 	saved_errno = errno;
1416bb140e3SRobert Wing 	free(vm);
142a7f81b48SRobert Wing 	errno = saved_errno;
143366f6083SPeter Grehan 	return (NULL);
144366f6083SPeter Grehan }
145366f6083SPeter Grehan 
146366f6083SPeter Grehan void
147f0880ab7SVitaliy Gusev vm_close(struct vmctx *vm)
148f0880ab7SVitaliy Gusev {
149f0880ab7SVitaliy Gusev 	assert(vm != NULL);
150f0880ab7SVitaliy Gusev 
151f0880ab7SVitaliy Gusev 	close(vm->fd);
152f0880ab7SVitaliy Gusev 	free(vm);
153f0880ab7SVitaliy Gusev }
154f0880ab7SVitaliy Gusev 
155f0880ab7SVitaliy Gusev void
156366f6083SPeter Grehan vm_destroy(struct vmctx *vm)
157366f6083SPeter Grehan {
158366f6083SPeter Grehan 	assert(vm != NULL);
159366f6083SPeter Grehan 
160366f6083SPeter Grehan 	if (vm->fd >= 0)
161366f6083SPeter Grehan 		close(vm->fd);
162f7d51510SNeel Natu 	DESTROY(vm->name);
163f7d51510SNeel Natu 
164366f6083SPeter Grehan 	free(vm);
165366f6083SPeter Grehan }
166366f6083SPeter Grehan 
1677d9ef309SJohn Baldwin struct vcpu *
1687d9ef309SJohn Baldwin vm_vcpu_open(struct vmctx *ctx, int vcpuid)
1697d9ef309SJohn Baldwin {
1707d9ef309SJohn Baldwin 	struct vcpu *vcpu;
1717d9ef309SJohn Baldwin 
1727d9ef309SJohn Baldwin 	vcpu = malloc(sizeof(*vcpu));
1737d9ef309SJohn Baldwin 	vcpu->ctx = ctx;
1747d9ef309SJohn Baldwin 	vcpu->vcpuid = vcpuid;
1757d9ef309SJohn Baldwin 	return (vcpu);
1767d9ef309SJohn Baldwin }
1777d9ef309SJohn Baldwin 
1787d9ef309SJohn Baldwin void
1797d9ef309SJohn Baldwin vm_vcpu_close(struct vcpu *vcpu)
1807d9ef309SJohn Baldwin {
1817d9ef309SJohn Baldwin 	free(vcpu);
1827d9ef309SJohn Baldwin }
1837d9ef309SJohn Baldwin 
1847d9ef309SJohn Baldwin int
1857d9ef309SJohn Baldwin vcpu_id(struct vcpu *vcpu)
1867d9ef309SJohn Baldwin {
1877d9ef309SJohn Baldwin 	return (vcpu->vcpuid);
1887d9ef309SJohn Baldwin }
1897d9ef309SJohn Baldwin 
190366f6083SPeter Grehan int
19145cd18ecSMark Johnston vm_parse_memsize(const char *opt, size_t *ret_memsize)
192200758f1SNeel Natu {
193200758f1SNeel Natu 	char *endptr;
194200758f1SNeel Natu 	size_t optval;
195200758f1SNeel Natu 	int error;
196200758f1SNeel Natu 
19745cd18ecSMark Johnston 	optval = strtoul(opt, &endptr, 0);
19845cd18ecSMark Johnston 	if (*opt != '\0' && *endptr == '\0') {
199200758f1SNeel Natu 		/*
200200758f1SNeel Natu 		 * For the sake of backward compatibility if the memory size
201200758f1SNeel Natu 		 * specified on the command line is less than a megabyte then
202200758f1SNeel Natu 		 * it is interpreted as being in units of MB.
203200758f1SNeel Natu 		 */
204200758f1SNeel Natu 		if (optval < MB)
205200758f1SNeel Natu 			optval *= MB;
206200758f1SNeel Natu 		*ret_memsize = optval;
207200758f1SNeel Natu 		error = 0;
208200758f1SNeel Natu 	} else
20945cd18ecSMark Johnston 		error = expand_number(opt, ret_memsize);
210200758f1SNeel Natu 
211200758f1SNeel Natu 	return (error);
212200758f1SNeel Natu }
213200758f1SNeel Natu 
214b060ba50SNeel Natu uint32_t
215b060ba50SNeel Natu vm_get_lowmem_limit(struct vmctx *ctx)
216b060ba50SNeel Natu {
217b060ba50SNeel Natu 
218b060ba50SNeel Natu 	return (ctx->lowmem_limit);
219b060ba50SNeel Natu }
220b060ba50SNeel Natu 
221b060ba50SNeel Natu void
222b060ba50SNeel Natu vm_set_lowmem_limit(struct vmctx *ctx, uint32_t limit)
223b060ba50SNeel Natu {
224b060ba50SNeel Natu 
225b060ba50SNeel Natu 	ctx->lowmem_limit = limit;
226b060ba50SNeel Natu }
227b060ba50SNeel Natu 
2280dd10c00SNeel Natu void
2290dd10c00SNeel Natu vm_set_memflags(struct vmctx *ctx, int flags)
2300dd10c00SNeel Natu {
2310dd10c00SNeel Natu 
2320dd10c00SNeel Natu 	ctx->memflags = flags;
2330dd10c00SNeel Natu }
2340dd10c00SNeel Natu 
2359b1aa8d6SNeel Natu int
2369b1aa8d6SNeel Natu vm_get_memflags(struct vmctx *ctx)
237366f6083SPeter Grehan {
2389b1aa8d6SNeel Natu 
2399b1aa8d6SNeel Natu 	return (ctx->memflags);
2409b1aa8d6SNeel Natu }
241366f6083SPeter Grehan 
242366f6083SPeter Grehan /*
2439b1aa8d6SNeel Natu  * Map segment 'segid' starting at 'off' into guest address range [gpa,gpa+len).
244366f6083SPeter Grehan  */
2459b1aa8d6SNeel Natu int
2469b1aa8d6SNeel Natu vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, vm_ooffset_t off,
2479b1aa8d6SNeel Natu     size_t len, int prot)
2489b1aa8d6SNeel Natu {
2499b1aa8d6SNeel Natu 	struct vm_memmap memmap;
2509b1aa8d6SNeel Natu 	int error, flags;
2519b1aa8d6SNeel Natu 
2529b1aa8d6SNeel Natu 	memmap.gpa = gpa;
2539b1aa8d6SNeel Natu 	memmap.segid = segid;
2549b1aa8d6SNeel Natu 	memmap.segoff = off;
2559b1aa8d6SNeel Natu 	memmap.len = len;
2569b1aa8d6SNeel Natu 	memmap.prot = prot;
2579b1aa8d6SNeel Natu 	memmap.flags = 0;
2589b1aa8d6SNeel Natu 
2599b1aa8d6SNeel Natu 	if (ctx->memflags & VM_MEM_F_WIRED)
2609b1aa8d6SNeel Natu 		memmap.flags |= VM_MEMMAP_F_WIRED;
2619b1aa8d6SNeel Natu 
2629b1aa8d6SNeel Natu 	/*
2639b1aa8d6SNeel Natu 	 * If this mapping already exists then don't create it again. This
2649b1aa8d6SNeel Natu 	 * is the common case for SYSMEM mappings created by bhyveload(8).
2659b1aa8d6SNeel Natu 	 */
2669b1aa8d6SNeel Natu 	error = vm_mmap_getnext(ctx, &gpa, &segid, &off, &len, &prot, &flags);
2679b1aa8d6SNeel Natu 	if (error == 0 && gpa == memmap.gpa) {
2689b1aa8d6SNeel Natu 		if (segid != memmap.segid || off != memmap.segoff ||
2699b1aa8d6SNeel Natu 		    prot != memmap.prot || flags != memmap.flags) {
2709b1aa8d6SNeel Natu 			errno = EEXIST;
2719b1aa8d6SNeel Natu 			return (-1);
2729b1aa8d6SNeel Natu 		} else {
2739b1aa8d6SNeel Natu 			return (0);
2749b1aa8d6SNeel Natu 		}
2759b1aa8d6SNeel Natu 	}
2769b1aa8d6SNeel Natu 
2779b1aa8d6SNeel Natu 	error = ioctl(ctx->fd, VM_MMAP_MEMSEG, &memmap);
2789b1aa8d6SNeel Natu 	return (error);
2799b1aa8d6SNeel Natu }
2809b1aa8d6SNeel Natu 
2819b1aa8d6SNeel Natu int
282483d953aSJohn Baldwin vm_get_guestmem_from_ctx(struct vmctx *ctx, char **guest_baseaddr,
283483d953aSJohn Baldwin     size_t *lowmem_size, size_t *highmem_size)
284483d953aSJohn Baldwin {
285483d953aSJohn Baldwin 
286483d953aSJohn Baldwin 	*guest_baseaddr = ctx->baseaddr;
287483d953aSJohn Baldwin 	*lowmem_size = ctx->lowmem;
288483d953aSJohn Baldwin 	*highmem_size = ctx->highmem;
289483d953aSJohn Baldwin 	return (0);
290483d953aSJohn Baldwin }
291483d953aSJohn Baldwin 
292483d953aSJohn Baldwin int
293f8a6ec2dSD Scott Phillips vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
294f8a6ec2dSD Scott Phillips {
295f8a6ec2dSD Scott Phillips 	struct vm_munmap munmap;
296f8a6ec2dSD Scott Phillips 	int error;
297f8a6ec2dSD Scott Phillips 
298f8a6ec2dSD Scott Phillips 	munmap.gpa = gpa;
299f8a6ec2dSD Scott Phillips 	munmap.len = len;
300f8a6ec2dSD Scott Phillips 
301f8a6ec2dSD Scott Phillips 	error = ioctl(ctx->fd, VM_MUNMAP_MEMSEG, &munmap);
302f8a6ec2dSD Scott Phillips 	return (error);
303f8a6ec2dSD Scott Phillips }
304f8a6ec2dSD Scott Phillips 
305f8a6ec2dSD Scott Phillips int
3069b1aa8d6SNeel Natu vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
3079b1aa8d6SNeel Natu     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
3089b1aa8d6SNeel Natu {
3099b1aa8d6SNeel Natu 	struct vm_memmap memmap;
3109b1aa8d6SNeel Natu 	int error;
3119b1aa8d6SNeel Natu 
3129b1aa8d6SNeel Natu 	bzero(&memmap, sizeof(struct vm_memmap));
3139b1aa8d6SNeel Natu 	memmap.gpa = *gpa;
3149b1aa8d6SNeel Natu 	error = ioctl(ctx->fd, VM_MMAP_GETNEXT, &memmap);
3159b1aa8d6SNeel Natu 	if (error == 0) {
3169b1aa8d6SNeel Natu 		*gpa = memmap.gpa;
3179b1aa8d6SNeel Natu 		*segid = memmap.segid;
3189b1aa8d6SNeel Natu 		*segoff = memmap.segoff;
3199b1aa8d6SNeel Natu 		*len = memmap.len;
3209b1aa8d6SNeel Natu 		*prot = memmap.prot;
3219b1aa8d6SNeel Natu 		*flags = memmap.flags;
322366f6083SPeter Grehan 	}
323366f6083SPeter Grehan 	return (error);
324366f6083SPeter Grehan }
325366f6083SPeter Grehan 
3269b1aa8d6SNeel Natu /*
3279b1aa8d6SNeel Natu  * Return 0 if the segments are identical and non-zero otherwise.
3289b1aa8d6SNeel Natu  *
3299b1aa8d6SNeel Natu  * This is slightly complicated by the fact that only device memory segments
3309b1aa8d6SNeel Natu  * are named.
3319b1aa8d6SNeel Natu  */
3329b1aa8d6SNeel Natu static int
3339b1aa8d6SNeel Natu cmpseg(size_t len, const char *str, size_t len2, const char *str2)
3349b1aa8d6SNeel Natu {
3359b1aa8d6SNeel Natu 
3369b1aa8d6SNeel Natu 	if (len == len2) {
3379b1aa8d6SNeel Natu 		if ((!str && !str2) || (str && str2 && !strcmp(str, str2)))
3389b1aa8d6SNeel Natu 			return (0);
3399b1aa8d6SNeel Natu 	}
3409b1aa8d6SNeel Natu 	return (-1);
3419b1aa8d6SNeel Natu }
3429b1aa8d6SNeel Natu 
3439b1aa8d6SNeel Natu static int
3449b1aa8d6SNeel Natu vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
3459b1aa8d6SNeel Natu {
3469b1aa8d6SNeel Natu 	struct vm_memseg memseg;
3479b1aa8d6SNeel Natu 	size_t n;
3489b1aa8d6SNeel Natu 	int error;
3499b1aa8d6SNeel Natu 
3509b1aa8d6SNeel Natu 	/*
3519b1aa8d6SNeel Natu 	 * If the memory segment has already been created then just return.
3529b1aa8d6SNeel Natu 	 * This is the usual case for the SYSMEM segment created by userspace
3539b1aa8d6SNeel Natu 	 * loaders like bhyveload(8).
3549b1aa8d6SNeel Natu 	 */
3559b1aa8d6SNeel Natu 	error = vm_get_memseg(ctx, segid, &memseg.len, memseg.name,
3569b1aa8d6SNeel Natu 	    sizeof(memseg.name));
3579b1aa8d6SNeel Natu 	if (error)
3589b1aa8d6SNeel Natu 		return (error);
3599b1aa8d6SNeel Natu 
3609b1aa8d6SNeel Natu 	if (memseg.len != 0) {
3619b1aa8d6SNeel Natu 		if (cmpseg(len, name, memseg.len, VM_MEMSEG_NAME(&memseg))) {
3629b1aa8d6SNeel Natu 			errno = EINVAL;
3639b1aa8d6SNeel Natu 			return (-1);
3649b1aa8d6SNeel Natu 		} else {
3659b1aa8d6SNeel Natu 			return (0);
3669b1aa8d6SNeel Natu 		}
3679b1aa8d6SNeel Natu 	}
3689b1aa8d6SNeel Natu 
3699b1aa8d6SNeel Natu 	bzero(&memseg, sizeof(struct vm_memseg));
3709b1aa8d6SNeel Natu 	memseg.segid = segid;
3719b1aa8d6SNeel Natu 	memseg.len = len;
3729b1aa8d6SNeel Natu 	if (name != NULL) {
3739b1aa8d6SNeel Natu 		n = strlcpy(memseg.name, name, sizeof(memseg.name));
3749b1aa8d6SNeel Natu 		if (n >= sizeof(memseg.name)) {
3759b1aa8d6SNeel Natu 			errno = ENAMETOOLONG;
3769b1aa8d6SNeel Natu 			return (-1);
3779b1aa8d6SNeel Natu 		}
3789b1aa8d6SNeel Natu 	}
3799b1aa8d6SNeel Natu 
3809b1aa8d6SNeel Natu 	error = ioctl(ctx->fd, VM_ALLOC_MEMSEG, &memseg);
3819b1aa8d6SNeel Natu 	return (error);
3829b1aa8d6SNeel Natu }
3839b1aa8d6SNeel Natu 
3849b1aa8d6SNeel Natu int
3859b1aa8d6SNeel Natu vm_get_memseg(struct vmctx *ctx, int segid, size_t *lenp, char *namebuf,
3869b1aa8d6SNeel Natu     size_t bufsize)
3879b1aa8d6SNeel Natu {
3889b1aa8d6SNeel Natu 	struct vm_memseg memseg;
3899b1aa8d6SNeel Natu 	size_t n;
3909b1aa8d6SNeel Natu 	int error;
3919b1aa8d6SNeel Natu 
3929b1aa8d6SNeel Natu 	memseg.segid = segid;
3939b1aa8d6SNeel Natu 	error = ioctl(ctx->fd, VM_GET_MEMSEG, &memseg);
3949b1aa8d6SNeel Natu 	if (error == 0) {
3959b1aa8d6SNeel Natu 		*lenp = memseg.len;
3969b1aa8d6SNeel Natu 		n = strlcpy(namebuf, memseg.name, bufsize);
3979b1aa8d6SNeel Natu 		if (n >= bufsize) {
3989b1aa8d6SNeel Natu 			errno = ENAMETOOLONG;
3999b1aa8d6SNeel Natu 			error = -1;
4009b1aa8d6SNeel Natu 		}
4019b1aa8d6SNeel Natu 	}
4029b1aa8d6SNeel Natu 	return (error);
4039b1aa8d6SNeel Natu }
4049b1aa8d6SNeel Natu 
4059b1aa8d6SNeel Natu static int
4069b1aa8d6SNeel Natu setup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
4079b1aa8d6SNeel Natu {
4089b1aa8d6SNeel Natu 	char *ptr;
4099b1aa8d6SNeel Natu 	int error, flags;
4109b1aa8d6SNeel Natu 
4119b1aa8d6SNeel Natu 	/* Map 'len' bytes starting at 'gpa' in the guest address space */
4129b1aa8d6SNeel Natu 	error = vm_mmap_memseg(ctx, gpa, VM_SYSMEM, gpa, len, PROT_ALL);
4139b1aa8d6SNeel Natu 	if (error)
4149b1aa8d6SNeel Natu 		return (error);
4159b1aa8d6SNeel Natu 
4169b1aa8d6SNeel Natu 	flags = MAP_SHARED | MAP_FIXED;
4179b1aa8d6SNeel Natu 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
4189b1aa8d6SNeel Natu 		flags |= MAP_NOCORE;
4199b1aa8d6SNeel Natu 
4209b1aa8d6SNeel Natu 	/* mmap into the process address space on the host */
4219b1aa8d6SNeel Natu 	ptr = mmap(base + gpa, len, PROT_RW, flags, ctx->fd, gpa);
4229b1aa8d6SNeel Natu 	if (ptr == MAP_FAILED)
4239b1aa8d6SNeel Natu 		return (-1);
4249b1aa8d6SNeel Natu 
4259b1aa8d6SNeel Natu 	return (0);
4269b1aa8d6SNeel Natu }
4279b1aa8d6SNeel Natu 
428b060ba50SNeel Natu int
429b060ba50SNeel Natu vm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
430b060ba50SNeel Natu {
4319b1aa8d6SNeel Natu 	size_t objsize, len;
4329b1aa8d6SNeel Natu 	vm_paddr_t gpa;
4339b1aa8d6SNeel Natu 	char *baseaddr, *ptr;
4346a9648b5SJohn Baldwin 	int error;
435b060ba50SNeel Natu 
4369b1aa8d6SNeel Natu 	assert(vms == VM_MMAP_ALL);
437b060ba50SNeel Natu 
438b060ba50SNeel Natu 	/*
439b060ba50SNeel Natu 	 * If 'memsize' cannot fit entirely in the 'lowmem' segment then
440b060ba50SNeel Natu 	 * create another 'highmem' segment above 4GB for the remainder.
441b060ba50SNeel Natu 	 */
442b060ba50SNeel Natu 	if (memsize > ctx->lowmem_limit) {
443b060ba50SNeel Natu 		ctx->lowmem = ctx->lowmem_limit;
4449b1aa8d6SNeel Natu 		ctx->highmem = memsize - ctx->lowmem_limit;
4459b1aa8d6SNeel Natu 		objsize = 4*GB + ctx->highmem;
446b060ba50SNeel Natu 	} else {
447b060ba50SNeel Natu 		ctx->lowmem = memsize;
448b060ba50SNeel Natu 		ctx->highmem = 0;
4499b1aa8d6SNeel Natu 		objsize = ctx->lowmem;
4509b1aa8d6SNeel Natu 	}
4519b1aa8d6SNeel Natu 
4529b1aa8d6SNeel Natu 	error = vm_alloc_memseg(ctx, VM_SYSMEM, objsize, NULL);
4539b1aa8d6SNeel Natu 	if (error)
4549b1aa8d6SNeel Natu 		return (error);
4559b1aa8d6SNeel Natu 
4569b1aa8d6SNeel Natu 	/*
4579b1aa8d6SNeel Natu 	 * Stake out a contiguous region covering the guest physical memory
4589b1aa8d6SNeel Natu 	 * and the adjoining guard regions.
4599b1aa8d6SNeel Natu 	 */
4609b1aa8d6SNeel Natu 	len = VM_MMAP_GUARD_SIZE + objsize + VM_MMAP_GUARD_SIZE;
4616a9648b5SJohn Baldwin 	ptr = mmap(NULL, len, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1, 0);
4629b1aa8d6SNeel Natu 	if (ptr == MAP_FAILED)
4639b1aa8d6SNeel Natu 		return (-1);
4649b1aa8d6SNeel Natu 
4659b1aa8d6SNeel Natu 	baseaddr = ptr + VM_MMAP_GUARD_SIZE;
4669b1aa8d6SNeel Natu 	if (ctx->highmem > 0) {
4679b1aa8d6SNeel Natu 		gpa = 4*GB;
4689b1aa8d6SNeel Natu 		len = ctx->highmem;
4699b1aa8d6SNeel Natu 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
4709b1aa8d6SNeel Natu 		if (error)
4719b1aa8d6SNeel Natu 			return (error);
472b060ba50SNeel Natu 	}
473b060ba50SNeel Natu 
474b060ba50SNeel Natu 	if (ctx->lowmem > 0) {
4759b1aa8d6SNeel Natu 		gpa = 0;
4769b1aa8d6SNeel Natu 		len = ctx->lowmem;
4779b1aa8d6SNeel Natu 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
478b060ba50SNeel Natu 		if (error)
479b060ba50SNeel Natu 			return (error);
480b060ba50SNeel Natu 	}
481b060ba50SNeel Natu 
4829b1aa8d6SNeel Natu 	ctx->baseaddr = baseaddr;
483b060ba50SNeel Natu 
484b060ba50SNeel Natu 	return (0);
485b060ba50SNeel Natu }
486b060ba50SNeel Natu 
48736e8356eSNeel Natu /*
48836e8356eSNeel Natu  * Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
48936e8356eSNeel Natu  * the lowmem or highmem regions.
49036e8356eSNeel Natu  *
49136e8356eSNeel Natu  * In particular return NULL if [gaddr, gaddr+len) falls in guest MMIO region.
49236e8356eSNeel Natu  * The instruction emulation code depends on this behavior.
49336e8356eSNeel Natu  */
494b060ba50SNeel Natu void *
495b060ba50SNeel Natu vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
496366f6083SPeter Grehan {
497366f6083SPeter Grehan 
49836e8356eSNeel Natu 	if (ctx->lowmem > 0) {
499edc816d6SGleb Smirnoff 		if (gaddr < ctx->lowmem && len <= ctx->lowmem &&
500edc816d6SGleb Smirnoff 		    gaddr + len <= ctx->lowmem)
50136e8356eSNeel Natu 			return (ctx->baseaddr + gaddr);
50236e8356eSNeel Natu 	}
503b060ba50SNeel Natu 
50436e8356eSNeel Natu 	if (ctx->highmem > 0) {
505edc816d6SGleb Smirnoff                 if (gaddr >= 4*GB) {
506edc816d6SGleb Smirnoff 			if (gaddr < 4*GB + ctx->highmem &&
507edc816d6SGleb Smirnoff 			    len <= ctx->highmem &&
508edc816d6SGleb Smirnoff 			    gaddr + len <= 4*GB + ctx->highmem)
50936e8356eSNeel Natu 				return (ctx->baseaddr + gaddr);
51036e8356eSNeel Natu 		}
511edc816d6SGleb Smirnoff 	}
51236e8356eSNeel Natu 
513b060ba50SNeel Natu 	return (NULL);
514366f6083SPeter Grehan }
515366f6083SPeter Grehan 
516483d953aSJohn Baldwin vm_paddr_t
517483d953aSJohn Baldwin vm_rev_map_gpa(struct vmctx *ctx, void *addr)
518483d953aSJohn Baldwin {
519483d953aSJohn Baldwin 	vm_paddr_t offaddr;
520483d953aSJohn Baldwin 
521483d953aSJohn Baldwin 	offaddr = (char *)addr - ctx->baseaddr;
522483d953aSJohn Baldwin 
523483d953aSJohn Baldwin 	if (ctx->lowmem > 0)
5245ac4ac85SJohn Baldwin 		if (offaddr <= ctx->lowmem)
525483d953aSJohn Baldwin 			return (offaddr);
526483d953aSJohn Baldwin 
527483d953aSJohn Baldwin 	if (ctx->highmem > 0)
528483d953aSJohn Baldwin 		if (offaddr >= 4*GB && offaddr < 4*GB + ctx->highmem)
529483d953aSJohn Baldwin 			return (offaddr);
530483d953aSJohn Baldwin 
531483d953aSJohn Baldwin 	return ((vm_paddr_t)-1);
532483d953aSJohn Baldwin }
533483d953aSJohn Baldwin 
5343efc45f3SRobert Wing const char *
5353efc45f3SRobert Wing vm_get_name(struct vmctx *ctx)
536483d953aSJohn Baldwin {
537483d953aSJohn Baldwin 
5383efc45f3SRobert Wing 	return (ctx->name);
539483d953aSJohn Baldwin }
540483d953aSJohn Baldwin 
541be679db4SNeel Natu size_t
542be679db4SNeel Natu vm_get_lowmem_size(struct vmctx *ctx)
543be679db4SNeel Natu {
544be679db4SNeel Natu 
545be679db4SNeel Natu 	return (ctx->lowmem);
546be679db4SNeel Natu }
547be679db4SNeel Natu 
548be679db4SNeel Natu size_t
549be679db4SNeel Natu vm_get_highmem_size(struct vmctx *ctx)
550be679db4SNeel Natu {
551be679db4SNeel Natu 
552be679db4SNeel Natu 	return (ctx->highmem);
553be679db4SNeel Natu }
554be679db4SNeel Natu 
5559b1aa8d6SNeel Natu void *
5569b1aa8d6SNeel Natu vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
5579b1aa8d6SNeel Natu {
5589b1aa8d6SNeel Natu 	char pathname[MAXPATHLEN];
5599b1aa8d6SNeel Natu 	size_t len2;
5609b1aa8d6SNeel Natu 	char *base, *ptr;
5619b1aa8d6SNeel Natu 	int fd, error, flags;
5629b1aa8d6SNeel Natu 
5639b1aa8d6SNeel Natu 	fd = -1;
5649b1aa8d6SNeel Natu 	ptr = MAP_FAILED;
5659b1aa8d6SNeel Natu 	if (name == NULL || strlen(name) == 0) {
5669b1aa8d6SNeel Natu 		errno = EINVAL;
5679b1aa8d6SNeel Natu 		goto done;
5689b1aa8d6SNeel Natu 	}
5699b1aa8d6SNeel Natu 
5709b1aa8d6SNeel Natu 	error = vm_alloc_memseg(ctx, segid, len, name);
5719b1aa8d6SNeel Natu 	if (error)
5729b1aa8d6SNeel Natu 		goto done;
5739b1aa8d6SNeel Natu 
5745e4f29c0SNeel Natu 	strlcpy(pathname, "/dev/vmm.io/", sizeof(pathname));
5759b1aa8d6SNeel Natu 	strlcat(pathname, ctx->name, sizeof(pathname));
5769b1aa8d6SNeel Natu 	strlcat(pathname, ".", sizeof(pathname));
5779b1aa8d6SNeel Natu 	strlcat(pathname, name, sizeof(pathname));
5789b1aa8d6SNeel Natu 
5799b1aa8d6SNeel Natu 	fd = open(pathname, O_RDWR);
5809b1aa8d6SNeel Natu 	if (fd < 0)
5819b1aa8d6SNeel Natu 		goto done;
5829b1aa8d6SNeel Natu 
5839b1aa8d6SNeel Natu 	/*
5849b1aa8d6SNeel Natu 	 * Stake out a contiguous region covering the device memory and the
5859b1aa8d6SNeel Natu 	 * adjoining guard regions.
5869b1aa8d6SNeel Natu 	 */
5879b1aa8d6SNeel Natu 	len2 = VM_MMAP_GUARD_SIZE + len + VM_MMAP_GUARD_SIZE;
5886a9648b5SJohn Baldwin 	base = mmap(NULL, len2, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1,
5896a9648b5SJohn Baldwin 	    0);
5909b1aa8d6SNeel Natu 	if (base == MAP_FAILED)
5919b1aa8d6SNeel Natu 		goto done;
5929b1aa8d6SNeel Natu 
5939b1aa8d6SNeel Natu 	flags = MAP_SHARED | MAP_FIXED;
5949b1aa8d6SNeel Natu 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
5959b1aa8d6SNeel Natu 		flags |= MAP_NOCORE;
5969b1aa8d6SNeel Natu 
5979b1aa8d6SNeel Natu 	/* mmap the devmem region in the host address space */
5989b1aa8d6SNeel Natu 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, fd, 0);
5999b1aa8d6SNeel Natu done:
6009b1aa8d6SNeel Natu 	if (fd >= 0)
6019b1aa8d6SNeel Natu 		close(fd);
6029b1aa8d6SNeel Natu 	return (ptr);
6039b1aa8d6SNeel Natu }
6049b1aa8d6SNeel Natu 
6057d9ef309SJohn Baldwin static int
6067d9ef309SJohn Baldwin vcpu_ioctl(struct vcpu *vcpu, u_long cmd, void *arg)
6077d9ef309SJohn Baldwin {
6087d9ef309SJohn Baldwin 	/*
6097d9ef309SJohn Baldwin 	 * XXX: fragile, handle with care
6107d9ef309SJohn Baldwin 	 * Assumes that the first field of the ioctl data
6117d9ef309SJohn Baldwin 	 * is the vcpuid.
6127d9ef309SJohn Baldwin 	 */
6137d9ef309SJohn Baldwin 	*(int *)arg = vcpu->vcpuid;
6147d9ef309SJohn Baldwin 	return (ioctl(vcpu->ctx->fd, cmd, arg));
6157d9ef309SJohn Baldwin }
6167d9ef309SJohn Baldwin 
617366f6083SPeter Grehan int
6187d9ef309SJohn Baldwin vm_set_desc(struct vcpu *vcpu, int reg,
619366f6083SPeter Grehan 	    uint64_t base, uint32_t limit, uint32_t access)
620366f6083SPeter Grehan {
621366f6083SPeter Grehan 	int error;
622366f6083SPeter Grehan 	struct vm_seg_desc vmsegdesc;
623366f6083SPeter Grehan 
624366f6083SPeter Grehan 	bzero(&vmsegdesc, sizeof(vmsegdesc));
625366f6083SPeter Grehan 	vmsegdesc.regnum = reg;
626366f6083SPeter Grehan 	vmsegdesc.desc.base = base;
627366f6083SPeter Grehan 	vmsegdesc.desc.limit = limit;
628366f6083SPeter Grehan 	vmsegdesc.desc.access = access;
629366f6083SPeter Grehan 
6307d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
631366f6083SPeter Grehan 	return (error);
632366f6083SPeter Grehan }
633366f6083SPeter Grehan 
634366f6083SPeter Grehan int
6357d9ef309SJohn Baldwin vm_get_desc(struct vcpu *vcpu, int reg, uint64_t *base, uint32_t *limit,
6367d9ef309SJohn Baldwin     uint32_t *access)
637366f6083SPeter Grehan {
638366f6083SPeter Grehan 	int error;
639366f6083SPeter Grehan 	struct vm_seg_desc vmsegdesc;
640366f6083SPeter Grehan 
641366f6083SPeter Grehan 	bzero(&vmsegdesc, sizeof(vmsegdesc));
642366f6083SPeter Grehan 	vmsegdesc.regnum = reg;
643366f6083SPeter Grehan 
6447d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
645366f6083SPeter Grehan 	if (error == 0) {
646366f6083SPeter Grehan 		*base = vmsegdesc.desc.base;
647366f6083SPeter Grehan 		*limit = vmsegdesc.desc.limit;
648366f6083SPeter Grehan 		*access = vmsegdesc.desc.access;
649366f6083SPeter Grehan 	}
650366f6083SPeter Grehan 	return (error);
651366f6083SPeter Grehan }
652366f6083SPeter Grehan 
653366f6083SPeter Grehan int
6547d9ef309SJohn Baldwin vm_get_seg_desc(struct vcpu *vcpu, int reg, struct seg_desc *seg_desc)
655d665d229SNeel Natu {
656d665d229SNeel Natu 	int error;
657d665d229SNeel Natu 
6587d9ef309SJohn Baldwin 	error = vm_get_desc(vcpu, reg, &seg_desc->base, &seg_desc->limit,
659d665d229SNeel Natu 	    &seg_desc->access);
660d665d229SNeel Natu 	return (error);
661d665d229SNeel Natu }
662d665d229SNeel Natu 
663d665d229SNeel Natu int
6647d9ef309SJohn Baldwin vm_set_register(struct vcpu *vcpu, int reg, uint64_t val)
665366f6083SPeter Grehan {
666366f6083SPeter Grehan 	int error;
667366f6083SPeter Grehan 	struct vm_register vmreg;
668366f6083SPeter Grehan 
669366f6083SPeter Grehan 	bzero(&vmreg, sizeof(vmreg));
670366f6083SPeter Grehan 	vmreg.regnum = reg;
671366f6083SPeter Grehan 	vmreg.regval = val;
672366f6083SPeter Grehan 
6737d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_SET_REGISTER, &vmreg);
674366f6083SPeter Grehan 	return (error);
675366f6083SPeter Grehan }
676366f6083SPeter Grehan 
677366f6083SPeter Grehan int
6787d9ef309SJohn Baldwin vm_get_register(struct vcpu *vcpu, int reg, uint64_t *ret_val)
679366f6083SPeter Grehan {
680366f6083SPeter Grehan 	int error;
681366f6083SPeter Grehan 	struct vm_register vmreg;
682366f6083SPeter Grehan 
683366f6083SPeter Grehan 	bzero(&vmreg, sizeof(vmreg));
684366f6083SPeter Grehan 	vmreg.regnum = reg;
685366f6083SPeter Grehan 
6867d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GET_REGISTER, &vmreg);
687366f6083SPeter Grehan 	*ret_val = vmreg.regval;
688366f6083SPeter Grehan 	return (error);
689366f6083SPeter Grehan }
690366f6083SPeter Grehan 
691366f6083SPeter Grehan int
6927d9ef309SJohn Baldwin vm_set_register_set(struct vcpu *vcpu, unsigned int count,
6934f866698SJohn Baldwin     const int *regnums, uint64_t *regvals)
6944f866698SJohn Baldwin {
6954f866698SJohn Baldwin 	int error;
6964f866698SJohn Baldwin 	struct vm_register_set vmregset;
6974f866698SJohn Baldwin 
6984f866698SJohn Baldwin 	bzero(&vmregset, sizeof(vmregset));
6994f866698SJohn Baldwin 	vmregset.count = count;
7004f866698SJohn Baldwin 	vmregset.regnums = regnums;
7014f866698SJohn Baldwin 	vmregset.regvals = regvals;
7024f866698SJohn Baldwin 
7037d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_SET_REGISTER_SET, &vmregset);
7044f866698SJohn Baldwin 	return (error);
7054f866698SJohn Baldwin }
7064f866698SJohn Baldwin 
7074f866698SJohn Baldwin int
7087d9ef309SJohn Baldwin vm_get_register_set(struct vcpu *vcpu, unsigned int count,
7094f866698SJohn Baldwin     const int *regnums, uint64_t *regvals)
7104f866698SJohn Baldwin {
7114f866698SJohn Baldwin 	int error;
7124f866698SJohn Baldwin 	struct vm_register_set vmregset;
7134f866698SJohn Baldwin 
7144f866698SJohn Baldwin 	bzero(&vmregset, sizeof(vmregset));
7154f866698SJohn Baldwin 	vmregset.count = count;
7164f866698SJohn Baldwin 	vmregset.regnums = regnums;
7174f866698SJohn Baldwin 	vmregset.regvals = regvals;
7184f866698SJohn Baldwin 
7197d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GET_REGISTER_SET, &vmregset);
7204f866698SJohn Baldwin 	return (error);
7214f866698SJohn Baldwin }
7224f866698SJohn Baldwin 
7234f866698SJohn Baldwin int
7247d9ef309SJohn Baldwin vm_run(struct vcpu *vcpu, struct vm_exit *vmexit)
725366f6083SPeter Grehan {
726366f6083SPeter Grehan 	int error;
727366f6083SPeter Grehan 	struct vm_run vmrun;
728366f6083SPeter Grehan 
729366f6083SPeter Grehan 	bzero(&vmrun, sizeof(vmrun));
730366f6083SPeter Grehan 
7317d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_RUN, &vmrun);
732366f6083SPeter Grehan 	bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit));
733366f6083SPeter Grehan 	return (error);
734366f6083SPeter Grehan }
735366f6083SPeter Grehan 
736b15a09c0SNeel Natu int
737f0fdcfe2SNeel Natu vm_suspend(struct vmctx *ctx, enum vm_suspend_how how)
738b15a09c0SNeel Natu {
739f0fdcfe2SNeel Natu 	struct vm_suspend vmsuspend;
740b15a09c0SNeel Natu 
741f0fdcfe2SNeel Natu 	bzero(&vmsuspend, sizeof(vmsuspend));
742f0fdcfe2SNeel Natu 	vmsuspend.how = how;
743f0fdcfe2SNeel Natu 	return (ioctl(ctx->fd, VM_SUSPEND, &vmsuspend));
744b15a09c0SNeel Natu }
745b15a09c0SNeel Natu 
7465fcf252fSNeel Natu int
7475fcf252fSNeel Natu vm_reinit(struct vmctx *ctx)
7485fcf252fSNeel Natu {
7495fcf252fSNeel Natu 
7505fcf252fSNeel Natu 	return (ioctl(ctx->fd, VM_REINIT, 0));
7515fcf252fSNeel Natu }
7525fcf252fSNeel Natu 
753d087a399SNeel Natu int
7547d9ef309SJohn Baldwin vm_inject_exception(struct vcpu *vcpu, int vector, int errcode_valid,
755d087a399SNeel Natu     uint32_t errcode, int restart_instruction)
756366f6083SPeter Grehan {
757dc506506SNeel Natu 	struct vm_exception exc;
758366f6083SPeter Grehan 
759dc506506SNeel Natu 	exc.vector = vector;
760d087a399SNeel Natu 	exc.error_code = errcode;
761d087a399SNeel Natu 	exc.error_code_valid = errcode_valid;
762d087a399SNeel Natu 	exc.restart_instruction = restart_instruction;
763366f6083SPeter Grehan 
7647d9ef309SJohn Baldwin 	return (vcpu_ioctl(vcpu, VM_INJECT_EXCEPTION, &exc));
765366f6083SPeter Grehan }
766366f6083SPeter Grehan 
767366f6083SPeter Grehan int
76845cd18ecSMark Johnston vm_apicid2vcpu(struct vmctx *ctx __unused, int apicid)
76990d4b48fSNeel Natu {
77090d4b48fSNeel Natu 	/*
77190d4b48fSNeel Natu 	 * The apic id associated with the 'vcpu' has the same numerical value
77290d4b48fSNeel Natu 	 * as the 'vcpu' itself.
77390d4b48fSNeel Natu 	 */
77490d4b48fSNeel Natu 	return (apicid);
77590d4b48fSNeel Natu }
77690d4b48fSNeel Natu 
77790d4b48fSNeel Natu int
7787d9ef309SJohn Baldwin vm_lapic_irq(struct vcpu *vcpu, int vector)
779366f6083SPeter Grehan {
780366f6083SPeter Grehan 	struct vm_lapic_irq vmirq;
781366f6083SPeter Grehan 
782366f6083SPeter Grehan 	bzero(&vmirq, sizeof(vmirq));
783366f6083SPeter Grehan 	vmirq.vector = vector;
784366f6083SPeter Grehan 
7857d9ef309SJohn Baldwin 	return (vcpu_ioctl(vcpu, VM_LAPIC_IRQ, &vmirq));
786366f6083SPeter Grehan }
787366f6083SPeter Grehan 
788366f6083SPeter Grehan int
7897d9ef309SJohn Baldwin vm_lapic_local_irq(struct vcpu *vcpu, int vector)
790330baf58SJohn Baldwin {
791330baf58SJohn Baldwin 	struct vm_lapic_irq vmirq;
792330baf58SJohn Baldwin 
793330baf58SJohn Baldwin 	bzero(&vmirq, sizeof(vmirq));
794330baf58SJohn Baldwin 	vmirq.vector = vector;
795330baf58SJohn Baldwin 
7967d9ef309SJohn Baldwin 	return (vcpu_ioctl(vcpu, VM_LAPIC_LOCAL_IRQ, &vmirq));
797330baf58SJohn Baldwin }
798330baf58SJohn Baldwin 
799330baf58SJohn Baldwin int
8004f8be175SNeel Natu vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg)
8014f8be175SNeel Natu {
8024f8be175SNeel Natu 	struct vm_lapic_msi vmmsi;
8034f8be175SNeel Natu 
8044f8be175SNeel Natu 	bzero(&vmmsi, sizeof(vmmsi));
8054f8be175SNeel Natu 	vmmsi.addr = addr;
8064f8be175SNeel Natu 	vmmsi.msg = msg;
8074f8be175SNeel Natu 
8084f8be175SNeel Natu 	return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi));
8094f8be175SNeel Natu }
8104f8be175SNeel Natu 
8114f8be175SNeel Natu int
812565bbb86SNeel Natu vm_ioapic_assert_irq(struct vmctx *ctx, int irq)
813565bbb86SNeel Natu {
814565bbb86SNeel Natu 	struct vm_ioapic_irq ioapic_irq;
815565bbb86SNeel Natu 
816565bbb86SNeel Natu 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
817565bbb86SNeel Natu 	ioapic_irq.irq = irq;
818565bbb86SNeel Natu 
819565bbb86SNeel Natu 	return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
820565bbb86SNeel Natu }
821565bbb86SNeel Natu 
822565bbb86SNeel Natu int
823565bbb86SNeel Natu vm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
824565bbb86SNeel Natu {
825565bbb86SNeel Natu 	struct vm_ioapic_irq ioapic_irq;
826565bbb86SNeel Natu 
827565bbb86SNeel Natu 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
828565bbb86SNeel Natu 	ioapic_irq.irq = irq;
829565bbb86SNeel Natu 
830565bbb86SNeel Natu 	return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
831565bbb86SNeel Natu }
832565bbb86SNeel Natu 
833565bbb86SNeel Natu int
834ac7304a7SNeel Natu vm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
835ac7304a7SNeel Natu {
836ac7304a7SNeel Natu 	struct vm_ioapic_irq ioapic_irq;
837ac7304a7SNeel Natu 
838ac7304a7SNeel Natu 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
839ac7304a7SNeel Natu 	ioapic_irq.irq = irq;
840ac7304a7SNeel Natu 
841ac7304a7SNeel Natu 	return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
842ac7304a7SNeel Natu }
843ac7304a7SNeel Natu 
844ac7304a7SNeel Natu int
8453cbf3585SJohn Baldwin vm_ioapic_pincount(struct vmctx *ctx, int *pincount)
8463cbf3585SJohn Baldwin {
8473cbf3585SJohn Baldwin 
8483cbf3585SJohn Baldwin 	return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
8493cbf3585SJohn Baldwin }
8503cbf3585SJohn Baldwin 
8513cbf3585SJohn Baldwin int
8527d9ef309SJohn Baldwin vm_readwrite_kernemu_device(struct vcpu *vcpu, vm_paddr_t gpa,
8538a68ae80SConrad Meyer     bool write, int size, uint64_t *value)
8548a68ae80SConrad Meyer {
8558a68ae80SConrad Meyer 	struct vm_readwrite_kernemu_device irp = {
8568a68ae80SConrad Meyer 		.access_width = fls(size) - 1,
8578a68ae80SConrad Meyer 		.gpa = gpa,
8588a68ae80SConrad Meyer 		.value = write ? *value : ~0ul,
8598a68ae80SConrad Meyer 	};
8608a68ae80SConrad Meyer 	long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV);
8618a68ae80SConrad Meyer 	int rc;
8628a68ae80SConrad Meyer 
8637d9ef309SJohn Baldwin 	rc = vcpu_ioctl(vcpu, cmd, &irp);
8648a68ae80SConrad Meyer 	if (rc == 0 && !write)
8658a68ae80SConrad Meyer 		*value = irp.value;
8668a68ae80SConrad Meyer 	return (rc);
8678a68ae80SConrad Meyer }
8688a68ae80SConrad Meyer 
8698a68ae80SConrad Meyer int
870762fd208STycho Nightingale vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
871762fd208STycho Nightingale {
872762fd208STycho Nightingale 	struct vm_isa_irq isa_irq;
873762fd208STycho Nightingale 
874762fd208STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
875762fd208STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
876762fd208STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
877762fd208STycho Nightingale 
878762fd208STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq));
879762fd208STycho Nightingale }
880762fd208STycho Nightingale 
881762fd208STycho Nightingale int
882762fd208STycho Nightingale vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
883762fd208STycho Nightingale {
884762fd208STycho Nightingale 	struct vm_isa_irq isa_irq;
885762fd208STycho Nightingale 
886762fd208STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
887762fd208STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
888762fd208STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
889762fd208STycho Nightingale 
890762fd208STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq));
891762fd208STycho Nightingale }
892762fd208STycho Nightingale 
893762fd208STycho Nightingale int
894762fd208STycho Nightingale vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
895762fd208STycho Nightingale {
896762fd208STycho Nightingale 	struct vm_isa_irq isa_irq;
897b3e9732aSJohn Baldwin 
898762fd208STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
899762fd208STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
900762fd208STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
901762fd208STycho Nightingale 
902762fd208STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq));
903762fd208STycho Nightingale }
904762fd208STycho Nightingale 
905762fd208STycho Nightingale int
906b3e9732aSJohn Baldwin vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq,
907b3e9732aSJohn Baldwin     enum vm_intr_trigger trigger)
908b3e9732aSJohn Baldwin {
909b3e9732aSJohn Baldwin 	struct vm_isa_irq_trigger isa_irq_trigger;
910b3e9732aSJohn Baldwin 
911b3e9732aSJohn Baldwin 	bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger));
912b3e9732aSJohn Baldwin 	isa_irq_trigger.atpic_irq = atpic_irq;
913b3e9732aSJohn Baldwin 	isa_irq_trigger.trigger = trigger;
914b3e9732aSJohn Baldwin 
915b3e9732aSJohn Baldwin 	return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger));
916b3e9732aSJohn Baldwin }
917b3e9732aSJohn Baldwin 
918b3e9732aSJohn Baldwin int
9197d9ef309SJohn Baldwin vm_inject_nmi(struct vcpu *vcpu)
920366f6083SPeter Grehan {
921366f6083SPeter Grehan 	struct vm_nmi vmnmi;
922366f6083SPeter Grehan 
923366f6083SPeter Grehan 	bzero(&vmnmi, sizeof(vmnmi));
924366f6083SPeter Grehan 
9257d9ef309SJohn Baldwin 	return (vcpu_ioctl(vcpu, VM_INJECT_NMI, &vmnmi));
926366f6083SPeter Grehan }
927366f6083SPeter Grehan 
928d000623aSJohn Baldwin static const char *capstrmap[] = {
929d000623aSJohn Baldwin 	[VM_CAP_HALT_EXIT]  = "hlt_exit",
930d000623aSJohn Baldwin 	[VM_CAP_MTRAP_EXIT] = "mtrap_exit",
931d000623aSJohn Baldwin 	[VM_CAP_PAUSE_EXIT] = "pause_exit",
932d000623aSJohn Baldwin 	[VM_CAP_UNRESTRICTED_GUEST] = "unrestricted_guest",
933d000623aSJohn Baldwin 	[VM_CAP_ENABLE_INVPCID] = "enable_invpcid",
934d000623aSJohn Baldwin 	[VM_CAP_BPT_EXIT] = "bpt_exit",
935366f6083SPeter Grehan };
936366f6083SPeter Grehan 
93713f4cf6cSNeel Natu int
93813f4cf6cSNeel Natu vm_capability_name2type(const char *capname)
93913f4cf6cSNeel Natu {
94013f4cf6cSNeel Natu 	int i;
94113f4cf6cSNeel Natu 
94245cd18ecSMark Johnston 	for (i = 0; i < (int)nitems(capstrmap); i++) {
943d000623aSJohn Baldwin 		if (strcmp(capstrmap[i], capname) == 0)
944d000623aSJohn Baldwin 			return (i);
945366f6083SPeter Grehan 	}
946366f6083SPeter Grehan 
947366f6083SPeter Grehan 	return (-1);
948366f6083SPeter Grehan }
949366f6083SPeter Grehan 
95013f4cf6cSNeel Natu const char *
95113f4cf6cSNeel Natu vm_capability_type2name(int type)
95213f4cf6cSNeel Natu {
95345cd18ecSMark Johnston 	if (type >= 0 && type < (int)nitems(capstrmap))
954d000623aSJohn Baldwin 		return (capstrmap[type]);
95513f4cf6cSNeel Natu 
95613f4cf6cSNeel Natu 	return (NULL);
95713f4cf6cSNeel Natu }
95813f4cf6cSNeel Natu 
959366f6083SPeter Grehan int
9607d9ef309SJohn Baldwin vm_get_capability(struct vcpu *vcpu, enum vm_cap_type cap, int *retval)
961366f6083SPeter Grehan {
962366f6083SPeter Grehan 	int error;
963366f6083SPeter Grehan 	struct vm_capability vmcap;
964366f6083SPeter Grehan 
965366f6083SPeter Grehan 	bzero(&vmcap, sizeof(vmcap));
966366f6083SPeter Grehan 	vmcap.captype = cap;
967366f6083SPeter Grehan 
9687d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GET_CAPABILITY, &vmcap);
969366f6083SPeter Grehan 	*retval = vmcap.capval;
970366f6083SPeter Grehan 	return (error);
971366f6083SPeter Grehan }
972366f6083SPeter Grehan 
973366f6083SPeter Grehan int
9747d9ef309SJohn Baldwin vm_set_capability(struct vcpu *vcpu, enum vm_cap_type cap, int val)
975366f6083SPeter Grehan {
976366f6083SPeter Grehan 	struct vm_capability vmcap;
977366f6083SPeter Grehan 
978366f6083SPeter Grehan 	bzero(&vmcap, sizeof(vmcap));
979366f6083SPeter Grehan 	vmcap.captype = cap;
980366f6083SPeter Grehan 	vmcap.capval = val;
981366f6083SPeter Grehan 
9827d9ef309SJohn Baldwin 	return (vcpu_ioctl(vcpu, VM_SET_CAPABILITY, &vmcap));
983366f6083SPeter Grehan }
984366f6083SPeter Grehan 
985366f6083SPeter Grehan int
986366f6083SPeter Grehan vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
987366f6083SPeter Grehan {
988366f6083SPeter Grehan 	struct vm_pptdev pptdev;
989366f6083SPeter Grehan 
990366f6083SPeter Grehan 	bzero(&pptdev, sizeof(pptdev));
991366f6083SPeter Grehan 	pptdev.bus = bus;
992366f6083SPeter Grehan 	pptdev.slot = slot;
993366f6083SPeter Grehan 	pptdev.func = func;
994366f6083SPeter Grehan 
995366f6083SPeter Grehan 	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
996366f6083SPeter Grehan }
997366f6083SPeter Grehan 
998366f6083SPeter Grehan int
999366f6083SPeter Grehan vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1000366f6083SPeter Grehan {
1001366f6083SPeter Grehan 	struct vm_pptdev pptdev;
1002366f6083SPeter Grehan 
1003366f6083SPeter Grehan 	bzero(&pptdev, sizeof(pptdev));
1004366f6083SPeter Grehan 	pptdev.bus = bus;
1005366f6083SPeter Grehan 	pptdev.slot = slot;
1006366f6083SPeter Grehan 	pptdev.func = func;
1007366f6083SPeter Grehan 
1008366f6083SPeter Grehan 	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
1009366f6083SPeter Grehan }
1010366f6083SPeter Grehan 
1011366f6083SPeter Grehan int
1012366f6083SPeter Grehan vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
1013366f6083SPeter Grehan 		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
1014366f6083SPeter Grehan {
1015366f6083SPeter Grehan 	struct vm_pptdev_mmio pptmmio;
1016366f6083SPeter Grehan 
1017366f6083SPeter Grehan 	bzero(&pptmmio, sizeof(pptmmio));
1018366f6083SPeter Grehan 	pptmmio.bus = bus;
1019366f6083SPeter Grehan 	pptmmio.slot = slot;
1020366f6083SPeter Grehan 	pptmmio.func = func;
1021366f6083SPeter Grehan 	pptmmio.gpa = gpa;
1022366f6083SPeter Grehan 	pptmmio.len = len;
1023366f6083SPeter Grehan 	pptmmio.hpa = hpa;
1024366f6083SPeter Grehan 
1025366f6083SPeter Grehan 	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
1026366f6083SPeter Grehan }
1027366f6083SPeter Grehan 
1028366f6083SPeter Grehan int
1029f8a6ec2dSD Scott Phillips vm_unmap_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
1030f8a6ec2dSD Scott Phillips 		     vm_paddr_t gpa, size_t len)
1031f8a6ec2dSD Scott Phillips {
1032f8a6ec2dSD Scott Phillips 	struct vm_pptdev_mmio pptmmio;
1033f8a6ec2dSD Scott Phillips 
1034f8a6ec2dSD Scott Phillips 	bzero(&pptmmio, sizeof(pptmmio));
1035f8a6ec2dSD Scott Phillips 	pptmmio.bus = bus;
1036f8a6ec2dSD Scott Phillips 	pptmmio.slot = slot;
1037f8a6ec2dSD Scott Phillips 	pptmmio.func = func;
1038f8a6ec2dSD Scott Phillips 	pptmmio.gpa = gpa;
1039f8a6ec2dSD Scott Phillips 	pptmmio.len = len;
1040f8a6ec2dSD Scott Phillips 
1041f8a6ec2dSD Scott Phillips 	return (ioctl(ctx->fd, VM_UNMAP_PPTDEV_MMIO, &pptmmio));
1042f8a6ec2dSD Scott Phillips }
1043f8a6ec2dSD Scott Phillips 
1044f8a6ec2dSD Scott Phillips int
10457d9ef309SJohn Baldwin vm_setup_pptdev_msi(struct vmctx *ctx, int bus, int slot, int func,
10464f8be175SNeel Natu     uint64_t addr, uint64_t msg, int numvec)
1047366f6083SPeter Grehan {
1048366f6083SPeter Grehan 	struct vm_pptdev_msi pptmsi;
1049366f6083SPeter Grehan 
1050366f6083SPeter Grehan 	bzero(&pptmsi, sizeof(pptmsi));
1051366f6083SPeter Grehan 	pptmsi.bus = bus;
1052366f6083SPeter Grehan 	pptmsi.slot = slot;
1053366f6083SPeter Grehan 	pptmsi.func = func;
10544f8be175SNeel Natu 	pptmsi.msg = msg;
10554f8be175SNeel Natu 	pptmsi.addr = addr;
1056366f6083SPeter Grehan 	pptmsi.numvec = numvec;
1057366f6083SPeter Grehan 
1058366f6083SPeter Grehan 	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
1059366f6083SPeter Grehan }
1060366f6083SPeter Grehan 
1061cd942e0fSPeter Grehan int
10627d9ef309SJohn Baldwin vm_setup_pptdev_msix(struct vmctx *ctx, int bus, int slot, int func,
10634f8be175SNeel Natu     int idx, uint64_t addr, uint64_t msg, uint32_t vector_control)
1064cd942e0fSPeter Grehan {
1065cd942e0fSPeter Grehan 	struct vm_pptdev_msix pptmsix;
1066cd942e0fSPeter Grehan 
1067cd942e0fSPeter Grehan 	bzero(&pptmsix, sizeof(pptmsix));
1068cd942e0fSPeter Grehan 	pptmsix.bus = bus;
1069cd942e0fSPeter Grehan 	pptmsix.slot = slot;
1070cd942e0fSPeter Grehan 	pptmsix.func = func;
1071cd942e0fSPeter Grehan 	pptmsix.idx = idx;
1072cd942e0fSPeter Grehan 	pptmsix.msg = msg;
1073cd942e0fSPeter Grehan 	pptmsix.addr = addr;
1074cd942e0fSPeter Grehan 	pptmsix.vector_control = vector_control;
1075cd942e0fSPeter Grehan 
1076cd942e0fSPeter Grehan 	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
1077cd942e0fSPeter Grehan }
1078cd942e0fSPeter Grehan 
10791925586eSJohn Baldwin int
10801925586eSJohn Baldwin vm_disable_pptdev_msix(struct vmctx *ctx, int bus, int slot, int func)
10811925586eSJohn Baldwin {
10821925586eSJohn Baldwin 	struct vm_pptdev ppt;
10831925586eSJohn Baldwin 
10841925586eSJohn Baldwin 	bzero(&ppt, sizeof(ppt));
10851925586eSJohn Baldwin 	ppt.bus = bus;
10861925586eSJohn Baldwin 	ppt.slot = slot;
10871925586eSJohn Baldwin 	ppt.func = func;
10881925586eSJohn Baldwin 
10891925586eSJohn Baldwin 	return ioctl(ctx->fd, VM_PPTDEV_DISABLE_MSIX, &ppt);
10901925586eSJohn Baldwin }
10911925586eSJohn Baldwin 
1092366f6083SPeter Grehan uint64_t *
10937d9ef309SJohn Baldwin vm_get_stats(struct vcpu *vcpu, struct timeval *ret_tv,
1094366f6083SPeter Grehan 	     int *ret_entries)
1095366f6083SPeter Grehan {
109664269786SJohn Baldwin 	static _Thread_local uint64_t *stats_buf;
109764269786SJohn Baldwin 	static _Thread_local u_int stats_count;
109864269786SJohn Baldwin 	uint64_t *new_stats;
109964269786SJohn Baldwin 	struct vm_stats vmstats;
110064269786SJohn Baldwin 	u_int count, index;
110164269786SJohn Baldwin 	bool have_stats;
1102366f6083SPeter Grehan 
110364269786SJohn Baldwin 	have_stats = false;
110464269786SJohn Baldwin 	count = 0;
110564269786SJohn Baldwin 	for (index = 0;; index += nitems(vmstats.statbuf)) {
110664269786SJohn Baldwin 		vmstats.index = index;
11077d9ef309SJohn Baldwin 		if (vcpu_ioctl(vcpu, VM_STATS, &vmstats) != 0)
110864269786SJohn Baldwin 			break;
110964269786SJohn Baldwin 		if (stats_count < index + vmstats.num_entries) {
111064269786SJohn Baldwin 			new_stats = realloc(stats_buf,
111164269786SJohn Baldwin 			    (index + vmstats.num_entries) * sizeof(uint64_t));
111264269786SJohn Baldwin 			if (new_stats == NULL) {
111364269786SJohn Baldwin 				errno = ENOMEM;
111464269786SJohn Baldwin 				return (NULL);
111564269786SJohn Baldwin 			}
111664269786SJohn Baldwin 			stats_count = index + vmstats.num_entries;
111764269786SJohn Baldwin 			stats_buf = new_stats;
111864269786SJohn Baldwin 		}
111964269786SJohn Baldwin 		memcpy(stats_buf + index, vmstats.statbuf,
112064269786SJohn Baldwin 		    vmstats.num_entries * sizeof(uint64_t));
112164269786SJohn Baldwin 		count += vmstats.num_entries;
112264269786SJohn Baldwin 		have_stats = true;
1123366f6083SPeter Grehan 
112464269786SJohn Baldwin 		if (vmstats.num_entries != nitems(vmstats.statbuf))
112564269786SJohn Baldwin 			break;
112664269786SJohn Baldwin 	}
112764269786SJohn Baldwin 	if (have_stats) {
1128366f6083SPeter Grehan 		if (ret_entries)
112964269786SJohn Baldwin 			*ret_entries = count;
1130366f6083SPeter Grehan 		if (ret_tv)
1131366f6083SPeter Grehan 			*ret_tv = vmstats.tv;
113264269786SJohn Baldwin 		return (stats_buf);
1133366f6083SPeter Grehan 	} else
1134366f6083SPeter Grehan 		return (NULL);
1135366f6083SPeter Grehan }
1136366f6083SPeter Grehan 
1137366f6083SPeter Grehan const char *
1138366f6083SPeter Grehan vm_get_stat_desc(struct vmctx *ctx, int index)
1139366f6083SPeter Grehan {
1140366f6083SPeter Grehan 	static struct vm_stat_desc statdesc;
1141366f6083SPeter Grehan 
1142366f6083SPeter Grehan 	statdesc.index = index;
1143366f6083SPeter Grehan 	if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
1144366f6083SPeter Grehan 		return (statdesc.desc);
1145366f6083SPeter Grehan 	else
1146366f6083SPeter Grehan 		return (NULL);
1147366f6083SPeter Grehan }
1148366f6083SPeter Grehan 
1149e9027382SNeel Natu int
11507d9ef309SJohn Baldwin vm_get_x2apic_state(struct vcpu *vcpu, enum x2apic_state *state)
1151e9027382SNeel Natu {
1152e9027382SNeel Natu 	int error;
1153e9027382SNeel Natu 	struct vm_x2apic x2apic;
1154e9027382SNeel Natu 
1155e9027382SNeel Natu 	bzero(&x2apic, sizeof(x2apic));
1156e9027382SNeel Natu 
11577d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GET_X2APIC_STATE, &x2apic);
1158e9027382SNeel Natu 	*state = x2apic.state;
1159e9027382SNeel Natu 	return (error);
1160e9027382SNeel Natu }
1161e9027382SNeel Natu 
1162e9027382SNeel Natu int
11637d9ef309SJohn Baldwin vm_set_x2apic_state(struct vcpu *vcpu, enum x2apic_state state)
1164e9027382SNeel Natu {
1165e9027382SNeel Natu 	int error;
1166e9027382SNeel Natu 	struct vm_x2apic x2apic;
1167e9027382SNeel Natu 
1168e9027382SNeel Natu 	bzero(&x2apic, sizeof(x2apic));
1169e9027382SNeel Natu 	x2apic.state = state;
1170e9027382SNeel Natu 
11717d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_SET_X2APIC_STATE, &x2apic);
1172e9027382SNeel Natu 
1173e9027382SNeel Natu 	return (error);
1174e9027382SNeel Natu }
1175e9027382SNeel Natu 
1176366f6083SPeter Grehan /*
1177366f6083SPeter Grehan  * From Intel Vol 3a:
1178366f6083SPeter Grehan  * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
1179366f6083SPeter Grehan  */
1180366f6083SPeter Grehan int
11817d9ef309SJohn Baldwin vcpu_reset(struct vcpu *vcpu)
1182366f6083SPeter Grehan {
1183366f6083SPeter Grehan 	int error;
1184366f6083SPeter Grehan 	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
1185366f6083SPeter Grehan 	uint32_t desc_access, desc_limit;
1186366f6083SPeter Grehan 	uint16_t sel;
1187366f6083SPeter Grehan 
1188366f6083SPeter Grehan 	zero = 0;
1189366f6083SPeter Grehan 
1190366f6083SPeter Grehan 	rflags = 0x2;
11917d9ef309SJohn Baldwin 	error = vm_set_register(vcpu, VM_REG_GUEST_RFLAGS, rflags);
1192366f6083SPeter Grehan 	if (error)
1193366f6083SPeter Grehan 		goto done;
1194366f6083SPeter Grehan 
1195366f6083SPeter Grehan 	rip = 0xfff0;
11967d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RIP, rip)) != 0)
1197366f6083SPeter Grehan 		goto done;
1198366f6083SPeter Grehan 
119956b8f5b1SCorvin Köhne 	/*
120056b8f5b1SCorvin Köhne 	 * According to Intels Software Developer Manual CR0 should be
120156b8f5b1SCorvin Köhne 	 * initialized with CR0_ET | CR0_NW | CR0_CD but that crashes some
120256b8f5b1SCorvin Köhne 	 * guests like Windows.
120356b8f5b1SCorvin Köhne 	 */
1204366f6083SPeter Grehan 	cr0 = CR0_NE;
12057d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
1206366f6083SPeter Grehan 		goto done;
1207366f6083SPeter Grehan 
12087d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR2, zero)) != 0)
120956b8f5b1SCorvin Köhne 		goto done;
121056b8f5b1SCorvin Köhne 
12117d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR3, zero)) != 0)
1212366f6083SPeter Grehan 		goto done;
1213366f6083SPeter Grehan 
121432c96bc8SNeel Natu 	cr4 = 0;
12157d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
1216366f6083SPeter Grehan 		goto done;
1217366f6083SPeter Grehan 
1218366f6083SPeter Grehan 	/*
1219366f6083SPeter Grehan 	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
1220366f6083SPeter Grehan 	 */
1221366f6083SPeter Grehan 	desc_base = 0xffff0000;
1222366f6083SPeter Grehan 	desc_limit = 0xffff;
1223366f6083SPeter Grehan 	desc_access = 0x0093;
12247d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_CS,
1225366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1226366f6083SPeter Grehan 	if (error)
1227366f6083SPeter Grehan 		goto done;
1228366f6083SPeter Grehan 
1229366f6083SPeter Grehan 	sel = 0xf000;
12307d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_CS, sel)) != 0)
1231366f6083SPeter Grehan 		goto done;
1232366f6083SPeter Grehan 
1233366f6083SPeter Grehan 	/*
1234366f6083SPeter Grehan 	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
1235366f6083SPeter Grehan 	 */
1236366f6083SPeter Grehan 	desc_base = 0;
1237366f6083SPeter Grehan 	desc_limit = 0xffff;
1238366f6083SPeter Grehan 	desc_access = 0x0093;
12397d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_SS,
1240366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1241366f6083SPeter Grehan 	if (error)
1242366f6083SPeter Grehan 		goto done;
1243366f6083SPeter Grehan 
12447d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_DS,
1245366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1246366f6083SPeter Grehan 	if (error)
1247366f6083SPeter Grehan 		goto done;
1248366f6083SPeter Grehan 
12497d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_ES,
1250366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1251366f6083SPeter Grehan 	if (error)
1252366f6083SPeter Grehan 		goto done;
1253366f6083SPeter Grehan 
12547d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_FS,
1255366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1256366f6083SPeter Grehan 	if (error)
1257366f6083SPeter Grehan 		goto done;
1258366f6083SPeter Grehan 
12597d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_GS,
1260366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1261366f6083SPeter Grehan 	if (error)
1262366f6083SPeter Grehan 		goto done;
1263366f6083SPeter Grehan 
1264366f6083SPeter Grehan 	sel = 0;
12657d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_SS, sel)) != 0)
1266366f6083SPeter Grehan 		goto done;
12677d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_DS, sel)) != 0)
1268366f6083SPeter Grehan 		goto done;
12697d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_ES, sel)) != 0)
1270366f6083SPeter Grehan 		goto done;
12717d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_FS, sel)) != 0)
1272366f6083SPeter Grehan 		goto done;
12737d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_GS, sel)) != 0)
1274366f6083SPeter Grehan 		goto done;
1275366f6083SPeter Grehan 
12767d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_EFER, zero)) != 0)
127756b8f5b1SCorvin Köhne 		goto done;
127856b8f5b1SCorvin Köhne 
1279366f6083SPeter Grehan 	/* General purpose registers */
1280366f6083SPeter Grehan 	rdx = 0xf00;
12817d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RAX, zero)) != 0)
1282366f6083SPeter Grehan 		goto done;
12837d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBX, zero)) != 0)
1284366f6083SPeter Grehan 		goto done;
12857d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RCX, zero)) != 0)
1286366f6083SPeter Grehan 		goto done;
12877d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
1288366f6083SPeter Grehan 		goto done;
12897d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSI, zero)) != 0)
1290366f6083SPeter Grehan 		goto done;
12917d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RDI, zero)) != 0)
1292366f6083SPeter Grehan 		goto done;
12937d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RBP, zero)) != 0)
1294366f6083SPeter Grehan 		goto done;
12957d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_RSP, zero)) != 0)
1296366f6083SPeter Grehan 		goto done;
12977d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R8, zero)) != 0)
129856b8f5b1SCorvin Köhne 		goto done;
12997d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R9, zero)) != 0)
130056b8f5b1SCorvin Köhne 		goto done;
13017d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R10, zero)) != 0)
130256b8f5b1SCorvin Köhne 		goto done;
13037d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R11, zero)) != 0)
130456b8f5b1SCorvin Köhne 		goto done;
13057d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R12, zero)) != 0)
130656b8f5b1SCorvin Köhne 		goto done;
13077d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R13, zero)) != 0)
130856b8f5b1SCorvin Köhne 		goto done;
13097d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R14, zero)) != 0)
131056b8f5b1SCorvin Köhne 		goto done;
13117d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_R15, zero)) != 0)
131256b8f5b1SCorvin Köhne 		goto done;
1313366f6083SPeter Grehan 
1314366f6083SPeter Grehan 	/* GDTR, IDTR */
1315366f6083SPeter Grehan 	desc_base = 0;
1316366f6083SPeter Grehan 	desc_limit = 0xffff;
1317366f6083SPeter Grehan 	desc_access = 0;
13187d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_GDTR,
1319366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1320366f6083SPeter Grehan 	if (error != 0)
1321366f6083SPeter Grehan 		goto done;
1322366f6083SPeter Grehan 
13237d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_IDTR,
1324366f6083SPeter Grehan 			    desc_base, desc_limit, desc_access);
1325366f6083SPeter Grehan 	if (error != 0)
1326366f6083SPeter Grehan 		goto done;
1327366f6083SPeter Grehan 
1328366f6083SPeter Grehan 	/* TR */
1329366f6083SPeter Grehan 	desc_base = 0;
1330366f6083SPeter Grehan 	desc_limit = 0xffff;
1331366f6083SPeter Grehan 	desc_access = 0x0000008b;
13327d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
1333366f6083SPeter Grehan 	if (error)
1334366f6083SPeter Grehan 		goto done;
1335366f6083SPeter Grehan 
1336366f6083SPeter Grehan 	sel = 0;
13377d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_TR, sel)) != 0)
1338366f6083SPeter Grehan 		goto done;
1339366f6083SPeter Grehan 
1340366f6083SPeter Grehan 	/* LDTR */
1341366f6083SPeter Grehan 	desc_base = 0;
1342366f6083SPeter Grehan 	desc_limit = 0xffff;
1343366f6083SPeter Grehan 	desc_access = 0x00000082;
13447d9ef309SJohn Baldwin 	error = vm_set_desc(vcpu, VM_REG_GUEST_LDTR, desc_base,
1345366f6083SPeter Grehan 			    desc_limit, desc_access);
1346366f6083SPeter Grehan 	if (error)
1347366f6083SPeter Grehan 		goto done;
1348366f6083SPeter Grehan 
1349366f6083SPeter Grehan 	sel = 0;
13507d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
1351366f6083SPeter Grehan 		goto done;
1352366f6083SPeter Grehan 
13537d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR6,
135456b8f5b1SCorvin Köhne 		 0xffff0ff0)) != 0)
135556b8f5b1SCorvin Köhne 		goto done;
13567d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_DR7, 0x400)) !=
135756b8f5b1SCorvin Köhne 	    0)
135856b8f5b1SCorvin Köhne 		goto done;
135956b8f5b1SCorvin Köhne 
13607d9ef309SJohn Baldwin 	if ((error = vm_set_register(vcpu, VM_REG_GUEST_INTR_SHADOW,
136156b8f5b1SCorvin Köhne 		 zero)) != 0)
136256b8f5b1SCorvin Köhne 		goto done;
1363366f6083SPeter Grehan 
1364366f6083SPeter Grehan 	error = 0;
1365366f6083SPeter Grehan done:
1366366f6083SPeter Grehan 	return (error);
1367366f6083SPeter Grehan }
1368318224bbSNeel Natu 
1369318224bbSNeel Natu int
1370318224bbSNeel Natu vm_get_gpa_pmap(struct vmctx *ctx, uint64_t gpa, uint64_t *pte, int *num)
1371318224bbSNeel Natu {
1372318224bbSNeel Natu 	int error, i;
1373318224bbSNeel Natu 	struct vm_gpa_pte gpapte;
1374318224bbSNeel Natu 
1375318224bbSNeel Natu 	bzero(&gpapte, sizeof(gpapte));
1376318224bbSNeel Natu 	gpapte.gpa = gpa;
1377318224bbSNeel Natu 
1378318224bbSNeel Natu 	error = ioctl(ctx->fd, VM_GET_GPA_PMAP, &gpapte);
1379318224bbSNeel Natu 
1380318224bbSNeel Natu 	if (error == 0) {
1381318224bbSNeel Natu 		*num = gpapte.ptenum;
1382318224bbSNeel Natu 		for (i = 0; i < gpapte.ptenum; i++)
1383318224bbSNeel Natu 			pte[i] = gpapte.pte[i];
1384318224bbSNeel Natu 	}
1385318224bbSNeel Natu 
1386318224bbSNeel Natu 	return (error);
1387318224bbSNeel Natu }
138808e3ff32SNeel Natu 
138908e3ff32SNeel Natu int
139008e3ff32SNeel Natu vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
139108e3ff32SNeel Natu {
139208e3ff32SNeel Natu 	int error;
139308e3ff32SNeel Natu 	struct vm_hpet_cap cap;
139408e3ff32SNeel Natu 
139508e3ff32SNeel Natu 	bzero(&cap, sizeof(struct vm_hpet_cap));
139608e3ff32SNeel Natu 	error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap);
139708e3ff32SNeel Natu 	if (capabilities != NULL)
139808e3ff32SNeel Natu 		*capabilities = cap.capabilities;
139908e3ff32SNeel Natu 	return (error);
140008e3ff32SNeel Natu }
1401da11f4aaSNeel Natu 
14029c4d5478SNeel Natu int
14037d9ef309SJohn Baldwin vm_gla2gpa(struct vcpu *vcpu, struct vm_guest_paging *paging,
14049c4d5478SNeel Natu     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1405da11f4aaSNeel Natu {
1406da11f4aaSNeel Natu 	struct vm_gla2gpa gg;
1407da11f4aaSNeel Natu 	int error;
1408da11f4aaSNeel Natu 
1409da11f4aaSNeel Natu 	bzero(&gg, sizeof(struct vm_gla2gpa));
1410da11f4aaSNeel Natu 	gg.prot = prot;
1411da11f4aaSNeel Natu 	gg.gla = gla;
1412da11f4aaSNeel Natu 	gg.paging = *paging;
1413da11f4aaSNeel Natu 
14147d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GLA2GPA, &gg);
1415da11f4aaSNeel Natu 	if (error == 0) {
1416da11f4aaSNeel Natu 		*fault = gg.fault;
1417da11f4aaSNeel Natu 		*gpa = gg.gpa;
1418da11f4aaSNeel Natu 	}
1419da11f4aaSNeel Natu 	return (error);
1420da11f4aaSNeel Natu }
1421da11f4aaSNeel Natu 
14225f8754c0SJohn Baldwin int
14237d9ef309SJohn Baldwin vm_gla2gpa_nofault(struct vcpu *vcpu, struct vm_guest_paging *paging,
14245f8754c0SJohn Baldwin     uint64_t gla, int prot, uint64_t *gpa, int *fault)
14255f8754c0SJohn Baldwin {
14265f8754c0SJohn Baldwin 	struct vm_gla2gpa gg;
14275f8754c0SJohn Baldwin 	int error;
14285f8754c0SJohn Baldwin 
14295f8754c0SJohn Baldwin 	bzero(&gg, sizeof(struct vm_gla2gpa));
14305f8754c0SJohn Baldwin 	gg.prot = prot;
14315f8754c0SJohn Baldwin 	gg.gla = gla;
14325f8754c0SJohn Baldwin 	gg.paging = *paging;
14335f8754c0SJohn Baldwin 
14347d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GLA2GPA_NOFAULT, &gg);
14355f8754c0SJohn Baldwin 	if (error == 0) {
14365f8754c0SJohn Baldwin 		*fault = gg.fault;
14375f8754c0SJohn Baldwin 		*gpa = gg.gpa;
14385f8754c0SJohn Baldwin 	}
14395f8754c0SJohn Baldwin 	return (error);
14405f8754c0SJohn Baldwin }
14415f8754c0SJohn Baldwin 
1442da11f4aaSNeel Natu #ifndef min
1443da11f4aaSNeel Natu #define	min(a,b)	(((a) < (b)) ? (a) : (b))
1444da11f4aaSNeel Natu #endif
1445da11f4aaSNeel Natu 
1446da11f4aaSNeel Natu int
14477d9ef309SJohn Baldwin vm_copy_setup(struct vcpu *vcpu, struct vm_guest_paging *paging,
14489c4d5478SNeel Natu     uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt,
14499c4d5478SNeel Natu     int *fault)
1450da11f4aaSNeel Natu {
1451009e2acbSNeel Natu 	void *va;
145245cd18ecSMark Johnston 	uint64_t gpa, off;
145345cd18ecSMark Johnston 	int error, i, n;
14546303b65dSNeel Natu 
14556303b65dSNeel Natu 	for (i = 0; i < iovcnt; i++) {
14566303b65dSNeel Natu 		iov[i].iov_base = 0;
14576303b65dSNeel Natu 		iov[i].iov_len = 0;
14586303b65dSNeel Natu 	}
14596303b65dSNeel Natu 
14606303b65dSNeel Natu 	while (len) {
14616303b65dSNeel Natu 		assert(iovcnt > 0);
14627d9ef309SJohn Baldwin 		error = vm_gla2gpa(vcpu, paging, gla, prot, &gpa, fault);
14639c4d5478SNeel Natu 		if (error || *fault)
14649c4d5478SNeel Natu 			return (error);
14656303b65dSNeel Natu 
14666303b65dSNeel Natu 		off = gpa & PAGE_MASK;
146745cd18ecSMark Johnston 		n = MIN(len, PAGE_SIZE - off);
14686303b65dSNeel Natu 
14697d9ef309SJohn Baldwin 		va = vm_map_gpa(vcpu->ctx, gpa, n);
1470009e2acbSNeel Natu 		if (va == NULL)
14719c4d5478SNeel Natu 			return (EFAULT);
1472009e2acbSNeel Natu 
1473009e2acbSNeel Natu 		iov->iov_base = va;
14746303b65dSNeel Natu 		iov->iov_len = n;
14756303b65dSNeel Natu 		iov++;
14766303b65dSNeel Natu 		iovcnt--;
14776303b65dSNeel Natu 
14786303b65dSNeel Natu 		gla += n;
14796303b65dSNeel Natu 		len -= n;
14806303b65dSNeel Natu 	}
14816303b65dSNeel Natu 	return (0);
14826303b65dSNeel Natu }
14836303b65dSNeel Natu 
14846303b65dSNeel Natu void
14852b4fe856SJohn Baldwin vm_copy_teardown(struct iovec *iov __unused, int iovcnt __unused)
1486009e2acbSNeel Natu {
14872b4fe856SJohn Baldwin 	/*
14882b4fe856SJohn Baldwin 	 * Intentionally empty.  This is used by the instruction
14892b4fe856SJohn Baldwin 	 * emulation code shared with the kernel.  The in-kernel
14902b4fe856SJohn Baldwin 	 * version of this is non-empty.
14912b4fe856SJohn Baldwin 	 */
1492009e2acbSNeel Natu }
1493009e2acbSNeel Natu 
1494009e2acbSNeel Natu void
14952b4fe856SJohn Baldwin vm_copyin(struct iovec *iov, void *vp, size_t len)
14966303b65dSNeel Natu {
14976303b65dSNeel Natu 	const char *src;
14986303b65dSNeel Natu 	char *dst;
14996303b65dSNeel Natu 	size_t n;
1500da11f4aaSNeel Natu 
1501da11f4aaSNeel Natu 	dst = vp;
1502da11f4aaSNeel Natu 	while (len) {
15036303b65dSNeel Natu 		assert(iov->iov_len);
15046303b65dSNeel Natu 		n = min(len, iov->iov_len);
1505009e2acbSNeel Natu 		src = iov->iov_base;
1506da11f4aaSNeel Natu 		bcopy(src, dst, n);
1507da11f4aaSNeel Natu 
15086303b65dSNeel Natu 		iov++;
1509da11f4aaSNeel Natu 		dst += n;
1510da11f4aaSNeel Natu 		len -= n;
1511da11f4aaSNeel Natu 	}
1512da11f4aaSNeel Natu }
1513da11f4aaSNeel Natu 
15146303b65dSNeel Natu void
15152b4fe856SJohn Baldwin vm_copyout(const void *vp, struct iovec *iov, size_t len)
1516da11f4aaSNeel Natu {
1517da11f4aaSNeel Natu 	const char *src;
15186303b65dSNeel Natu 	char *dst;
15196303b65dSNeel Natu 	size_t n;
1520da11f4aaSNeel Natu 
1521da11f4aaSNeel Natu 	src = vp;
1522da11f4aaSNeel Natu 	while (len) {
15236303b65dSNeel Natu 		assert(iov->iov_len);
15246303b65dSNeel Natu 		n = min(len, iov->iov_len);
1525009e2acbSNeel Natu 		dst = iov->iov_base;
1526da11f4aaSNeel Natu 		bcopy(src, dst, n);
1527da11f4aaSNeel Natu 
15286303b65dSNeel Natu 		iov++;
1529da11f4aaSNeel Natu 		src += n;
1530da11f4aaSNeel Natu 		len -= n;
1531da11f4aaSNeel Natu 	}
1532da11f4aaSNeel Natu }
153395ebc360SNeel Natu 
153495ebc360SNeel Natu static int
153595ebc360SNeel Natu vm_get_cpus(struct vmctx *ctx, int which, cpuset_t *cpus)
153695ebc360SNeel Natu {
153795ebc360SNeel Natu 	struct vm_cpuset vm_cpuset;
153895ebc360SNeel Natu 	int error;
153995ebc360SNeel Natu 
154095ebc360SNeel Natu 	bzero(&vm_cpuset, sizeof(struct vm_cpuset));
154195ebc360SNeel Natu 	vm_cpuset.which = which;
154295ebc360SNeel Natu 	vm_cpuset.cpusetsize = sizeof(cpuset_t);
154395ebc360SNeel Natu 	vm_cpuset.cpus = cpus;
154495ebc360SNeel Natu 
154595ebc360SNeel Natu 	error = ioctl(ctx->fd, VM_GET_CPUS, &vm_cpuset);
154695ebc360SNeel Natu 	return (error);
154795ebc360SNeel Natu }
154895ebc360SNeel Natu 
154995ebc360SNeel Natu int
155095ebc360SNeel Natu vm_active_cpus(struct vmctx *ctx, cpuset_t *cpus)
155195ebc360SNeel Natu {
155295ebc360SNeel Natu 
155395ebc360SNeel Natu 	return (vm_get_cpus(ctx, VM_ACTIVE_CPUS, cpus));
155495ebc360SNeel Natu }
155595ebc360SNeel Natu 
155695ebc360SNeel Natu int
155795ebc360SNeel Natu vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus)
155895ebc360SNeel Natu {
155995ebc360SNeel Natu 
156095ebc360SNeel Natu 	return (vm_get_cpus(ctx, VM_SUSPENDED_CPUS, cpus));
156195ebc360SNeel Natu }
156295ebc360SNeel Natu 
156395ebc360SNeel Natu int
1564fc276d92SJohn Baldwin vm_debug_cpus(struct vmctx *ctx, cpuset_t *cpus)
1565fc276d92SJohn Baldwin {
1566fc276d92SJohn Baldwin 
1567fc276d92SJohn Baldwin 	return (vm_get_cpus(ctx, VM_DEBUG_CPUS, cpus));
1568fc276d92SJohn Baldwin }
1569fc276d92SJohn Baldwin 
1570fc276d92SJohn Baldwin int
15717d9ef309SJohn Baldwin vm_activate_cpu(struct vcpu *vcpu)
157295ebc360SNeel Natu {
157395ebc360SNeel Natu 	struct vm_activate_cpu ac;
157495ebc360SNeel Natu 	int error;
157595ebc360SNeel Natu 
157695ebc360SNeel Natu 	bzero(&ac, sizeof(struct vm_activate_cpu));
15777d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_ACTIVATE_CPU, &ac);
157895ebc360SNeel Natu 	return (error);
157995ebc360SNeel Natu }
1580091d4532SNeel Natu 
1581091d4532SNeel Natu int
15827d9ef309SJohn Baldwin vm_suspend_all_cpus(struct vmctx *ctx)
1583fc276d92SJohn Baldwin {
1584fc276d92SJohn Baldwin 	struct vm_activate_cpu ac;
1585fc276d92SJohn Baldwin 	int error;
1586fc276d92SJohn Baldwin 
1587fc276d92SJohn Baldwin 	bzero(&ac, sizeof(struct vm_activate_cpu));
15887d9ef309SJohn Baldwin 	ac.vcpuid = -1;
1589fc276d92SJohn Baldwin 	error = ioctl(ctx->fd, VM_SUSPEND_CPU, &ac);
1590fc276d92SJohn Baldwin 	return (error);
1591fc276d92SJohn Baldwin }
1592fc276d92SJohn Baldwin 
1593fc276d92SJohn Baldwin int
15947d9ef309SJohn Baldwin vm_suspend_cpu(struct vcpu *vcpu)
1595fc276d92SJohn Baldwin {
1596fc276d92SJohn Baldwin 	struct vm_activate_cpu ac;
1597fc276d92SJohn Baldwin 	int error;
1598fc276d92SJohn Baldwin 
1599fc276d92SJohn Baldwin 	bzero(&ac, sizeof(struct vm_activate_cpu));
16007d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_SUSPEND_CPU, &ac);
16017d9ef309SJohn Baldwin 	return (error);
16027d9ef309SJohn Baldwin }
16037d9ef309SJohn Baldwin 
16047d9ef309SJohn Baldwin int
16057d9ef309SJohn Baldwin vm_resume_cpu(struct vcpu *vcpu)
16067d9ef309SJohn Baldwin {
16077d9ef309SJohn Baldwin 	struct vm_activate_cpu ac;
16087d9ef309SJohn Baldwin 	int error;
16097d9ef309SJohn Baldwin 
16107d9ef309SJohn Baldwin 	bzero(&ac, sizeof(struct vm_activate_cpu));
16117d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_RESUME_CPU, &ac);
16127d9ef309SJohn Baldwin 	return (error);
16137d9ef309SJohn Baldwin }
16147d9ef309SJohn Baldwin 
16157d9ef309SJohn Baldwin int
16167d9ef309SJohn Baldwin vm_resume_all_cpus(struct vmctx *ctx)
16177d9ef309SJohn Baldwin {
16187d9ef309SJohn Baldwin 	struct vm_activate_cpu ac;
16197d9ef309SJohn Baldwin 	int error;
16207d9ef309SJohn Baldwin 
16217d9ef309SJohn Baldwin 	bzero(&ac, sizeof(struct vm_activate_cpu));
16227d9ef309SJohn Baldwin 	ac.vcpuid = -1;
1623fc276d92SJohn Baldwin 	error = ioctl(ctx->fd, VM_RESUME_CPU, &ac);
1624fc276d92SJohn Baldwin 	return (error);
1625fc276d92SJohn Baldwin }
1626fc276d92SJohn Baldwin 
1627fc276d92SJohn Baldwin int
16287d9ef309SJohn Baldwin vm_get_intinfo(struct vcpu *vcpu, uint64_t *info1, uint64_t *info2)
1629091d4532SNeel Natu {
1630091d4532SNeel Natu 	struct vm_intinfo vmii;
1631091d4532SNeel Natu 	int error;
1632091d4532SNeel Natu 
1633091d4532SNeel Natu 	bzero(&vmii, sizeof(struct vm_intinfo));
16347d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_GET_INTINFO, &vmii);
1635091d4532SNeel Natu 	if (error == 0) {
1636091d4532SNeel Natu 		*info1 = vmii.info1;
1637091d4532SNeel Natu 		*info2 = vmii.info2;
1638091d4532SNeel Natu 	}
1639091d4532SNeel Natu 	return (error);
1640091d4532SNeel Natu }
1641091d4532SNeel Natu 
1642091d4532SNeel Natu int
16437d9ef309SJohn Baldwin vm_set_intinfo(struct vcpu *vcpu, uint64_t info1)
1644091d4532SNeel Natu {
1645091d4532SNeel Natu 	struct vm_intinfo vmii;
1646091d4532SNeel Natu 	int error;
1647091d4532SNeel Natu 
1648091d4532SNeel Natu 	bzero(&vmii, sizeof(struct vm_intinfo));
1649091d4532SNeel Natu 	vmii.info1 = info1;
16507d9ef309SJohn Baldwin 	error = vcpu_ioctl(vcpu, VM_SET_INTINFO, &vmii);
1651091d4532SNeel Natu 	return (error);
1652091d4532SNeel Natu }
16530dafa5cdSNeel Natu 
16540dafa5cdSNeel Natu int
16550dafa5cdSNeel Natu vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
16560dafa5cdSNeel Natu {
16570dafa5cdSNeel Natu 	struct vm_rtc_data rtcdata;
16580dafa5cdSNeel Natu 	int error;
16590dafa5cdSNeel Natu 
16600dafa5cdSNeel Natu 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
16610dafa5cdSNeel Natu 	rtcdata.offset = offset;
16620dafa5cdSNeel Natu 	rtcdata.value = value;
16630dafa5cdSNeel Natu 	error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
16640dafa5cdSNeel Natu 	return (error);
16650dafa5cdSNeel Natu }
16660dafa5cdSNeel Natu 
16670dafa5cdSNeel Natu int
16680dafa5cdSNeel Natu vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
16690dafa5cdSNeel Natu {
16700dafa5cdSNeel Natu 	struct vm_rtc_data rtcdata;
16710dafa5cdSNeel Natu 	int error;
16720dafa5cdSNeel Natu 
16730dafa5cdSNeel Natu 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
16740dafa5cdSNeel Natu 	rtcdata.offset = offset;
16750dafa5cdSNeel Natu 	error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
16760dafa5cdSNeel Natu 	if (error == 0)
16770dafa5cdSNeel Natu 		*retval = rtcdata.value;
16780dafa5cdSNeel Natu 	return (error);
16790dafa5cdSNeel Natu }
16800dafa5cdSNeel Natu 
16810dafa5cdSNeel Natu int
16820dafa5cdSNeel Natu vm_rtc_settime(struct vmctx *ctx, time_t secs)
16830dafa5cdSNeel Natu {
16840dafa5cdSNeel Natu 	struct vm_rtc_time rtctime;
16850dafa5cdSNeel Natu 	int error;
16860dafa5cdSNeel Natu 
16870dafa5cdSNeel Natu 	bzero(&rtctime, sizeof(struct vm_rtc_time));
16880dafa5cdSNeel Natu 	rtctime.secs = secs;
16890dafa5cdSNeel Natu 	error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
16900dafa5cdSNeel Natu 	return (error);
16910dafa5cdSNeel Natu }
16920dafa5cdSNeel Natu 
16930dafa5cdSNeel Natu int
16940dafa5cdSNeel Natu vm_rtc_gettime(struct vmctx *ctx, time_t *secs)
16950dafa5cdSNeel Natu {
16960dafa5cdSNeel Natu 	struct vm_rtc_time rtctime;
16970dafa5cdSNeel Natu 	int error;
16980dafa5cdSNeel Natu 
16990dafa5cdSNeel Natu 	bzero(&rtctime, sizeof(struct vm_rtc_time));
17000dafa5cdSNeel Natu 	error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
17010dafa5cdSNeel Natu 	if (error == 0)
17020dafa5cdSNeel Natu 		*secs = rtctime.secs;
17030dafa5cdSNeel Natu 	return (error);
17040dafa5cdSNeel Natu }
1705d087a399SNeel Natu 
1706d087a399SNeel Natu int
17077d9ef309SJohn Baldwin vm_restart_instruction(struct vcpu *vcpu)
1708d087a399SNeel Natu {
17097d9ef309SJohn Baldwin 	int arg;
1710d087a399SNeel Natu 
17117d9ef309SJohn Baldwin 	return (vcpu_ioctl(vcpu, VM_RESTART_INSTRUCTION, &arg));
1712d087a399SNeel Natu }
171300ef17beSBartek Rutkowski 
171400ef17beSBartek Rutkowski int
1715*0f735657SJohn Baldwin vm_snapshot_req(struct vmctx *ctx, struct vm_snapshot_meta *meta)
1716483d953aSJohn Baldwin {
1717483d953aSJohn Baldwin 
1718*0f735657SJohn Baldwin 	if (ioctl(ctx->fd, VM_SNAPSHOT_REQ, meta) == -1) {
1719483d953aSJohn Baldwin #ifdef SNAPSHOT_DEBUG
1720483d953aSJohn Baldwin 		fprintf(stderr, "%s: snapshot failed for %s: %d\r\n",
1721483d953aSJohn Baldwin 		    __func__, meta->dev_name, errno);
1722483d953aSJohn Baldwin #endif
1723483d953aSJohn Baldwin 		return (-1);
1724483d953aSJohn Baldwin 	}
1725483d953aSJohn Baldwin 	return (0);
1726483d953aSJohn Baldwin }
1727483d953aSJohn Baldwin 
1728483d953aSJohn Baldwin int
1729483d953aSJohn Baldwin vm_restore_time(struct vmctx *ctx)
1730483d953aSJohn Baldwin {
1731483d953aSJohn Baldwin 	int dummy;
1732483d953aSJohn Baldwin 
1733483d953aSJohn Baldwin 	dummy = 0;
1734483d953aSJohn Baldwin 	return (ioctl(ctx->fd, VM_RESTORE_TIME, &dummy));
1735483d953aSJohn Baldwin }
1736483d953aSJohn Baldwin 
1737483d953aSJohn Baldwin int
173801d822d3SRodney W. Grimes vm_set_topology(struct vmctx *ctx,
173901d822d3SRodney W. Grimes     uint16_t sockets, uint16_t cores, uint16_t threads, uint16_t maxcpus)
174001d822d3SRodney W. Grimes {
174101d822d3SRodney W. Grimes 	struct vm_cpu_topology topology;
174201d822d3SRodney W. Grimes 
174301d822d3SRodney W. Grimes 	bzero(&topology, sizeof (struct vm_cpu_topology));
174401d822d3SRodney W. Grimes 	topology.sockets = sockets;
174501d822d3SRodney W. Grimes 	topology.cores = cores;
174601d822d3SRodney W. Grimes 	topology.threads = threads;
174701d822d3SRodney W. Grimes 	topology.maxcpus = maxcpus;
174801d822d3SRodney W. Grimes 	return (ioctl(ctx->fd, VM_SET_TOPOLOGY, &topology));
174901d822d3SRodney W. Grimes }
175001d822d3SRodney W. Grimes 
175101d822d3SRodney W. Grimes int
175201d822d3SRodney W. Grimes vm_get_topology(struct vmctx *ctx,
175301d822d3SRodney W. Grimes     uint16_t *sockets, uint16_t *cores, uint16_t *threads, uint16_t *maxcpus)
175401d822d3SRodney W. Grimes {
175501d822d3SRodney W. Grimes 	struct vm_cpu_topology topology;
175601d822d3SRodney W. Grimes 	int error;
175701d822d3SRodney W. Grimes 
175801d822d3SRodney W. Grimes 	bzero(&topology, sizeof (struct vm_cpu_topology));
175901d822d3SRodney W. Grimes 	error = ioctl(ctx->fd, VM_GET_TOPOLOGY, &topology);
176001d822d3SRodney W. Grimes 	if (error == 0) {
176101d822d3SRodney W. Grimes 		*sockets = topology.sockets;
176201d822d3SRodney W. Grimes 		*cores = topology.cores;
176301d822d3SRodney W. Grimes 		*threads = topology.threads;
176401d822d3SRodney W. Grimes 		*maxcpus = topology.maxcpus;
176501d822d3SRodney W. Grimes 	}
176601d822d3SRodney W. Grimes 	return (error);
176701d822d3SRodney W. Grimes }
176801d822d3SRodney W. Grimes 
17693e9b4532SMark Johnston /* Keep in sync with machine/vmm_dev.h. */
177000ef17beSBartek Rutkowski static const cap_ioctl_t vm_ioctl_cmds[] = { VM_RUN, VM_SUSPEND, VM_REINIT,
177100ef17beSBartek Rutkowski     VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
1772f8a6ec2dSD Scott Phillips     VM_MMAP_GETNEXT, VM_MUNMAP_MEMSEG, VM_SET_REGISTER, VM_GET_REGISTER,
177300ef17beSBartek Rutkowski     VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
17744f866698SJohn Baldwin     VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
17758a68ae80SConrad Meyer     VM_SET_KERNEMU_DEV, VM_GET_KERNEMU_DEV,
177600ef17beSBartek Rutkowski     VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
177700ef17beSBartek Rutkowski     VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
177800ef17beSBartek Rutkowski     VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,
177900ef17beSBartek Rutkowski     VM_ISA_DEASSERT_IRQ, VM_ISA_PULSE_IRQ, VM_ISA_SET_IRQ_TRIGGER,
178000ef17beSBartek Rutkowski     VM_SET_CAPABILITY, VM_GET_CAPABILITY, VM_BIND_PPTDEV,
178100ef17beSBartek Rutkowski     VM_UNBIND_PPTDEV, VM_MAP_PPTDEV_MMIO, VM_PPTDEV_MSI,
1782f8a6ec2dSD Scott Phillips     VM_PPTDEV_MSIX, VM_UNMAP_PPTDEV_MMIO, VM_PPTDEV_DISABLE_MSIX,
17831925586eSJohn Baldwin     VM_INJECT_NMI, VM_STATS, VM_STAT_DESC,
178400ef17beSBartek Rutkowski     VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
178500ef17beSBartek Rutkowski     VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
17865f8754c0SJohn Baldwin     VM_GLA2GPA_NOFAULT,
1787fc276d92SJohn Baldwin     VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU,
1788fc276d92SJohn Baldwin     VM_SET_INTINFO, VM_GET_INTINFO,
178900ef17beSBartek Rutkowski     VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
1790755dcd5eSVitaliy Gusev     VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY,
1791755dcd5eSVitaliy Gusev     VM_SNAPSHOT_REQ, VM_RESTORE_TIME
17923e9b4532SMark Johnston };
17933e9b4532SMark Johnston 
17943e9b4532SMark Johnston int
17953e9b4532SMark Johnston vm_limit_rights(struct vmctx *ctx)
17963e9b4532SMark Johnston {
17973e9b4532SMark Johnston 	cap_rights_t rights;
17983e9b4532SMark Johnston 	size_t ncmds;
17993e9b4532SMark Johnston 
18003e9b4532SMark Johnston 	cap_rights_init(&rights, CAP_IOCTL, CAP_MMAP_RW);
18013e9b4532SMark Johnston 	if (caph_rights_limit(ctx->fd, &rights) != 0)
18023e9b4532SMark Johnston 		return (-1);
18033e9b4532SMark Johnston 	ncmds = nitems(vm_ioctl_cmds);
18043e9b4532SMark Johnston 	if (caph_ioctls_limit(ctx->fd, vm_ioctl_cmds, ncmds) != 0)
18053e9b4532SMark Johnston 		return (-1);
18063e9b4532SMark Johnston 	return (0);
18073e9b4532SMark Johnston }
18083e9b4532SMark Johnston 
18093e9b4532SMark Johnston /*
18103e9b4532SMark Johnston  * Avoid using in new code.  Operations on the fd should be wrapped here so that
18113e9b4532SMark Johnston  * capability rights can be kept in sync.
18123e9b4532SMark Johnston  */
18133e9b4532SMark Johnston int
18143e9b4532SMark Johnston vm_get_device_fd(struct vmctx *ctx)
18153e9b4532SMark Johnston {
18163e9b4532SMark Johnston 
18173e9b4532SMark Johnston 	return (ctx->fd);
18183e9b4532SMark Johnston }
18193e9b4532SMark Johnston 
18203e9b4532SMark Johnston /* Legacy interface, do not use. */
18213e9b4532SMark Johnston const cap_ioctl_t *
18223e9b4532SMark Johnston vm_get_ioctls(size_t *len)
18233e9b4532SMark Johnston {
18243e9b4532SMark Johnston 	cap_ioctl_t *cmds;
182500ef17beSBartek Rutkowski 
182600ef17beSBartek Rutkowski 	if (len == NULL) {
182700ef17beSBartek Rutkowski 		cmds = malloc(sizeof(vm_ioctl_cmds));
182800ef17beSBartek Rutkowski 		if (cmds == NULL)
182900ef17beSBartek Rutkowski 			return (NULL);
183000ef17beSBartek Rutkowski 		bcopy(vm_ioctl_cmds, cmds, sizeof(vm_ioctl_cmds));
183100ef17beSBartek Rutkowski 		return (cmds);
183200ef17beSBartek Rutkowski 	}
183300ef17beSBartek Rutkowski 
183400ef17beSBartek Rutkowski 	*len = nitems(vm_ioctl_cmds);
183500ef17beSBartek Rutkowski 	return (NULL);
183600ef17beSBartek Rutkowski }
1837