1bf21cd93STycho Nightingale /*-
2*4c87aefeSPatrick Mooney  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3*4c87aefeSPatrick 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  *
28*4c87aefeSPatrick 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.
41*4c87aefeSPatrick Mooney  * Copyright 2019 Joyent, Inc.
42bf21cd93STycho Nightingale  */
43bf21cd93STycho Nightingale 
44bf21cd93STycho Nightingale #include <sys/cdefs.h>
45*4c87aefeSPatrick Mooney __FBSDID("$FreeBSD$");
46bf21cd93STycho Nightingale 
47bf21cd93STycho Nightingale #include <sys/param.h>
48bf21cd93STycho Nightingale #include <sys/sysctl.h>
49bf21cd93STycho Nightingale #include <sys/ioctl.h>
50bf21cd93STycho Nightingale #include <sys/mman.h>
51bf21cd93STycho Nightingale #include <sys/_iovec.h>
52bf21cd93STycho Nightingale #include <sys/cpuset.h>
53bf21cd93STycho Nightingale 
54*4c87aefeSPatrick Mooney #include <x86/segments.h>
55bf21cd93STycho Nightingale #include <machine/specialreg.h>
56bf21cd93STycho Nightingale 
57bf21cd93STycho Nightingale #include <errno.h>
58bf21cd93STycho Nightingale #include <stdio.h>
59bf21cd93STycho Nightingale #include <stdlib.h>
60bf21cd93STycho Nightingale #include <assert.h>
61bf21cd93STycho Nightingale #include <string.h>
62bf21cd93STycho Nightingale #include <fcntl.h>
63bf21cd93STycho Nightingale #include <unistd.h>
64bf21cd93STycho Nightingale 
65bf21cd93STycho Nightingale #include <libutil.h>
66bf21cd93STycho Nightingale 
67bf21cd93STycho Nightingale #include <machine/vmm.h>
68bf21cd93STycho Nightingale #include <machine/vmm_dev.h>
69bf21cd93STycho Nightingale #ifndef	__FreeBSD__
70bf21cd93STycho Nightingale #include <sys/vmm_impl.h>
71bf21cd93STycho Nightingale #endif
72bf21cd93STycho Nightingale 
73bf21cd93STycho Nightingale #include "vmmapi.h"
74bf21cd93STycho Nightingale 
75bf21cd93STycho Nightingale #define	MB	(1024 * 1024UL)
76bf21cd93STycho Nightingale #define	GB	(1024 * 1024 * 1024UL)
77bf21cd93STycho Nightingale 
78*4c87aefeSPatrick Mooney #ifndef __FreeBSD__
79*4c87aefeSPatrick Mooney /* shim to no-op for now */
80*4c87aefeSPatrick Mooney #define	MAP_NOCORE		0
81*4c87aefeSPatrick Mooney #define	MAP_ALIGNED_SUPER	0
82*4c87aefeSPatrick Mooney 
83*4c87aefeSPatrick Mooney /* Rely on PROT_NONE for guard purposes */
84*4c87aefeSPatrick Mooney #define	MAP_GUARD		(MAP_PRIVATE | MAP_ANON | MAP_NORESERVE)
85*4c87aefeSPatrick Mooney #endif
86*4c87aefeSPatrick Mooney 
87*4c87aefeSPatrick Mooney /*
88*4c87aefeSPatrick Mooney  * Size of the guard region before and after the virtual address space
89*4c87aefeSPatrick Mooney  * mapping the guest physical memory. This must be a multiple of the
90*4c87aefeSPatrick Mooney  * superpage size for performance reasons.
91*4c87aefeSPatrick Mooney  */
92*4c87aefeSPatrick Mooney #define	VM_MMAP_GUARD_SIZE	(4 * MB)
93*4c87aefeSPatrick Mooney 
94*4c87aefeSPatrick Mooney #define	PROT_RW		(PROT_READ | PROT_WRITE)
95*4c87aefeSPatrick Mooney #define	PROT_ALL	(PROT_READ | PROT_WRITE | PROT_EXEC)
96*4c87aefeSPatrick Mooney 
97bf21cd93STycho Nightingale struct vmctx {
98bf21cd93STycho Nightingale 	int	fd;
99bf21cd93STycho Nightingale 	uint32_t lowmem_limit;
100*4c87aefeSPatrick Mooney 	int	memflags;
101bf21cd93STycho Nightingale 	size_t	lowmem;
102bf21cd93STycho Nightingale 	size_t	highmem;
103*4c87aefeSPatrick Mooney 	char	*baseaddr;
104bf21cd93STycho Nightingale 	char	*name;
105bf21cd93STycho Nightingale };
106bf21cd93STycho Nightingale 
107bf21cd93STycho Nightingale #ifdef	__FreeBSD__
108bf21cd93STycho Nightingale #define	CREATE(x)  sysctlbyname("hw.vmm.create", NULL, NULL, (x), strlen((x)))
109bf21cd93STycho Nightingale #define	DESTROY(x) sysctlbyname("hw.vmm.destroy", NULL, NULL, (x), strlen((x)))
110bf21cd93STycho Nightingale #else
111*4c87aefeSPatrick Mooney #define	CREATE(x)	vm_do_ctl(VMM_CREATE_VM, (x))
112*4c87aefeSPatrick Mooney #define	DESTROY(x)	vm_do_ctl(VMM_DESTROY_VM, (x))
113bf21cd93STycho Nightingale 
114bf21cd93STycho Nightingale static int
115*4c87aefeSPatrick Mooney vm_do_ctl(int cmd, const char *name)
116bf21cd93STycho Nightingale {
117*4c87aefeSPatrick Mooney 	int ctl_fd;
118bf21cd93STycho Nightingale 
119*4c87aefeSPatrick Mooney 	ctl_fd = open(VMM_CTL_DEV, O_EXCL | O_RDWR);
120*4c87aefeSPatrick Mooney 	if (ctl_fd < 0) {
121*4c87aefeSPatrick Mooney 		return (-1);
122*4c87aefeSPatrick Mooney 	}
123bf21cd93STycho Nightingale 
124*4c87aefeSPatrick Mooney 	if (ioctl(ctl_fd, cmd, name) == -1) {
125*4c87aefeSPatrick Mooney 		int err = errno;
126bf21cd93STycho Nightingale 
127*4c87aefeSPatrick Mooney 		/* Do not lose ioctl errno through the close(2) */
128*4c87aefeSPatrick Mooney 		(void) close(ctl_fd);
129*4c87aefeSPatrick Mooney 		errno = err;
130*4c87aefeSPatrick Mooney 		return (-1);
131*4c87aefeSPatrick Mooney 	}
132*4c87aefeSPatrick Mooney 	(void) close(ctl_fd);
133*4c87aefeSPatrick Mooney 
134*4c87aefeSPatrick Mooney 	return (0);
135bf21cd93STycho Nightingale }
136*4c87aefeSPatrick Mooney #endif
137bf21cd93STycho Nightingale 
138bf21cd93STycho Nightingale static int
139*4c87aefeSPatrick Mooney vm_device_open(const char *name)
140bf21cd93STycho Nightingale {
141*4c87aefeSPatrick Mooney 	int fd, len;
142*4c87aefeSPatrick Mooney 	char *vmfile;
143bf21cd93STycho Nightingale 
144*4c87aefeSPatrick Mooney 	len = strlen("/dev/vmm/") + strlen(name) + 1;
145*4c87aefeSPatrick Mooney 	vmfile = malloc(len);
146*4c87aefeSPatrick Mooney 	assert(vmfile != NULL);
147*4c87aefeSPatrick Mooney 	snprintf(vmfile, len, "/dev/vmm/%s", name);
148bf21cd93STycho Nightingale 
149*4c87aefeSPatrick Mooney 	/* Open the device file */
150*4c87aefeSPatrick Mooney 	fd = open(vmfile, O_RDWR, 0);
151bf21cd93STycho Nightingale 
152*4c87aefeSPatrick Mooney 	free(vmfile);
153*4c87aefeSPatrick Mooney 	return (fd);
154bf21cd93STycho Nightingale }
155bf21cd93STycho Nightingale 
156bf21cd93STycho Nightingale int
157bf21cd93STycho Nightingale vm_create(const char *name)
158bf21cd93STycho Nightingale {
159bf21cd93STycho Nightingale 
160bf21cd93STycho Nightingale 	return (CREATE((char *)name));
161bf21cd93STycho Nightingale }
162bf21cd93STycho Nightingale 
163bf21cd93STycho Nightingale struct vmctx *
164bf21cd93STycho Nightingale vm_open(const char *name)
165bf21cd93STycho Nightingale {
166bf21cd93STycho Nightingale 	struct vmctx *vm;
167bf21cd93STycho Nightingale 
168bf21cd93STycho Nightingale 	vm = malloc(sizeof(struct vmctx) + strlen(name) + 1);
169bf21cd93STycho Nightingale 	assert(vm != NULL);
170bf21cd93STycho Nightingale 
171bf21cd93STycho Nightingale 	vm->fd = -1;
172*4c87aefeSPatrick Mooney 	vm->memflags = 0;
173bf21cd93STycho Nightingale 	vm->lowmem_limit = 3 * GB;
174bf21cd93STycho Nightingale 	vm->name = (char *)(vm + 1);
175bf21cd93STycho Nightingale 	strcpy(vm->name, name);
176bf21cd93STycho Nightingale 
177bf21cd93STycho Nightingale 	if ((vm->fd = vm_device_open(vm->name)) < 0)
178bf21cd93STycho Nightingale 		goto err;
179bf21cd93STycho Nightingale 
180bf21cd93STycho Nightingale 	return (vm);
181bf21cd93STycho Nightingale err:
182*4c87aefeSPatrick Mooney 	vm_destroy(vm);
183bf21cd93STycho Nightingale 	return (NULL);
184bf21cd93STycho Nightingale }
185bf21cd93STycho Nightingale 
186*4c87aefeSPatrick Mooney void
187bf21cd93STycho Nightingale vm_destroy(struct vmctx *vm)
188bf21cd93STycho Nightingale {
189bf21cd93STycho Nightingale 	assert(vm != NULL);
190bf21cd93STycho Nightingale 
191bf21cd93STycho Nightingale 	if (vm->fd >= 0)
192bf21cd93STycho Nightingale 		close(vm->fd);
193*4c87aefeSPatrick Mooney 	DESTROY(vm->name);
194bf21cd93STycho Nightingale 
195bf21cd93STycho Nightingale 	free(vm);
196bf21cd93STycho Nightingale }
197bf21cd93STycho Nightingale 
198bf21cd93STycho Nightingale int
199bf21cd93STycho Nightingale vm_parse_memsize(const char *optarg, size_t *ret_memsize)
200bf21cd93STycho Nightingale {
201bf21cd93STycho Nightingale 	char *endptr;
202bf21cd93STycho Nightingale 	size_t optval;
203bf21cd93STycho Nightingale 	int error;
204bf21cd93STycho Nightingale 
205bf21cd93STycho Nightingale 	optval = strtoul(optarg, &endptr, 0);
206bf21cd93STycho Nightingale 	if (*optarg != '\0' && *endptr == '\0') {
207bf21cd93STycho Nightingale 		/*
208bf21cd93STycho Nightingale 		 * For the sake of backward compatibility if the memory size
209bf21cd93STycho Nightingale 		 * specified on the command line is less than a megabyte then
210bf21cd93STycho Nightingale 		 * it is interpreted as being in units of MB.
211bf21cd93STycho Nightingale 		 */
212bf21cd93STycho Nightingale 		if (optval < MB)
213bf21cd93STycho Nightingale 			optval *= MB;
214bf21cd93STycho Nightingale 		*ret_memsize = optval;
215bf21cd93STycho Nightingale 		error = 0;
216bf21cd93STycho Nightingale 	} else
217bf21cd93STycho Nightingale 		error = expand_number(optarg, ret_memsize);
218bf21cd93STycho Nightingale 
219bf21cd93STycho Nightingale 	return (error);
220bf21cd93STycho Nightingale }
221bf21cd93STycho Nightingale 
222*4c87aefeSPatrick Mooney uint32_t
223*4c87aefeSPatrick Mooney vm_get_lowmem_limit(struct vmctx *ctx)
224bf21cd93STycho Nightingale {
225*4c87aefeSPatrick Mooney 
226*4c87aefeSPatrick Mooney 	return (ctx->lowmem_limit);
227bf21cd93STycho Nightingale }
228bf21cd93STycho Nightingale 
229*4c87aefeSPatrick Mooney void
230*4c87aefeSPatrick Mooney vm_set_lowmem_limit(struct vmctx *ctx, uint32_t limit)
231bf21cd93STycho Nightingale {
232*4c87aefeSPatrick Mooney 
233*4c87aefeSPatrick Mooney 	ctx->lowmem_limit = limit;
234*4c87aefeSPatrick Mooney }
235*4c87aefeSPatrick Mooney 
236*4c87aefeSPatrick Mooney void
237*4c87aefeSPatrick Mooney vm_set_memflags(struct vmctx *ctx, int flags)
238*4c87aefeSPatrick Mooney {
239*4c87aefeSPatrick Mooney 
240*4c87aefeSPatrick Mooney 	ctx->memflags = flags;
241bf21cd93STycho Nightingale }
242bf21cd93STycho Nightingale 
243bf21cd93STycho Nightingale int
244*4c87aefeSPatrick Mooney vm_get_memflags(struct vmctx *ctx)
245bf21cd93STycho Nightingale {
246*4c87aefeSPatrick Mooney 
247*4c87aefeSPatrick Mooney 	return (ctx->memflags);
248*4c87aefeSPatrick Mooney }
249*4c87aefeSPatrick Mooney 
250*4c87aefeSPatrick Mooney /*
251*4c87aefeSPatrick Mooney  * Map segment 'segid' starting at 'off' into guest address range [gpa,gpa+len).
252*4c87aefeSPatrick Mooney  */
253*4c87aefeSPatrick Mooney int
254*4c87aefeSPatrick Mooney vm_mmap_memseg(struct vmctx *ctx, vm_paddr_t gpa, int segid, vm_ooffset_t off,
255*4c87aefeSPatrick Mooney     size_t len, int prot)
256*4c87aefeSPatrick Mooney {
257*4c87aefeSPatrick Mooney 	struct vm_memmap memmap;
258*4c87aefeSPatrick Mooney 	int error, flags;
259*4c87aefeSPatrick Mooney 
260*4c87aefeSPatrick Mooney 	memmap.gpa = gpa;
261*4c87aefeSPatrick Mooney 	memmap.segid = segid;
262*4c87aefeSPatrick Mooney 	memmap.segoff = off;
263*4c87aefeSPatrick Mooney 	memmap.len = len;
264*4c87aefeSPatrick Mooney 	memmap.prot = prot;
265*4c87aefeSPatrick Mooney 	memmap.flags = 0;
266*4c87aefeSPatrick Mooney 
267*4c87aefeSPatrick Mooney 	if (ctx->memflags & VM_MEM_F_WIRED)
268*4c87aefeSPatrick Mooney 		memmap.flags |= VM_MEMMAP_F_WIRED;
269*4c87aefeSPatrick Mooney 
270*4c87aefeSPatrick Mooney 	/*
271*4c87aefeSPatrick Mooney 	 * If this mapping already exists then don't create it again. This
272*4c87aefeSPatrick Mooney 	 * is the common case for SYSMEM mappings created by bhyveload(8).
273*4c87aefeSPatrick Mooney 	 */
274*4c87aefeSPatrick Mooney 	error = vm_mmap_getnext(ctx, &gpa, &segid, &off, &len, &prot, &flags);
275*4c87aefeSPatrick Mooney 	if (error == 0 && gpa == memmap.gpa) {
276*4c87aefeSPatrick Mooney 		if (segid != memmap.segid || off != memmap.segoff ||
277*4c87aefeSPatrick Mooney 		    prot != memmap.prot || flags != memmap.flags) {
278*4c87aefeSPatrick Mooney 			errno = EEXIST;
279*4c87aefeSPatrick Mooney 			return (-1);
280*4c87aefeSPatrick Mooney 		} else {
281*4c87aefeSPatrick Mooney 			return (0);
282*4c87aefeSPatrick Mooney 		}
283*4c87aefeSPatrick Mooney 	}
284*4c87aefeSPatrick Mooney 
285*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_MMAP_MEMSEG, &memmap);
286bf21cd93STycho Nightingale 	return (error);
287bf21cd93STycho Nightingale }
288bf21cd93STycho Nightingale 
289*4c87aefeSPatrick Mooney int
290*4c87aefeSPatrick Mooney vm_mmap_getnext(struct vmctx *ctx, vm_paddr_t *gpa, int *segid,
291*4c87aefeSPatrick Mooney     vm_ooffset_t *segoff, size_t *len, int *prot, int *flags)
292bf21cd93STycho Nightingale {
293*4c87aefeSPatrick Mooney 	struct vm_memmap memmap;
294*4c87aefeSPatrick Mooney 	int error;
295bf21cd93STycho Nightingale 
296*4c87aefeSPatrick Mooney 	bzero(&memmap, sizeof(struct vm_memmap));
297*4c87aefeSPatrick Mooney 	memmap.gpa = *gpa;
298*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_MMAP_GETNEXT, &memmap);
299*4c87aefeSPatrick Mooney 	if (error == 0) {
300*4c87aefeSPatrick Mooney 		*gpa = memmap.gpa;
301*4c87aefeSPatrick Mooney 		*segid = memmap.segid;
302*4c87aefeSPatrick Mooney 		*segoff = memmap.segoff;
303*4c87aefeSPatrick Mooney 		*len = memmap.len;
304*4c87aefeSPatrick Mooney 		*prot = memmap.prot;
305*4c87aefeSPatrick Mooney 		*flags = memmap.flags;
306*4c87aefeSPatrick Mooney 	}
307*4c87aefeSPatrick Mooney 	return (error);
308bf21cd93STycho Nightingale }
309bf21cd93STycho Nightingale 
310*4c87aefeSPatrick Mooney /*
311*4c87aefeSPatrick Mooney  * Return 0 if the segments are identical and non-zero otherwise.
312*4c87aefeSPatrick Mooney  *
313*4c87aefeSPatrick Mooney  * This is slightly complicated by the fact that only device memory segments
314*4c87aefeSPatrick Mooney  * are named.
315*4c87aefeSPatrick Mooney  */
316*4c87aefeSPatrick Mooney static int
317*4c87aefeSPatrick Mooney cmpseg(size_t len, const char *str, size_t len2, const char *str2)
318bf21cd93STycho Nightingale {
319bf21cd93STycho Nightingale 
320*4c87aefeSPatrick Mooney 	if (len == len2) {
321*4c87aefeSPatrick Mooney 		if ((!str && !str2) || (str && str2 && !strcmp(str, str2)))
322*4c87aefeSPatrick Mooney 			return (0);
323*4c87aefeSPatrick Mooney 	}
324*4c87aefeSPatrick Mooney 	return (-1);
325bf21cd93STycho Nightingale }
326bf21cd93STycho Nightingale 
327bf21cd93STycho Nightingale static int
328*4c87aefeSPatrick Mooney vm_alloc_memseg(struct vmctx *ctx, int segid, size_t len, const char *name)
329bf21cd93STycho Nightingale {
330*4c87aefeSPatrick Mooney 	struct vm_memseg memseg;
331*4c87aefeSPatrick Mooney 	size_t n;
332bf21cd93STycho Nightingale 	int error;
333bf21cd93STycho Nightingale 
334bf21cd93STycho Nightingale 	/*
335*4c87aefeSPatrick Mooney 	 * If the memory segment has already been created then just return.
336*4c87aefeSPatrick Mooney 	 * This is the usual case for the SYSMEM segment created by userspace
337*4c87aefeSPatrick Mooney 	 * loaders like bhyveload(8).
338bf21cd93STycho Nightingale 	 */
339*4c87aefeSPatrick Mooney 	error = vm_get_memseg(ctx, segid, &memseg.len, memseg.name,
340*4c87aefeSPatrick Mooney 	    sizeof(memseg.name));
341*4c87aefeSPatrick Mooney 	if (error)
342*4c87aefeSPatrick Mooney 		return (error);
343*4c87aefeSPatrick Mooney 
344*4c87aefeSPatrick Mooney 	if (memseg.len != 0) {
345*4c87aefeSPatrick Mooney 		if (cmpseg(len, name, memseg.len, VM_MEMSEG_NAME(&memseg))) {
346*4c87aefeSPatrick Mooney 			errno = EINVAL;
347*4c87aefeSPatrick Mooney 			return (-1);
348*4c87aefeSPatrick Mooney 		} else {
349*4c87aefeSPatrick Mooney 			return (0);
350*4c87aefeSPatrick Mooney 		}
351*4c87aefeSPatrick Mooney 	}
352*4c87aefeSPatrick Mooney 
353*4c87aefeSPatrick Mooney 	bzero(&memseg, sizeof(struct vm_memseg));
354*4c87aefeSPatrick Mooney 	memseg.segid = segid;
355*4c87aefeSPatrick Mooney 	memseg.len = len;
356*4c87aefeSPatrick Mooney 	if (name != NULL) {
357*4c87aefeSPatrick Mooney 		n = strlcpy(memseg.name, name, sizeof(memseg.name));
358*4c87aefeSPatrick Mooney 		if (n >= sizeof(memseg.name)) {
359*4c87aefeSPatrick Mooney 			errno = ENAMETOOLONG;
360*4c87aefeSPatrick Mooney 			return (-1);
361*4c87aefeSPatrick Mooney 		}
362*4c87aefeSPatrick Mooney 	}
363*4c87aefeSPatrick Mooney 
364*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_ALLOC_MEMSEG, &memseg);
365*4c87aefeSPatrick Mooney 	return (error);
366*4c87aefeSPatrick Mooney }
367*4c87aefeSPatrick Mooney 
368*4c87aefeSPatrick Mooney int
369*4c87aefeSPatrick Mooney vm_get_memseg(struct vmctx *ctx, int segid, size_t *lenp, char *namebuf,
370*4c87aefeSPatrick Mooney     size_t bufsize)
371*4c87aefeSPatrick Mooney {
372*4c87aefeSPatrick Mooney 	struct vm_memseg memseg;
373*4c87aefeSPatrick Mooney 	size_t n;
374*4c87aefeSPatrick Mooney 	int error;
375*4c87aefeSPatrick Mooney 
376*4c87aefeSPatrick Mooney 	memseg.segid = segid;
377*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_MEMSEG, &memseg);
378*4c87aefeSPatrick Mooney 	if (error == 0) {
379*4c87aefeSPatrick Mooney 		*lenp = memseg.len;
380*4c87aefeSPatrick Mooney 		n = strlcpy(namebuf, memseg.name, bufsize);
381*4c87aefeSPatrick Mooney 		if (n >= bufsize) {
382*4c87aefeSPatrick Mooney 			errno = ENAMETOOLONG;
383*4c87aefeSPatrick Mooney 			error = -1;
384*4c87aefeSPatrick Mooney 		}
385bf21cd93STycho Nightingale 	}
386bf21cd93STycho Nightingale 	return (error);
387bf21cd93STycho Nightingale }
388bf21cd93STycho Nightingale 
389*4c87aefeSPatrick Mooney static int
390*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
391*4c87aefeSPatrick Mooney setup_memory_segment(struct vmctx *ctx, vm_paddr_t gpa, size_t len, char *base)
392*4c87aefeSPatrick Mooney #else
393*4c87aefeSPatrick Mooney setup_memory_segment(struct vmctx *ctx, int segid, vm_paddr_t gpa, size_t len,
394*4c87aefeSPatrick Mooney     char *base)
395*4c87aefeSPatrick Mooney #endif
396*4c87aefeSPatrick Mooney {
397*4c87aefeSPatrick Mooney 	char *ptr;
398*4c87aefeSPatrick Mooney 	int error, flags;
399*4c87aefeSPatrick Mooney 
400*4c87aefeSPatrick Mooney 	/* Map 'len' bytes starting at 'gpa' in the guest address space */
401*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
402*4c87aefeSPatrick Mooney 	error = vm_mmap_memseg(ctx, gpa, VM_SYSMEM, gpa, len, PROT_ALL);
403*4c87aefeSPatrick Mooney #else
404*4c87aefeSPatrick Mooney 	/*
405*4c87aefeSPatrick Mooney 	 * As we use two segments for lowmem/highmem the offset within the
406*4c87aefeSPatrick Mooney 	 * segment is 0 on illumos.
407*4c87aefeSPatrick Mooney 	 */
408*4c87aefeSPatrick Mooney 	error = vm_mmap_memseg(ctx, gpa, segid, 0, len, PROT_ALL);
409*4c87aefeSPatrick Mooney #endif
410*4c87aefeSPatrick Mooney 	if (error)
411*4c87aefeSPatrick Mooney 		return (error);
412*4c87aefeSPatrick Mooney 
413*4c87aefeSPatrick Mooney 	flags = MAP_SHARED | MAP_FIXED;
414*4c87aefeSPatrick Mooney 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
415*4c87aefeSPatrick Mooney 		flags |= MAP_NOCORE;
416*4c87aefeSPatrick Mooney 
417*4c87aefeSPatrick Mooney 	/* mmap into the process address space on the host */
418*4c87aefeSPatrick Mooney 	ptr = mmap(base + gpa, len, PROT_RW, flags, ctx->fd, gpa);
419*4c87aefeSPatrick Mooney 	if (ptr == MAP_FAILED)
420*4c87aefeSPatrick Mooney 		return (-1);
421*4c87aefeSPatrick Mooney 
422*4c87aefeSPatrick Mooney 	return (0);
423*4c87aefeSPatrick Mooney }
424*4c87aefeSPatrick Mooney 
425bf21cd93STycho Nightingale int
426bf21cd93STycho Nightingale vm_setup_memory(struct vmctx *ctx, size_t memsize, enum vm_mmap_style vms)
427bf21cd93STycho Nightingale {
428*4c87aefeSPatrick Mooney 	size_t objsize, len;
429*4c87aefeSPatrick Mooney 	vm_paddr_t gpa;
430*4c87aefeSPatrick Mooney 	char *baseaddr, *ptr;
431bf21cd93STycho Nightingale 	int error;
432bf21cd93STycho Nightingale 
433*4c87aefeSPatrick Mooney 	assert(vms == VM_MMAP_ALL);
434bf21cd93STycho Nightingale 
435bf21cd93STycho Nightingale 	/*
436bf21cd93STycho Nightingale 	 * If 'memsize' cannot fit entirely in the 'lowmem' segment then
437bf21cd93STycho Nightingale 	 * create another 'highmem' segment above 4GB for the remainder.
438bf21cd93STycho Nightingale 	 */
439bf21cd93STycho Nightingale 	if (memsize > ctx->lowmem_limit) {
440bf21cd93STycho Nightingale 		ctx->lowmem = ctx->lowmem_limit;
441*4c87aefeSPatrick Mooney 		ctx->highmem = memsize - ctx->lowmem_limit;
442*4c87aefeSPatrick Mooney 		objsize = 4*GB + ctx->highmem;
443bf21cd93STycho Nightingale 	} else {
444bf21cd93STycho Nightingale 		ctx->lowmem = memsize;
445bf21cd93STycho Nightingale 		ctx->highmem = 0;
446*4c87aefeSPatrick Mooney 		objsize = ctx->lowmem;
447bf21cd93STycho Nightingale 	}
448bf21cd93STycho Nightingale 
449*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
450*4c87aefeSPatrick Mooney 	error = vm_alloc_memseg(ctx, VM_SYSMEM, objsize, NULL);
451*4c87aefeSPatrick Mooney 	if (error)
452*4c87aefeSPatrick Mooney 		return (error);
453*4c87aefeSPatrick Mooney #endif
454*4c87aefeSPatrick Mooney 
455*4c87aefeSPatrick Mooney 	/*
456*4c87aefeSPatrick Mooney 	 * Stake out a contiguous region covering the guest physical memory
457*4c87aefeSPatrick Mooney 	 * and the adjoining guard regions.
458*4c87aefeSPatrick Mooney 	 */
459*4c87aefeSPatrick Mooney 	len = VM_MMAP_GUARD_SIZE + objsize + VM_MMAP_GUARD_SIZE;
460*4c87aefeSPatrick Mooney 	ptr = mmap(NULL, len, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1, 0);
461*4c87aefeSPatrick Mooney 	if (ptr == MAP_FAILED)
462*4c87aefeSPatrick Mooney 		return (-1);
463*4c87aefeSPatrick Mooney 
464*4c87aefeSPatrick Mooney 	baseaddr = ptr + VM_MMAP_GUARD_SIZE;
465bf21cd93STycho Nightingale 
466*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
467*4c87aefeSPatrick Mooney 	if (ctx->highmem > 0) {
468*4c87aefeSPatrick Mooney 		gpa = 4*GB;
469*4c87aefeSPatrick Mooney 		len = ctx->highmem;
470*4c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
471bf21cd93STycho Nightingale 		if (error)
472bf21cd93STycho Nightingale 			return (error);
473*4c87aefeSPatrick Mooney 	}
474bf21cd93STycho Nightingale 
475*4c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
476*4c87aefeSPatrick Mooney 		gpa = 0;
477*4c87aefeSPatrick Mooney 		len = ctx->lowmem;
478*4c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, gpa, len, baseaddr);
479bf21cd93STycho Nightingale 		if (error)
480bf21cd93STycho Nightingale 			return (error);
481bf21cd93STycho Nightingale 	}
482*4c87aefeSPatrick Mooney #else
483bf21cd93STycho Nightingale 	if (ctx->highmem > 0) {
484*4c87aefeSPatrick Mooney 		error = vm_alloc_memseg(ctx, VM_HIGHMEM, ctx->highmem, NULL);
485*4c87aefeSPatrick Mooney 		if (error)
486*4c87aefeSPatrick Mooney 			return (error);
487*4c87aefeSPatrick Mooney 		gpa = 4*GB;
488*4c87aefeSPatrick Mooney 		len = ctx->highmem;
489*4c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, VM_HIGHMEM, gpa, len, baseaddr);
490bf21cd93STycho Nightingale 		if (error)
491bf21cd93STycho Nightingale 			return (error);
492bf21cd93STycho Nightingale 	}
493bf21cd93STycho Nightingale 
494*4c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
495*4c87aefeSPatrick Mooney 		error = vm_alloc_memseg(ctx, VM_LOWMEM, ctx->lowmem, NULL);
496*4c87aefeSPatrick Mooney 		if (error)
497*4c87aefeSPatrick Mooney 			return (error);
498*4c87aefeSPatrick Mooney 		gpa = 0;
499*4c87aefeSPatrick Mooney 		len = ctx->lowmem;
500*4c87aefeSPatrick Mooney 		error = setup_memory_segment(ctx, VM_LOWMEM, gpa, len, baseaddr);
501*4c87aefeSPatrick Mooney 		if (error)
502*4c87aefeSPatrick Mooney 			return (error);
503*4c87aefeSPatrick Mooney 	}
504*4c87aefeSPatrick Mooney #endif
505bf21cd93STycho Nightingale 
506*4c87aefeSPatrick Mooney 	ctx->baseaddr = baseaddr;
507bf21cd93STycho Nightingale 
508*4c87aefeSPatrick Mooney 	return (0);
509bf21cd93STycho Nightingale }
510bf21cd93STycho Nightingale 
511*4c87aefeSPatrick Mooney /*
512*4c87aefeSPatrick Mooney  * Returns a non-NULL pointer if [gaddr, gaddr+len) is entirely contained in
513*4c87aefeSPatrick Mooney  * the lowmem or highmem regions.
514*4c87aefeSPatrick Mooney  *
515*4c87aefeSPatrick Mooney  * In particular return NULL if [gaddr, gaddr+len) falls in guest MMIO region.
516*4c87aefeSPatrick Mooney  * The instruction emulation code depends on this behavior.
517*4c87aefeSPatrick Mooney  */
518bf21cd93STycho Nightingale void *
519bf21cd93STycho Nightingale vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len)
520bf21cd93STycho Nightingale {
521bf21cd93STycho Nightingale 
522*4c87aefeSPatrick Mooney 	if (ctx->lowmem > 0) {
523*4c87aefeSPatrick Mooney 		if (gaddr < ctx->lowmem && len <= ctx->lowmem &&
524*4c87aefeSPatrick Mooney 		    gaddr + len <= ctx->lowmem)
525*4c87aefeSPatrick Mooney 			return (ctx->baseaddr + gaddr);
526bf21cd93STycho Nightingale 	}
527bf21cd93STycho Nightingale 
528*4c87aefeSPatrick Mooney 	if (ctx->highmem > 0) {
529*4c87aefeSPatrick Mooney                 if (gaddr >= 4*GB) {
530*4c87aefeSPatrick Mooney 			if (gaddr < 4*GB + ctx->highmem &&
531*4c87aefeSPatrick Mooney 			    len <= ctx->highmem &&
532*4c87aefeSPatrick Mooney 			    gaddr + len <= 4*GB + ctx->highmem)
533*4c87aefeSPatrick Mooney 				return (ctx->baseaddr + gaddr);
534*4c87aefeSPatrick Mooney 		}
535bf21cd93STycho Nightingale 	}
536bf21cd93STycho Nightingale 
537bf21cd93STycho Nightingale 	return (NULL);
538bf21cd93STycho Nightingale }
539bf21cd93STycho Nightingale 
540bf21cd93STycho Nightingale size_t
541bf21cd93STycho Nightingale vm_get_lowmem_size(struct vmctx *ctx)
542bf21cd93STycho Nightingale {
543bf21cd93STycho Nightingale 
544bf21cd93STycho Nightingale 	return (ctx->lowmem);
545bf21cd93STycho Nightingale }
546bf21cd93STycho Nightingale 
547bf21cd93STycho Nightingale size_t
548bf21cd93STycho Nightingale vm_get_highmem_size(struct vmctx *ctx)
549bf21cd93STycho Nightingale {
550bf21cd93STycho Nightingale 
551bf21cd93STycho Nightingale 	return (ctx->highmem);
552bf21cd93STycho Nightingale }
553bf21cd93STycho Nightingale 
554*4c87aefeSPatrick Mooney void *
555*4c87aefeSPatrick Mooney vm_create_devmem(struct vmctx *ctx, int segid, const char *name, size_t len)
556*4c87aefeSPatrick Mooney {
557*4c87aefeSPatrick Mooney #ifdef	__FreeBSD__
558*4c87aefeSPatrick Mooney 	char pathname[MAXPATHLEN];
559*4c87aefeSPatrick Mooney #endif
560*4c87aefeSPatrick Mooney 	size_t len2;
561*4c87aefeSPatrick Mooney 	char *base, *ptr;
562*4c87aefeSPatrick Mooney 	int fd, error, flags;
563*4c87aefeSPatrick Mooney 	off_t mapoff;
564*4c87aefeSPatrick Mooney 
565*4c87aefeSPatrick Mooney 	fd = -1;
566*4c87aefeSPatrick Mooney 	ptr = MAP_FAILED;
567*4c87aefeSPatrick Mooney 	if (name == NULL || strlen(name) == 0) {
568*4c87aefeSPatrick Mooney 		errno = EINVAL;
569*4c87aefeSPatrick Mooney 		goto done;
570*4c87aefeSPatrick Mooney 	}
571*4c87aefeSPatrick Mooney 
572*4c87aefeSPatrick Mooney 	error = vm_alloc_memseg(ctx, segid, len, name);
573*4c87aefeSPatrick Mooney 	if (error)
574*4c87aefeSPatrick Mooney 		goto done;
575*4c87aefeSPatrick Mooney 
576*4c87aefeSPatrick Mooney #ifdef	__FreeBSD__
577*4c87aefeSPatrick Mooney 	strlcpy(pathname, "/dev/vmm.io/", sizeof(pathname));
578*4c87aefeSPatrick Mooney 	strlcat(pathname, ctx->name, sizeof(pathname));
579*4c87aefeSPatrick Mooney 	strlcat(pathname, ".", sizeof(pathname));
580*4c87aefeSPatrick Mooney 	strlcat(pathname, name, sizeof(pathname));
581*4c87aefeSPatrick Mooney 
582*4c87aefeSPatrick Mooney 	fd = open(pathname, O_RDWR);
583*4c87aefeSPatrick Mooney 	if (fd < 0)
584*4c87aefeSPatrick Mooney 		goto done;
585*4c87aefeSPatrick Mooney #else
586*4c87aefeSPatrick Mooney 	{
587*4c87aefeSPatrick Mooney 		struct vm_devmem_offset vdo;
588*4c87aefeSPatrick Mooney 
589*4c87aefeSPatrick Mooney 		vdo.segid = segid;
590*4c87aefeSPatrick Mooney 		error = ioctl(ctx->fd, VM_DEVMEM_GETOFFSET, &vdo);
591*4c87aefeSPatrick Mooney 		if (error == 0) {
592*4c87aefeSPatrick Mooney 			mapoff = vdo.offset;
593*4c87aefeSPatrick Mooney 		} else {
594*4c87aefeSPatrick Mooney 			goto done;
595*4c87aefeSPatrick Mooney 		}
596*4c87aefeSPatrick Mooney 	}
597*4c87aefeSPatrick Mooney #endif
598*4c87aefeSPatrick Mooney 
599*4c87aefeSPatrick Mooney 	/*
600*4c87aefeSPatrick Mooney 	 * Stake out a contiguous region covering the device memory and the
601*4c87aefeSPatrick Mooney 	 * adjoining guard regions.
602*4c87aefeSPatrick Mooney 	 */
603*4c87aefeSPatrick Mooney 	len2 = VM_MMAP_GUARD_SIZE + len + VM_MMAP_GUARD_SIZE;
604*4c87aefeSPatrick Mooney 	base = mmap(NULL, len2, PROT_NONE, MAP_GUARD | MAP_ALIGNED_SUPER, -1,
605*4c87aefeSPatrick Mooney 	    0);
606*4c87aefeSPatrick Mooney 	if (base == MAP_FAILED)
607*4c87aefeSPatrick Mooney 		goto done;
608*4c87aefeSPatrick Mooney 
609*4c87aefeSPatrick Mooney 	flags = MAP_SHARED | MAP_FIXED;
610*4c87aefeSPatrick Mooney 	if ((ctx->memflags & VM_MEM_F_INCORE) == 0)
611*4c87aefeSPatrick Mooney 		flags |= MAP_NOCORE;
612*4c87aefeSPatrick Mooney 
613*4c87aefeSPatrick Mooney #ifdef	__FreeBSD__
614*4c87aefeSPatrick Mooney 	/* mmap the devmem region in the host address space */
615*4c87aefeSPatrick Mooney 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, fd, 0);
616*4c87aefeSPatrick Mooney #else
617*4c87aefeSPatrick Mooney 	/* mmap the devmem region in the host address space */
618*4c87aefeSPatrick Mooney 	ptr = mmap(base + VM_MMAP_GUARD_SIZE, len, PROT_RW, flags, ctx->fd,
619*4c87aefeSPatrick Mooney 	    mapoff);
620*4c87aefeSPatrick Mooney #endif
621*4c87aefeSPatrick Mooney done:
622*4c87aefeSPatrick Mooney 	if (fd >= 0)
623*4c87aefeSPatrick Mooney 		close(fd);
624*4c87aefeSPatrick Mooney 	return (ptr);
625*4c87aefeSPatrick Mooney }
626*4c87aefeSPatrick Mooney 
627bf21cd93STycho Nightingale int
628bf21cd93STycho Nightingale vm_set_desc(struct vmctx *ctx, int vcpu, int reg,
629bf21cd93STycho Nightingale 	    uint64_t base, uint32_t limit, uint32_t access)
630bf21cd93STycho Nightingale {
631bf21cd93STycho Nightingale 	int error;
632bf21cd93STycho Nightingale 	struct vm_seg_desc vmsegdesc;
633bf21cd93STycho Nightingale 
634bf21cd93STycho Nightingale 	bzero(&vmsegdesc, sizeof(vmsegdesc));
635bf21cd93STycho Nightingale 	vmsegdesc.cpuid = vcpu;
636bf21cd93STycho Nightingale 	vmsegdesc.regnum = reg;
637bf21cd93STycho Nightingale 	vmsegdesc.desc.base = base;
638bf21cd93STycho Nightingale 	vmsegdesc.desc.limit = limit;
639bf21cd93STycho Nightingale 	vmsegdesc.desc.access = access;
640bf21cd93STycho Nightingale 
641bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_SEGMENT_DESCRIPTOR, &vmsegdesc);
642bf21cd93STycho Nightingale 	return (error);
643bf21cd93STycho Nightingale }
644bf21cd93STycho Nightingale 
645bf21cd93STycho Nightingale int
646bf21cd93STycho Nightingale vm_get_desc(struct vmctx *ctx, int vcpu, int reg,
647bf21cd93STycho Nightingale 	    uint64_t *base, uint32_t *limit, uint32_t *access)
648bf21cd93STycho Nightingale {
649bf21cd93STycho Nightingale 	int error;
650bf21cd93STycho Nightingale 	struct vm_seg_desc vmsegdesc;
651bf21cd93STycho Nightingale 
652bf21cd93STycho Nightingale 	bzero(&vmsegdesc, sizeof(vmsegdesc));
653bf21cd93STycho Nightingale 	vmsegdesc.cpuid = vcpu;
654bf21cd93STycho Nightingale 	vmsegdesc.regnum = reg;
655bf21cd93STycho Nightingale 
656bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_SEGMENT_DESCRIPTOR, &vmsegdesc);
657bf21cd93STycho Nightingale 	if (error == 0) {
658bf21cd93STycho Nightingale 		*base = vmsegdesc.desc.base;
659bf21cd93STycho Nightingale 		*limit = vmsegdesc.desc.limit;
660bf21cd93STycho Nightingale 		*access = vmsegdesc.desc.access;
661bf21cd93STycho Nightingale 	}
662bf21cd93STycho Nightingale 	return (error);
663bf21cd93STycho Nightingale }
664bf21cd93STycho Nightingale 
665bf21cd93STycho Nightingale int
666bf21cd93STycho Nightingale vm_get_seg_desc(struct vmctx *ctx, int vcpu, int reg, struct seg_desc *seg_desc)
667bf21cd93STycho Nightingale {
668bf21cd93STycho Nightingale 	int error;
669bf21cd93STycho Nightingale 
670bf21cd93STycho Nightingale 	error = vm_get_desc(ctx, vcpu, reg, &seg_desc->base, &seg_desc->limit,
671bf21cd93STycho Nightingale 	    &seg_desc->access);
672bf21cd93STycho Nightingale 	return (error);
673bf21cd93STycho Nightingale }
674bf21cd93STycho Nightingale 
675bf21cd93STycho Nightingale int
676bf21cd93STycho Nightingale vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
677bf21cd93STycho Nightingale {
678bf21cd93STycho Nightingale 	int error;
679bf21cd93STycho Nightingale 	struct vm_register vmreg;
680bf21cd93STycho Nightingale 
681bf21cd93STycho Nightingale 	bzero(&vmreg, sizeof(vmreg));
682bf21cd93STycho Nightingale 	vmreg.cpuid = vcpu;
683bf21cd93STycho Nightingale 	vmreg.regnum = reg;
684bf21cd93STycho Nightingale 	vmreg.regval = val;
685bf21cd93STycho Nightingale 
686bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
687bf21cd93STycho Nightingale 	return (error);
688bf21cd93STycho Nightingale }
689bf21cd93STycho Nightingale 
690bf21cd93STycho Nightingale int
691bf21cd93STycho Nightingale vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
692bf21cd93STycho Nightingale {
693bf21cd93STycho Nightingale 	int error;
694bf21cd93STycho Nightingale 	struct vm_register vmreg;
695bf21cd93STycho Nightingale 
696bf21cd93STycho Nightingale 	bzero(&vmreg, sizeof(vmreg));
697bf21cd93STycho Nightingale 	vmreg.cpuid = vcpu;
698bf21cd93STycho Nightingale 	vmreg.regnum = reg;
699bf21cd93STycho Nightingale 
700bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_REGISTER, &vmreg);
701bf21cd93STycho Nightingale 	*ret_val = vmreg.regval;
702bf21cd93STycho Nightingale 	return (error);
703bf21cd93STycho Nightingale }
704bf21cd93STycho Nightingale 
705*4c87aefeSPatrick Mooney int
706*4c87aefeSPatrick Mooney vm_set_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
707*4c87aefeSPatrick Mooney     const int *regnums, uint64_t *regvals)
708*4c87aefeSPatrick Mooney {
709*4c87aefeSPatrick Mooney 	int error;
710*4c87aefeSPatrick Mooney 	struct vm_register_set vmregset;
711*4c87aefeSPatrick Mooney 
712*4c87aefeSPatrick Mooney 	bzero(&vmregset, sizeof(vmregset));
713*4c87aefeSPatrick Mooney 	vmregset.cpuid = vcpu;
714*4c87aefeSPatrick Mooney 	vmregset.count = count;
715*4c87aefeSPatrick Mooney 	vmregset.regnums = regnums;
716*4c87aefeSPatrick Mooney 	vmregset.regvals = regvals;
717*4c87aefeSPatrick Mooney 
718*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SET_REGISTER_SET, &vmregset);
719*4c87aefeSPatrick Mooney 	return (error);
720*4c87aefeSPatrick Mooney }
721*4c87aefeSPatrick Mooney 
722*4c87aefeSPatrick Mooney int
723*4c87aefeSPatrick Mooney vm_get_register_set(struct vmctx *ctx, int vcpu, unsigned int count,
724*4c87aefeSPatrick Mooney     const int *regnums, uint64_t *regvals)
725*4c87aefeSPatrick Mooney {
726*4c87aefeSPatrick Mooney 	int error;
727*4c87aefeSPatrick Mooney 	struct vm_register_set vmregset;
728*4c87aefeSPatrick Mooney 
729*4c87aefeSPatrick Mooney 	bzero(&vmregset, sizeof(vmregset));
730*4c87aefeSPatrick Mooney 	vmregset.cpuid = vcpu;
731*4c87aefeSPatrick Mooney 	vmregset.count = count;
732*4c87aefeSPatrick Mooney 	vmregset.regnums = regnums;
733*4c87aefeSPatrick Mooney 	vmregset.regvals = regvals;
734*4c87aefeSPatrick Mooney 
735*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_REGISTER_SET, &vmregset);
736*4c87aefeSPatrick Mooney 	return (error);
737*4c87aefeSPatrick Mooney }
738*4c87aefeSPatrick Mooney 
739bf21cd93STycho Nightingale int
740bf21cd93STycho Nightingale vm_run(struct vmctx *ctx, int vcpu, struct vm_exit *vmexit)
741bf21cd93STycho Nightingale {
742bf21cd93STycho Nightingale 	int error;
743bf21cd93STycho Nightingale 	struct vm_run vmrun;
744bf21cd93STycho Nightingale 
745bf21cd93STycho Nightingale 	bzero(&vmrun, sizeof(vmrun));
746bf21cd93STycho Nightingale 	vmrun.cpuid = vcpu;
747bf21cd93STycho Nightingale 
748bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_RUN, &vmrun);
749bf21cd93STycho Nightingale 	bcopy(&vmrun.vm_exit, vmexit, sizeof(struct vm_exit));
750bf21cd93STycho Nightingale 	return (error);
751bf21cd93STycho Nightingale }
752bf21cd93STycho Nightingale 
753*4c87aefeSPatrick Mooney int
754*4c87aefeSPatrick Mooney vm_suspend(struct vmctx *ctx, enum vm_suspend_how how)
755bf21cd93STycho Nightingale {
756*4c87aefeSPatrick Mooney 	struct vm_suspend vmsuspend;
757bf21cd93STycho Nightingale 
758*4c87aefeSPatrick Mooney 	bzero(&vmsuspend, sizeof(vmsuspend));
759*4c87aefeSPatrick Mooney 	vmsuspend.how = how;
760*4c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_SUSPEND, &vmsuspend));
761*4c87aefeSPatrick Mooney }
762bf21cd93STycho Nightingale 
763*4c87aefeSPatrick Mooney int
764*4c87aefeSPatrick Mooney vm_reinit(struct vmctx *ctx)
765*4c87aefeSPatrick Mooney {
766*4c87aefeSPatrick Mooney 
767*4c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_REINIT, 0));
768bf21cd93STycho Nightingale }
769bf21cd93STycho Nightingale 
770bf21cd93STycho Nightingale int
771bf21cd93STycho Nightingale vm_inject_exception(struct vmctx *ctx, int vcpu, int vector, int errcode_valid,
772bf21cd93STycho Nightingale     uint32_t errcode, int restart_instruction)
773bf21cd93STycho Nightingale {
774bf21cd93STycho Nightingale 	struct vm_exception exc;
775bf21cd93STycho Nightingale 
776bf21cd93STycho Nightingale 	exc.cpuid = vcpu;
777bf21cd93STycho Nightingale 	exc.vector = vector;
778bf21cd93STycho Nightingale 	exc.error_code = errcode;
779bf21cd93STycho Nightingale 	exc.error_code_valid = errcode_valid;
780bf21cd93STycho Nightingale 	exc.restart_instruction = restart_instruction;
781bf21cd93STycho Nightingale 
782bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_INJECT_EXCEPTION, &exc));
783bf21cd93STycho Nightingale }
784bf21cd93STycho Nightingale 
785bf21cd93STycho Nightingale int
786bf21cd93STycho Nightingale vm_apicid2vcpu(struct vmctx *ctx, int apicid)
787bf21cd93STycho Nightingale {
788bf21cd93STycho Nightingale 	/*
789bf21cd93STycho Nightingale 	 * The apic id associated with the 'vcpu' has the same numerical value
790bf21cd93STycho Nightingale 	 * as the 'vcpu' itself.
791bf21cd93STycho Nightingale 	 */
792bf21cd93STycho Nightingale 	return (apicid);
793bf21cd93STycho Nightingale }
794bf21cd93STycho Nightingale 
795bf21cd93STycho Nightingale int
796bf21cd93STycho Nightingale vm_lapic_irq(struct vmctx *ctx, int vcpu, int vector)
797bf21cd93STycho Nightingale {
798bf21cd93STycho Nightingale 	struct vm_lapic_irq vmirq;
799bf21cd93STycho Nightingale 
800bf21cd93STycho Nightingale 	bzero(&vmirq, sizeof(vmirq));
801bf21cd93STycho Nightingale 	vmirq.cpuid = vcpu;
802bf21cd93STycho Nightingale 	vmirq.vector = vector;
803bf21cd93STycho Nightingale 
804bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_IRQ, &vmirq));
805bf21cd93STycho Nightingale }
806bf21cd93STycho Nightingale 
807bf21cd93STycho Nightingale int
808bf21cd93STycho Nightingale vm_lapic_local_irq(struct vmctx *ctx, int vcpu, int vector)
809bf21cd93STycho Nightingale {
810bf21cd93STycho Nightingale 	struct vm_lapic_irq vmirq;
811bf21cd93STycho Nightingale 
812bf21cd93STycho Nightingale 	bzero(&vmirq, sizeof(vmirq));
813bf21cd93STycho Nightingale 	vmirq.cpuid = vcpu;
814bf21cd93STycho Nightingale 	vmirq.vector = vector;
815bf21cd93STycho Nightingale 
816bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_LOCAL_IRQ, &vmirq));
817bf21cd93STycho Nightingale }
818bf21cd93STycho Nightingale 
819bf21cd93STycho Nightingale int
820bf21cd93STycho Nightingale vm_lapic_msi(struct vmctx *ctx, uint64_t addr, uint64_t msg)
821bf21cd93STycho Nightingale {
822bf21cd93STycho Nightingale 	struct vm_lapic_msi vmmsi;
823bf21cd93STycho Nightingale 
824bf21cd93STycho Nightingale 	bzero(&vmmsi, sizeof(vmmsi));
825bf21cd93STycho Nightingale 	vmmsi.addr = addr;
826bf21cd93STycho Nightingale 	vmmsi.msg = msg;
827bf21cd93STycho Nightingale 
828bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_LAPIC_MSI, &vmmsi));
829bf21cd93STycho Nightingale }
830bf21cd93STycho Nightingale 
831bf21cd93STycho Nightingale int
832bf21cd93STycho Nightingale vm_ioapic_assert_irq(struct vmctx *ctx, int irq)
833bf21cd93STycho Nightingale {
834bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
835bf21cd93STycho Nightingale 
836bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
837bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
838bf21cd93STycho Nightingale 
839bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_ASSERT_IRQ, &ioapic_irq));
840bf21cd93STycho Nightingale }
841bf21cd93STycho Nightingale 
842bf21cd93STycho Nightingale int
843bf21cd93STycho Nightingale vm_ioapic_deassert_irq(struct vmctx *ctx, int irq)
844bf21cd93STycho Nightingale {
845bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
846bf21cd93STycho Nightingale 
847bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
848bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
849bf21cd93STycho Nightingale 
850bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_DEASSERT_IRQ, &ioapic_irq));
851bf21cd93STycho Nightingale }
852bf21cd93STycho Nightingale 
853bf21cd93STycho Nightingale int
854bf21cd93STycho Nightingale vm_ioapic_pulse_irq(struct vmctx *ctx, int irq)
855bf21cd93STycho Nightingale {
856bf21cd93STycho Nightingale 	struct vm_ioapic_irq ioapic_irq;
857bf21cd93STycho Nightingale 
858bf21cd93STycho Nightingale 	bzero(&ioapic_irq, sizeof(struct vm_ioapic_irq));
859bf21cd93STycho Nightingale 	ioapic_irq.irq = irq;
860bf21cd93STycho Nightingale 
861bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_PULSE_IRQ, &ioapic_irq));
862bf21cd93STycho Nightingale }
863bf21cd93STycho Nightingale 
864bf21cd93STycho Nightingale int
865bf21cd93STycho Nightingale vm_ioapic_pincount(struct vmctx *ctx, int *pincount)
866bf21cd93STycho Nightingale {
867bf21cd93STycho Nightingale 
868bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
869bf21cd93STycho Nightingale }
870bf21cd93STycho Nightingale 
871bf21cd93STycho Nightingale int
872bf21cd93STycho Nightingale vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
873bf21cd93STycho Nightingale {
874bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
875bf21cd93STycho Nightingale 
876bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
877bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
878bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
879bf21cd93STycho Nightingale 
880bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_ASSERT_IRQ, &isa_irq));
881bf21cd93STycho Nightingale }
882bf21cd93STycho Nightingale 
883bf21cd93STycho Nightingale int
884bf21cd93STycho Nightingale vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
885bf21cd93STycho Nightingale {
886bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
887bf21cd93STycho Nightingale 
888bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
889bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
890bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
891bf21cd93STycho Nightingale 
892bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_DEASSERT_IRQ, &isa_irq));
893bf21cd93STycho Nightingale }
894bf21cd93STycho Nightingale 
895bf21cd93STycho Nightingale int
896bf21cd93STycho Nightingale vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
897bf21cd93STycho Nightingale {
898bf21cd93STycho Nightingale 	struct vm_isa_irq isa_irq;
899bf21cd93STycho Nightingale 
900bf21cd93STycho Nightingale 	bzero(&isa_irq, sizeof(struct vm_isa_irq));
901bf21cd93STycho Nightingale 	isa_irq.atpic_irq = atpic_irq;
902bf21cd93STycho Nightingale 	isa_irq.ioapic_irq = ioapic_irq;
903bf21cd93STycho Nightingale 
904bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_PULSE_IRQ, &isa_irq));
905bf21cd93STycho Nightingale }
906bf21cd93STycho Nightingale 
907bf21cd93STycho Nightingale int
908bf21cd93STycho Nightingale vm_isa_set_irq_trigger(struct vmctx *ctx, int atpic_irq,
909bf21cd93STycho Nightingale     enum vm_intr_trigger trigger)
910bf21cd93STycho Nightingale {
911bf21cd93STycho Nightingale 	struct vm_isa_irq_trigger isa_irq_trigger;
912bf21cd93STycho Nightingale 
913bf21cd93STycho Nightingale 	bzero(&isa_irq_trigger, sizeof(struct vm_isa_irq_trigger));
914bf21cd93STycho Nightingale 	isa_irq_trigger.atpic_irq = atpic_irq;
915bf21cd93STycho Nightingale 	isa_irq_trigger.trigger = trigger;
916bf21cd93STycho Nightingale 
917bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_ISA_SET_IRQ_TRIGGER, &isa_irq_trigger));
918bf21cd93STycho Nightingale }
919bf21cd93STycho Nightingale 
920bf21cd93STycho Nightingale int
921bf21cd93STycho Nightingale vm_inject_nmi(struct vmctx *ctx, int vcpu)
922bf21cd93STycho Nightingale {
923bf21cd93STycho Nightingale 	struct vm_nmi vmnmi;
924bf21cd93STycho Nightingale 
925bf21cd93STycho Nightingale 	bzero(&vmnmi, sizeof(vmnmi));
926bf21cd93STycho Nightingale 	vmnmi.cpuid = vcpu;
927bf21cd93STycho Nightingale 
928bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_INJECT_NMI, &vmnmi));
929bf21cd93STycho Nightingale }
930bf21cd93STycho Nightingale 
931bf21cd93STycho Nightingale static struct {
932bf21cd93STycho Nightingale 	const char	*name;
933bf21cd93STycho Nightingale 	int		type;
934bf21cd93STycho Nightingale } capstrmap[] = {
935bf21cd93STycho Nightingale 	{ "hlt_exit",		VM_CAP_HALT_EXIT },
936bf21cd93STycho Nightingale 	{ "mtrap_exit",		VM_CAP_MTRAP_EXIT },
937bf21cd93STycho Nightingale 	{ "pause_exit",		VM_CAP_PAUSE_EXIT },
938bf21cd93STycho Nightingale 	{ "unrestricted_guest",	VM_CAP_UNRESTRICTED_GUEST },
939bf21cd93STycho Nightingale 	{ "enable_invpcid",	VM_CAP_ENABLE_INVPCID },
940bf21cd93STycho Nightingale 	{ 0 }
941bf21cd93STycho Nightingale };
942bf21cd93STycho Nightingale 
943bf21cd93STycho Nightingale int
944bf21cd93STycho Nightingale vm_capability_name2type(const char *capname)
945bf21cd93STycho Nightingale {
946bf21cd93STycho Nightingale 	int i;
947bf21cd93STycho Nightingale 
948bf21cd93STycho Nightingale 	for (i = 0; capstrmap[i].name != NULL && capname != NULL; i++) {
949bf21cd93STycho Nightingale 		if (strcmp(capstrmap[i].name, capname) == 0)
950bf21cd93STycho Nightingale 			return (capstrmap[i].type);
951bf21cd93STycho Nightingale 	}
952bf21cd93STycho Nightingale 
953bf21cd93STycho Nightingale 	return (-1);
954bf21cd93STycho Nightingale }
955bf21cd93STycho Nightingale 
956bf21cd93STycho Nightingale const char *
957bf21cd93STycho Nightingale vm_capability_type2name(int type)
958bf21cd93STycho Nightingale {
959bf21cd93STycho Nightingale 	int i;
960bf21cd93STycho Nightingale 
961bf21cd93STycho Nightingale 	for (i = 0; capstrmap[i].name != NULL; i++) {
962bf21cd93STycho Nightingale 		if (capstrmap[i].type == type)
963bf21cd93STycho Nightingale 			return (capstrmap[i].name);
964bf21cd93STycho Nightingale 	}
965bf21cd93STycho Nightingale 
966bf21cd93STycho Nightingale 	return (NULL);
967bf21cd93STycho Nightingale }
968bf21cd93STycho Nightingale 
969bf21cd93STycho Nightingale int
970bf21cd93STycho Nightingale vm_get_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap,
971bf21cd93STycho Nightingale 		  int *retval)
972bf21cd93STycho Nightingale {
973bf21cd93STycho Nightingale 	int error;
974bf21cd93STycho Nightingale 	struct vm_capability vmcap;
975bf21cd93STycho Nightingale 
976bf21cd93STycho Nightingale 	bzero(&vmcap, sizeof(vmcap));
977bf21cd93STycho Nightingale 	vmcap.cpuid = vcpu;
978bf21cd93STycho Nightingale 	vmcap.captype = cap;
979bf21cd93STycho Nightingale 
980bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_CAPABILITY, &vmcap);
981bf21cd93STycho Nightingale 	*retval = vmcap.capval;
982bf21cd93STycho Nightingale 	return (error);
983bf21cd93STycho Nightingale }
984bf21cd93STycho Nightingale 
985bf21cd93STycho Nightingale int
986bf21cd93STycho Nightingale vm_set_capability(struct vmctx *ctx, int vcpu, enum vm_cap_type cap, int val)
987bf21cd93STycho Nightingale {
988bf21cd93STycho Nightingale 	struct vm_capability vmcap;
989bf21cd93STycho Nightingale 
990bf21cd93STycho Nightingale 	bzero(&vmcap, sizeof(vmcap));
991bf21cd93STycho Nightingale 	vmcap.cpuid = vcpu;
992bf21cd93STycho Nightingale 	vmcap.captype = cap;
993bf21cd93STycho Nightingale 	vmcap.capval = val;
994*4c87aefeSPatrick Mooney 
995bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_SET_CAPABILITY, &vmcap));
996bf21cd93STycho Nightingale }
997bf21cd93STycho Nightingale 
998bf21cd93STycho Nightingale int
999bf21cd93STycho Nightingale vm_assign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1000bf21cd93STycho Nightingale {
1001bf21cd93STycho Nightingale 	struct vm_pptdev pptdev;
1002bf21cd93STycho Nightingale 
1003bf21cd93STycho Nightingale 	bzero(&pptdev, sizeof(pptdev));
1004bf21cd93STycho Nightingale 	pptdev.bus = bus;
1005bf21cd93STycho Nightingale 	pptdev.slot = slot;
1006bf21cd93STycho Nightingale 	pptdev.func = func;
1007bf21cd93STycho Nightingale 
1008bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_BIND_PPTDEV, &pptdev));
1009bf21cd93STycho Nightingale }
1010bf21cd93STycho Nightingale 
1011bf21cd93STycho Nightingale int
1012bf21cd93STycho Nightingale vm_unassign_pptdev(struct vmctx *ctx, int bus, int slot, int func)
1013bf21cd93STycho Nightingale {
1014bf21cd93STycho Nightingale 	struct vm_pptdev pptdev;
1015bf21cd93STycho Nightingale 
1016bf21cd93STycho Nightingale 	bzero(&pptdev, sizeof(pptdev));
1017bf21cd93STycho Nightingale 	pptdev.bus = bus;
1018bf21cd93STycho Nightingale 	pptdev.slot = slot;
1019bf21cd93STycho Nightingale 	pptdev.func = func;
1020bf21cd93STycho Nightingale 
1021bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_UNBIND_PPTDEV, &pptdev));
1022bf21cd93STycho Nightingale }
1023bf21cd93STycho Nightingale 
1024bf21cd93STycho Nightingale int
1025bf21cd93STycho Nightingale vm_map_pptdev_mmio(struct vmctx *ctx, int bus, int slot, int func,
1026bf21cd93STycho Nightingale 		   vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
1027bf21cd93STycho Nightingale {
1028bf21cd93STycho Nightingale 	struct vm_pptdev_mmio pptmmio;
1029bf21cd93STycho Nightingale 
1030bf21cd93STycho Nightingale 	bzero(&pptmmio, sizeof(pptmmio));
1031bf21cd93STycho Nightingale 	pptmmio.bus = bus;
1032bf21cd93STycho Nightingale 	pptmmio.slot = slot;
1033bf21cd93STycho Nightingale 	pptmmio.func = func;
1034bf21cd93STycho Nightingale 	pptmmio.gpa = gpa;
1035bf21cd93STycho Nightingale 	pptmmio.len = len;
1036bf21cd93STycho Nightingale 	pptmmio.hpa = hpa;
1037bf21cd93STycho Nightingale 
1038bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_MAP_PPTDEV_MMIO, &pptmmio));
1039bf21cd93STycho Nightingale }
1040bf21cd93STycho Nightingale 
1041bf21cd93STycho Nightingale int
1042bf21cd93STycho Nightingale vm_setup_pptdev_msi(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
1043bf21cd93STycho Nightingale     uint64_t addr, uint64_t msg, int numvec)
1044bf21cd93STycho Nightingale {
1045bf21cd93STycho Nightingale 	struct vm_pptdev_msi pptmsi;
1046bf21cd93STycho Nightingale 
1047bf21cd93STycho Nightingale 	bzero(&pptmsi, sizeof(pptmsi));
1048bf21cd93STycho Nightingale 	pptmsi.vcpu = vcpu;
1049bf21cd93STycho Nightingale 	pptmsi.bus = bus;
1050bf21cd93STycho Nightingale 	pptmsi.slot = slot;
1051bf21cd93STycho Nightingale 	pptmsi.func = func;
1052bf21cd93STycho Nightingale 	pptmsi.msg = msg;
1053bf21cd93STycho Nightingale 	pptmsi.addr = addr;
1054bf21cd93STycho Nightingale 	pptmsi.numvec = numvec;
1055bf21cd93STycho Nightingale 
1056bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_PPTDEV_MSI, &pptmsi));
1057bf21cd93STycho Nightingale }
1058bf21cd93STycho Nightingale 
1059bf21cd93STycho Nightingale int
1060bf21cd93STycho Nightingale vm_setup_pptdev_msix(struct vmctx *ctx, int vcpu, int bus, int slot, int func,
1061bf21cd93STycho Nightingale     int idx, uint64_t addr, uint64_t msg, uint32_t vector_control)
1062bf21cd93STycho Nightingale {
1063bf21cd93STycho Nightingale 	struct vm_pptdev_msix pptmsix;
1064bf21cd93STycho Nightingale 
1065bf21cd93STycho Nightingale 	bzero(&pptmsix, sizeof(pptmsix));
1066bf21cd93STycho Nightingale 	pptmsix.vcpu = vcpu;
1067bf21cd93STycho Nightingale 	pptmsix.bus = bus;
1068bf21cd93STycho Nightingale 	pptmsix.slot = slot;
1069bf21cd93STycho Nightingale 	pptmsix.func = func;
1070bf21cd93STycho Nightingale 	pptmsix.idx = idx;
1071bf21cd93STycho Nightingale 	pptmsix.msg = msg;
1072bf21cd93STycho Nightingale 	pptmsix.addr = addr;
1073bf21cd93STycho Nightingale 	pptmsix.vector_control = vector_control;
1074bf21cd93STycho Nightingale 
1075bf21cd93STycho Nightingale 	return ioctl(ctx->fd, VM_PPTDEV_MSIX, &pptmsix);
1076bf21cd93STycho Nightingale }
1077bf21cd93STycho Nightingale 
1078bf21cd93STycho Nightingale uint64_t *
1079bf21cd93STycho Nightingale vm_get_stats(struct vmctx *ctx, int vcpu, struct timeval *ret_tv,
1080bf21cd93STycho Nightingale 	     int *ret_entries)
1081bf21cd93STycho Nightingale {
1082bf21cd93STycho Nightingale 	int error;
1083bf21cd93STycho Nightingale 
1084bf21cd93STycho Nightingale 	static struct vm_stats vmstats;
1085bf21cd93STycho Nightingale 
1086bf21cd93STycho Nightingale 	vmstats.cpuid = vcpu;
1087bf21cd93STycho Nightingale 
1088*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_STATS_IOC, &vmstats);
1089bf21cd93STycho Nightingale 	if (error == 0) {
1090bf21cd93STycho Nightingale 		if (ret_entries)
1091bf21cd93STycho Nightingale 			*ret_entries = vmstats.num_entries;
1092bf21cd93STycho Nightingale 		if (ret_tv)
1093bf21cd93STycho Nightingale 			*ret_tv = vmstats.tv;
1094bf21cd93STycho Nightingale 		return (vmstats.statbuf);
1095bf21cd93STycho Nightingale 	} else
1096bf21cd93STycho Nightingale 		return (NULL);
1097bf21cd93STycho Nightingale }
1098bf21cd93STycho Nightingale 
1099bf21cd93STycho Nightingale const char *
1100bf21cd93STycho Nightingale vm_get_stat_desc(struct vmctx *ctx, int index)
1101bf21cd93STycho Nightingale {
1102bf21cd93STycho Nightingale 	static struct vm_stat_desc statdesc;
1103bf21cd93STycho Nightingale 
1104bf21cd93STycho Nightingale 	statdesc.index = index;
1105bf21cd93STycho Nightingale 	if (ioctl(ctx->fd, VM_STAT_DESC, &statdesc) == 0)
1106bf21cd93STycho Nightingale 		return (statdesc.desc);
1107bf21cd93STycho Nightingale 	else
1108bf21cd93STycho Nightingale 		return (NULL);
1109bf21cd93STycho Nightingale }
1110bf21cd93STycho Nightingale 
1111bf21cd93STycho Nightingale int
1112bf21cd93STycho Nightingale vm_get_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state *state)
1113bf21cd93STycho Nightingale {
1114bf21cd93STycho Nightingale 	int error;
1115bf21cd93STycho Nightingale 	struct vm_x2apic x2apic;
1116bf21cd93STycho Nightingale 
1117bf21cd93STycho Nightingale 	bzero(&x2apic, sizeof(x2apic));
1118bf21cd93STycho Nightingale 	x2apic.cpuid = vcpu;
1119bf21cd93STycho Nightingale 
1120bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_X2APIC_STATE, &x2apic);
1121bf21cd93STycho Nightingale 	*state = x2apic.state;
1122bf21cd93STycho Nightingale 	return (error);
1123bf21cd93STycho Nightingale }
1124bf21cd93STycho Nightingale 
1125bf21cd93STycho Nightingale int
1126bf21cd93STycho Nightingale vm_set_x2apic_state(struct vmctx *ctx, int vcpu, enum x2apic_state state)
1127bf21cd93STycho Nightingale {
1128bf21cd93STycho Nightingale 	int error;
1129bf21cd93STycho Nightingale 	struct vm_x2apic x2apic;
1130bf21cd93STycho Nightingale 
1131bf21cd93STycho Nightingale 	bzero(&x2apic, sizeof(x2apic));
1132bf21cd93STycho Nightingale 	x2apic.cpuid = vcpu;
1133bf21cd93STycho Nightingale 	x2apic.state = state;
1134bf21cd93STycho Nightingale 
1135bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_SET_X2APIC_STATE, &x2apic);
1136bf21cd93STycho Nightingale 
1137bf21cd93STycho Nightingale 	return (error);
1138bf21cd93STycho Nightingale }
1139bf21cd93STycho Nightingale 
1140bf21cd93STycho Nightingale /*
1141bf21cd93STycho Nightingale  * From Intel Vol 3a:
1142bf21cd93STycho Nightingale  * Table 9-1. IA-32 Processor States Following Power-up, Reset or INIT
1143bf21cd93STycho Nightingale  */
1144bf21cd93STycho Nightingale int
1145bf21cd93STycho Nightingale vcpu_reset(struct vmctx *vmctx, int vcpu)
1146bf21cd93STycho Nightingale {
1147bf21cd93STycho Nightingale 	int error;
1148bf21cd93STycho Nightingale 	uint64_t rflags, rip, cr0, cr4, zero, desc_base, rdx;
1149bf21cd93STycho Nightingale 	uint32_t desc_access, desc_limit;
1150bf21cd93STycho Nightingale 	uint16_t sel;
1151bf21cd93STycho Nightingale 
1152bf21cd93STycho Nightingale 	zero = 0;
1153bf21cd93STycho Nightingale 
1154bf21cd93STycho Nightingale 	rflags = 0x2;
1155bf21cd93STycho Nightingale 	error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RFLAGS, rflags);
1156bf21cd93STycho Nightingale 	if (error)
1157bf21cd93STycho Nightingale 		goto done;
1158bf21cd93STycho Nightingale 
1159bf21cd93STycho Nightingale 	rip = 0xfff0;
1160bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RIP, rip)) != 0)
1161bf21cd93STycho Nightingale 		goto done;
1162bf21cd93STycho Nightingale 
1163bf21cd93STycho Nightingale 	cr0 = CR0_NE;
1164bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR0, cr0)) != 0)
1165bf21cd93STycho Nightingale 		goto done;
1166bf21cd93STycho Nightingale 
1167bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR3, zero)) != 0)
1168bf21cd93STycho Nightingale 		goto done;
1169bf21cd93STycho Nightingale 
1170bf21cd93STycho Nightingale 	cr4 = 0;
1171bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CR4, cr4)) != 0)
1172bf21cd93STycho Nightingale 		goto done;
1173bf21cd93STycho Nightingale 
1174bf21cd93STycho Nightingale 	/*
1175bf21cd93STycho Nightingale 	 * CS: present, r/w, accessed, 16-bit, byte granularity, usable
1176bf21cd93STycho Nightingale 	 */
1177bf21cd93STycho Nightingale 	desc_base = 0xffff0000;
1178bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1179bf21cd93STycho Nightingale 	desc_access = 0x0093;
1180bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_CS,
1181bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1182bf21cd93STycho Nightingale 	if (error)
1183bf21cd93STycho Nightingale 		goto done;
1184bf21cd93STycho Nightingale 
1185bf21cd93STycho Nightingale 	sel = 0xf000;
1186bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_CS, sel)) != 0)
1187bf21cd93STycho Nightingale 		goto done;
1188bf21cd93STycho Nightingale 
1189bf21cd93STycho Nightingale 	/*
1190bf21cd93STycho Nightingale 	 * SS,DS,ES,FS,GS: present, r/w, accessed, 16-bit, byte granularity
1191bf21cd93STycho Nightingale 	 */
1192bf21cd93STycho Nightingale 	desc_base = 0;
1193bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1194bf21cd93STycho Nightingale 	desc_access = 0x0093;
1195bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_SS,
1196bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1197bf21cd93STycho Nightingale 	if (error)
1198bf21cd93STycho Nightingale 		goto done;
1199bf21cd93STycho Nightingale 
1200bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_DS,
1201bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1202bf21cd93STycho Nightingale 	if (error)
1203bf21cd93STycho Nightingale 		goto done;
1204bf21cd93STycho Nightingale 
1205bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_ES,
1206bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1207bf21cd93STycho Nightingale 	if (error)
1208bf21cd93STycho Nightingale 		goto done;
1209bf21cd93STycho Nightingale 
1210bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_FS,
1211bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1212bf21cd93STycho Nightingale 	if (error)
1213bf21cd93STycho Nightingale 		goto done;
1214bf21cd93STycho Nightingale 
1215bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GS,
1216bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1217bf21cd93STycho Nightingale 	if (error)
1218bf21cd93STycho Nightingale 		goto done;
1219bf21cd93STycho Nightingale 
1220bf21cd93STycho Nightingale 	sel = 0;
1221bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_SS, sel)) != 0)
1222bf21cd93STycho Nightingale 		goto done;
1223bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_DS, sel)) != 0)
1224bf21cd93STycho Nightingale 		goto done;
1225bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_ES, sel)) != 0)
1226bf21cd93STycho Nightingale 		goto done;
1227bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_FS, sel)) != 0)
1228bf21cd93STycho Nightingale 		goto done;
1229bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_GS, sel)) != 0)
1230bf21cd93STycho Nightingale 		goto done;
1231bf21cd93STycho Nightingale 
1232bf21cd93STycho Nightingale 	/* General purpose registers */
1233bf21cd93STycho Nightingale 	rdx = 0xf00;
1234bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RAX, zero)) != 0)
1235bf21cd93STycho Nightingale 		goto done;
1236bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBX, zero)) != 0)
1237bf21cd93STycho Nightingale 		goto done;
1238bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RCX, zero)) != 0)
1239bf21cd93STycho Nightingale 		goto done;
1240bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDX, rdx)) != 0)
1241bf21cd93STycho Nightingale 		goto done;
1242bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSI, zero)) != 0)
1243bf21cd93STycho Nightingale 		goto done;
1244bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RDI, zero)) != 0)
1245bf21cd93STycho Nightingale 		goto done;
1246bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RBP, zero)) != 0)
1247bf21cd93STycho Nightingale 		goto done;
1248bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_RSP, zero)) != 0)
1249bf21cd93STycho Nightingale 		goto done;
1250bf21cd93STycho Nightingale 
1251bf21cd93STycho Nightingale 	/* GDTR, IDTR */
1252bf21cd93STycho Nightingale 	desc_base = 0;
1253bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1254bf21cd93STycho Nightingale 	desc_access = 0;
1255bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_GDTR,
1256bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1257bf21cd93STycho Nightingale 	if (error != 0)
1258bf21cd93STycho Nightingale 		goto done;
1259bf21cd93STycho Nightingale 
1260bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_IDTR,
1261bf21cd93STycho Nightingale 			    desc_base, desc_limit, desc_access);
1262bf21cd93STycho Nightingale 	if (error != 0)
1263bf21cd93STycho Nightingale 		goto done;
1264bf21cd93STycho Nightingale 
1265bf21cd93STycho Nightingale 	/* TR */
1266bf21cd93STycho Nightingale 	desc_base = 0;
1267bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1268bf21cd93STycho Nightingale 	desc_access = 0x0000008b;
1269bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_TR, 0, 0, desc_access);
1270bf21cd93STycho Nightingale 	if (error)
1271bf21cd93STycho Nightingale 		goto done;
1272bf21cd93STycho Nightingale 
1273bf21cd93STycho Nightingale 	sel = 0;
1274bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_TR, sel)) != 0)
1275bf21cd93STycho Nightingale 		goto done;
1276bf21cd93STycho Nightingale 
1277bf21cd93STycho Nightingale 	/* LDTR */
1278bf21cd93STycho Nightingale 	desc_base = 0;
1279bf21cd93STycho Nightingale 	desc_limit = 0xffff;
1280bf21cd93STycho Nightingale 	desc_access = 0x00000082;
1281bf21cd93STycho Nightingale 	error = vm_set_desc(vmctx, vcpu, VM_REG_GUEST_LDTR, desc_base,
1282bf21cd93STycho Nightingale 			    desc_limit, desc_access);
1283bf21cd93STycho Nightingale 	if (error)
1284bf21cd93STycho Nightingale 		goto done;
1285bf21cd93STycho Nightingale 
1286bf21cd93STycho Nightingale 	sel = 0;
1287bf21cd93STycho Nightingale 	if ((error = vm_set_register(vmctx, vcpu, VM_REG_GUEST_LDTR, 0)) != 0)
1288bf21cd93STycho Nightingale 		goto done;
1289bf21cd93STycho Nightingale 
1290bf21cd93STycho Nightingale 	/* XXX cr2, debug registers */
1291bf21cd93STycho Nightingale 
1292bf21cd93STycho Nightingale 	error = 0;
1293bf21cd93STycho Nightingale done:
1294bf21cd93STycho Nightingale 	return (error);
1295bf21cd93STycho Nightingale }
1296bf21cd93STycho Nightingale 
1297bf21cd93STycho Nightingale int
1298bf21cd93STycho Nightingale vm_get_gpa_pmap(struct vmctx *ctx, uint64_t gpa, uint64_t *pte, int *num)
1299bf21cd93STycho Nightingale {
1300bf21cd93STycho Nightingale 	int error, i;
1301bf21cd93STycho Nightingale 	struct vm_gpa_pte gpapte;
1302bf21cd93STycho Nightingale 
1303bf21cd93STycho Nightingale 	bzero(&gpapte, sizeof(gpapte));
1304bf21cd93STycho Nightingale 	gpapte.gpa = gpa;
1305bf21cd93STycho Nightingale 
1306bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_GPA_PMAP, &gpapte);
1307bf21cd93STycho Nightingale 
1308bf21cd93STycho Nightingale 	if (error == 0) {
1309bf21cd93STycho Nightingale 		*num = gpapte.ptenum;
1310bf21cd93STycho Nightingale 		for (i = 0; i < gpapte.ptenum; i++)
1311bf21cd93STycho Nightingale 			pte[i] = gpapte.pte[i];
1312bf21cd93STycho Nightingale 	}
1313bf21cd93STycho Nightingale 
1314bf21cd93STycho Nightingale 	return (error);
1315bf21cd93STycho Nightingale }
1316bf21cd93STycho Nightingale 
1317bf21cd93STycho Nightingale int
1318bf21cd93STycho Nightingale vm_get_hpet_capabilities(struct vmctx *ctx, uint32_t *capabilities)
1319bf21cd93STycho Nightingale {
1320bf21cd93STycho Nightingale 	int error;
1321bf21cd93STycho Nightingale 	struct vm_hpet_cap cap;
1322bf21cd93STycho Nightingale 
1323bf21cd93STycho Nightingale 	bzero(&cap, sizeof(struct vm_hpet_cap));
1324bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GET_HPET_CAPABILITIES, &cap);
1325bf21cd93STycho Nightingale 	if (capabilities != NULL)
1326bf21cd93STycho Nightingale 		*capabilities = cap.capabilities;
1327bf21cd93STycho Nightingale 	return (error);
1328bf21cd93STycho Nightingale }
1329bf21cd93STycho Nightingale 
1330*4c87aefeSPatrick Mooney int
1331*4c87aefeSPatrick Mooney vm_gla2gpa(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
1332*4c87aefeSPatrick Mooney     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1333bf21cd93STycho Nightingale {
1334bf21cd93STycho Nightingale 	struct vm_gla2gpa gg;
1335bf21cd93STycho Nightingale 	int error;
1336bf21cd93STycho Nightingale 
1337bf21cd93STycho Nightingale 	bzero(&gg, sizeof(struct vm_gla2gpa));
1338bf21cd93STycho Nightingale 	gg.vcpuid = vcpu;
1339bf21cd93STycho Nightingale 	gg.prot = prot;
1340bf21cd93STycho Nightingale 	gg.gla = gla;
1341bf21cd93STycho Nightingale 	gg.paging = *paging;
1342bf21cd93STycho Nightingale 
1343bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_GLA2GPA, &gg);
1344bf21cd93STycho Nightingale 	if (error == 0) {
1345bf21cd93STycho Nightingale 		*fault = gg.fault;
1346bf21cd93STycho Nightingale 		*gpa = gg.gpa;
1347bf21cd93STycho Nightingale 	}
1348bf21cd93STycho Nightingale 	return (error);
1349bf21cd93STycho Nightingale }
1350bf21cd93STycho Nightingale 
1351bf21cd93STycho Nightingale int
1352*4c87aefeSPatrick Mooney vm_gla2gpa_nofault(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
1353*4c87aefeSPatrick Mooney     uint64_t gla, int prot, uint64_t *gpa, int *fault)
1354bf21cd93STycho Nightingale {
1355*4c87aefeSPatrick Mooney 	struct vm_gla2gpa gg;
1356*4c87aefeSPatrick Mooney 	int error;
1357*4c87aefeSPatrick Mooney 
1358*4c87aefeSPatrick Mooney 	bzero(&gg, sizeof(struct vm_gla2gpa));
1359*4c87aefeSPatrick Mooney 	gg.vcpuid = vcpu;
1360*4c87aefeSPatrick Mooney 	gg.prot = prot;
1361*4c87aefeSPatrick Mooney 	gg.gla = gla;
1362*4c87aefeSPatrick Mooney 	gg.paging = *paging;
1363bf21cd93STycho Nightingale 
1364*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GLA2GPA_NOFAULT, &gg);
1365*4c87aefeSPatrick Mooney 	if (error == 0) {
1366*4c87aefeSPatrick Mooney 		*fault = gg.fault;
1367*4c87aefeSPatrick Mooney 		*gpa = gg.gpa;
1368*4c87aefeSPatrick Mooney 	}
1369bf21cd93STycho Nightingale 	return (error);
1370bf21cd93STycho Nightingale }
1371bf21cd93STycho Nightingale 
1372bf21cd93STycho Nightingale #ifndef min
1373bf21cd93STycho Nightingale #define	min(a,b)	(((a) < (b)) ? (a) : (b))
1374bf21cd93STycho Nightingale #endif
1375bf21cd93STycho Nightingale 
1376bf21cd93STycho Nightingale int
1377bf21cd93STycho Nightingale vm_copy_setup(struct vmctx *ctx, int vcpu, struct vm_guest_paging *paging,
1378*4c87aefeSPatrick Mooney     uint64_t gla, size_t len, int prot, struct iovec *iov, int iovcnt,
1379*4c87aefeSPatrick Mooney     int *fault)
1380bf21cd93STycho Nightingale {
1381bf21cd93STycho Nightingale 	void *va;
1382bf21cd93STycho Nightingale 	uint64_t gpa;
1383*4c87aefeSPatrick Mooney 	int error, i, n, off;
1384bf21cd93STycho Nightingale 
1385bf21cd93STycho Nightingale 	for (i = 0; i < iovcnt; i++) {
1386bf21cd93STycho Nightingale 		iov[i].iov_base = 0;
1387bf21cd93STycho Nightingale 		iov[i].iov_len = 0;
1388bf21cd93STycho Nightingale 	}
1389bf21cd93STycho Nightingale 
1390bf21cd93STycho Nightingale 	while (len) {
1391bf21cd93STycho Nightingale 		assert(iovcnt > 0);
1392*4c87aefeSPatrick Mooney 		error = vm_gla2gpa(ctx, vcpu, paging, gla, prot, &gpa, fault);
1393*4c87aefeSPatrick Mooney 		if (error || *fault)
1394*4c87aefeSPatrick Mooney 			return (error);
1395bf21cd93STycho Nightingale 
1396bf21cd93STycho Nightingale 		off = gpa & PAGE_MASK;
1397bf21cd93STycho Nightingale 		n = min(len, PAGE_SIZE - off);
1398bf21cd93STycho Nightingale 
1399bf21cd93STycho Nightingale 		va = vm_map_gpa(ctx, gpa, n);
1400bf21cd93STycho Nightingale 		if (va == NULL)
1401*4c87aefeSPatrick Mooney 			return (EFAULT);
1402bf21cd93STycho Nightingale 
1403bf21cd93STycho Nightingale 		iov->iov_base = va;
1404bf21cd93STycho Nightingale 		iov->iov_len = n;
1405bf21cd93STycho Nightingale 		iov++;
1406bf21cd93STycho Nightingale 		iovcnt--;
1407bf21cd93STycho Nightingale 
1408bf21cd93STycho Nightingale 		gla += n;
1409bf21cd93STycho Nightingale 		len -= n;
1410bf21cd93STycho Nightingale 	}
1411bf21cd93STycho Nightingale 	return (0);
1412bf21cd93STycho Nightingale }
1413bf21cd93STycho Nightingale 
1414bf21cd93STycho Nightingale void
1415bf21cd93STycho Nightingale vm_copy_teardown(struct vmctx *ctx, int vcpu, struct iovec *iov, int iovcnt)
1416bf21cd93STycho Nightingale {
1417bf21cd93STycho Nightingale 
1418bf21cd93STycho Nightingale 	return;
1419bf21cd93STycho Nightingale }
1420bf21cd93STycho Nightingale 
1421bf21cd93STycho Nightingale void
1422bf21cd93STycho Nightingale vm_copyin(struct vmctx *ctx, int vcpu, struct iovec *iov, void *vp, size_t len)
1423bf21cd93STycho Nightingale {
1424bf21cd93STycho Nightingale 	const char *src;
1425bf21cd93STycho Nightingale 	char *dst;
1426bf21cd93STycho Nightingale 	size_t n;
1427bf21cd93STycho Nightingale 
1428bf21cd93STycho Nightingale 	dst = vp;
1429bf21cd93STycho Nightingale 	while (len) {
1430bf21cd93STycho Nightingale 		assert(iov->iov_len);
1431bf21cd93STycho Nightingale 		n = min(len, iov->iov_len);
1432bf21cd93STycho Nightingale 		src = iov->iov_base;
1433bf21cd93STycho Nightingale 		bcopy(src, dst, n);
1434bf21cd93STycho Nightingale 
1435bf21cd93STycho Nightingale 		iov++;
1436bf21cd93STycho Nightingale 		dst += n;
1437bf21cd93STycho Nightingale 		len -= n;
1438bf21cd93STycho Nightingale 	}
1439bf21cd93STycho Nightingale }
1440bf21cd93STycho Nightingale 
1441bf21cd93STycho Nightingale void
1442bf21cd93STycho Nightingale vm_copyout(struct vmctx *ctx, int vcpu, const void *vp, struct iovec *iov,
1443bf21cd93STycho Nightingale     size_t len)
1444bf21cd93STycho Nightingale {
1445bf21cd93STycho Nightingale 	const char *src;
1446bf21cd93STycho Nightingale 	char *dst;
1447bf21cd93STycho Nightingale 	size_t n;
1448bf21cd93STycho Nightingale 
1449bf21cd93STycho Nightingale 	src = vp;
1450bf21cd93STycho Nightingale 	while (len) {
1451bf21cd93STycho Nightingale 		assert(iov->iov_len);
1452bf21cd93STycho Nightingale 		n = min(len, iov->iov_len);
1453bf21cd93STycho Nightingale 		dst = iov->iov_base;
1454bf21cd93STycho Nightingale 		bcopy(src, dst, n);
1455bf21cd93STycho Nightingale 
1456bf21cd93STycho Nightingale 		iov++;
1457bf21cd93STycho Nightingale 		src += n;
1458bf21cd93STycho Nightingale 		len -= n;
1459bf21cd93STycho Nightingale 	}
1460bf21cd93STycho Nightingale }
1461bf21cd93STycho Nightingale 
1462*4c87aefeSPatrick Mooney static int
1463*4c87aefeSPatrick Mooney vm_get_cpus(struct vmctx *ctx, int which, cpuset_t *cpus)
1464*4c87aefeSPatrick Mooney {
1465*4c87aefeSPatrick Mooney 	struct vm_cpuset vm_cpuset;
1466*4c87aefeSPatrick Mooney 	int error;
1467*4c87aefeSPatrick Mooney 
1468*4c87aefeSPatrick Mooney 	bzero(&vm_cpuset, sizeof(struct vm_cpuset));
1469*4c87aefeSPatrick Mooney 	vm_cpuset.which = which;
1470*4c87aefeSPatrick Mooney 	vm_cpuset.cpusetsize = sizeof(cpuset_t);
1471*4c87aefeSPatrick Mooney 	vm_cpuset.cpus = cpus;
1472*4c87aefeSPatrick Mooney 
1473*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_CPUS, &vm_cpuset);
1474*4c87aefeSPatrick Mooney 	return (error);
1475*4c87aefeSPatrick Mooney }
1476*4c87aefeSPatrick Mooney 
1477*4c87aefeSPatrick Mooney int
1478*4c87aefeSPatrick Mooney vm_active_cpus(struct vmctx *ctx, cpuset_t *cpus)
1479*4c87aefeSPatrick Mooney {
1480*4c87aefeSPatrick Mooney 
1481*4c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_ACTIVE_CPUS, cpus));
1482*4c87aefeSPatrick Mooney }
1483*4c87aefeSPatrick Mooney 
1484*4c87aefeSPatrick Mooney int
1485*4c87aefeSPatrick Mooney vm_suspended_cpus(struct vmctx *ctx, cpuset_t *cpus)
1486*4c87aefeSPatrick Mooney {
1487*4c87aefeSPatrick Mooney 
1488*4c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_SUSPENDED_CPUS, cpus));
1489*4c87aefeSPatrick Mooney }
1490*4c87aefeSPatrick Mooney 
1491*4c87aefeSPatrick Mooney int
1492*4c87aefeSPatrick Mooney vm_debug_cpus(struct vmctx *ctx, cpuset_t *cpus)
1493*4c87aefeSPatrick Mooney {
1494*4c87aefeSPatrick Mooney 
1495*4c87aefeSPatrick Mooney 	return (vm_get_cpus(ctx, VM_DEBUG_CPUS, cpus));
1496*4c87aefeSPatrick Mooney }
1497*4c87aefeSPatrick Mooney 
1498bf21cd93STycho Nightingale int
1499bf21cd93STycho Nightingale vm_activate_cpu(struct vmctx *ctx, int vcpu)
1500bf21cd93STycho Nightingale {
1501bf21cd93STycho Nightingale 	struct vm_activate_cpu ac;
1502bf21cd93STycho Nightingale 	int error;
1503bf21cd93STycho Nightingale 
1504bf21cd93STycho Nightingale 	bzero(&ac, sizeof(struct vm_activate_cpu));
1505bf21cd93STycho Nightingale 	ac.vcpuid = vcpu;
1506bf21cd93STycho Nightingale 	error = ioctl(ctx->fd, VM_ACTIVATE_CPU, &ac);
1507bf21cd93STycho Nightingale 	return (error);
1508bf21cd93STycho Nightingale }
1509bf21cd93STycho Nightingale 
1510*4c87aefeSPatrick Mooney int
1511*4c87aefeSPatrick Mooney vm_suspend_cpu(struct vmctx *ctx, int vcpu)
1512*4c87aefeSPatrick Mooney {
1513*4c87aefeSPatrick Mooney 	struct vm_activate_cpu ac;
1514*4c87aefeSPatrick Mooney 	int error;
1515*4c87aefeSPatrick Mooney 
1516*4c87aefeSPatrick Mooney 	bzero(&ac, sizeof(struct vm_activate_cpu));
1517*4c87aefeSPatrick Mooney 	ac.vcpuid = vcpu;
1518*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SUSPEND_CPU, &ac);
1519*4c87aefeSPatrick Mooney 	return (error);
1520*4c87aefeSPatrick Mooney }
1521*4c87aefeSPatrick Mooney 
1522*4c87aefeSPatrick Mooney int
1523*4c87aefeSPatrick Mooney vm_resume_cpu(struct vmctx *ctx, int vcpu)
1524*4c87aefeSPatrick Mooney {
1525*4c87aefeSPatrick Mooney 	struct vm_activate_cpu ac;
1526*4c87aefeSPatrick Mooney 	int error;
1527*4c87aefeSPatrick Mooney 
1528*4c87aefeSPatrick Mooney 	bzero(&ac, sizeof(struct vm_activate_cpu));
1529*4c87aefeSPatrick Mooney 	ac.vcpuid = vcpu;
1530*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RESUME_CPU, &ac);
1531*4c87aefeSPatrick Mooney 	return (error);
1532*4c87aefeSPatrick Mooney }
1533*4c87aefeSPatrick Mooney 
1534*4c87aefeSPatrick Mooney int
1535*4c87aefeSPatrick Mooney vm_get_intinfo(struct vmctx *ctx, int vcpu, uint64_t *info1, uint64_t *info2)
1536*4c87aefeSPatrick Mooney {
1537*4c87aefeSPatrick Mooney 	struct vm_intinfo vmii;
1538*4c87aefeSPatrick Mooney 	int error;
1539*4c87aefeSPatrick Mooney 
1540*4c87aefeSPatrick Mooney 	bzero(&vmii, sizeof(struct vm_intinfo));
1541*4c87aefeSPatrick Mooney 	vmii.vcpuid = vcpu;
1542*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_INTINFO, &vmii);
1543*4c87aefeSPatrick Mooney 	if (error == 0) {
1544*4c87aefeSPatrick Mooney 		*info1 = vmii.info1;
1545*4c87aefeSPatrick Mooney 		*info2 = vmii.info2;
1546*4c87aefeSPatrick Mooney 	}
1547*4c87aefeSPatrick Mooney 	return (error);
1548*4c87aefeSPatrick Mooney }
1549*4c87aefeSPatrick Mooney 
1550*4c87aefeSPatrick Mooney int
1551*4c87aefeSPatrick Mooney vm_set_intinfo(struct vmctx *ctx, int vcpu, uint64_t info1)
1552*4c87aefeSPatrick Mooney {
1553*4c87aefeSPatrick Mooney 	struct vm_intinfo vmii;
1554*4c87aefeSPatrick Mooney 	int error;
1555*4c87aefeSPatrick Mooney 
1556*4c87aefeSPatrick Mooney 	bzero(&vmii, sizeof(struct vm_intinfo));
1557*4c87aefeSPatrick Mooney 	vmii.vcpuid = vcpu;
1558*4c87aefeSPatrick Mooney 	vmii.info1 = info1;
1559*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_SET_INTINFO, &vmii);
1560*4c87aefeSPatrick Mooney 	return (error);
1561*4c87aefeSPatrick Mooney }
1562*4c87aefeSPatrick Mooney 
1563*4c87aefeSPatrick Mooney int
1564*4c87aefeSPatrick Mooney vm_rtc_write(struct vmctx *ctx, int offset, uint8_t value)
1565*4c87aefeSPatrick Mooney {
1566*4c87aefeSPatrick Mooney 	struct vm_rtc_data rtcdata;
1567*4c87aefeSPatrick Mooney 	int error;
1568*4c87aefeSPatrick Mooney 
1569*4c87aefeSPatrick Mooney 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
1570*4c87aefeSPatrick Mooney 	rtcdata.offset = offset;
1571*4c87aefeSPatrick Mooney 	rtcdata.value = value;
1572*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_WRITE, &rtcdata);
1573*4c87aefeSPatrick Mooney 	return (error);
1574*4c87aefeSPatrick Mooney }
1575*4c87aefeSPatrick Mooney 
1576*4c87aefeSPatrick Mooney int
1577*4c87aefeSPatrick Mooney vm_rtc_read(struct vmctx *ctx, int offset, uint8_t *retval)
1578*4c87aefeSPatrick Mooney {
1579*4c87aefeSPatrick Mooney 	struct vm_rtc_data rtcdata;
1580*4c87aefeSPatrick Mooney 	int error;
1581*4c87aefeSPatrick Mooney 
1582*4c87aefeSPatrick Mooney 	bzero(&rtcdata, sizeof(struct vm_rtc_data));
1583*4c87aefeSPatrick Mooney 	rtcdata.offset = offset;
1584*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_READ, &rtcdata);
1585*4c87aefeSPatrick Mooney 	if (error == 0)
1586*4c87aefeSPatrick Mooney 		*retval = rtcdata.value;
1587*4c87aefeSPatrick Mooney 	return (error);
1588*4c87aefeSPatrick Mooney }
1589*4c87aefeSPatrick Mooney 
1590*4c87aefeSPatrick Mooney int
1591*4c87aefeSPatrick Mooney vm_rtc_settime(struct vmctx *ctx, time_t secs)
1592*4c87aefeSPatrick Mooney {
1593*4c87aefeSPatrick Mooney 	struct vm_rtc_time rtctime;
1594*4c87aefeSPatrick Mooney 	int error;
1595*4c87aefeSPatrick Mooney 
1596*4c87aefeSPatrick Mooney 	bzero(&rtctime, sizeof(struct vm_rtc_time));
1597*4c87aefeSPatrick Mooney 	rtctime.secs = secs;
1598*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_SETTIME, &rtctime);
1599*4c87aefeSPatrick Mooney 	return (error);
1600*4c87aefeSPatrick Mooney }
1601*4c87aefeSPatrick Mooney 
1602*4c87aefeSPatrick Mooney int
1603*4c87aefeSPatrick Mooney vm_rtc_gettime(struct vmctx *ctx, time_t *secs)
1604*4c87aefeSPatrick Mooney {
1605*4c87aefeSPatrick Mooney 	struct vm_rtc_time rtctime;
1606*4c87aefeSPatrick Mooney 	int error;
1607*4c87aefeSPatrick Mooney 
1608*4c87aefeSPatrick Mooney 	bzero(&rtctime, sizeof(struct vm_rtc_time));
1609*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_RTC_GETTIME, &rtctime);
1610*4c87aefeSPatrick Mooney 	if (error == 0)
1611*4c87aefeSPatrick Mooney 		*secs = rtctime.secs;
1612*4c87aefeSPatrick Mooney 	return (error);
1613*4c87aefeSPatrick Mooney }
1614*4c87aefeSPatrick Mooney 
1615bf21cd93STycho Nightingale int
1616bf21cd93STycho Nightingale vm_restart_instruction(void *arg, int vcpu)
1617bf21cd93STycho Nightingale {
1618bf21cd93STycho Nightingale 	struct vmctx *ctx = arg;
1619bf21cd93STycho Nightingale 
1620bf21cd93STycho Nightingale 	return (ioctl(ctx->fd, VM_RESTART_INSTRUCTION, &vcpu));
1621bf21cd93STycho Nightingale }
1622*4c87aefeSPatrick Mooney 
1623*4c87aefeSPatrick Mooney int
1624*4c87aefeSPatrick Mooney vm_set_topology(struct vmctx *ctx,
1625*4c87aefeSPatrick Mooney     uint16_t sockets, uint16_t cores, uint16_t threads, uint16_t maxcpus)
1626*4c87aefeSPatrick Mooney {
1627*4c87aefeSPatrick Mooney 	struct vm_cpu_topology topology;
1628*4c87aefeSPatrick Mooney 
1629*4c87aefeSPatrick Mooney 	bzero(&topology, sizeof (struct vm_cpu_topology));
1630*4c87aefeSPatrick Mooney 	topology.sockets = sockets;
1631*4c87aefeSPatrick Mooney 	topology.cores = cores;
1632*4c87aefeSPatrick Mooney 	topology.threads = threads;
1633*4c87aefeSPatrick Mooney 	topology.maxcpus = maxcpus;
1634*4c87aefeSPatrick Mooney 	return (ioctl(ctx->fd, VM_SET_TOPOLOGY, &topology));
1635*4c87aefeSPatrick Mooney }
1636*4c87aefeSPatrick Mooney 
1637*4c87aefeSPatrick Mooney int
1638*4c87aefeSPatrick Mooney vm_get_topology(struct vmctx *ctx,
1639*4c87aefeSPatrick Mooney     uint16_t *sockets, uint16_t *cores, uint16_t *threads, uint16_t *maxcpus)
1640*4c87aefeSPatrick Mooney {
1641*4c87aefeSPatrick Mooney 	struct vm_cpu_topology topology;
1642*4c87aefeSPatrick Mooney 	int error;
1643*4c87aefeSPatrick Mooney 
1644*4c87aefeSPatrick Mooney 	bzero(&topology, sizeof (struct vm_cpu_topology));
1645*4c87aefeSPatrick Mooney 	error = ioctl(ctx->fd, VM_GET_TOPOLOGY, &topology);
1646*4c87aefeSPatrick Mooney 	if (error == 0) {
1647*4c87aefeSPatrick Mooney 		*sockets = topology.sockets;
1648*4c87aefeSPatrick Mooney 		*cores = topology.cores;
1649*4c87aefeSPatrick Mooney 		*threads = topology.threads;
1650*4c87aefeSPatrick Mooney 		*maxcpus = topology.maxcpus;
1651*4c87aefeSPatrick Mooney 	}
1652*4c87aefeSPatrick Mooney 	return (error);
1653*4c87aefeSPatrick Mooney }
1654*4c87aefeSPatrick Mooney 
1655*4c87aefeSPatrick Mooney int
1656*4c87aefeSPatrick Mooney vm_get_device_fd(struct vmctx *ctx)
1657*4c87aefeSPatrick Mooney {
1658*4c87aefeSPatrick Mooney 
1659*4c87aefeSPatrick Mooney 	return (ctx->fd);
1660*4c87aefeSPatrick Mooney }
1661*4c87aefeSPatrick Mooney 
1662*4c87aefeSPatrick Mooney #ifndef __FreeBSD__
1663*4c87aefeSPatrick Mooney int
1664*4c87aefeSPatrick Mooney vm_wrlock_cycle(struct vmctx *ctx)
1665*4c87aefeSPatrick Mooney {
1666*4c87aefeSPatrick Mooney 	if (ioctl(ctx->fd, VM_WRLOCK_CYCLE, 0) != 0) {
1667*4c87aefeSPatrick Mooney 		return (errno);
1668*4c87aefeSPatrick Mooney 	}
1669*4c87aefeSPatrick Mooney 	return (0);
1670*4c87aefeSPatrick Mooney }
1671*4c87aefeSPatrick Mooney #endif /* __FreeBSD__ */
1672*4c87aefeSPatrick Mooney 
1673*4c87aefeSPatrick Mooney #ifdef __FreeBSD__
1674*4c87aefeSPatrick Mooney const cap_ioctl_t *
1675*4c87aefeSPatrick Mooney vm_get_ioctls(size_t *len)
1676*4c87aefeSPatrick Mooney {
1677*4c87aefeSPatrick Mooney 	cap_ioctl_t *cmds;
1678*4c87aefeSPatrick Mooney 	/* keep in sync with machine/vmm_dev.h */
1679*4c87aefeSPatrick Mooney 	static const cap_ioctl_t vm_ioctl_cmds[] = { VM_RUN, VM_SUSPEND, VM_REINIT,
1680*4c87aefeSPatrick Mooney 	    VM_ALLOC_MEMSEG, VM_GET_MEMSEG, VM_MMAP_MEMSEG, VM_MMAP_MEMSEG,
1681*4c87aefeSPatrick Mooney 	    VM_MMAP_GETNEXT, VM_SET_REGISTER, VM_GET_REGISTER,
1682*4c87aefeSPatrick Mooney 	    VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
1683*4c87aefeSPatrick Mooney 	    VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
1684*4c87aefeSPatrick Mooney 	    VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
1685*4c87aefeSPatrick Mooney 	    VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
1686*4c87aefeSPatrick Mooney 	    VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,
1687*4c87aefeSPatrick Mooney 	    VM_ISA_DEASSERT_IRQ, VM_ISA_PULSE_IRQ, VM_ISA_SET_IRQ_TRIGGER,
1688*4c87aefeSPatrick Mooney 	    VM_SET_CAPABILITY, VM_GET_CAPABILITY, VM_BIND_PPTDEV,
1689*4c87aefeSPatrick Mooney 	    VM_UNBIND_PPTDEV, VM_MAP_PPTDEV_MMIO, VM_PPTDEV_MSI,
1690*4c87aefeSPatrick Mooney 	    VM_PPTDEV_MSIX, VM_INJECT_NMI, VM_STATS, VM_STAT_DESC,
1691*4c87aefeSPatrick Mooney 	    VM_SET_X2APIC_STATE, VM_GET_X2APIC_STATE,
1692*4c87aefeSPatrick Mooney 	    VM_GET_HPET_CAPABILITIES, VM_GET_GPA_PMAP, VM_GLA2GPA,
1693*4c87aefeSPatrick Mooney 	    VM_GLA2GPA_NOFAULT,
1694*4c87aefeSPatrick Mooney 	    VM_ACTIVATE_CPU, VM_GET_CPUS, VM_SUSPEND_CPU, VM_RESUME_CPU,
1695*4c87aefeSPatrick Mooney 	    VM_SET_INTINFO, VM_GET_INTINFO,
1696*4c87aefeSPatrick Mooney 	    VM_RTC_WRITE, VM_RTC_READ, VM_RTC_SETTIME, VM_RTC_GETTIME,
1697*4c87aefeSPatrick Mooney 	    VM_RESTART_INSTRUCTION, VM_SET_TOPOLOGY, VM_GET_TOPOLOGY };
1698*4c87aefeSPatrick Mooney 
1699*4c87aefeSPatrick Mooney 	if (len == NULL) {
1700*4c87aefeSPatrick Mooney 		cmds = malloc(sizeof(vm_ioctl_cmds));
1701*4c87aefeSPatrick Mooney 		if (cmds == NULL)
1702*4c87aefeSPatrick Mooney 			return (NULL);
1703*4c87aefeSPatrick Mooney 		bcopy(vm_ioctl_cmds, cmds, sizeof(vm_ioctl_cmds));
1704*4c87aefeSPatrick Mooney 		return (cmds);
1705*4c87aefeSPatrick Mooney 	}
1706*4c87aefeSPatrick Mooney 
1707*4c87aefeSPatrick Mooney 	*len = nitems(vm_ioctl_cmds);
1708*4c87aefeSPatrick Mooney 	return (NULL);
1709*4c87aefeSPatrick Mooney }
1710*4c87aefeSPatrick Mooney #endif /* __FreeBSD__ */
1711