Home | History | Annotate | Line # | Download | only in libnvmm
      1  1.20  reinoud /*	$NetBSD: libnvmm.c,v 1.20 2021/04/06 08:40:17 reinoud Exp $	*/
      2   1.1     maxv 
      3   1.1     maxv /*
      4  1.19     maxv  * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
      5   1.1     maxv  * All rights reserved.
      6   1.1     maxv  *
      7  1.19     maxv  * This code is part of the NVMM hypervisor.
      8   1.1     maxv  *
      9   1.1     maxv  * Redistribution and use in source and binary forms, with or without
     10   1.1     maxv  * modification, are permitted provided that the following conditions
     11   1.1     maxv  * are met:
     12   1.1     maxv  * 1. Redistributions of source code must retain the above copyright
     13   1.1     maxv  *    notice, this list of conditions and the following disclaimer.
     14   1.1     maxv  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1     maxv  *    notice, this list of conditions and the following disclaimer in the
     16   1.1     maxv  *    documentation and/or other materials provided with the distribution.
     17   1.1     maxv  *
     18  1.19     maxv  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     19  1.19     maxv  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     20  1.19     maxv  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     21  1.19     maxv  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     22  1.19     maxv  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     23  1.19     maxv  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     24  1.19     maxv  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     25  1.19     maxv  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     26  1.19     maxv  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     27  1.19     maxv  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     28  1.19     maxv  * SUCH DAMAGE.
     29   1.1     maxv  */
     30   1.1     maxv 
     31   1.1     maxv #include <sys/cdefs.h>
     32   1.1     maxv 
     33   1.1     maxv #include <stdio.h>
     34   1.1     maxv #include <stdlib.h>
     35   1.1     maxv #include <string.h>
     36   1.1     maxv #include <unistd.h>
     37   1.1     maxv #include <fcntl.h>
     38   1.1     maxv #include <errno.h>
     39   1.1     maxv #include <sys/ioctl.h>
     40   1.1     maxv #include <sys/mman.h>
     41   1.3     maxv #include <sys/queue.h>
     42  1.10     maxv #include <machine/vmparam.h>
     43   1.1     maxv 
     44   1.1     maxv #include "nvmm.h"
     45   1.1     maxv 
     46  1.10     maxv static struct nvmm_capability __capability;
     47  1.10     maxv 
     48  1.10     maxv #ifdef __x86_64__
     49  1.10     maxv #include "libnvmm_x86.c"
     50  1.10     maxv #endif
     51   1.6     maxv 
     52   1.3     maxv typedef struct __area {
     53   1.3     maxv 	LIST_ENTRY(__area) list;
     54   1.3     maxv 	gpaddr_t gpa;
     55   1.3     maxv 	uintptr_t hva;
     56   1.3     maxv 	size_t size;
     57   1.8     maxv 	nvmm_prot_t prot;
     58   1.3     maxv } area_t;
     59   1.3     maxv 
     60   1.3     maxv typedef LIST_HEAD(, __area) area_list_t;
     61   1.3     maxv 
     62   1.1     maxv static int nvmm_fd = -1;
     63   1.1     maxv 
     64   1.1     maxv /* -------------------------------------------------------------------------- */
     65   1.1     maxv 
     66   1.4     maxv static bool
     67   1.4     maxv __area_isvalid(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
     68   1.1     maxv     size_t size)
     69   1.1     maxv {
     70   1.3     maxv 	area_list_t *areas = mach->areas;
     71   1.4     maxv 	area_t *ent;
     72   1.3     maxv 
     73   1.4     maxv 	LIST_FOREACH(ent, areas, list) {
     74   1.4     maxv 		/* Collision on GPA */
     75   1.4     maxv 		if (gpa >= ent->gpa && gpa < ent->gpa + ent->size) {
     76   1.4     maxv 			return false;
     77   1.1     maxv 		}
     78   1.5     maxv 		if (gpa + size > ent->gpa &&
     79   1.5     maxv 		    gpa + size <= ent->gpa + ent->size) {
     80   1.4     maxv 			return false;
     81   1.3     maxv 		}
     82   1.4     maxv 		if (gpa <= ent->gpa && gpa + size >= ent->gpa + ent->size) {
     83   1.4     maxv 			return false;
     84   1.1     maxv 		}
     85   1.1     maxv 	}
     86   1.1     maxv 
     87   1.4     maxv 	return true;
     88   1.3     maxv }
     89   1.3     maxv 
     90   1.3     maxv static int
     91   1.8     maxv __area_add(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, size_t size,
     92   1.8     maxv     int prot)
     93   1.3     maxv {
     94   1.3     maxv 	area_list_t *areas = mach->areas;
     95   1.8     maxv 	nvmm_prot_t nprot;
     96   1.3     maxv 	area_t *area;
     97   1.4     maxv 
     98   1.8     maxv 	nprot = 0;
     99   1.8     maxv 	if (prot & PROT_READ)
    100   1.8     maxv 		nprot |= NVMM_PROT_READ;
    101   1.8     maxv 	if (prot & PROT_WRITE)
    102   1.8     maxv 		nprot |= NVMM_PROT_WRITE;
    103   1.8     maxv 	if (prot & PROT_EXEC)
    104   1.8     maxv 		nprot |= NVMM_PROT_EXEC;
    105   1.8     maxv 
    106   1.4     maxv 	if (!__area_isvalid(mach, hva, gpa, size)) {
    107   1.4     maxv 		errno = EINVAL;
    108   1.4     maxv 		return -1;
    109   1.4     maxv 	}
    110   1.3     maxv 
    111   1.3     maxv 	area = malloc(sizeof(*area));
    112   1.3     maxv 	if (area == NULL)
    113   1.1     maxv 		return -1;
    114   1.1     maxv 	area->gpa = gpa;
    115   1.1     maxv 	area->hva = hva;
    116   1.1     maxv 	area->size = size;
    117   1.8     maxv 	area->prot = nprot;
    118   1.1     maxv 
    119   1.4     maxv 	LIST_INSERT_HEAD(areas, area, list);
    120   1.4     maxv 
    121   1.4     maxv 	return 0;
    122   1.4     maxv }
    123   1.4     maxv 
    124   1.4     maxv static int
    125   1.4     maxv __area_delete(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
    126   1.4     maxv     size_t size)
    127   1.4     maxv {
    128   1.4     maxv 	area_list_t *areas = mach->areas;
    129   1.4     maxv 	area_t *ent, *nxt;
    130   1.4     maxv 
    131   1.4     maxv 	LIST_FOREACH_SAFE(ent, areas, list, nxt) {
    132   1.4     maxv 		if (hva == ent->hva && gpa == ent->gpa && size == ent->size) {
    133   1.4     maxv 			LIST_REMOVE(ent, list);
    134   1.4     maxv 			free(ent);
    135   1.4     maxv 			return 0;
    136   1.4     maxv 		}
    137   1.3     maxv 	}
    138   1.3     maxv 
    139   1.4     maxv 	return -1;
    140   1.1     maxv }
    141   1.1     maxv 
    142   1.3     maxv static void
    143   1.3     maxv __area_remove_all(struct nvmm_machine *mach)
    144   1.1     maxv {
    145   1.3     maxv 	area_list_t *areas = mach->areas;
    146   1.3     maxv 	area_t *ent;
    147   1.1     maxv 
    148   1.3     maxv 	while ((ent = LIST_FIRST(areas)) != NULL) {
    149   1.3     maxv 		LIST_REMOVE(ent, list);
    150   1.3     maxv 		free(ent);
    151   1.1     maxv 	}
    152   1.1     maxv 
    153   1.3     maxv 	free(areas);
    154   1.1     maxv }
    155   1.1     maxv 
    156   1.1     maxv /* -------------------------------------------------------------------------- */
    157   1.1     maxv 
    158  1.17     maxv int
    159   1.1     maxv nvmm_init(void)
    160   1.1     maxv {
    161   1.1     maxv 	if (nvmm_fd != -1)
    162   1.1     maxv 		return 0;
    163  1.15     maxv 	nvmm_fd = open("/dev/nvmm", O_RDONLY | O_CLOEXEC);
    164   1.1     maxv 	if (nvmm_fd == -1)
    165   1.1     maxv 		return -1;
    166  1.10     maxv 	if (nvmm_capability(&__capability) == -1) {
    167  1.10     maxv 		close(nvmm_fd);
    168  1.10     maxv 		nvmm_fd = -1;
    169  1.10     maxv 		return -1;
    170  1.10     maxv 	}
    171  1.15     maxv 	if (__capability.version != NVMM_KERN_VERSION) {
    172  1.15     maxv 		close(nvmm_fd);
    173  1.15     maxv 		nvmm_fd = -1;
    174  1.15     maxv 		errno = EPROGMISMATCH;
    175  1.15     maxv 		return -1;
    176  1.15     maxv 	}
    177  1.15     maxv 
    178   1.1     maxv 	return 0;
    179   1.1     maxv }
    180   1.1     maxv 
    181   1.1     maxv int
    182  1.18     maxv nvmm_root_init(void)
    183  1.18     maxv {
    184  1.18     maxv 	if (nvmm_fd != -1)
    185  1.18     maxv 		return 0;
    186  1.18     maxv 	nvmm_fd = open("/dev/nvmm", O_WRONLY | O_CLOEXEC);
    187  1.18     maxv 	if (nvmm_fd == -1)
    188  1.18     maxv 		return -1;
    189  1.18     maxv 	if (nvmm_capability(&__capability) == -1) {
    190  1.18     maxv 		close(nvmm_fd);
    191  1.18     maxv 		nvmm_fd = -1;
    192  1.18     maxv 		return -1;
    193  1.18     maxv 	}
    194  1.18     maxv 	if (__capability.version != NVMM_KERN_VERSION) {
    195  1.18     maxv 		close(nvmm_fd);
    196  1.18     maxv 		nvmm_fd = -1;
    197  1.18     maxv 		errno = EPROGMISMATCH;
    198  1.18     maxv 		return -1;
    199  1.18     maxv 	}
    200  1.18     maxv 
    201  1.18     maxv 	return 0;
    202  1.18     maxv }
    203  1.18     maxv 
    204  1.18     maxv int
    205   1.1     maxv nvmm_capability(struct nvmm_capability *cap)
    206   1.1     maxv {
    207   1.1     maxv 	struct nvmm_ioc_capability args;
    208   1.1     maxv 	int ret;
    209   1.1     maxv 
    210   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_CAPABILITY, &args);
    211   1.1     maxv 	if (ret == -1)
    212   1.1     maxv 		return -1;
    213   1.1     maxv 
    214   1.1     maxv 	memcpy(cap, &args.cap, sizeof(args.cap));
    215   1.1     maxv 
    216   1.1     maxv 	return 0;
    217   1.1     maxv }
    218   1.1     maxv 
    219   1.1     maxv int
    220   1.1     maxv nvmm_machine_create(struct nvmm_machine *mach)
    221   1.1     maxv {
    222   1.1     maxv 	struct nvmm_ioc_machine_create args;
    223  1.10     maxv 	struct nvmm_comm_page **pages;
    224   1.3     maxv 	area_list_t *areas;
    225   1.1     maxv 	int ret;
    226   1.1     maxv 
    227   1.3     maxv 	areas = calloc(1, sizeof(*areas));
    228   1.3     maxv 	if (areas == NULL)
    229   1.3     maxv 		return -1;
    230   1.3     maxv 
    231  1.10     maxv 	pages = calloc(__capability.max_vcpus, sizeof(*pages));
    232  1.10     maxv 	if (pages == NULL) {
    233  1.10     maxv 		free(areas);
    234  1.10     maxv 		return -1;
    235  1.10     maxv 	}
    236  1.10     maxv 
    237   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_MACHINE_CREATE, &args);
    238   1.3     maxv 	if (ret == -1) {
    239   1.3     maxv 		free(areas);
    240   1.1     maxv 		return -1;
    241   1.3     maxv 	}
    242   1.1     maxv 
    243  1.10     maxv 	LIST_INIT(areas);
    244  1.10     maxv 
    245   1.1     maxv 	memset(mach, 0, sizeof(*mach));
    246  1.10     maxv 	mach->machid = args.machid;
    247  1.10     maxv 	mach->pages = pages;
    248   1.3     maxv 	mach->areas = areas;
    249   1.1     maxv 
    250   1.1     maxv 	return 0;
    251   1.1     maxv }
    252   1.1     maxv 
    253   1.1     maxv int
    254   1.1     maxv nvmm_machine_destroy(struct nvmm_machine *mach)
    255   1.1     maxv {
    256   1.1     maxv 	struct nvmm_ioc_machine_destroy args;
    257   1.1     maxv 	int ret;
    258   1.1     maxv 
    259   1.1     maxv 	args.machid = mach->machid;
    260   1.1     maxv 
    261   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_MACHINE_DESTROY, &args);
    262   1.1     maxv 	if (ret == -1)
    263   1.1     maxv 		return -1;
    264   1.1     maxv 
    265   1.3     maxv 	__area_remove_all(mach);
    266  1.10     maxv 	free(mach->pages);
    267   1.1     maxv 
    268   1.1     maxv 	return 0;
    269   1.1     maxv }
    270   1.1     maxv 
    271   1.1     maxv int
    272   1.1     maxv nvmm_machine_configure(struct nvmm_machine *mach, uint64_t op, void *conf)
    273   1.1     maxv {
    274   1.1     maxv 	struct nvmm_ioc_machine_configure args;
    275   1.1     maxv 	int ret;
    276   1.1     maxv 
    277   1.1     maxv 	args.machid = mach->machid;
    278   1.1     maxv 	args.op = op;
    279   1.1     maxv 	args.conf = conf;
    280   1.1     maxv 
    281   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_MACHINE_CONFIGURE, &args);
    282   1.1     maxv 	if (ret == -1)
    283   1.1     maxv 		return -1;
    284   1.1     maxv 
    285   1.1     maxv 	return 0;
    286   1.1     maxv }
    287   1.1     maxv 
    288   1.1     maxv int
    289  1.14     maxv nvmm_vcpu_create(struct nvmm_machine *mach, nvmm_cpuid_t cpuid,
    290  1.14     maxv     struct nvmm_vcpu *vcpu)
    291   1.1     maxv {
    292   1.1     maxv 	struct nvmm_ioc_vcpu_create args;
    293  1.10     maxv 	struct nvmm_comm_page *comm;
    294   1.1     maxv 	int ret;
    295   1.1     maxv 
    296   1.1     maxv 	args.machid = mach->machid;
    297   1.1     maxv 	args.cpuid = cpuid;
    298   1.1     maxv 
    299   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_CREATE, &args);
    300   1.1     maxv 	if (ret == -1)
    301   1.1     maxv 		return -1;
    302   1.1     maxv 
    303  1.10     maxv 	comm = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE,
    304  1.10     maxv 	    nvmm_fd, NVMM_COMM_OFF(mach->machid, cpuid));
    305  1.10     maxv 	if (comm == MAP_FAILED)
    306  1.10     maxv 		return -1;
    307  1.10     maxv 
    308  1.10     maxv 	mach->pages[cpuid] = comm;
    309  1.10     maxv 
    310  1.14     maxv 	vcpu->cpuid = cpuid;
    311  1.14     maxv 	vcpu->state = &comm->state;
    312  1.14     maxv 	vcpu->event = &comm->event;
    313  1.20  reinoud 	vcpu->stop = &comm->stop;
    314  1.14     maxv 	vcpu->exit = malloc(sizeof(*vcpu->exit));
    315  1.14     maxv 
    316   1.1     maxv 	return 0;
    317   1.1     maxv }
    318   1.1     maxv 
    319   1.1     maxv int
    320  1.14     maxv nvmm_vcpu_destroy(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
    321   1.1     maxv {
    322   1.1     maxv 	struct nvmm_ioc_vcpu_destroy args;
    323  1.10     maxv 	struct nvmm_comm_page *comm;
    324   1.1     maxv 	int ret;
    325   1.1     maxv 
    326   1.1     maxv 	args.machid = mach->machid;
    327  1.14     maxv 	args.cpuid = vcpu->cpuid;
    328   1.1     maxv 
    329   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_DESTROY, &args);
    330   1.1     maxv 	if (ret == -1)
    331   1.1     maxv 		return -1;
    332   1.1     maxv 
    333  1.14     maxv 	comm = mach->pages[vcpu->cpuid];
    334  1.10     maxv 	munmap(comm, PAGE_SIZE);
    335  1.14     maxv 	free(vcpu->exit);
    336  1.10     maxv 
    337   1.1     maxv 	return 0;
    338   1.1     maxv }
    339   1.1     maxv 
    340   1.1     maxv int
    341  1.15     maxv nvmm_vcpu_configure(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
    342  1.15     maxv     uint64_t op, void *conf)
    343  1.15     maxv {
    344  1.15     maxv 	struct nvmm_ioc_vcpu_configure args;
    345  1.15     maxv 	int ret;
    346  1.15     maxv 
    347  1.16     maxv 	switch (op) {
    348  1.16     maxv 	case NVMM_VCPU_CONF_CALLBACKS:
    349  1.16     maxv 		memcpy(&vcpu->cbs, conf, sizeof(vcpu->cbs));
    350  1.16     maxv 		return 0;
    351  1.16     maxv 	}
    352  1.16     maxv 
    353  1.15     maxv 	args.machid = mach->machid;
    354  1.15     maxv 	args.cpuid = vcpu->cpuid;
    355  1.15     maxv 	args.op = op;
    356  1.15     maxv 	args.conf = conf;
    357  1.15     maxv 
    358  1.15     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_CONFIGURE, &args);
    359  1.15     maxv 	if (ret == -1)
    360  1.15     maxv 		return -1;
    361  1.15     maxv 
    362  1.15     maxv 	return 0;
    363  1.15     maxv }
    364  1.15     maxv 
    365  1.15     maxv int
    366  1.14     maxv nvmm_vcpu_setstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
    367  1.14     maxv     uint64_t flags)
    368   1.1     maxv {
    369  1.10     maxv 	struct nvmm_comm_page *comm;
    370   1.1     maxv 
    371  1.14     maxv 	comm = mach->pages[vcpu->cpuid];
    372  1.10     maxv 	comm->state_commit |= flags;
    373  1.10     maxv 	comm->state_cached |= flags;
    374   1.1     maxv 
    375   1.1     maxv 	return 0;
    376   1.1     maxv }
    377   1.1     maxv 
    378   1.1     maxv int
    379  1.14     maxv nvmm_vcpu_getstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
    380  1.14     maxv     uint64_t flags)
    381   1.1     maxv {
    382   1.1     maxv 	struct nvmm_ioc_vcpu_getstate args;
    383  1.10     maxv 	struct nvmm_comm_page *comm;
    384   1.1     maxv 	int ret;
    385   1.1     maxv 
    386  1.14     maxv 	comm = mach->pages[vcpu->cpuid];
    387  1.10     maxv 
    388  1.10     maxv 	if (__predict_true((flags & ~comm->state_cached) == 0)) {
    389  1.14     maxv 		return 0;
    390  1.10     maxv 	}
    391  1.10     maxv 	comm->state_wanted = flags & ~comm->state_cached;
    392  1.10     maxv 
    393   1.1     maxv 	args.machid = mach->machid;
    394  1.14     maxv 	args.cpuid = vcpu->cpuid;
    395   1.1     maxv 
    396   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_GETSTATE, &args);
    397   1.1     maxv 	if (ret == -1)
    398   1.1     maxv 		return -1;
    399   1.1     maxv 
    400   1.1     maxv 	return 0;
    401   1.1     maxv }
    402   1.1     maxv 
    403   1.1     maxv int
    404  1.14     maxv nvmm_vcpu_inject(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
    405   1.1     maxv {
    406  1.12     maxv 	struct nvmm_comm_page *comm;
    407   1.1     maxv 
    408  1.14     maxv 	comm = mach->pages[vcpu->cpuid];
    409  1.12     maxv 	comm->event_commit = true;
    410   1.1     maxv 
    411   1.1     maxv 	return 0;
    412   1.1     maxv }
    413   1.1     maxv 
    414   1.1     maxv int
    415  1.14     maxv nvmm_vcpu_run(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
    416   1.1     maxv {
    417   1.1     maxv 	struct nvmm_ioc_vcpu_run args;
    418   1.1     maxv 	int ret;
    419   1.1     maxv 
    420   1.1     maxv 	args.machid = mach->machid;
    421  1.14     maxv 	args.cpuid = vcpu->cpuid;
    422   1.1     maxv 	memset(&args.exit, 0, sizeof(args.exit));
    423   1.1     maxv 
    424   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_RUN, &args);
    425   1.1     maxv 	if (ret == -1)
    426   1.1     maxv 		return -1;
    427   1.1     maxv 
    428  1.14     maxv 	/* No comm support yet, just copy. */
    429  1.14     maxv 	memcpy(vcpu->exit, &args.exit, sizeof(args.exit));
    430   1.1     maxv 
    431   1.1     maxv 	return 0;
    432   1.1     maxv }
    433   1.1     maxv 
    434   1.1     maxv int
    435   1.1     maxv nvmm_gpa_map(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
    436   1.7     maxv     size_t size, int prot)
    437   1.1     maxv {
    438   1.1     maxv 	struct nvmm_ioc_gpa_map args;
    439   1.1     maxv 	int ret;
    440   1.1     maxv 
    441   1.8     maxv 	ret = __area_add(mach, hva, gpa, size, prot);
    442   1.3     maxv 	if (ret == -1)
    443   1.3     maxv 		return -1;
    444   1.3     maxv 
    445   1.1     maxv 	args.machid = mach->machid;
    446   1.1     maxv 	args.hva = hva;
    447   1.1     maxv 	args.gpa = gpa;
    448   1.1     maxv 	args.size = size;
    449   1.7     maxv 	args.prot = prot;
    450   1.1     maxv 
    451   1.1     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_GPA_MAP, &args);
    452   1.1     maxv 	if (ret == -1) {
    453   1.3     maxv 		/* Can't recover. */
    454   1.3     maxv 		abort();
    455   1.1     maxv 	}
    456   1.1     maxv 
    457   1.1     maxv 	return 0;
    458   1.1     maxv }
    459   1.1     maxv 
    460   1.1     maxv int
    461   1.1     maxv nvmm_gpa_unmap(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
    462   1.1     maxv     size_t size)
    463   1.1     maxv {
    464   1.4     maxv 	struct nvmm_ioc_gpa_unmap args;
    465   1.4     maxv 	int ret;
    466   1.4     maxv 
    467   1.4     maxv 	ret = __area_delete(mach, hva, gpa, size);
    468   1.4     maxv 	if (ret == -1)
    469   1.4     maxv 		return -1;
    470   1.4     maxv 
    471   1.4     maxv 	args.machid = mach->machid;
    472   1.4     maxv 	args.gpa = gpa;
    473   1.4     maxv 	args.size = size;
    474   1.4     maxv 
    475   1.4     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_GPA_UNMAP, &args);
    476   1.5     maxv 	if (ret == -1) {
    477   1.5     maxv 		/* Can't recover. */
    478   1.5     maxv 		abort();
    479   1.5     maxv 	}
    480   1.5     maxv 
    481   1.5     maxv 	return 0;
    482   1.5     maxv }
    483   1.5     maxv 
    484   1.5     maxv int
    485   1.5     maxv nvmm_hva_map(struct nvmm_machine *mach, uintptr_t hva, size_t size)
    486   1.5     maxv {
    487   1.5     maxv 	struct nvmm_ioc_hva_map args;
    488   1.5     maxv 	int ret;
    489   1.5     maxv 
    490   1.5     maxv 	args.machid = mach->machid;
    491   1.5     maxv 	args.hva = hva;
    492   1.5     maxv 	args.size = size;
    493   1.5     maxv 
    494   1.5     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_HVA_MAP, &args);
    495   1.4     maxv 	if (ret == -1)
    496   1.4     maxv 		return -1;
    497   1.4     maxv 
    498   1.5     maxv 	return 0;
    499   1.5     maxv }
    500   1.4     maxv 
    501   1.5     maxv int
    502   1.5     maxv nvmm_hva_unmap(struct nvmm_machine *mach, uintptr_t hva, size_t size)
    503   1.5     maxv {
    504   1.6     maxv 	struct nvmm_ioc_hva_unmap args;
    505   1.5     maxv 	int ret;
    506   1.5     maxv 
    507   1.5     maxv 	args.machid = mach->machid;
    508   1.5     maxv 	args.hva = hva;
    509   1.5     maxv 	args.size = size;
    510   1.5     maxv 
    511   1.6     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_HVA_UNMAP, &args);
    512   1.5     maxv 	if (ret == -1)
    513   1.5     maxv 		return -1;
    514   1.5     maxv 
    515   1.5     maxv 	return 0;
    516   1.1     maxv }
    517   1.1     maxv 
    518   1.1     maxv /*
    519   1.1     maxv  * nvmm_gva_to_gpa(): architecture-specific.
    520   1.1     maxv  */
    521   1.1     maxv 
    522   1.1     maxv int
    523   1.8     maxv nvmm_gpa_to_hva(struct nvmm_machine *mach, gpaddr_t gpa, uintptr_t *hva,
    524   1.8     maxv     nvmm_prot_t *prot)
    525   1.1     maxv {
    526   1.3     maxv 	area_list_t *areas = mach->areas;
    527   1.3     maxv 	area_t *ent;
    528   1.1     maxv 
    529   1.3     maxv 	LIST_FOREACH(ent, areas, list) {
    530   1.5     maxv 		if (gpa >= ent->gpa && gpa < ent->gpa + ent->size) {
    531   1.5     maxv 			*hva = ent->hva + (gpa - ent->gpa);
    532   1.8     maxv 			*prot = ent->prot;
    533   1.5     maxv 			return 0;
    534   1.1     maxv 		}
    535   1.1     maxv 	}
    536   1.1     maxv 
    537   1.1     maxv 	errno = ENOENT;
    538   1.1     maxv 	return -1;
    539   1.1     maxv }
    540   1.1     maxv 
    541   1.1     maxv /*
    542   1.1     maxv  * nvmm_assist_io(): architecture-specific.
    543   1.1     maxv  */
    544   1.6     maxv 
    545   1.6     maxv /*
    546   1.6     maxv  * nvmm_assist_mem(): architecture-specific.
    547   1.6     maxv  */
    548   1.6     maxv 
    549   1.9     maxv int
    550   1.9     maxv nvmm_ctl(int op, void *data, size_t size)
    551   1.9     maxv {
    552   1.9     maxv 	struct nvmm_ioc_ctl args;
    553   1.9     maxv 	int ret;
    554   1.9     maxv 
    555   1.9     maxv 	args.op = op;
    556   1.9     maxv 	args.data = data;
    557   1.9     maxv 	args.size = size;
    558   1.9     maxv 
    559   1.9     maxv 	ret = ioctl(nvmm_fd, NVMM_IOC_CTL, &args);
    560   1.9     maxv 	if (ret == -1)
    561   1.9     maxv 		return -1;
    562   1.9     maxv 
    563   1.9     maxv 	return 0;
    564   1.9     maxv }
    565  1.20  reinoud 
    566  1.20  reinoud int
    567  1.20  reinoud nvmm_vcpu_stop(struct nvmm_vcpu *vcpu)
    568  1.20  reinoud {
    569  1.20  reinoud 
    570  1.20  reinoud 	*vcpu->stop = 1;
    571  1.20  reinoud 
    572  1.20  reinoud 	return 0;
    573  1.20  reinoud }
    574