mirror of
https://git.hardenedbsd.org/hardenedbsd/HardenedBSD.git
synced 2024-11-15 06:42:51 +01:00
vmm(4), bhyve(8): Expose kernel-emulated special devices to userspace
Expose the special kernel LAPIC, IOAPIC, and HPET devices to userspace for use in, e.g., fallback instruction emulation (when userspace has a newer instruction decode/emulation layer than the kernel vmm(4)). Plumb the ioctl through libvmmapi and register the memory ranges in bhyve(8). Reviewed by: grehan Differential Revision: https://reviews.freebsd.org/D24525
This commit is contained in:
parent
e240ce42bf
commit
8a68ae80f6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=361082
@ -798,6 +798,25 @@ vm_ioapic_pincount(struct vmctx *ctx, int *pincount)
|
||||
return (ioctl(ctx->fd, VM_IOAPIC_PINCOUNT, pincount));
|
||||
}
|
||||
|
||||
int
|
||||
vm_readwrite_kernemu_device(struct vmctx *ctx, int vcpu, vm_paddr_t gpa,
|
||||
bool write, int size, uint64_t *value)
|
||||
{
|
||||
struct vm_readwrite_kernemu_device irp = {
|
||||
.vcpuid = vcpu,
|
||||
.access_width = fls(size) - 1,
|
||||
.gpa = gpa,
|
||||
.value = write ? *value : ~0ul,
|
||||
};
|
||||
long cmd = (write ? VM_SET_KERNEMU_DEV : VM_GET_KERNEMU_DEV);
|
||||
int rc;
|
||||
|
||||
rc = ioctl(ctx->fd, cmd, &irp);
|
||||
if (rc == 0 && !write)
|
||||
*value = irp.value;
|
||||
return (rc);
|
||||
}
|
||||
|
||||
int
|
||||
vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq)
|
||||
{
|
||||
@ -1615,6 +1634,7 @@ vm_get_ioctls(size_t *len)
|
||||
VM_MMAP_GETNEXT, VM_SET_REGISTER, VM_GET_REGISTER,
|
||||
VM_SET_SEGMENT_DESCRIPTOR, VM_GET_SEGMENT_DESCRIPTOR,
|
||||
VM_SET_REGISTER_SET, VM_GET_REGISTER_SET,
|
||||
VM_SET_KERNEMU_DEV, VM_GET_KERNEMU_DEV,
|
||||
VM_INJECT_EXCEPTION, VM_LAPIC_IRQ, VM_LAPIC_LOCAL_IRQ,
|
||||
VM_LAPIC_MSI, VM_IOAPIC_ASSERT_IRQ, VM_IOAPIC_DEASSERT_IRQ,
|
||||
VM_IOAPIC_PULSE_IRQ, VM_IOAPIC_PINCOUNT, VM_ISA_ASSERT_IRQ,
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <sys/cpuset.h>
|
||||
#include <machine/vmm_dev.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
/*
|
||||
* API version for out-of-tree consumers like grub-bhyve for making compile
|
||||
* time decisions.
|
||||
@ -156,6 +158,8 @@ int vm_ioapic_assert_irq(struct vmctx *ctx, int irq);
|
||||
int vm_ioapic_deassert_irq(struct vmctx *ctx, int irq);
|
||||
int vm_ioapic_pulse_irq(struct vmctx *ctx, int irq);
|
||||
int vm_ioapic_pincount(struct vmctx *ctx, int *pincount);
|
||||
int vm_readwrite_kernemu_device(struct vmctx *ctx, int vcpu,
|
||||
vm_paddr_t gpa, bool write, int size, uint64_t *value);
|
||||
int vm_isa_assert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq);
|
||||
int vm_isa_deassert_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq);
|
||||
int vm_isa_pulse_irq(struct vmctx *ctx, int atpic_irq, int ioapic_irq);
|
||||
|
@ -235,6 +235,15 @@ struct vm_cpu_topology {
|
||||
uint16_t maxcpus;
|
||||
};
|
||||
|
||||
struct vm_readwrite_kernemu_device {
|
||||
int vcpuid;
|
||||
unsigned access_width : 3;
|
||||
unsigned _unused : 29;
|
||||
uint64_t gpa;
|
||||
uint64_t value;
|
||||
};
|
||||
_Static_assert(sizeof(struct vm_readwrite_kernemu_device) == 24, "ABI");
|
||||
|
||||
enum {
|
||||
/* general routines */
|
||||
IOCNUM_ABIVERS = 0,
|
||||
@ -262,6 +271,8 @@ enum {
|
||||
IOCNUM_GET_SEGMENT_DESCRIPTOR = 23,
|
||||
IOCNUM_SET_REGISTER_SET = 24,
|
||||
IOCNUM_GET_REGISTER_SET = 25,
|
||||
IOCNUM_GET_KERNEMU_DEV = 26,
|
||||
IOCNUM_SET_KERNEMU_DEV = 27,
|
||||
|
||||
/* interrupt injection */
|
||||
IOCNUM_GET_INTINFO = 28,
|
||||
@ -347,6 +358,12 @@ enum {
|
||||
_IOW('v', IOCNUM_SET_REGISTER_SET, struct vm_register_set)
|
||||
#define VM_GET_REGISTER_SET \
|
||||
_IOWR('v', IOCNUM_GET_REGISTER_SET, struct vm_register_set)
|
||||
#define VM_SET_KERNEMU_DEV \
|
||||
_IOW('v', IOCNUM_SET_KERNEMU_DEV, \
|
||||
struct vm_readwrite_kernemu_device)
|
||||
#define VM_GET_KERNEMU_DEV \
|
||||
_IOWR('v', IOCNUM_GET_KERNEMU_DEV, \
|
||||
struct vm_readwrite_kernemu_device)
|
||||
#define VM_INJECT_EXCEPTION \
|
||||
_IOW('v', IOCNUM_INJECT_EXCEPTION, struct vm_exception)
|
||||
#define VM_LAPIC_IRQ \
|
||||
|
@ -58,6 +58,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/vmm_dev.h>
|
||||
#include <machine/vmm_instruction_emul.h>
|
||||
#include <machine/vmm_snapshot.h>
|
||||
#include <x86/apicreg.h>
|
||||
|
||||
#include "vmm_lapic.h"
|
||||
#include "vmm_stat.h"
|
||||
@ -382,6 +383,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
struct vm_rtc_data *rtcdata;
|
||||
struct vm_memmap *mm;
|
||||
struct vm_cpu_topology *topology;
|
||||
struct vm_readwrite_kernemu_device *kernemu;
|
||||
uint64_t *regvals;
|
||||
int *regnums;
|
||||
#ifdef BHYVE_SNAPSHOT
|
||||
@ -561,6 +563,41 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
|
||||
case VM_IOAPIC_PINCOUNT:
|
||||
*(int *)data = vioapic_pincount(sc->vm);
|
||||
break;
|
||||
case VM_SET_KERNEMU_DEV:
|
||||
case VM_GET_KERNEMU_DEV: {
|
||||
mem_region_write_t mwrite;
|
||||
mem_region_read_t mread;
|
||||
bool arg;
|
||||
|
||||
kernemu = (void *)data;
|
||||
|
||||
if (kernemu->access_width > 0)
|
||||
size = (1u << kernemu->access_width);
|
||||
else
|
||||
size = 1;
|
||||
|
||||
if (kernemu->gpa >= DEFAULT_APIC_BASE && kernemu->gpa < DEFAULT_APIC_BASE + PAGE_SIZE) {
|
||||
mread = lapic_mmio_read;
|
||||
mwrite = lapic_mmio_write;
|
||||
} else if (kernemu->gpa >= VIOAPIC_BASE && kernemu->gpa < VIOAPIC_BASE + VIOAPIC_SIZE) {
|
||||
mread = vioapic_mmio_read;
|
||||
mwrite = vioapic_mmio_write;
|
||||
} else if (kernemu->gpa >= VHPET_BASE && kernemu->gpa < VHPET_BASE + VHPET_SIZE) {
|
||||
mread = vhpet_mmio_read;
|
||||
mwrite = vhpet_mmio_write;
|
||||
} else {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (cmd == VM_SET_KERNEMU_DEV)
|
||||
error = mwrite(sc->vm, kernemu->vcpuid, kernemu->gpa,
|
||||
kernemu->value, size, &arg);
|
||||
else
|
||||
error = mread(sc->vm, kernemu->vcpuid, kernemu->gpa,
|
||||
&kernemu->value, size, &arg);
|
||||
break;
|
||||
}
|
||||
case VM_ISA_ASSERT_IRQ:
|
||||
isa_irq = (struct vm_isa_irq *)data;
|
||||
error = vatpic_assert_irq(sc->vm, isa_irq->atpic_irq);
|
||||
|
@ -31,6 +31,7 @@ SRCS= \
|
||||
hda_codec.c \
|
||||
inout.c \
|
||||
ioapic.c \
|
||||
kernemu_dev.c \
|
||||
mem.c \
|
||||
mevent.c \
|
||||
mptbl.c \
|
||||
@ -76,6 +77,8 @@ SRCS= \
|
||||
SRCS+= snapshot.c
|
||||
.endif
|
||||
|
||||
CFLAGS.kernemu_dev.c+= -I${SRCTOP}/sys/amd64
|
||||
|
||||
.PATH: ${BHYVE_SYSDIR}/sys/amd64/vmm
|
||||
SRCS+= vmm_instruction_emul.c
|
||||
|
||||
|
@ -92,6 +92,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include "fwctl.h"
|
||||
#include "gdb.h"
|
||||
#include "ioapic.h"
|
||||
#include "kernemu_dev.h"
|
||||
#include "mem.h"
|
||||
#include "mevent.h"
|
||||
#include "mptbl.h"
|
||||
@ -1268,6 +1269,7 @@ main(int argc, char *argv[])
|
||||
|
||||
init_mem();
|
||||
init_inout();
|
||||
kernemu_dev_init();
|
||||
init_bootrom(ctx);
|
||||
atkbdc_init(ctx);
|
||||
pci_irq_init(ctx);
|
||||
|
98
usr.sbin/bhyve/kernemu_dev.c
Normal file
98
usr.sbin/bhyve/kernemu_dev.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright 2020 Conrad Meyer <cem@FreeBSD.org>. All rights reserved.
|
||||
*
|
||||
* 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 AUTHOR 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 AUTHOR 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>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/tree.h>
|
||||
|
||||
#include <amd64/include/vmm.h>
|
||||
#include <x86/include/apicreg.h>
|
||||
struct vm;
|
||||
struct vm_hpet_cap;
|
||||
#include <vmm/io/vioapic.h>
|
||||
#include <vmm/io/vhpet.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <vmmapi.h>
|
||||
|
||||
#include "kernemu_dev.h"
|
||||
#include "mem.h"
|
||||
|
||||
static int
|
||||
apic_handler(struct vmctx *ctx, int vcpu, int dir, uint64_t addr, int size,
|
||||
uint64_t *val, void *arg1 __unused, long arg2 __unused)
|
||||
{
|
||||
if (vm_readwrite_kernemu_device(ctx, vcpu, addr, (dir == MEM_F_WRITE),
|
||||
size, val) != 0)
|
||||
return (errno);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct mem_range lapic_mmio = {
|
||||
.name = "kern-lapic-mmio",
|
||||
.base = DEFAULT_APIC_BASE,
|
||||
.size = PAGE_SIZE,
|
||||
.flags = MEM_F_RW | MEM_F_IMMUTABLE,
|
||||
.handler = apic_handler,
|
||||
|
||||
};
|
||||
static struct mem_range ioapic_mmio = {
|
||||
.name = "kern-ioapic-mmio",
|
||||
.base = VIOAPIC_BASE,
|
||||
.size = VIOAPIC_SIZE,
|
||||
.flags = MEM_F_RW | MEM_F_IMMUTABLE,
|
||||
.handler = apic_handler,
|
||||
};
|
||||
static struct mem_range hpet_mmio = {
|
||||
.name = "kern-hpet-mmio",
|
||||
.base = VHPET_BASE,
|
||||
.size = VHPET_SIZE,
|
||||
.flags = MEM_F_RW | MEM_F_IMMUTABLE,
|
||||
.handler = apic_handler,
|
||||
};
|
||||
|
||||
void
|
||||
kernemu_dev_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = register_mem(&lapic_mmio);
|
||||
if (rc != 0)
|
||||
errc(4, rc, "register_mem: LAPIC (0x%08x)",
|
||||
(unsigned)lapic_mmio.base);
|
||||
rc = register_mem(&ioapic_mmio);
|
||||
if (rc != 0)
|
||||
errc(4, rc, "register_mem: IOAPIC (0x%08x)",
|
||||
(unsigned)ioapic_mmio.base);
|
||||
rc = register_mem(&hpet_mmio);
|
||||
if (rc != 0)
|
||||
errc(4, rc, "register_mem: HPET (0x%08x)",
|
||||
(unsigned)hpet_mmio.base);
|
||||
}
|
32
usr.sbin/bhyve/kernemu_dev.h
Normal file
32
usr.sbin/bhyve/kernemu_dev.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause-FreeBSD
|
||||
*
|
||||
* Copyright 2020 Conrad Meyer <cem@FreeBSD.org>. All rights reserved.
|
||||
*
|
||||
* 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 AUTHOR 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 AUTHOR 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.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
void kernemu_dev_init(void);
|
Loading…
Reference in New Issue
Block a user