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.
42b57f5d3eSPatrick 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 
113b57f5d3eSPatrick Mooney int
114b57f5d3eSPatrick Mooney vm_create(const char *name)
115b57f5d3eSPatrick Mooney {
116b57f5d3eSPatrick Mooney 	/* Try to load vmm(4) module before creating a guest. */
117b57f5d3eSPatrick Mooney 	if (modfind("vmm") < 0)
118b57f5d3eSPatrick Mooney 		kldload("vmm");
119*b0de25cbSAndy Fiddaman 	return (CREATE(name));
120b57f5d3eSPatrick Mooney }
121b57f5d3eSPatrick Mooney 
122b57f5d3eSPatrick Mooney void
123b57f5d3eSPatrick Mooney vm_destroy(struct vmctx *vm)
124b57f5d3eSPatrick Mooney {
125b57f5d3eSPatrick Mooney 	assert(vm != NULL);
126b57f5d3eSPatrick Mooney 
127b57f5d3eSPatrick Mooney 	if (vm->fd >= 0)
128b57f5d3eSPatrick Mooney 		close(vm->fd);
129b57f5d3eSPatrick Mooney 	DESTROY(vm->name);
130b57f5d3eSPatrick Mooney 
131b57f5d3eSPatrick Mooney 	free(vm);
132b57f5d3eSPatrick Mooney }
133b57f5d3eSPatrick Mooney 
134b57f5d3eSPatrick Mooney #else
135bf21cd93STycho Nightingale static int
136b57f5d3eSPatrick 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 
145b57f5d3eSPatrick 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 }
157b57f5d3eSPatrick Mooney 
158b57f5d3eSPatrick Mooney int
159b57f5d3eSPatrick Mooney vm_create(const char *name, uint64_t flags)
160b57f5d3eSPatrick Mooney {
161b57f5d3eSPatrick Mooney 	struct vm_create_req req;
162b57f5d3eSPatrick Mooney 
163b57f5d3eSPatrick Mooney 	(void) strncpy(req.name, name, VM_MAX_NAMELEN);
164b57f5d3eSPatrick Mooney 	req.flags = flags;
165b57f5d3eSPatrick Mooney 
166b57f5d3eSPatrick Mooney 	return (vm_do_ctl(VMM_CREATE_VM, &req));
167b57f5d3eSPatrick Mooney }
168b57f5d3eSPatrick Mooney 
169b57f5d3eSPatrick Mooney void
170b57f5d3eSPatrick Mooney vm_close(struct vmctx *vm)
171b57f5d3eSPatrick Mooney {
172b57f5d3eSPatrick Mooney 	assert(vm != NULL);
173b57f5d3eSPatrick Mooney 	assert(vm->fd >= 0);
174b57f5d3eSPatrick Mooney 
175b57f5d3eSPatrick Mooney 	(void) close(vm->fd);
176b57f5d3eSPatrick Mooney 
177b57f5d3eSPatrick Mooney 	free(vm);
178b57f5d3eSPatrick Mooney }
179b57f5d3eSPatrick Mooney 
180b57f5d3eSPatrick Mooney void
181b57f5d3eSPatrick Mooney vm_destroy(struct vmctx *vm)
182b57f5d3eSPatrick Mooney {
183b57f5d3eSPatrick Mooney 	struct vm_destroy_req req;
184b57f5d3eSPatrick Mooney 
185b57f5d3eSPatrick Mooney 	assert(vm != NULL);
186b57f5d3eSPatrick Mooney 
187b57f5d3eSPatrick Mooney 	if (vm->fd >= 0) {
188b57f5d3eSPatrick Mooney 		(void) close(vm->fd);
189b57f5d3eSPatrick Mooney 		vm->fd = -1;
190b57f5d3eSPatrick Mooney 	}
191b57f5d3eSPatrick Mooney 
192b57f5d3eSPatrick Mooney 	(void) strncpy(req.name, vm->name, VM_MAX_NAMELEN);
193b57f5d3eSPatrick Mooney 	(void) vm_do_ctl(VMM_DESTROY_VM, &req);
194b57f5d3eSPatrick Mooney 
195b57f5d3eSPatrick Mooney 	free(vm);
196b57f5d3eSPatrick 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;
221*b0de25cbSAndy Fiddaman 	int saved_errno;
222bf21cd93STycho Nightingale 
223bf21cd93STycho Nightingale 	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
224bf21cd93STycho Nightingale 	assert(vm != NULL);
225bf21cd93STycho Nightingale 
226bf21cd93STycho Nightingale 	vm->fd = -1;
2274c87aefeSPatrick Mooney 	vm->memflags = 0;
228bf21cd93STycho Nightingale 	vm->lowmem_limit = 3 * GB;
229bf21cd93STycho Nightingale 	vm->name = (char *)(vm + 1);
230bf21cd93STycho Nightingale 	strcpy(vm->name, name);
231bf21cd93STycho Nightingale 
232bf21cd93STycho Nightingale 	if ((vm->fd = vm_device_open(vm->name)) < 0)
233bf21cd93STycho Nightingale 		goto err;
234bf21cd93STycho Nightingale 
235bf21cd93STycho Nightingale 	return (vm);
236bf21cd93STycho Nightingale err:
237*b0de25cbSAndy Fiddaman 	saved_errno = errno;
2389c3024a3SHans Rosenfeld 	free(vm);
239*b0de25cbSAndy Fiddaman 	errno = saved_errno;
240bf21cd93STycho Nightingale 	return (NULL);
241bf21cd93STycho Nightingale }
242bf21cd93STycho Nightingale 
243bf21cd93STycho Nightingale 
244bf21cd93STycho Nightingale int
245*b0de25cbSAndy Fiddaman vm_parse_memsize(const char *opt, size_t *ret_memsize)
246bf21cd93STycho Nightingale {
247bf21cd93STycho Nightingale 	char *endptr;
248bf21cd93STycho Nightingale 	size_t optval;
249bf21cd93STycho Nightingale 	int error;
250bf21cd93STycho Nightingale 
251*b0de25cbSAndy Fiddaman 	optval = strtoul(opt, &endptr, 0);
252*b0de25cbSAndy Fiddaman 	if (*opt != '\0' && *endptr == '\0') {
253bf21cd93STycho Nightingale 		/*
254bf21cd93STycho Nightingale 		 * For the sake of backward compatibility if the memory size
255bf21cd93STycho Nightingale 		 * specified on the command line is less than a megabyte then
256bf21cd93STycho Nightingale 		 * it is interpreted as being in units of MB.
257bf21cd93STycho Nightingale 		 */
258bf21cd93STycho Nightingale 		if (optval < MB)
259bf21cd93STycho Nightingale 			optval *= MB;
260bf21cd93STycho Nightingale 		*ret_memsize = optval;
261bf21cd93STycho Nightingale 		error = 0;
262bf21cd93STycho Nightingale 	} else
263*b0de25cbSAndy Fiddaman 		error = expand_number(opt, ret_memsize);
264bf21cd93STycho Nightingale 
265bf21cd93STycho Nightingale 	return (error);
266bf21cd93STycho Nightingale }
267bf21cd93STycho Nightingale 
2684c87aefeSPatrick Mooney uint32_t
2694c87aefeSPatrick Mooney vm_get_lowmem_limit(struct vmctx *ctx)
270bf21cd93STycho Nightingale {
2714c87aefeSPatrick Mooney 
2724c87aefeSPatrick Mooney 	return (ctx->lowmem_limit);
273bf21cd93STycho Nightingale }
274bf21cd93STycho Nightingale 
2754c87aefeSPatrick Mooney void
2764c87aefeSPatrick Mooney vm_set_lowmem_limit(struct vmctx *ctx, uint32_t limit)
277bf21cd93STycho Nightingale {
2784c87aefeSPatrick Mooney 
2794c87aefeSPatrick Mooney 	ctx->lowmem_limit = limit;
2804c87aefeSPatrick Mooney }
2814c87aefeSPatrick Mooney 
2824c87aefeSPatrick Mooney void
2834c87aefeSPatrick Mooney vm_set_memflags(struct vmctx *ctx, int flags)
2844c87aefeSPatrick Mooney {
2854c87aefeSPatrick Mooney 
2864c87aefeSPatrick Mooney 	ctx->memflags = flags;
287bf21cd93STycho Nightingale }
288bf21cd93STycho Nightingale 
289bf21cd93STycho Nightingale int
2904c87aefeSPatrick Mooney vm_get_memflags(struct vmctx *ctx)
291bf21cd93STycho Nightingale {
2924c87aefeSPatrick Mooney 
2934c87aefeSPatrick Mooney 	return (ctx->memflags);
2944c87aefeSPatrick Mooney }
2954c87aefeSPatrick Mooney 
2964c87aefeSPatrick Mooney /*
2974c87aefeSPatrick Mooney  * Map segment 'segid' starting at 'off' into guest address range [gpa,gpa+len).
2984c87aefeSPatrick Mooney  */
2994c87aefeSPatrick Mooney int
3004c87aefeSPatrick Mooney vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, vm_ooffset_t off,
3014c87aefeSPatrick Mooney     size_t len, int prot)
3024c87aefeSPatrick Mooney {
3034c87aefeSPatrick Mooney 	struct vm_memmap memmap;
3044c87aefeSPatrick Mooney 	int error, flags;
3054c87aefeSPatrick Mooney 
3064c87aefeSPatrick Mooney 	memmap.gpa = gpa;
3074c87aefeSPatrick Mooney 	memmap.segid = segid;
3084c87aefeSPatrick Mooney 	memmap.segoff = off;
3094c87aefeSPatrick Mooney 	memmap.len = len;
3104c87aefeSPatrick Mooney 	memmap.prot = prot;
3114c87aefeSPatrick Mooney 	memmap.flags = 0;
3124c87aefeSPatrick Mooney 
3134c87aefeSPatrick Mooney 	if (ctx->memflags & VM_MEM_F_WIRED)
3144c87aefeSPatrick Mooney 		memmap.flags |= VM_MEMMAP_F_WIRED;
3154c87aefeSPatrick Mooney 
3164c87aefeSPatrick Mooney 	/*
3174c87aefeSPatrick Mooney 	 * If this mapping already exists then don't create it again. This
3184c87aefeSPatrick Mooney 	 * is the common case for SYSMEM mappings created by bhyveload(8).
3194c87aefeSPatrick Mooney 	 */
3204c87aefeSPatrick Mooney 	error = vm_mmap_getnext(ctx, &gpa, &segid, &off, &len, &prot, &flags);
3214c87aefeSPatrick Mooney 	if (error == 0 && gpa == memmap.gpa) {
3224c87aefeSPatrick Mooney 		if (segid != memmap.segid || off != memmap.segoff ||
3234c87aefeSPatrick Mooney 		    prot != memmap.prot || flags != memmap.flags) {
3244c87aefeSPatrick Mooney 			errno = EEXIST;
3254c87aefeSPatrick Mooney 			return (-1);
3264c87aefeSPatrick Mooney 		} else {
3274c87aefeSPatrick Mooney 			return (0);
3284c87aefeSPatrick Mooney 		}
3294c87aefeSPatrick Mooney 	}
3304c87aefeSPatrick Mooney 
3314c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_MMAP_MEMSEG, &memmap);
332bf21cd93STycho Nightingale 	return (error);
333bf21cd93STycho Nightingale }
334bf21cd93STycho Nightingale 
3352b948146SAndy Fiddaman int
3362b948146SAndy Fiddaman vm_munmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, size_t len)
3372b948146SAndy Fiddaman {
3382b948146SAndy Fiddaman 	struct vm_munmap munmap;
3392b948146SAndy Fiddaman 	int error;
3402b948146SAndy Fiddaman 
3412b948146SAndy Fiddaman 	munmap.gpa = gpa;
3422b948146SAndy Fiddaman 	munmap.len = len;
3432b948146SAndy Fiddaman 
3442b948146SAndy Fiddaman 	error = ioctl(ctx->fd, VM_MUNMAP_MEMSEG, &munmap);
3452b948146SAndy Fiddaman 	return (error);
3462b948146SAndy Fiddaman }
3472b948146SAndy Fiddaman 
3484c87aefeSPatrick Mooney int
3494c87aefeSPatrick Mooney vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
3504c87aefeSPatrick Mooney     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
351bf21cd93STycho Nightingale {
3524c87aefeSPatrick Mooney 	struct vm_memmap memmap;
3534c87aefeSPatrick Mooney 	int error;
354bf21cd93STycho Nightingale 
3554c87aefeSPatrick Mooney 	bzero(&memmap, sizeof(struct vm_memmap));
3564c87aefeSPatrick Mooney 	memmap.gpa = *gpa;
3574c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_MMAP_GETNEXT, &memmap);
3584c87aefeSPatrick Mooney 	if (error == 0) {
3594c87aefeSPatrick Mooney 		*gpa = memmap.gpa;
3604c87aefeSPatrick Mooney 		*segid = memmap.segid;
3614c87aefeSPatrick Mooney 		*segoff = memmap.segoff;
3624c87aefeSPatrick Mooney 		*len = memmap.len;
3634c87aefeSPatrick Mooney 		*prot = memmap.prot;
3644c87aefeSPatrick Mooney 		*flags = memmap.flags;
3654c87aefeSPatrick Mooney 	}
3664c87aefeSPatrick Mooney 	return (error);
367bf21cd93STycho Nightingale }
368bf21cd93STycho Nightingale 
3694c87aefeSPatrick Mooney /*
3704c87aefeSPatrick Mooney  * Return 0 if the segments are identical and non-zero otherwise.
3714c87aefeSPatrick Mooney  *
3724c87aefeSPatrick Mooney  * This is slightly complicated by the fact that only device memory segments
3734c87aefeSPatrick Mooney  * are named.
3744c87aefeSPatrick Mooney  */
3754c87aefeSPatrick Mooney static int
3764c87aefeSPatrick Mooney cmpseg(size_t len, const char *str, size_t len2, const char *str2)
377bf21cd93STycho Nightingale {
378bf21cd93STycho Nightingale 
3794c87aefeSPatrick Mooney 	if (len == len2) {
3804c87aefeSPatrick Mooney 		if ((!str && !str2) || (str && str2 && !strcmp(str, str2)))
3814c87aefeSPatrick Mooney 			return (0);
3824c87aefeSPatrick Mooney 	}
3834c87aefeSPatrick Mooney 	return (-1);
384bf21cd93STycho Nightingale }
385bf21cd93STycho Nightingale 
386bf21cd93STycho Nightingale static int
3874c87aefeSPatrick Mooney vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
388bf21cd93STycho Nightingale {
3894c87aefeSPatrick Mooney 	struct vm_memseg memseg;
3904c87aefeSPatrick Mooney 	size_t n;
391bf21cd93STycho Nightingale 	int error;
392bf21cd93STycho Nightingale 
393bf21cd93STycho Nightingale 	/*
3944c87aefeSPatrick Mooney 	 * If the memory segment has already been created then just return.
3954c87aefeSPatrick Mooney 	 * This is the usual case for the SYSMEM segment created by userspace
3964c87aefeSPatrick Mooney 	 * loaders like bhyveload(8).
397bf21cd93STycho Nightingale 	 */
3984c87aefeSPatrick Mooney 	error = vm_get_memseg(ctx, segid, &memseg.len, memseg.name,
3994c87aefeSPatrick Mooney 	    sizeof(memseg.name));
4004c87aefeSPatrick Mooney 	if (error)
4014c87aefeSPatrick Mooney 		return (error);
4024c87aefeSPatrick Mooney 
4034c87aefeSPatrick Mooney 	if (memseg.len != 0) {
4044c87aefeSPatrick Mooney 		if (cmpseg(len, name, memseg.len, VM_MEMSEG_NAME(&memseg))) {
4054c87aefeSPatrick Mooney 			errno = EINVAL;
4064c87aefeSPatrick Mooney 			return (-1);
4074c87aefeSPatrick Mooney 		} else {
4084c87aefeSPatrick Mooney 			return (0);
4094c87aefeSPatrick Mooney 		}
4104c87aefeSPatrick Mooney 	}
4114c87aefeSPatrick Mooney 
4124c87aefeSPatrick Mooney 	bzero(&memseg, sizeof(struct vm_memseg));
4134c87aefeSPatrick Mooney 	memseg.segid = segid;
4144c87aefeSPatrick Mooney 	memseg.len = len;
4154c87aefeSPatrick Mooney 	if (name != NULL) {
4164c87aefeSPatrick Mooney 		n = strlcpy(memseg.name, name, sizeof(memseg.name));
4174c87aefeSPatrick Mooney 		if (n >= sizeof(memseg.name)) {
4184c87aefeSPatrick Mooney 			errno = ENAMETOOLONG;
4194c87aefeSPatrick Mooney 			return (-1);
4204c87aefeSPatrick Mooney 		}
4214c87aefeSPatrick Mooney 	}
4224c87aefeSPatrick Mooney 
4234c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_ALLOC_MEMSEG, &memseg);
4244c87aefeSPatrick Mooney 	return (error);
4254c87aefeSPatrick Mooney }
4264c87aefeSPatrick Mooney 
4274c87aefeSPatrick Mooney int
4284c87aefeSPatrick Mooney vm_get_memseg(struct vmctx *ctx, int segid, size_t *lenp, char *namebuf,
4294c87aefeSPatrick Mooney     size_t bufsize)
4304c87aefeSPatrick Mooney {
4314c87aefeSPatrick Mooney 	struct vm_memseg memseg;
4324c87aefeSPatrick Mooney 	size_t n;
4334c87aefeSPatrick Mooney 	int error;
4344c87aefeSPatrick Mooney 
4354c87aefeSPatrick Mooney 	memseg.segid = segid;
4364c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_MEMSEG, &memseg);
4374c87aefeSPatrick Mooney 	if (error == 0) {
4384c87aefeSPatrick Mooney 		*lenp = memseg.len;
4394c87aefeSPatrick Mooney 		n = strlcpy(namebuf, memseg.name, bufsize);
4404c87aefeSPatrick Mooney 		if (n >= bufsize) {
4414c87aefeSPatrick Mooney 			errno = ENAMETOOLONG;
4424c87aefeSPatrick Mooney 			error = -1;
4434c87aefeSPatrick Mooney 		}
444bf21cd93STycho Nightingale 	}
445bf21cd93STycho Nightingale 	return (error);
446bf21cd93STycho Nightingale }
447bf21cd93STycho Nightingale 
4484c87aefeSPatrick Mooney static int
4494c87aefeSPatrick Mooney #ifdef __FreeBSD__
4504c87aefeSPatrick Mooney setup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
4514c87aefeSPatrick Mooney #else
4524c87aefeSPatrick Mooney setup_memory_segment(struct vmctx *ctx, int segid, vm_paddr_t gpa, size_t len,
4534c87aefeSPatrick Mooney     char *base)
4544c87aefeSPatrick Mooney #endif
4554c87aefeSPatrick Mooney {
4564c87aefeSPatrick Mooney 	char *ptr;
4574c87aefeSPatrick Mooney 	int error, flags;
4584c87aefeSPatrick Mooney 
4594c87aefeSPatrick Mooney 	/* Map 'len' bytes starting at 'gpa' in the guest address space */
4604c87aefeSPatrick Mooney #ifdef __FreeBSD__
4614c87aefeSPatrick Mooney 	error = vm_mmap_memseg(ctx, gpa, VM_SYSMEM, gpa, len, PROT_ALL);
4624c87aefeSPatrick Mooney #else
4634c87aefeSPatrick Mooney 	/*
4644c87aefeSPatrick Mooney 	 * As we use two segments for lowmem/highmem the offset within the
4654c87aefeSPatrick Mooney 	 * segment is 0 on illumos.
4664c87aefeSPatrick Mooney 	 */
4674c87aefeSPatrick Mooney 	error = vm_mmap_memseg(ctx, gpa, segid, 0, len, PROT_ALL);
4684c87aefeSPatrick Mooney #endif
4694c87aefeSPatrick Mooney 	if (error)
4704c87aefeSPatrick Mooney 		return (error);
4714c87aefeSPatrick Mooney 
4724c87aefeSPatrick Mooney 	flags = MAP_SHARED | MAP_FIXED;
4734c87aefeSPatrick Mooney 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
4744c87aefeSPatrick Mooney 		flags |= MAP_NOCORE;
4754c87aefeSPatrick Mooney 
4764c87aefeSPatrick Mooney 	/* mmap into the process address space on the host */
4774c87aefeSPatrick Mooney 	ptr = mmap(base + gpa, len, PROT_RW, flags, ctx->fd, gpa);
4784c87aefeSPatrick Mooney 	if (ptr == MAP_FAILED)
4794c87aefeSPatrick Mooney 		return (-1);
4804c87aefeSPatrick Mooney 
4814c87aefeSPatrick Mooney 	return (0);
4824c87aefeSPatrick Mooney }
4834c87aefeSPatrick Mooney 
484bf21cd93STycho Nightingale int
485bf21cd93STycho Nightingale vm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
486bf21cd93STycho Nightingale {
4874c87aefeSPatrick Mooney 	size_t objsize, len;
4884c87aefeSPatrick Mooney 	vm_paddr_t gpa;
4894c87aefeSPatrick Mooney 	char *baseaddr, *ptr;
490bf21cd93STycho Nightingale 	int error;
491bf21cd93STycho Nightingale 
4924c87aefeSPatrick Mooney 	assert(vms == VM_MMAP_ALL);
493bf21cd93STycho Nightingale 
494bf21cd93STycho Nightingale 	/*
495bf21cd93STycho Nightingale 	 * If 'memsize' cannot fit entirely in the 'lowmem' segment then
496bf21cd93STycho Nightingale 	 * create another 'highmem' segment above 4GB for the remainder.
497bf21cd93STycho Nightingale 	 */
498bf21cd93STycho Nightingale 	if (memsize > ctx->lowmem_limit) {
499bf21cd93STycho Nightingale 		ctx->lowmem = ctx->lowmem_limit;
5004c87aefeSPatrick Mooney 		ctx->highmem = memsize - ctx->lowmem_limit;
5014c87aefeSPatrick Mooney 		objsize = 4*GB + ctx->highmem;
502bf21cd93STycho Nightingale 	} else {
503bf21cd93STycho Nightingale 		ctx->lowmem = memsize;
504bf21cd93STycho Nightingale 		ctx->highmem = 0;
5054c87aefeSPatrick Mooney 		objsize = ctx->lowmem;
506bf21cd93STycho Nightingale 	}
507bf21cd93STycho Nightingale 
5084c87aefeSPatrick Mooney #ifdef __FreeBSD__
5094c87aefeSPatrick Mooney 	error = vm_alloc_memseg(ctx, VM_SYSMEM, objsize, NULL);
5104c87aefeSPatrick Mooney 	if (error)
5114c87aefeSPatrick Mooney 		return (error);
5124c87aefeSPatrick Mooney #endif
5134c87aefeSPatrick Mooney 
5144c87aefeSPatrick Mooney 	/*
5154c87aefeSPatrick Mooney 	 * Stake out a contiguous region covering the guest physical memory
5164c87aefeSPatrick Mooney 	 * and the adjoining guard regions.
5174c87aefeSPatrick Mooney 	 */
5184c87aefeSPatrick Mooney 	len = VM_MMAP_GUARD_SIZE + objsize + VM_MMAP_GUARD_SIZE;
5194c87aefeSPatrick Mooney 	ptr = mmap(NULL, len, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1, 0);
5204c87aefeSPatrick Mooney 	if (ptr == MAP_FAILED)
5214c87aefeSPatrick Mooney 		return (-1);
5224c87aefeSPatrick Mooney 
5234c87aefeSPatrick Mooney 	baseaddr = ptr + VM_MMAP_GUARD_SIZE;
524bf21cd93STycho Nightingale 
5254c87aefeSPatrick Mooney #ifdef __FreeBSD__
5264c87aefeSPatrick Mooney 	if (ctx->highmem > 0) {
5274c87aefeSPatrick Mooney 		gpa = 4*GB;
5284c87aefeSPatrick Mooney 		len = ctx->highmem;
5294c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
530bf21cd93STycho Nightingale 		if (error)
531bf21cd93STycho Nightingale 			return (error);
5324c87aefeSPatrick Mooney 	}
533bf21cd93STycho Nightingale 
5344c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
5354c87aefeSPatrick Mooney 		gpa = 0;
5364c87aefeSPatrick Mooney 		len = ctx->lowmem;
5374c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
538bf21cd93STycho Nightingale 		if (error)
539bf21cd93STycho Nightingale 			return (error);
540bf21cd93STycho Nightingale 	}
5414c87aefeSPatrick Mooney #else
542bf21cd93STycho Nightingale 	if (ctx->highmem > 0) {
5434c87aefeSPatrick Mooney 		error = vm_alloc_memseg(ctx, VM_HIGHMEM, ctx->highmem, NULL);
5444c87aefeSPatrick Mooney 		if (error)
5454c87aefeSPatrick Mooney 			return (error);
5464c87aefeSPatrick Mooney 		gpa = 4*GB;
5474c87aefeSPatrick Mooney 		len = ctx->highmem;
5484c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, VM_HIGHMEM, gpa, len, baseaddr);
549bf21cd93STycho Nightingale 		if (error)
550bf21cd93STycho Nightingale 			return (error);
551bf21cd93STycho Nightingale 	}
552bf21cd93STycho Nightingale 
5534c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
5544c87aefeSPatrick Mooney 		error = vm_alloc_memseg(ctx, VM_LOWMEM, ctx->lowmem, NULL);
5554c87aefeSPatrick Mooney 		if (error)
5564c87aefeSPatrick Mooney 			return (error);
5574c87aefeSPatrick Mooney 		gpa = 0;
5584c87aefeSPatrick Mooney 		len = ctx->lowmem;
5594c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, VM_LOWMEM, gpa, len, baseaddr);
5604c87aefeSPatrick Mooney 		if (error)
5614c87aefeSPatrick Mooney 			return (error);
5624c87aefeSPatrick Mooney 	}
5634c87aefeSPatrick Mooney #endif
564bf21cd93STycho Nightingale 
5654c87aefeSPatrick Mooney 	ctx->baseaddr = baseaddr;
566bf21cd93STycho Nightingale 
5674c87aefeSPatrick Mooney 	return (0);
568bf21cd93STycho Nightingale }
569bf21cd93STycho Nightingale 
5704c87aefeSPatrick Mooney /*
5714c87aefeSPatrick Mooney  * Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
5724c87aefeSPatrick Mooney  * the lowmem or highmem regions.
5734c87aefeSPatrick Mooney  *
5744c87aefeSPatrick Mooney  * In particular return NULL if [gaddr, gaddr+len) falls in guest MMIO region.
5754c87aefeSPatrick Mooney  * The instruction emulation code depends on this behavior.
5764c87aefeSPatrick Mooney  */
577bf21cd93STycho Nightingale void *
578bf21cd93STycho Nightingale vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
579bf21cd93STycho Nightingale {
580bf21cd93STycho Nightingale 
5814c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
5824c87aefeSPatrick Mooney 		if (gaddr < ctx->lowmem && len <= ctx->lowmem &&
5834c87aefeSPatrick Mooney 		    gaddr + len <= ctx->lowmem)
5844c87aefeSPatrick Mooney 			return (ctx->baseaddr + gaddr);
585bf21cd93STycho Nightingale 	}
586bf21cd93STycho Nightingale 
5874c87aefeSPatrick Mooney 	if (ctx->highmem > 0) {
5884c87aefeSPatrick Mooney                 if (gaddr >= 4*GB) {
5894c87aefeSPatrick Mooney 			if (gaddr < 4*GB + ctx->highmem &&
5904c87aefeSPatrick Mooney 			    len <= ctx->highmem &&
5914c87aefeSPatrick Mooney 			    gaddr + len <= 4*GB + ctx->highmem)
5924c87aefeSPatrick Mooney 				return (ctx->baseaddr + gaddr);
5934c87aefeSPatrick Mooney 		}
594bf21cd93STycho Nightingale 	}
595bf21cd93STycho Nightingale 
596bf21cd93STycho Nightingale 	return (NULL);
597bf21cd93STycho Nightingale }
598bf21cd93STycho Nightingale 
599bf21cd93STycho Nightingale size_t
600bf21cd93STycho Nightingale vm_get_lowmem_size(struct vmctx *ctx)
601bf21cd93STycho Nightingale {
602bf21cd93STycho Nightingale 
603bf21cd93STycho Nightingale 	return (ctx->lowmem);
604bf21cd93STycho Nightingale }
605bf21cd93STycho Nightingale 
606bf21cd93STycho Nightingale size_t
607bf21cd93STycho Nightingale vm_get_highmem_size(struct vmctx *ctx)
608bf21cd93STycho Nightingale {
609bf21cd93STycho Nightingale 
610bf21cd93STycho Nightingale 	return (ctx->highmem);
611bf21cd93STycho Nightingale }
612bf21cd93STycho Nightingale 
6139c3024a3SHans Rosenfeld #ifndef __FreeBSD__
6149c3024a3SHans Rosenfeld int
6159c3024a3SHans Rosenfeld vm_get_devmem_offset(struct vmctx *ctx, int segid, off_t *mapoff)
6169c3024a3SHans Rosenfeld {
6179c3024a3SHans Rosenfeld 	struct vm_devmem_offset vdo;
6189c3024a3SHans Rosenfeld 	int error;
6199c3024a3SHans Rosenfeld 
6209c3024a3SHans Rosenfeld 	vdo.segid = segid;
6219c3024a3SHans Rosenfeld 	error = ioctl(ctx->fd, VM_DEVMEM_GETOFFSET, &vdo);
6229c3024a3SHans Rosenfeld 	if (error == 0)
6239c3024a3SHans Rosenfeld 		*mapoff = vdo.offset;
6249c3024a3SHans Rosenfeld 
6259c3024a3SHans Rosenfeld 	return (error);
6269c3024a3SHans Rosenfeld }
6279c3024a3SHans Rosenfeld #endif
6289c3024a3SHans Rosenfeld 
6294c87aefeSPatrick Mooney void *
6304c87aefeSPatrick Mooney vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
6314c87aefeSPatrick Mooney {
6324c87aefeSPatrick Mooney #ifdef	__FreeBSD__
6334c87aefeSPatrick Mooney 	char pathname[MAXPATHLEN];
6344c87aefeSPatrick Mooney #endif
6354c87aefeSPatrick Mooney 	size_t len2;
6364c87aefeSPatrick Mooney 	char *base, *ptr;
6374c87aefeSPatrick Mooney 	int fd, error, flags;
6384c87aefeSPatrick Mooney 	off_t mapoff;
6394c87aefeSPatrick Mooney 
6404c87aefeSPatrick Mooney 	fd = -1;
6414c87aefeSPatrick Mooney 	ptr = MAP_FAILED;
6424c87aefeSPatrick Mooney 	if (name == NULL || strlen(name) == 0) {
6434c87aefeSPatrick Mooney 		errno = EINVAL;
6444c87aefeSPatrick Mooney 		goto done;
6454c87aefeSPatrick Mooney 	}
6464c87aefeSPatrick Mooney 
6474c87aefeSPatrick Mooney 	error = vm_alloc_memseg(ctx, segid, len, name);
6484c87aefeSPatrick Mooney 	if (error)
6494c87aefeSPatrick Mooney 		goto done;
6504c87aefeSPatrick Mooney 
6514c87aefeSPatrick Mooney #ifdef	__FreeBSD__
6524c87aefeSPatrick Mooney 	strlcpy(pathname, "/dev/vmm.io/", sizeof(pathname));
6534c87aefeSPatrick Mooney 	strlcat(pathname, ctx->name, sizeof(pathname));
6544c87aefeSPatrick Mooney 	strlcat(pathname, ".", sizeof(pathname));
6554c87aefeSPatrick Mooney 	strlcat(pathname, name, sizeof(pathname));
6564c87aefeSPatrick Mooney 
6574c87aefeSPatrick Mooney 	fd = open(pathname, O_RDWR);
6584c87aefeSPatrick Mooney 	if (fd < 0)
6594c87aefeSPatrick Mooney 		goto done;
6604c87aefeSPatrick Mooney #else
6619c3024a3SHans Rosenfeld 	if (vm_get_devmem_offset(ctx, segid, &mapoff) != 0)
6629c3024a3SHans Rosenfeld 		goto done;
6634c87aefeSPatrick Mooney #endif
6644c87aefeSPatrick Mooney 
6654c87aefeSPatrick Mooney 	/*
6664c87aefeSPatrick Mooney 	 * Stake out a contiguous region covering the device memory and the
6674c87aefeSPatrick Mooney 	 * adjoining guard regions.
6684c87aefeSPatrick Mooney 	 */
6694c87aefeSPatrick Mooney 	len2 = VM_MMAP_GUARD_SIZE + len + VM_MMAP_GUARD_SIZE;
6704c87aefeSPatrick Mooney 	base = mmap(NULL, len2, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1,
6714c87aefeSPatrick Mooney 	    0);
6724c87aefeSPatrick Mooney 	if (base == MAP_FAILED)
6734c87aefeSPatrick Mooney 		goto done;
6744c87aefeSPatrick Mooney 
6754c87aefeSPatrick Mooney 	flags = MAP_SHARED | MAP_FIXED;
6764c87aefeSPatrick Mooney 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
6774c87aefeSPatrick Mooney 		flags |= MAP_NOCORE;
6784c87aefeSPatrick Mooney 
6794c87aefeSPatrick Mooney #ifdef	__FreeBSD__
6804c87aefeSPatrick Mooney 	/* mmap the devmem region in the host address space */
6814c87aefeSPatrick Mooney 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, fd, 0);
6824c87aefeSPatrick Mooney #else
6834c87aefeSPatrick Mooney 	/* mmap the devmem region in the host address space */
6844c87aefeSPatrick Mooney 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, ctx->fd,
6854c87aefeSPatrick Mooney 	    mapoff);
6864c87aefeSPatrick Mooney #endif
6874c87aefeSPatrick Mooney done:
6884c87aefeSPatrick Mooney 	if (fd >= 0)
6894c87aefeSPatrick Mooney 		close(fd);
6904c87aefeSPatrick Mooney 	return (ptr);
6914c87aefeSPatrick Mooney }
6924c87aefeSPatrick Mooney 
693bf21cd93STycho Nightingale int
694bf21cd93STycho Nightingale vm_set_desc(struct vmctx *ctx, int vcpu, int reg,
695bf21cd93STycho Nightingale 	    uint64_t base, uint32_t limit, uint32_t access)
696bf21cd93STycho Nightingale {
697bf21cd93STycho Nightingale 	int error;
698bf21cd93STycho Nightingale 	struct vm_seg_desc vmsegdesc;
699bf21cd93STycho Nightingale 
700bf21cd93STycho Nightingale 	bzero(&vmsegdesc, sizeof(vmsegdesc));
701bf21cd93STycho Nightingale 	vmsegdesc.cpuid = vcpu;
702bf21cd93STycho Nightingale 	vmsegdesc.regnum = reg;
703bf21cd93STycho Nightingale 	vmsegdesc.desc.base = base;
704bf21cd93STycho Nightingale 	vmsegdesc.desc.limit = limit;
705bf21cd93STycho Nightingale 	vmsegdesc.desc.access = access;
706bf21cd93STycho Nightingale 
707bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
708bf21cd93STycho Nightingale 	return (error);
709bf21cd93STycho Nightingale }
710bf21cd93STycho Nightingale 
711bf21cd93STycho Nightingale int
712bf21cd93STycho Nightingale vm_get_desc(struct vmctx *ctx, int vcpu, int reg,
713bf21cd93STycho Nightingale 	    uint64_t *base, uint32_t *limit, uint32_t *access)
714bf21cd93STycho Nightingale {
715bf21cd93STycho Nightingale 	int error;
716bf21cd93STycho Nightingale 	struct vm_seg_desc vmsegdesc;
717bf21cd93STycho Nightingale 
718bf21cd93STycho Nightingale 	bzero(&vmsegdesc, sizeof(vmsegdesc));
719bf21cd93STycho Nightingale 	vmsegdesc.cpuid = vcpu;
720bf21cd93STycho Nightingale 	vmsegdesc.regnum = reg;
721bf21cd93STycho Nightingale 
722bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
723bf21cd93STycho Nightingale 	if (error == 0) {
724bf21cd93STycho Nightingale 		*base = vmsegdesc.desc.base;
725bf21cd93STycho Nightingale 		*limit = vmsegdesc.desc.limit;
726bf21cd93STycho Nightingale 		*access = vmsegdesc.desc.access;
727bf21cd93STycho Nightingale 	}
728bf21cd93STycho Nightingale 	return (error);
729bf21cd93STycho Nightingale }
730bf21cd93STycho Nightingale 
731bf21cd93STycho Nightingale int
732bf21cd93STycho Nightingale vm_get_seg_desc(struct vmctx *ctx, int vcpu, int reg, struct seg_desc *seg_desc)
733bf21cd93STycho Nightingale {
734bf21cd93STycho Nightingale 	int error;
735bf21cd93STycho Nightingale 
736bf21cd93STycho Nightingale 	error = vm_get_desc(ctx, vcpu, reg, &seg_desc->base, &seg_desc->limit,
737bf21cd93STycho Nightingale 	    &seg_desc->access);
738bf21cd93STycho Nightingale 	return (error);
739bf21cd93STycho Nightingale }
740bf21cd93STycho Nightingale 
741bf21cd93STycho Nightingale int
742bf21cd93STycho Nightingale vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
743bf21cd93STycho Nightingale {
744bf21cd93STycho Nightingale 	int error;
745bf21cd93STycho Nightingale 	struct vm_register vmreg;
746bf21cd93STycho Nightingale 
747bf21cd93STycho Nightingale 	bzero(&vmreg, sizeof(vmreg));
748bf21cd93STycho Nightingale 	vmreg.cpuid = vcpu;
749bf21cd93STycho Nightingale 	vmreg.regnum = reg;
750bf21cd93STycho Nightingale 	vmreg.regval = val;
751bf21cd93STycho Nightingale 
752bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
753bf21cd93STycho Nightingale 	return (error);
754bf21cd93STycho Nightingale }
755bf21cd93STycho Nightingale 
756bf21cd93STycho Nightingale int
757bf21cd93STycho Nightingale vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
758bf21cd93STycho Nightingale {
759bf21cd93STycho Nightingale 	int error;
760bf21cd93STycho Nightingale 	struct vm_register vmreg;
761bf21cd93STycho Nightingale 
762bf21cd93STycho Nightingale 	bzero(&vmreg, sizeof(vmreg));
763bf21cd93STycho Nightingale 	vmreg.cpuid = vcpu;
764bf21cd93STycho Nightingale 	vmreg.regnum = reg;
765bf21cd93STycho Nightingale 
766bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
767bf21cd93STycho Nightingale 	*ret_val = vmreg.regval;
768bf21cd93STycho Nightingale 	return (error);
769bf21cd93STycho Nightingale }
770bf21cd93STycho Nightingale 
7714c87aefeSPatrick Mooney int
7724c87aefeSPatrick Mooney vm_set_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
7734c87aefeSPatrick Mooney     const int *regnums, uint64_t *regvals)
7744c87aefeSPatrick Mooney {
7754c87aefeSPatrick Mooney 	int error;
7764c87aefeSPatrick Mooney 	struct vm_register_set vmregset;
7774c87aefeSPatrick Mooney 
7784c87aefeSPatrick Mooney 	bzero(&vmregset, sizeof(vmregset));
7794c87aefeSPatrick Mooney 	vmregset.cpuid = vcpu;
7804c87aefeSPatrick Mooney 	vmregset.count = count;
7814c87aefeSPatrick Mooney 	vmregset.regnums = regnums;
7824c87aefeSPatrick Mooney 	vmregset.regvals = regvals;
7834c87aefeSPatrick Mooney 
7844c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SET_REGISTER_SET, &vmregset);
7854c87aefeSPatrick Mooney 	return (error);
7864c87aefeSPatrick Mooney }
7874c87aefeSPatrick Mooney 
7884c87aefeSPatrick Mooney int
7894c87aefeSPatrick Mooney vm_get_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
7904c87aefeSPatrick Mooney     const int *regnums, uint64_t *regvals)
7914c87aefeSPatrick Mooney {
7924c87aefeSPatrick Mooney 	int error;
7934c87aefeSPatrick Mooney 	struct vm_register_set vmregset;
7944c87aefeSPatrick Mooney 
7954c87aefeSPatrick Mooney 	bzero(&vmregset, sizeof(vmregset));
7964c87aefeSPatrick Mooney 	vmregset.cpuid = vcpu;
7974c87aefeSPatrick Mooney 	vmregset.count = count;
7984c87aefeSPatrick Mooney 	vmregset.regnums = regnums;
7994c87aefeSPatrick Mooney 	vmregset.regvals = regvals;
8004c87aefeSPatrick Mooney 
8014c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_REGISTER_SET, &vmregset);
8024c87aefeSPatrick Mooney 	return (error);
8034c87aefeSPatrick Mooney }
8044c87aefeSPatrick Mooney 
805bf21cd93STycho Nightingale int
806e0c0d44eSPatrick Mooney vm_run(struct vmctx *ctx, int vcpu, const struct vm_entry *vm_entry,
807e0c0d44eSPatrick Mooney     struct vm_exit *vm_exit)
808bf21cd93STycho Nightingale {
809e0c0d44eSPatrick Mooney 	struct vm_entry entry;
810bf21cd93STycho Nightingale 
811e0c0d44eSPatrick Mooney 	bcopy(vm_entry, &entry, sizeof (entry));
812e0c0d44eSPatrick Mooney 	entry.cpuid = vcpu;
813e0c0d44eSPatrick Mooney 	entry.exit_data = vm_exit;
814bf21cd93STycho Nightingale 
815e0c0d44eSPatrick Mooney 	return (ioctl(ctx->fd, VM_RUN, &entry));
816bf21cd93STycho Nightingale }
817bf21cd93STycho Nightingale 
8184c87aefeSPatrick Mooney int
8194c87aefeSPatrick Mooney vm_suspend(struct vmctx *ctx, enum vm_suspend_how how)
820bf21cd93STycho Nightingale {
8214c87aefeSPatrick Mooney 	struct vm_suspend vmsuspend;
822bf21cd93STycho Nightingale 
8234c87aefeSPatrick Mooney 	bzero(&vmsuspend, sizeof(vmsuspend));
8244c87aefeSPatrick Mooney 	vmsuspend.how = how;
8254c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_SUSPEND, &vmsuspend));
8264c87aefeSPatrick Mooney }
827bf21cd93STycho Nightingale 
82852fac30eSPatrick Mooney #ifndef __FreeBSD__
82952fac30eSPatrick Mooney int
83052fac30eSPatrick Mooney vm_reinit(struct vmctx *ctx, uint64_t flags)
83152fac30eSPatrick Mooney {
83252fac30eSPatrick Mooney 	struct vm_reinit reinit = {
83352fac30eSPatrick Mooney 		.flags = flags
83452fac30eSPatrick Mooney 	};
83552fac30eSPatrick Mooney 
83652fac30eSPatrick Mooney 	return (ioctl(ctx->fd, VM_REINIT, &reinit));
83752fac30eSPatrick Mooney }
83852fac30eSPatrick Mooney #else
8394c87aefeSPatrick Mooney int
8404c87aefeSPatrick Mooney vm_reinit(struct vmctx *ctx)
8414c87aefeSPatrick Mooney {
8424c87aefeSPatrick Mooney 
8434c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_REINIT, 0));
844bf21cd93STycho Nightingale }
84552fac30eSPatrick Mooney #endif
846bf21cd93STycho Nightingale 
847bf21cd93STycho Nightingale int
848bf21cd93STycho Nightingale vm_inject_exception(struct vmctx *ctx, int vcpu, int vector, int errcode_valid,
849bf21cd93STycho Nightingale     uint32_t errcode, int restart_instruction)
850bf21cd93STycho Nightingale {
851bf21cd93STycho Nightingale 	struct vm_exception exc;
852bf21cd93STycho Nightingale 
853bf21cd93STycho Nightingale 	exc.cpuid = vcpu;
854bf21cd93STycho Nightingale 	exc.vector = vector;
855bf21cd93STycho Nightingale 	exc.error_code = errcode;
856bf21cd93STycho Nightingale 	exc.error_code_valid = errcode_valid;
857bf21cd93STycho Nightingale 	exc.restart_instruction = restart_instruction;
858bf21cd93STycho Nightingale 
859bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_INJECT_EXCEPTION, &exc));
860bf21cd93STycho Nightingale }
861bf21cd93STycho Nightingale 
862b58b977eSPatrick Mooney #ifndef __FreeBSD__
863b58b977eSPatrick Mooney void
864b58b977eSPatrick Mooney vm_inject_fault(struct vmctx *ctx, int vcpu, int vector, int errcode_valid,
865b58b977eSPatrick Mooney     int errcode)
866b58b977eSPatrick Mooney {
867b58b977eSPatrick Mooney 	int error;
868b58b977eSPatrick Mooney 	struct vm_exception exc;
869b58b977eSPatrick Mooney 
870b58b977eSPatrick Mooney 	exc.cpuid = vcpu;
871b58b977eSPatrick Mooney 	exc.vector = vector;
872b58b977eSPatrick Mooney 	exc.error_code = errcode;
873b58b977eSPatrick Mooney 	exc.error_code_valid = errcode_valid;
874b58b977eSPatrick Mooney 	exc.restart_instruction = 1;
875b58b977eSPatrick Mooney 	error = ioctl(ctx->fd, VM_INJECT_EXCEPTION, &exc);
876b58b977eSPatrick Mooney 
877b58b977eSPatrick Mooney 	assert(error == 0);
878b58b977eSPatrick Mooney }
879b58b977eSPatrick Mooney #endif /* __FreeBSD__ */
880b58b977eSPatrick Mooney 
881bf21cd93STycho Nightingale int
882*b0de25cbSAndy Fiddaman vm_apicid2vcpu(struct vmctx *ctx __unused, int apicid)
883bf21cd93STycho Nightingale {
884bf21cd93STycho Nightingale 	/*
885bf21cd93STycho Nightingale 	 * The apic id associated with the 'vcpu' has the same numerical value
886bf21cd93STycho Nightingale 	 * as the 'vcpu' itself.
887bf21cd93STycho Nightingale 	 */
888bf21cd93STycho Nightingale 	return (apicid);
889bf21cd93STycho Nightingale }
890bf21cd93STycho Nightingale 
891bf21cd93STycho Nightingale int
892bf21cd93STycho Nightingale vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
893bf21cd93STycho Nightingale {
894bf21cd93STycho Nightingale 	struct vm_lapic_irq vmirq;
895bf21cd93STycho Nightingale 
896bf21cd93STycho Nightingale 	bzero(&vmirq, sizeof(vmirq));
897bf21cd93STycho Nightingale 	vmirq.cpuid = vcpu;
898bf21cd93STycho Nightingale 	vmirq.vector = vector;
899bf21cd93STycho Nightingale 
900bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
901bf21cd93STycho Nightingale }
902bf21cd93STycho Nightingale 
903bf21cd93STycho Nightingale int
904bf21cd93STycho Nightingale vm_lapic_local_irq(struct vmctx *ctx, int vcpu, int vector)
905bf21cd93STycho Nightingale {
906bf21cd93STycho Nightingale 	struct vm_lapic_irq vmirq;
907bf21cd93STycho Nightingale 
908bf21cd93STycho Nightingale 	bzero(&vmirq, sizeof(vmirq));
909bf21cd93STycho Nightingale 	vmirq.cpuid = vcpu;
910bf21cd93STycho Nightingale 	vmirq.vector = vector;
911bf21cd93STycho Nightingale 
912bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_LOCAL_IRQ, &vmirq));
913bf21cd93STycho Nightingale }
914bf21cd93STycho Nightingale 
915bf21cd93STycho Nightingale int
916bf21cd93STycho Nightingale vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg)
917bf21cd93STycho Nightingale {
918bf21cd93STycho Nightingale 	struct vm_lapic_msi vmmsi;
919bf21cd93STycho Nightingale 
920bf21cd93STycho Nightingale 	bzero(&vmmsi, sizeof(vmmsi));
921bf21cd93STycho Nightingale 	vmmsi.addr = addr;
922bf21cd93STycho Nightingale 	vmmsi.msg = msg;
923bf21cd93STycho Nightingale 
924bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi));
925bf21cd93STycho Nightingale }
926bf21cd93STycho Nightingale 
927bf21cd93STycho Nightingale int
928bf21cd93STycho Nightingale vm_ioapic_assert_irq(struct vmctx *ctx, int irq)
929bf21cd93STycho Nightingale {
930bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
931bf21cd93STycho Nightingale 
932bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
933bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
934bf21cd93STycho Nightingale 
935bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
936bf21cd93STycho Nightingale }
937bf21cd93STycho Nightingale 
938bf21cd93STycho Nightingale int
939bf21cd93STycho Nightingale vm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
940bf21cd93STycho Nightingale {
941bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
942bf21cd93STycho Nightingale 
943bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
944bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
945bf21cd93STycho Nightingale 
946bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
947bf21cd93STycho Nightingale }
948bf21cd93STycho Nightingale 
949bf21cd93STycho Nightingale int
950bf21cd93STycho Nightingale vm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
951bf21cd93STycho Nightingale {
952bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
953bf21cd93STycho Nightingale 
954bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
955bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
956bf21cd93STycho Nightingale 
957bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
958bf21cd93STycho Nightingale }
959bf21cd93STycho Nightingale 
960bf21cd93STycho Nightingale int
961bf21cd93STycho Nightingale vm_ioapic_pincount(struct vmctx *ctx, int *pincount)
962bf21cd93STycho Nightingale {
963bf21cd93STycho Nightingale 
964bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
965bf21cd93STycho Nightingale }
966bf21cd93STycho Nightingale 
967154972afSPatrick Mooney int
968154972afSPatrick Mooney vm_readwrite_kernemu_device(struct vmctx *ctx, int vcpu, vm_paddr_t gpa,
969154972afSPatrick Mooney     bool write, int size, uint64_t *value)
970154972afSPatrick Mooney {
971154972afSPatrick Mooney 	struct vm_readwrite_kernemu_device irp = {
972154972afSPatrick Mooney 		.vcpuid = vcpu,
973154972afSPatrick Mooney 		.access_width = fls(size) - 1,
974154972afSPatrick Mooney 		.gpa = gpa,
975154972afSPatrick Mooney 		.value = write ? *value : ~0ul,
976154972afSPatrick Mooney 	};
977154972afSPatrick Mooney 	long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV);
978154972afSPatrick Mooney 	int rc;
979154972afSPatrick Mooney 
980154972afSPatrick Mooney 	rc = ioctl(ctx->fd, cmd, &irp);
981154972afSPatrick Mooney 	if (rc == 0 && !write)
982154972afSPatrick Mooney 		*value = irp.value;
983154972afSPatrick Mooney 	return (rc);
984154972afSPatrick Mooney }
985154972afSPatrick Mooney 
986bf21cd93STycho Nightingale int
987bf21cd93STycho Nightingale vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
988bf21cd93STycho Nightingale {
989bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
990bf21cd93STycho Nightingale 
991bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
992bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
993bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
994bf21cd93STycho Nightingale 
995bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq));
996bf21cd93STycho Nightingale }
997bf21cd93STycho Nightingale 
998bf21cd93STycho Nightingale int
999bf21cd93STycho Nightingale vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
1000bf21cd93STycho Nightingale {
1001bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
1002bf21cd93STycho Nightingale 
1003bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
1004bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
1005bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
1006bf21cd93STycho Nightingale 
1007bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq));
1008bf21cd93STycho Nightingale }
1009bf21cd93STycho Nightingale 
1010bf21cd93STycho Nightingale int
1011bf21cd93STycho Nightingale vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
1012bf21cd93STycho Nightingale {
1013bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
1014bf21cd93STycho Nightingale 
1015bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
1016bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
1017bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
1018bf21cd93STycho Nightingale 
1019bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq));
1020bf21cd93STycho Nightingale }
1021bf21cd93STycho Nightingale 
1022bf21cd93STycho Nightingale int
1023bf21cd93STycho Nightingale vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq,
1024bf21cd93STycho Nightingale     enum vm_intr_trigger trigger)
1025bf21cd93STycho Nightingale {
1026bf21cd93STycho Nightingale 	struct vm_isa_irq_trigger isa_irq_trigger;
1027bf21cd93STycho Nightingale 
1028bf21cd93STycho Nightingale 	bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger));
1029bf21cd93STycho Nightingale 	isa_irq_trigger.atpic_irq = atpic_irq;
1030bf21cd93STycho Nightingale 	isa_irq_trigger.trigger = trigger;
1031bf21cd93STycho Nightingale 
1032bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger));
1033bf21cd93STycho Nightingale }
1034bf21cd93STycho Nightingale 
1035bf21cd93STycho Nightingale int
1036bf21cd93STycho Nightingale vm_inject_nmi(struct vmctx *ctx, int vcpu)
1037bf21cd93STycho Nightingale {
1038bf21cd93STycho Nightingale 	struct vm_nmi vmnmi;
1039bf21cd93STycho Nightingale 
1040bf21cd93STycho Nightingale 	bzero(&vmnmi, sizeof(vmnmi));
1041bf21cd93STycho Nightingale 	vmnmi.cpuid = vcpu;
1042bf21cd93STycho Nightingale 
1043bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
1044bf21cd93STycho Nightingale }
1045bf21cd93STycho Nightingale 
1046154972afSPatrick Mooney static const char *capstrmap[] = {
1047154972afSPatrick Mooney 	[VM_CAP_HALT_EXIT]  = "hlt_exit",
1048154972afSPatrick Mooney 	[VM_CAP_MTRAP_EXIT] = "mtrap_exit",
1049154972afSPatrick Mooney 	[VM_CAP_PAUSE_EXIT] = "pause_exit",
1050c3ae3afaSPatrick Mooney #ifdef __FreeBSD__
1051154972afSPatrick Mooney 	[VM_CAP_UNRESTRICTED_GUEST] = "unrestricted_guest",
1052c3ae3afaSPatrick Mooney #endif
1053154972afSPatrick Mooney 	[VM_CAP_ENABLE_INVPCID] = "enable_invpcid",
1054154972afSPatrick Mooney 	[VM_CAP_BPT_EXIT] = "bpt_exit",
1055bf21cd93STycho Nightingale };
1056bf21cd93STycho Nightingale 
1057bf21cd93STycho Nightingale int
1058bf21cd93STycho Nightingale vm_capability_name2type(const char *capname)
1059bf21cd93STycho Nightingale {
1060bf21cd93STycho Nightingale 	int i;
1061bf21cd93STycho Nightingale 
1062*b0de25cbSAndy Fiddaman 	for (i = 0; i < (int)nitems(capstrmap); i++) {
1063154972afSPatrick Mooney 		if (strcmp(capstrmap[i], capname) == 0)
1064154972afSPatrick Mooney 			return (i);
1065bf21cd93STycho Nightingale 	}
1066bf21cd93STycho Nightingale 
1067bf21cd93STycho Nightingale 	return (-1);
1068bf21cd93STycho Nightingale }
1069bf21cd93STycho Nightingale 
1070bf21cd93STycho Nightingale const char *
1071bf21cd93STycho Nightingale vm_capability_type2name(int type)
1072bf21cd93STycho Nightingale {
1073*b0de25cbSAndy Fiddaman 	if (type >= 0 && type < (int)nitems(capstrmap))
1074154972afSPatrick Mooney 		return (capstrmap[type]);
1075bf21cd93STycho Nightingale 
1076bf21cd93STycho Nightingale 	return (NULL);
1077bf21cd93STycho Nightingale }
1078bf21cd93STycho Nightingale 
1079bf21cd93STycho Nightingale int
1080bf21cd93STycho Nightingale vm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
1081bf21cd93STycho Nightingale 		  int *retval)
1082bf21cd93STycho Nightingale {
1083bf21cd93STycho Nightingale 	int error;
1084bf21cd93STycho Nightingale 	struct vm_capability vmcap;
1085bf21cd93STycho Nightingale 
1086bf21cd93STycho Nightingale 	bzero(&vmcap, sizeof(vmcap));
1087bf21cd93STycho Nightingale 	vmcap.cpuid = vcpu;
1088bf21cd93STycho Nightingale 	vmcap.captype = cap;
1089bf21cd93STycho Nightingale 
1090bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
1091bf21cd93STycho Nightingale 	*retval = vmcap.capval;
1092bf21cd93STycho Nightingale 	return (error);
1093bf21cd93STycho Nightingale }
1094bf21cd93STycho Nightingale 
1095bf21cd93STycho Nightingale int
1096bf21cd93STycho Nightingale vm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
1097bf21cd93STycho Nightingale {
1098bf21cd93STycho Nightingale 	struct vm_capability vmcap;
1099bf21cd93STycho Nightingale 
1100bf21cd93STycho Nightingale 	bzero(&vmcap, sizeof(vmcap));
1101bf21cd93STycho Nightingale 	vmcap.cpuid = vcpu;
1102bf21cd93STycho Nightingale 	vmcap.captype = cap;
1103bf21cd93STycho Nightingale 	vmcap.capval = val;
11044c87aefeSPatrick Mooney 
1105bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
1106bf21cd93STycho Nightingale }
1107bf21cd93STycho Nightingale 
1108eb9a1df2SHans Rosenfeld #ifdef __FreeBSD__
1109bf21cd93STycho Nightingale int
1110bf21cd93STycho Nightingale vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1111bf21cd93STycho Nightingale {
1112bf21cd93STycho Nightingale 	struct vm_pptdev pptdev;
1113bf21cd93STycho Nightingale 
1114bf21cd93STycho Nightingale 	bzero(&pptdev, sizeof(pptdev));
1115bf21cd93STycho Nightingale 	pptdev.bus = bus;
1116bf21cd93STycho Nightingale 	pptdev.slot = slot;
1117bf21cd93STycho Nightingale 	pptdev.func = func;
1118bf21cd93STycho Nightingale 
1119bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
1120bf21cd93STycho Nightingale }
1121bf21cd93STycho Nightingale 
1122bf21cd93STycho Nightingale int
1123bf21cd93STycho Nightingale vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1124bf21cd93STycho Nightingale {
1125bf21cd93STycho Nightingale 	struct vm_pptdev pptdev;
1126bf21cd93STycho Nightingale 
1127bf21cd93STycho Nightingale 	bzero(&pptdev, sizeof(pptdev));
1128bf21cd93STycho Nightingale 	pptdev.bus = bus;
1129bf21cd93STycho Nightingale 	pptdev.slot = slot;
1130bf21cd93STycho Nightingale 	pptdev.func = func;
1131bf21cd93STycho Nightingale 
1132bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
1133bf21cd93STycho Nightingale }
1134bf21cd93STycho Nightingale 
1135bf21cd93STycho Nightingale int
1136bf21cd93STycho Nightingale vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
1137bf21cd93STycho Nightingale 		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
1138bf21cd93STycho Nightingale {
1139bf21cd93STycho Nightingale 	struct vm_pptdev_mmio pptmmio;
1140bf21cd93STycho Nightingale 
1141bf21cd93STycho Nightingale 	bzero(&pptmmio, sizeof(pptmmio));
1142bf21cd93STycho Nightingale 	pptmmio.bus = bus;
1143bf21cd93STycho Nightingale 	pptmmio.slot = slot;
1144bf21cd93STycho Nightingale 	pptmmio.func = func;
1145bf21cd93STycho Nightingale 	pptmmio.gpa = gpa;
1146bf21cd93STycho Nightingale 	pptmmio.len = len;
1147bf21cd93STycho Nightingale 	pptmmio.hpa = hpa;
1148bf21cd93STycho Nightingale 
1149bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
1150bf21cd93STycho Nightingale }
1151bf21cd93STycho Nightingale 
11522b948146SAndy Fiddaman int
11532b948146SAndy Fiddaman vm_unmap_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
11542b948146SAndy Fiddaman 		     vm_paddr_t gpa, size_t len)
11552b948146SAndy Fiddaman {
11562b948146SAndy Fiddaman 	struct vm_pptdev_mmio pptmmio;
11572b948146SAndy Fiddaman 
11582b948146SAndy Fiddaman 	bzero(&pptmmio, sizeof(pptmmio));
11592b948146SAndy Fiddaman 	pptmmio.bus = bus;
11602b948146SAndy Fiddaman 	pptmmio.slot = slot;
11612b948146SAndy Fiddaman 	pptmmio.func = func;
11622b948146SAndy Fiddaman 	pptmmio.gpa = gpa;
11632b948146SAndy Fiddaman 	pptmmio.len = len;
11642b948146SAndy Fiddaman 
11652b948146SAndy Fiddaman 	return (ioctl(ctx->fd, VM_UNMAP_PPTDEV_MMIO, &pptmmio));
11662b948146SAndy Fiddaman }
11672b948146SAndy Fiddaman 
1168bf21cd93STycho Nightingale int
1169bf21cd93STycho Nightingale vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
1170bf21cd93STycho Nightingale     uint64_t addr, uint64_t msg, int numvec)
1171bf21cd93STycho Nightingale {
1172bf21cd93STycho Nightingale 	struct vm_pptdev_msi pptmsi;
1173bf21cd93STycho Nightingale 
1174bf21cd93STycho Nightingale 	bzero(&pptmsi, sizeof(pptmsi));
1175bf21cd93STycho Nightingale 	pptmsi.vcpu = vcpu;
1176bf21cd93STycho Nightingale 	pptmsi.bus = bus;
1177bf21cd93STycho Nightingale 	pptmsi.slot = slot;
1178bf21cd93STycho Nightingale 	pptmsi.func = func;
1179bf21cd93STycho Nightingale 	pptmsi.msg = msg;
1180bf21cd93STycho Nightingale 	pptmsi.addr = addr;
1181bf21cd93STycho Nightingale 	pptmsi.numvec = numvec;
1182bf21cd93STycho Nightingale 
1183bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
1184bf21cd93STycho Nightingale }
1185bf21cd93STycho Nightingale 
1186eb9a1df2SHans Rosenfeld int
1187bf21cd93STycho Nightingale vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
1188bf21cd93STycho Nightingale     int idx, uint64_t addr, uint64_t msg, uint32_t vector_control)
1189bf21cd93STycho Nightingale {
1190bf21cd93STycho Nightingale 	struct vm_pptdev_msix pptmsix;
1191bf21cd93STycho Nightingale 
1192bf21cd93STycho Nightingale 	bzero(&pptmsix, sizeof(pptmsix));
1193bf21cd93STycho Nightingale 	pptmsix.vcpu = vcpu;
1194bf21cd93STycho Nightingale 	pptmsix.bus = bus;
1195bf21cd93STycho Nightingale 	pptmsix.slot = slot;
1196bf21cd93STycho Nightingale 	pptmsix.func = func;
1197bf21cd93STycho Nightingale 	pptmsix.idx = idx;
1198bf21cd93STycho Nightingale 	pptmsix.msg = msg;
1199bf21cd93STycho Nightingale 	pptmsix.addr = addr;
1200bf21cd93STycho Nightingale 	pptmsix.vector_control = vector_control;
1201bf21cd93STycho Nightingale 
1202bf21cd93STycho Nightingale 	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
1203bf21cd93STycho Nightingale }
1204bf21cd93STycho Nightingale 
1205eb9a1df2SHans Rosenfeld int
1206eb9a1df2SHans Rosenfeld vm_get_pptdev_limits(struct vmctx *ctx, int bus, int slot, int func,
1207eb9a1df2SHans Rosenfeld     int *msi_limit, int *msix_limit)
1208eb9a1df2SHans Rosenfeld {
1209eb9a1df2SHans Rosenfeld 	struct vm_pptdev_limits pptlimits;
1210eb9a1df2SHans Rosenfeld 	int error;
1211eb9a1df2SHans Rosenfeld 
1212eb9a1df2SHans Rosenfeld 	bzero(&pptlimits, sizeof (pptlimits));
1213eb9a1df2SHans Rosenfeld 	pptlimits.bus = bus;
1214eb9a1df2SHans Rosenfeld 	pptlimits.slot = slot;
1215eb9a1df2SHans Rosenfeld 	pptlimits.func = func;
1216eb9a1df2SHans Rosenfeld 
1217eb9a1df2SHans Rosenfeld 	error = ioctl(ctx->fd, VM_GET_PPTDEV_LIMITS, &pptlimits);
1218eb9a1df2SHans Rosenfeld 
1219eb9a1df2SHans Rosenfeld 	*msi_limit = pptlimits.msi_limit;
1220eb9a1df2SHans Rosenfeld 	*msix_limit = pptlimits.msix_limit;
1221eb9a1df2SHans Rosenfeld 
1222eb9a1df2SHans Rosenfeld 	return (error);
1223eb9a1df2SHans Rosenfeld }
12246960cd89SAndy Fiddaman 
12256960cd89SAndy Fiddaman int
12266960cd89SAndy Fiddaman vm_disable_pptdev_msix(struct vmctx *ctx, int bus, int slot, int func)
12276960cd89SAndy Fiddaman {
12286960cd89SAndy Fiddaman 	struct vm_pptdev ppt;
12296960cd89SAndy Fiddaman 
12306960cd89SAndy Fiddaman 	bzero(&ppt, sizeof(ppt));
12316960cd89SAndy Fiddaman 	ppt.bus = bus;
12326960cd89SAndy Fiddaman 	ppt.slot = slot;
12336960cd89SAndy Fiddaman 	ppt.func = func;
12346960cd89SAndy Fiddaman 
12356960cd89SAndy Fiddaman 	return ioctl(ctx->fd, VM_PPTDEV_DISABLE_MSIX, &ppt);
12366960cd89SAndy Fiddaman }
12376960cd89SAndy Fiddaman 
1238eb9a1df2SHans Rosenfeld #else /* __FreeBSD__ */
12396960cd89SAndy Fiddaman 
1240eb9a1df2SHans Rosenfeld int
1241eb9a1df2SHans Rosenfeld vm_assign_pptdev(struct vmctx *ctx, int pptfd)
1242eb9a1df2SHans Rosenfeld {
1243eb9a1df2SHans Rosenfeld 	struct vm_pptdev pptdev;
1244eb9a1df2SHans Rosenfeld 
1245eb9a1df2SHans Rosenfeld 	pptdev.pptfd = pptfd;
1246eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
1247eb9a1df2SHans Rosenfeld }
1248eb9a1df2SHans Rosenfeld 
1249eb9a1df2SHans Rosenfeld int
1250eb9a1df2SHans Rosenfeld vm_unassign_pptdev(struct vmctx *ctx, int pptfd)
1251eb9a1df2SHans Rosenfeld {
1252eb9a1df2SHans Rosenfeld 	struct vm_pptdev pptdev;
1253eb9a1df2SHans Rosenfeld 
1254eb9a1df2SHans Rosenfeld 	pptdev.pptfd = pptfd;
1255eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
1256eb9a1df2SHans Rosenfeld }
1257eb9a1df2SHans Rosenfeld 
1258eb9a1df2SHans Rosenfeld int
1259eb9a1df2SHans Rosenfeld vm_map_pptdev_mmio(struct vmctx *ctx, int pptfd, vm_paddr_t gpa, size_t len,
1260eb9a1df2SHans Rosenfeld     vm_paddr_t hpa)
1261eb9a1df2SHans Rosenfeld {
1262eb9a1df2SHans Rosenfeld 	struct vm_pptdev_mmio pptmmio;
1263eb9a1df2SHans Rosenfeld 
1264eb9a1df2SHans Rosenfeld 	pptmmio.pptfd = pptfd;
1265eb9a1df2SHans Rosenfeld 	pptmmio.gpa = gpa;
1266eb9a1df2SHans Rosenfeld 	pptmmio.len = len;
1267eb9a1df2SHans Rosenfeld 	pptmmio.hpa = hpa;
1268eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
1269eb9a1df2SHans Rosenfeld }
1270eb9a1df2SHans Rosenfeld 
12712b948146SAndy Fiddaman int
12722b948146SAndy Fiddaman vm_unmap_pptdev_mmio(struct vmctx *ctx, int pptfd, vm_paddr_t gpa, size_t len)
12732b948146SAndy Fiddaman {
12742b948146SAndy Fiddaman 	struct vm_pptdev_mmio pptmmio;
12752b948146SAndy Fiddaman 
12762b948146SAndy Fiddaman 	bzero(&pptmmio, sizeof(pptmmio));
12772b948146SAndy Fiddaman 	pptmmio.pptfd = pptfd;
12782b948146SAndy Fiddaman 	pptmmio.gpa = gpa;
12792b948146SAndy Fiddaman 	pptmmio.len = len;
12802b948146SAndy Fiddaman 
12812b948146SAndy Fiddaman 	return (ioctl(ctx->fd, VM_UNMAP_PPTDEV_MMIO, &pptmmio));
12822b948146SAndy Fiddaman }
12832b948146SAndy Fiddaman 
1284eb9a1df2SHans Rosenfeld int
1285eb9a1df2SHans Rosenfeld vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int pptfd, uint64_t addr,
1286eb9a1df2SHans Rosenfeld     uint64_t msg, int numvec)
1287eb9a1df2SHans Rosenfeld {
1288eb9a1df2SHans Rosenfeld 	struct vm_pptdev_msi pptmsi;
1289eb9a1df2SHans Rosenfeld 
1290eb9a1df2SHans Rosenfeld 	pptmsi.vcpu = vcpu;
1291eb9a1df2SHans Rosenfeld 	pptmsi.pptfd = pptfd;
1292eb9a1df2SHans Rosenfeld 	pptmsi.msg = msg;
1293eb9a1df2SHans Rosenfeld 	pptmsi.addr = addr;
1294eb9a1df2SHans Rosenfeld 	pptmsi.numvec = numvec;
1295eb9a1df2SHans Rosenfeld 	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
1296eb9a1df2SHans Rosenfeld }
1297eb9a1df2SHans Rosenfeld 
1298eb9a1df2SHans Rosenfeld int
1299eb9a1df2SHans Rosenfeld vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int pptfd, int idx,
1300eb9a1df2SHans Rosenfeld     uint64_t addr, uint64_t msg, uint32_t vector_control)
1301eb9a1df2SHans Rosenfeld {
1302eb9a1df2SHans Rosenfeld 	struct vm_pptdev_msix pptmsix;
1303eb9a1df2SHans Rosenfeld 
1304eb9a1df2SHans Rosenfeld 	pptmsix.vcpu = vcpu;
1305eb9a1df2SHans Rosenfeld 	pptmsix.pptfd = pptfd;
1306eb9a1df2SHans Rosenfeld 	pptmsix.idx = idx;
1307eb9a1df2SHans Rosenfeld 	pptmsix.msg = msg;
1308eb9a1df2SHans Rosenfeld 	pptmsix.addr = addr;
1309eb9a1df2SHans Rosenfeld 	pptmsix.vector_control = vector_control;
1310eb9a1df2SHans Rosenfeld 	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
1311eb9a1df2SHans Rosenfeld }
1312eb9a1df2SHans Rosenfeld 
1313eb9a1df2SHans Rosenfeld int
1314eb9a1df2SHans Rosenfeld vm_get_pptdev_limits(struct vmctx *ctx, int pptfd, int *msi_limit,
1315eb9a1df2SHans Rosenfeld     int *msix_limit)
1316eb9a1df2SHans Rosenfeld {
1317eb9a1df2SHans Rosenfeld 	struct vm_pptdev_limits pptlimits;
1318eb9a1df2SHans Rosenfeld 	int error;
1319eb9a1df2SHans Rosenfeld 
1320eb9a1df2SHans Rosenfeld 	bzero(&pptlimits, sizeof (pptlimits));
1321eb9a1df2SHans Rosenfeld 	pptlimits.pptfd = pptfd;
1322eb9a1df2SHans Rosenfeld 	error = ioctl(ctx->fd, VM_GET_PPTDEV_LIMITS, &pptlimits);
1323eb9a1df2SHans Rosenfeld 
1324eb9a1df2SHans Rosenfeld 	*msi_limit = pptlimits.msi_limit;
1325eb9a1df2SHans Rosenfeld 	*msix_limit = pptlimits.msix_limit;
1326eb9a1df2SHans Rosenfeld 	return (error);
1327eb9a1df2SHans Rosenfeld }
13286960cd89SAndy Fiddaman 
13296960cd89SAndy Fiddaman int
13306960cd89SAndy Fiddaman vm_disable_pptdev_msix(struct vmctx *ctx, int pptfd)
13316960cd89SAndy Fiddaman {
13326960cd89SAndy Fiddaman 	struct vm_pptdev pptdev;
13336960cd89SAndy Fiddaman 
13346960cd89SAndy Fiddaman 	pptdev.pptfd = pptfd;
13356960cd89SAndy Fiddaman 	return (ioctl(ctx->fd, VM_PPTDEV_DISABLE_MSIX, &pptdev));
13366960cd89SAndy Fiddaman }
1337eb9a1df2SHans Rosenfeld #endif /* __FreeBSD__ */
1338eb9a1df2SHans Rosenfeld 
1339bf21cd93STycho Nightingale uint64_t *
1340bf21cd93STycho Nightingale vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
1341bf21cd93STycho Nightingale 	     int *ret_entries)
1342bf21cd93STycho Nightingale {
1343bf21cd93STycho Nightingale 	int error;
1344bf21cd93STycho Nightingale 
1345bf21cd93STycho Nightingale 	static struct vm_stats vmstats;
1346bf21cd93STycho Nightingale 
1347bf21cd93STycho Nightingale 	vmstats.cpuid = vcpu;
1348bf21cd93STycho Nightingale 
13494c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_STATS_IOC, &vmstats);
1350bf21cd93STycho Nightingale 	if (error == 0) {
1351bf21cd93STycho Nightingale 		if (ret_entries)
1352bf21cd93STycho Nightingale 			*ret_entries = vmstats.num_entries;
1353bf21cd93STycho Nightingale 		if (ret_tv)
1354bf21cd93STycho Nightingale 			*ret_tv = vmstats.tv;
1355bf21cd93STycho Nightingale 		return (vmstats.statbuf);
1356bf21cd93STycho Nightingale 	} else
1357bf21cd93STycho Nightingale 		return (NULL);
1358bf21cd93STycho Nightingale }
1359bf21cd93STycho Nightingale 
1360bf21cd93STycho Nightingale const char *
1361bf21cd93STycho Nightingale vm_get_stat_desc(struct vmctx *ctx, int index)
1362bf21cd93STycho Nightingale {
1363bf21cd93STycho Nightingale 	static struct vm_stat_desc statdesc;
1364bf21cd93STycho Nightingale 
1365bf21cd93STycho Nightingale 	statdesc.index = index;
1366bf21cd93STycho Nightingale 	if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
1367bf21cd93STycho Nightingale 		return (statdesc.desc);
1368bf21cd93STycho Nightingale 	else
1369bf21cd93STycho Nightingale 		return (NULL);
1370bf21cd93STycho Nightingale }
1371bf21cd93STycho Nightingale 
1372bf21cd93STycho Nightingale int
1373bf21cd93STycho Nightingale vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *state)
1374bf21cd93STycho Nightingale {
1375bf21cd93STycho Nightingale 	int error;
1376bf21cd93STycho Nightingale 	struct vm_x2apic x2apic;
1377bf21cd93STycho Nightingale 
1378bf21cd93STycho Nightingale 	bzero(&x2apic, sizeof(x2apic));
1379bf21cd93STycho Nightingale 	x2apic.cpuid = vcpu;
1380bf21cd93STycho Nightingale 
1381bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_X2APIC_STATE, &x2apic);
1382bf21cd93STycho Nightingale 	*state = x2apic.state;
1383bf21cd93STycho Nightingale 	return (error);
1384bf21cd93STycho Nightingale }
1385bf21cd93STycho Nightingale 
1386bf21cd93STycho Nightingale int
1387bf21cd93STycho Nightingale vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state state)
1388bf21cd93STycho Nightingale {
1389bf21cd93STycho Nightingale 	int error;
1390bf21cd93STycho Nightingale 	struct vm_x2apic x2apic;
1391bf21cd93STycho Nightingale 
1392bf21cd93STycho Nightingale 	bzero(&x2apic, sizeof(x2apic));
1393bf21cd93STycho Nightingale 	x2apic.cpuid = vcpu;
1394bf21cd93STycho Nightingale 	x2apic.state = state;
1395bf21cd93STycho Nightingale 
1396bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_X2APIC_STATE, &x2apic);
1397bf21cd93STycho Nightingale 
1398bf21cd93STycho Nightingale 	return (error);
1399bf21cd93STycho Nightingale }
1400bf21cd93STycho Nightingale 
14012606939dSPatrick Mooney #ifndef __FreeBSD__
14022606939dSPatrick Mooney int
14032606939dSPatrick Mooney vcpu_reset(struct vmctx *vmctx, int vcpu)
14042606939dSPatrick Mooney {
14052606939dSPatrick Mooney 	struct vm_vcpu_reset vvr;
14062606939dSPatrick Mooney 
14072606939dSPatrick Mooney 	vvr.vcpuid = vcpu;
14082606939dSPatrick Mooney 	vvr.kind = VRK_RESET;
14092606939dSPatrick Mooney 
14102606939dSPatrick Mooney 	return (ioctl(vmctx->fd, VM_RESET_CPU, &vvr));
14112606939dSPatrick Mooney }
14122606939dSPatrick Mooney #else /* __FreeBSD__ */
1413bf21cd93STycho Nightingale /*
1414bf21cd93STycho Nightingale  * From Intel Vol 3a:
1415bf21cd93STycho Nightingale  * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
1416bf21cd93STycho Nightingale  */
1417bf21cd93STycho Nightingale int
1418bf21cd93STycho Nightingale vcpu_reset(struct vmctx *vmctx, int vcpu)
1419bf21cd93STycho Nightingale {
1420bf21cd93STycho Nightingale 	int error;
1421bf21cd93STycho Nightingale 	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
1422bf21cd93STycho Nightingale 	uint32_t desc_access, desc_limit;
1423bf21cd93STycho Nightingale 	uint16_t sel;
1424bf21cd93STycho Nightingale 
1425bf21cd93STycho Nightingale 	zero = 0;
1426bf21cd93STycho Nightingale 
1427bf21cd93STycho Nightingale 	rflags = 0x2;
1428bf21cd93STycho Nightingale 	error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
1429bf21cd93STycho Nightingale 	if (error)
1430bf21cd93STycho Nightingale 		goto done;
1431bf21cd93STycho Nightingale 
1432bf21cd93STycho Nightingale 	rip = 0xfff0;
1433bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
1434bf21cd93STycho Nightingale 		goto done;
1435bf21cd93STycho Nightingale 
1436bf21cd93STycho Nightingale 	cr0 = CR0_NE;
1437bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
1438bf21cd93STycho Nightingale 		goto done;
1439bf21cd93STycho Nightingale 
1440bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0)
1441bf21cd93STycho Nightingale 		goto done;
1442bf21cd93STycho Nightingale 
1443bf21cd93STycho Nightingale 	cr4 = 0;
1444bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
1445bf21cd93STycho Nightingale 		goto done;
1446bf21cd93STycho Nightingale 
1447bf21cd93STycho Nightingale 	/*
1448bf21cd93STycho Nightingale 	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
1449bf21cd93STycho Nightingale 	 */
1450bf21cd93STycho Nightingale 	desc_base = 0xffff0000;
1451bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1452bf21cd93STycho Nightingale 	desc_access = 0x0093;
1453bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
1454bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1455bf21cd93STycho Nightingale 	if (error)
1456bf21cd93STycho Nightingale 		goto done;
1457bf21cd93STycho Nightingale 
1458bf21cd93STycho Nightingale 	sel = 0xf000;
1459bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, sel)) != 0)
1460bf21cd93STycho Nightingale 		goto done;
1461bf21cd93STycho Nightingale 
1462bf21cd93STycho Nightingale 	/*
1463bf21cd93STycho Nightingale 	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
1464bf21cd93STycho Nightingale 	 */
1465bf21cd93STycho Nightingale 	desc_base = 0;
1466bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1467bf21cd93STycho Nightingale 	desc_access = 0x0093;
1468bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
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_DS,
1474bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1475bf21cd93STycho Nightingale 	if (error)
1476bf21cd93STycho Nightingale 		goto done;
1477bf21cd93STycho Nightingale 
1478bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
1479bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1480bf21cd93STycho Nightingale 	if (error)
1481bf21cd93STycho Nightingale 		goto done;
1482bf21cd93STycho Nightingale 
1483bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
1484bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1485bf21cd93STycho Nightingale 	if (error)
1486bf21cd93STycho Nightingale 		goto done;
1487bf21cd93STycho Nightingale 
1488bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
1489bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1490bf21cd93STycho Nightingale 	if (error)
1491bf21cd93STycho Nightingale 		goto done;
1492bf21cd93STycho Nightingale 
1493bf21cd93STycho Nightingale 	sel = 0;
1494bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, sel)) != 0)
1495bf21cd93STycho Nightingale 		goto done;
1496bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, sel)) != 0)
1497bf21cd93STycho Nightingale 		goto done;
1498bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, sel)) != 0)
1499bf21cd93STycho Nightingale 		goto done;
1500bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, sel)) != 0)
1501bf21cd93STycho Nightingale 		goto done;
1502bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0)
1503bf21cd93STycho Nightingale 		goto done;
1504bf21cd93STycho Nightingale 
1505bf21cd93STycho Nightingale 	/* General purpose registers */
1506bf21cd93STycho Nightingale 	rdx = 0xf00;
1507bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0)
1508bf21cd93STycho Nightingale 		goto done;
1509bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBX, zero)) != 0)
1510bf21cd93STycho Nightingale 		goto done;
1511bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RCX, zero)) != 0)
1512bf21cd93STycho Nightingale 		goto done;
1513bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
1514bf21cd93STycho Nightingale 		goto done;
1515bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSI, zero)) != 0)
1516bf21cd93STycho Nightingale 		goto done;
1517bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDI, zero)) != 0)
1518bf21cd93STycho Nightingale 		goto done;
1519bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBP, zero)) != 0)
1520bf21cd93STycho Nightingale 		goto done;
1521bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0)
1522bf21cd93STycho Nightingale 		goto done;
1523bf21cd93STycho Nightingale 
1524bf21cd93STycho Nightingale 	/* GDTR, IDTR */
1525bf21cd93STycho Nightingale 	desc_base = 0;
1526bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1527bf21cd93STycho Nightingale 	desc_access = 0;
1528bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
1529bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1530bf21cd93STycho Nightingale 	if (error != 0)
1531bf21cd93STycho Nightingale 		goto done;
1532bf21cd93STycho Nightingale 
1533bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_IDTR,
1534bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1535bf21cd93STycho Nightingale 	if (error != 0)
1536bf21cd93STycho Nightingale 		goto done;
1537bf21cd93STycho Nightingale 
1538bf21cd93STycho Nightingale 	/* TR */
1539bf21cd93STycho Nightingale 	desc_base = 0;
1540bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1541bf21cd93STycho Nightingale 	desc_access = 0x0000008b;
1542bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
1543bf21cd93STycho Nightingale 	if (error)
1544bf21cd93STycho Nightingale 		goto done;
1545bf21cd93STycho Nightingale 
1546bf21cd93STycho Nightingale 	sel = 0;
1547bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, sel)) != 0)
1548bf21cd93STycho Nightingale 		goto done;
1549bf21cd93STycho Nightingale 
1550bf21cd93STycho Nightingale 	/* LDTR */
1551bf21cd93STycho Nightingale 	desc_base = 0;
1552bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1553bf21cd93STycho Nightingale 	desc_access = 0x00000082;
1554bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, desc_base,
1555bf21cd93STycho Nightingale 			    desc_limit, desc_access);
1556bf21cd93STycho Nightingale 	if (error)
1557bf21cd93STycho Nightingale 		goto done;
1558bf21cd93STycho Nightingale 
1559bf21cd93STycho Nightingale 	sel = 0;
1560bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
1561bf21cd93STycho Nightingale 		goto done;
1562bf21cd93STycho Nightingale 
1563bf21cd93STycho Nightingale 	/* XXX cr2, debug registers */
1564bf21cd93STycho Nightingale 
1565bf21cd93STycho Nightingale 	error = 0;
1566bf21cd93STycho Nightingale done:
1567bf21cd93STycho Nightingale 	return (error);
1568bf21cd93STycho Nightingale }
15692606939dSPatrick Mooney #endif /* __FreeBSD__ */
1570bf21cd93STycho Nightingale 
1571bf21cd93STycho Nightingale int
1572bf21cd93STycho Nightingale vm_get_gpa_pmap(struct vmctx *ctx, uint64_t gpa, uint64_t *pte, int *num)
1573bf21cd93STycho Nightingale {
1574bf21cd93STycho Nightingale 	int error, i;
1575bf21cd93STycho Nightingale 	struct vm_gpa_pte gpapte;
1576bf21cd93STycho Nightingale 
1577bf21cd93STycho Nightingale 	bzero(&gpapte, sizeof(gpapte));
1578bf21cd93STycho Nightingale 	gpapte.gpa = gpa;
1579bf21cd93STycho Nightingale 
1580bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_GPA_PMAP, &gpapte);
1581bf21cd93STycho Nightingale 
1582bf21cd93STycho Nightingale 	if (error == 0) {
1583bf21cd93STycho Nightingale 		*num = gpapte.ptenum;
1584bf21cd93STycho Nightingale 		for (i = 0; i < gpapte.ptenum; i++)
1585bf21cd93STycho Nightingale 			pte[i] = gpapte.pte[i];
1586bf21cd93STycho Nightingale 	}
1587bf21cd93STycho Nightingale 
1588bf21cd93STycho Nightingale 	return (error);
1589bf21cd93STycho Nightingale }
1590bf21cd93STycho Nightingale 
1591bf21cd93STycho Nightingale int
1592bf21cd93STycho Nightingale vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
1593bf21cd93STycho Nightingale {
1594bf21cd93STycho Nightingale 	int error;
1595bf21cd93STycho Nightingale 	struct vm_hpet_cap cap;
1596bf21cd93STycho Nightingale 
1597bf21cd93STycho Nightingale 	bzero(&cap, sizeof(struct vm_hpet_cap));
1598bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap);
1599bf21cd93STycho Nightingale 	if (capabilities != NULL)
1600bf21cd93STycho Nightingale 		*capabilities = cap.capabilities;
1601bf21cd93STycho Nightingale 	return (error);
1602bf21cd93STycho Nightingale }
1603bf21cd93STycho Nightingale 
16044c87aefeSPatrick Mooney int
16054c87aefeSPatrick Mooney vm_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
16064c87aefeSPatrick Mooney     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1607bf21cd93STycho Nightingale {
1608bf21cd93STycho Nightingale 	struct vm_gla2gpa gg;
1609bf21cd93STycho Nightingale 	int error;
1610bf21cd93STycho Nightingale 
1611bf21cd93STycho Nightingale 	bzero(&gg, sizeof(struct vm_gla2gpa));
1612bf21cd93STycho Nightingale 	gg.vcpuid = vcpu;
1613bf21cd93STycho Nightingale 	gg.prot = prot;
1614bf21cd93STycho Nightingale 	gg.gla = gla;
1615bf21cd93STycho Nightingale 	gg.paging = *paging;
1616bf21cd93STycho Nightingale 
1617bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GLA2GPA, &gg);
1618bf21cd93STycho Nightingale 	if (error == 0) {
1619bf21cd93STycho Nightingale 		*fault = gg.fault;
1620bf21cd93STycho Nightingale 		*gpa = gg.gpa;
1621bf21cd93STycho Nightingale 	}
1622bf21cd93STycho Nightingale 	return (error);
1623bf21cd93STycho Nightingale }
1624bf21cd93STycho Nightingale 
1625bf21cd93STycho Nightingale int
16264c87aefeSPatrick Mooney vm_gla2gpa_nofault(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
16274c87aefeSPatrick Mooney     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1628bf21cd93STycho Nightingale {
16294c87aefeSPatrick Mooney 	struct vm_gla2gpa gg;
16304c87aefeSPatrick Mooney 	int error;
16314c87aefeSPatrick Mooney 
16324c87aefeSPatrick Mooney 	bzero(&gg, sizeof(struct vm_gla2gpa));
16334c87aefeSPatrick Mooney 	gg.vcpuid = vcpu;
16344c87aefeSPatrick Mooney 	gg.prot = prot;
16354c87aefeSPatrick Mooney 	gg.gla = gla;
16364c87aefeSPatrick Mooney 	gg.paging = *paging;
1637bf21cd93STycho Nightingale 
16384c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GLA2GPA_NOFAULT, &gg);
16394c87aefeSPatrick Mooney 	if (error == 0) {
16404c87aefeSPatrick Mooney 		*fault = gg.fault;
16414c87aefeSPatrick Mooney 		*gpa = gg.gpa;
16424c87aefeSPatrick Mooney 	}
1643bf21cd93STycho Nightingale 	return (error);
1644bf21cd93STycho Nightingale }
1645bf21cd93STycho Nightingale 
1646bf21cd93STycho Nightingale #ifndef min
1647bf21cd93STycho Nightingale #define	min(a,b)	(((a) < (b)) ? (a) : (b))
1648bf21cd93STycho Nightingale #endif
1649bf21cd93STycho Nightingale 
1650bf21cd93STycho Nightingale int
1651bf21cd93STycho Nightingale vm_copy_setup(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
16524c87aefeSPatrick Mooney     uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt,
16534c87aefeSPatrick Mooney     int *fault)
1654bf21cd93STycho Nightingale {
1655bf21cd93STycho Nightingale 	void *va;
1656*b0de25cbSAndy Fiddaman 	uint64_t gpa, off;
1657*b0de25cbSAndy Fiddaman 	int error, i, n;
1658bf21cd93STycho Nightingale 
1659bf21cd93STycho Nightingale 	for (i = 0; i < iovcnt; i++) {
1660bf21cd93STycho Nightingale 		iov[i].iov_base = 0;
1661bf21cd93STycho Nightingale 		iov[i].iov_len = 0;
1662bf21cd93STycho Nightingale 	}
1663bf21cd93STycho Nightingale 
1664bf21cd93STycho Nightingale 	while (len) {
1665bf21cd93STycho Nightingale 		assert(iovcnt > 0);
16664c87aefeSPatrick Mooney 		error = vm_gla2gpa(ctx, vcpu, paging, gla, prot, &gpa, fault);
16674c87aefeSPatrick Mooney 		if (error || *fault)
16684c87aefeSPatrick Mooney 			return (error);
1669bf21cd93STycho Nightingale 
1670bf21cd93STycho Nightingale 		off = gpa & PAGE_MASK;
1671*b0de25cbSAndy Fiddaman 		n = MIN(len, PAGE_SIZE - off);
1672bf21cd93STycho Nightingale 
1673bf21cd93STycho Nightingale 		va = vm_map_gpa(ctx, gpa, n);
1674bf21cd93STycho Nightingale 		if (va == NULL)
16754c87aefeSPatrick Mooney 			return (EFAULT);
1676bf21cd93STycho Nightingale 
1677bf21cd93STycho Nightingale 		iov->iov_base = va;
1678bf21cd93STycho Nightingale 		iov->iov_len = n;
1679bf21cd93STycho Nightingale 		iov++;
1680bf21cd93STycho Nightingale 		iovcnt--;
1681bf21cd93STycho Nightingale 
1682bf21cd93STycho Nightingale 		gla += n;
1683bf21cd93STycho Nightingale 		len -= n;
1684bf21cd93STycho Nightingale 	}
1685bf21cd93STycho Nightingale 	return (0);
1686bf21cd93STycho Nightingale }
1687bf21cd93STycho Nightingale 
1688bf21cd93STycho Nightingale void
1689*b0de25cbSAndy Fiddaman vm_copy_teardown(struct vmctx *ctx __unused, int vcpu __unused,
1690*b0de25cbSAndy Fiddaman     struct iovec *iov __unused, int iovcnt __unused)
1691bf21cd93STycho Nightingale {
1692bf21cd93STycho Nightingale }
1693bf21cd93STycho Nightingale 
1694bf21cd93STycho Nightingale void
1695*b0de25cbSAndy Fiddaman vm_copyin(struct vmctx *ctx __unused, int vcpu __unused, struct iovec *iov,
1696*b0de25cbSAndy Fiddaman     void *vp, size_t len)
1697bf21cd93STycho Nightingale {
1698bf21cd93STycho Nightingale 	const char *src;
1699bf21cd93STycho Nightingale 	char *dst;
1700bf21cd93STycho Nightingale 	size_t n;
1701bf21cd93STycho Nightingale 
1702bf21cd93STycho Nightingale 	dst = vp;
1703bf21cd93STycho Nightingale 	while (len) {
1704bf21cd93STycho Nightingale 		assert(iov->iov_len);
1705bf21cd93STycho Nightingale 		n = min(len, iov->iov_len);
1706bf21cd93STycho Nightingale 		src = iov->iov_base;
1707bf21cd93STycho Nightingale 		bcopy(src, dst, n);
1708bf21cd93STycho Nightingale 
1709bf21cd93STycho Nightingale 		iov++;
1710bf21cd93STycho Nightingale 		dst += n;
1711bf21cd93STycho Nightingale 		len -= n;
1712bf21cd93STycho Nightingale 	}
1713bf21cd93STycho Nightingale }
1714bf21cd93STycho Nightingale 
1715bf21cd93STycho Nightingale void
1716*b0de25cbSAndy Fiddaman vm_copyout(struct vmctx *ctx __unused, int vcpu __unused, const void *vp,
1717*b0de25cbSAndy Fiddaman     struct iovec *iov, size_t len)
1718bf21cd93STycho Nightingale {
1719bf21cd93STycho Nightingale 	const char *src;
1720bf21cd93STycho Nightingale 	char *dst;
1721bf21cd93STycho Nightingale 	size_t n;
1722bf21cd93STycho Nightingale 
1723bf21cd93STycho Nightingale 	src = vp;
1724bf21cd93STycho Nightingale 	while (len) {
1725bf21cd93STycho Nightingale 		assert(iov->iov_len);
1726bf21cd93STycho Nightingale 		n = min(len, iov->iov_len);
1727bf21cd93STycho Nightingale 		dst = iov->iov_base;
1728bf21cd93STycho Nightingale 		bcopy(src, dst, n);
1729bf21cd93STycho Nightingale 
1730bf21cd93STycho Nightingale 		iov++;
1731bf21cd93STycho Nightingale 		src += n;
1732bf21cd93STycho Nightingale 		len -= n;
1733bf21cd93STycho Nightingale 	}
1734bf21cd93STycho Nightingale }
1735bf21cd93STycho Nightingale 
17364c87aefeSPatrick Mooney static int
17374c87aefeSPatrick Mooney vm_get_cpus(struct vmctx *ctx, int which, cpuset_t *cpus)
17384c87aefeSPatrick Mooney {
17394c87aefeSPatrick Mooney 	struct vm_cpuset vm_cpuset;
17404c87aefeSPatrick Mooney 	int error;
17414c87aefeSPatrick Mooney 
17424c87aefeSPatrick Mooney 	bzero(&vm_cpuset, sizeof(struct vm_cpuset));
17434c87aefeSPatrick Mooney 	vm_cpuset.which = which;
17444c87aefeSPatrick Mooney 	vm_cpuset.cpusetsize = sizeof(cpuset_t);
17454c87aefeSPatrick Mooney 	vm_cpuset.cpus = cpus;
17464c87aefeSPatrick Mooney 
17474c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_CPUS, &vm_cpuset);
17484c87aefeSPatrick Mooney 	return (error);
17494c87aefeSPatrick Mooney }
17504c87aefeSPatrick Mooney 
17514c87aefeSPatrick Mooney int
17524c87aefeSPatrick Mooney vm_active_cpus(struct vmctx *ctx, cpuset_t *cpus)
17534c87aefeSPatrick Mooney {
17544c87aefeSPatrick Mooney 
17554c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_ACTIVE_CPUS, cpus));
17564c87aefeSPatrick Mooney }
17574c87aefeSPatrick Mooney 
17584c87aefeSPatrick Mooney int
17594c87aefeSPatrick Mooney vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus)
17604c87aefeSPatrick Mooney {
17614c87aefeSPatrick Mooney 
17624c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_SUSPENDED_CPUS, cpus));
17634c87aefeSPatrick Mooney }
17644c87aefeSPatrick Mooney 
17654c87aefeSPatrick Mooney int
17664c87aefeSPatrick Mooney vm_debug_cpus(struct vmctx *ctx, cpuset_t *cpus)
17674c87aefeSPatrick Mooney {
17684c87aefeSPatrick Mooney 
17694c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_DEBUG_CPUS, cpus));
17704c87aefeSPatrick Mooney }
17714c87aefeSPatrick Mooney 
1772bf21cd93STycho Nightingale int
1773bf21cd93STycho Nightingale vm_activate_cpu(struct vmctx *ctx, int vcpu)
1774bf21cd93STycho Nightingale {
1775bf21cd93STycho Nightingale 	struct vm_activate_cpu ac;
1776bf21cd93STycho Nightingale 	int error;
1777bf21cd93STycho Nightingale 
1778bf21cd93STycho Nightingale 	bzero(&ac, sizeof(struct vm_activate_cpu));
1779bf21cd93STycho Nightingale 	ac.vcpuid = vcpu;
1780bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_ACTIVATE_CPU, &ac);
1781bf21cd93STycho Nightingale 	return (error);
1782bf21cd93STycho Nightingale }
1783bf21cd93STycho Nightingale 
17844c87aefeSPatrick Mooney int
17854c87aefeSPatrick Mooney vm_suspend_cpu(struct vmctx *ctx, int vcpu)
17864c87aefeSPatrick Mooney {
17874c87aefeSPatrick Mooney 	struct vm_activate_cpu ac;
17884c87aefeSPatrick Mooney 	int error;
17894c87aefeSPatrick Mooney 
17904c87aefeSPatrick Mooney 	bzero(&ac, sizeof(struct vm_activate_cpu));
17914c87aefeSPatrick Mooney 	ac.vcpuid = vcpu;
17924c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SUSPEND_CPU, &ac);
17934c87aefeSPatrick Mooney 	return (error);
17944c87aefeSPatrick Mooney }
17954c87aefeSPatrick Mooney 
17964c87aefeSPatrick Mooney int
17974c87aefeSPatrick Mooney vm_resume_cpu(struct vmctx *ctx, int vcpu)
17984c87aefeSPatrick Mooney {
17994c87aefeSPatrick Mooney 	struct vm_activate_cpu ac;
18004c87aefeSPatrick Mooney 	int error;
18014c87aefeSPatrick Mooney 
18024c87aefeSPatrick Mooney 	bzero(&ac, sizeof(struct vm_activate_cpu));
18034c87aefeSPatrick Mooney 	ac.vcpuid = vcpu;
18044c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RESUME_CPU, &ac);
18054c87aefeSPatrick Mooney 	return (error);
18064c87aefeSPatrick Mooney }
18074c87aefeSPatrick Mooney 
18084c87aefeSPatrick Mooney int
18094c87aefeSPatrick Mooney vm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *info1, uint64_t *info2)
18104c87aefeSPatrick Mooney {
18114c87aefeSPatrick Mooney 	struct vm_intinfo vmii;
18124c87aefeSPatrick Mooney 	int error;
18134c87aefeSPatrick Mooney 
18144c87aefeSPatrick Mooney 	bzero(&vmii, sizeof(struct vm_intinfo));
18154c87aefeSPatrick Mooney 	vmii.vcpuid = vcpu;
18164c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_INTINFO, &vmii);
18174c87aefeSPatrick Mooney 	if (error == 0) {
18184c87aefeSPatrick Mooney 		*info1 = vmii.info1;
18194c87aefeSPatrick Mooney 		*info2 = vmii.info2;
18204c87aefeSPatrick Mooney 	}
18214c87aefeSPatrick Mooney 	return (error);
18224c87aefeSPatrick Mooney }
18234c87aefeSPatrick Mooney 
18244c87aefeSPatrick Mooney int
18254c87aefeSPatrick Mooney vm_set_intinfo(struct vmctx *ctx, int vcpu, uint64_t info1)
18264c87aefeSPatrick Mooney {
18274c87aefeSPatrick Mooney 	struct vm_intinfo vmii;
18284c87aefeSPatrick Mooney 	int error;
18294c87aefeSPatrick Mooney 
18304c87aefeSPatrick Mooney 	bzero(&vmii, sizeof(struct vm_intinfo));
18314c87aefeSPatrick Mooney 	vmii.vcpuid = vcpu;
18324c87aefeSPatrick Mooney 	vmii.info1 = info1;
18334c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SET_INTINFO, &vmii);
18344c87aefeSPatrick Mooney 	return (error);
18354c87aefeSPatrick Mooney }
18364c87aefeSPatrick Mooney 
18374c87aefeSPatrick Mooney int
18384c87aefeSPatrick Mooney vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
18394c87aefeSPatrick Mooney {
18404c87aefeSPatrick Mooney 	struct vm_rtc_data rtcdata;
18414c87aefeSPatrick Mooney 	int error;
18424c87aefeSPatrick Mooney 
18434c87aefeSPatrick Mooney 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
18444c87aefeSPatrick Mooney 	rtcdata.offset = offset;
18454c87aefeSPatrick Mooney 	rtcdata.value = value;
18464c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
18474c87aefeSPatrick Mooney 	return (error);
18484c87aefeSPatrick Mooney }
18494c87aefeSPatrick Mooney 
18504c87aefeSPatrick Mooney int
18514c87aefeSPatrick Mooney vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
18524c87aefeSPatrick Mooney {
18534c87aefeSPatrick Mooney 	struct vm_rtc_data rtcdata;
18544c87aefeSPatrick Mooney 	int error;
18554c87aefeSPatrick Mooney 
18564c87aefeSPatrick Mooney 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
18574c87aefeSPatrick Mooney 	rtcdata.offset = offset;
18584c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
18594c87aefeSPatrick Mooney 	if (error == 0)
18604c87aefeSPatrick Mooney 		*retval = rtcdata.value;
18614c87aefeSPatrick Mooney 	return (error);
18624c87aefeSPatrick Mooney }
18634c87aefeSPatrick Mooney 
18644c87aefeSPatrick Mooney int
18654c87aefeSPatrick Mooney vm_rtc_settime(struct vmctx *ctx, time_t secs)
18664c87aefeSPatrick Mooney {
18674c87aefeSPatrick Mooney 	struct vm_rtc_time rtctime;
18684c87aefeSPatrick Mooney 	int error;
18694c87aefeSPatrick Mooney 
18704c87aefeSPatrick Mooney 	bzero(&rtctime, sizeof(struct vm_rtc_time));
18714c87aefeSPatrick Mooney 	rtctime.secs = secs;
18724c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
18734c87aefeSPatrick Mooney 	return (error);
18744c87aefeSPatrick Mooney }
18754c87aefeSPatrick Mooney 
18764c87aefeSPatrick Mooney int
18774c87aefeSPatrick Mooney vm_rtc_gettime(struct vmctx *ctx, time_t *secs)
18784c87aefeSPatrick Mooney {
18794c87aefeSPatrick Mooney 	struct vm_rtc_time rtctime;
18804c87aefeSPatrick Mooney 	int error;
18814c87aefeSPatrick Mooney 
18824c87aefeSPatrick Mooney 	bzero(&rtctime, sizeof(struct vm_rtc_time));
18834c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
18844c87aefeSPatrick Mooney 	if (error == 0)
18854c87aefeSPatrick Mooney 		*secs = rtctime.secs;
18864c87aefeSPatrick Mooney 	return (error);
18874c87aefeSPatrick Mooney }
18884c87aefeSPatrick Mooney 
1889bf21cd93STycho Nightingale int
1890bf21cd93STycho Nightingale vm_restart_instruction(void *arg, int vcpu)
1891bf21cd93STycho Nightingale {
1892bf21cd93STycho Nightingale 	struct vmctx *ctx = arg;
1893bf21cd93STycho Nightingale 
1894bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_RESTART_INSTRUCTION, &vcpu));
1895bf21cd93STycho Nightingale }
18964c87aefeSPatrick Mooney 
18974c87aefeSPatrick Mooney int
18984c87aefeSPatrick Mooney vm_set_topology(struct vmctx *ctx,
18994c87aefeSPatrick Mooney     uint16_t sockets, uint16_t cores, uint16_t threads, uint16_t maxcpus)
19004c87aefeSPatrick Mooney {
19014c87aefeSPatrick Mooney 	struct vm_cpu_topology topology;
19024c87aefeSPatrick Mooney 
19034c87aefeSPatrick Mooney 	bzero(&topology, sizeof (struct vm_cpu_topology));
19044c87aefeSPatrick Mooney 	topology.sockets = sockets;
19054c87aefeSPatrick Mooney 	topology.cores = cores;
19064c87aefeSPatrick Mooney 	topology.threads = threads;
19074c87aefeSPatrick Mooney 	topology.maxcpus = maxcpus;
19084c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_SET_TOPOLOGY, &topology));
19094c87aefeSPatrick Mooney }
19104c87aefeSPatrick Mooney 
19114c87aefeSPatrick Mooney int
19124c87aefeSPatrick Mooney vm_get_topology(struct vmctx *ctx,
19134c87aefeSPatrick Mooney     uint16_t *sockets, uint16_t *cores, uint16_t *threads, uint16_t *maxcpus)
19144c87aefeSPatrick Mooney {
19154c87aefeSPatrick Mooney 	struct vm_cpu_topology topology;
19164c87aefeSPatrick Mooney 	int error;
19174c87aefeSPatrick Mooney 
19184c87aefeSPatrick Mooney 	bzero(&topology, sizeof (struct vm_cpu_topology));
19194c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_TOPOLOGY, &topology);
19204c87aefeSPatrick Mooney 	if (error == 0) {
19214c87aefeSPatrick Mooney 		*sockets = topology.sockets;
19224c87aefeSPatrick Mooney 		*cores = topology.cores;
19234c87aefeSPatrick Mooney 		*threads = topology.threads;
19244c87aefeSPatrick Mooney 		*maxcpus = topology.maxcpus;
19254c87aefeSPatrick Mooney 	}
19264c87aefeSPatrick Mooney 	return (error);
19274c87aefeSPatrick Mooney }
19284c87aefeSPatrick Mooney 
19294c87aefeSPatrick Mooney int
19304c87aefeSPatrick Mooney vm_get_device_fd(struct vmctx *ctx)
19314c87aefeSPatrick Mooney {
19324c87aefeSPatrick Mooney 
19334c87aefeSPatrick Mooney 	return (ctx->fd);
19344c87aefeSPatrick Mooney }
19354c87aefeSPatrick Mooney 
19364c87aefeSPatrick Mooney #ifndef __FreeBSD__
19370e1453c3SPatrick Mooney int
19380e1453c3SPatrick Mooney vm_pmtmr_set_location(struct vmctx *ctx, uint16_t ioport)
19390e1453c3SPatrick Mooney {
19400e1453c3SPatrick Mooney 	return (ioctl(ctx->fd, VM_PMTMR_LOCATE, ioport));
19410e1453c3SPatrick Mooney }
19420e1453c3SPatrick Mooney 
19434c87aefeSPatrick Mooney int
19444c87aefeSPatrick Mooney vm_wrlock_cycle(struct vmctx *ctx)
19454c87aefeSPatrick Mooney {
19464c87aefeSPatrick Mooney 	if (ioctl(ctx->fd, VM_WRLOCK_CYCLE, 0) != 0) {
19474c87aefeSPatrick Mooney 		return (errno);
19484c87aefeSPatrick Mooney 	}
19494c87aefeSPatrick Mooney 	return (0);
19504c87aefeSPatrick Mooney }
19512606939dSPatrick Mooney 
19522606939dSPatrick Mooney int
19532606939dSPatrick Mooney vm_get_run_state(struct vmctx *ctx, int vcpu, enum vcpu_run_state *state,
19542606939dSPatrick Mooney     uint8_t *sipi_vector)
19552606939dSPatrick Mooney {
19562606939dSPatrick Mooney 	struct vm_run_state data;
19572606939dSPatrick Mooney 
19582606939dSPatrick Mooney 	data.vcpuid = vcpu;
19592606939dSPatrick Mooney 	if (ioctl(ctx->fd, VM_GET_RUN_STATE, &data) != 0) {
19602606939dSPatrick Mooney 		return (errno);
19612606939dSPatrick Mooney 	}
19622606939dSPatrick Mooney 
19632606939dSPatrick Mooney 	*state = data.state;
19642606939dSPatrick Mooney 	*sipi_vector = data.sipi_vector;
19652606939dSPatrick Mooney 	return (0);
19662606939dSPatrick Mooney }
19672606939dSPatrick Mooney 
19682606939dSPatrick Mooney int
19692606939dSPatrick Mooney vm_set_run_state(struct vmctx *ctx, int vcpu, enum vcpu_run_state state,
19702606939dSPatrick Mooney     uint8_t sipi_vector)
19712606939dSPatrick Mooney {
19722606939dSPatrick Mooney 	struct vm_run_state data;
19732606939dSPatrick Mooney 
19742606939dSPatrick Mooney 	data.vcpuid = vcpu;
19752606939dSPatrick Mooney 	data.state = state;
19762606939dSPatrick Mooney 	data.sipi_vector = sipi_vector;
19772606939dSPatrick Mooney 	if (ioctl(ctx->fd, VM_SET_RUN_STATE, &data) != 0) {
19782606939dSPatrick Mooney 		return (errno);
19792606939dSPatrick Mooney 	}
19802606939dSPatrick Mooney 
19812606939dSPatrick Mooney 	return (0);
19822606939dSPatrick Mooney }
19832606939dSPatrick Mooney 
19844c87aefeSPatrick Mooney #endif /* __FreeBSD__ */
19854c87aefeSPatrick Mooney 
19864c87aefeSPatrick Mooney #ifdef __FreeBSD__
19874c87aefeSPatrick Mooney const cap_ioctl_t *
19884c87aefeSPatrick Mooney vm_get_ioctls(size_t *len)
19894c87aefeSPatrick Mooney {
19904c87aefeSPatrick Mooney 	cap_ioctl_t *cmds;
19914c87aefeSPatrick Mooney 	/* keep in sync with machine/vmm_dev.h */
19924c87aefeSPatrick Mooney 	static const cap_ioctl_t vm_ioctl_cmds[] = { VM_RUN, VM_SUSPEND, VM_REINIT,
19934c87aefeSPatrick Mooney 	    VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
19942b948146SAndy Fiddaman 	    VM_MMAP_GETNEXT, VM_MUNMAP_MEMSEG, VM_SET_REGISTER, VM_GET_REGISTER,
19954c87aefeSPatrick Mooney 	    VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
19964c87aefeSPatrick Mooney 	    VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
1997154972afSPatrick Mooney 	    VM_SET_KERNEMU_DEV, VM_GET_KERNEMU_DEV,
19984c87aefeSPatrick Mooney 	    VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
19994c87aefeSPatrick Mooney 	    VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
20004c87aefeSPatrick Mooney 	    VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,
20014c87aefeSPatrick Mooney 	    VM_ISA_DEASSERT_IRQ, VM_ISA_PULSE_IRQ, VM_ISA_SET_IRQ_TRIGGER,
20024c87aefeSPatrick Mooney 	    VM_SET_CAPABILITY, VM_GET_CAPABILITY, VM_BIND_PPTDEV,
20034c87aefeSPatrick Mooney 	    VM_UNBIND_PPTDEV, VM_MAP_PPTDEV_MMIO, VM_PPTDEV_MSI,
20042b948146SAndy Fiddaman 	    VM_PPTDEV_MSIX, VM_UNMAP_PPTDEV_MMIO, VM_PPTDEV_DISABLE_MSIX,
20056960cd89SAndy Fiddaman 	    VM_INJECT_NMI, VM_STATS, VM_STAT_DESC,
20064c87aefeSPatrick Mooney 	    VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
20074c87aefeSPatrick Mooney 	    VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
20084c87aefeSPatrick Mooney 	    VM_GLA2GPA_NOFAULT,
20094c87aefeSPatrick Mooney 	    VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU,
20104c87aefeSPatrick Mooney 	    VM_SET_INTINFO, VM_GET_INTINFO,
20114c87aefeSPatrick Mooney 	    VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
20124c87aefeSPatrick Mooney 	    VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY };
20134c87aefeSPatrick Mooney 
20144c87aefeSPatrick Mooney 	if (len == NULL) {
20154c87aefeSPatrick Mooney 		cmds = malloc(sizeof(vm_ioctl_cmds));
20164c87aefeSPatrick Mooney 		if (cmds == NULL)
20174c87aefeSPatrick Mooney 			return (NULL);
20184c87aefeSPatrick Mooney 		bcopy(vm_ioctl_cmds, cmds, sizeof(vm_ioctl_cmds));
20194c87aefeSPatrick Mooney 		return (cmds);
20204c87aefeSPatrick Mooney 	}
20214c87aefeSPatrick Mooney 
20224c87aefeSPatrick Mooney 	*len = nitems(vm_ioctl_cmds);
20234c87aefeSPatrick Mooney 	return (NULL);
20244c87aefeSPatrick Mooney }
20254c87aefeSPatrick Mooney #endif /* __FreeBSD__ */
2026