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