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