Add NVMM - for NetBSD Virtual Machine Monitor -, a kernel driver that
provides support for hardware-accelerated virtualization on NetBSD. It is made of an MI frontend, to which MD backends can be plugged. One MD backend is implemented, x86-SVM, for x86 AMD CPUs. We install /usr/include/dev/nvmm/nvmm.h /usr/include/dev/nvmm/nvmm_ioctl.h /usr/include/dev/nvmm/{arch}/nvmm_{arch}.h And the kernel module. For now, the only architecture where we do that is amd64 (arch=x86). NVMM is not enabled by default in amd64-GENERIC, but is instead easily modloadable. Sent to tech-kern@ a month ago. Validated with kASan, and optimized with tprof.
This commit is contained in:
parent
8c426f1bc1
commit
f3a4baf748
@ -1,4 +1,4 @@
|
||||
# $NetBSD: md.amd64,v 1.259 2018/07/17 18:55:24 joerg Exp $
|
||||
# $NetBSD: md.amd64,v 1.260 2018/11/07 07:43:07 maxv Exp $
|
||||
|
||||
./usr/include/amd64 comp-c-include
|
||||
./usr/include/amd64/ansi.h comp-c-include
|
||||
@ -677,6 +677,11 @@
|
||||
./usr/include/ieeefp.h comp-c-include
|
||||
./usr/include/mm_malloc.h comp-obsolete obsolete
|
||||
./usr/include/mmintrin.h comp-obsolete obsolete
|
||||
./usr/include/dev/nvmm comp-c-include
|
||||
./usr/include/dev/nvmm/nvmm.h comp-c-include
|
||||
./usr/include/dev/nvmm/nvmm_ioctl.h comp-c-include
|
||||
./usr/include/dev/nvmm/x86 comp-c-include
|
||||
./usr/include/dev/nvmm/x86/nvmm_x86.h comp-c-include
|
||||
./usr/include/pmmintrin.h comp-obsolete obsolete
|
||||
./usr/include/x64_64 comp-obsolete obsolete
|
||||
./usr/include/x64_64/ansi.h comp-obsolete obsolete
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: md.amd64,v 1.77 2018/08/28 09:42:10 martin Exp $
|
||||
# $NetBSD: md.amd64,v 1.78 2018/11/07 07:43:07 maxv Exp $
|
||||
#
|
||||
# NOTE that there are two sets of files here:
|
||||
# @MODULEDIR@ and amd64-xen
|
||||
@ -141,6 +141,8 @@
|
||||
./@MODULEDIR@/mt2131/mt2131.kmod base-kernel-modules kmod
|
||||
./@MODULEDIR@/nvme base-obsolete obsolete
|
||||
./@MODULEDIR@/nvme/nvme.kmod base-obsolete obsolete
|
||||
./@MODULEDIR@/nvmm base-kernel-modules kmod
|
||||
./@MODULEDIR@/nvmm/nvmm.kmod base-kernel-modules kmod
|
||||
./@MODULEDIR@/nxt2k base-kernel-modules kmod
|
||||
./@MODULEDIR@/nxt2k/nxt2k.kmod base-kernel-modules kmod
|
||||
./@MODULEDIR@/odcm base-kernel-modules kmod
|
||||
|
@ -1,5 +1,5 @@
|
||||
#!/bin/sh -
|
||||
# $NetBSD: MAKEDEV.tmpl,v 1.195 2018/11/04 12:48:01 maxv Exp $
|
||||
# $NetBSD: MAKEDEV.tmpl,v 1.196 2018/11/07 07:43:07 maxv Exp $
|
||||
#
|
||||
# Copyright (c) 2003,2007,2008 The NetBSD Foundation, Inc.
|
||||
# All rights reserved.
|
||||
@ -258,6 +258,7 @@
|
||||
# nsmb* SMB requester
|
||||
# nvme* Non-Volatile Memory Host Controller Interface device driver
|
||||
# nvme*ns* Non-Volatile Memory namespace
|
||||
# nvmm NetBSD Virtual Machine Monitor
|
||||
# openfirm OpenFirmware accessor
|
||||
# pad* Pseudo-audio device driver
|
||||
# pci* PCI bus access devices
|
||||
@ -277,7 +278,7 @@
|
||||
# stic* PixelStamp interface chip
|
||||
# sysmon System Monitoring hardware
|
||||
# tap* virtual Ethernet device
|
||||
# tprof task profiler
|
||||
# tprof task profiler
|
||||
# tun* network tunnel driver
|
||||
# twa 3ware Apache control interface
|
||||
# twe 3ware Escalade control interface
|
||||
@ -2205,6 +2206,10 @@ nvme[0-9]*)
|
||||
mkdev nvme$unit c %nvme_chr% $(($unit * 65536))
|
||||
;;
|
||||
|
||||
nvmm)
|
||||
mkdev nvmm c %nvmm_chr% 0
|
||||
;;
|
||||
|
||||
autofs)
|
||||
mkdev autofs c %autofs_chr% 0 600
|
||||
;;
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: files,v 1.1215 2018/10/19 21:09:10 jakllsch Exp $
|
||||
# $NetBSD: files,v 1.1216 2018/11/07 07:43:07 maxv Exp $
|
||||
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
|
||||
|
||||
version 20171118
|
||||
@ -1548,6 +1548,11 @@ include "lib/libx86emu/files.x86emu"
|
||||
#
|
||||
include "dev/tprof/files.tprof"
|
||||
|
||||
#
|
||||
# NetBSD Virtual Machine Monitor.
|
||||
#
|
||||
include "dev/nvmm/files.nvmm"
|
||||
|
||||
#
|
||||
# alternate memory device
|
||||
#
|
||||
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: majors,v 1.79 2018/05/20 14:08:33 thorpej Exp $
|
||||
# $NetBSD: majors,v 1.80 2018/11/07 07:43:07 maxv Exp $
|
||||
#
|
||||
# Device majors for Machine-Independent drivers.
|
||||
#
|
||||
@ -78,3 +78,4 @@ device-major nvme char 341 nvme
|
||||
device-major qemufwcfg char 342 qemufwcfg
|
||||
device-major autofs char 343 autofs
|
||||
device-major gpiopps char 344 gpiopps
|
||||
device-major nvmm char 345 nvmm
|
||||
|
@ -1,10 +1,14 @@
|
||||
# $NetBSD: Makefile,v 1.39 2017/12/10 20:38:14 bouyer Exp $
|
||||
# $NetBSD: Makefile,v 1.40 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
SUBDIR= apm ata bluetooth dec dm dmover dtv filemon hdaudio hdmicec hid hpc \
|
||||
i2c i2o ic ieee1394 ir isa \
|
||||
microcode ofw pci pckbport pcmcia pud putter raidframe sbus scsipi \
|
||||
sun tc usb vme wscons
|
||||
|
||||
.if ${MACHINE_ARCH} == "x86_64"
|
||||
SUBDIR+= nvmm
|
||||
.endif
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
.if ${MKISCSI} != "no"
|
||||
|
13
sys/dev/nvmm/Makefile
Normal file
13
sys/dev/nvmm/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
# $NetBSD: Makefile,v 1.1 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
.if ${MACHINE_ARCH} == "x86_64"
|
||||
SUBDIR= x86
|
||||
.endif
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
INCSDIR= /usr/include/dev/nvmm
|
||||
|
||||
INCS= nvmm.h nvmm_ioctl.h
|
||||
|
||||
.include <bsd.kinc.mk>
|
11
sys/dev/nvmm/files.nvmm
Normal file
11
sys/dev/nvmm/files.nvmm
Normal file
@ -0,0 +1,11 @@
|
||||
# $NetBSD: files.nvmm,v 1.1 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
defpseudo nvmm
|
||||
|
||||
file dev/nvmm/nvmm.c nvmm
|
||||
|
||||
ifdef amd64
|
||||
file dev/nvmm/x86/nvmm_x86_svm.c nvmm
|
||||
file dev/nvmm/x86/nvmm_x86_svmfunc.S nvmm
|
||||
endif
|
||||
|
788
sys/dev/nvmm/nvmm.c
Normal file
788
sys/dev/nvmm/nvmm.c
Normal file
@ -0,0 +1,788 @@
|
||||
/* $NetBSD: nvmm.c,v 1.1 2018/11/07 07:43:08 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: nvmm.c,v 1.1 2018/11/07 07:43:08 maxv Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
|
||||
#include <sys/cpu.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <uvm/uvm.h>
|
||||
#include <uvm/uvm_page.h>
|
||||
|
||||
#include "ioconf.h"
|
||||
|
||||
#include <dev/nvmm/nvmm.h>
|
||||
#include <dev/nvmm/nvmm_internal.h>
|
||||
#include <dev/nvmm/nvmm_ioctl.h>
|
||||
|
||||
static struct nvmm_machine machines[NVMM_MAX_MACHINES];
|
||||
|
||||
static const struct nvmm_impl *nvmm_impl_list[] = {
|
||||
&nvmm_x86_svm /* x86 AMD SVM */
|
||||
};
|
||||
|
||||
static const struct nvmm_impl *nvmm_impl = NULL;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
nvmm_machine_alloc(struct nvmm_machine **ret)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NVMM_MAX_MACHINES; i++) {
|
||||
mach = &machines[i];
|
||||
|
||||
rw_enter(&mach->lock, RW_WRITER);
|
||||
if (mach->present) {
|
||||
rw_exit(&mach->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
mach->present = true;
|
||||
*ret = mach;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
static void
|
||||
nvmm_machine_free(struct nvmm_machine *mach)
|
||||
{
|
||||
KASSERT(rw_write_held(&mach->lock));
|
||||
KASSERT(mach->present);
|
||||
mach->present = false;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_machine_get(nvmm_machid_t machid, struct nvmm_machine **ret, bool writer)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
krw_t op = writer ? RW_WRITER : RW_READER;
|
||||
|
||||
if (machid >= NVMM_MAX_MACHINES) {
|
||||
return EINVAL;
|
||||
}
|
||||
mach = &machines[machid];
|
||||
|
||||
rw_enter(&mach->lock, op);
|
||||
if (!mach->present) {
|
||||
rw_exit(&mach->lock);
|
||||
return ENOENT;
|
||||
}
|
||||
if (mach->procid != curproc->p_pid) {
|
||||
rw_exit(&mach->lock);
|
||||
return EPERM;
|
||||
}
|
||||
*ret = mach;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvmm_machine_put(struct nvmm_machine *mach)
|
||||
{
|
||||
rw_exit(&mach->lock);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
nvmm_vcpu_alloc(struct nvmm_machine *mach, struct nvmm_cpu **ret)
|
||||
{
|
||||
struct nvmm_cpu *vcpu;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < NVMM_MAX_VCPUS; i++) {
|
||||
vcpu = &mach->cpus[i];
|
||||
|
||||
mutex_enter(&vcpu->lock);
|
||||
if (vcpu->present) {
|
||||
mutex_exit(&vcpu->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
vcpu->present = true;
|
||||
vcpu->cpuid = i;
|
||||
*ret = vcpu;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return ENOBUFS;
|
||||
}
|
||||
|
||||
static void
|
||||
nvmm_vcpu_free(struct nvmm_machine *mach, struct nvmm_cpu *vcpu)
|
||||
{
|
||||
KASSERT(mutex_owned(&vcpu->lock));
|
||||
vcpu->present = false;
|
||||
vcpu->hcpu_last = -1;
|
||||
}
|
||||
|
||||
int
|
||||
nvmm_vcpu_get(struct nvmm_machine *mach, nvmm_cpuid_t cpuid,
|
||||
struct nvmm_cpu **ret)
|
||||
{
|
||||
struct nvmm_cpu *vcpu;
|
||||
|
||||
if (cpuid >= NVMM_MAX_VCPUS) {
|
||||
return EINVAL;
|
||||
}
|
||||
vcpu = &mach->cpus[cpuid];
|
||||
|
||||
mutex_enter(&vcpu->lock);
|
||||
if (!vcpu->present) {
|
||||
mutex_exit(&vcpu->lock);
|
||||
return ENOENT;
|
||||
}
|
||||
*ret = vcpu;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
nvmm_vcpu_put(struct nvmm_cpu *vcpu)
|
||||
{
|
||||
mutex_exit(&vcpu->lock);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void
|
||||
nvmm_kill_machines(pid_t pid)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
size_t i, j;
|
||||
int error;
|
||||
|
||||
for (i = 0; i < NVMM_MAX_MACHINES; i++) {
|
||||
mach = &machines[i];
|
||||
|
||||
rw_enter(&mach->lock, RW_WRITER);
|
||||
if (!mach->present || mach->procid != pid) {
|
||||
rw_exit(&mach->lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Kill it. */
|
||||
for (j = 0; j < NVMM_MAX_VCPUS; j++) {
|
||||
error = nvmm_vcpu_get(mach, j, &vcpu);
|
||||
if (error)
|
||||
continue;
|
||||
(*nvmm_impl->vcpu_destroy)(mach, vcpu);
|
||||
nvmm_vcpu_free(mach, vcpu);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
}
|
||||
uvmspace_free(mach->vm);
|
||||
uao_detach(mach->uobj);
|
||||
nvmm_machine_free(mach);
|
||||
|
||||
rw_exit(&mach->lock);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
nvmm_capability(struct nvmm_ioc_capability *args)
|
||||
{
|
||||
args->cap.version = NVMM_CAPABILITY_VERSION;
|
||||
args->cap.state_size = nvmm_impl->state_size;
|
||||
args->cap.max_machines = NVMM_MAX_MACHINES;
|
||||
args->cap.max_vcpus = NVMM_MAX_VCPUS;
|
||||
args->cap.max_ram = NVMM_MAX_RAM;
|
||||
|
||||
(*nvmm_impl->capability)(&args->cap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_machine_create(struct nvmm_ioc_machine_create *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_alloc(&mach);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Curproc owns the machine. */
|
||||
mach->procid = curproc->p_pid;
|
||||
|
||||
/* Create the machine vmspace. */
|
||||
mach->gpa_begin = 0;
|
||||
mach->gpa_end = NVMM_MAX_RAM;
|
||||
mach->vm = uvmspace_alloc(0, mach->gpa_end - mach->gpa_begin, false);
|
||||
mach->uobj = uao_create(mach->gpa_end - mach->gpa_begin, 0);
|
||||
|
||||
/* Grab a reference for the machine. */
|
||||
uao_reference(mach->uobj);
|
||||
|
||||
(*nvmm_impl->machine_create)(mach);
|
||||
|
||||
args->machid = mach->machid;
|
||||
nvmm_machine_put(mach);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_machine_destroy(struct nvmm_ioc_machine_destroy *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
int error;
|
||||
size_t i;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, true);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
for (i = 0; i < NVMM_MAX_VCPUS; i++) {
|
||||
error = nvmm_vcpu_get(mach, i, &vcpu);
|
||||
if (error)
|
||||
continue;
|
||||
|
||||
(*nvmm_impl->vcpu_destroy)(mach, vcpu);
|
||||
nvmm_vcpu_free(mach, vcpu);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
}
|
||||
|
||||
(*nvmm_impl->machine_destroy)(mach);
|
||||
|
||||
/* Free the machine vmspace. */
|
||||
uvmspace_free(mach->vm);
|
||||
uao_detach(mach->uobj);
|
||||
|
||||
nvmm_machine_free(mach);
|
||||
nvmm_machine_put(mach);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_machine_configure(struct nvmm_ioc_machine_configure *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
size_t allocsz;
|
||||
void *data;
|
||||
int error;
|
||||
|
||||
if (__predict_false(args->op >= nvmm_impl->conf_max)) {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
allocsz = nvmm_impl->conf_sizes[args->op];
|
||||
data = kmem_alloc(allocsz, KM_SLEEP);
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, true);
|
||||
if (error) {
|
||||
kmem_free(data, allocsz);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = copyin(args->conf, data, allocsz);
|
||||
if (error) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
error = (*nvmm_impl->machine_configure)(mach, args->op, data);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
kmem_free(data, allocsz);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_vcpu_create(struct nvmm_ioc_vcpu_create *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = nvmm_vcpu_alloc(mach, &vcpu);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = (*nvmm_impl->vcpu_create)(mach, vcpu);
|
||||
if (error) {
|
||||
nvmm_vcpu_free(mach, vcpu);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
goto out;
|
||||
}
|
||||
|
||||
nvmm_vcpu_put(vcpu);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_vcpu_destroy(struct nvmm_ioc_vcpu_destroy *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
(*nvmm_impl->vcpu_destroy)(mach, vcpu);
|
||||
nvmm_vcpu_free(mach, vcpu);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_vcpu_setstate(struct nvmm_ioc_vcpu_setstate *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
void *data;
|
||||
int error;
|
||||
|
||||
data = kmem_alloc(nvmm_impl->state_size, KM_SLEEP);
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error) {
|
||||
kmem_free(data, nvmm_impl->state_size);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = copyin(args->state, data, nvmm_impl->state_size);
|
||||
if (error) {
|
||||
nvmm_vcpu_put(vcpu);
|
||||
goto out;
|
||||
}
|
||||
|
||||
(*nvmm_impl->vcpu_setstate)(vcpu, data, args->flags);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
kmem_free(data, nvmm_impl->state_size);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_vcpu_getstate(struct nvmm_ioc_vcpu_getstate *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
void *data;
|
||||
int error;
|
||||
|
||||
data = kmem_alloc(nvmm_impl->state_size, KM_SLEEP);
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error) {
|
||||
kmem_free(data, nvmm_impl->state_size);
|
||||
return error;
|
||||
}
|
||||
|
||||
error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
(*nvmm_impl->vcpu_getstate)(vcpu, data, args->flags);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
error = copyout(data, args->state, nvmm_impl->state_size);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
kmem_free(data, nvmm_impl->state_size);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_vcpu_inject(struct nvmm_ioc_vcpu_inject *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
error = (*nvmm_impl->vcpu_inject)(mach, vcpu, &args->event);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_vcpu_run(struct nvmm_ioc_vcpu_run *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
struct nvmm_cpu *vcpu;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
error = nvmm_vcpu_get(mach, args->cpuid, &vcpu);
|
||||
if (error)
|
||||
goto out;
|
||||
|
||||
(*nvmm_impl->vcpu_run)(mach, vcpu, &args->exit);
|
||||
nvmm_vcpu_put(vcpu);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
nvmm_gpa_map(struct nvmm_ioc_gpa_map *args)
|
||||
{
|
||||
struct proc *p = curproc;
|
||||
struct nvmm_machine *mach;
|
||||
struct vmspace *vmspace;
|
||||
gpaddr_t gpa;
|
||||
vaddr_t uva;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
vmspace = p->p_vmspace;
|
||||
|
||||
if ((args->gpa % PAGE_SIZE) != 0 || (args->size % PAGE_SIZE) != 0 ||
|
||||
(args->hva % PAGE_SIZE) != 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->hva == 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->gpa < mach->gpa_begin || args->gpa >= mach->gpa_end) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->gpa + args->size <= args->gpa) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->gpa + args->size >= mach->gpa_end) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
gpa = args->gpa;
|
||||
|
||||
/* Take a reference for the kernel. */
|
||||
uao_reference(mach->uobj);
|
||||
|
||||
/* Map the uobj into the machine address space, as pageable. */
|
||||
error = uvm_map(&mach->vm->vm_map, &gpa, args->size, mach->uobj,
|
||||
args->gpa, 0, UVM_MAPFLAG(UVM_PROT_RWX, UVM_PROT_RWX,
|
||||
UVM_INH_NONE, UVM_ADV_NORMAL, UVM_FLAG_FIXED));
|
||||
if (error) {
|
||||
uao_detach(mach->uobj);
|
||||
goto out;
|
||||
}
|
||||
if (gpa != args->gpa) {
|
||||
uao_detach(mach->uobj);
|
||||
printf("[!] uvm_map problem\n");
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
uva = (vaddr_t)args->hva;
|
||||
|
||||
/* Take a reference for the user. */
|
||||
uao_reference(mach->uobj);
|
||||
|
||||
/* Map the uobj into the user address space, as pageable. */
|
||||
error = uvm_map(&vmspace->vm_map, &uva, args->size, mach->uobj,
|
||||
args->gpa, 0, UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW,
|
||||
UVM_INH_SHARE, UVM_ADV_NORMAL, UVM_FLAG_FIXED|UVM_FLAG_UNMAP));
|
||||
if (error) {
|
||||
uao_detach(mach->uobj);
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
return error;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_gpa_unmap(struct nvmm_ioc_gpa_unmap *args)
|
||||
{
|
||||
struct nvmm_machine *mach;
|
||||
gpaddr_t gpa;
|
||||
int error;
|
||||
|
||||
error = nvmm_machine_get(args->machid, &mach, false);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if ((args->gpa % PAGE_SIZE) != 0 || (args->size % PAGE_SIZE) != 0) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->gpa < mach->gpa_begin || args->gpa >= mach->gpa_end) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->gpa + args->size <= args->gpa) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
if (args->gpa + args->size >= mach->gpa_end) {
|
||||
error = EINVAL;
|
||||
goto out;
|
||||
}
|
||||
gpa = args->gpa;
|
||||
|
||||
/* Unmap the memory from the machine. */
|
||||
uvm_unmap(&mach->vm->vm_map, gpa, gpa + args->size);
|
||||
|
||||
out:
|
||||
nvmm_machine_put(mach);
|
||||
return error;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
nvmm_init(void)
|
||||
{
|
||||
size_t i, n;
|
||||
|
||||
for (i = 0; i < __arraycount(nvmm_impl_list); i++) {
|
||||
if (!(*nvmm_impl_list[i]->ident)()) {
|
||||
continue;
|
||||
}
|
||||
nvmm_impl = nvmm_impl_list[i];
|
||||
break;
|
||||
}
|
||||
if (nvmm_impl == NULL) {
|
||||
printf("[!] No implementation found\n");
|
||||
return ENOTSUP;
|
||||
}
|
||||
|
||||
for (i = 0; i < NVMM_MAX_MACHINES; i++) {
|
||||
machines[i].machid = i;
|
||||
rw_init(&machines[i].lock);
|
||||
for (n = 0; n < NVMM_MAX_VCPUS; n++) {
|
||||
mutex_init(&machines[i].cpus[n].lock, MUTEX_DEFAULT,
|
||||
IPL_NONE);
|
||||
machines[i].cpus[n].hcpu_last = -1;
|
||||
}
|
||||
}
|
||||
|
||||
(*nvmm_impl->init)();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
nvmm_fini(void)
|
||||
{
|
||||
size_t i, n;
|
||||
|
||||
for (i = 0; i < NVMM_MAX_MACHINES; i++) {
|
||||
rw_destroy(&machines[i].lock);
|
||||
for (n = 0; n < NVMM_MAX_VCPUS; n++) {
|
||||
mutex_destroy(&machines[i].cpus[n].lock);
|
||||
}
|
||||
/* TODO need to free stuff, etc */
|
||||
}
|
||||
|
||||
(*nvmm_impl->fini)();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
nvmm_open(dev_t dev, int flags, int type, struct lwp *l)
|
||||
{
|
||||
if (minor(dev) != 0) {
|
||||
return EXDEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_close(dev_t dev, int flags, int type, struct lwp *l)
|
||||
{
|
||||
KASSERT(minor(dev) == 0);
|
||||
|
||||
nvmm_kill_machines(l->l_proc->p_pid);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
nvmm_ioctl(dev_t dev, u_long cmd, void *data, int flags, struct lwp *l)
|
||||
{
|
||||
KASSERT(minor(dev) == 0);
|
||||
|
||||
switch (cmd) {
|
||||
case NVMM_IOC_CAPABILITY:
|
||||
return nvmm_capability(data);
|
||||
case NVMM_IOC_MACHINE_CREATE:
|
||||
return nvmm_machine_create(data);
|
||||
case NVMM_IOC_MACHINE_DESTROY:
|
||||
return nvmm_machine_destroy(data);
|
||||
case NVMM_IOC_MACHINE_CONFIGURE:
|
||||
return nvmm_machine_configure(data);
|
||||
case NVMM_IOC_VCPU_CREATE:
|
||||
return nvmm_vcpu_create(data);
|
||||
case NVMM_IOC_VCPU_DESTROY:
|
||||
return nvmm_vcpu_destroy(data);
|
||||
case NVMM_IOC_VCPU_SETSTATE:
|
||||
return nvmm_vcpu_setstate(data);
|
||||
case NVMM_IOC_VCPU_GETSTATE:
|
||||
return nvmm_vcpu_getstate(data);
|
||||
case NVMM_IOC_VCPU_INJECT:
|
||||
return nvmm_vcpu_inject(data);
|
||||
case NVMM_IOC_VCPU_RUN:
|
||||
return nvmm_vcpu_run(data);
|
||||
case NVMM_IOC_GPA_MAP:
|
||||
return nvmm_gpa_map(data);
|
||||
case NVMM_IOC_GPA_UNMAP:
|
||||
return nvmm_gpa_unmap(data);
|
||||
default:
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
const struct cdevsw nvmm_cdevsw = {
|
||||
.d_open = nvmm_open,
|
||||
.d_close = nvmm_close,
|
||||
.d_read = noread,
|
||||
.d_write = nowrite,
|
||||
.d_ioctl = nvmm_ioctl,
|
||||
.d_stop = nostop,
|
||||
.d_tty = notty,
|
||||
.d_poll = nopoll,
|
||||
.d_mmap = nommap,
|
||||
.d_kqfilter = nokqfilter,
|
||||
.d_discard = nodiscard,
|
||||
.d_flag = D_OTHER | D_MPSAFE
|
||||
};
|
||||
|
||||
void
|
||||
nvmmattach(int nunits)
|
||||
{
|
||||
/* nothing */
|
||||
}
|
||||
|
||||
MODULE(MODULE_CLASS_DRIVER, nvmm, NULL);
|
||||
|
||||
static int
|
||||
nvmm_modcmd(modcmd_t cmd, void *arg)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (cmd) {
|
||||
case MODULE_CMD_INIT:
|
||||
error = nvmm_init();
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
#if defined(_MODULE)
|
||||
{
|
||||
devmajor_t bmajor = NODEVMAJOR;
|
||||
devmajor_t cmajor = 345;
|
||||
|
||||
/* mknod /dev/nvmm c 345 0 */
|
||||
error = devsw_attach("nvmm", NULL, &bmajor,
|
||||
&nvmm_cdevsw, &cmajor);
|
||||
if (error) {
|
||||
nvmm_fini();
|
||||
return error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
case MODULE_CMD_FINI:
|
||||
#if defined(_MODULE)
|
||||
{
|
||||
error = devsw_detach(NULL, &nvmm_cdevsw);
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
nvmm_fini();
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return ENOTTY;
|
||||
}
|
||||
}
|
155
sys/dev/nvmm/nvmm.h
Normal file
155
sys/dev/nvmm/nvmm.h
Normal file
@ -0,0 +1,155 @@
|
||||
/* $NetBSD: nvmm.h,v 1.1 2018/11/07 07:43:08 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NVMM_H_
|
||||
#define _NVMM_H_
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifndef _KERNEL
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
typedef uint64_t gpaddr_t;
|
||||
typedef uint64_t gvaddr_t;
|
||||
|
||||
typedef uint32_t nvmm_machid_t;
|
||||
typedef uint32_t nvmm_cpuid_t;
|
||||
|
||||
enum nvmm_exit_reason {
|
||||
NVMM_EXIT_NONE = 0x0000000000000000,
|
||||
|
||||
/* General. */
|
||||
NVMM_EXIT_MEMORY = 0x0000000000000001,
|
||||
NVMM_EXIT_IO = 0x0000000000000002,
|
||||
NVMM_EXIT_MSR = 0x0000000000000003,
|
||||
NVMM_EXIT_INT_READY = 0x0000000000000004,
|
||||
NVMM_EXIT_NMI_READY = 0x0000000000000005,
|
||||
NVMM_EXIT_SHUTDOWN = 0x0000000000000006,
|
||||
|
||||
/* Instructions (x86). */
|
||||
NVMM_EXIT_HLT = 0x0000000000001000,
|
||||
NVMM_EXIT_MONITOR = 0x0000000000001001,
|
||||
NVMM_EXIT_MWAIT = 0x0000000000001002,
|
||||
NVMM_EXIT_MWAIT_COND = 0x0000000000001003,
|
||||
|
||||
NVMM_EXIT_INVALID = 0xFFFFFFFFFFFFFFFF
|
||||
};
|
||||
|
||||
enum nvmm_exit_memory_perm {
|
||||
NVMM_EXIT_MEMORY_READ,
|
||||
NVMM_EXIT_MEMORY_WRITE,
|
||||
NVMM_EXIT_MEMORY_EXEC
|
||||
};
|
||||
|
||||
struct nvmm_exit_memory {
|
||||
enum nvmm_exit_memory_perm perm;
|
||||
gpaddr_t gpa;
|
||||
uint8_t inst_len;
|
||||
uint8_t inst_bytes[15];
|
||||
uint64_t npc;
|
||||
};
|
||||
|
||||
enum nvmm_exit_io_type {
|
||||
NVMM_EXIT_IO_IN,
|
||||
NVMM_EXIT_IO_OUT
|
||||
};
|
||||
|
||||
struct nvmm_exit_io {
|
||||
enum nvmm_exit_io_type type;
|
||||
uint16_t port;
|
||||
int seg;
|
||||
uint8_t address_size;
|
||||
uint8_t operand_size;
|
||||
bool rep;
|
||||
bool str;
|
||||
uint64_t npc;
|
||||
};
|
||||
|
||||
enum nvmm_exit_msr_type {
|
||||
NVMM_EXIT_MSR_RDMSR,
|
||||
NVMM_EXIT_MSR_WRMSR
|
||||
};
|
||||
|
||||
struct nvmm_exit_msr {
|
||||
enum nvmm_exit_msr_type type;
|
||||
uint64_t msr;
|
||||
uint64_t val;
|
||||
uint64_t npc;
|
||||
};
|
||||
|
||||
struct nvmm_exit {
|
||||
enum nvmm_exit_reason reason;
|
||||
union {
|
||||
struct nvmm_exit_memory mem;
|
||||
struct nvmm_exit_io io;
|
||||
struct nvmm_exit_msr msr;
|
||||
} u;
|
||||
uint64_t exitstate[8];
|
||||
};
|
||||
|
||||
enum nvmm_event_type {
|
||||
NVMM_EVENT_INTERRUPT_HW,
|
||||
NVMM_EVENT_INTERRUPT_SW,
|
||||
NVMM_EVENT_EXCEPTION
|
||||
};
|
||||
|
||||
struct nvmm_event {
|
||||
enum nvmm_event_type type;
|
||||
uint64_t vector;
|
||||
union {
|
||||
/* NVMM_EVENT_INTERRUPT_HW */
|
||||
uint8_t prio;
|
||||
|
||||
/* NVMM_EVENT_EXCEPTION */
|
||||
uint64_t error;
|
||||
} u;
|
||||
};
|
||||
|
||||
#define NVMM_CAPABILITY_VERSION 1
|
||||
|
||||
struct nvmm_capability {
|
||||
uint64_t version;
|
||||
uint64_t state_size;
|
||||
uint64_t max_machines;
|
||||
uint64_t max_vcpus;
|
||||
uint64_t max_ram;
|
||||
union {
|
||||
struct {
|
||||
uint64_t xcr0_mask;
|
||||
uint64_t mxcsr_mask;
|
||||
uint64_t conf_cpuid_maxops;
|
||||
} x86;
|
||||
uint64_t rsvd[8];
|
||||
} u;
|
||||
};
|
||||
|
||||
#endif
|
100
sys/dev/nvmm/nvmm_internal.h
Normal file
100
sys/dev/nvmm/nvmm_internal.h
Normal file
@ -0,0 +1,100 @@
|
||||
/* $NetBSD: nvmm_internal.h,v 1.1 2018/11/07 07:43:08 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NVMM_INTERNAL_H_
|
||||
#define _NVMM_INTERNAL_H_
|
||||
|
||||
#define NVMM_MAX_MACHINES 128
|
||||
#define NVMM_MAX_VCPUS 256
|
||||
#define NVMM_MAX_RAM (4UL * (1 << 30))
|
||||
|
||||
struct nvmm_cpu {
|
||||
/* Shared. */
|
||||
bool present;
|
||||
nvmm_cpuid_t cpuid;
|
||||
kmutex_t lock;
|
||||
|
||||
/* Last host CPU on which the VCPU ran. */
|
||||
int hcpu_last;
|
||||
|
||||
/* Implementation-specific. */
|
||||
void *cpudata;
|
||||
};
|
||||
|
||||
struct nvmm_machine {
|
||||
bool present;
|
||||
nvmm_machid_t machid;
|
||||
pid_t procid;
|
||||
krwlock_t lock;
|
||||
|
||||
/* Kernel */
|
||||
struct vmspace *vm;
|
||||
struct uvm_object *uobj;
|
||||
gpaddr_t gpa_begin;
|
||||
gpaddr_t gpa_end;
|
||||
|
||||
/* CPU */
|
||||
struct nvmm_cpu cpus[NVMM_MAX_VCPUS];
|
||||
|
||||
/* Implementation-specific */
|
||||
void *machdata;
|
||||
};
|
||||
|
||||
struct nvmm_impl {
|
||||
bool (*ident)(void);
|
||||
void (*init)(void);
|
||||
void (*fini)(void);
|
||||
void (*capability)(struct nvmm_capability *);
|
||||
|
||||
size_t conf_max;
|
||||
const size_t *conf_sizes;
|
||||
size_t state_size;
|
||||
|
||||
void (*machine_create)(struct nvmm_machine *);
|
||||
void (*machine_destroy)(struct nvmm_machine *);
|
||||
int (*machine_configure)(struct nvmm_machine *, uint64_t, void *);
|
||||
|
||||
int (*vcpu_create)(struct nvmm_machine *, struct nvmm_cpu *);
|
||||
void (*vcpu_destroy)(struct nvmm_machine *, struct nvmm_cpu *);
|
||||
void (*vcpu_setstate)(struct nvmm_cpu *, void *, uint64_t);
|
||||
void (*vcpu_getstate)(struct nvmm_cpu *, void *, uint64_t);
|
||||
int (*vcpu_inject)(struct nvmm_machine *, struct nvmm_cpu *,
|
||||
struct nvmm_event *);
|
||||
int (*vcpu_run)(struct nvmm_machine *, struct nvmm_cpu *,
|
||||
struct nvmm_exit *);
|
||||
};
|
||||
|
||||
int nvmm_vcpu_get(struct nvmm_machine *, nvmm_cpuid_t, struct nvmm_cpu **);
|
||||
void nvmm_vcpu_put(struct nvmm_cpu *);
|
||||
|
||||
extern const struct nvmm_impl nvmm_x86_svm;
|
||||
|
||||
#endif /* _NVMM_INTERNAL_H_ */
|
120
sys/dev/nvmm/nvmm_ioctl.h
Normal file
120
sys/dev/nvmm/nvmm_ioctl.h
Normal file
@ -0,0 +1,120 @@
|
||||
/* $NetBSD: nvmm_ioctl.h,v 1.1 2018/11/07 07:43:08 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NVMM_IOCTL_H_
|
||||
#define _NVMM_IOCTL_H_
|
||||
|
||||
#include <dev/nvmm/nvmm.h>
|
||||
|
||||
struct nvmm_ioc_capability {
|
||||
struct nvmm_capability cap;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_machine_create {
|
||||
nvmm_machid_t machid;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_machine_destroy {
|
||||
nvmm_machid_t machid;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_machine_configure {
|
||||
nvmm_machid_t machid;
|
||||
uint64_t op;
|
||||
void *conf;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_vcpu_create {
|
||||
nvmm_machid_t machid;
|
||||
nvmm_cpuid_t cpuid;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_vcpu_destroy {
|
||||
nvmm_machid_t machid;
|
||||
nvmm_cpuid_t cpuid;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_vcpu_setstate {
|
||||
nvmm_machid_t machid;
|
||||
nvmm_cpuid_t cpuid;
|
||||
uint64_t flags;
|
||||
void *state;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_vcpu_getstate {
|
||||
nvmm_machid_t machid;
|
||||
nvmm_cpuid_t cpuid;
|
||||
uint64_t flags;
|
||||
void *state;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_vcpu_inject {
|
||||
nvmm_machid_t machid;
|
||||
nvmm_cpuid_t cpuid;
|
||||
struct nvmm_event event;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_vcpu_run {
|
||||
/* input */
|
||||
nvmm_machid_t machid;
|
||||
nvmm_cpuid_t cpuid;
|
||||
/* output */
|
||||
struct nvmm_exit exit;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_gpa_map {
|
||||
nvmm_machid_t machid;
|
||||
uintptr_t hva;
|
||||
gpaddr_t gpa;
|
||||
size_t size;
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct nvmm_ioc_gpa_unmap {
|
||||
nvmm_machid_t machid;
|
||||
gpaddr_t gpa;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
#define NVMM_IOC_CAPABILITY _IOR ('N', 0, struct nvmm_ioc_capability)
|
||||
#define NVMM_IOC_MACHINE_CREATE _IOWR('N', 1, struct nvmm_ioc_machine_create)
|
||||
#define NVMM_IOC_MACHINE_DESTROY _IOW ('N', 2, struct nvmm_ioc_machine_destroy)
|
||||
#define NVMM_IOC_MACHINE_CONFIGURE _IOW ('N', 3, struct nvmm_ioc_machine_configure)
|
||||
#define NVMM_IOC_VCPU_CREATE _IOW ('N', 4, struct nvmm_ioc_vcpu_create)
|
||||
#define NVMM_IOC_VCPU_DESTROY _IOW ('N', 5, struct nvmm_ioc_vcpu_destroy)
|
||||
#define NVMM_IOC_VCPU_SETSTATE _IOW ('N', 6, struct nvmm_ioc_vcpu_setstate)
|
||||
#define NVMM_IOC_VCPU_GETSTATE _IOW ('N', 7, struct nvmm_ioc_vcpu_getstate)
|
||||
#define NVMM_IOC_VCPU_INJECT _IOWR('N', 8, struct nvmm_ioc_vcpu_inject)
|
||||
#define NVMM_IOC_VCPU_RUN _IOWR('N', 9, struct nvmm_ioc_vcpu_run)
|
||||
#define NVMM_IOC_GPA_MAP _IOW ('N', 10, struct nvmm_ioc_gpa_map)
|
||||
#define NVMM_IOC_GPA_UNMAP _IOW ('N', 11, struct nvmm_ioc_gpa_unmap)
|
||||
|
||||
#endif /* _NVMM_IOCTL_H_ */
|
7
sys/dev/nvmm/x86/Makefile
Normal file
7
sys/dev/nvmm/x86/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# $NetBSD: Makefile,v 1.1 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
INCSDIR= /usr/include/dev/nvmm/x86
|
||||
|
||||
INCS= nvmm_x86.h
|
||||
|
||||
.include <bsd.kinc.mk>
|
172
sys/dev/nvmm/x86/nvmm_x86.h
Normal file
172
sys/dev/nvmm/x86/nvmm_x86.h
Normal file
@ -0,0 +1,172 @@
|
||||
/* $NetBSD: nvmm_x86.h,v 1.1 2018/11/07 07:43:08 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _NVMM_X86_H_
|
||||
#define _NVMM_X86_H_
|
||||
|
||||
/* Segments. */
|
||||
#define NVMM_X64_SEG_CS 0
|
||||
#define NVMM_X64_SEG_DS 1
|
||||
#define NVMM_X64_SEG_ES 2
|
||||
#define NVMM_X64_SEG_FS 3
|
||||
#define NVMM_X64_SEG_GS 4
|
||||
#define NVMM_X64_SEG_SS 5
|
||||
#define NVMM_X64_SEG_GDT 6
|
||||
#define NVMM_X64_SEG_IDT 7
|
||||
#define NVMM_X64_SEG_LDT 8
|
||||
#define NVMM_X64_SEG_TR 9
|
||||
#define NVMM_X64_NSEG 10
|
||||
|
||||
/* General Purpose Registers. */
|
||||
#define NVMM_X64_GPR_RAX 0
|
||||
#define NVMM_X64_GPR_RBX 1
|
||||
#define NVMM_X64_GPR_RCX 2
|
||||
#define NVMM_X64_GPR_RDX 3
|
||||
#define NVMM_X64_GPR_R8 4
|
||||
#define NVMM_X64_GPR_R9 5
|
||||
#define NVMM_X64_GPR_R10 6
|
||||
#define NVMM_X64_GPR_R11 7
|
||||
#define NVMM_X64_GPR_R12 8
|
||||
#define NVMM_X64_GPR_R13 9
|
||||
#define NVMM_X64_GPR_R14 10
|
||||
#define NVMM_X64_GPR_R15 11
|
||||
#define NVMM_X64_GPR_RDI 12
|
||||
#define NVMM_X64_GPR_RSI 13
|
||||
#define NVMM_X64_GPR_RBP 14
|
||||
#define NVMM_X64_GPR_RSP 15
|
||||
#define NVMM_X64_GPR_RIP 16
|
||||
#define NVMM_X64_GPR_RFLAGS 17
|
||||
#define NVMM_X64_NGPR 18
|
||||
|
||||
/* Control Registers. */
|
||||
#define NVMM_X64_CR_CR0 0
|
||||
#define NVMM_X64_CR_CR2 1
|
||||
#define NVMM_X64_CR_CR3 2
|
||||
#define NVMM_X64_CR_CR4 3
|
||||
#define NVMM_X64_CR_CR8 4
|
||||
#define NVMM_X64_CR_XCR0 5
|
||||
#define NVMM_X64_NCR 6
|
||||
|
||||
/* Debug Registers. */
|
||||
#define NVMM_X64_DR_DR0 0
|
||||
#define NVMM_X64_DR_DR1 1
|
||||
#define NVMM_X64_DR_DR2 2
|
||||
#define NVMM_X64_DR_DR3 3
|
||||
#define NVMM_X64_DR_DR6 4
|
||||
#define NVMM_X64_DR_DR7 5
|
||||
#define NVMM_X64_NDR 6
|
||||
|
||||
/* MSRs. */
|
||||
#define NVMM_X64_MSR_EFER 0
|
||||
#define NVMM_X64_MSR_STAR 1
|
||||
#define NVMM_X64_MSR_LSTAR 2
|
||||
#define NVMM_X64_MSR_CSTAR 3
|
||||
#define NVMM_X64_MSR_SFMASK 4
|
||||
#define NVMM_X64_MSR_KERNELGSBASE 5
|
||||
#define NVMM_X64_MSR_SYSENTER_CS 6
|
||||
#define NVMM_X64_MSR_SYSENTER_ESP 7
|
||||
#define NVMM_X64_MSR_SYSENTER_EIP 8
|
||||
#define NVMM_X64_MSR_PAT 9
|
||||
#define NVMM_X64_NMSR 10
|
||||
|
||||
/* Misc. */
|
||||
#define NVMM_X64_MISC_CPL 0
|
||||
#define NVMM_X64_NMISC 1
|
||||
|
||||
#ifndef ASM_NVMM
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <x86/cpu_extended_state.h>
|
||||
|
||||
struct nvmm_x64_state_seg {
|
||||
uint64_t selector;
|
||||
struct { /* hidden */
|
||||
uint64_t type:5;
|
||||
uint64_t dpl:2;
|
||||
uint64_t p:1;
|
||||
uint64_t avl:1;
|
||||
uint64_t lng:1;
|
||||
uint64_t def32:1;
|
||||
uint64_t gran:1;
|
||||
uint64_t rsvd:52;
|
||||
} attrib;
|
||||
uint64_t limit; /* hidden */
|
||||
uint64_t base; /* hidden */
|
||||
};
|
||||
|
||||
/* VM exit state indexes. */
|
||||
#define NVMM_X64_EXITSTATE_CR8 0
|
||||
|
||||
/* Flags. */
|
||||
#define NVMM_X64_STATE_SEGS 0x01
|
||||
#define NVMM_X64_STATE_GPRS 0x02
|
||||
#define NVMM_X64_STATE_CRS 0x04
|
||||
#define NVMM_X64_STATE_DRS 0x08
|
||||
#define NVMM_X64_STATE_MSRS 0x10
|
||||
#define NVMM_X64_STATE_MISC 0x20
|
||||
#define NVMM_X64_STATE_FPU 0x40
|
||||
#define NVMM_X64_STATE_ALL \
|
||||
(NVMM_X64_STATE_SEGS | NVMM_X64_STATE_GPRS | NVMM_X64_STATE_CRS | \
|
||||
NVMM_X64_STATE_DRS | NVMM_X64_STATE_MSRS | NVMM_X64_STATE_MISC | \
|
||||
NVMM_X64_STATE_FPU)
|
||||
|
||||
struct nvmm_x64_state {
|
||||
struct nvmm_x64_state_seg segs[NVMM_X64_NSEG];
|
||||
uint64_t gprs[NVMM_X64_NGPR];
|
||||
uint64_t crs[NVMM_X64_NCR];
|
||||
uint64_t drs[NVMM_X64_NDR];
|
||||
uint64_t msrs[NVMM_X64_NMSR];
|
||||
uint64_t misc[NVMM_X64_NMISC];
|
||||
struct fxsave fpu;
|
||||
};
|
||||
|
||||
#define NVMM_X86_CONF_CPUID 0
|
||||
#define NVMM_X86_NCONF 1
|
||||
|
||||
struct nvmm_x86_conf_cpuid {
|
||||
uint32_t leaf;
|
||||
struct {
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
} set;
|
||||
struct {
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
} del;
|
||||
};
|
||||
|
||||
#endif /* ASM_NVMM */
|
||||
|
||||
#endif /* _NVMM_X86_H_ */
|
2088
sys/dev/nvmm/x86/nvmm_x86_svm.c
Normal file
2088
sys/dev/nvmm/x86/nvmm_x86_svm.c
Normal file
File diff suppressed because it is too large
Load Diff
218
sys/dev/nvmm/x86/nvmm_x86_svmfunc.S
Normal file
218
sys/dev/nvmm/x86/nvmm_x86_svmfunc.S
Normal file
@ -0,0 +1,218 @@
|
||||
/* $NetBSD: nvmm_x86_svmfunc.S,v 1.1 2018/11/07 07:43:08 maxv Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2018 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Maxime Villard.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Override user-land alignment before including asm.h */
|
||||
#define ALIGN_DATA .align 8
|
||||
#define ALIGN_TEXT .align 16,0x90
|
||||
#define _ALIGN_TEXT ALIGN_TEXT
|
||||
|
||||
#define _LOCORE
|
||||
#include "assym.h"
|
||||
#include <machine/asm.h>
|
||||
#include <machine/segments.h>
|
||||
#include <x86/specialreg.h>
|
||||
|
||||
#define ASM_NVMM
|
||||
#include <dev/nvmm/x86/nvmm_x86.h>
|
||||
|
||||
.text
|
||||
|
||||
#define HOST_SAVE_GPRS \
|
||||
pushq %rbx ;\
|
||||
pushq %rbp ;\
|
||||
pushq %r12 ;\
|
||||
pushq %r13 ;\
|
||||
pushq %r14 ;\
|
||||
pushq %r15
|
||||
|
||||
#define HOST_RESTORE_GPRS \
|
||||
popq %r15 ;\
|
||||
popq %r14 ;\
|
||||
popq %r13 ;\
|
||||
popq %r12 ;\
|
||||
popq %rbp ;\
|
||||
popq %rbx
|
||||
|
||||
#define HOST_SAVE_MSR(msr) \
|
||||
movq $msr,%rcx ;\
|
||||
rdmsr ;\
|
||||
pushq %rdx ;\
|
||||
pushq %rax
|
||||
|
||||
#define HOST_RESTORE_MSR(msr) \
|
||||
popq %rax ;\
|
||||
popq %rdx ;\
|
||||
movq $msr,%rcx ;\
|
||||
wrmsr
|
||||
|
||||
#define HOST_SAVE_SEGREG(sreg) \
|
||||
movw sreg,%ax ;\
|
||||
pushw %ax
|
||||
|
||||
#define HOST_RESTORE_SEGREG(sreg)\
|
||||
popw %ax ;\
|
||||
movw %ax,sreg
|
||||
|
||||
#define HOST_SAVE_TR \
|
||||
strw %ax ;\
|
||||
pushw %ax
|
||||
|
||||
#define HOST_RESTORE_TR \
|
||||
popw %ax ;\
|
||||
movzwq %ax,%rdx ;\
|
||||
movq CPUVAR(GDT),%rax ;\
|
||||
andq $~0x0200,4(%rax,%rdx, 1) ;\
|
||||
ltrw %dx
|
||||
|
||||
#define HOST_SAVE_LDT \
|
||||
sldtw %ax ;\
|
||||
pushw %ax
|
||||
|
||||
#define HOST_RESTORE_LDT \
|
||||
popw %ax ;\
|
||||
lldtw %ax
|
||||
|
||||
/*
|
||||
* All GPRs except RAX and RSP, which are taken care of in VMCB.
|
||||
*/
|
||||
|
||||
#define GUEST_SAVE_GPRS(reg) \
|
||||
movq %rbx,(NVMM_X64_GPR_RBX * 8)(reg) ;\
|
||||
movq %rcx,(NVMM_X64_GPR_RCX * 8)(reg) ;\
|
||||
movq %rdx,(NVMM_X64_GPR_RDX * 8)(reg) ;\
|
||||
movq %r8,(NVMM_X64_GPR_R8 * 8)(reg) ;\
|
||||
movq %r9,(NVMM_X64_GPR_R9 * 8)(reg) ;\
|
||||
movq %r10,(NVMM_X64_GPR_R10 * 8)(reg) ;\
|
||||
movq %r11,(NVMM_X64_GPR_R11 * 8)(reg) ;\
|
||||
movq %r12,(NVMM_X64_GPR_R12 * 8)(reg) ;\
|
||||
movq %r13,(NVMM_X64_GPR_R13 * 8)(reg) ;\
|
||||
movq %r14,(NVMM_X64_GPR_R14 * 8)(reg) ;\
|
||||
movq %r15,(NVMM_X64_GPR_R15 * 8)(reg) ;\
|
||||
movq %rbp,(NVMM_X64_GPR_RBP * 8)(reg) ;\
|
||||
movq %rdi,(NVMM_X64_GPR_RDI * 8)(reg) ;\
|
||||
movq %rsi,(NVMM_X64_GPR_RSI * 8)(reg)
|
||||
|
||||
#define GUEST_RESTORE_GPRS(reg) \
|
||||
movq (NVMM_X64_GPR_RBX * 8)(reg),%rbx ;\
|
||||
movq (NVMM_X64_GPR_RCX * 8)(reg),%rcx ;\
|
||||
movq (NVMM_X64_GPR_RDX * 8)(reg),%rdx ;\
|
||||
movq (NVMM_X64_GPR_R8 * 8)(reg),%r8 ;\
|
||||
movq (NVMM_X64_GPR_R9 * 8)(reg),%r9 ;\
|
||||
movq (NVMM_X64_GPR_R10 * 8)(reg),%r10 ;\
|
||||
movq (NVMM_X64_GPR_R11 * 8)(reg),%r11 ;\
|
||||
movq (NVMM_X64_GPR_R12 * 8)(reg),%r12 ;\
|
||||
movq (NVMM_X64_GPR_R13 * 8)(reg),%r13 ;\
|
||||
movq (NVMM_X64_GPR_R14 * 8)(reg),%r14 ;\
|
||||
movq (NVMM_X64_GPR_R15 * 8)(reg),%r15 ;\
|
||||
movq (NVMM_X64_GPR_RBP * 8)(reg),%rbp ;\
|
||||
movq (NVMM_X64_GPR_RDI * 8)(reg),%rdi ;\
|
||||
movq (NVMM_X64_GPR_RSI * 8)(reg),%rsi
|
||||
|
||||
/*
|
||||
* %rdi = PA of VMCB
|
||||
* %rsi = VA of guest GPR state
|
||||
*/
|
||||
ENTRY(svm_vmrun)
|
||||
/* Save the Host GPRs. */
|
||||
HOST_SAVE_GPRS
|
||||
|
||||
/* Disable Host interrupts. */
|
||||
clgi
|
||||
|
||||
/* Save the Host TR. */
|
||||
HOST_SAVE_TR
|
||||
|
||||
/* Save the variable Host MSRs. */
|
||||
HOST_SAVE_MSR(MSR_KERNELGSBASE)
|
||||
HOST_SAVE_MSR(MSR_GSBASE)
|
||||
HOST_SAVE_MSR(MSR_FSBASE)
|
||||
|
||||
/* Reset the Host Segregs. */
|
||||
movq $GSEL(GUDATA_SEL, SEL_UPL),%rax
|
||||
movw %ax,%ds
|
||||
movw %ax,%es
|
||||
xorq %rax,%rax
|
||||
movw %ax,%fs
|
||||
movw %ax,%gs
|
||||
|
||||
/* Save some Host Segregs. */
|
||||
HOST_SAVE_SEGREG(%fs)
|
||||
HOST_SAVE_SEGREG(%gs)
|
||||
|
||||
/* Save the Host LDT. */
|
||||
HOST_SAVE_LDT
|
||||
|
||||
/* Prepare RAX. */
|
||||
pushq %rsi
|
||||
pushq %rdi
|
||||
|
||||
/* Restore the Guest GPRs. */
|
||||
movq %rsi,%rax
|
||||
GUEST_RESTORE_GPRS(%rax)
|
||||
|
||||
/* Set RAX. */
|
||||
popq %rax
|
||||
|
||||
/* Run the VM. */
|
||||
vmload %rax
|
||||
vmrun %rax
|
||||
vmsave %rax
|
||||
|
||||
/* Get RAX. */
|
||||
popq %rax
|
||||
|
||||
/* Save the Guest GPRs. */
|
||||
GUEST_SAVE_GPRS(%rax)
|
||||
|
||||
/* Restore the Host LDT. */
|
||||
HOST_RESTORE_LDT
|
||||
|
||||
/* Restore the Host Segregs. */
|
||||
HOST_RESTORE_SEGREG(%gs)
|
||||
HOST_RESTORE_SEGREG(%fs)
|
||||
|
||||
/* Restore the variable Host MSRs. */
|
||||
HOST_RESTORE_MSR(MSR_FSBASE)
|
||||
HOST_RESTORE_MSR(MSR_GSBASE)
|
||||
HOST_RESTORE_MSR(MSR_KERNELGSBASE)
|
||||
|
||||
/* Restore the Host TR. */
|
||||
HOST_RESTORE_TR
|
||||
|
||||
/* Enable Host interrupts. */
|
||||
stgi
|
||||
|
||||
/* Restore the Host GPRs. */
|
||||
HOST_RESTORE_GPRS
|
||||
|
||||
xorq %rax,%rax
|
||||
retq
|
||||
END(svm_vmrun)
|
@ -1,4 +1,4 @@
|
||||
# $NetBSD: Makefile,v 1.209 2018/08/28 03:41:38 riastradh Exp $
|
||||
# $NetBSD: Makefile,v 1.210 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
.include <bsd.own.mk>
|
||||
|
||||
@ -202,6 +202,10 @@ SUBDIR+= tprof_x86
|
||||
SUBDIR+= vmt
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_ARCH} == "x86_64"
|
||||
SUBDIR+= nvmm
|
||||
.endif
|
||||
|
||||
.if ${MACHINE_ARCH} == "i386" || \
|
||||
${MACHINE_ARCH} == "x86_64"
|
||||
SUBDIR+= ubsec # Builds on architectures with PCI bus
|
||||
|
19
sys/modules/nvmm/Makefile
Normal file
19
sys/modules/nvmm/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
# $NetBSD: Makefile,v 1.1 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
.include "../Makefile.inc"
|
||||
.include "../Makefile.assym"
|
||||
|
||||
CPPFLAGS+=
|
||||
|
||||
.PATH: ${S}/dev/nvmm
|
||||
.PATH: ${S}/dev/nvmm/x86
|
||||
|
||||
KMOD= nvmm
|
||||
IOCONF= nvmm.ioconf
|
||||
SRCS= nvmm.c
|
||||
|
||||
.if ${MACHINE_ARCH} == "x86_64"
|
||||
SRCS+= nvmm_x86_svm.c nvmm_x86_svmfunc.S
|
||||
.endif
|
||||
|
||||
.include <bsd.kmodule.mk>
|
7
sys/modules/nvmm/nvmm.ioconf
Normal file
7
sys/modules/nvmm/nvmm.ioconf
Normal file
@ -0,0 +1,7 @@
|
||||
# $NetBSD: nvmm.ioconf,v 1.1 2018/11/07 07:43:08 maxv Exp $
|
||||
|
||||
ioconf nvmm
|
||||
|
||||
include "conf/files"
|
||||
|
||||
pseudo-device nvmm
|
Loading…
Reference in New Issue
Block a user