mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream-hvf' into staging
Initial support for the HVF accelerator # gpg: Signature made Sat 23 Dec 2017 07:51:18 GMT # gpg: using RSA key 0xBFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream-hvf: i386: hvf: cleanup x86_gen.h i386: hvf: remove VM_PANIC from "in" i386: hvf: remove addr_t i386: hvf: simplify flag handling i386: hvf: abort on decoding error i386: hvf: remove ZERO_INIT macro i386: hvf: remove more dead emulator code i386: hvf: unify register enums between HVF and the rest i386: hvf: header cleanup i386: hvf: move all hvf files in the same directory i386: hvf: inject General Protection Fault when vmexit through vmcall i386: hvf: refactor event injection code for hvf i386: hvf: implement vga dirty page tracking i386: refactor KVM cpuid code so that it applies to hvf as well i386: hvf: implement hvf_get_supported_cpuid i386: hvf: use new helper functions for put/get xsave i386: hvf: fix licensing issues; isolate task handling code (GPL v2-only) i386: hvf: add code base from Google's QEMU repository apic: add function to apic that will be used by hvf Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
obj-$(call lnot,$(CONFIG_HAX)) += hax-stub.o
|
||||
obj-$(call lnot,$(CONFIG_HVF)) += hvf-stub.o
|
||||
obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o
|
||||
obj-$(call lnot,$(CONFIG_TCG)) += tcg-stub.o
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* QEMU HVF support
|
||||
*
|
||||
* Copyright 2017 Red Hat, Inc.
|
||||
*
|
||||
* This software is licensed under the terms of the GNU General Public
|
||||
* License version 2 or later, as published by the Free Software Foundation,
|
||||
* and may be copied, distributed, and modified under those terms.
|
||||
*
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "cpu.h"
|
||||
#include "sysemu/hvf.h"
|
||||
|
||||
int hvf_init_vcpu(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
int hvf_vcpu_exec(CPUState *cpu)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
void hvf_vcpu_destroy(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
@@ -211,6 +211,17 @@ supported_xen_target() {
|
||||
return 1
|
||||
}
|
||||
|
||||
supported_hvf_target() {
|
||||
test "$hvf" = "yes" || return 1
|
||||
glob "$1" "*-softmmu" || return 1
|
||||
case "${1%-softmmu}" in
|
||||
x86_64)
|
||||
return 0
|
||||
;;
|
||||
esac
|
||||
return 1
|
||||
}
|
||||
|
||||
supported_target() {
|
||||
case "$1" in
|
||||
*-softmmu)
|
||||
@@ -236,6 +247,7 @@ supported_target() {
|
||||
supported_kvm_target "$1" && return 0
|
||||
supported_xen_target "$1" && return 0
|
||||
supported_hax_target "$1" && return 0
|
||||
supported_hvf_target "$1" && return 0
|
||||
print_error "TCG disabled, but hardware accelerator not available for '$target'"
|
||||
return 1
|
||||
}
|
||||
@@ -325,6 +337,7 @@ vhost_vsock="no"
|
||||
vhost_user=""
|
||||
kvm="no"
|
||||
hax="no"
|
||||
hvf="no"
|
||||
rdma=""
|
||||
gprof="no"
|
||||
debug_tcg="no"
|
||||
@@ -741,6 +754,7 @@ Darwin)
|
||||
bsd="yes"
|
||||
darwin="yes"
|
||||
hax="yes"
|
||||
hvf="yes"
|
||||
LDFLAGS_SHARED="-bundle -undefined dynamic_lookup"
|
||||
if [ "$cpu" = "x86_64" ] ; then
|
||||
QEMU_CFLAGS="-arch x86_64 $QEMU_CFLAGS"
|
||||
@@ -1036,6 +1050,10 @@ for opt do
|
||||
;;
|
||||
--enable-hax) hax="yes"
|
||||
;;
|
||||
--disable-hvf) hvf="no"
|
||||
;;
|
||||
--enable-hvf) hvf="yes"
|
||||
;;
|
||||
--disable-tcg-interpreter) tcg_interpreter="no"
|
||||
;;
|
||||
--enable-tcg-interpreter) tcg_interpreter="yes"
|
||||
@@ -1529,6 +1547,7 @@ disabled with --disable-FEATURE, default is enabled if available:
|
||||
bluez bluez stack connectivity
|
||||
kvm KVM acceleration support
|
||||
hax HAX acceleration support
|
||||
hvf Hypervisor.framework acceleration support
|
||||
rdma RDMA-based migration support
|
||||
vde support for vde network
|
||||
netmap support for netmap network
|
||||
@@ -5055,6 +5074,21 @@ then
|
||||
fi
|
||||
|
||||
|
||||
#################################################
|
||||
# Check to see if we have the Hypervisor framework
|
||||
if [ "$darwin" == "yes" ] ; then
|
||||
cat > $TMPC << EOF
|
||||
#include <Hypervisor/hv.h>
|
||||
int main() { return 0;}
|
||||
EOF
|
||||
if ! compile_object ""; then
|
||||
hvf='no'
|
||||
else
|
||||
hvf='yes'
|
||||
LDFLAGS="-framework Hypervisor $LDFLAGS"
|
||||
fi
|
||||
fi
|
||||
|
||||
#################################################
|
||||
# Sparc implicitly links with --relax, which is
|
||||
# incompatible with -r, so --no-relax should be
|
||||
@@ -5530,6 +5564,7 @@ echo "ATTR/XATTR support $attr"
|
||||
echo "Install blobs $blobs"
|
||||
echo "KVM support $kvm"
|
||||
echo "HAX support $hax"
|
||||
echo "HVF support $hvf"
|
||||
echo "TCG support $tcg"
|
||||
if test "$tcg" = "yes" ; then
|
||||
echo "TCG debug enabled $debug_tcg"
|
||||
@@ -6602,6 +6637,9 @@ fi
|
||||
if supported_hax_target $target; then
|
||||
echo "CONFIG_HAX=y" >> $config_target_mak
|
||||
fi
|
||||
if supported_hvf_target $target; then
|
||||
echo "CONFIG_HVF=y" >> $config_target_mak
|
||||
fi
|
||||
if test "$target_bigendian" = "yes" ; then
|
||||
echo "TARGET_WORDS_BIGENDIAN=y" >> $config_target_mak
|
||||
fi
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hax.h"
|
||||
#include "sysemu/hvf.h"
|
||||
#include "qmp-commands.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
@@ -900,6 +901,10 @@ void cpu_synchronize_all_states(void)
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_synchronize_state(cpu);
|
||||
/* TODO: move to cpu_synchronize_state() */
|
||||
if (hvf_enabled()) {
|
||||
hvf_cpu_synchronize_state(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -909,6 +914,10 @@ void cpu_synchronize_all_post_reset(void)
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_synchronize_post_reset(cpu);
|
||||
/* TODO: move to cpu_synchronize_post_reset() */
|
||||
if (hvf_enabled()) {
|
||||
hvf_cpu_synchronize_post_reset(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -918,6 +927,10 @@ void cpu_synchronize_all_post_init(void)
|
||||
|
||||
CPU_FOREACH(cpu) {
|
||||
cpu_synchronize_post_init(cpu);
|
||||
/* TODO: move to cpu_synchronize_post_init() */
|
||||
if (hvf_enabled()) {
|
||||
hvf_cpu_synchronize_post_init(cpu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1107,6 +1120,14 @@ static void qemu_kvm_wait_io_event(CPUState *cpu)
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
|
||||
static void qemu_hvf_wait_io_event(CPUState *cpu)
|
||||
{
|
||||
while (cpu_thread_is_idle(cpu)) {
|
||||
qemu_cond_wait(cpu->halt_cond, &qemu_global_mutex);
|
||||
}
|
||||
qemu_wait_io_event_common(cpu);
|
||||
}
|
||||
|
||||
static void *qemu_kvm_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
@@ -1444,6 +1465,48 @@ static void *qemu_hax_cpu_thread_fn(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The HVF-specific vCPU thread function. This one should only run when the host
|
||||
* CPU supports the VMX "unrestricted guest" feature. */
|
||||
static void *qemu_hvf_cpu_thread_fn(void *arg)
|
||||
{
|
||||
CPUState *cpu = arg;
|
||||
|
||||
int r;
|
||||
|
||||
assert(hvf_enabled());
|
||||
|
||||
rcu_register_thread();
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
qemu_thread_get_self(cpu->thread);
|
||||
|
||||
cpu->thread_id = qemu_get_thread_id();
|
||||
cpu->can_do_io = 1;
|
||||
current_cpu = cpu;
|
||||
|
||||
hvf_init_vcpu(cpu);
|
||||
|
||||
/* signal CPU creation */
|
||||
cpu->created = true;
|
||||
qemu_cond_signal(&qemu_cpu_cond);
|
||||
|
||||
do {
|
||||
if (cpu_can_run(cpu)) {
|
||||
r = hvf_vcpu_exec(cpu);
|
||||
if (r == EXCP_DEBUG) {
|
||||
cpu_handle_guest_debug(cpu);
|
||||
}
|
||||
}
|
||||
qemu_hvf_wait_io_event(cpu);
|
||||
} while (!cpu->unplug || cpu_can_run(cpu));
|
||||
|
||||
hvf_vcpu_destroy(cpu);
|
||||
cpu->created = false;
|
||||
qemu_cond_signal(&qemu_cpu_cond);
|
||||
qemu_mutex_unlock_iothread();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static void CALLBACK dummy_apc_func(ULONG_PTR unused)
|
||||
{
|
||||
@@ -1761,6 +1824,27 @@ static void qemu_kvm_start_vcpu(CPUState *cpu)
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_hvf_start_vcpu(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
|
||||
/* HVF currently does not support TCG, and only runs in
|
||||
* unrestricted-guest mode. */
|
||||
assert(hvf_enabled());
|
||||
|
||||
cpu->thread = g_malloc0(sizeof(QemuThread));
|
||||
cpu->halt_cond = g_malloc0(sizeof(QemuCond));
|
||||
qemu_cond_init(cpu->halt_cond);
|
||||
|
||||
snprintf(thread_name, VCPU_THREAD_NAME_SIZE, "CPU %d/HVF",
|
||||
cpu->cpu_index);
|
||||
qemu_thread_create(cpu->thread, thread_name, qemu_hvf_cpu_thread_fn,
|
||||
cpu, QEMU_THREAD_JOINABLE);
|
||||
while (!cpu->created) {
|
||||
qemu_cond_wait(&qemu_cpu_cond, &qemu_global_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void qemu_dummy_start_vcpu(CPUState *cpu)
|
||||
{
|
||||
char thread_name[VCPU_THREAD_NAME_SIZE];
|
||||
@@ -1795,6 +1879,8 @@ void qemu_init_vcpu(CPUState *cpu)
|
||||
qemu_kvm_start_vcpu(cpu);
|
||||
} else if (hax_enabled()) {
|
||||
qemu_hax_start_vcpu(cpu);
|
||||
} else if (hvf_enabled()) {
|
||||
qemu_hvf_start_vcpu(cpu);
|
||||
} else if (tcg_enabled()) {
|
||||
qemu_tcg_init_vcpu(cpu);
|
||||
} else {
|
||||
|
||||
@@ -305,6 +305,18 @@ static void apic_set_tpr(APICCommonState *s, uint8_t val)
|
||||
}
|
||||
}
|
||||
|
||||
int apic_get_highest_priority_irr(DeviceState *dev)
|
||||
{
|
||||
APICCommonState *s;
|
||||
|
||||
if (!dev) {
|
||||
/* no interrupts */
|
||||
return -1;
|
||||
}
|
||||
s = APIC_COMMON(dev);
|
||||
return get_highest_priority_int(s->irr);
|
||||
}
|
||||
|
||||
static uint8_t apic_get_tpr(APICCommonState *s)
|
||||
{
|
||||
apic_sync_vapic(s, SYNC_FROM_VAPIC);
|
||||
|
||||
@@ -20,6 +20,7 @@ void apic_init_reset(DeviceState *s);
|
||||
void apic_sipi(DeviceState *s);
|
||||
void apic_poll_irq(DeviceState *d);
|
||||
void apic_designate_bsp(DeviceState *d, bool bsp);
|
||||
int apic_get_highest_priority_irr(DeviceState *dev);
|
||||
|
||||
/* pc.c */
|
||||
DeviceState *cpu_get_current_apic(void);
|
||||
|
||||
@@ -36,6 +36,7 @@ typedef struct FWCfgIoState FWCfgIoState;
|
||||
typedef struct FWCfgMemState FWCfgMemState;
|
||||
typedef struct FWCfgState FWCfgState;
|
||||
typedef struct HCIInfo HCIInfo;
|
||||
typedef struct HVFX86EmulatorState HVFX86EmulatorState;
|
||||
typedef struct I2CBus I2CBus;
|
||||
typedef struct I2SCodec I2SCodec;
|
||||
typedef struct ISABus ISABus;
|
||||
|
||||
@@ -423,6 +423,8 @@ struct CPUState {
|
||||
* unnecessary flushes.
|
||||
*/
|
||||
uint16_t pending_tlb_flush;
|
||||
|
||||
int hvf_fd;
|
||||
};
|
||||
|
||||
QTAILQ_HEAD(CPUTailQ, CPUState);
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* QEMU Hypervisor.framework (HVF) support
|
||||
*
|
||||
* Copyright Google Inc., 2017
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
/* header to be included in non-HVF-specific code */
|
||||
#ifndef _HVF_H
|
||||
#define _HVF_H
|
||||
|
||||
#include "config-host.h"
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "exec/memory.h"
|
||||
#include "sysemu/accel.h"
|
||||
|
||||
extern int hvf_disabled;
|
||||
#ifdef CONFIG_HVF
|
||||
#include <Hypervisor/hv.h>
|
||||
#include <Hypervisor/hv_vmx.h>
|
||||
#include <Hypervisor/hv_error.h>
|
||||
#include "target/i386/cpu.h"
|
||||
#include "hw/hw.h"
|
||||
uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
|
||||
int reg);
|
||||
#define hvf_enabled() !hvf_disabled
|
||||
#else
|
||||
#define hvf_enabled() 0
|
||||
#define hvf_get_supported_cpuid(func, idx, reg) 0
|
||||
#endif
|
||||
|
||||
/* hvf_slot flags */
|
||||
#define HVF_SLOT_LOG (1 << 0)
|
||||
|
||||
typedef struct hvf_slot {
|
||||
uint64_t start;
|
||||
uint64_t size;
|
||||
uint8_t *mem;
|
||||
int slot_id;
|
||||
uint32_t flags;
|
||||
MemoryRegion *region;
|
||||
} hvf_slot;
|
||||
|
||||
typedef struct hvf_vcpu_caps {
|
||||
uint64_t vmx_cap_pinbased;
|
||||
uint64_t vmx_cap_procbased;
|
||||
uint64_t vmx_cap_procbased2;
|
||||
uint64_t vmx_cap_entry;
|
||||
uint64_t vmx_cap_exit;
|
||||
uint64_t vmx_cap_preemption_timer;
|
||||
} hvf_vcpu_caps;
|
||||
|
||||
typedef struct HVFState {
|
||||
AccelState parent;
|
||||
hvf_slot slots[32];
|
||||
int num_slots;
|
||||
|
||||
hvf_vcpu_caps *hvf_caps;
|
||||
} HVFState;
|
||||
extern HVFState *hvf_state;
|
||||
|
||||
void hvf_set_phys_mem(MemoryRegionSection *, bool);
|
||||
void hvf_handle_io(CPUArchState *, uint16_t, void *,
|
||||
int, int, int);
|
||||
hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
|
||||
|
||||
/* Disable HVF if |disable| is 1, otherwise, enable it iff it is supported by
|
||||
* the host CPU. Use hvf_enabled() after this to get the result. */
|
||||
void hvf_disable(int disable);
|
||||
|
||||
/* Returns non-0 if the host CPU supports the VMX "unrestricted guest" feature
|
||||
* which allows the virtual CPU to directly run in "real mode". If true, this
|
||||
* allows QEMU to run several vCPU threads in parallel (see cpus.c). Otherwise,
|
||||
* only a a single TCG thread can run, and it will call HVF to run the current
|
||||
* instructions, except in case of "real mode" (paging disabled, typically at
|
||||
* boot time), or MMIO operations. */
|
||||
|
||||
int hvf_sync_vcpus(void);
|
||||
|
||||
int hvf_init_vcpu(CPUState *);
|
||||
int hvf_vcpu_exec(CPUState *);
|
||||
int hvf_smp_cpu_exec(CPUState *);
|
||||
void hvf_cpu_synchronize_state(CPUState *);
|
||||
void hvf_cpu_synchronize_post_reset(CPUState *);
|
||||
void hvf_cpu_synchronize_post_init(CPUState *);
|
||||
void _hvf_cpu_synchronize_post_init(CPUState *, run_on_cpu_data);
|
||||
|
||||
void hvf_vcpu_destroy(CPUState *);
|
||||
void hvf_raise_event(CPUState *);
|
||||
/* void hvf_reset_vcpu_state(void *opaque); */
|
||||
void hvf_reset_vcpu(CPUState *);
|
||||
void vmx_update_tpr(CPUState *);
|
||||
void update_apic_tpr(CPUState *);
|
||||
int hvf_put_registers(CPUState *);
|
||||
void vmx_clear_int_window_exiting(CPUState *cpu);
|
||||
|
||||
#define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf")
|
||||
|
||||
#define HVF_STATE(obj) \
|
||||
OBJECT_CHECK(HVFState, (obj), TYPE_HVF_ACCEL)
|
||||
|
||||
#endif
|
||||
+5
-5
@@ -31,7 +31,7 @@ DEF("machine", HAS_ARG, QEMU_OPTION_machine, \
|
||||
"-machine [type=]name[,prop[=value][,...]]\n"
|
||||
" selects emulated machine ('-machine help' for list)\n"
|
||||
" property accel=accel1[:accel2[:...]] selects accelerator\n"
|
||||
" supported accelerators are kvm, xen, hax or tcg (default: tcg)\n"
|
||||
" supported accelerators are kvm, xen, hax, hvf or tcg (default: tcg)\n"
|
||||
" kernel_irqchip=on|off|split controls accelerated irqchip support (default=off)\n"
|
||||
" vmport=on|off|auto controls emulation of vmport (default: auto)\n"
|
||||
" kvm_shadow_mem=size of KVM shadow MMU in bytes\n"
|
||||
@@ -66,7 +66,7 @@ Supported machine properties are:
|
||||
@table @option
|
||||
@item accel=@var{accels1}[:@var{accels2}[:...]]
|
||||
This is used to enable an accelerator. Depending on the target architecture,
|
||||
kvm, xen, hax or tcg can be available. By default, tcg is used. If there is
|
||||
kvm, xen, hax, hvf or tcg can be available. By default, tcg is used. If there is
|
||||
more than one accelerator specified, the next one is used if the previous one
|
||||
fails to initialize.
|
||||
@item kernel_irqchip=on|off
|
||||
@@ -126,13 +126,13 @@ ETEXI
|
||||
|
||||
DEF("accel", HAS_ARG, QEMU_OPTION_accel,
|
||||
"-accel [accel=]accelerator[,thread=single|multi]\n"
|
||||
" select accelerator (kvm, xen, hax or tcg; use 'help' for a list)\n"
|
||||
" thread=single|multi (enable multi-threaded TCG)\n", QEMU_ARCH_ALL)
|
||||
" select accelerator (kvm, xen, hax, hvf or tcg; use 'help' for a list)\n"
|
||||
" thread=single|multi (enable multi-threaded TCG)", QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -accel @var{name}[,prop=@var{value}[,...]]
|
||||
@findex -accel
|
||||
This is used to enable an accelerator. Depending on the target architecture,
|
||||
kvm, xen, hax or tcg can be available. By default, tcg is used. If there is
|
||||
kvm, xen, hax, hvf or tcg can be available. By default, tcg is used. If there is
|
||||
more than one accelerator specified, the next one is used if the previous one
|
||||
fails to initialize.
|
||||
@table @option
|
||||
|
||||
@@ -12,4 +12,5 @@ obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-windows.o
|
||||
endif
|
||||
ifdef CONFIG_DARWIN
|
||||
obj-$(CONFIG_HAX) += hax-all.o hax-mem.o hax-darwin.o
|
||||
obj-$(CONFIG_HVF) += hvf/
|
||||
endif
|
||||
|
||||
@@ -47,7 +47,7 @@ typedef struct X86CPUDefinition X86CPUDefinition;
|
||||
/**
|
||||
* X86CPUClass:
|
||||
* @cpu_def: CPU model definition
|
||||
* @kvm_required: Whether CPU model requires KVM to be enabled.
|
||||
* @host_cpuid_required: Whether CPU model requires cpuid from host.
|
||||
* @ordering: Ordering on the "-cpu help" CPU model list.
|
||||
* @migration_safe: See CpuDefinitionInfo::migration_safe
|
||||
* @static_model: See CpuDefinitionInfo::static
|
||||
@@ -66,7 +66,7 @@ typedef struct X86CPUClass {
|
||||
*/
|
||||
X86CPUDefinition *cpu_def;
|
||||
|
||||
bool kvm_required;
|
||||
bool host_cpuid_required;
|
||||
int ordering;
|
||||
bool migration_safe;
|
||||
bool static_model;
|
||||
|
||||
+60
-20
@@ -22,6 +22,7 @@
|
||||
#include "cpu.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/hvf.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "kvm_i386.h"
|
||||
|
||||
@@ -615,6 +616,11 @@ static uint32_t xsave_area_size(uint64_t mask)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline bool accel_uses_host_cpuid(void)
|
||||
{
|
||||
return kvm_enabled() || hvf_enabled();
|
||||
}
|
||||
|
||||
static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
|
||||
{
|
||||
return ((uint64_t)cpu->env.features[FEAT_XSAVE_COMP_HI]) << 32 |
|
||||
@@ -1686,10 +1692,15 @@ static void max_x86_cpu_initfn(Object *obj)
|
||||
*/
|
||||
cpu->max_features = true;
|
||||
|
||||
if (kvm_enabled()) {
|
||||
if (accel_uses_host_cpuid()) {
|
||||
char vendor[CPUID_VENDOR_SZ + 1] = { 0 };
|
||||
char model_id[CPUID_MODEL_ID_SZ + 1] = { 0 };
|
||||
int family, model, stepping;
|
||||
X86CPUDefinition host_cpudef = { };
|
||||
uint32_t eax = 0, ebx = 0, ecx = 0, edx = 0;
|
||||
|
||||
host_cpuid(0x0, 0, &eax, &ebx, &ecx, &edx);
|
||||
x86_cpu_vendor_words2str(host_cpudef.vendor, ebx, edx, ecx);
|
||||
|
||||
host_vendor_fms(vendor, &family, &model, &stepping);
|
||||
|
||||
@@ -1703,12 +1714,21 @@ static void max_x86_cpu_initfn(Object *obj)
|
||||
object_property_set_str(OBJECT(cpu), model_id, "model-id",
|
||||
&error_abort);
|
||||
|
||||
env->cpuid_min_level =
|
||||
kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
|
||||
env->cpuid_min_xlevel =
|
||||
kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
|
||||
env->cpuid_min_xlevel2 =
|
||||
kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
|
||||
if (kvm_enabled()) {
|
||||
env->cpuid_min_level =
|
||||
kvm_arch_get_supported_cpuid(s, 0x0, 0, R_EAX);
|
||||
env->cpuid_min_xlevel =
|
||||
kvm_arch_get_supported_cpuid(s, 0x80000000, 0, R_EAX);
|
||||
env->cpuid_min_xlevel2 =
|
||||
kvm_arch_get_supported_cpuid(s, 0xC0000000, 0, R_EAX);
|
||||
} else {
|
||||
env->cpuid_min_level =
|
||||
hvf_get_supported_cpuid(0x0, 0, R_EAX);
|
||||
env->cpuid_min_xlevel =
|
||||
hvf_get_supported_cpuid(0x80000000, 0, R_EAX);
|
||||
env->cpuid_min_xlevel2 =
|
||||
hvf_get_supported_cpuid(0xC0000000, 0, R_EAX);
|
||||
}
|
||||
|
||||
if (lmce_supported()) {
|
||||
object_property_set_bool(OBJECT(cpu), true, "lmce", &error_abort);
|
||||
@@ -1734,18 +1754,21 @@ static const TypeInfo max_x86_cpu_type_info = {
|
||||
.class_init = max_x86_cpu_class_init,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_KVM
|
||||
|
||||
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
|
||||
static void host_x86_cpu_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
X86CPUClass *xcc = X86_CPU_CLASS(oc);
|
||||
|
||||
xcc->kvm_required = true;
|
||||
xcc->host_cpuid_required = true;
|
||||
xcc->ordering = 8;
|
||||
|
||||
xcc->model_description =
|
||||
"KVM processor with all supported host features "
|
||||
"(only available in KVM mode)";
|
||||
if (kvm_enabled()) {
|
||||
xcc->model_description =
|
||||
"KVM processor with all supported host features ";
|
||||
} else if (hvf_enabled()) {
|
||||
xcc->model_description =
|
||||
"HVF processor with all supported host features ";
|
||||
}
|
||||
}
|
||||
|
||||
static const TypeInfo host_x86_cpu_type_info = {
|
||||
@@ -1767,7 +1790,7 @@ static void report_unavailable_features(FeatureWord w, uint32_t mask)
|
||||
assert(reg);
|
||||
warn_report("%s doesn't support requested feature: "
|
||||
"CPUID.%02XH:%s%s%s [bit %d]",
|
||||
kvm_enabled() ? "host" : "TCG",
|
||||
accel_uses_host_cpuid() ? "host" : "TCG",
|
||||
f->cpuid_eax, reg,
|
||||
f->feat_names[i] ? "." : "",
|
||||
f->feat_names[i] ? f->feat_names[i] : "", i);
|
||||
@@ -2218,7 +2241,7 @@ static void x86_cpu_class_check_missing_features(X86CPUClass *xcc,
|
||||
Error *err = NULL;
|
||||
strList **next = missing_feats;
|
||||
|
||||
if (xcc->kvm_required && !kvm_enabled()) {
|
||||
if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
|
||||
strList *new = g_new0(strList, 1);
|
||||
new->value = g_strdup("kvm");
|
||||
*missing_feats = new;
|
||||
@@ -2380,6 +2403,10 @@ static uint32_t x86_cpu_get_supported_feature_word(FeatureWord w,
|
||||
r = kvm_arch_get_supported_cpuid(kvm_state, wi->cpuid_eax,
|
||||
wi->cpuid_ecx,
|
||||
wi->cpuid_reg);
|
||||
} else if (hvf_enabled()) {
|
||||
r = hvf_get_supported_cpuid(wi->cpuid_eax,
|
||||
wi->cpuid_ecx,
|
||||
wi->cpuid_reg);
|
||||
} else if (tcg_enabled()) {
|
||||
r = wi->tcg_features;
|
||||
} else {
|
||||
@@ -2439,6 +2466,7 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
|
||||
}
|
||||
|
||||
/* Special cases not set in the X86CPUDefinition structs: */
|
||||
/* TODO: in-kernel irqchip for hvf */
|
||||
if (kvm_enabled()) {
|
||||
if (!kvm_irqchip_in_kernel()) {
|
||||
x86_cpu_change_kvm_default("x2apic", "off");
|
||||
@@ -2459,7 +2487,7 @@ static void x86_cpu_load_def(X86CPU *cpu, X86CPUDefinition *def, Error **errp)
|
||||
* when doing cross vendor migration
|
||||
*/
|
||||
vendor = def->vendor;
|
||||
if (kvm_enabled()) {
|
||||
if (accel_uses_host_cpuid()) {
|
||||
uint32_t ebx = 0, ecx = 0, edx = 0;
|
||||
host_cpuid(0, 0, NULL, &ebx, &ecx, &edx);
|
||||
x86_cpu_vendor_words2str(host_vendor, ebx, edx, ecx);
|
||||
@@ -2910,6 +2938,11 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||
*ebx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EBX);
|
||||
*ecx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_ECX);
|
||||
*edx = kvm_arch_get_supported_cpuid(s, 0xA, count, R_EDX);
|
||||
} else if (hvf_enabled() && cpu->enable_pmu) {
|
||||
*eax = hvf_get_supported_cpuid(0xA, count, R_EAX);
|
||||
*ebx = hvf_get_supported_cpuid(0xA, count, R_EBX);
|
||||
*ecx = hvf_get_supported_cpuid(0xA, count, R_ECX);
|
||||
*edx = hvf_get_supported_cpuid(0xA, count, R_EDX);
|
||||
} else {
|
||||
*eax = 0;
|
||||
*ebx = 0;
|
||||
@@ -3252,6 +3285,9 @@ static void x86_cpu_reset(CPUState *s)
|
||||
memset(env->mtrr_var, 0, sizeof(env->mtrr_var));
|
||||
memset(env->mtrr_fixed, 0, sizeof(env->mtrr_fixed));
|
||||
|
||||
env->interrupt_injected = -1;
|
||||
env->exception_injected = -1;
|
||||
env->nmi_injected = false;
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* We hard-wire the BSP to the first CPU. */
|
||||
apic_designate_bsp(cpu->apic_state, s->cpu_index == 0);
|
||||
@@ -3261,6 +3297,9 @@ static void x86_cpu_reset(CPUState *s)
|
||||
if (kvm_enabled()) {
|
||||
kvm_arch_reset_vcpu(cpu);
|
||||
}
|
||||
else if (hvf_enabled()) {
|
||||
hvf_reset_vcpu(s);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -3300,6 +3339,7 @@ APICCommonClass *apic_get_class(void)
|
||||
{
|
||||
const char *apic_type = "apic";
|
||||
|
||||
/* TODO: in-kernel irqchip for hvf */
|
||||
if (kvm_apic_in_kernel()) {
|
||||
apic_type = "kvm-apic";
|
||||
} else if (xen_enabled()) {
|
||||
@@ -3613,7 +3653,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
Error *local_err = NULL;
|
||||
static bool ht_warned;
|
||||
|
||||
if (xcc->kvm_required && !kvm_enabled()) {
|
||||
if (xcc->host_cpuid_required && !accel_uses_host_cpuid()) {
|
||||
char *name = x86_cpu_class_get_model_name(xcc);
|
||||
error_setg(&local_err, "CPU model '%s' requires KVM", name);
|
||||
g_free(name);
|
||||
@@ -3635,7 +3675,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
x86_cpu_report_filtered_features(cpu);
|
||||
if (cpu->enforce_cpuid) {
|
||||
error_setg(&local_err,
|
||||
kvm_enabled() ?
|
||||
accel_uses_host_cpuid() ?
|
||||
"Host doesn't support requested features" :
|
||||
"TCG doesn't support requested features");
|
||||
goto out;
|
||||
@@ -3658,7 +3698,7 @@ static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
|
||||
* consumer AMD devices but nothing else.
|
||||
*/
|
||||
if (env->features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
|
||||
if (kvm_enabled()) {
|
||||
if (accel_uses_host_cpuid()) {
|
||||
uint32_t host_phys_bits = x86_host_phys_bits();
|
||||
static bool warned;
|
||||
|
||||
@@ -4272,7 +4312,7 @@ static void x86_cpu_register_types(void)
|
||||
}
|
||||
type_register_static(&max_x86_cpu_type_info);
|
||||
type_register_static(&x86_base_cpu_type_info);
|
||||
#ifdef CONFIG_KVM
|
||||
#if defined(CONFIG_KVM) || defined(CONFIG_HVF)
|
||||
type_register_static(&host_x86_cpu_type_info);
|
||||
#endif
|
||||
}
|
||||
|
||||
+69
-28
@@ -30,6 +30,8 @@
|
||||
#define TARGET_LONG_BITS 32
|
||||
#endif
|
||||
|
||||
#include "exec/cpu-defs.h"
|
||||
|
||||
/* The x86 has a strong memory model with some store-after-load re-ordering */
|
||||
#define TCG_GUEST_DEFAULT_MO (TCG_MO_ALL & ~TCG_MO_ST_LD)
|
||||
|
||||
@@ -50,48 +52,64 @@
|
||||
|
||||
#define CPUArchState struct CPUX86State
|
||||
|
||||
#include "exec/cpu-defs.h"
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
#include "fpu/softfloat.h"
|
||||
#endif
|
||||
|
||||
#define R_EAX 0
|
||||
#define R_ECX 1
|
||||
#define R_EDX 2
|
||||
#define R_EBX 3
|
||||
#define R_ESP 4
|
||||
#define R_EBP 5
|
||||
#define R_ESI 6
|
||||
#define R_EDI 7
|
||||
enum {
|
||||
R_EAX = 0,
|
||||
R_ECX = 1,
|
||||
R_EDX = 2,
|
||||
R_EBX = 3,
|
||||
R_ESP = 4,
|
||||
R_EBP = 5,
|
||||
R_ESI = 6,
|
||||
R_EDI = 7,
|
||||
R_R8 = 8,
|
||||
R_R9 = 9,
|
||||
R_R10 = 10,
|
||||
R_R11 = 11,
|
||||
R_R12 = 12,
|
||||
R_R13 = 13,
|
||||
R_R14 = 14,
|
||||
R_R15 = 15,
|
||||
|
||||
#define R_AL 0
|
||||
#define R_CL 1
|
||||
#define R_DL 2
|
||||
#define R_BL 3
|
||||
#define R_AH 4
|
||||
#define R_CH 5
|
||||
#define R_DH 6
|
||||
#define R_BH 7
|
||||
R_AL = 0,
|
||||
R_CL = 1,
|
||||
R_DL = 2,
|
||||
R_BL = 3,
|
||||
R_AH = 4,
|
||||
R_CH = 5,
|
||||
R_DH = 6,
|
||||
R_BH = 7,
|
||||
};
|
||||
|
||||
#define R_ES 0
|
||||
#define R_CS 1
|
||||
#define R_SS 2
|
||||
#define R_DS 3
|
||||
#define R_FS 4
|
||||
#define R_GS 5
|
||||
typedef enum X86Seg {
|
||||
R_ES = 0,
|
||||
R_CS = 1,
|
||||
R_SS = 2,
|
||||
R_DS = 3,
|
||||
R_FS = 4,
|
||||
R_GS = 5,
|
||||
R_LDTR = 6,
|
||||
R_TR = 7,
|
||||
} X86Seg;
|
||||
|
||||
/* segment descriptor fields */
|
||||
#define DESC_G_MASK (1 << 23)
|
||||
#define DESC_G_SHIFT 23
|
||||
#define DESC_G_MASK (1 << DESC_G_SHIFT)
|
||||
#define DESC_B_SHIFT 22
|
||||
#define DESC_B_MASK (1 << DESC_B_SHIFT)
|
||||
#define DESC_L_SHIFT 21 /* x86_64 only : 64 bit code segment */
|
||||
#define DESC_L_MASK (1 << DESC_L_SHIFT)
|
||||
#define DESC_AVL_MASK (1 << 20)
|
||||
#define DESC_P_MASK (1 << 15)
|
||||
#define DESC_AVL_SHIFT 20
|
||||
#define DESC_AVL_MASK (1 << DESC_AVL_SHIFT)
|
||||
#define DESC_P_SHIFT 15
|
||||
#define DESC_P_MASK (1 << DESC_P_SHIFT)
|
||||
#define DESC_DPL_SHIFT 13
|
||||
#define DESC_DPL_MASK (3 << DESC_DPL_SHIFT)
|
||||
#define DESC_S_MASK (1 << 12)
|
||||
#define DESC_S_SHIFT 12
|
||||
#define DESC_S_MASK (1 << DESC_S_SHIFT)
|
||||
#define DESC_TYPE_SHIFT 8
|
||||
#define DESC_TYPE_MASK (15 << DESC_TYPE_SHIFT)
|
||||
#define DESC_A_MASK (1 << 8)
|
||||
@@ -631,6 +649,7 @@ typedef uint32_t FeatureWordArray[FEATURE_WORDS];
|
||||
#define CPUID_7_0_EBX_AVX512BW (1U << 30) /* AVX-512 Byte and Word Instructions */
|
||||
#define CPUID_7_0_EBX_AVX512VL (1U << 31) /* AVX-512 Vector Length Extensions */
|
||||
|
||||
#define CPUID_7_0_ECX_AVX512BMI (1U << 1)
|
||||
#define CPUID_7_0_ECX_VBMI (1U << 1) /* AVX-512 Vector Byte Manipulation Instrs */
|
||||
#define CPUID_7_0_ECX_UMIP (1U << 2)
|
||||
#define CPUID_7_0_ECX_PKU (1U << 3)
|
||||
@@ -812,6 +831,20 @@ typedef struct SegmentCache {
|
||||
float64 _d_##n[(bits)/64]; \
|
||||
}
|
||||
|
||||
typedef union {
|
||||
uint8_t _b[16];
|
||||
uint16_t _w[8];
|
||||
uint32_t _l[4];
|
||||
uint64_t _q[2];
|
||||
} XMMReg;
|
||||
|
||||
typedef union {
|
||||
uint8_t _b[32];
|
||||
uint16_t _w[16];
|
||||
uint32_t _l[8];
|
||||
uint64_t _q[4];
|
||||
} YMMReg;
|
||||
|
||||
typedef MMREG_UNION(ZMMReg, 512) ZMMReg;
|
||||
typedef MMREG_UNION(MMXReg, 64) MMXReg;
|
||||
|
||||
@@ -1047,7 +1080,11 @@ typedef struct CPUX86State {
|
||||
ZMMReg xmm_t0;
|
||||
MMXReg mmx_t0;
|
||||
|
||||
XMMReg ymmh_regs[CPU_NB_REGS];
|
||||
|
||||
uint64_t opmask_regs[NB_OPMASK_REGS];
|
||||
YMMReg zmmh_regs[CPU_NB_REGS];
|
||||
ZMMReg hi16_zmm_regs[CPU_NB_REGS];
|
||||
|
||||
/* sysenter registers */
|
||||
uint32_t sysenter_cs;
|
||||
@@ -1172,11 +1209,15 @@ typedef struct CPUX86State {
|
||||
int32_t interrupt_injected;
|
||||
uint8_t soft_interrupt;
|
||||
uint8_t has_error_code;
|
||||
uint32_t ins_len;
|
||||
uint32_t sipi_vector;
|
||||
bool tsc_valid;
|
||||
int64_t tsc_khz;
|
||||
int64_t user_tsc_khz; /* for sanity check only */
|
||||
void *kvm_xsave_buf;
|
||||
#if defined(CONFIG_HVF)
|
||||
HVFX86EmulatorState *hvf_emul;
|
||||
#endif
|
||||
|
||||
uint64_t mcg_cap;
|
||||
uint64_t mcg_ctl;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-y += hvf.o
|
||||
obj-y += x86.o x86_cpuid.o x86_decode.o x86_descr.o x86_emu.o x86_flags.o x86_mmu.o x86hvf.o x86_task.o
|
||||
@@ -0,0 +1,7 @@
|
||||
# OS X Hypervisor.framework support in QEMU
|
||||
|
||||
These sources (and ../hvf-all.c) are adapted from Veertu Inc's vdhh (Veertu Desktop Hosted Hypervisor) (last known location: https://github.com/veertuinc/vdhh) with some minor changes, the most significant of which were:
|
||||
|
||||
1. Adapt to our current QEMU's `CPUState` structure and `address_space_rw` API; many struct members have been moved around (emulated x86 state, kvm_xsave_buf) due to historical differences + QEMU needing to handle more emulation targets.
|
||||
2. Removal of `apic_page` and hyperv-related functionality.
|
||||
3. More relaxed use of `qemu_mutex_lock_iothread`.
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* QEMU Hypervisor.framework (HVF) support
|
||||
*
|
||||
* Copyright 2017 Google Inc
|
||||
*
|
||||
* Adapted from target-i386/hax-i386.h:
|
||||
* Copyright (c) 2011 Intel Corporation
|
||||
* Written by:
|
||||
* Jiang Yunhong<yunhong.jiang@intel.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _HVF_I386_H
|
||||
#define _HVF_I386_H
|
||||
|
||||
#include "sysemu/hvf.h"
|
||||
#include "cpu.h"
|
||||
#include "x86.h"
|
||||
|
||||
#define HVF_MAX_VCPU 0x10
|
||||
#define MAX_VM_ID 0x40
|
||||
#define MAX_VCPU_ID 0x40
|
||||
|
||||
extern struct hvf_state hvf_global;
|
||||
|
||||
struct hvf_vm {
|
||||
int id;
|
||||
struct hvf_vcpu_state *vcpus[HVF_MAX_VCPU];
|
||||
};
|
||||
|
||||
struct hvf_state {
|
||||
uint32_t version;
|
||||
struct hvf_vm *vm;
|
||||
uint64_t mem_quota;
|
||||
};
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
/* Functions exported to host specific mode */
|
||||
|
||||
/* Host specific functions */
|
||||
int hvf_inject_interrupt(CPUArchState *env, int vector);
|
||||
int hvf_vcpu_run(struct hvf_vcpu_state *vcpu);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2016 Veertu Inc,
|
||||
* Copyright (C) 2017 Google Inc,
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef HVF_PANIC_H
|
||||
#define HVF_PANIC_H
|
||||
|
||||
#define VM_PANIC(x) {\
|
||||
printf("%s\n", x); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define VM_PANIC_ON(x) {\
|
||||
if (x) { \
|
||||
printf("%s\n", #x); \
|
||||
abort(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define VM_PANIC_EX(...) {\
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
}
|
||||
|
||||
#define VM_PANIC_ON_EX(x, ...) {\
|
||||
if (x) { \
|
||||
printf(__VA_ARGS__); \
|
||||
abort(); \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,374 @@
|
||||
/*-
|
||||
* Copyright (c) 2011 NetApp, Inc.
|
||||
* 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 NETAPP, INC ``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 NETAPP, INC 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$
|
||||
*/
|
||||
|
||||
#ifndef _VMCS_H_
|
||||
#define _VMCS_H_
|
||||
|
||||
#include <Hypervisor/hv.h>
|
||||
#include <Hypervisor/hv_vmx.h>
|
||||
|
||||
#define VMCS_INITIAL 0xffffffffffffffff
|
||||
|
||||
#define VMCS_IDENT(encoding) ((encoding) | 0x80000000)
|
||||
/*
|
||||
* VMCS field encodings from Appendix H, Intel Architecture Manual Vol3B.
|
||||
*/
|
||||
#define VMCS_INVALID_ENCODING 0xffffffff
|
||||
|
||||
/* 16-bit control fields */
|
||||
#define VMCS_VPID 0x00000000
|
||||
#define VMCS_PIR_VECTOR 0x00000002
|
||||
|
||||
/* 16-bit guest-state fields */
|
||||
#define VMCS_GUEST_ES_SELECTOR 0x00000800
|
||||
#define VMCS_GUEST_CS_SELECTOR 0x00000802
|
||||
#define VMCS_GUEST_SS_SELECTOR 0x00000804
|
||||
#define VMCS_GUEST_DS_SELECTOR 0x00000806
|
||||
#define VMCS_GUEST_FS_SELECTOR 0x00000808
|
||||
#define VMCS_GUEST_GS_SELECTOR 0x0000080A
|
||||
#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C
|
||||
#define VMCS_GUEST_TR_SELECTOR 0x0000080E
|
||||
#define VMCS_GUEST_INTR_STATUS 0x00000810
|
||||
|
||||
/* 16-bit host-state fields */
|
||||
#define VMCS_HOST_ES_SELECTOR 0x00000C00
|
||||
#define VMCS_HOST_CS_SELECTOR 0x00000C02
|
||||
#define VMCS_HOST_SS_SELECTOR 0x00000C04
|
||||
#define VMCS_HOST_DS_SELECTOR 0x00000C06
|
||||
#define VMCS_HOST_FS_SELECTOR 0x00000C08
|
||||
#define VMCS_HOST_GS_SELECTOR 0x00000C0A
|
||||
#define VMCS_HOST_TR_SELECTOR 0x00000C0C
|
||||
|
||||
/* 64-bit control fields */
|
||||
#define VMCS_IO_BITMAP_A 0x00002000
|
||||
#define VMCS_IO_BITMAP_B 0x00002002
|
||||
#define VMCS_MSR_BITMAP 0x00002004
|
||||
#define VMCS_EXIT_MSR_STORE 0x00002006
|
||||
#define VMCS_EXIT_MSR_LOAD 0x00002008
|
||||
#define VMCS_ENTRY_MSR_LOAD 0x0000200A
|
||||
#define VMCS_EXECUTIVE_VMCS 0x0000200C
|
||||
#define VMCS_TSC_OFFSET 0x00002010
|
||||
#define VMCS_VIRTUAL_APIC 0x00002012
|
||||
#define VMCS_APIC_ACCESS 0x00002014
|
||||
#define VMCS_PIR_DESC 0x00002016
|
||||
#define VMCS_EPTP 0x0000201A
|
||||
#define VMCS_EOI_EXIT0 0x0000201C
|
||||
#define VMCS_EOI_EXIT1 0x0000201E
|
||||
#define VMCS_EOI_EXIT2 0x00002020
|
||||
#define VMCS_EOI_EXIT3 0x00002022
|
||||
#define VMCS_EOI_EXIT(vector) (VMCS_EOI_EXIT0 + ((vector) / 64) * 2)
|
||||
|
||||
/* 64-bit read-only fields */
|
||||
#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400
|
||||
|
||||
/* 64-bit guest-state fields */
|
||||
#define VMCS_LINK_POINTER 0x00002800
|
||||
#define VMCS_GUEST_IA32_DEBUGCTL 0x00002802
|
||||
#define VMCS_GUEST_IA32_PAT 0x00002804
|
||||
#define VMCS_GUEST_IA32_EFER 0x00002806
|
||||
#define VMCS_GUEST_IA32_PERF_GLOBAL_CTRL 0x00002808
|
||||
#define VMCS_GUEST_PDPTE0 0x0000280A
|
||||
#define VMCS_GUEST_PDPTE1 0x0000280C
|
||||
#define VMCS_GUEST_PDPTE2 0x0000280E
|
||||
#define VMCS_GUEST_PDPTE3 0x00002810
|
||||
|
||||
/* 64-bit host-state fields */
|
||||
#define VMCS_HOST_IA32_PAT 0x00002C00
|
||||
#define VMCS_HOST_IA32_EFER 0x00002C02
|
||||
#define VMCS_HOST_IA32_PERF_GLOBAL_CTRL 0x00002C04
|
||||
|
||||
/* 32-bit control fields */
|
||||
#define VMCS_PIN_BASED_CTLS 0x00004000
|
||||
#define VMCS_PRI_PROC_BASED_CTLS 0x00004002
|
||||
#define VMCS_EXCEPTION_BITMAP 0x00004004
|
||||
#define VMCS_PF_ERROR_MASK 0x00004006
|
||||
#define VMCS_PF_ERROR_MATCH 0x00004008
|
||||
#define VMCS_CR3_TARGET_COUNT 0x0000400A
|
||||
#define VMCS_EXIT_CTLS 0x0000400C
|
||||
#define VMCS_EXIT_MSR_STORE_COUNT 0x0000400E
|
||||
#define VMCS_EXIT_MSR_LOAD_COUNT 0x00004010
|
||||
#define VMCS_ENTRY_CTLS 0x00004012
|
||||
#define VMCS_ENTRY_MSR_LOAD_COUNT 0x00004014
|
||||
#define VMCS_ENTRY_INTR_INFO 0x00004016
|
||||
#define VMCS_ENTRY_EXCEPTION_ERROR 0x00004018
|
||||
#define VMCS_ENTRY_INST_LENGTH 0x0000401A
|
||||
#define VMCS_TPR_THRESHOLD 0x0000401C
|
||||
#define VMCS_SEC_PROC_BASED_CTLS 0x0000401E
|
||||
#define VMCS_PLE_GAP 0x00004020
|
||||
#define VMCS_PLE_WINDOW 0x00004022
|
||||
|
||||
/* 32-bit read-only data fields */
|
||||
#define VMCS_INSTRUCTION_ERROR 0x00004400
|
||||
#define VMCS_EXIT_REASON 0x00004402
|
||||
#define VMCS_EXIT_INTR_INFO 0x00004404
|
||||
#define VMCS_EXIT_INTR_ERRCODE 0x00004406
|
||||
#define VMCS_IDT_VECTORING_INFO 0x00004408
|
||||
#define VMCS_IDT_VECTORING_ERROR 0x0000440A
|
||||
#define VMCS_EXIT_INSTRUCTION_LENGTH 0x0000440C
|
||||
#define VMCS_EXIT_INSTRUCTION_INFO 0x0000440E
|
||||
|
||||
/* 32-bit guest-state fields */
|
||||
#define VMCS_GUEST_ES_LIMIT 0x00004800
|
||||
#define VMCS_GUEST_CS_LIMIT 0x00004802
|
||||
#define VMCS_GUEST_SS_LIMIT 0x00004804
|
||||
#define VMCS_GUEST_DS_LIMIT 0x00004806
|
||||
#define VMCS_GUEST_FS_LIMIT 0x00004808
|
||||
#define VMCS_GUEST_GS_LIMIT 0x0000480A
|
||||
#define VMCS_GUEST_LDTR_LIMIT 0x0000480C
|
||||
#define VMCS_GUEST_TR_LIMIT 0x0000480E
|
||||
#define VMCS_GUEST_GDTR_LIMIT 0x00004810
|
||||
#define VMCS_GUEST_IDTR_LIMIT 0x00004812
|
||||
#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814
|
||||
#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816
|
||||
#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818
|
||||
#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A
|
||||
#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C
|
||||
#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E
|
||||
#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820
|
||||
#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822
|
||||
#define VMCS_GUEST_INTERRUPTIBILITY 0x00004824
|
||||
#define VMCS_GUEST_ACTIVITY 0x00004826
|
||||
#define VMCS_GUEST_SMBASE 0x00004828
|
||||
#define VMCS_GUEST_IA32_SYSENTER_CS 0x0000482A
|
||||
#define VMCS_PREEMPTION_TIMER_VALUE 0x0000482E
|
||||
|
||||
/* 32-bit host state fields */
|
||||
#define VMCS_HOST_IA32_SYSENTER_CS 0x00004C00
|
||||
|
||||
/* Natural Width control fields */
|
||||
#define VMCS_CR0_MASK 0x00006000
|
||||
#define VMCS_CR4_MASK 0x00006002
|
||||
#define VMCS_CR0_SHADOW 0x00006004
|
||||
#define VMCS_CR4_SHADOW 0x00006006
|
||||
#define VMCS_CR3_TARGET0 0x00006008
|
||||
#define VMCS_CR3_TARGET1 0x0000600A
|
||||
#define VMCS_CR3_TARGET2 0x0000600C
|
||||
#define VMCS_CR3_TARGET3 0x0000600E
|
||||
|
||||
/* Natural Width read-only fields */
|
||||
#define VMCS_EXIT_QUALIFICATION 0x00006400
|
||||
#define VMCS_IO_RCX 0x00006402
|
||||
#define VMCS_IO_RSI 0x00006404
|
||||
#define VMCS_IO_RDI 0x00006406
|
||||
#define VMCS_IO_RIP 0x00006408
|
||||
#define VMCS_GUEST_LINEAR_ADDRESS 0x0000640A
|
||||
|
||||
/* Natural Width guest-state fields */
|
||||
#define VMCS_GUEST_CR0 0x00006800
|
||||
#define VMCS_GUEST_CR3 0x00006802
|
||||
#define VMCS_GUEST_CR4 0x00006804
|
||||
#define VMCS_GUEST_ES_BASE 0x00006806
|
||||
#define VMCS_GUEST_CS_BASE 0x00006808
|
||||
#define VMCS_GUEST_SS_BASE 0x0000680A
|
||||
#define VMCS_GUEST_DS_BASE 0x0000680C
|
||||
#define VMCS_GUEST_FS_BASE 0x0000680E
|
||||
#define VMCS_GUEST_GS_BASE 0x00006810
|
||||
#define VMCS_GUEST_LDTR_BASE 0x00006812
|
||||
#define VMCS_GUEST_TR_BASE 0x00006814
|
||||
#define VMCS_GUEST_GDTR_BASE 0x00006816
|
||||
#define VMCS_GUEST_IDTR_BASE 0x00006818
|
||||
#define VMCS_GUEST_DR7 0x0000681A
|
||||
#define VMCS_GUEST_RSP 0x0000681C
|
||||
#define VMCS_GUEST_RIP 0x0000681E
|
||||
#define VMCS_GUEST_RFLAGS 0x00006820
|
||||
#define VMCS_GUEST_PENDING_DBG_EXCEPTIONS 0x00006822
|
||||
#define VMCS_GUEST_IA32_SYSENTER_ESP 0x00006824
|
||||
#define VMCS_GUEST_IA32_SYSENTER_EIP 0x00006826
|
||||
|
||||
/* Natural Width host-state fields */
|
||||
#define VMCS_HOST_CR0 0x00006C00
|
||||
#define VMCS_HOST_CR3 0x00006C02
|
||||
#define VMCS_HOST_CR4 0x00006C04
|
||||
#define VMCS_HOST_FS_BASE 0x00006C06
|
||||
#define VMCS_HOST_GS_BASE 0x00006C08
|
||||
#define VMCS_HOST_TR_BASE 0x00006C0A
|
||||
#define VMCS_HOST_GDTR_BASE 0x00006C0C
|
||||
#define VMCS_HOST_IDTR_BASE 0x00006C0E
|
||||
#define VMCS_HOST_IA32_SYSENTER_ESP 0x00006C10
|
||||
#define VMCS_HOST_IA32_SYSENTER_EIP 0x00006C12
|
||||
#define VMCS_HOST_RSP 0x00006C14
|
||||
#define VMCS_HOST_RIP 0x00006c16
|
||||
|
||||
/*
|
||||
* VM instruction error numbers
|
||||
*/
|
||||
#define VMRESUME_WITH_NON_LAUNCHED_VMCS 5
|
||||
|
||||
/*
|
||||
* VMCS exit reasons
|
||||
*/
|
||||
#define EXIT_REASON_EXCEPTION 0
|
||||
#define EXIT_REASON_EXT_INTR 1
|
||||
#define EXIT_REASON_TRIPLE_FAULT 2
|
||||
#define EXIT_REASON_INIT 3
|
||||
#define EXIT_REASON_SIPI 4
|
||||
#define EXIT_REASON_IO_SMI 5
|
||||
#define EXIT_REASON_SMI 6
|
||||
#define EXIT_REASON_INTR_WINDOW 7
|
||||
#define EXIT_REASON_NMI_WINDOW 8
|
||||
#define EXIT_REASON_TASK_SWITCH 9
|
||||
#define EXIT_REASON_CPUID 10
|
||||
#define EXIT_REASON_GETSEC 11
|
||||
#define EXIT_REASON_HLT 12
|
||||
#define EXIT_REASON_INVD 13
|
||||
#define EXIT_REASON_INVLPG 14
|
||||
#define EXIT_REASON_RDPMC 15
|
||||
#define EXIT_REASON_RDTSC 16
|
||||
#define EXIT_REASON_RSM 17
|
||||
#define EXIT_REASON_VMCALL 18
|
||||
#define EXIT_REASON_VMCLEAR 19
|
||||
#define EXIT_REASON_VMLAUNCH 20
|
||||
#define EXIT_REASON_VMPTRLD 21
|
||||
#define EXIT_REASON_VMPTRST 22
|
||||
#define EXIT_REASON_VMREAD 23
|
||||
#define EXIT_REASON_VMRESUME 24
|
||||
#define EXIT_REASON_VMWRITE 25
|
||||
#define EXIT_REASON_VMXOFF 26
|
||||
#define EXIT_REASON_VMXON 27
|
||||
#define EXIT_REASON_CR_ACCESS 28
|
||||
#define EXIT_REASON_DR_ACCESS 29
|
||||
#define EXIT_REASON_INOUT 30
|
||||
#define EXIT_REASON_RDMSR 31
|
||||
#define EXIT_REASON_WRMSR 32
|
||||
#define EXIT_REASON_INVAL_VMCS 33
|
||||
#define EXIT_REASON_INVAL_MSR 34
|
||||
#define EXIT_REASON_MWAIT 36
|
||||
#define EXIT_REASON_MTF 37
|
||||
#define EXIT_REASON_MONITOR 39
|
||||
#define EXIT_REASON_PAUSE 40
|
||||
#define EXIT_REASON_MCE_DURING_ENTR 41
|
||||
#define EXIT_REASON_TPR 43
|
||||
#define EXIT_REASON_APIC_ACCESS 44
|
||||
#define EXIT_REASON_VIRTUALIZED_EOI 45
|
||||
#define EXIT_REASON_GDTR_IDTR 46
|
||||
#define EXIT_REASON_LDTR_TR 47
|
||||
#define EXIT_REASON_EPT_FAULT 48
|
||||
#define EXIT_REASON_EPT_MISCONFIG 49
|
||||
#define EXIT_REASON_INVEPT 50
|
||||
#define EXIT_REASON_RDTSCP 51
|
||||
#define EXIT_REASON_VMX_PREEMPT 52
|
||||
#define EXIT_REASON_INVVPID 53
|
||||
#define EXIT_REASON_WBINVD 54
|
||||
#define EXIT_REASON_XSETBV 55
|
||||
#define EXIT_REASON_APIC_WRITE 56
|
||||
|
||||
/*
|
||||
* NMI unblocking due to IRET.
|
||||
*
|
||||
* Applies to VM-exits due to hardware exception or EPT fault.
|
||||
*/
|
||||
#define EXIT_QUAL_NMIUDTI (1 << 12)
|
||||
/*
|
||||
* VMCS interrupt information fields
|
||||
*/
|
||||
#define VMCS_INTR_VALID (1U << 31)
|
||||
#define VMCS_INTR_T_MASK 0x700 /* Interruption-info type */
|
||||
#define VMCS_INTR_T_HWINTR (0 << 8)
|
||||
#define VMCS_INTR_T_NMI (2 << 8)
|
||||
#define VMCS_INTR_T_HWEXCEPTION (3 << 8)
|
||||
#define VMCS_INTR_T_SWINTR (4 << 8)
|
||||
#define VMCS_INTR_T_PRIV_SWEXCEPTION (5 << 8)
|
||||
#define VMCS_INTR_T_SWEXCEPTION (6 << 8)
|
||||
#define VMCS_INTR_DEL_ERRCODE (1 << 11)
|
||||
|
||||
/*
|
||||
* VMCS IDT-Vectoring information fields
|
||||
*/
|
||||
#define VMCS_IDT_VEC_VECNUM 0xFF
|
||||
#define VMCS_IDT_VEC_VALID (1U << 31)
|
||||
#define VMCS_IDT_VEC_TYPE 0x700
|
||||
#define VMCS_IDT_VEC_ERRCODE_VALID (1U << 11)
|
||||
#define VMCS_IDT_VEC_HWINTR (0 << 8)
|
||||
#define VMCS_IDT_VEC_NMI (2 << 8)
|
||||
#define VMCS_IDT_VEC_HWEXCEPTION (3 << 8)
|
||||
#define VMCS_IDT_VEC_SWINTR (4 << 8)
|
||||
#define VMCS_IDT_VEC_PRIV_SWEXCEPTION (5 << 8)
|
||||
#define VMCS_IDT_VEC_SWEXCEPTION (6 << 8)
|
||||
|
||||
/*
|
||||
* VMCS Guest interruptibility field
|
||||
*/
|
||||
#define VMCS_INTERRUPTIBILITY_STI_BLOCKING (1 << 0)
|
||||
#define VMCS_INTERRUPTIBILITY_MOVSS_BLOCKING (1 << 1)
|
||||
#define VMCS_INTERRUPTIBILITY_SMI_BLOCKING (1 << 2)
|
||||
#define VMCS_INTERRUPTIBILITY_NMI_BLOCKING (1 << 3)
|
||||
|
||||
/*
|
||||
* Exit qualification for EXIT_REASON_INVAL_VMCS
|
||||
*/
|
||||
#define EXIT_QUAL_NMI_WHILE_STI_BLOCKING 3
|
||||
|
||||
/*
|
||||
* Exit qualification for EPT violation
|
||||
*/
|
||||
#define EPT_VIOLATION_DATA_READ (1UL << 0)
|
||||
#define EPT_VIOLATION_DATA_WRITE (1UL << 1)
|
||||
#define EPT_VIOLATION_INST_FETCH (1UL << 2)
|
||||
#define EPT_VIOLATION_GPA_READABLE (1UL << 3)
|
||||
#define EPT_VIOLATION_GPA_WRITEABLE (1UL << 4)
|
||||
#define EPT_VIOLATION_GPA_EXECUTABLE (1UL << 5)
|
||||
#define EPT_VIOLATION_GLA_VALID (1UL << 7)
|
||||
#define EPT_VIOLATION_XLAT_VALID (1UL << 8)
|
||||
|
||||
/*
|
||||
* Exit qualification for APIC-access VM exit
|
||||
*/
|
||||
#define APIC_ACCESS_OFFSET(qual) ((qual) & 0xFFF)
|
||||
#define APIC_ACCESS_TYPE(qual) (((qual) >> 12) & 0xF)
|
||||
|
||||
/*
|
||||
* Exit qualification for APIC-write VM exit
|
||||
*/
|
||||
#define APIC_WRITE_OFFSET(qual) ((qual) & 0xFFF)
|
||||
|
||||
#define VMCS_PIN_BASED_CTLS_EXTINT (1 << 0)
|
||||
#define VMCS_PIN_BASED_CTLS_NMI (1 << 3)
|
||||
#define VMCS_PIN_BASED_CTLS_VNMI (1 << 5)
|
||||
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_INT_WINDOW_EXITING (1 << 2)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_TSC_OFFSET (1 << 3)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_HLT (1 << 7)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_MWAIT (1 << 10)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_TSC (1 << 12)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_CR8_LOAD (1 << 19)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_CR8_STORE (1 << 20)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_TPR_SHADOW (1 << 21)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_NMI_WINDOW_EXITING (1 << 22)
|
||||
#define VMCS_PRI_PROC_BASED_CTLS_SEC_CONTROL (1 << 31)
|
||||
|
||||
#define VMCS_PRI_PROC_BASED2_CTLS_APIC_ACCESSES (1 << 0)
|
||||
#define VMCS_PRI_PROC_BASED2_CTLS_X2APIC (1 << 4)
|
||||
|
||||
enum task_switch_reason {
|
||||
TSR_CALL,
|
||||
TSR_IRET,
|
||||
TSR_JMP,
|
||||
TSR_IDT_GATE, /* task gate in IDT */
|
||||
};
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user