Commit c97d6d2c authored by Sergio Andres Gomez Del Real's avatar Sergio Andres Gomez Del Real Committed by Paolo Bonzini
Browse files

i386: hvf: add code base from Google's QEMU repository

This file begins tracking the files that will be the code base for HVF
support in QEMU. This code base is part of Google's QEMU version of
their Android emulator, and can be found at
https://android.googlesource.com/platform/external/qemu/+/emu-master-dev

This code is based on Veertu Inc's vdhh (Veertu Desktop Hosted
Hypervisor), found at https://github.com/veertuinc/vdhh

. Everything is
appropriately licensed under GPL v2-or-later, except for the code inside
x86_task.c and x86_task.h, which, deriving from KVM (the Linux kernel),
is licensed GPL v2-only.

This code base already implements a very great deal of functionality,
although Google's version removed from Vertuu's the support for APIC
page and hyperv-related stuff. According to the Android Emulator Release
Notes, Revision 26.1.3 (August 2017), "Hypervisor.framework is now
enabled by default on macOS for 32-bit x86 images to improve performance
and macOS compatibility", although we better use with caution for, as the
same Revision warns us, "If you experience issues with it specifically,
please file a bug report...". The code hasn't seen much update in the
last 5 months, so I think that we can further develop the code with
occasional visiting Google's repository to see if there has been any
update.

On top of Google's code, the following changes were made:

- add code to the configure script to support the --enable-hvf argument.
If the OS is Darwin, it checks for presence of HVF in the system. The
patch also adds strings related to HVF in the file qemu-options.hx.
QEMU will only support the modern syntax style '-M accel=hvf' no enable
hvf; the legacy '-enable-hvf' will not be supported.

- fix styling issues

- add glue code to cpus.c

- move HVFX86EmulatorState field to CPUX86State, changing the
the emulation functions to have a parameter with signature 'CPUX86State *'
instead of 'CPUState *' so we don't have to get the 'env'.

Signed-off-by: default avatarSergio Andres Gomez Del Real <Sergio.G.DelReal@gmail.com>
Message-Id: <20170913090522.4022-2-Sergio.G.DelReal@gmail.com>
Message-Id: <20170913090522.4022-3-Sergio.G.DelReal@gmail.com>
Message-Id: <20170913090522.4022-5-Sergio.G.DelReal@gmail.com>
Message-Id: <20170913090522.4022-6-Sergio.G.DelReal@gmail.com>
Message-Id: <20170905035457.3753-7-Sergio.G.DelReal@gmail.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 2cb9f06e
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
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

accel/stubs/hvf-stub.c

0 → 100644
+31 −0
Original line number Diff line number Diff line
/*
 * 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)
{
}
+38 −0
Original line number Diff line number Diff line
@@ -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
+86 −0
Original line number Diff line number Diff line
@@ -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 {
+1 −0
Original line number Diff line number Diff line
@@ -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;
Loading