1bf21cd93STycho Nightingale /*-
24c87aefeSPatrick Mooney  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
34c87aefeSPatrick Mooney  *
4bf21cd93STycho Nightingale  * Copyright (c) 2011 NetApp, Inc.
5bf21cd93STycho Nightingale  * All rights reserved.
6bf21cd93STycho Nightingale  *
7bf21cd93STycho Nightingale  * Redistribution and use in source and binary forms, with or without
8bf21cd93STycho Nightingale  * modification, are permitted provided that the following conditions
9bf21cd93STycho Nightingale  * are met:
10bf21cd93STycho Nightingale  * 1. Redistributions of source code must retain the above copyright
11bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer.
12bf21cd93STycho Nightingale  * 2. Redistributions in binary form must reproduce the above copyright
13bf21cd93STycho Nightingale  *    notice, this list of conditions and the following disclaimer in the
14bf21cd93STycho Nightingale  *    documentation and/or other materials provided with the distribution.
15bf21cd93STycho Nightingale  *
16bf21cd93STycho Nightingale  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17bf21cd93STycho Nightingale  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18bf21cd93STycho Nightingale  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19bf21cd93STycho Nightingale  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20bf21cd93STycho Nightingale  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21bf21cd93STycho Nightingale  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22bf21cd93STycho Nightingale  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23bf21cd93STycho Nightingale  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24bf21cd93STycho Nightingale  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25bf21cd93STycho Nightingale  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26bf21cd93STycho Nightingale  * SUCH DAMAGE.
27bf21cd93STycho Nightingale  *
284c87aefeSPatrick Mooney  * $FreeBSD$
29bf21cd93STycho Nightingale  */
30bf21cd93STycho Nightingale /*
31bf21cd93STycho Nightingale  * This file and its contents are supplied under the terms of the
32bf21cd93STycho Nightingale  * Common Development and Distribution License ("CDDL"), version 1.0.
33bf21cd93STycho Nightingale  * You may only use this file in accordance with the terms of version
34bf21cd93STycho Nightingale  * 1.0 of the CDDL.
35bf21cd93STycho Nightingale  *
36bf21cd93STycho Nightingale  * A full copy of the text of the CDDL should have accompanied this
37bf21cd93STycho Nightingale  * source.  A copy of the CDDL is also available via the Internet at
38bf21cd93STycho Nightingale  * http://www.illumos.org/license/CDDL.
39bf21cd93STycho Nightingale  *
40bf21cd93STycho Nightingale  * Copyright 2015 Pluribus Networks Inc.
414c87aefeSPatrick Mooney  * Copyright 2019 Joyent, Inc.
42*b57f5d3eSPatrick Mooney  * Copyright 2021 Oxide Computer Company
43bf21cd93STycho Nightingale  */
44bf21cd93STycho Nightingale 
45bf21cd93STycho Nightingale #include <sys/cdefs.h>
464c87aefeSPatrick Mooney __FBSDID("$FreeBSD$");
47bf21cd93STycho Nightingale 
48bf21cd93STycho Nightingale #include <sys/param.h>
49bf21cd93STycho Nightingale #include <sys/sysctl.h>
50bf21cd93STycho Nightingale #include <sys/ioctl.h>
51154972afSPatrick Mooney #ifdef	__FreeBSD__
52154972afSPatrick Mooney #include <sys/linker.h>
53154972afSPatrick Mooney #endif
54bf21cd93STycho Nightingale #include <sys/mman.h>
55154972afSPatrick Mooney #include <sys/module.h>
56bf21cd93STycho Nightingale #include <sys/_iovec.h>
57bf21cd93STycho Nightingale #include <sys/cpuset.h>
58bf21cd93STycho Nightingale 
594c87aefeSPatrick Mooney #include <x86/segments.h>
60bf21cd93STycho Nightingale #include <machine/specialreg.h>
61bf21cd93STycho Nightingale 
62bf21cd93STycho Nightingale #include <errno.h>
63bf21cd93STycho Nightingale #include <stdio.h>
64bf21cd93STycho Nightingale #include <stdlib.h>
65bf21cd93STycho Nightingale #include <assert.h>
66bf21cd93STycho Nightingale #include <string.h>
67bf21cd93STycho Nightingale #include <fcntl.h>
68bf21cd93STycho Nightingale #include <unistd.h>
69bf21cd93STycho Nightingale 
70bf21cd93STycho Nightingale #include <libutil.h>
71bf21cd93STycho Nightingale 
72bf21cd93STycho Nightingale #include <machine/vmm.h>
73bf21cd93STycho Nightingale #include <machine/vmm_dev.h>
74bf21cd93STycho Nightingale 
75bf21cd93STycho Nightingale #include "vmmapi.h"
76bf21cd93STycho Nightingale 
77bf21cd93STycho Nightingale #define	MB	(1024 * 1024UL)
78bf21cd93STycho Nightingale #define	GB	(1024 * 1024 * 1024UL)
79bf21cd93STycho Nightingale 
804c87aefeSPatrick Mooney #ifndef __FreeBSD__
814c87aefeSPatrick Mooney /* shim to no-op for now */
824c87aefeSPatrick Mooney #define	MAP_NOCORE		0
834c87aefeSPatrick Mooney #define	MAP_ALIGNED_SUPER	0
844c87aefeSPatrick Mooney 
854c87aefeSPatrick Mooney /* Rely on PROT_NONE for guard purposes */
864c87aefeSPatrick Mooney #define	MAP_GUARD		(MAP_PRIVATE | MAP_ANON | MAP_NORESERVE)
874c87aefeSPatrick Mooney #endif
884c87aefeSPatrick Mooney 
894c87aefeSPatrick Mooney /*
904c87aefeSPatrick Mooney  * Size of the guard region before and after the virtual address space
914c87aefeSPatrick Mooney  * mapping the guest physical memory. This must be a multiple of the
924c87aefeSPatrick Mooney  * superpage size for performance reasons.
934c87aefeSPatrick Mooney  */
944c87aefeSPatrick Mooney #define	VM_MMAP_GUARD_SIZE	(4 * MB)
954c87aefeSPatrick Mooney 
964c87aefeSPatrick Mooney #define	PROT_RW		(PROT_READ | PROT_WRITE)
974c87aefeSPatrick Mooney #define	PROT_ALL	(PROT_READ | PROT_WRITE | PROT_EXEC)
984c87aefeSPatrick Mooney 
99bf21cd93STycho Nightingale struct vmctx {
100bf21cd93STycho Nightingale 	int	fd;
101bf21cd93STycho Nightingale 	uint32_t lowmem_limit;
1024c87aefeSPatrick Mooney 	int	memflags;
103bf21cd93STycho Nightingale 	size_t	lowmem;
104bf21cd93STycho Nightingale 	size_t	highmem;
1054c87aefeSPatrick Mooney 	char	*baseaddr;
106bf21cd93STycho Nightingale 	char	*name;
107bf21cd93STycho Nightingale };
108bf21cd93STycho Nightingale 
109bf21cd93STycho Nightingale #ifdef	__FreeBSD__
110bf21cd93STycho Nightingale #define	CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
111bf21cd93STycho Nightingale #define	DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
112bf21cd93STycho Nightingale 
113*b57f5d3eSPatrick Mooney int
114*b57f5d3eSPatrick Mooney vm_create(const char *name)
115*b57f5d3eSPatrick Mooney {
116*b57f5d3eSPatrick Mooney 	/* Try to load vmm(4) module before creating a guest. */
117*b57f5d3eSPatrick Mooney 	if (modfind("vmm") < 0)
118*b57f5d3eSPatrick Mooney 		kldload("vmm");
119*b57f5d3eSPatrick Mooney 	return (CREATE((char *)name));
120*b57f5d3eSPatrick Mooney }
121*b57f5d3eSPatrick Mooney 
122*b57f5d3eSPatrick Mooney void
123*b57f5d3eSPatrick Mooney vm_destroy(struct vmctx *vm)
124*b57f5d3eSPatrick Mooney {
125*b57f5d3eSPatrick Mooney 	assert(vm != NULL);
126*b57f5d3eSPatrick Mooney 
127*b57f5d3eSPatrick Mooney 	if (vm->fd >= 0)
128*b57f5d3eSPatrick Mooney 		close(vm->fd);
129*b57f5d3eSPatrick Mooney 	DESTROY(vm->name);
130*b57f5d3eSPatrick Mooney 
131*b57f5d3eSPatrick Mooney 	free(vm);
132*b57f5d3eSPatrick Mooney }
133*b57f5d3eSPatrick Mooney 
134*b57f5d3eSPatrick Mooney #else
135bf21cd93STycho Nightingale static int
136*b57f5d3eSPatrick Mooney vm_do_ctl(int cmd, void *req)
137bf21cd93STycho Nightingale {
1384c87aefeSPatrick Mooney 	int ctl_fd;
139bf21cd93STycho Nightingale 
1404c87aefeSPatrick Mooney 	ctl_fd = open(VMM_CTL_DEV, O_EXCL | O_RDWR);
1414c87aefeSPatrick Mooney 	if (ctl_fd < 0) {
1424c87aefeSPatrick Mooney 		return (-1);
1434c87aefeSPatrick Mooney 	}
144bf21cd93STycho Nightingale 
145*b57f5d3eSPatrick Mooney 	if (ioctl(ctl_fd, cmd, req) == -1) {
1464c87aefeSPatrick Mooney 		int err = errno;
147bf21cd93STycho Nightingale 
1484c87aefeSPatrick Mooney 		/* Do not lose ioctl errno through the close(2) */
1494c87aefeSPatrick Mooney 		(void) close(ctl_fd);
1504c87aefeSPatrick Mooney 		errno = err;
1514c87aefeSPatrick Mooney 		return (-1);
1524c87aefeSPatrick Mooney 	}
1534c87aefeSPatrick Mooney 	(void) close(ctl_fd);
1544c87aefeSPatrick Mooney 
1554c87aefeSPatrick Mooney 	return (0);
156bf21cd93STycho Nightingale }
157*b57f5d3eSPatrick Mooney 
158*b57f5d3eSPatrick Mooney int
159*b57f5d3eSPatrick Mooney vm_create(const char *name, uint64_t flags)
160*b57f5d3eSPatrick Mooney {
161*b57f5d3eSPatrick Mooney 	struct vm_create_req req;
162*b57f5d3eSPatrick Mooney 
163*b57f5d3eSPatrick Mooney 	(void) strncpy(req.name, name, VM_MAX_NAMELEN);
164*b57f5d3eSPatrick Mooney 	req.flags = flags;
165*b57f5d3eSPatrick Mooney 
166*b57f5d3eSPatrick Mooney 	return (vm_do_ctl(VMM_CREATE_VM, &req));
167*b57f5d3eSPatrick Mooney }
168*b57f5d3eSPatrick Mooney 
169*b57f5d3eSPatrick Mooney void
170*b57f5d3eSPatrick Mooney vm_close(struct vmctx *vm)
171*b57f5d3eSPatrick Mooney {
172*b57f5d3eSPatrick Mooney 	assert(vm != NULL);
173*b57f5d3eSPatrick Mooney 	assert(vm->fd >= 0);
174*b57f5d3eSPatrick Mooney 
175*b57f5d3eSPatrick Mooney 	(void) close(vm->fd);
176*b57f5d3eSPatrick Mooney 
177*b57f5d3eSPatrick Mooney 	free(vm);
178*b57f5d3eSPatrick Mooney }
179*b57f5d3eSPatrick Mooney 
180*b57f5d3eSPatrick Mooney void
181*b57f5d3eSPatrick Mooney vm_destroy(struct vmctx *vm)
182*b57f5d3eSPatrick Mooney {
183*b57f5d3eSPatrick Mooney 	struct vm_destroy_req req;
184*b57f5d3eSPatrick Mooney 
185*b57f5d3eSPatrick Mooney 	assert(vm != NULL);
186*b57f5d3eSPatrick Mooney 
187*b57f5d3eSPatrick Mooney 	if (vm->fd >= 0) {
188*b57f5d3eSPatrick Mooney 		(void) close(vm->fd);
189*b57f5d3eSPatrick Mooney 		vm->fd = -1;
190*b57f5d3eSPatrick Mooney 	}
191*b57f5d3eSPatrick Mooney 
192*b57f5d3eSPatrick Mooney 	(void) strncpy(req.name, vm->name, VM_MAX_NAMELEN);
193*b57f5d3eSPatrick Mooney 	(void) vm_do_ctl(VMM_DESTROY_VM, &req);
194*b57f5d3eSPatrick Mooney 
195*b57f5d3eSPatrick Mooney 	free(vm);
196*b57f5d3eSPatrick Mooney }
1974c87aefeSPatrick Mooney #endif
198bf21cd93STycho Nightingale 
199bf21cd93STycho Nightingale static int
2004c87aefeSPatrick Mooney vm_device_open(const char *name)
201bf21cd93STycho Nightingale {
2024c87aefeSPatrick Mooney 	int fd, len;
2034c87aefeSPatrick Mooney 	char *vmfile;
204bf21cd93STycho Nightingale 
2054c87aefeSPatrick Mooney 	len = strlen("/dev/vmm/") + strlen(name) + 1;
2064c87aefeSPatrick Mooney 	vmfile = malloc(len);
2074c87aefeSPatrick Mooney 	assert(vmfile != NULL);
2084c87aefeSPatrick Mooney 	snprintf(vmfile, len, "/dev/vmm/%s", name);
209bf21cd93STycho Nightingale 
2104c87aefeSPatrick Mooney 	/* Open the device file */
2114c87aefeSPatrick Mooney 	fd = open(vmfile, O_RDWR, 0);
212bf21cd93STycho Nightingale 
2134c87aefeSPatrick Mooney 	free(vmfile);
2144c87aefeSPatrick Mooney 	return (fd);
215bf21cd93STycho Nightingale }
216bf21cd93STycho Nightingale 
217bf21cd93STycho Nightingale struct vmctx *
218bf21cd93STycho Nightingale vm_open(const char *name)
219bf21cd93STycho Nightingale {
220bf21cd93STycho Nightingale 	struct vmctx *vm;
221bf21cd93STycho Nightingale 
222bf21cd93STycho Nightingale 	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
223bf21cd93STycho Nightingale 	assert(vm != NULL);
224bf21cd93STycho Nightingale 
225bf21cd93STycho Nightingale 	vm->fd = -1;
2264c87aefeSPatrick Mooney 	vm->memflags = 0;
227bf21cd93STycho Nightingale 	vm->lowmem_limit = 3 * GB;
228bf21cd93STycho Nightingale 	vm->name = (char *)(vm + 1);
229bf21cd93STycho Nightingale 	strcpy(vm->name, name);
230bf21cd93STycho Nightingale 
231bf21cd93STycho Nightingale 	if ((vm->fd = vm_device_open(vm->name)) < 0)
232bf21cd93STycho Nightingale 		goto err;
233bf21cd93STycho Nightingale 
234bf21cd93STycho Nightingale 	return (vm);
235bf21cd93STycho Nightingale err:
2369c3024a3SHans Rosenfeld 	free(vm);
237bf21cd93STycho Nightingale 	return (NULL);
238bf21cd93STycho Nightingale }
239bf21cd93STycho Nightingale 
240bf21cd93STycho Nightingale 
241bf21cd93STycho Nightingale int
242bf21cd93STycho Nightingale vm_parse_memsize(const char *optarg, size_t *ret_memsize)
243bf21cd93STycho Nightingale {
244bf21cd93STycho Nightingale 	char *endptr;
245bf21cd93STycho Nightingale 	size_t optval;
246bf21cd93STycho Nightingale 	int error;
247bf21cd93STycho Nightingale 
248bf21cd93STycho Nightingale 	optval = strtoul(optarg, &endptr, 0);
249bf21cd93STycho Nightingale 	if (*optarg != '\0' && *endptr == '\0') {
250bf21cd93STycho Nightingale 		/*
251bf21cd93STycho Nightingale 		 * For the sake of backward compatibility if the memory size
252bf21cd93STycho Nightingale 		 * specified on the command line is less than a megabyte then
253bf21cd93STycho Nightingale 		 * it is interpreted as being in units of MB.
254bf21cd93STycho Nightingale 		 */
255bf21cd93STycho Nightingale 		if (optval < MB)
256bf21cd93STycho Nightingale 			optval *= MB;
257bf21cd93STycho Nightingale 		*ret_memsize = optval;
258bf21cd93STycho Nightingale 		error = 0;
259bf21cd93STycho Nightingale 	} else
260bf21cd93STycho Nightingale 		error = expand_number(optarg, ret_memsize);
261bf21cd93STycho Nightingale 
262bf21cd93STycho Nightingale 	return (error);
263bf21cd93STycho Nightingale }
264bf21cd93STycho Nightingale 
2654c87aefeSPatrick Mooney uint32_t
2664c87aefeSPatrick Mooney vm_get_lowmem_limit(struct vmctx *ctx)
267bf21cd93STycho Nightingale {
2684c87aefeSPatrick Mooney 
2694c87aefeSPatrick Mooney 	return (ctx->lowmem_limit);
270bf21cd93STycho Nightingale }
271bf21cd93STycho Nightingale 
2724c87aefeSPatrick Mooney void
2734c87aefeSPatrick Mooney vm_set_lowmem_limit(struct vmctx *ctx, uint32_t limit)
274bf21cd93STycho Nightingale {
2754c87aefeSPatrick Mooney 
2764c87aefeSPatrick Mooney 	ctx->lowmem_limit = limit;
2774c87aefeSPatrick Mooney }
2784c87aefeSPatrick Mooney 
2794c87aefeSPatrick Mooney void
2804c87aefeSPatrick Mooney vm_set_memflags(struct vmctx *ctx, int flags)
2814c87aefeSPatrick Mooney {
2824c87aefeSPatrick Mooney 
2834c87aefeSPatrick Mooney 	ctx->memflags = flags;
284bf21cd93STycho Nightingale }
285bf21cd93STycho Nightingale 
286bf21cd93STycho Nightingale int
2874c87aefeSPatrick Mooney vm_get_memflags(struct vmctx *ctx)
288bf21cd93STycho Nightingale {
2894c87aefeSPatrick Mooney 
2904c87aefeSPatrick Mooney 	return (ctx->memflags);
2914c87aefeSPatrick Mooney }
2924c87aefeSPatrick Mooney 
2934c87aefeSPatrick Mooney /*
2944c87aefeSPatrick Mooney  * Map segment 'segid' starting at 'off' into guest address range [gpa,gpa+len).
2954c87aefeSPatrick Mooney  */
2964c87aefeSPatrick Mooney int
2974c87aefeSPatrick Mooney vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, vm_ooffset_t off,
2984c87aefeSPatrick Mooney     size_t len, int prot)
2994c87aefeSPatrick Mooney {
3004c87aefeSPatrick Mooney 	struct vm_memmap memmap;
3014c87aefeSPatrick Mooney 	int error, flags;
3024c87aefeSPatrick Mooney 
3034c87aefeSPatrick Mooney 	memmap.gpa = gpa;
3044c87aefeSPatrick Mooney 	memmap.segid = segid;
3054c87aefeSPatrick Mooney 	memmap.segoff = off;
3064c87aefeSPatrick Mooney 	memmap.len = len;
3074c87aefeSPatrick Mooney 	memmap.prot = prot;
3084c87aefeSPatrick Mooney 	memmap.flags = 0;
3094c87aefeSPatrick Mooney 
3104c87aefeSPatrick Mooney 	if (ctx->memflags & VM_MEM_F_WIRED)
3114c87aefeSPatrick Mooney 		memmap.flags |= VM_MEMMAP_F_WIRED;
3124c87aefeSPatrick Mooney 
3134c87aefeSPatrick Mooney 	/*
3144c87aefeSPatrick Mooney 	 * If this mapping already exists then don't create it again. This
3154c87aefeSPatrick Mooney 	 * is the common case for SYSMEM mappings created by bhyveload(8).
3164c87aefeSPatrick Mooney 	 */
3174c87aefeSPatrick Mooney 	error = vm_mmap_getnext(ctx, &gpa, &segid, &off, &len, &prot, &flags);
3184c87aefeSPatrick Mooney 	if (error == 0 && gpa == memmap.gpa) {
3194c87aefeSPatrick Mooney 		if (segid != memmap.segid || off != memmap.segoff ||
3204c87aefeSPatrick Mooney 		    prot != memmap.prot || flags != memmap.flags) {
3214c87aefeSPatrick Mooney 			errno = EEXIST;
3224c87aefeSPatrick Mooney 			return (-1);
3234c87aefeSPatrick Mooney 		} else {
3244c87aefeSPatrick Mooney 			return (0);
3254c87aefeSPatrick Mooney 		}
3264c87aefeSPatrick Mooney 	}
3274c87aefeSPatrick Mooney 
3284c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_MMAP_MEMSEG, &memmap);
329bf21cd93STycho Nightingale 	return (error);
330bf21cd93STycho Nightingale }
331bf21cd93STycho Nightingale 
3322b948146SAndy Fiddaman int
3332b948146SAndy Fiddaman vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
3342b948146SAndy Fiddaman {
3352b948146SAndy Fiddaman 	struct vm_munmap munmap;
3362b948146SAndy Fiddaman 	int error;
3372b948146SAndy Fiddaman 
3382b948146SAndy Fiddaman 	munmap.gpa = gpa;
3392b948146SAndy Fiddaman 	munmap.len = len;
3402b948146SAndy Fiddaman 
3412b948146SAndy Fiddaman 	error = ioctl(ctx->fd, VM_MUNMAP_MEMSEG, &munmap);
3422b948146SAndy Fiddaman 	return (error);
3432b948146SAndy Fiddaman }
3442b948146SAndy Fiddaman 
3454c87aefeSPatrick Mooney int
3464c87aefeSPatrick Mooney vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
3474c87aefeSPatrick Mooney     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
348bf21cd93STycho Nightingale {
3494c87aefeSPatrick Mooney 	struct vm_memmap memmap;
3504c87aefeSPatrick Mooney 	int error;
351bf21cd93STycho Nightingale 
3524c87aefeSPatrick Mooney 	bzero(&memmap, sizeof(struct vm_memmap));
3534c87aefeSPatrick Mooney 	memmap.gpa = *gpa;
3544c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_MMAP_GETNEXT, &memmap);
3554c87aefeSPatrick Mooney 	if (error == 0) {
3564c87aefeSPatrick Mooney 		*gpa = memmap.gpa;
3574c87aefeSPatrick Mooney 		*segid = memmap.segid;
3584c87aefeSPatrick Mooney 		*segoff = memmap.segoff;
3594c87aefeSPatrick Mooney 		*len = memmap.len;
3604c87aefeSPatrick Mooney 		*prot = memmap.prot;
3614c87aefeSPatrick Mooney 		*flags = memmap.flags;
3624c87aefeSPatrick Mooney 	}
3634c87aefeSPatrick Mooney 	return (error);
364bf21cd93STycho Nightingale }
365bf21cd93STycho Nightingale 
3664c87aefeSPatrick Mooney /*
3674c87aefeSPatrick Mooney  * Return 0 if the segments are identical and non-zero otherwise.
3684c87aefeSPatrick Mooney  *
3694c87aefeSPatrick Mooney  * This is slightly complicated by the fact that only device memory segments
3704c87aefeSPatrick Mooney  * are named.
3714c87aefeSPatrick Mooney  */
3724c87aefeSPatrick Mooney static int
3734c87aefeSPatrick Mooney cmpseg(size_t len, const char *str, size_t len2, const char *str2)
374bf21cd93STycho Nightingale {
375bf21cd93STycho Nightingale 
3764c87aefeSPatrick Mooney 	if (len == len2) {
3774c87aefeSPatrick Mooney 		if ((!str && !str2) || (str && str2 && !strcmp(str, str2)))
3784c87aefeSPatrick Mooney 			return (0);
3794c87aefeSPatrick Mooney 	}
3804c87aefeSPatrick Mooney 	return (-1);
381bf21cd93STycho Nightingale }
382bf21cd93STycho Nightingale 
383bf21cd93STycho Nightingale static int
3844c87aefeSPatrick Mooney vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
385bf21cd93STycho Nightingale {
3864c87aefeSPatrick Mooney 	struct vm_memseg memseg;
3874c87aefeSPatrick Mooney 	size_t n;
388bf21cd93STycho Nightingale 	int error;
389bf21cd93STycho Nightingale 
390bf21cd93STycho Nightingale 	/*
3914c87aefeSPatrick Mooney 	 * If the memory segment has already been created then just return.
3924c87aefeSPatrick Mooney 	 * This is the usual case for the SYSMEM segment created by userspace
3934c87aefeSPatrick Mooney 	 * loaders like bhyveload(8).
394bf21cd93STycho Nightingale 	 */
3954c87aefeSPatrick Mooney 	error = vm_get_memseg(ctx, segid, &memseg.len, memseg.name,
3964c87aefeSPatrick Mooney 	    sizeof(memseg.name));
3974c87aefeSPatrick Mooney 	if (error)
3984c87aefeSPatrick Mooney 		return (error);
3994c87aefeSPatrick Mooney 
4004c87aefeSPatrick Mooney 	if (memseg.len != 0) {
4014c87aefeSPatrick Mooney 		if (cmpseg(len, name, memseg.len, VM_MEMSEG_NAME(&memseg))) {
4024c87aefeSPatrick Mooney 			errno = EINVAL;
4034c87aefeSPatrick Mooney 			return (-1);
4044c87aefeSPatrick Mooney 		} else {
4054c87aefeSPatrick Mooney 			return (0);
4064c87aefeSPatrick Mooney 		}
4074c87aefeSPatrick Mooney 	}
4084c87aefeSPatrick Mooney 
4094c87aefeSPatrick Mooney 	bzero(&memseg, sizeof(struct vm_memseg));
4104c87aefeSPatrick Mooney 	memseg.segid = segid;
4114c87aefeSPatrick Mooney 	memseg.len = len;
4124c87aefeSPatrick Mooney 	if (name != NULL) {
4134c87aefeSPatrick Mooney 		n = strlcpy(memseg.name, name, sizeof(memseg.name));
4144c87aefeSPatrick Mooney 		if (n >= sizeof(memseg.name)) {
4154c87aefeSPatrick Mooney 			errno = ENAMETOOLONG;
4164c87aefeSPatrick Mooney 			return (-1);
4174c87aefeSPatrick Mooney 		}
4184c87aefeSPatrick Mooney 	}
4194c87aefeSPatrick Mooney 
4204c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_ALLOC_MEMSEG, &memseg);
4214c87aefeSPatrick Mooney 	return (error);
4224c87aefeSPatrick Mooney }
4234c87aefeSPatrick Mooney 
4244c87aefeSPatrick Mooney int
4254c87aefeSPatrick Mooney vm_get_memseg(struct vmctx *ctx, int segid, size_t *lenp, char *namebuf,
4264c87aefeSPatrick Mooney     size_t bufsize)
4274c87aefeSPatrick Mooney {
4284c87aefeSPatrick Mooney 	struct vm_memseg memseg;
4294c87aefeSPatrick Mooney 	size_t n;
4304c87aefeSPatrick Mooney 	int error;
4314c87aefeSPatrick Mooney 
4324c87aefeSPatrick Mooney 	memseg.segid = segid;
4334c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_MEMSEG, &memseg);
4344c87aefeSPatrick Mooney 	if (error == 0) {
4354c87aefeSPatrick Mooney 		*lenp = memseg.len;
4364c87aefeSPatrick Mooney 		n = strlcpy(namebuf, memseg.name, bufsize);
4374c87aefeSPatrick Mooney 		if (n >= bufsize) {
4384c87aefeSPatrick Mooney 			errno = ENAMETOOLONG;
4394c87aefeSPatrick Mooney 			error = -1;
4404c87aefeSPatrick Mooney 		}
441bf21cd93STycho Nightingale 	}
442bf21cd93STycho Nightingale 	return (error);
443bf21cd93STycho Nightingale }
444bf21cd93STycho Nightingale 
4454c87aefeSPatrick Mooney static int
4464c87aefeSPatrick Mooney #ifdef __FreeBSD__
4474c87aefeSPatrick Mooney setup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
4484c87aefeSPatrick Mooney #else
4494c87aefeSPatrick Mooney setup_memory_segment(struct vmctx *ctx, int segid, vm_paddr_t gpa, size_t len,
4504c87aefeSPatrick Mooney     char *base)
4514c87aefeSPatrick Mooney #endif
4524c87aefeSPatrick Mooney {
4534c87aefeSPatrick Mooney 	char *ptr;
4544c87aefeSPatrick Mooney 	int error, flags;
4554c87aefeSPatrick Mooney 
4564c87aefeSPatrick Mooney 	/* Map 'len' bytes starting at 'gpa' in the guest address space */
4574c87aefeSPatrick Mooney #ifdef __FreeBSD__
4584c87aefeSPatrick Mooney 	error = vm_mmap_memseg(ctx, gpa, VM_SYSMEM, gpa, len, PROT_ALL);
4594c87aefeSPatrick Mooney #else
4604c87aefeSPatrick Mooney 	/*
4614c87aefeSPatrick Mooney 	 * As we use two segments for lowmem/highmem the offset within the
4624c87aefeSPatrick Mooney 	 * segment is 0 on illumos.
4634c87aefeSPatrick Mooney 	 */
4644c87aefeSPatrick Mooney 	error = vm_mmap_memseg(ctx, gpa, segid, 0, len, PROT_ALL);
4654c87aefeSPatrick Mooney #endif
4664c87aefeSPatrick Mooney 	if (error)
4674c87aefeSPatrick Mooney 		return (error);
4684c87aefeSPatrick Mooney 
4694c87aefeSPatrick Mooney 	flags = MAP_SHARED | MAP_FIXED;
4704c87aefeSPatrick Mooney 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
4714c87aefeSPatrick Mooney 		flags |= MAP_NOCORE;
4724c87aefeSPatrick Mooney 
4734c87aefeSPatrick Mooney 	/* mmap into the process address space on the host */
4744c87aefeSPatrick Mooney 	ptr = mmap(base + gpa, len, PROT_RW, flags, ctx->fd, gpa);
4754c87aefeSPatrick Mooney 	if (ptr == MAP_FAILED)
4764c87aefeSPatrick Mooney 		return (-1);
4774c87aefeSPatrick Mooney 
4784c87aefeSPatrick Mooney 	return (0);
4794c87aefeSPatrick Mooney }
4804c87aefeSPatrick Mooney 
481bf21cd93STycho Nightingale int
482bf21cd93STycho Nightingale vm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
483bf21cd93STycho Nightingale {
4844c87aefeSPatrick Mooney 	size_t objsize, len;
4854c87aefeSPatrick Mooney 	vm_paddr_t gpa;
4864c87aefeSPatrick Mooney 	char *baseaddr, *ptr;
487bf21cd93STycho Nightingale 	int error;
488bf21cd93STycho Nightingale 
4894c87aefeSPatrick Mooney 	assert(vms == VM_MMAP_ALL);
490bf21cd93STycho Nightingale 
491bf21cd93STycho Nightingale 	/*
492bf21cd93STycho Nightingale 	 * If 'memsize' cannot fit entirely in the 'lowmem' segment then
493bf21cd93STycho Nightingale 	 * create another 'highmem' segment above 4GB for the remainder.
494bf21cd93STycho Nightingale 	 */
495bf21cd93STycho Nightingale 	if (memsize > ctx->lowmem_limit) {
496bf21cd93STycho Nightingale 		ctx->lowmem = ctx->lowmem_limit;
4974c87aefeSPatrick Mooney 		ctx->highmem = memsize - ctx->lowmem_limit;
4984c87aefeSPatrick Mooney 		objsize = 4*GB + ctx->highmem;
499bf21cd93STycho Nightingale 	} else {
500bf21cd93STycho Nightingale 		ctx->lowmem = memsize;
501bf21cd93STycho Nightingale 		ctx->highmem = 0;
5024c87aefeSPatrick Mooney 		objsize = ctx->lowmem;
503bf21cd93STycho Nightingale 	}
504bf21cd93STycho Nightingale 
5054c87aefeSPatrick Mooney #ifdef __FreeBSD__
5064c87aefeSPatrick Mooney 	error = vm_alloc_memseg(ctx, VM_SYSMEM, objsize, NULL);
5074c87aefeSPatrick Mooney 	if (error)
5084c87aefeSPatrick Mooney 		return (error);
5094c87aefeSPatrick Mooney #endif
5104c87aefeSPatrick Mooney 
5114c87aefeSPatrick Mooney 	/*
5124c87aefeSPatrick Mooney 	 * Stake out a contiguous region covering the guest physical memory
5134c87aefeSPatrick Mooney 	 * and the adjoining guard regions.
5144c87aefeSPatrick Mooney 	 */
5154c87aefeSPatrick Mooney 	len = VM_MMAP_GUARD_SIZE + objsize + VM_MMAP_GUARD_SIZE;
5164c87aefeSPatrick Mooney 	ptr = mmap(NULL, len, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1, 0);
5174c87aefeSPatrick Mooney 	if (ptr == MAP_FAILED)
5184c87aefeSPatrick Mooney 		return (-1);
5194c87aefeSPatrick Mooney 
5204c87aefeSPatrick Mooney 	baseaddr = ptr + VM_MMAP_GUARD_SIZE;
521bf21cd93STycho Nightingale 
5224c87aefeSPatrick Mooney #ifdef __FreeBSD__
5234c87aefeSPatrick Mooney 	if (ctx->highmem > 0) {
5244c87aefeSPatrick Mooney 		gpa = 4*GB;
5254c87aefeSPatrick Mooney 		len = ctx->highmem;
5264c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
527bf21cd93STycho Nightingale 		if (error)
528bf21cd93STycho Nightingale 			return (error);
5294c87aefeSPatrick Mooney 	}
530bf21cd93STycho Nightingale 
5314c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
5324c87aefeSPatrick Mooney 		gpa = 0;
5334c87aefeSPatrick Mooney 		len = ctx->lowmem;
5344c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
535bf21cd93STycho Nightingale 		if (error)
536bf21cd93STycho Nightingale 			return (error);
537bf21cd93STycho Nightingale 	}
5384c87aefeSPatrick Mooney #else
539bf21cd93STycho Nightingale 	if (ctx->highmem > 0) {
5404c87aefeSPatrick Mooney 		error = vm_alloc_memseg(ctx, VM_HIGHMEM, ctx->highmem, NULL);
5414c87aefeSPatrick Mooney 		if (error)
5424c87aefeSPatrick Mooney 			return (error);
5434c87aefeSPatrick Mooney 		gpa = 4*GB;
5444c87aefeSPatrick Mooney 		len = ctx->highmem;
5454c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, VM_HIGHMEM, gpa, len, baseaddr);
546bf21cd93STycho Nightingale 		if (error)
547bf21cd93STycho Nightingale 			return (error);
548bf21cd93STycho Nightingale 	}
549bf21cd93STycho Nightingale 
5504c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
5514c87aefeSPatrick Mooney 		error = vm_alloc_memseg(ctx, VM_LOWMEM, ctx->lowmem, NULL);
5524c87aefeSPatrick Mooney 		if (error)
5534c87aefeSPatrick Mooney 			return (error);
5544c87aefeSPatrick Mooney 		gpa = 0;
5554c87aefeSPatrick Mooney 		len = ctx->lowmem;
5564c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, VM_LOWMEM, gpa, len, baseaddr);
5574c87aefeSPatrick Mooney 		if (error)
5584c87aefeSPatrick Mooney 			return (error);
5594c87aefeSPatrick Mooney 	}
5604c87aefeSPatrick Mooney #endif
561bf21cd93STycho Nightingale 
5624c87aefeSPatrick Mooney 	ctx->baseaddr = baseaddr;
563bf21cd93STycho Nightingale 
5644c87aefeSPatrick Mooney 	return (0);
565bf21cd93STycho Nightingale }
566bf21cd93STycho Nightingale 
5674c87aefeSPatrick Mooney /*
5684c87aefeSPatrick Mooney  * Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
5694c87aefeSPatrick Mooney  * the lowmem or highmem regions.
5704c87aefeSPatrick Mooney  *
5714c87aefeSPatrick Mooney  * In particular return NULL if [gaddr, gaddr+len) falls in guest MMIO region.
5724c87aefeSPatrick Mooney  * The instruction emulation code depends on this behavior.
5734c87aefeSPatrick Mooney  */
574bf21cd93STycho Nightingale void *
575bf21cd93STycho Nightingale vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
576bf21cd93STycho Nightingale {
577bf21cd93STycho Nightingale 
5784c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
5794c87aefeSPatrick Mooney 		if (gaddr < ctx->lowmem && len <= ctx->lowmem &&
5804c87aefeSPatrick Mooney 		    gaddr + len <= ctx->lowmem)
5814c87aefeSPatrick Mooney 			return (ctx->baseaddr + gaddr);
582bf21cd93STycho Nightingale 	}
583bf21cd93STycho Nightingale 
5844c87aefeSPatrick Mooney 	if (ctx->highmem > 0) {
5854c87aefeSPatrick Mooney                 if (gaddr >= 4*GB) {
5864c87aefeSPatrick Mooney 			if (gaddr < 4*GB + ctx->highmem &&
5874c87aefeSPatrick Mooney 			    len <= ctx->highmem &&
5884c87aefeSPatrick Mooney 			    gaddr + len <= 4*GB + ctx->highmem)
5894c87aefeSPatrick Mooney 				return (ctx->baseaddr + gaddr);
5904c87aefeSPatrick Mooney 		}
591bf21cd93STycho Nightingale 	}
592bf21cd93STycho Nightingale 
593bf21cd93STycho Nightingale 	return (NULL);
594bf21cd93STycho Nightingale }
595bf21cd93STycho Nightingale 
596bf21cd93STycho Nightingale size_t
597bf21cd93STycho Nightingale vm_get_lowmem_size(struct vmctx *ctx)
598bf21cd93STycho Nightingale {
599bf21cd93STycho Nightingale 
600bf21cd93STycho Nightingale 	return (ctx->lowmem);
601bf21cd93STycho Nightingale }
602bf21cd93STycho Nightingale 
603bf21cd93STycho Nightingale size_t
604bf21cd93STycho Nightingale vm_get_highmem_size(struct vmctx *ctx)
605bf21cd93STycho Nightingale {
606bf21cd93STycho Nightingale 
607bf21cd93STycho Nightingale 	return (ctx->highmem);
608bf21cd93STycho Nightingale }
609bf21cd93STycho Nightingale 
6109c3024a3SHans Rosenfeld #ifndef __FreeBSD__
6119c3024a3SHans Rosenfeld int
6129c3024a3SHans Rosenfeld vm_get_devmem_offset(struct vmctx *ctx, int segid, off_t *mapoff)
6139c3024a3SHans Rosenfeld {
6149c3024a3SHans Rosenfeld 	struct vm_devmem_offset vdo;
6159c3024a3SHans Rosenfeld 	int error;
6169c3024a3SHans Rosenfeld 
6179c3024a3SHans Rosenfeld 	vdo.segid = segid;
6189c3024a3SHans Rosenfeld 	error = ioctl(ctx->fd, VM_DEVMEM_GETOFFSET, &vdo);
6199c3024a3SHans Rosenfeld 	if (error == 0)
6209c3024a3SHans Rosenfeld 		*mapoff = vdo.offset;
6219c3024a3SHans Rosenfeld 
6229c3024a3SHans Rosenfeld 	return (error);
6239c3024a3SHans Rosenfeld }
6249c3024a3SHans Rosenfeld #endif
6259c3024a3SHans Rosenfeld 
6264c87aefeSPatrick Mooney void *
6274c87aefeSPatrick Mooney vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
6284c87aefeSPatrick Mooney {
6294c87aefeSPatrick Mooney #ifdef	__FreeBSD__
6304c87aefeSPatrick Mooney 	char pathname[MAXPATHLEN];
6314c87aefeSPatrick Mooney #endif
6324c87aefeSPatrick Mooney 	size_t len2;
6334c87aefeSPatrick Mooney 	char *base, *ptr;
6344c87aefeSPatrick Mooney 	int fd, error, flags;
6354c87aefeSPatrick Mooney 	off_t mapoff;
6364c87aefeSPatrick Mooney 
6374c87aefeSPatrick Mooney 	fd = -1;
6384c87aefeSPatrick Mooney 	ptr = MAP_FAILED;
6394c87aefeSPatrick Mooney 	if (name == NULL || strlen(name) == 0) {
6404c87aefeSPatrick Mooney 		errno = EINVAL;
6414c87aefeSPatrick Mooney 		goto done;
6424c87aefeSPatrick Mooney 	}
6434c87aefeSPatrick Mooney 
6444c87aefeSPatrick Mooney 	error = vm_alloc_memseg(ctx, segid, len, name);
6454c87aefeSPatrick Mooney 	if (error)
6464c87aefeSPatrick Mooney 		goto done;
6474c87aefeSPatrick Mooney 
6484c87aefeSPatrick Mooney #ifdef	__FreeBSD__
6494c87aefeSPatrick Mooney 	strlcpy(pathname, "/dev/vmm.io/", sizeof(pathname));
6504c87aefeSPatrick Mooney 	strlcat(pathname, ctx->name, sizeof(pathname));
6514c87aefeSPatrick Mooney 	strlcat(pathname, ".", sizeof(pathname));
6524c87aefeSPatrick Mooney 	strlcat(pathname, name, sizeof(pathname));
6534c87aefeSPatrick Mooney 
6544c87aefeSPatrick Mooney 	fd = open(pathname, O_RDWR);
6554c87aefeSPatrick Mooney 	if (fd < 0)
6564c87aefeSPatrick Mooney 		goto done;
6574c87aefeSPatrick Mooney #else
6589c3024a3SHans Rosenfeld 	if (vm_get_devmem_offset(ctx, segid, &mapoff) != 0)
6599c3024a3SHans Rosenfeld 		goto done;
6604c87aefeSPatrick Mooney #endif
6614c87aefeSPatrick Mooney 
6624c87aefeSPatrick Mooney 	/*
6634c87aefeSPatrick Mooney 	 * Stake out a contiguous region covering the device memory and the
6644c87aefeSPatrick Mooney 	 * adjoining guard regions.
6654c87aefeSPatrick Mooney 	 */
6664c87aefeSPatrick Mooney 	len2 = VM_MMAP_GUARD_SIZE + len + VM_MMAP_GUARD_SIZE;
6674c87aefeSPatrick Mooney 	base = mmap(NULL, len2, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1,
6684c87aefeSPatrick Mooney 	    0);
6694c87aefeSPatrick Mooney 	if (base == MAP_FAILED)
6704c87aefeSPatrick Mooney 		goto done;
6714c87aefeSPatrick Mooney 
6724c87aefeSPatrick Mooney 	flags = MAP_SHARED | MAP_FIXED;
6734c87aefeSPatrick Mooney 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
6744c87aefeSPatrick Mooney 		flags |= MAP_NOCORE;
6754c87aefeSPatrick Mooney 
6764c87aefeSPatrick Mooney #ifdef	__FreeBSD__
6774c87aefeSPatrick Mooney 	/* mmap the devmem region in the host address space */
6784c87aefeSPatrick Mooney 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, fd, 0);
6794c87aefeSPatrick Mooney #else
6804c87aefeSPatrick Mooney 	/* mmap the devmem region in the host address space */
6814c87aefeSPatrick Mooney 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, ctx->fd,
6824c87aefeSPatrick Mooney 	    mapoff);
6834c87aefeSPatrick Mooney #endif
6844c87aefeSPatrick Mooney done:
6854c87aefeSPatrick Mooney 	if (fd >= 0)
6864c87aefeSPatrick Mooney 		close(fd);
6874c87aefeSPatrick Mooney 	return (ptr);
6884c87aefeSPatrick Mooney }
6894c87aefeSPatrick Mooney 
690bf21cd93STycho Nightingale int
691bf21cd93STycho Nightingale vm_set_desc(struct vmctx *ctx, int vcpu, int reg,
692bf21cd93STycho Nightingale 	    uint64_t base, uint32_t limit, uint32_t access)
693bf21cd93STycho Nightingale {
694bf21cd93STycho Nightingale 	int error;
695bf21cd93STycho Nightingale 	struct vm_seg_desc vmsegdesc;
696bf21cd93STycho Nightingale 
697bf21cd93STycho Nightingale 	bzero(&vmsegdesc, sizeof(vmsegdesc));
698bf21cd93STycho Nightingale 	vmsegdesc.cpuid = vcpu;
699bf21cd93STycho Nightingale 	vmsegdesc.regnum = reg;
700bf21cd93STycho Nightingale 	vmsegdesc.desc.base = base;
701bf21cd93STycho Nightingale 	vmsegdesc.desc.limit = limit;
702bf21cd93STycho Nightingale 	vmsegdesc.desc.access = access;
703bf21cd93STycho Nightingale 
704bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
705bf21cd93STycho Nightingale 	return (error);
706bf21cd93STycho Nightingale }
707bf21cd93STycho Nightingale 
708bf21cd93STycho Nightingale int
709bf21cd93STycho Nightingale vm_get_desc(struct vmctx *ctx, int vcpu, int reg,
710bf21cd93STycho Nightingale 	    uint64_t *base, uint32_t *limit, uint32_t *access)
711bf21cd93STycho Nightingale {
712bf21cd93STycho Nightingale 	int error;
713bf21cd93STycho Nightingale 	struct vm_seg_desc vmsegdesc;
714bf21cd93STycho Nightingale 
715bf21cd93STycho Nightingale 	bzero(&vmsegdesc, sizeof(vmsegdesc));
716bf21cd93STycho Nightingale 	vmsegdesc.cpuid = vcpu;
717bf21cd93STycho Nightingale 	vmsegdesc.regnum = reg;
718bf21cd93STycho Nightingale 
719bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
720bf21cd93STycho Nightingale 	if (error == 0) {
721bf21cd93STycho Nightingale 		*base = vmsegdesc.desc.base;
722bf21cd93STycho Nightingale 		*limit = vmsegdesc.desc.limit;
723bf21cd93STycho Nightingale 		*access = vmsegdesc.desc.access;
724bf21cd93STycho Nightingale 	}
725bf21cd93STycho Nightingale 	return (error);
726bf21cd93STycho Nightingale }
727bf21cd93STycho Nightingale 
728bf21cd93STycho Nightingale int
729bf21cd93STycho Nightingale vm_get_seg_desc(struct vmctx *ctx, int vcpu, int reg, struct seg_desc *seg_desc)
730bf21cd93STycho Nightingale {
731bf21cd93STycho Nightingale 	int error;
732bf21cd93STycho Nightingale 
733bf21cd93STycho Nightingale 	error = vm_get_desc(ctx, vcpu, reg, &seg_desc->base, &seg_desc->limit,
734bf21cd93STycho Nightingale 	    &seg_desc->access);
735bf21cd93STycho Nightingale 	return (error);
736bf21cd93STycho Nightingale }
737bf21cd93STycho Nightingale 
738bf21cd93STycho Nightingale int
739bf21cd93STycho Nightingale vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
740bf21cd93STycho Nightingale {
741bf21cd93STycho Nightingale 	int error;
742bf21cd93STycho Nightingale 	struct vm_register vmreg;
743bf21cd93STycho Nightingale 
744bf21cd93STycho Nightingale 	bzero(&vmreg, sizeof(vmreg));
745bf21cd93STycho Nightingale 	vmreg.cpuid = vcpu;
746bf21cd93STycho Nightingale 	vmreg.regnum = reg;
747bf21cd93STycho Nightingale 	vmreg.regval = val;
748bf21cd93STycho Nightingale 
749bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
750bf21cd93STycho Nightingale 	return (error);
751bf21cd93STycho Nightingale }
752bf21cd93STycho Nightingale 
753bf21cd93STycho Nightingale int
754bf21cd93STycho Nightingale vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
755bf21cd93STycho Nightingale {
756bf21cd93STycho Nightingale 	int error;
757bf21cd93STycho Nightingale 	struct vm_register vmreg;
758bf21cd93STycho Nightingale 
759bf21cd93STycho Nightingale 	bzero(&vmreg, sizeof(vmreg));
760bf21cd93STycho Nightingale 	vmreg.cpuid = vcpu;
761bf21cd93STycho Nightingale 	vmreg.regnum = reg;
762bf21cd93STycho Nightingale 
763bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
764bf21cd93STycho Nightingale 	*ret_val = vmreg.regval;
765bf21cd93STycho Nightingale 	return (error);
766bf21cd93STycho Nightingale }
767bf21cd93STycho Nightingale 
7684c87aefeSPatrick Mooney int
7694c87aefeSPatrick Mooney vm_set_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
7704c87aefeSPatrick Mooney     const int *regnums, uint64_t *regvals)
7714c87aefeSPatrick Mooney {
7724c87aefeSPatrick Mooney 	int error;
7734c87aefeSPatrick Mooney 	struct vm_register_set vmregset;
7744c87aefeSPatrick Mooney 
7754c87aefeSPatrick Mooney 	bzero(&vmregset, sizeof(vmregset));
7764c87aefeSPatrick Mooney 	vmregset.cpuid = vcpu;
7774c87aefeSPatrick Mooney 	vmregset.count = count;
7784c87aefeSPatrick Mooney 	vmregset.regnums = regnums;
7794c87aefeSPatrick Mooney 	vmregset.regvals = regvals;
7804c87aefeSPatrick Mooney 
7814c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SET_REGISTER_SET, &vmregset);
7824c87aefeSPatrick Mooney 	return (error);
7834c87aefeSPatrick Mooney }
7844c87aefeSPatrick Mooney 
7854c87aefeSPatrick Mooney int
7864c87aefeSPatrick Mooney vm_get_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
7874c87aefeSPatrick Mooney     const int *regnums, uint64_t *regvals)
7884c87aefeSPatrick Mooney {
7894c87aefeSPatrick Mooney 	int error;
7904c87aefeSPatrick Mooney 	struct vm_register_set vmregset;
7914c87aefeSPatrick Mooney 
7924c87aefeSPatrick Mooney 	bzero(&vmregset, sizeof(vmregset));
7934c87aefeSPatrick Mooney 	vmregset.cpuid = vcpu;
7944c87aefeSPatrick Mooney 	vmregset.count = count;
7954c87aefeSPatrick Mooney 	vmregset.regnums = regnums;
7964c87aefeSPatrick Mooney 	vmregset.regvals = regvals;
7974c87aefeSPatrick Mooney 
7984c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_REGISTER_SET, &vmregset);
7994c87aefeSPatrick Mooney 	return (error);
8004c87aefeSPatrick Mooney }
8014c87aefeSPatrick Mooney 
802bf21cd93STycho Nightingale int
803e0c0d44eSPatrick Mooney vm_run(struct vmctx *ctx, int vcpu, const struct vm_entry *vm_entry,
804e0c0d44eSPatrick Mooney     struct vm_exit *vm_exit)
805bf21cd93STycho Nightingale {
806e0c0d44eSPatrick Mooney 	struct vm_entry entry;
807bf21cd93STycho Nightingale 
808e0c0d44eSPatrick Mooney 	bcopy(vm_entry, &entry, sizeof (entry));
809e0c0d44eSPatrick Mooney 	entry.cpuid = vcpu;
810e0c0d44eSPatrick Mooney 	entry.exit_data = vm_exit;
811bf21cd93STycho Nightingale 
812e0c0d44eSPatrick Mooney 	return (ioctl(ctx->fd, VM_RUN, &entry));
813bf21cd93STycho Nightingale }
814bf21cd93STycho Nightingale 
8154c87aefeSPatrick Mooney int
8164c87aefeSPatrick Mooney vm_suspend(struct vmctx *ctx, enum vm_suspend_how how)
817bf21cd93STycho Nightingale {
8184c87aefeSPatrick Mooney 	struct vm_suspend vmsuspend;
819bf21cd93STycho Nightingale 
8204c87aefeSPatrick Mooney 	bzero(&vmsuspend, sizeof(vmsuspend));
8214c87aefeSPatrick Mooney 	vmsuspend.how = how;
8224c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_SUSPEND, &vmsuspend));
8234c87aefeSPatrick Mooney }
824bf21cd93STycho Nightingale 
8254c87aefeSPatrick Mooney int
8264c87aefeSPatrick Mooney vm_reinit(struct vmctx *ctx)
8274c87aefeSPatrick Mooney {
8284c87aefeSPatrick Mooney 
8294c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_REINIT, 0));
830bf21cd93STycho Nightingale }
831bf21cd93STycho Nightingale 
832bf21cd93STycho Nightingale int
833bf21cd93STycho Nightingale vm_inject_exception(struct vmctx *ctx, int vcpu, int vector, int errcode_valid,
834bf21cd93STycho Nightingale     uint32_t errcode, int restart_instruction)
835bf21cd93STycho Nightingale {
836bf21cd93STycho Nightingale 	struct vm_exception exc;
837bf21cd93STycho Nightingale 
838bf21cd93STycho Nightingale 	exc.cpuid = vcpu;
839bf21cd93STycho Nightingale 	exc.vector = vector;
840bf21cd93STycho Nightingale 	exc.error_code = errcode;
841bf21cd93STycho Nightingale 	exc.error_code_valid = errcode_valid;
842bf21cd93STycho Nightingale 	exc.restart_instruction = restart_instruction;
843bf21cd93STycho Nightingale 
844bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_INJECT_EXCEPTION, &exc));
845bf21cd93STycho Nightingale }
846bf21cd93STycho Nightingale 
847b58b977eSPatrick Mooney #ifndef __FreeBSD__
848b58b977eSPatrick Mooney void
849b58b977eSPatrick Mooney vm_inject_fault(struct vmctx *ctx, int vcpu, int vector, int errcode_valid,
850b58b977eSPatrick Mooney     int errcode)
851b58b977eSPatrick Mooney {
852b58b977eSPatrick Mooney 	int error;
853b58b977eSPatrick Mooney 	struct vm_exception exc;
854b58b977eSPatrick Mooney 
855b58b977eSPatrick Mooney 	exc.cpuid = vcpu;
856b58b977eSPatrick Mooney 	exc.vector = vector;
857b58b977eSPatrick Mooney 	exc.error_code = errcode;
858b58b977eSPatrick Mooney 	exc.error_code_valid = errcode_valid;
859b58b977eSPatrick Mooney 	exc.restart_instruction = 1;
860b58b977eSPatrick Mooney 	error = ioctl(ctx->fd, VM_INJECT_EXCEPTION, &exc);
861b58b977eSPatrick Mooney 
862b58b977eSPatrick Mooney 	assert(error == 0);
863b58b977eSPatrick Mooney }
864b58b977eSPatrick Mooney #endif /* __FreeBSD__ */
865b58b977eSPatrick Mooney 
866bf21cd93STycho Nightingale int
867bf21cd93STycho Nightingale vm_apicid2vcpu(struct vmctx *ctx, int apicid)
868bf21cd93STycho Nightingale {
869bf21cd93STycho Nightingale 	/*
870bf21cd93STycho Nightingale 	 * The apic id associated with the 'vcpu' has the same numerical value
871bf21cd93STycho Nightingale 	 * as the 'vcpu' itself.
872bf21cd93STycho Nightingale 	 */
873bf21cd93STycho Nightingale 	return (apicid);
874bf21cd93STycho Nightingale }
875bf21cd93STycho Nightingale 
876bf21cd93STycho Nightingale int
877bf21cd93STycho Nightingale vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
878bf21cd93STycho Nightingale {
879bf21cd93STycho Nightingale 	struct vm_lapic_irq vmirq;
880bf21cd93STycho Nightingale 
881bf21cd93STycho Nightingale 	bzero(&vmirq, sizeof(vmirq));
882bf21cd93STycho Nightingale 	vmirq.cpuid = vcpu;
883bf21cd93STycho Nightingale 	vmirq.vector = vector;
884bf21cd93STycho Nightingale 
885bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
886bf21cd93STycho Nightingale }
887bf21cd93STycho Nightingale 
888bf21cd93STycho Nightingale int
889bf21cd93STycho Nightingale vm_lapic_local_irq(struct vmctx *ctx, int vcpu, int vector)
890bf21cd93STycho Nightingale {
891bf21cd93STycho Nightingale 	struct vm_lapic_irq vmirq;
892bf21cd93STycho Nightingale 
893bf21cd93STycho Nightingale 	bzero(&vmirq, sizeof(vmirq));
894bf21cd93STycho Nightingale 	vmirq.cpuid = vcpu;
895bf21cd93STycho Nightingale 	vmirq.vector = vector;
896bf21cd93STycho Nightingale 
897bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_LOCAL_IRQ, &vmirq));
898bf21cd93STycho Nightingale }
899bf21cd93STycho Nightingale 
900bf21cd93STycho Nightingale int
901bf21cd93STycho Nightingale vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg)
902bf21cd93STycho Nightingale {
903bf21cd93STycho Nightingale 	struct vm_lapic_msi vmmsi;
904bf21cd93STycho Nightingale 
905bf21cd93STycho Nightingale 	bzero(&vmmsi, sizeof(vmmsi));
906bf21cd93STycho Nightingale 	vmmsi.addr = addr;
907bf21cd93STycho Nightingale 	vmmsi.msg = msg;
908bf21cd93STycho Nightingale 
909bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi));
910bf21cd93STycho Nightingale }
911bf21cd93STycho Nightingale 
912bf21cd93STycho Nightingale int
913bf21cd93STycho Nightingale vm_ioapic_assert_irq(struct vmctx *ctx, int irq)
914bf21cd93STycho Nightingale {
915bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
916bf21cd93STycho Nightingale 
917bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
918bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
919bf21cd93STycho Nightingale 
920bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
921bf21cd93STycho Nightingale }
922bf21cd93STycho Nightingale 
923bf21cd93STycho Nightingale int
924bf21cd93STycho Nightingale vm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
925bf21cd93STycho Nightingale {
926bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
927bf21cd93STycho Nightingale 
928bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
929bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
930bf21cd93STycho Nightingale 
931bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
932bf21cd93STycho Nightingale }
933bf21cd93STycho Nightingale 
934bf21cd93STycho Nightingale int
935bf21cd93STycho Nightingale vm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
936bf21cd93STycho Nightingale {
937bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
938bf21cd93STycho Nightingale 
939bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
940bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
941bf21cd93STycho Nightingale 
942bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
943bf21cd93STycho Nightingale }
944bf21cd93STycho Nightingale 
945bf21cd93STycho Nightingale int
946bf21cd93STycho Nightingale vm_ioapic_pincount(struct vmctx *ctx, int *pincount)
947bf21cd93STycho Nightingale {
948bf21cd93STycho Nightingale 
949bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
950bf21cd93STycho Nightingale }
951bf21cd93STycho Nightingale 
952154972afSPatrick Mooney int
953154972afSPatrick Mooney vm_readwrite_kernemu_device(struct vmctx *ctx, int vcpu, vm_paddr_t gpa,
954154972afSPatrick Mooney     bool write, int size, uint64_t *value)
955154972afSPatrick Mooney {
956154972afSPatrick Mooney 	struct vm_readwrite_kernemu_device irp = {
957154972afSPatrick Mooney 		.vcpuid = vcpu,
958154972afSPatrick Mooney 		.access_width = fls(size) - 1,
959154972afSPatrick Mooney 		.gpa = gpa,
960154972afSPatrick Mooney 		.value = write ? *value : ~0ul,
961154972afSPatrick Mooney 	};
962154972afSPatrick Mooney 	long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV);
963154972afSPatrick Mooney 	int rc;
964154972afSPatrick Mooney 
965154972afSPatrick Mooney 	rc = ioctl(ctx->fd, cmd, &irp);
966154972afSPatrick Mooney 	if (rc == 0 && !write)
967154972afSPatrick Mooney 		*value = irp.value;
968154972afSPatrick Mooney 	return (rc);
969154972afSPatrick Mooney }
970154972afSPatrick Mooney 
971bf21cd93STycho Nightingale int
972bf21cd93STycho Nightingale vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
973bf21cd93STycho Nightingale {
974bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
975bf21cd93STycho Nightingale 
976bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
977bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
978bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
979bf21cd93STycho Nightingale 
980bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq));
981bf21cd93STycho Nightingale }
982bf21cd93STycho Nightingale 
983bf21cd93STycho Nightingale int
984bf21cd93STycho Nightingale vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
985bf21cd93STycho Nightingale {
986bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
987bf21cd93STycho Nightingale 
988bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
989bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
990bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
991bf21cd93STycho Nightingale 
992bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq));
993bf21cd93STycho Nightingale }
994bf21cd93STycho Nightingale 
995bf21cd93STycho Nightingale int
996bf21cd93STycho Nightingale vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
997bf21cd93STycho Nightingale {
998bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
999bf21cd93STycho Nightingale 
1000bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
1001bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
1002bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
1003bf21cd93STycho Nightingale 
1004bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq));
1005bf21cd93STycho Nightingale }
1006bf21cd93STycho Nightingale 
1007bf21cd93STycho Nightingale int
1008bf21cd93STycho Nightingale vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq,
1009bf21cd93STycho Nightingale     enum vm_intr_trigger trigger)
1010bf21cd93STycho Nightingale {
1011bf21cd93STycho Nightingale 	struct vm_isa_irq_trigger isa_irq_trigger;
1012bf21cd93STycho Nightingale 
1013bf21cd93STycho Nightingale 	bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger));
1014bf21cd93STycho Nightingale 	isa_irq_trigger.atpic_irq = atpic_irq;
1015bf21cd93STycho Nightingale 	isa_irq_trigger.trigger = trigger;
1016bf21cd93STycho Nightingale 
1017bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger));
1018bf21cd93STycho Nightingale }
1019bf21cd93STycho Nightingale 
1020bf21cd93STycho Nightingale int
1021bf21cd93STycho Nightingale vm_inject_nmi(struct vmctx *ctx, int vcpu)
1022bf21cd93STycho Nightingale {
1023bf21cd93STycho Nightingale 	struct vm_nmi vmnmi;
1024bf21cd93STycho Nightingale 
1025bf21cd93STycho Nightingale 	bzero(&vmnmi, sizeof(vmnmi));
1026bf21cd93STycho Nightingale 	vmnmi.cpuid = vcpu;
1027bf21cd93STycho Nightingale 
1028bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
1029bf21cd93STycho Nightingale }
1030bf21cd93STycho Nightingale 
1031154972afSPatrick Mooney static const char *capstrmap[] = {
1032154972afSPatrick Mooney 	[VM_CAP_HALT_EXIT]  = "hlt_exit",
1033154972afSPatrick Mooney 	[VM_CAP_MTRAP_EXIT] = "mtrap_exit",
1034154972afSPatrick Mooney 	[VM_CAP_PAUSE_EXIT] = "pause_exit",
1035c3ae3afaSPatrick Mooney #ifdef __FreeBSD__
1036154972afSPatrick Mooney 	[VM_CAP_UNRESTRICTED_GUEST] = "unrestricted_guest",
1037c3ae3afaSPatrick Mooney #endif
1038154972afSPatrick Mooney 	[VM_CAP_ENABLE_INVPCID] = "enable_invpcid",
1039154972afSPatrick Mooney 	[VM_CAP_BPT_EXIT] = "bpt_exit",
1040bf21cd93STycho Nightingale };
1041bf21cd93STycho Nightingale 
1042bf21cd93STycho Nightingale int
1043bf21cd93STycho Nightingale vm_capability_name2type(const char *capname)
1044bf21cd93STycho Nightingale {
1045bf21cd93STycho Nightingale 	int i;
1046bf21cd93STycho Nightingale 
1047154972afSPatrick Mooney 	for (i = 0; i < nitems(capstrmap); i++) {
1048154972afSPatrick Mooney 		if (strcmp(capstrmap[i], capname) == 0)
1049154972afSPatrick Mooney 			return (i);
1050bf21cd93STycho Nightingale 	}
1051bf21cd93STycho Nightingale 
1052bf21cd93STycho Nightingale 	return (-1);
1053bf21cd93STycho Nightingale }
1054bf21cd93STycho Nightingale 
1055bf21cd93STycho Nightingale const char *
1056bf21cd93STycho Nightingale vm_capability_type2name(int type)
1057bf21cd93STycho Nightingale {
1058154972afSPatrick Mooney 	if (type >= 0 && type < nitems(capstrmap))
1059154972afSPatrick Mooney 		return (capstrmap[type]);
1060bf21cd93STycho Nightingale 
1061bf21cd93STycho Nightingale 	return (NULL);
1062bf21cd93STycho Nightingale }
1063bf21cd93STycho Nightingale 
1064bf21cd93STycho Nightingale int
1065bf21cd93STycho Nightingale vm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
1066bf21cd93STycho Nightingale 		  int *retval)
1067bf21cd93STycho Nightingale {
1068bf21cd93STycho Nightingale 	int error;
1069bf21cd93STycho Nightingale 	struct vm_capability vmcap;
1070bf21cd93STycho Nightingale 
1071bf21cd93STycho Nightingale 	bzero(&vmcap, sizeof(vmcap));
1072bf21cd93STycho Nightingale 	vmcap.cpuid = vcpu;
1073bf21cd93STycho Nightingale 	vmcap.captype = cap;
1074bf21cd93STycho Nightingale 
1075bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
1076bf21cd93STycho Nightingale 	*retval = vmcap.capval;
1077bf21cd93STycho Nightingale 	return (error);
1078bf21cd93STycho Nightingale }
1079bf21cd93STycho Nightingale 
1080bf21cd93STycho Nightingale int
1081bf21cd93STycho Nightingale vm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
1082bf21cd93STycho Nightingale {
1083bf21cd93STycho Nightingale 	struct vm_capability vmcap;
1084bf21cd93STycho Nightingale 
1085bf21cd93STycho Nightingale 	bzero(&vmcap, sizeof(vmcap));
1086bf21cd93STycho Nightingale 	vmcap.cpuid = vcpu;
1087bf21cd93STycho Nightingale 	vmcap.captype = cap;
1088bf21cd93STycho Nightingale 	vmcap.capval = val;
10894c87aefeSPatrick Mooney 
1090bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
1091bf21cd93STycho Nightingale }
1092bf21cd93STycho Nightingale 
1093eb9a1df2SHans Rosenfeld #ifdef __FreeBSD__
1094bf21cd93STycho Nightingale int
1095bf21cd93STycho Nightingale vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1096bf21cd93STycho Nightingale {
1097bf21cd93STycho Nightingale 	struct vm_pptdev pptdev;
1098bf21cd93STycho Nightingale 
1099bf21cd93STycho Nightingale 	bzero(&pptdev, sizeof(pptdev));
1100bf21cd93STycho Nightingale 	pptdev.bus = bus;
1101bf21cd93STycho Nightingale 	pptdev.slot = slot;
1102bf21cd93STycho Nightingale 	pptdev.func = func;
1103bf21cd93STycho Nightingale 
1104bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
1105bf21cd93STycho Nightingale }
1106bf21cd93STycho Nightingale 
1107bf21cd93STycho Nightingale int
1108bf21cd93STycho Nightingale vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1109bf21cd93STycho Nightingale {
1110bf21cd93STycho Nightingale 	struct vm_pptdev pptdev;
1111bf21cd93STycho Nightingale 
1112bf21cd93STycho Nightingale 	bzero(&pptdev, sizeof(pptdev));
1113bf21cd93STycho Nightingale 	pptdev.bus = bus;
1114bf21cd93STycho Nightingale 	pptdev.slot = slot;
1115bf21cd93STycho Nightingale 	pptdev.func = func;
1116bf21cd93STycho Nightingale 
1117bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
1118bf21cd93STycho Nightingale }
1119bf21cd93STycho Nightingale 
1120bf21cd93STycho Nightingale int
1121bf21cd93STycho Nightingale vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
1122bf21cd93STycho Nightingale 		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
1123bf21cd93STycho Nightingale {
1124bf21cd93STycho Nightingale 	struct vm_pptdev_mmio pptmmio;
1125bf21cd93STycho Nightingale 
1126bf21cd93STycho Nightingale 	bzero(&pptmmio, sizeof(pptmmio));
1127bf21cd93STycho Nightingale 	pptmmio.bus = bus;
1128bf21cd93STycho Nightingale 	pptmmio.slot = slot;
1129bf21cd93STycho Nightingale 	pptmmio.func = func;
1130bf21cd93STycho Nightingale 	pptmmio.gpa = gpa;
1131bf21cd93STycho Nightingale 	pptmmio.len = len;
1132bf21cd93STycho Nightingale 	pptmmio.hpa = hpa;
1133bf21cd93STycho Nightingale 
1134bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
1135bf21cd93STycho Nightingale }
1136bf21cd93STycho Nightingale 
11372b948146SAndy Fiddaman int
11382b948146SAndy Fiddaman vm_unmap_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
11392b948146SAndy Fiddaman 		     vm_paddr_t gpa, size_t len)
11402b948146SAndy Fiddaman {
11412b948146SAndy Fiddaman 	struct vm_pptdev_mmio pptmmio;
11422b948146SAndy Fiddaman 
11432b948146SAndy Fiddaman 	bzero(&pptmmio, sizeof(pptmmio));
11442b948146SAndy Fiddaman 	pptmmio.bus = bus;
11452b948146SAndy Fiddaman 	pptmmio.slot = slot;
11462b948146SAndy Fiddaman 	pptmmio.func = func;
11472b948146SAndy Fiddaman 	pptmmio.gpa = gpa;
11482b948146SAndy Fiddaman 	pptmmio.len = len;
11492b948146SAndy Fiddaman 
11502b948146SAndy Fiddaman 	return (ioctl(ctx->fd, VM_UNMAP_PPTDEV_MMIO, &pptmmio));
11512b948146SAndy Fiddaman }
11522b948146SAndy Fiddaman 
1153bf21cd93STycho Nightingale int
1154bf21cd93STycho Nightingale vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
1155bf21cd93STycho Nightingale     uint64_t addr, uint64_t msg, int numvec)
1156bf21cd93STycho Nightingale {
1157bf21cd93STycho Nightingale 	struct vm_pptdev_msi pptmsi;
1158bf21cd93STycho Nightingale 
1159bf21cd93STycho Nightingale 	bzero(&pptmsi, sizeof(pptmsi));
1160bf21cd93STycho Nightingale 	pptmsi.vcpu = vcpu;
1161bf21cd93STycho Nightingale 	pptmsi.bus = bus;
1162bf21cd93STycho Nightingale 	pptmsi.slot = slot;
1163bf21cd93STycho Nightingale 	pptmsi.func = func;
1164bf21cd93STycho Nightingale 	pptmsi.msg = msg;
1165bf21cd93STycho Nightingale 	pptmsi.addr = addr;
1166bf21cd93STycho Nightingale 	pptmsi.numvec = numvec;
1167bf21cd93STycho Nightingale 
1168bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
1169bf21cd93STycho Nightingale }
1170bf21cd93STycho Nightingale 
1171eb9a1df2SHans Rosenfeld int
1172bf21cd93STycho Nightingale vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
1173bf21cd93STycho Nightingale     int idx, uint64_t addr, uint64_t msg, uint32_t vector_control)
1174bf21cd93STycho Nightingale {
1175bf21cd93STycho Nightingale 	struct vm_pptdev_msix pptmsix;
1176bf21cd93STycho Nightingale 
1177bf21cd93STycho Nightingale 	bzero(&pptmsix, sizeof(pptmsix));
1178bf21cd93STycho Nightingale 	pptmsix.vcpu = vcpu;
1179bf21cd93STycho Nightingale 	pptmsix.bus = bus;
1180bf21cd93STycho Nightingale 	pptmsix.slot = slot;
1181bf21cd93STycho Nightingale 	pptmsix.func = func;
1182bf21cd93STycho Nightingale 	pptmsix.idx = idx;
1183bf21cd93STycho Nightingale 	pptmsix.msg = msg;
1184bf21cd93STycho Nightingale 	pptmsix.addr = addr;
1185bf21cd93STycho Nightingale 	pptmsix.vector_control = vector_control;
1186bf21cd93STycho Nightingale 
1187bf21cd93STycho Nightingale 	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
1188bf21cd93STycho Nightingale }
1189bf21cd93STycho Nightingale 
1190eb9a1df2SHans Rosenfeld int
1191eb9a1df2SHans Rosenfeld vm_get_pptdev_limits(struct vmctx *ctx, int bus, int slot, int func,
1192eb9a1df2SHans Rosenfeld     int *msi_limit, int *msix_limit)
1193eb9a1df2SHans Rosenfeld {
1194eb9a1df2SHans Rosenfeld 	struct vm_pptdev_limits pptlimits;
1195eb9a1df2SHans Rosenfeld 	int error;
1196eb9a1df2SHans Rosenfeld 
1197eb9a1df2SHans Rosenfeld 	bzero(&pptlimits, sizeof (pptlimits));
1198eb9a1df2SHans Rosenfeld 	pptlimits.bus = bus;
1199eb9a1df2SHans Rosenfeld 	pptlimits.slot = slot;
1200eb9a1df2SHans Rosenfeld 	pptlimits.func = func;
1201eb9a1df2SHans Rosenfeld 
1202eb9a1df2SHans Rosenfeld 	error = ioctl(ctx->fd, VM_GET_PPTDEV_LIMITS, &pptlimits);
1203eb9a1df2SHans Rosenfeld 
1204eb9a1df2SHans Rosenfeld 	*msi_limit = pptlimits.msi_limit;
1205eb9a1df2SHans Rosenfeld 	*msix_limit = pptlimits.msix_limit;
1206eb9a1df2SHans Rosenfeld 
1207eb9a1df2SHans Rosenfeld 	return (error);
1208eb9a1df2SHans Rosenfeld }
12096960cd89SAndy Fiddaman 
12106960cd89SAndy Fiddaman int
12116960cd89SAndy Fiddaman vm_disable_pptdev_msix(struct vmctx *ctx, int bus, int slot, int func)
12126960cd89SAndy Fiddaman {
12136960cd89SAndy Fiddaman 	struct vm_pptdev ppt;
12146960cd89SAndy Fiddaman 
12156960cd89SAndy Fiddaman 	bzero(&ppt, sizeof(ppt));
12166960cd89SAndy Fiddaman 	ppt.bus = bus;
12176960cd89SAndy Fiddaman 	ppt.slot = slot;
12186960cd89SAndy Fiddaman 	ppt.func = func;
12196960cd89SAndy Fiddaman 
12206960cd89SAndy Fiddaman 	return ioctl(ctx->fd, VM_PPTDEV_DISABLE_MSIX, &ppt);
12216960cd89SAndy Fiddaman }
12226960cd89SAndy Fiddaman 
1223eb9a1df2SHans Rosenfeld #else /* __FreeBSD__ */
12246960cd89SAndy Fiddaman 
1225eb9a1df2SHans Rosenfeld int
1226eb9a1df2SHans Rosenfeld vm_assign_pptdev(struct vmctx *ctx, int pptfd)
1227eb9a1df2SHans Rosenfeld {
1228eb9a1df2SHans Rosenfeld 	struct vm_pptdev pptdev;
1229eb9a1df2SHans Rosenfeld 
1230eb9a1df2SHans Rosenfeld 	pptdev.pptfd = pptfd;
1231eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
1232eb9a1df2SHans Rosenfeld }
1233eb9a1df2SHans Rosenfeld 
1234eb9a1df2SHans Rosenfeld int
1235eb9a1df2SHans Rosenfeld vm_unassign_pptdev(struct vmctx *ctx, int pptfd)
1236eb9a1df2SHans Rosenfeld {
1237eb9a1df2SHans Rosenfeld 	struct vm_pptdev pptdev;
1238eb9a1df2SHans Rosenfeld 
1239eb9a1df2SHans Rosenfeld 	pptdev.pptfd = pptfd;
1240eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
1241eb9a1df2SHans Rosenfeld }
1242eb9a1df2SHans Rosenfeld 
1243eb9a1df2SHans Rosenfeld int
1244eb9a1df2SHans Rosenfeld vm_map_pptdev_mmio(struct vmctx *ctx, int pptfd, vm_paddr_t gpa, size_t len,
1245eb9a1df2SHans Rosenfeld     vm_paddr_t hpa)
1246eb9a1df2SHans Rosenfeld {
1247eb9a1df2SHans Rosenfeld 	struct vm_pptdev_mmio pptmmio;
1248eb9a1df2SHans Rosenfeld 
1249eb9a1df2SHans Rosenfeld 	pptmmio.pptfd = pptfd;
1250eb9a1df2SHans Rosenfeld 	pptmmio.gpa = gpa;
1251eb9a1df2SHans Rosenfeld 	pptmmio.len = len;
1252eb9a1df2SHans Rosenfeld 	pptmmio.hpa = hpa;
1253eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
1254eb9a1df2SHans Rosenfeld }
1255eb9a1df2SHans Rosenfeld 
12562b948146SAndy Fiddaman int
12572b948146SAndy Fiddaman vm_unmap_pptdev_mmio(struct vmctx *ctx, int pptfd, vm_paddr_t gpa, size_t len)
12582b948146SAndy Fiddaman {
12592b948146SAndy Fiddaman 	struct vm_pptdev_mmio pptmmio;
12602b948146SAndy Fiddaman 
12612b948146SAndy Fiddaman 	bzero(&pptmmio, sizeof(pptmmio));
12622b948146SAndy Fiddaman 	pptmmio.pptfd = pptfd;
12632b948146SAndy Fiddaman 	pptmmio.gpa = gpa;
12642b948146SAndy Fiddaman 	pptmmio.len = len;
12652b948146SAndy Fiddaman 
12662b948146SAndy Fiddaman 	return (ioctl(ctx->fd, VM_UNMAP_PPTDEV_MMIO, &pptmmio));
12672b948146SAndy Fiddaman }
12682b948146SAndy Fiddaman 
1269eb9a1df2SHans Rosenfeld int
1270eb9a1df2SHans Rosenfeld vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int pptfd, uint64_t addr,
1271eb9a1df2SHans Rosenfeld     uint64_t msg, int numvec)
1272eb9a1df2SHans Rosenfeld {
1273eb9a1df2SHans Rosenfeld 	struct vm_pptdev_msi pptmsi;
1274eb9a1df2SHans Rosenfeld 
1275eb9a1df2SHans Rosenfeld 	pptmsi.vcpu = vcpu;
1276eb9a1df2SHans Rosenfeld 	pptmsi.pptfd = pptfd;
1277eb9a1df2SHans Rosenfeld 	pptmsi.msg = msg;
1278eb9a1df2SHans Rosenfeld 	pptmsi.addr = addr;
1279eb9a1df2SHans Rosenfeld 	pptmsi.numvec = numvec;
1280eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
1281eb9a1df2SHans Rosenfeld }
1282eb9a1df2SHans Rosenfeld 
1283eb9a1df2SHans Rosenfeld int
1284eb9a1df2SHans Rosenfeld vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int pptfd, int idx,
1285eb9a1df2SHans Rosenfeld     uint64_t addr, uint64_t msg, uint32_t vector_control)
1286eb9a1df2SHans Rosenfeld {
1287eb9a1df2SHans Rosenfeld 	struct vm_pptdev_msix pptmsix;
1288eb9a1df2SHans Rosenfeld 
1289eb9a1df2SHans Rosenfeld 	pptmsix.vcpu = vcpu;
1290eb9a1df2SHans Rosenfeld 	pptmsix.pptfd = pptfd;
1291eb9a1df2SHans Rosenfeld 	pptmsix.idx = idx;
1292eb9a1df2SHans Rosenfeld 	pptmsix.msg = msg;
1293eb9a1df2SHans Rosenfeld 	pptmsix.addr = addr;
1294eb9a1df2SHans Rosenfeld 	pptmsix.vector_control = vector_control;
1295eb9a1df2SHans Rosenfeld 	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
1296eb9a1df2SHans Rosenfeld }
1297eb9a1df2SHans Rosenfeld 
1298eb9a1df2SHans Rosenfeld int
1299eb9a1df2SHans Rosenfeld vm_get_pptdev_limits(struct vmctx *ctx, int pptfd, int *msi_limit,
1300eb9a1df2SHans Rosenfeld     int *msix_limit)
1301eb9a1df2SHans Rosenfeld {
1302eb9a1df2SHans Rosenfeld 	struct vm_pptdev_limits pptlimits;
1303eb9a1df2SHans Rosenfeld 	int error;
1304eb9a1df2SHans Rosenfeld 
1305eb9a1df2SHans Rosenfeld 	bzero(&pptlimits, sizeof (pptlimits));
1306eb9a1df2SHans Rosenfeld 	pptlimits.pptfd = pptfd;
1307eb9a1df2SHans Rosenfeld 	error = ioctl(ctx->fd, VM_GET_PPTDEV_LIMITS, &pptlimits);
1308eb9a1df2SHans Rosenfeld 
1309eb9a1df2SHans Rosenfeld 	*msi_limit = pptlimits.msi_limit;
1310eb9a1df2SHans Rosenfeld 	*msix_limit = pptlimits.msix_limit;
1311eb9a1df2SHans Rosenfeld 	return (error);
1312eb9a1df2SHans Rosenfeld }
13136960cd89SAndy Fiddaman 
13146960cd89SAndy Fiddaman int
13156960cd89SAndy Fiddaman vm_disable_pptdev_msix(struct vmctx *ctx, int pptfd)
13166960cd89SAndy Fiddaman {
13176960cd89SAndy Fiddaman 	struct vm_pptdev pptdev;
13186960cd89SAndy Fiddaman 
13196960cd89SAndy Fiddaman 	pptdev.pptfd = pptfd;
13206960cd89SAndy Fiddaman 	return (ioctl(ctx->fd, VM_PPTDEV_DISABLE_MSIX, &pptdev));
13216960cd89SAndy Fiddaman }
1322eb9a1df2SHans Rosenfeld #endif /* __FreeBSD__ */
1323eb9a1df2SHans Rosenfeld 
1324bf21cd93STycho Nightingale uint64_t *
1325bf21cd93STycho Nightingale vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
1326bf21cd93STycho Nightingale 	     int *ret_entries)
1327bf21cd93STycho Nightingale {
1328bf21cd93STycho Nightingale 	int error;
1329bf21cd93STycho Nightingale 
1330bf21cd93STycho Nightingale 	static struct vm_stats vmstats;
1331bf21cd93STycho Nightingale 
1332bf21cd93STycho Nightingale 	vmstats.cpuid = vcpu;
1333bf21cd93STycho Nightingale 
13344c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_STATS_IOC, &vmstats);
1335bf21cd93STycho Nightingale 	if (error == 0) {
1336bf21cd93STycho Nightingale 		if (ret_entries)
1337bf21cd93STycho Nightingale 			*ret_entries = vmstats.num_entries;
1338bf21cd93STycho Nightingale 		if (ret_tv)
1339bf21cd93STycho Nightingale 			*ret_tv = vmstats.tv;
1340bf21cd93STycho Nightingale 		return (vmstats.statbuf);
1341bf21cd93STycho Nightingale 	} else
1342bf21cd93STycho Nightingale 		return (NULL);
1343bf21cd93STycho Nightingale }
1344bf21cd93STycho Nightingale 
1345bf21cd93STycho Nightingale const char *
1346bf21cd93STycho Nightingale vm_get_stat_desc(struct vmctx *ctx, int index)
1347bf21cd93STycho Nightingale {
1348bf21cd93STycho Nightingale 	static struct vm_stat_desc statdesc;
1349bf21cd93STycho Nightingale 
1350bf21cd93STycho Nightingale 	statdesc.index = index;
1351bf21cd93STycho Nightingale 	if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
1352bf21cd93STycho Nightingale 		return (statdesc.desc);
1353bf21cd93STycho Nightingale 	else
1354bf21cd93STycho Nightingale 		return (NULL);
1355bf21cd93STycho Nightingale }
1356bf21cd93STycho Nightingale 
1357bf21cd93STycho Nightingale int
1358bf21cd93STycho Nightingale vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *state)
1359bf21cd93STycho Nightingale {
1360bf21cd93STycho Nightingale 	int error;
1361bf21cd93STycho Nightingale 	struct vm_x2apic x2apic;
1362bf21cd93STycho Nightingale 
1363bf21cd93STycho Nightingale 	bzero(&x2apic, sizeof(x2apic));
1364bf21cd93STycho Nightingale 	x2apic.cpuid = vcpu;
1365bf21cd93STycho Nightingale 
1366bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_X2APIC_STATE, &x2apic);
1367bf21cd93STycho Nightingale 	*state = x2apic.state;
1368bf21cd93STycho Nightingale 	return (error);
1369bf21cd93STycho Nightingale }
1370bf21cd93STycho Nightingale 
1371bf21cd93STycho Nightingale int
1372bf21cd93STycho Nightingale vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state state)
1373bf21cd93STycho Nightingale {
1374bf21cd93STycho Nightingale 	int error;
1375bf21cd93STycho Nightingale 	struct vm_x2apic x2apic;
1376bf21cd93STycho Nightingale 
1377bf21cd93STycho Nightingale 	bzero(&x2apic, sizeof(x2apic));
1378bf21cd93STycho Nightingale 	x2apic.cpuid = vcpu;
1379bf21cd93STycho Nightingale 	x2apic.state = state;
1380bf21cd93STycho Nightingale 
1381bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_X2APIC_STATE, &x2apic);
1382bf21cd93STycho Nightingale 
1383bf21cd93STycho Nightingale 	return (error);
1384bf21cd93STycho Nightingale }
1385bf21cd93STycho Nightingale 
13862606939dSPatrick Mooney #ifndef __FreeBSD__
13872606939dSPatrick Mooney int
13882606939dSPatrick Mooney vcpu_reset(struct vmctx *vmctx, int vcpu)
13892606939dSPatrick Mooney {
13902606939dSPatrick Mooney 	struct vm_vcpu_reset vvr;
13912606939dSPatrick Mooney 
13922606939dSPatrick Mooney 	vvr.vcpuid = vcpu;
13932606939dSPatrick Mooney 	vvr.kind = VRK_RESET;
13942606939dSPatrick Mooney 
13952606939dSPatrick Mooney 	return (ioctl(vmctx->fd, VM_RESET_CPU, &vvr));
13962606939dSPatrick Mooney }
13972606939dSPatrick Mooney #else /* __FreeBSD__ */
1398bf21cd93STycho Nightingale /*
1399bf21cd93STycho Nightingale  * From Intel Vol 3a:
1400bf21cd93STycho Nightingale  * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
1401bf21cd93STycho Nightingale  */
1402bf21cd93STycho Nightingale int
1403bf21cd93STycho Nightingale vcpu_reset(struct vmctx *vmctx, int vcpu)
1404bf21cd93STycho Nightingale {
1405bf21cd93STycho Nightingale 	int error;
1406bf21cd93STycho Nightingale 	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
1407bf21cd93STycho Nightingale 	uint32_t desc_access, desc_limit;
1408bf21cd93STycho Nightingale 	uint16_t sel;
1409bf21cd93STycho Nightingale 
1410bf21cd93STycho Nightingale 	zero = 0;
1411bf21cd93STycho Nightingale 
1412bf21cd93STycho Nightingale 	rflags = 0x2;
1413bf21cd93STycho Nightingale 	error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
1414bf21cd93STycho Nightingale 	if (error)
1415bf21cd93STycho Nightingale 		goto done;
1416bf21cd93STycho Nightingale 
1417bf21cd93STycho Nightingale 	rip = 0xfff0;
1418bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
1419bf21cd93STycho Nightingale 		goto done;
1420bf21cd93STycho Nightingale 
1421bf21cd93STycho Nightingale 	cr0 = CR0_NE;
1422bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
1423bf21cd93STycho Nightingale 		goto done;
1424bf21cd93STycho Nightingale 
1425bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0)
1426bf21cd93STycho Nightingale 		goto done;
1427bf21cd93STycho Nightingale 
1428bf21cd93STycho Nightingale 	cr4 = 0;
1429bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
1430bf21cd93STycho Nightingale 		goto done;
1431bf21cd93STycho Nightingale 
1432bf21cd93STycho Nightingale 	/*
1433bf21cd93STycho Nightingale 	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
1434bf21cd93STycho Nightingale 	 */
1435bf21cd93STycho Nightingale 	desc_base = 0xffff0000;
1436bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1437bf21cd93STycho Nightingale 	desc_access = 0x0093;
1438bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
1439bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1440bf21cd93STycho Nightingale 	if (error)
1441bf21cd93STycho Nightingale 		goto done;
1442bf21cd93STycho Nightingale 
1443bf21cd93STycho Nightingale 	sel = 0xf000;
1444bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, sel)) != 0)
1445bf21cd93STycho Nightingale 		goto done;
1446bf21cd93STycho Nightingale 
1447bf21cd93STycho Nightingale 	/*
1448bf21cd93STycho Nightingale 	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
1449bf21cd93STycho Nightingale 	 */
1450bf21cd93STycho Nightingale 	desc_base = 0;
1451bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1452bf21cd93STycho Nightingale 	desc_access = 0x0093;
1453bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
1454bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1455bf21cd93STycho Nightingale 	if (error)
1456bf21cd93STycho Nightingale 		goto done;
1457bf21cd93STycho Nightingale 
1458bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
1459bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1460bf21cd93STycho Nightingale 	if (error)
1461bf21cd93STycho Nightingale 		goto done;
1462bf21cd93STycho Nightingale 
1463bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
1464bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1465bf21cd93STycho Nightingale 	if (error)
1466bf21cd93STycho Nightingale 		goto done;
1467bf21cd93STycho Nightingale 
1468bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
1469bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1470bf21cd93STycho Nightingale 	if (error)
1471bf21cd93STycho Nightingale 		goto done;
1472bf21cd93STycho Nightingale 
1473bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
1474bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1475bf21cd93STycho Nightingale 	if (error)
1476bf21cd93STycho Nightingale 		goto done;
1477bf21cd93STycho Nightingale 
1478bf21cd93STycho Nightingale 	sel = 0;
1479bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, sel)) != 0)
1480bf21cd93STycho Nightingale 		goto done;
1481bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, sel)) != 0)
1482bf21cd93STycho Nightingale 		goto done;
1483bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, sel)) != 0)
1484bf21cd93STycho Nightingale 		goto done;
1485bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, sel)) != 0)
1486bf21cd93STycho Nightingale 		goto done;
1487bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0)
1488bf21cd93STycho Nightingale 		goto done;
1489bf21cd93STycho Nightingale 
1490bf21cd93STycho Nightingale 	/* General purpose registers */
1491bf21cd93STycho Nightingale 	rdx = 0xf00;
1492bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0)
1493bf21cd93STycho Nightingale 		goto done;
1494bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBX, zero)) != 0)
1495bf21cd93STycho Nightingale 		goto done;
1496bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RCX, zero)) != 0)
1497bf21cd93STycho Nightingale 		goto done;
1498bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
1499bf21cd93STycho Nightingale 		goto done;
1500bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSI, zero)) != 0)
1501bf21cd93STycho Nightingale 		goto done;
1502bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDI, zero)) != 0)
1503bf21cd93STycho Nightingale 		goto done;
1504bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBP, zero)) != 0)
1505bf21cd93STycho Nightingale 		goto done;
1506bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0)
1507bf21cd93STycho Nightingale 		goto done;
1508bf21cd93STycho Nightingale 
1509bf21cd93STycho Nightingale 	/* GDTR, IDTR */
1510bf21cd93STycho Nightingale 	desc_base = 0;
1511bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1512bf21cd93STycho Nightingale 	desc_access = 0;
1513bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
1514bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1515bf21cd93STycho Nightingale 	if (error != 0)
1516bf21cd93STycho Nightingale 		goto done;
1517bf21cd93STycho Nightingale 
1518bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_IDTR,
1519bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1520bf21cd93STycho Nightingale 	if (error != 0)
1521bf21cd93STycho Nightingale 		goto done;
1522bf21cd93STycho Nightingale 
1523bf21cd93STycho Nightingale 	/* TR */
1524bf21cd93STycho Nightingale 	desc_base = 0;
1525bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1526bf21cd93STycho Nightingale 	desc_access = 0x0000008b;
1527bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
1528bf21cd93STycho Nightingale 	if (error)
1529bf21cd93STycho Nightingale 		goto done;
1530bf21cd93STycho Nightingale 
1531bf21cd93STycho Nightingale 	sel = 0;
1532bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, sel)) != 0)
1533bf21cd93STycho Nightingale 		goto done;
1534bf21cd93STycho Nightingale 
1535bf21cd93STycho Nightingale 	/* LDTR */
1536bf21cd93STycho Nightingale 	desc_base = 0;
1537bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1538bf21cd93STycho Nightingale 	desc_access = 0x00000082;
1539bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, desc_base,
1540bf21cd93STycho Nightingale 			    desc_limit, desc_access);
1541bf21cd93STycho Nightingale 	if (error)
1542bf21cd93STycho Nightingale 		goto done;
1543bf21cd93STycho Nightingale 
1544bf21cd93STycho Nightingale 	sel = 0;
1545bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
1546bf21cd93STycho Nightingale 		goto done;
1547bf21cd93STycho Nightingale 
1548bf21cd93STycho Nightingale 	/* XXX cr2, debug registers */
1549bf21cd93STycho Nightingale 
1550bf21cd93STycho Nightingale 	error = 0;
1551bf21cd93STycho Nightingale done:
1552bf21cd93STycho Nightingale 	return (error);
1553bf21cd93STycho Nightingale }
15542606939dSPatrick Mooney #endif /* __FreeBSD__ */
1555bf21cd93STycho Nightingale 
1556bf21cd93STycho Nightingale int
1557bf21cd93STycho Nightingale vm_get_gpa_pmap(struct vmctx *ctx, uint64_t gpa, uint64_t *pte, int *num)
1558bf21cd93STycho Nightingale {
1559bf21cd93STycho Nightingale 	int error, i;
1560bf21cd93STycho Nightingale 	struct vm_gpa_pte gpapte;
1561bf21cd93STycho Nightingale 
1562bf21cd93STycho Nightingale 	bzero(&gpapte, sizeof(gpapte));
1563bf21cd93STycho Nightingale 	gpapte.gpa = gpa;
1564bf21cd93STycho Nightingale 
1565bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_GPA_PMAP, &gpapte);
1566bf21cd93STycho Nightingale 
1567bf21cd93STycho Nightingale 	if (error == 0) {
1568bf21cd93STycho Nightingale 		*num = gpapte.ptenum;
1569bf21cd93STycho Nightingale 		for (i = 0; i < gpapte.ptenum; i++)
1570bf21cd93STycho Nightingale 			pte[i] = gpapte.pte[i];
1571bf21cd93STycho Nightingale 	}
1572bf21cd93STycho Nightingale 
1573bf21cd93STycho Nightingale 	return (error);
1574bf21cd93STycho Nightingale }
1575bf21cd93STycho Nightingale 
1576bf21cd93STycho Nightingale int
1577bf21cd93STycho Nightingale vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
1578bf21cd93STycho Nightingale {
1579bf21cd93STycho Nightingale 	int error;
1580bf21cd93STycho Nightingale 	struct vm_hpet_cap cap;
1581bf21cd93STycho Nightingale 
1582bf21cd93STycho Nightingale 	bzero(&cap, sizeof(struct vm_hpet_cap));
1583bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap);
1584bf21cd93STycho Nightingale 	if (capabilities != NULL)
1585bf21cd93STycho Nightingale 		*capabilities = cap.capabilities;
1586bf21cd93STycho Nightingale 	return (error);
1587bf21cd93STycho Nightingale }
1588bf21cd93STycho Nightingale 
15894c87aefeSPatrick Mooney int
15904c87aefeSPatrick Mooney vm_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
15914c87aefeSPatrick Mooney     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1592bf21cd93STycho Nightingale {
1593bf21cd93STycho Nightingale 	struct vm_gla2gpa gg;
1594bf21cd93STycho Nightingale 	int error;
1595bf21cd93STycho Nightingale 
1596bf21cd93STycho Nightingale 	bzero(&gg, sizeof(struct vm_gla2gpa));
1597bf21cd93STycho Nightingale 	gg.vcpuid = vcpu;
1598bf21cd93STycho Nightingale 	gg.prot = prot;
1599bf21cd93STycho Nightingale 	gg.gla = gla;
1600bf21cd93STycho Nightingale 	gg.paging = *paging;
1601bf21cd93STycho Nightingale 
1602bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GLA2GPA, &gg);
1603bf21cd93STycho Nightingale 	if (error == 0) {
1604bf21cd93STycho Nightingale 		*fault = gg.fault;
1605bf21cd93STycho Nightingale 		*gpa = gg.gpa;
1606bf21cd93STycho Nightingale 	}
1607bf21cd93STycho Nightingale 	return (error);
1608bf21cd93STycho Nightingale }
1609bf21cd93STycho Nightingale 
1610bf21cd93STycho Nightingale int
16114c87aefeSPatrick Mooney vm_gla2gpa_nofault(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
16124c87aefeSPatrick Mooney     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1613bf21cd93STycho Nightingale {
16144c87aefeSPatrick Mooney 	struct vm_gla2gpa gg;
16154c87aefeSPatrick Mooney 	int error;
16164c87aefeSPatrick Mooney 
16174c87aefeSPatrick Mooney 	bzero(&gg, sizeof(struct vm_gla2gpa));
16184c87aefeSPatrick Mooney 	gg.vcpuid = vcpu;
16194c87aefeSPatrick Mooney 	gg.prot = prot;
16204c87aefeSPatrick Mooney 	gg.gla = gla;
16214c87aefeSPatrick Mooney 	gg.paging = *paging;
1622bf21cd93STycho Nightingale 
16234c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GLA2GPA_NOFAULT, &gg);
16244c87aefeSPatrick Mooney 	if (error == 0) {
16254c87aefeSPatrick Mooney 		*fault = gg.fault;
16264c87aefeSPatrick Mooney 		*gpa = gg.gpa;
16274c87aefeSPatrick Mooney 	}
1628bf21cd93STycho Nightingale 	return (error);
1629bf21cd93STycho Nightingale }
1630bf21cd93STycho Nightingale 
1631bf21cd93STycho Nightingale #ifndef min
1632bf21cd93STycho Nightingale #define	min(a,b)	(((a) < (b)) ? (a) : (b))
1633bf21cd93STycho Nightingale #endif
1634bf21cd93STycho Nightingale 
1635bf21cd93STycho Nightingale int
1636bf21cd93STycho Nightingale vm_copy_setup(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
16374c87aefeSPatrick Mooney     uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt,
16384c87aefeSPatrick Mooney     int *fault)
1639bf21cd93STycho Nightingale {
1640bf21cd93STycho Nightingale 	void *va;
1641bf21cd93STycho Nightingale 	uint64_t gpa;
16424c87aefeSPatrick Mooney 	int error, i, n, off;
1643bf21cd93STycho Nightingale 
1644bf21cd93STycho Nightingale 	for (i = 0; i < iovcnt; i++) {
1645bf21cd93STycho Nightingale 		iov[i].iov_base = 0;
1646bf21cd93STycho Nightingale 		iov[i].iov_len = 0;
1647bf21cd93STycho Nightingale 	}
1648bf21cd93STycho Nightingale 
1649bf21cd93STycho Nightingale 	while (len) {
1650bf21cd93STycho Nightingale 		assert(iovcnt > 0);
16514c87aefeSPatrick Mooney 		error = vm_gla2gpa(ctx, vcpu, paging, gla, prot, &gpa, fault);
16524c87aefeSPatrick Mooney 		if (error || *fault)
16534c87aefeSPatrick Mooney 			return (error);
1654bf21cd93STycho Nightingale 
1655bf21cd93STycho Nightingale 		off = gpa & PAGE_MASK;
1656bf21cd93STycho Nightingale 		n = min(len, PAGE_SIZE - off);
1657bf21cd93STycho Nightingale 
1658bf21cd93STycho Nightingale 		va = vm_map_gpa(ctx, gpa, n);
1659bf21cd93STycho Nightingale 		if (va == NULL)
16604c87aefeSPatrick Mooney 			return (EFAULT);
1661bf21cd93STycho Nightingale 
1662bf21cd93STycho Nightingale 		iov->iov_base = va;
1663bf21cd93STycho Nightingale 		iov->iov_len = n;
1664bf21cd93STycho Nightingale 		iov++;
1665bf21cd93STycho Nightingale 		iovcnt--;
1666bf21cd93STycho Nightingale 
1667bf21cd93STycho Nightingale 		gla += n;
1668bf21cd93STycho Nightingale 		len -= n;
1669bf21cd93STycho Nightingale 	}
1670bf21cd93STycho Nightingale 	return (0);
1671bf21cd93STycho Nightingale }
1672bf21cd93STycho Nightingale 
1673bf21cd93STycho Nightingale void
1674bf21cd93STycho Nightingale vm_copy_teardown(struct vmctx *ctx, int vcpu, struct iovec *iov, int iovcnt)
1675bf21cd93STycho Nightingale {
1676bf21cd93STycho Nightingale 
1677bf21cd93STycho Nightingale 	return;
1678bf21cd93STycho Nightingale }
1679bf21cd93STycho Nightingale 
1680bf21cd93STycho Nightingale void
1681bf21cd93STycho Nightingale vm_copyin(struct vmctx *ctx, int vcpu, struct iovec *iov, void *vp, size_t len)
1682bf21cd93STycho Nightingale {
1683bf21cd93STycho Nightingale 	const char *src;
1684bf21cd93STycho Nightingale 	char *dst;
1685bf21cd93STycho Nightingale 	size_t n;
1686bf21cd93STycho Nightingale 
1687bf21cd93STycho Nightingale 	dst = vp;
1688bf21cd93STycho Nightingale 	while (len) {
1689bf21cd93STycho Nightingale 		assert(iov->iov_len);
1690bf21cd93STycho Nightingale 		n = min(len, iov->iov_len);
1691bf21cd93STycho Nightingale 		src = iov->iov_base;
1692bf21cd93STycho Nightingale 		bcopy(src, dst, n);
1693bf21cd93STycho Nightingale 
1694bf21cd93STycho Nightingale 		iov++;
1695bf21cd93STycho Nightingale 		dst += n;
1696bf21cd93STycho Nightingale 		len -= n;
1697bf21cd93STycho Nightingale 	}
1698bf21cd93STycho Nightingale }
1699bf21cd93STycho Nightingale 
1700bf21cd93STycho Nightingale void
1701bf21cd93STycho Nightingale vm_copyout(struct vmctx *ctx, int vcpu, const void *vp, struct iovec *iov,
1702bf21cd93STycho Nightingale     size_t len)
1703bf21cd93STycho Nightingale {
1704bf21cd93STycho Nightingale 	const char *src;
1705bf21cd93STycho Nightingale 	char *dst;
1706bf21cd93STycho Nightingale 	size_t n;
1707bf21cd93STycho Nightingale 
1708bf21cd93STycho Nightingale 	src = vp;
1709bf21cd93STycho Nightingale 	while (len) {
1710bf21cd93STycho Nightingale 		assert(iov->iov_len);
1711bf21cd93STycho Nightingale 		n = min(len, iov->iov_len);
1712bf21cd93STycho Nightingale 		dst = iov->iov_base;
1713bf21cd93STycho Nightingale 		bcopy(src, dst, n);
1714bf21cd93STycho Nightingale 
1715bf21cd93STycho Nightingale 		iov++;
1716bf21cd93STycho Nightingale 		src += n;
1717bf21cd93STycho Nightingale 		len -= n;
1718bf21cd93STycho Nightingale 	}
1719bf21cd93STycho Nightingale }
1720bf21cd93STycho Nightingale 
17214c87aefeSPatrick Mooney static int
17224c87aefeSPatrick Mooney vm_get_cpus(struct vmctx *ctx, int which, cpuset_t *cpus)
17234c87aefeSPatrick Mooney {
17244c87aefeSPatrick Mooney 	struct vm_cpuset vm_cpuset;
17254c87aefeSPatrick Mooney 	int error;
17264c87aefeSPatrick Mooney 
17274c87aefeSPatrick Mooney 	bzero(&vm_cpuset, sizeof(struct vm_cpuset));
17284c87aefeSPatrick Mooney 	vm_cpuset.which = which;
17294c87aefeSPatrick Mooney 	vm_cpuset.cpusetsize = sizeof(cpuset_t);
17304c87aefeSPatrick Mooney 	vm_cpuset.cpus = cpus;
17314c87aefeSPatrick Mooney 
17324c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_CPUS, &vm_cpuset);
17334c87aefeSPatrick Mooney 	return (error);
17344c87aefeSPatrick Mooney }
17354c87aefeSPatrick Mooney 
17364c87aefeSPatrick Mooney int
17374c87aefeSPatrick Mooney vm_active_cpus(struct vmctx *ctx, cpuset_t *cpus)
17384c87aefeSPatrick Mooney {
17394c87aefeSPatrick Mooney 
17404c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_ACTIVE_CPUS, cpus));
17414c87aefeSPatrick Mooney }
17424c87aefeSPatrick Mooney 
17434c87aefeSPatrick Mooney int
17444c87aefeSPatrick Mooney vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus)
17454c87aefeSPatrick Mooney {
17464c87aefeSPatrick Mooney 
17474c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_SUSPENDED_CPUS, cpus));
17484c87aefeSPatrick Mooney }
17494c87aefeSPatrick Mooney 
17504c87aefeSPatrick Mooney int
17514c87aefeSPatrick Mooney vm_debug_cpus(struct vmctx *ctx, cpuset_t *cpus)
17524c87aefeSPatrick Mooney {
17534c87aefeSPatrick Mooney 
17544c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_DEBUG_CPUS, cpus));
17554c87aefeSPatrick Mooney }
17564c87aefeSPatrick Mooney 
1757bf21cd93STycho Nightingale int
1758bf21cd93STycho Nightingale vm_activate_cpu(struct vmctx *ctx, int vcpu)
1759bf21cd93STycho Nightingale {
1760bf21cd93STycho Nightingale 	struct vm_activate_cpu ac;
1761bf21cd93STycho Nightingale 	int error;
1762bf21cd93STycho Nightingale 
1763bf21cd93STycho Nightingale 	bzero(&ac, sizeof(struct vm_activate_cpu));
1764bf21cd93STycho Nightingale 	ac.vcpuid = vcpu;
1765bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_ACTIVATE_CPU, &ac);
1766bf21cd93STycho Nightingale 	return (error);
1767bf21cd93STycho Nightingale }
1768bf21cd93STycho Nightingale 
17694c87aefeSPatrick Mooney int
17704c87aefeSPatrick Mooney vm_suspend_cpu(struct vmctx *ctx, int vcpu)
17714c87aefeSPatrick Mooney {
17724c87aefeSPatrick Mooney 	struct vm_activate_cpu ac;
17734c87aefeSPatrick Mooney 	int error;
17744c87aefeSPatrick Mooney 
17754c87aefeSPatrick Mooney 	bzero(&ac, sizeof(struct vm_activate_cpu));
17764c87aefeSPatrick Mooney 	ac.vcpuid = vcpu;
17774c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SUSPEND_CPU, &ac);
17784c87aefeSPatrick Mooney 	return (error);
17794c87aefeSPatrick Mooney }
17804c87aefeSPatrick Mooney 
17814c87aefeSPatrick Mooney int
17824c87aefeSPatrick Mooney vm_resume_cpu(struct vmctx *ctx, int vcpu)
17834c87aefeSPatrick Mooney {
17844c87aefeSPatrick Mooney 	struct vm_activate_cpu ac;
17854c87aefeSPatrick Mooney 	int error;
17864c87aefeSPatrick Mooney 
17874c87aefeSPatrick Mooney 	bzero(&ac, sizeof(struct vm_activate_cpu));
17884c87aefeSPatrick Mooney 	ac.vcpuid = vcpu;
17894c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RESUME_CPU, &ac);
17904c87aefeSPatrick Mooney 	return (error);
17914c87aefeSPatrick Mooney }
17924c87aefeSPatrick Mooney 
17934c87aefeSPatrick Mooney int
17944c87aefeSPatrick Mooney vm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *info1, uint64_t *info2)
17954c87aefeSPatrick Mooney {
17964c87aefeSPatrick Mooney 	struct vm_intinfo vmii;
17974c87aefeSPatrick Mooney 	int error;
17984c87aefeSPatrick Mooney 
17994c87aefeSPatrick Mooney 	bzero(&vmii, sizeof(struct vm_intinfo));
18004c87aefeSPatrick Mooney 	vmii.vcpuid = vcpu;
18014c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_INTINFO, &vmii);
18024c87aefeSPatrick Mooney 	if (error == 0) {
18034c87aefeSPatrick Mooney 		*info1 = vmii.info1;
18044c87aefeSPatrick Mooney 		*info2 = vmii.info2;
18054c87aefeSPatrick Mooney 	}
18064c87aefeSPatrick Mooney 	return (error);
18074c87aefeSPatrick Mooney }
18084c87aefeSPatrick Mooney 
18094c87aefeSPatrick Mooney int
18104c87aefeSPatrick Mooney vm_set_intinfo(struct vmctx *ctx, int vcpu, uint64_t info1)
18114c87aefeSPatrick Mooney {
18124c87aefeSPatrick Mooney 	struct vm_intinfo vmii;
18134c87aefeSPatrick Mooney 	int error;
18144c87aefeSPatrick Mooney 
18154c87aefeSPatrick Mooney 	bzero(&vmii, sizeof(struct vm_intinfo));
18164c87aefeSPatrick Mooney 	vmii.vcpuid = vcpu;
18174c87aefeSPatrick Mooney 	vmii.info1 = info1;
18184c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SET_INTINFO, &vmii);
18194c87aefeSPatrick Mooney 	return (error);
18204c87aefeSPatrick Mooney }
18214c87aefeSPatrick Mooney 
18224c87aefeSPatrick Mooney int
18234c87aefeSPatrick Mooney vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
18244c87aefeSPatrick Mooney {
18254c87aefeSPatrick Mooney 	struct vm_rtc_data rtcdata;
18264c87aefeSPatrick Mooney 	int error;
18274c87aefeSPatrick Mooney 
18284c87aefeSPatrick Mooney 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
18294c87aefeSPatrick Mooney 	rtcdata.offset = offset;
18304c87aefeSPatrick Mooney 	rtcdata.value = value;
18314c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
18324c87aefeSPatrick Mooney 	return (error);
18334c87aefeSPatrick Mooney }
18344c87aefeSPatrick Mooney 
18354c87aefeSPatrick Mooney int
18364c87aefeSPatrick Mooney vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
18374c87aefeSPatrick Mooney {
18384c87aefeSPatrick Mooney 	struct vm_rtc_data rtcdata;
18394c87aefeSPatrick Mooney 	int error;
18404c87aefeSPatrick Mooney 
18414c87aefeSPatrick Mooney 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
18424c87aefeSPatrick Mooney 	rtcdata.offset = offset;
18434c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
18444c87aefeSPatrick Mooney 	if (error == 0)
18454c87aefeSPatrick Mooney 		*retval = rtcdata.value;
18464c87aefeSPatrick Mooney 	return (error);
18474c87aefeSPatrick Mooney }
18484c87aefeSPatrick Mooney 
18494c87aefeSPatrick Mooney int
18504c87aefeSPatrick Mooney vm_rtc_settime(struct vmctx *ctx, time_t secs)
18514c87aefeSPatrick Mooney {
18524c87aefeSPatrick Mooney 	struct vm_rtc_time rtctime;
18534c87aefeSPatrick Mooney 	int error;
18544c87aefeSPatrick Mooney 
18554c87aefeSPatrick Mooney 	bzero(&rtctime, sizeof(struct vm_rtc_time));
18564c87aefeSPatrick Mooney 	rtctime.secs = secs;
18574c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
18584c87aefeSPatrick Mooney 	return (error);
18594c87aefeSPatrick Mooney }
18604c87aefeSPatrick Mooney 
18614c87aefeSPatrick Mooney int
18624c87aefeSPatrick Mooney vm_rtc_gettime(struct vmctx *ctx, time_t *secs)
18634c87aefeSPatrick Mooney {
18644c87aefeSPatrick Mooney 	struct vm_rtc_time rtctime;
18654c87aefeSPatrick Mooney 	int error;
18664c87aefeSPatrick Mooney 
18674c87aefeSPatrick Mooney 	bzero(&rtctime, sizeof(struct vm_rtc_time));
18684c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
18694c87aefeSPatrick Mooney 	if (error == 0)
18704c87aefeSPatrick Mooney 		*secs = rtctime.secs;
18714c87aefeSPatrick Mooney 	return (error);
18724c87aefeSPatrick Mooney }
18734c87aefeSPatrick Mooney 
1874bf21cd93STycho Nightingale int
1875bf21cd93STycho Nightingale vm_restart_instruction(void *arg, int vcpu)
1876bf21cd93STycho Nightingale {
1877bf21cd93STycho Nightingale 	struct vmctx *ctx = arg;
1878bf21cd93STycho Nightingale 
1879bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_RESTART_INSTRUCTION, &vcpu));
1880bf21cd93STycho Nightingale }
18814c87aefeSPatrick Mooney 
18824c87aefeSPatrick Mooney int
18834c87aefeSPatrick Mooney vm_set_topology(struct vmctx *ctx,
18844c87aefeSPatrick Mooney     uint16_t sockets, uint16_t cores, uint16_t threads, uint16_t maxcpus)
18854c87aefeSPatrick Mooney {
18864c87aefeSPatrick Mooney 	struct vm_cpu_topology topology;
18874c87aefeSPatrick Mooney 
18884c87aefeSPatrick Mooney 	bzero(&topology, sizeof (struct vm_cpu_topology));
18894c87aefeSPatrick Mooney 	topology.sockets = sockets;
18904c87aefeSPatrick Mooney 	topology.cores = cores;
18914c87aefeSPatrick Mooney 	topology.threads = threads;
18924c87aefeSPatrick Mooney 	topology.maxcpus = maxcpus;
18934c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_SET_TOPOLOGY, &topology));
18944c87aefeSPatrick Mooney }
18954c87aefeSPatrick Mooney 
18964c87aefeSPatrick Mooney int
18974c87aefeSPatrick Mooney vm_get_topology(struct vmctx *ctx,
18984c87aefeSPatrick Mooney     uint16_t *sockets, uint16_t *cores, uint16_t *threads, uint16_t *maxcpus)
18994c87aefeSPatrick Mooney {
19004c87aefeSPatrick Mooney 	struct vm_cpu_topology topology;
19014c87aefeSPatrick Mooney 	int error;
19024c87aefeSPatrick Mooney 
19034c87aefeSPatrick Mooney 	bzero(&topology, sizeof (struct vm_cpu_topology));
19044c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_TOPOLOGY, &topology);
19054c87aefeSPatrick Mooney 	if (error == 0) {
19064c87aefeSPatrick Mooney 		*sockets = topology.sockets;
19074c87aefeSPatrick Mooney 		*cores = topology.cores;
19084c87aefeSPatrick Mooney 		*threads = topology.threads;
19094c87aefeSPatrick Mooney 		*maxcpus = topology.maxcpus;
19104c87aefeSPatrick Mooney 	}
19114c87aefeSPatrick Mooney 	return (error);
19124c87aefeSPatrick Mooney }
19134c87aefeSPatrick Mooney 
19144c87aefeSPatrick Mooney int
19154c87aefeSPatrick Mooney vm_get_device_fd(struct vmctx *ctx)
19164c87aefeSPatrick Mooney {
19174c87aefeSPatrick Mooney 
19184c87aefeSPatrick Mooney 	return (ctx->fd);
19194c87aefeSPatrick Mooney }
19204c87aefeSPatrick Mooney 
19214c87aefeSPatrick Mooney #ifndef __FreeBSD__
19220e1453c3SPatrick Mooney int
19230e1453c3SPatrick Mooney vm_pmtmr_set_location(struct vmctx *ctx, uint16_t ioport)
19240e1453c3SPatrick Mooney {
19250e1453c3SPatrick Mooney 	return (ioctl(ctx->fd, VM_PMTMR_LOCATE, ioport));
19260e1453c3SPatrick Mooney }
19270e1453c3SPatrick Mooney 
19284c87aefeSPatrick Mooney int
19294c87aefeSPatrick Mooney vm_wrlock_cycle(struct vmctx *ctx)
19304c87aefeSPatrick Mooney {
19314c87aefeSPatrick Mooney 	if (ioctl(ctx->fd, VM_WRLOCK_CYCLE, 0) != 0) {
19324c87aefeSPatrick Mooney 		return (errno);
19334c87aefeSPatrick Mooney 	}
19344c87aefeSPatrick Mooney 	return (0);
19354c87aefeSPatrick Mooney }
19362606939dSPatrick Mooney 
19372606939dSPatrick Mooney int
19382606939dSPatrick Mooney vm_get_run_state(struct vmctx *ctx, int vcpu, enum vcpu_run_state *state,
19392606939dSPatrick Mooney     uint8_t *sipi_vector)
19402606939dSPatrick Mooney {
19412606939dSPatrick Mooney 	struct vm_run_state data;
19422606939dSPatrick Mooney 
19432606939dSPatrick Mooney 	data.vcpuid = vcpu;
19442606939dSPatrick Mooney 	if (ioctl(ctx->fd, VM_GET_RUN_STATE, &data) != 0) {
19452606939dSPatrick Mooney 		return (errno);
19462606939dSPatrick Mooney 	}
19472606939dSPatrick Mooney 
19482606939dSPatrick Mooney 	*state = data.state;
19492606939dSPatrick Mooney 	*sipi_vector = data.sipi_vector;
19502606939dSPatrick Mooney 	return (0);
19512606939dSPatrick Mooney }
19522606939dSPatrick Mooney 
19532606939dSPatrick Mooney int
19542606939dSPatrick Mooney vm_set_run_state(struct vmctx *ctx, int vcpu, enum vcpu_run_state state,
19552606939dSPatrick Mooney     uint8_t sipi_vector)
19562606939dSPatrick Mooney {
19572606939dSPatrick Mooney 	struct vm_run_state data;
19582606939dSPatrick Mooney 
19592606939dSPatrick Mooney 	data.vcpuid = vcpu;
19602606939dSPatrick Mooney 	data.state = state;
19612606939dSPatrick Mooney 	data.sipi_vector = sipi_vector;
19622606939dSPatrick Mooney 	if (ioctl(ctx->fd, VM_SET_RUN_STATE, &data) != 0) {
19632606939dSPatrick Mooney 		return (errno);
19642606939dSPatrick Mooney 	}
19652606939dSPatrick Mooney 
19662606939dSPatrick Mooney 	return (0);
19672606939dSPatrick Mooney }
19682606939dSPatrick Mooney 
19694c87aefeSPatrick Mooney #endif /* __FreeBSD__ */
19704c87aefeSPatrick Mooney 
19714c87aefeSPatrick Mooney #ifdef __FreeBSD__
19724c87aefeSPatrick Mooney const cap_ioctl_t *
19734c87aefeSPatrick Mooney vm_get_ioctls(size_t *len)
19744c87aefeSPatrick Mooney {
19754c87aefeSPatrick Mooney 	cap_ioctl_t *cmds;
19764c87aefeSPatrick Mooney 	/* keep in sync with machine/vmm_dev.h */
19774c87aefeSPatrick Mooney 	static const cap_ioctl_t vm_ioctl_cmds[] = { VM_RUN, VM_SUSPEND, VM_REINIT,
19784c87aefeSPatrick Mooney 	    VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
19792b948146SAndy Fiddaman 	    VM_MMAP_GETNEXT, VM_MUNMAP_MEMSEG, VM_SET_REGISTER, VM_GET_REGISTER,
19804c87aefeSPatrick Mooney 	    VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
19814c87aefeSPatrick Mooney 	    VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
1982154972afSPatrick Mooney 	    VM_SET_KERNEMU_DEV, VM_GET_KERNEMU_DEV,
19834c87aefeSPatrick Mooney 	    VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
19844c87aefeSPatrick Mooney 	    VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
19854c87aefeSPatrick Mooney 	    VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,
19864c87aefeSPatrick Mooney 	    VM_ISA_DEASSERT_IRQ, VM_ISA_PULSE_IRQ, VM_ISA_SET_IRQ_TRIGGER,
19874c87aefeSPatrick Mooney 	    VM_SET_CAPABILITY, VM_GET_CAPABILITY, VM_BIND_PPTDEV,
19884c87aefeSPatrick Mooney 	    VM_UNBIND_PPTDEV, VM_MAP_PPTDEV_MMIO, VM_PPTDEV_MSI,
19892b948146SAndy Fiddaman 	    VM_PPTDEV_MSIX, VM_UNMAP_PPTDEV_MMIO, VM_PPTDEV_DISABLE_MSIX,
19906960cd89SAndy Fiddaman 	    VM_INJECT_NMI, VM_STATS, VM_STAT_DESC,
19914c87aefeSPatrick Mooney 	    VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
19924c87aefeSPatrick Mooney 	    VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
19934c87aefeSPatrick Mooney 	    VM_GLA2GPA_NOFAULT,
19944c87aefeSPatrick Mooney 	    VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU,
19954c87aefeSPatrick Mooney 	    VM_SET_INTINFO, VM_GET_INTINFO,
19964c87aefeSPatrick Mooney 	    VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
19974c87aefeSPatrick Mooney 	    VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY };
19984c87aefeSPatrick Mooney 
19994c87aefeSPatrick Mooney 	if (len == NULL) {
20004c87aefeSPatrick Mooney 		cmds = malloc(sizeof(vm_ioctl_cmds));
20014c87aefeSPatrick Mooney 		if (cmds == NULL)
20024c87aefeSPatrick Mooney 			return (NULL);
20034c87aefeSPatrick Mooney 		bcopy(vm_ioctl_cmds, cmds, sizeof(vm_ioctl_cmds));
20044c87aefeSPatrick Mooney 		return (cmds);
20054c87aefeSPatrick Mooney 	}
20064c87aefeSPatrick Mooney 
20074c87aefeSPatrick Mooney 	*len = nitems(vm_ioctl_cmds);
20084c87aefeSPatrick Mooney 	return (NULL);
20094c87aefeSPatrick Mooney }
20104c87aefeSPatrick Mooney #endif /* __FreeBSD__ */
2011