1*e0d9d410Sreinoud /* $NetBSD: libnvmm.c,v 1.20 2021/04/06 08:40:17 reinoud Exp $ */
22760ca24Smaxv
32760ca24Smaxv /*
44a2e4dc3Smaxv * Copyright (c) 2018-2020 Maxime Villard, m00nbsd.net
52760ca24Smaxv * All rights reserved.
62760ca24Smaxv *
74a2e4dc3Smaxv * This code is part of the NVMM hypervisor.
82760ca24Smaxv *
92760ca24Smaxv * Redistribution and use in source and binary forms, with or without
102760ca24Smaxv * modification, are permitted provided that the following conditions
112760ca24Smaxv * are met:
122760ca24Smaxv * 1. Redistributions of source code must retain the above copyright
132760ca24Smaxv * notice, this list of conditions and the following disclaimer.
142760ca24Smaxv * 2. Redistributions in binary form must reproduce the above copyright
152760ca24Smaxv * notice, this list of conditions and the following disclaimer in the
162760ca24Smaxv * documentation and/or other materials provided with the distribution.
172760ca24Smaxv *
184a2e4dc3Smaxv * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
194a2e4dc3Smaxv * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
204a2e4dc3Smaxv * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
214a2e4dc3Smaxv * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
224a2e4dc3Smaxv * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
234a2e4dc3Smaxv * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
244a2e4dc3Smaxv * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
254a2e4dc3Smaxv * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
264a2e4dc3Smaxv * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
274a2e4dc3Smaxv * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
284a2e4dc3Smaxv * SUCH DAMAGE.
292760ca24Smaxv */
302760ca24Smaxv
312760ca24Smaxv #include <sys/cdefs.h>
322760ca24Smaxv
332760ca24Smaxv #include <stdio.h>
342760ca24Smaxv #include <stdlib.h>
352760ca24Smaxv #include <string.h>
362760ca24Smaxv #include <unistd.h>
372760ca24Smaxv #include <fcntl.h>
382760ca24Smaxv #include <errno.h>
392760ca24Smaxv #include <sys/ioctl.h>
402760ca24Smaxv #include <sys/mman.h>
41a026d6cbSmaxv #include <sys/queue.h>
42f9737344Smaxv #include <machine/vmparam.h>
432760ca24Smaxv
442760ca24Smaxv #include "nvmm.h"
452760ca24Smaxv
46f9737344Smaxv static struct nvmm_capability __capability;
47f9737344Smaxv
48f9737344Smaxv #ifdef __x86_64__
49f9737344Smaxv #include "libnvmm_x86.c"
50f9737344Smaxv #endif
5138b2a665Smaxv
52a026d6cbSmaxv typedef struct __area {
53a026d6cbSmaxv LIST_ENTRY(__area) list;
54a026d6cbSmaxv gpaddr_t gpa;
55a026d6cbSmaxv uintptr_t hva;
56a026d6cbSmaxv size_t size;
57e00a8e01Smaxv nvmm_prot_t prot;
58a026d6cbSmaxv } area_t;
59a026d6cbSmaxv
60a026d6cbSmaxv typedef LIST_HEAD(, __area) area_list_t;
61a026d6cbSmaxv
622760ca24Smaxv static int nvmm_fd = -1;
632760ca24Smaxv
642760ca24Smaxv /* -------------------------------------------------------------------------- */
652760ca24Smaxv
666c8db606Smaxv static bool
__area_isvalid(struct nvmm_machine * mach,uintptr_t hva,gpaddr_t gpa,size_t size)676c8db606Smaxv __area_isvalid(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
68a026d6cbSmaxv size_t size)
69a026d6cbSmaxv {
70a026d6cbSmaxv area_list_t *areas = mach->areas;
716c8db606Smaxv area_t *ent;
72a026d6cbSmaxv
736c8db606Smaxv LIST_FOREACH(ent, areas, list) {
746c8db606Smaxv /* Collision on GPA */
756c8db606Smaxv if (gpa >= ent->gpa && gpa < ent->gpa + ent->size) {
766c8db606Smaxv return false;
77a026d6cbSmaxv }
78506b4248Smaxv if (gpa + size > ent->gpa &&
79506b4248Smaxv gpa + size <= ent->gpa + ent->size) {
806c8db606Smaxv return false;
81a026d6cbSmaxv }
826c8db606Smaxv if (gpa <= ent->gpa && gpa + size >= ent->gpa + ent->size) {
836c8db606Smaxv return false;
84a026d6cbSmaxv }
85a026d6cbSmaxv }
86a026d6cbSmaxv
876c8db606Smaxv return true;
88a026d6cbSmaxv }
89a026d6cbSmaxv
90a026d6cbSmaxv static int
__area_add(struct nvmm_machine * mach,uintptr_t hva,gpaddr_t gpa,size_t size,int prot)91e00a8e01Smaxv __area_add(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa, size_t size,
92e00a8e01Smaxv int prot)
93a026d6cbSmaxv {
94a026d6cbSmaxv area_list_t *areas = mach->areas;
95e00a8e01Smaxv nvmm_prot_t nprot;
96a026d6cbSmaxv area_t *area;
976c8db606Smaxv
98e00a8e01Smaxv nprot = 0;
99e00a8e01Smaxv if (prot & PROT_READ)
100e00a8e01Smaxv nprot |= NVMM_PROT_READ;
101e00a8e01Smaxv if (prot & PROT_WRITE)
102e00a8e01Smaxv nprot |= NVMM_PROT_WRITE;
103e00a8e01Smaxv if (prot & PROT_EXEC)
104e00a8e01Smaxv nprot |= NVMM_PROT_EXEC;
105e00a8e01Smaxv
1066c8db606Smaxv if (!__area_isvalid(mach, hva, gpa, size)) {
1076c8db606Smaxv errno = EINVAL;
1086c8db606Smaxv return -1;
1096c8db606Smaxv }
110a026d6cbSmaxv
111a026d6cbSmaxv area = malloc(sizeof(*area));
112a026d6cbSmaxv if (area == NULL)
113a026d6cbSmaxv return -1;
1142760ca24Smaxv area->gpa = gpa;
1152760ca24Smaxv area->hva = hva;
1162760ca24Smaxv area->size = size;
117e00a8e01Smaxv area->prot = nprot;
1182760ca24Smaxv
1196c8db606Smaxv LIST_INSERT_HEAD(areas, area, list);
1206c8db606Smaxv
1216c8db606Smaxv return 0;
1222760ca24Smaxv }
1232760ca24Smaxv
1246c8db606Smaxv static int
__area_delete(struct nvmm_machine * mach,uintptr_t hva,gpaddr_t gpa,size_t size)1256c8db606Smaxv __area_delete(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
1266c8db606Smaxv size_t size)
1276c8db606Smaxv {
1286c8db606Smaxv area_list_t *areas = mach->areas;
1296c8db606Smaxv area_t *ent, *nxt;
1306c8db606Smaxv
1316c8db606Smaxv LIST_FOREACH_SAFE(ent, areas, list, nxt) {
1326c8db606Smaxv if (hva == ent->hva && gpa == ent->gpa && size == ent->size) {
1336c8db606Smaxv LIST_REMOVE(ent, list);
1346c8db606Smaxv free(ent);
135a026d6cbSmaxv return 0;
136a026d6cbSmaxv }
1376c8db606Smaxv }
1386c8db606Smaxv
1396c8db606Smaxv return -1;
1406c8db606Smaxv }
141a026d6cbSmaxv
142a026d6cbSmaxv static void
__area_remove_all(struct nvmm_machine * mach)143a026d6cbSmaxv __area_remove_all(struct nvmm_machine *mach)
1442760ca24Smaxv {
145a026d6cbSmaxv area_list_t *areas = mach->areas;
146a026d6cbSmaxv area_t *ent;
1472760ca24Smaxv
148a026d6cbSmaxv while ((ent = LIST_FIRST(areas)) != NULL) {
149a026d6cbSmaxv LIST_REMOVE(ent, list);
150a026d6cbSmaxv free(ent);
1512760ca24Smaxv }
1522760ca24Smaxv
153a026d6cbSmaxv free(areas);
1542760ca24Smaxv }
1552760ca24Smaxv
1562760ca24Smaxv /* -------------------------------------------------------------------------- */
1572760ca24Smaxv
158a6418236Smaxv int
nvmm_init(void)1592760ca24Smaxv nvmm_init(void)
1602760ca24Smaxv {
1612760ca24Smaxv if (nvmm_fd != -1)
1622760ca24Smaxv return 0;
163f9fb7866Smaxv nvmm_fd = open("/dev/nvmm", O_RDONLY | O_CLOEXEC);
1642760ca24Smaxv if (nvmm_fd == -1)
1652760ca24Smaxv return -1;
166f9737344Smaxv if (nvmm_capability(&__capability) == -1) {
167f9737344Smaxv close(nvmm_fd);
168f9737344Smaxv nvmm_fd = -1;
169f9737344Smaxv return -1;
170f9737344Smaxv }
171f9fb7866Smaxv if (__capability.version != NVMM_KERN_VERSION) {
172f9fb7866Smaxv close(nvmm_fd);
173f9fb7866Smaxv nvmm_fd = -1;
174f9fb7866Smaxv errno = EPROGMISMATCH;
175f9fb7866Smaxv return -1;
176f9fb7866Smaxv }
177f9fb7866Smaxv
1782760ca24Smaxv return 0;
1792760ca24Smaxv }
1802760ca24Smaxv
1812760ca24Smaxv int
nvmm_root_init(void)182d2ac291eSmaxv nvmm_root_init(void)
183d2ac291eSmaxv {
184d2ac291eSmaxv if (nvmm_fd != -1)
185d2ac291eSmaxv return 0;
186d2ac291eSmaxv nvmm_fd = open("/dev/nvmm", O_WRONLY | O_CLOEXEC);
187d2ac291eSmaxv if (nvmm_fd == -1)
188d2ac291eSmaxv return -1;
189d2ac291eSmaxv if (nvmm_capability(&__capability) == -1) {
190d2ac291eSmaxv close(nvmm_fd);
191d2ac291eSmaxv nvmm_fd = -1;
192d2ac291eSmaxv return -1;
193d2ac291eSmaxv }
194d2ac291eSmaxv if (__capability.version != NVMM_KERN_VERSION) {
195d2ac291eSmaxv close(nvmm_fd);
196d2ac291eSmaxv nvmm_fd = -1;
197d2ac291eSmaxv errno = EPROGMISMATCH;
198d2ac291eSmaxv return -1;
199d2ac291eSmaxv }
200d2ac291eSmaxv
201d2ac291eSmaxv return 0;
202d2ac291eSmaxv }
203d2ac291eSmaxv
204d2ac291eSmaxv int
nvmm_capability(struct nvmm_capability * cap)2052760ca24Smaxv nvmm_capability(struct nvmm_capability *cap)
2062760ca24Smaxv {
2072760ca24Smaxv struct nvmm_ioc_capability args;
2082760ca24Smaxv int ret;
2092760ca24Smaxv
2102760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_CAPABILITY, &args);
2112760ca24Smaxv if (ret == -1)
2122760ca24Smaxv return -1;
2132760ca24Smaxv
2142760ca24Smaxv memcpy(cap, &args.cap, sizeof(args.cap));
2152760ca24Smaxv
2162760ca24Smaxv return 0;
2172760ca24Smaxv }
2182760ca24Smaxv
2192760ca24Smaxv int
nvmm_machine_create(struct nvmm_machine * mach)2202760ca24Smaxv nvmm_machine_create(struct nvmm_machine *mach)
2212760ca24Smaxv {
2222760ca24Smaxv struct nvmm_ioc_machine_create args;
223f9737344Smaxv struct nvmm_comm_page **pages;
224a026d6cbSmaxv area_list_t *areas;
2252760ca24Smaxv int ret;
2262760ca24Smaxv
227a026d6cbSmaxv areas = calloc(1, sizeof(*areas));
228a026d6cbSmaxv if (areas == NULL)
2292760ca24Smaxv return -1;
2302760ca24Smaxv
231f9737344Smaxv pages = calloc(__capability.max_vcpus, sizeof(*pages));
232f9737344Smaxv if (pages == NULL) {
233f9737344Smaxv free(areas);
234f9737344Smaxv return -1;
235f9737344Smaxv }
236f9737344Smaxv
237a026d6cbSmaxv ret = ioctl(nvmm_fd, NVMM_IOC_MACHINE_CREATE, &args);
238a026d6cbSmaxv if (ret == -1) {
239a026d6cbSmaxv free(areas);
240a026d6cbSmaxv return -1;
241a026d6cbSmaxv }
242a026d6cbSmaxv
243a026d6cbSmaxv LIST_INIT(areas);
244f9737344Smaxv
245f9737344Smaxv memset(mach, 0, sizeof(*mach));
2462760ca24Smaxv mach->machid = args.machid;
247f9737344Smaxv mach->pages = pages;
248f9737344Smaxv mach->areas = areas;
2492760ca24Smaxv
2502760ca24Smaxv return 0;
2512760ca24Smaxv }
2522760ca24Smaxv
2532760ca24Smaxv int
nvmm_machine_destroy(struct nvmm_machine * mach)2542760ca24Smaxv nvmm_machine_destroy(struct nvmm_machine *mach)
2552760ca24Smaxv {
2562760ca24Smaxv struct nvmm_ioc_machine_destroy args;
2572760ca24Smaxv int ret;
2582760ca24Smaxv
2592760ca24Smaxv args.machid = mach->machid;
2602760ca24Smaxv
2612760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_MACHINE_DESTROY, &args);
2622760ca24Smaxv if (ret == -1)
2632760ca24Smaxv return -1;
2642760ca24Smaxv
265a026d6cbSmaxv __area_remove_all(mach);
266f9737344Smaxv free(mach->pages);
2672760ca24Smaxv
2682760ca24Smaxv return 0;
2692760ca24Smaxv }
2702760ca24Smaxv
2712760ca24Smaxv int
nvmm_machine_configure(struct nvmm_machine * mach,uint64_t op,void * conf)2722760ca24Smaxv nvmm_machine_configure(struct nvmm_machine *mach, uint64_t op, void *conf)
2732760ca24Smaxv {
2742760ca24Smaxv struct nvmm_ioc_machine_configure args;
2752760ca24Smaxv int ret;
2762760ca24Smaxv
2772760ca24Smaxv args.machid = mach->machid;
2782760ca24Smaxv args.op = op;
2792760ca24Smaxv args.conf = conf;
2802760ca24Smaxv
2812760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_MACHINE_CONFIGURE, &args);
2822760ca24Smaxv if (ret == -1)
2832760ca24Smaxv return -1;
2842760ca24Smaxv
2852760ca24Smaxv return 0;
2862760ca24Smaxv }
2872760ca24Smaxv
2882760ca24Smaxv int
nvmm_vcpu_create(struct nvmm_machine * mach,nvmm_cpuid_t cpuid,struct nvmm_vcpu * vcpu)289d1002cd7Smaxv nvmm_vcpu_create(struct nvmm_machine *mach, nvmm_cpuid_t cpuid,
290d1002cd7Smaxv struct nvmm_vcpu *vcpu)
2912760ca24Smaxv {
2922760ca24Smaxv struct nvmm_ioc_vcpu_create args;
293f9737344Smaxv struct nvmm_comm_page *comm;
2942760ca24Smaxv int ret;
2952760ca24Smaxv
2962760ca24Smaxv args.machid = mach->machid;
2972760ca24Smaxv args.cpuid = cpuid;
2982760ca24Smaxv
2992760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_CREATE, &args);
3002760ca24Smaxv if (ret == -1)
3012760ca24Smaxv return -1;
3022760ca24Smaxv
303f9737344Smaxv comm = mmap(NULL, PAGE_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FILE,
304f9737344Smaxv nvmm_fd, NVMM_COMM_OFF(mach->machid, cpuid));
305f9737344Smaxv if (comm == MAP_FAILED)
306f9737344Smaxv return -1;
307f9737344Smaxv
308f9737344Smaxv mach->pages[cpuid] = comm;
309f9737344Smaxv
310d1002cd7Smaxv vcpu->cpuid = cpuid;
311d1002cd7Smaxv vcpu->state = &comm->state;
312d1002cd7Smaxv vcpu->event = &comm->event;
313*e0d9d410Sreinoud vcpu->stop = &comm->stop;
314d1002cd7Smaxv vcpu->exit = malloc(sizeof(*vcpu->exit));
315d1002cd7Smaxv
3162760ca24Smaxv return 0;
3172760ca24Smaxv }
3182760ca24Smaxv
3192760ca24Smaxv int
nvmm_vcpu_destroy(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)320d1002cd7Smaxv nvmm_vcpu_destroy(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
3212760ca24Smaxv {
3222760ca24Smaxv struct nvmm_ioc_vcpu_destroy args;
323f9737344Smaxv struct nvmm_comm_page *comm;
3242760ca24Smaxv int ret;
3252760ca24Smaxv
3262760ca24Smaxv args.machid = mach->machid;
327d1002cd7Smaxv args.cpuid = vcpu->cpuid;
3282760ca24Smaxv
3292760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_DESTROY, &args);
3302760ca24Smaxv if (ret == -1)
3312760ca24Smaxv return -1;
3322760ca24Smaxv
333d1002cd7Smaxv comm = mach->pages[vcpu->cpuid];
334f9737344Smaxv munmap(comm, PAGE_SIZE);
335d1002cd7Smaxv free(vcpu->exit);
336f9737344Smaxv
3372760ca24Smaxv return 0;
3382760ca24Smaxv }
3392760ca24Smaxv
3402760ca24Smaxv int
nvmm_vcpu_configure(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu,uint64_t op,void * conf)341f9fb7866Smaxv nvmm_vcpu_configure(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
342f9fb7866Smaxv uint64_t op, void *conf)
343f9fb7866Smaxv {
344f9fb7866Smaxv struct nvmm_ioc_vcpu_configure args;
345f9fb7866Smaxv int ret;
346f9fb7866Smaxv
347e6f32a58Smaxv switch (op) {
348e6f32a58Smaxv case NVMM_VCPU_CONF_CALLBACKS:
349e6f32a58Smaxv memcpy(&vcpu->cbs, conf, sizeof(vcpu->cbs));
350e6f32a58Smaxv return 0;
351e6f32a58Smaxv }
352e6f32a58Smaxv
353f9fb7866Smaxv args.machid = mach->machid;
354f9fb7866Smaxv args.cpuid = vcpu->cpuid;
355f9fb7866Smaxv args.op = op;
356f9fb7866Smaxv args.conf = conf;
357f9fb7866Smaxv
358f9fb7866Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_CONFIGURE, &args);
359f9fb7866Smaxv if (ret == -1)
360f9fb7866Smaxv return -1;
361f9fb7866Smaxv
362f9fb7866Smaxv return 0;
363f9fb7866Smaxv }
364f9fb7866Smaxv
365f9fb7866Smaxv int
nvmm_vcpu_setstate(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu,uint64_t flags)366d1002cd7Smaxv nvmm_vcpu_setstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
367d1002cd7Smaxv uint64_t flags)
3682760ca24Smaxv {
369f9737344Smaxv struct nvmm_comm_page *comm;
3702760ca24Smaxv
371d1002cd7Smaxv comm = mach->pages[vcpu->cpuid];
372f9737344Smaxv comm->state_commit |= flags;
373f9737344Smaxv comm->state_cached |= flags;
3742760ca24Smaxv
3752760ca24Smaxv return 0;
3762760ca24Smaxv }
3772760ca24Smaxv
3782760ca24Smaxv int
nvmm_vcpu_getstate(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu,uint64_t flags)379d1002cd7Smaxv nvmm_vcpu_getstate(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu,
380d1002cd7Smaxv uint64_t flags)
3812760ca24Smaxv {
3822760ca24Smaxv struct nvmm_ioc_vcpu_getstate args;
383f9737344Smaxv struct nvmm_comm_page *comm;
3842760ca24Smaxv int ret;
3852760ca24Smaxv
386d1002cd7Smaxv comm = mach->pages[vcpu->cpuid];
387f9737344Smaxv
388f9737344Smaxv if (__predict_true((flags & ~comm->state_cached) == 0)) {
389d1002cd7Smaxv return 0;
390f9737344Smaxv }
391f9737344Smaxv comm->state_wanted = flags & ~comm->state_cached;
392f9737344Smaxv
3932760ca24Smaxv args.machid = mach->machid;
394d1002cd7Smaxv args.cpuid = vcpu->cpuid;
3952760ca24Smaxv
3962760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_GETSTATE, &args);
3972760ca24Smaxv if (ret == -1)
3982760ca24Smaxv return -1;
3992760ca24Smaxv
4002760ca24Smaxv return 0;
4012760ca24Smaxv }
4022760ca24Smaxv
4032760ca24Smaxv int
nvmm_vcpu_inject(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)404d1002cd7Smaxv nvmm_vcpu_inject(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
4052760ca24Smaxv {
4060d954de6Smaxv struct nvmm_comm_page *comm;
4072760ca24Smaxv
408d1002cd7Smaxv comm = mach->pages[vcpu->cpuid];
4090d954de6Smaxv comm->event_commit = true;
4102760ca24Smaxv
4112760ca24Smaxv return 0;
4122760ca24Smaxv }
4132760ca24Smaxv
4142760ca24Smaxv int
nvmm_vcpu_run(struct nvmm_machine * mach,struct nvmm_vcpu * vcpu)415d1002cd7Smaxv nvmm_vcpu_run(struct nvmm_machine *mach, struct nvmm_vcpu *vcpu)
4162760ca24Smaxv {
4172760ca24Smaxv struct nvmm_ioc_vcpu_run args;
4182760ca24Smaxv int ret;
4192760ca24Smaxv
4202760ca24Smaxv args.machid = mach->machid;
421d1002cd7Smaxv args.cpuid = vcpu->cpuid;
4222760ca24Smaxv memset(&args.exit, 0, sizeof(args.exit));
4232760ca24Smaxv
4242760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_VCPU_RUN, &args);
4252760ca24Smaxv if (ret == -1)
4262760ca24Smaxv return -1;
4272760ca24Smaxv
428d1002cd7Smaxv /* No comm support yet, just copy. */
429d1002cd7Smaxv memcpy(vcpu->exit, &args.exit, sizeof(args.exit));
4302760ca24Smaxv
4312760ca24Smaxv return 0;
4322760ca24Smaxv }
4332760ca24Smaxv
4342760ca24Smaxv int
nvmm_gpa_map(struct nvmm_machine * mach,uintptr_t hva,gpaddr_t gpa,size_t size,int prot)4352760ca24Smaxv nvmm_gpa_map(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
436e8b93c69Smaxv size_t size, int prot)
4372760ca24Smaxv {
4382760ca24Smaxv struct nvmm_ioc_gpa_map args;
4392760ca24Smaxv int ret;
4402760ca24Smaxv
441e00a8e01Smaxv ret = __area_add(mach, hva, gpa, size, prot);
442a026d6cbSmaxv if (ret == -1)
443a026d6cbSmaxv return -1;
444a026d6cbSmaxv
4452760ca24Smaxv args.machid = mach->machid;
4462760ca24Smaxv args.hva = hva;
4472760ca24Smaxv args.gpa = gpa;
4482760ca24Smaxv args.size = size;
449e8b93c69Smaxv args.prot = prot;
4502760ca24Smaxv
4512760ca24Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_GPA_MAP, &args);
4522760ca24Smaxv if (ret == -1) {
453a026d6cbSmaxv /* Can't recover. */
454a026d6cbSmaxv abort();
4552760ca24Smaxv }
4562760ca24Smaxv
4572760ca24Smaxv return 0;
4582760ca24Smaxv }
4592760ca24Smaxv
4602760ca24Smaxv int
nvmm_gpa_unmap(struct nvmm_machine * mach,uintptr_t hva,gpaddr_t gpa,size_t size)4612760ca24Smaxv nvmm_gpa_unmap(struct nvmm_machine *mach, uintptr_t hva, gpaddr_t gpa,
4622760ca24Smaxv size_t size)
4632760ca24Smaxv {
4646c8db606Smaxv struct nvmm_ioc_gpa_unmap args;
4656c8db606Smaxv int ret;
4666c8db606Smaxv
4676c8db606Smaxv ret = __area_delete(mach, hva, gpa, size);
4686c8db606Smaxv if (ret == -1)
4696c8db606Smaxv return -1;
4706c8db606Smaxv
4716c8db606Smaxv args.machid = mach->machid;
4726c8db606Smaxv args.gpa = gpa;
4736c8db606Smaxv args.size = size;
4746c8db606Smaxv
4756c8db606Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_GPA_UNMAP, &args);
476506b4248Smaxv if (ret == -1) {
477506b4248Smaxv /* Can't recover. */
478506b4248Smaxv abort();
479506b4248Smaxv }
480506b4248Smaxv
481506b4248Smaxv return 0;
482506b4248Smaxv }
483506b4248Smaxv
484506b4248Smaxv int
nvmm_hva_map(struct nvmm_machine * mach,uintptr_t hva,size_t size)485506b4248Smaxv nvmm_hva_map(struct nvmm_machine *mach, uintptr_t hva, size_t size)
486506b4248Smaxv {
487506b4248Smaxv struct nvmm_ioc_hva_map args;
488506b4248Smaxv int ret;
489506b4248Smaxv
490506b4248Smaxv args.machid = mach->machid;
491506b4248Smaxv args.hva = hva;
492506b4248Smaxv args.size = size;
493506b4248Smaxv
494506b4248Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_HVA_MAP, &args);
4956c8db606Smaxv if (ret == -1)
4966c8db606Smaxv return -1;
4976c8db606Smaxv
498506b4248Smaxv return 0;
499506b4248Smaxv }
5006c8db606Smaxv
501506b4248Smaxv int
nvmm_hva_unmap(struct nvmm_machine * mach,uintptr_t hva,size_t size)502506b4248Smaxv nvmm_hva_unmap(struct nvmm_machine *mach, uintptr_t hva, size_t size)
503506b4248Smaxv {
50438b2a665Smaxv struct nvmm_ioc_hva_unmap args;
505506b4248Smaxv int ret;
506506b4248Smaxv
507506b4248Smaxv args.machid = mach->machid;
508506b4248Smaxv args.hva = hva;
509506b4248Smaxv args.size = size;
510506b4248Smaxv
51138b2a665Smaxv ret = ioctl(nvmm_fd, NVMM_IOC_HVA_UNMAP, &args);
512506b4248Smaxv if (ret == -1)
513506b4248Smaxv return -1;
514506b4248Smaxv
515506b4248Smaxv return 0;
5162760ca24Smaxv }
5172760ca24Smaxv
5182760ca24Smaxv /*
5192760ca24Smaxv * nvmm_gva_to_gpa(): architecture-specific.
5202760ca24Smaxv */
5212760ca24Smaxv
5222760ca24Smaxv int
nvmm_gpa_to_hva(struct nvmm_machine * mach,gpaddr_t gpa,uintptr_t * hva,nvmm_prot_t * prot)523e00a8e01Smaxv nvmm_gpa_to_hva(struct nvmm_machine *mach, gpaddr_t gpa, uintptr_t *hva,
524e00a8e01Smaxv nvmm_prot_t *prot)
5252760ca24Smaxv {
526a026d6cbSmaxv area_list_t *areas = mach->areas;
527a026d6cbSmaxv area_t *ent;
5282760ca24Smaxv
529a026d6cbSmaxv LIST_FOREACH(ent, areas, list) {
530506b4248Smaxv if (gpa >= ent->gpa && gpa < ent->gpa + ent->size) {
531a026d6cbSmaxv *hva = ent->hva + (gpa - ent->gpa);
532e00a8e01Smaxv *prot = ent->prot;
5332760ca24Smaxv return 0;
5342760ca24Smaxv }
535506b4248Smaxv }
5362760ca24Smaxv
5372760ca24Smaxv errno = ENOENT;
5382760ca24Smaxv return -1;
5392760ca24Smaxv }
5402760ca24Smaxv
5412760ca24Smaxv /*
5422760ca24Smaxv * nvmm_assist_io(): architecture-specific.
5432760ca24Smaxv */
54438b2a665Smaxv
54538b2a665Smaxv /*
54638b2a665Smaxv * nvmm_assist_mem(): architecture-specific.
54738b2a665Smaxv */
54838b2a665Smaxv
549fbb489fbSmaxv int
nvmm_ctl(int op,void * data,size_t size)550fbb489fbSmaxv nvmm_ctl(int op, void *data, size_t size)
551fbb489fbSmaxv {
552fbb489fbSmaxv struct nvmm_ioc_ctl args;
553fbb489fbSmaxv int ret;
554fbb489fbSmaxv
555fbb489fbSmaxv args.op = op;
556fbb489fbSmaxv args.data = data;
557fbb489fbSmaxv args.size = size;
558fbb489fbSmaxv
559fbb489fbSmaxv ret = ioctl(nvmm_fd, NVMM_IOC_CTL, &args);
560fbb489fbSmaxv if (ret == -1)
561fbb489fbSmaxv return -1;
562fbb489fbSmaxv
563fbb489fbSmaxv return 0;
564fbb489fbSmaxv }
565*e0d9d410Sreinoud
566*e0d9d410Sreinoud int
nvmm_vcpu_stop(struct nvmm_vcpu * vcpu)567*e0d9d410Sreinoud nvmm_vcpu_stop(struct nvmm_vcpu *vcpu)
568*e0d9d410Sreinoud {
569*e0d9d410Sreinoud
570*e0d9d410Sreinoud *vcpu->stop = 1;
571*e0d9d410Sreinoud
572*e0d9d410Sreinoud return 0;
573*e0d9d410Sreinoud }
574