Skip to contentSkip to conversation

add support for Hypervisor.framework in QEMU

PATCH In review Sergio Andres Gomez Del Real 2 participants 15 messages Sep 13, 2017 – Oct 3, 2017

lore
Share & tools
lore
#0 lore raw

v4 cover add support for Hypervisor.framework in QEMU

================
Changes in v4:
(1) Use g_new0 instead of g_malloc.
(2) hvf TODO's in cpu.c explained: in-kernel irqchip.
(3) Introduce ins_len field in patch where actually used.
(4) Remove outdated comment "/* Definition of hvf_state is here */"
(5) Treat vcpu_dirty as boolean throughout.
(6) checkpatch.pl patch only does styling changes.
(8) Add comment documenting meaning of -1 returned by apic_get_highest_priority_irr.
(9) Add TODO to move hvf's synchronization functions inside cpu_synchronize_*, along with kvm's and hax's.
================

================
Changes in v3:
(1) Fixed licensing issues in patch 3.
(2) Revert to late adding of compilation rules in Makefile.objs (patch 8/14); files aren't ready to compile earlier.
(3) Make a single patch just for fixing style (patch 4/14).
(4) Fix data type for hvf_fd field.
(5) Add comment that return value of -1 in apic function added in 7/14 means "no interrupt".
================

================
Changes in v2:
(1) Removed legacy option "-enable-hvf" in favor of "-M accel=hvf"
(2) Added missing copyright headers; replace fprintfs for error_report; improved commit description.
(3) Moved patch that adds compilation rules in Makefile.objs right after the patch that adds the new files from Google's repo.
(4) Removed conditional macros from cpus.c and cpu.c
(5) Moved patch that fixes coding style to patch # 3
(6) Fix commit message in apic patch
(7) Squash some commits to avoid code churn
================

The following patchset adds to QEMU the supporting for macOS's native hypervisor, Hypervisor.framework (hvf). The code base is taken from Google's Android emulator at
https://android.googlesource.com/platform/external/qemu/+/emu-master-dev.
Notably missing is support for live migration.

Apart from general code refactoring, some additional features were implemented:
retrieve the set of features supported by host cpu and hvf (cpuid); dirty page tracking for VGA memory area; reimplementation of the event injection mechanism to allow injection of exceptions during vmexits, which is exemplified by the injection of a GP fault when the guest vmexits due to execution of the vmcall instruction; changing the emulator's use of CPUState structure in favor of CPUX86State, so as to in the future remove data structures that are uselessly specific to hvf and unified some of the state between kvm/tcg and hvf.
Some features initially planned to implement that didn't make it include:
page fault handling in the emulator and implementing the dummy_signal to handle the SIG_IPI signal without race conditions. Hopefully these can be implemented in the near future.
Event injection was tested through the eventinj kvm test. The latest Debian and Damn Small Linux images were executed, although by now ways it was an exhaustive testing.

Sergio Andres Gomez Del Real (14):
hvf: add support for Hypervisor.framework in the configure script
hvf: add code base from Google's QEMU repository
hvf: fix licensing issues; isolate task handling code (GPL v2-only)
hvf: run hvf code through checkpatch.pl and fix style issues
hvf: add code to cpus.c and do refactoring in preparation for
compiling
hvf: handle fields from CPUState and CPUX86State
apic: add function to apic that will be used by hvf
hvf: add compilation rules to Makefile.objs
hvf: use new helper functions for put/get xsave
hvf: implement hvf_get_supported_cpuid
hvf: refactor cpuid code
hvf: implement vga dirty page tracking
hvf: refactor event injection code for hvf
hvf: inject General Protection Fault when vmexit through vmcall

 configure                           |   38 +
 cpus.c                              |   89 ++
 hw/intc/apic.c                      |   12 +
 include/hw/i386/apic.h              |    1 +
 include/qom/cpu.h                   |    2 +
 include/sysemu/hvf.h                |  181 +++
 qemu-options.hx                     |   10 +-
 target/i386/Makefile.objs           |    1 +
 target/i386/cpu-qom.h               |    4 +-
 target/i386/cpu.c                   |   80 +-
 target/i386/cpu.h                   |   34 +-
 target/i386/hvf-all.c               |  963 +++++++++++++++
 target/i386/hvf-i386.h              |   50 +
 target/i386/hvf-utils/Makefile.objs |    1 +
 target/i386/hvf-utils/README.md     |    7 +
 target/i386/hvf-utils/vmcs.h        |  371 ++++++
 target/i386/hvf-utils/vmx.h         |  222 ++++
 target/i386/hvf-utils/x86.c         |  184 +++
 target/i386/hvf-utils/x86.h         |  394 +++++++
 target/i386/hvf-utils/x86_cpuid.c   |  417 +++++++
 target/i386/hvf-utils/x86_cpuid.h   |   52 +
 target/i386/hvf-utils/x86_decode.c  | 2186 +++++++++++++++++++++++++++++++++++
 target/i386/hvf-utils/x86_decode.h  |  325 ++++++
 target/i386/hvf-utils/x86_descr.c   |  124 ++
 target/i386/hvf-utils/x86_descr.h   |   55 +
 target/i386/hvf-utils/x86_emu.c     | 1536 ++++++++++++++++++++++++
 target/i386/hvf-utils/x86_emu.h     |   49 +
 target/i386/hvf-utils/x86_flags.c   |  333 ++++++
 target/i386/hvf-utils/x86_flags.h   |  243 ++++
 target/i386/hvf-utils/x86_gen.h     |   53 +
 target/i386/hvf-utils/x86_mmu.c     |  273 +++++
 target/i386/hvf-utils/x86_mmu.h     |   45 +
 target/i386/hvf-utils/x86_task.c    |  201 ++++
 target/i386/hvf-utils/x86_task.h    |   18 +
 target/i386/hvf-utils/x86hvf.c      |  463 ++++++++
 target/i386/hvf-utils/x86hvf.h      |   39 +
 target/i386/kvm.c                   |    2 -
 37 files changed, 9025 insertions(+), 33 deletions(-)
 create mode 100644 include/sysemu/hvf.h
 create mode 100644 target/i386/hvf-all.c
 create mode 100644 target/i386/hvf-i386.h
 create mode 100644 target/i386/hvf-utils/Makefile.objs
 create mode 100644 target/i386/hvf-utils/README.md
 create mode 100644 target/i386/hvf-utils/vmcs.h
 create mode 100644 target/i386/hvf-utils/vmx.h
 create mode 100644 target/i386/hvf-utils/x86.c
 create mode 100644 target/i386/hvf-utils/x86.h
 create mode 100644 target/i386/hvf-utils/x86_cpuid.c
 create mode 100644 target/i386/hvf-utils/x86_cpuid.h
 create mode 100644 target/i386/hvf-utils/x86_decode.c
 create mode 100644 target/i386/hvf-utils/x86_decode.h
 create mode 100644 target/i386/hvf-utils/x86_descr.c
 create mode 100644 target/i386/hvf-utils/x86_descr.h
 create mode 100644 target/i386/hvf-utils/x86_emu.c
 create mode 100644 target/i386/hvf-utils/x86_emu.h
 create mode 100644 target/i386/hvf-utils/x86_flags.c
 create mode 100644 target/i386/hvf-utils/x86_flags.h
 create mode 100644 target/i386/hvf-utils/x86_gen.h
 create mode 100644 target/i386/hvf-utils/x86_mmu.c
 create mode 100644 target/i386/hvf-utils/x86_mmu.h
 create mode 100644 target/i386/hvf-utils/x86_task.c
 create mode 100644 target/i386/hvf-utils/x86_task.h
 create mode 100644 target/i386/hvf-utils/x86hvf.c
 create mode 100644 target/i386/hvf-utils/x86hvf.h
Signature · 1 line
2.14.1
#1 lore raw

PATCH v4 1/14 hvf: add support for Hypervisor.framework in the configure script

This patch adds to the configure script the code 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.

---
 configure       | 38 ++++++++++++++++++++++++++++++++++++++
 qemu-options.hx | 10 +++++-----
 2 files changed, 43 insertions(+), 5 deletions(-)
configure +38 -0
index dd73cce62f..5d9152b80a 100755
@@ -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
 }
@@ -309,6 +321,7 @@ vhost_vsock="no"
 vhost_user=""
 kvm="no"
 hax="no"
+hvf="no"
 rdma=""
 gprof="no"
 debug_tcg="no"
@@ -727,6 +740,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"
@@ -1027,6 +1041,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"
@@ -1499,6 +1517,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
@@ -4900,6 +4919,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
@@ -5356,6 +5390,7 @@ if test "$tcg" = "yes" ; then
     echo "TCG debug enabled $debug_tcg"
     echo "TCG interpreter   $tcg_interpreter"
 fi
+echo "HVF support       $hvf"
 echo "RDMA support      $rdma"
 echo "fdt support       $fdt"
 echo "preadv support    $preadv"
@@ -6388,6 +6423,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
qemu-options.hx +5 -5
index 9f6e2adfff..bcb44420ee 100644
@@ -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
@@ -120,13 +120,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
Signature · 1 line
2.14.1
#2 lore raw

PATCH v4 2/14 hvf: add code base from Google's QEMU repository

In reply to Sergio Andres Gomez Del Real

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.

The code's style isn't aligned to QEMU's standards; this will be fixed in a subsequent patch in this series.
On top of this code base we are implementing the following features: fix the code that passes the cpuid features to the guest; implementing dirty page tracking for vga memory region; reimplementing the event injection mechanism for exception injection and many other minor fixes/refactoring that are documented in their respective patches. It is important to note that this patch still doesn't add rules for compiling these files, because some glue code in cpus.c and other issues need to be handled before the HVF files compile cleanly. This will be done in subsequent patches.

---
 cpus.c                              |   42 +
 include/sysemu/hvf.h                |   99 +++
 target/i386/hvf-all.c               | 1000 +++++++++++++++++++++
 target/i386/hvf-i386.h              |   48 +
 target/i386/hvf-utils/Makefile.objs |    1 +
 target/i386/hvf-utils/README.md     |    7 +
 target/i386/hvf-utils/vmcs.h        |  368 ++++++++
 target/i386/hvf-utils/vmx.h         |  200 +++++
 target/i386/hvf-utils/x86.c         |  174 ++++
 target/i386/hvf-utils/x86.h         |  470 ++++++++++
 target/i386/hvf-utils/x86_cpuid.c   |  270 ++++++
 target/i386/hvf-utils/x86_cpuid.h   |   51 ++
 target/i386/hvf-utils/x86_decode.c  | 1659 +++++++++++++++++++++++++++++++++++
 target/i386/hvf-utils/x86_decode.h  |  314 +++++++
 target/i386/hvf-utils/x86_descr.c   |  124 +++
 target/i386/hvf-utils/x86_descr.h   |   40 +
 target/i386/hvf-utils/x86_emu.c     | 1466 +++++++++++++++++++++++++++++++
 target/i386/hvf-utils/x86_emu.h     |   33 +
 target/i386/hvf-utils/x86_flags.c   |  317 +++++++
 target/i386/hvf-utils/x86_flags.h   |  218 +++++
 target/i386/hvf-utils/x86_gen.h     |   53 ++
 target/i386/hvf-utils/x86_mmu.c     |  254 ++++++
 target/i386/hvf-utils/x86_mmu.h     |   45 +
 target/i386/hvf-utils/x86hvf.c      |  501 +++++++++++
 target/i386/hvf-utils/x86hvf.h      |   36 +
 25 files changed, 7790 insertions(+)
 create mode 100644 include/sysemu/hvf.h
 create mode 100644 target/i386/hvf-all.c
 create mode 100644 target/i386/hvf-i386.h
 create mode 100644 target/i386/hvf-utils/Makefile.objs
 create mode 100644 target/i386/hvf-utils/README.md
 create mode 100644 target/i386/hvf-utils/vmcs.h
 create mode 100644 target/i386/hvf-utils/vmx.h
 create mode 100644 target/i386/hvf-utils/x86.c
 create mode 100644 target/i386/hvf-utils/x86.h
 create mode 100644 target/i386/hvf-utils/x86_cpuid.c
 create mode 100644 target/i386/hvf-utils/x86_cpuid.h
 create mode 100644 target/i386/hvf-utils/x86_decode.c
 create mode 100644 target/i386/hvf-utils/x86_decode.h
 create mode 100644 target/i386/hvf-utils/x86_descr.c
 create mode 100644 target/i386/hvf-utils/x86_descr.h
 create mode 100644 target/i386/hvf-utils/x86_emu.c
 create mode 100644 target/i386/hvf-utils/x86_emu.h
 create mode 100644 target/i386/hvf-utils/x86_flags.c
 create mode 100644 target/i386/hvf-utils/x86_flags.h
 create mode 100644 target/i386/hvf-utils/x86_gen.h
 create mode 100644 target/i386/hvf-utils/x86_mmu.c
 create mode 100644 target/i386/hvf-utils/x86_mmu.h
 create mode 100644 target/i386/hvf-utils/x86hvf.c
 create mode 100644 target/i386/hvf-utils/x86hvf.h
cpus.c +42 -0
index 9bed61eefc..a2cd9dfa5d 100644
@@ -1434,6 +1434,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)
 {
include/sysemu/hvf.h new file +99 -0

99 lines not on this page · raw message

target/i386/hvf-all.c new file +1000 -0

1,000 lines not on this page · raw message

target/i386/hvf-i386.h new file +48 -0

48 lines not on this page · raw message

target/i386/hvf-utils/Makefile.objs new file +1 -0
new file mode 100644
index 0000000000..7df219ad9c
@@ -0,0 +1 @@
+obj-y += x86.o x86_cpuid.o x86_decode.o x86_descr.o x86_emu.o x86_flags.o x86_mmu.o x86hvf.o
target/i386/hvf-utils/README.md new file +7 -0
new file mode 100644
index 0000000000..0d27a0d52b
@@ -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`.
target/i386/hvf-utils/vmcs.h new file +368 -0

368 lines not on this page · raw message

target/i386/hvf-utils/vmx.h new file +200 -0

200 lines not on this page · raw message

target/i386/hvf-utils/x86.c new file +174 -0

174 lines not on this page · raw message

target/i386/hvf-utils/x86.h new file +470 -0

470 lines not on this page · raw message

target/i386/hvf-utils/x86_cpuid.c new file +270 -0

270 lines not on this page · raw message

target/i386/hvf-utils/x86_cpuid.h new file +51 -0

51 lines not on this page · raw message

target/i386/hvf-utils/x86_decode.c new file +1659 -0

264 lines not on this page · raw message

target/i386/hvf-utils/x86_decode.h new file +314 -0

314 lines not on this page · raw message

target/i386/hvf-utils/x86_descr.c new file +124 -0

124 lines not on this page · raw message

target/i386/hvf-utils/x86_descr.h new file +40 -0
new file mode 100644
index 0000000000..78fb1bc420

Lines of this file are not shown. View the raw message.

target/i386/hvf-utils/x86_emu.c new file +1466 -0

1,466 lines not on this page · raw message

target/i386/hvf-utils/x86_emu.h new file +33 -0
new file mode 100644
index 0000000000..42cc5e4296

Lines of this file are not shown. View the raw message.

target/i386/hvf-utils/x86_flags.c new file +317 -0

317 lines not on this page · raw message

target/i386/hvf-utils/x86_flags.h new file +218 -0

218 lines not on this page · raw message

target/i386/hvf-utils/x86_gen.h new file +53 -0

53 lines not on this page · raw message

target/i386/hvf-utils/x86_mmu.c new file +254 -0

254 lines not on this page · raw message

target/i386/hvf-utils/x86_mmu.h new file +45 -0

45 lines not on this page · raw message

target/i386/hvf-utils/x86hvf.c new file +501 -0

501 lines not on this page · raw message

target/i386/hvf-utils/x86hvf.h new file +36 -0
new file mode 100644
index 0000000000..fbc2158a2b

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.14.1

Part of the diff is not shown here. View the raw message.

#3 lore raw

PATCH v4 3/14 hvf: fix licensing issues; isolate task handling code (GPL v2-only)

In reply to Sergio Andres Gomez Del Real

This patch replaces the license header for those files that were either GPL v2-or-v3, or GPL v2-only; the replacing license is GPL v2-or-later. The code for task switching/handling, which is derived from KVM and hence is GPL v2-only, is isolated in the new files (with this license) x86_task.c/.h, and the corresponding compilation rule is added to target/i386/hvf-utils/Makefile.objs.
Note that rules for compiling are still missing from target/i386/Makefile.objs; they will be added later in this patchset.

---
 target/i386/hvf-all.c               | 173 +++----------------------------
 target/i386/hvf-utils/Makefile.objs |   2 +-
 target/i386/hvf-utils/vmx.h         |  14 +--
 target/i386/hvf-utils/x86.c         |  14 +--
 target/i386/hvf-utils/x86.h         |  14 +--
 target/i386/hvf-utils/x86_cpuid.c   |   6 +-
 target/i386/hvf-utils/x86_cpuid.h   |  14 +--
 target/i386/hvf-utils/x86_decode.c  |  14 +--
 target/i386/hvf-utils/x86_decode.h  |  14 +--
 target/i386/hvf-utils/x86_descr.c   |  14 +--
 target/i386/hvf-utils/x86_descr.h   |  14 +--
 target/i386/hvf-utils/x86_emu.c     |  14 +--
 target/i386/hvf-utils/x86_emu.h     |  14 +--
 target/i386/hvf-utils/x86_gen.h     |  14 +--
 target/i386/hvf-utils/x86_mmu.c     |  14 +--
 target/i386/hvf-utils/x86_mmu.h     |  14 +--
 target/i386/hvf-utils/x86_task.c    | 201 ++++++++++++++++++++++++++++++++++++
 target/i386/hvf-utils/x86_task.h    |  18 ++++
 target/i386/hvf-utils/x86hvf.c      |  14 +--
 target/i386/hvf-utils/x86hvf.h      |  14 +--
 20 files changed, 340 insertions(+), 270 deletions(-)
 create mode 100644 target/i386/hvf-utils/x86_task.c
 create mode 100644 target/i386/hvf-utils/x86_task.h
target/i386/hvf-all.c +12 -161
index d5e18faa68..270ec56b8d 100644
@@ -5,15 +5,19 @@
 // Copyright 2017 The Android Open Source Project
 // 
 // QEMU Hypervisor.framework support
-// 
-// This software is licensed under the terms of the GNU General Public
-// License version 2, as published by the Free Software Foundation, and
-// may be copied, distributed, and modified under those terms.
-// 
+//
+// 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 General Public License for more details.
+// 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/>.
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/error-report.h"
@@ -28,6 +32,7 @@
 #include "hvf-utils/x86_decode.h"
 #include "hvf-utils/x86_emu.h"
 #include "hvf-utils/x86_cpuid.h"
+#include "hvf-utils/x86_task.h"
 #include "hvf-utils/x86hvf.h"
 
 #include <Hypervisor/hv.h>
@@ -224,160 +229,6 @@ void update_apic_tpr(CPUState *cpu)
 
 #define VECTORING_INFO_VECTOR_MASK     0xff
 
-// TODO: taskswitch handling
-static void save_state_to_tss32(CPUState *cpu, struct x86_tss_segment32 *tss)
-{
-    /* CR3 and ldt selector are not saved intentionally */
-    tss->eip = EIP(cpu);
-    tss->eflags = EFLAGS(cpu);
-    tss->eax = EAX(cpu);
-    tss->ecx = ECX(cpu);
-    tss->edx = EDX(cpu);
-    tss->ebx = EBX(cpu);
-    tss->esp = ESP(cpu);
-    tss->ebp = EBP(cpu);
-    tss->esi = ESI(cpu);
-    tss->edi = EDI(cpu);
-
-    tss->es = vmx_read_segment_selector(cpu, REG_SEG_ES).sel;
-    tss->cs = vmx_read_segment_selector(cpu, REG_SEG_CS).sel;
-    tss->ss = vmx_read_segment_selector(cpu, REG_SEG_SS).sel;
-    tss->ds = vmx_read_segment_selector(cpu, REG_SEG_DS).sel;
-    tss->fs = vmx_read_segment_selector(cpu, REG_SEG_FS).sel;
-    tss->gs = vmx_read_segment_selector(cpu, REG_SEG_GS).sel;
-}
-
-static void load_state_from_tss32(CPUState *cpu, struct x86_tss_segment32 *tss)
-{
-    wvmcs(cpu->hvf_fd, VMCS_GUEST_CR3, tss->cr3);
-
-    RIP(cpu) = tss->eip;
-    EFLAGS(cpu) = tss->eflags | 2;
-
-    /* General purpose registers */
-    RAX(cpu) = tss->eax;
-    RCX(cpu) = tss->ecx;
-    RDX(cpu) = tss->edx;
-    RBX(cpu) = tss->ebx;
-    RSP(cpu) = tss->esp;
-    RBP(cpu) = tss->ebp;
-    RSI(cpu) = tss->esi;
-    RDI(cpu) = tss->edi;
-
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ldt}}, REG_SEG_LDTR);
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->es}}, REG_SEG_ES);
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->cs}}, REG_SEG_CS);
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ss}}, REG_SEG_SS);
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->ds}}, REG_SEG_DS);
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->fs}}, REG_SEG_FS);
-    vmx_write_segment_selector(cpu, (x68_segment_selector){{tss->gs}}, REG_SEG_GS);
-
-#if 0
-    load_segment(cpu, REG_SEG_LDTR, tss->ldt);
-    load_segment(cpu, REG_SEG_ES, tss->es);
-    load_segment(cpu, REG_SEG_CS, tss->cs);
-    load_segment(cpu, REG_SEG_SS, tss->ss);
-    load_segment(cpu, REG_SEG_DS, tss->ds);
-    load_segment(cpu, REG_SEG_FS, tss->fs);
-    load_segment(cpu, REG_SEG_GS, tss->gs);
-#endif
-}
-
-static int task_switch_32(CPUState *cpu, x68_segment_selector tss_sel, x68_segment_selector old_tss_sel,
-                          uint64_t old_tss_base, struct x86_segment_descriptor *new_desc)
-{
-    struct x86_tss_segment32 tss_seg;
-    uint32_t new_tss_base = x86_segment_base(new_desc);
-    uint32_t eip_offset = offsetof(struct x86_tss_segment32, eip);
-    uint32_t ldt_sel_offset = offsetof(struct x86_tss_segment32, ldt);
-
-    vmx_read_mem(cpu, &tss_seg, old_tss_base, sizeof(tss_seg));
-    save_state_to_tss32(cpu, &tss_seg);
-
-    vmx_write_mem(cpu, old_tss_base + eip_offset, &tss_seg.eip, ldt_sel_offset - eip_offset);
-    vmx_read_mem(cpu, &tss_seg, new_tss_base, sizeof(tss_seg));
-
-    if (old_tss_sel.sel != 0xffff) {
-        tss_seg.prev_tss = old_tss_sel.sel;
-
-        vmx_write_mem(cpu, new_tss_base, &tss_seg.prev_tss, sizeof(tss_seg.prev_tss));
-    }
-    load_state_from_tss32(cpu, &tss_seg);
-    return 0;
-}
-
-static void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel, int reason, bool gate_valid, uint8_t gate, uint64_t gate_type)
-{
-    uint64_t rip = rreg(cpu->hvf_fd, HV_X86_RIP);
-    if (!gate_valid || (gate_type != VMCS_INTR_T_HWEXCEPTION &&
-                        gate_type != VMCS_INTR_T_HWINTR &&
-                        gate_type != VMCS_INTR_T_NMI)) {
-        int ins_len = rvmcs(cpu->hvf_fd, VMCS_EXIT_INSTRUCTION_LENGTH);
-        macvm_set_rip(cpu, rip + ins_len);
-        return;
-    }
-
-    load_regs(cpu);
-
-    struct x86_segment_descriptor curr_tss_desc, next_tss_desc;
-    int ret;
-    x68_segment_selector old_tss_sel = vmx_read_segment_selector(cpu, REG_SEG_TR);
-    uint64_t old_tss_base = vmx_read_segment_base(cpu, REG_SEG_TR);
-    uint32_t desc_limit;
-    struct x86_call_gate task_gate_desc;
-    struct vmx_segment vmx_seg;
-
-    x86_read_segment_descriptor(cpu, &next_tss_desc, tss_sel);
-    x86_read_segment_descriptor(cpu, &curr_tss_desc, old_tss_sel);
-
-    if (reason == TSR_IDT_GATE && gate_valid) {
-        int dpl;
-
-        ret = x86_read_call_gate(cpu, &task_gate_desc, gate);
-
-        dpl = task_gate_desc.dpl;
-        x68_segment_selector cs = vmx_read_segment_selector(cpu, REG_SEG_CS);
-        if (tss_sel.rpl > dpl || cs.rpl > dpl)
-            ;//DPRINTF("emulate_gp");
-    }
-
-    desc_limit = x86_segment_limit(&next_tss_desc);
-    if (!next_tss_desc.p || ((desc_limit < 0x67 && (next_tss_desc.type & 8)) || desc_limit < 0x2b)) {
-        VM_PANIC("emulate_ts");
-    }
-
-    if (reason == TSR_IRET || reason == TSR_JMP) {
-        curr_tss_desc.type &= ~(1 << 1); /* clear busy flag */
-        x86_write_segment_descriptor(cpu, &curr_tss_desc, old_tss_sel);
-    }
-
-    if (reason == TSR_IRET)
-        EFLAGS(cpu) &= ~RFLAGS_NT;
-
-    if (reason != TSR_CALL && reason != TSR_IDT_GATE)
-        old_tss_sel.sel = 0xffff;
-
-    if (reason != TSR_IRET) {
-        next_tss_desc.type |= (1 << 1); /* set busy flag */
-        x86_write_segment_descriptor(cpu, &next_tss_desc, tss_sel);
-    }
-
-    if (next_tss_desc.type & 8)
-        ret = task_switch_32(cpu, tss_sel, old_tss_sel, old_tss_base, &next_tss_desc);
-    else
-        //ret = task_switch_16(cpu, tss_sel, old_tss_sel, old_tss_base, &next_tss_desc);
-        VM_PANIC("task_switch_16");
-
-    macvm_set_cr0(cpu->hvf_fd, rvmcs(cpu->hvf_fd, VMCS_GUEST_CR0) | CR0_TS);
-    x86_segment_descriptor_to_vmx(cpu, tss_sel, &next_tss_desc, &vmx_seg);
-    vmx_write_segment_descriptor(cpu, &vmx_seg, REG_SEG_TR);
-
-    store_regs(cpu);
-
-    hv_vcpu_invalidate_tlb(cpu->hvf_fd);
-    hv_vcpu_flush(cpu->hvf_fd);
-}
-
 static void hvf_handle_interrupt(CPUState * cpu, int mask)
 {
     cpu->interrupt_request |= mask;
target/i386/hvf-utils/Makefile.objs +1 -1
index 7df219ad9c..79d8969ca8 100644
@@ -1 +1 @@
-obj-y += x86.o x86_cpuid.o x86_decode.o x86_descr.o x86_emu.o x86_flags.o x86_mmu.o x86hvf.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
target/i386/hvf-utils/vmx.h +7 -7
index 8a080e6777..e5359df87f 100644
@@ -6,17 +6,17 @@
  * Interfaces to Hypervisor.framework to read/write X86 registers and VMCS.
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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 VMX_H
target/i386/hvf-utils/x86.c +7 -7
index e3db2c9c8b..4debbff31c 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #include "qemu/osdep.h"
target/i386/hvf-utils/x86.h +7 -7
index 5dffdd6568..d433d15ea4 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Veertu Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #pragma once
target/i386/hvf-utils/x86_cpuid.c +3 -3
index e496cf001c..4abeb5c2da 100644
@@ -4,18 +4,18 @@
  *  Copyright (c) 2003 Fabrice Bellard
  *  Copyright (c) 2017 Google Inc.
  *
- * This library is free software; you can redistribute it and/or
+ * 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 library is distributed in the hope that it will be useful,
+ * 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 library; if not, see <http://www.gnu.org/licenses/>.
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  *
  * cpuid
  */
target/i386/hvf-utils/x86_cpuid.h +7 -7
index 02f2f115b0..b84a2f08df 100644
@@ -2,17 +2,17 @@
  * Copyright (C) 2016 Veertu Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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 __CPUID_H__
 #define __CPUID_H__
target/i386/hvf-utils/x86_decode.c +7 -7
index b4d8e22449..8deaab11d2 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #include "qemu/osdep.h"
target/i386/hvf-utils/x86_decode.h +7 -7
index 3a22d7d1a5..fde524f819 100644
@@ -2,17 +2,17 @@
  * Copyright (C) 2016 Veertu Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #pragma once
target/i386/hvf-utils/x86_descr.c +7 -7
index c3b089aaa8..0b9562818f 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #include "qemu/osdep.h"
target/i386/hvf-utils/x86_descr.h +7 -7
index 78fb1bc420..9917585aeb 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #pragma once
target/i386/hvf-utils/x86_emu.c +7 -7
index 8b5efc76f0..76680921d1 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 /////////////////////////////////////////////////////////////////////////
target/i386/hvf-utils/x86_emu.h +7 -7
index 42cc5e4296..f6feff5553 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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 __X86_EMU_H__
 #define __X86_EMU_H__
target/i386/hvf-utils/x86_gen.h +7 -7
index e4340fa244..2045b0e69d 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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 __X86_GEN_H__
 #define __X86_GEN_H__
target/i386/hvf-utils/x86_mmu.c +7 -7
index 00fae735be..95b3d15b94 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 #include "qemu/osdep.h"
 
target/i386/hvf-utils/x86_mmu.h +7 -7
index f794d04b3d..aa0fcfafd2 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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 __X86_MMU_H__
 #define __X86_MMU_H__
target/i386/hvf-utils/x86_task.c new file +201 -0

201 lines not on this page · raw message

target/i386/hvf-utils/x86_task.h new file +18 -0
new file mode 100644
index 0000000000..4f1b188d2e
@@ -0,0 +1,18 @@
+/* This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef HVF_TASK
+#define HVF_TASK
+void vmx_handle_task_switch(CPUState *cpu, x68_segment_selector tss_sel,
+        int reason, bool gate_valid, uint8_t gate, uint64_t gate_type);
+#endif
target/i386/hvf-utils/x86hvf.c +7 -7
index d5668df37f..aba8983dc7 100644
@@ -4,17 +4,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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/>.
  */
 
 #include "qemu/osdep.h"
target/i386/hvf-utils/x86hvf.h +7 -7
index fbc2158a2b..0c5bc3dcf8 100644
@@ -3,17 +3,17 @@
  * Copyright (C) 2017 Google Inc,
  *
  * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 or
- * (at your option) version 3 of the License.
+ * 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 General Public License for more details.
+ * 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 General Public License along
- * with this program; if not, see <http://www.gnu.org/licenses/>.
+ * 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 X86HVF_H
 #define X86HVF_H
Signature · 1 line
2.14.1
#4 lore raw

PATCH v4 4/14 hvf: run hvf code through checkpatch.pl and fix style issues

In reply to Sergio Andres Gomez Del Real

This patch fixes styling issues for the hvf code added in previous patches from Google's repository.

---
 include/sysemu/hvf.h               |   19 +-
 target/i386/hvf-all.c              |  255 ++--
 target/i386/hvf-i386.h             |    2 +-
 target/i386/hvf-utils/vmcs.h       |  484 ++++----
 target/i386/hvf-utils/vmx.h        |   92 +-
 target/i386/hvf-utils/x86.c        |   80 +-
 target/i386/hvf-utils/x86.h        |  110 +-
 target/i386/hvf-utils/x86_cpuid.c  |  337 ++---
 target/i386/hvf-utils/x86_cpuid.h  |    5 +-
 target/i386/hvf-utils/x86_decode.c | 2376 ++++++++++++++++++++++--------------
 target/i386/hvf-utils/x86_decode.h |   18 +-
 target/i386/hvf-utils/x86_descr.h  |   23 +-
 target/i386/hvf-utils/x86_emu.c    | 1318 ++++++++++----------
 target/i386/hvf-utils/x86_flags.c  |   52 +-
 target/i386/hvf-utils/x86_flags.h  |   99 +-
 target/i386/hvf-utils/x86_mmu.c    |   79 +-
 target/i386/hvf-utils/x86_mmu.h    |    6 +-
 target/i386/hvf-utils/x86hvf.c     |   53 +-
 target/i386/hvf-utils/x86hvf.h     |    3 +-
 19 files changed, 3083 insertions(+), 2328 deletions(-)
include/sysemu/hvf.h +9 -10
index 752a78eaa4..d068a95e93 100644
@@ -58,17 +58,16 @@ hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
 
 /* Returns 1 if HVF is available and enabled, 0 otherwise. */
 int hvf_enabled(void);
-
-/* 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. */
+/* 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_ug_platform(void); does not apply to HVF; assume we must be in UG mode
+/* 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);
 
@@ -82,7 +81,7 @@ 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_state(void *opaque); */
 void vmx_reset_vcpu(CPUState *);
 void __hvf_cpu_synchronize_state(CPUState *, run_on_cpu_data);
 void __hvf_cpu_synchronize_post_reset(CPUState *, run_on_cpu_data);
target/i386/hvf-all.c +145 -110

432 lines not on this page · raw message

target/i386/hvf-i386.h +1 -1
index f3f958058a..797718ce34 100644
@@ -41,7 +41,7 @@ struct hvf_state {
 /* Functions exported to host specific mode */
 
 /* Host specific functions */
-int hvf_inject_interrupt(CPUArchState * env, int vector);
+int hvf_inject_interrupt(CPUArchState *env, int vector);
 int hvf_vcpu_run(struct hvf_vcpu_state *vcpu);
 #endif
 
target/i386/hvf-utils/vmcs.h +242 -242

578 lines not on this page · raw message

target/i386/hvf-utils/vmx.h +53 -39

194 lines not on this page · raw message

target/i386/hvf-utils/x86.c +44 -36

136 lines not on this page · raw message

target/i386/hvf-utils/x86.h +58 -52

226 lines not on this page · raw message

target/i386/hvf-utils/x86_cpuid.c +173 -164

361 lines not on this page · raw message

target/i386/hvf-utils/x86_cpuid.h +3 -2
index b84a2f08df..45d27c457a 100644
@@ -44,8 +44,9 @@ struct x86_cpuid {
 
 struct CPUState;
 
-void init_cpuid(struct CPUState* cpu);
-void get_cpuid_func(struct CPUState *cpu, int func, int cnt, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
+void init_cpuid(struct CPUState *cpu);
+void get_cpuid_func(struct CPUState *cpu, int func, int cnt, uint32_t *eax,
+                    uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
 
 #endif /* __CPUID_H__ */
 
target/i386/hvf-utils/x86_decode.c +1451 -925

1,021 lines not on this page · raw message

target/i386/hvf-utils/x86_decode.h +10 -8
index fde524f819..26932b7ff7 100644

Lines of this file are not shown. View the raw message.

target/i386/hvf-utils/x86_descr.h +16 -7
index 9917585aeb..e2d3f75054 100644

Lines of this file are not shown. View the raw message.

target/i386/hvf-utils/x86_emu.c +693 -625

1,318 lines not on this page · raw message

target/i386/hvf-utils/x86_flags.c +34 -18

52 lines not on this page · raw message

target/i386/hvf-utils/x86_flags.h +63 -36

99 lines not on this page · raw message

target/i386/hvf-utils/x86_mmu.c +49 -30

79 lines not on this page · raw message

target/i386/hvf-utils/x86_mmu.h +3 -3
index aa0fcfafd2..b786af280b 100644

Lines of this file are not shown. View the raw message.

target/i386/hvf-utils/x86hvf.c +34 -19

53 lines not on this page · raw message

target/i386/hvf-utils/x86hvf.h +2 -1
index 0c5bc3dcf8..ddc73ed114 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.14.1

Part of the diff is not shown here. View the raw message.

#5 lore raw

PATCH v4 5/14 hvf: add code to cpus.c and do refactoring in preparation for compiling

In reply to Sergio Andres Gomez Del Real

The files originally added from Google's repository in previous patches won't compile cleanly unless some functions are implemented in cpus.c and some other reorganization is done. This patch adds that code and does some general refactoring in preparation for compiling in subsequent patches.

---
 cpus.c                             |  47 ++++
 include/sysemu/hvf.h               |  30 ++-
 target/i386/hvf-all.c              | 485 +++++++++++++++++--------------------
 target/i386/hvf-utils/x86.c        |   2 +-
 target/i386/hvf-utils/x86_cpuid.h  |   2 +-
 target/i386/hvf-utils/x86_decode.h |   8 +
 target/i386/hvf-utils/x86_descr.h  |   6 +
 target/i386/hvf-utils/x86_emu.c    |   5 +-
 target/i386/hvf-utils/x86_emu.h    |  15 ++
 target/i386/hvf-utils/x86_flags.h  |   2 +
 target/i386/hvf-utils/x86hvf.c     |   3 -
 target/i386/hvf-utils/x86hvf.h     |   2 +
 12 files changed, 326 insertions(+), 281 deletions(-)
cpus.c +47 -0
index a2cd9dfa5d..414c04ca6b 100644
@@ -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);
+        }
     }
 }
 
@@ -1098,6 +1111,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;
@@ -1564,6 +1585,9 @@ static void qemu_cpu_kick_thread(CPUState *cpu)
         fprintf(stderr, "qemu:%s: %s", __func__, strerror(err));
         exit(1);
     }
+    if (hvf_enabled()) {
+        cpu_exit(cpu);
+    }
 #else /* _WIN32 */
     if (!qemu_cpu_is_self(cpu)) {
         if (!QueueUserAPC(dummy_apc_func, cpu->hThread, 0)) {
@@ -1780,6 +1804,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];
@@ -1816,6 +1861,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 {
include/sysemu/hvf.h +17 -13
index d068a95e93..614a2d203b 100644
@@ -15,15 +15,24 @@
 #include "config-host.h"
 #include "qemu/osdep.h"
 #include "qemu-common.h"
-#include "hw/hw.h"
-#include "target/i386/cpu.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
 
 typedef struct hvf_slot {
     uint64_t start;
@@ -32,22 +41,21 @@ typedef struct hvf_slot {
     int slot_id;
 } hvf_slot;
 
-struct hvf_vcpu_caps {
+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;
 
-int __hvf_set_memory(hvf_slot *);
 typedef struct HVFState {
     AccelState parent;
     hvf_slot slots[32];
     int num_slots;
 
-    struct hvf_vcpu_caps *hvf_caps;
+    hvf_vcpu_caps *hvf_caps;
 } HVFState;
 extern HVFState *hvf_state;
 
@@ -56,8 +64,6 @@ void hvf_handle_io(CPUArchState *, uint16_t, void *,
                   int, int, int);
 hvf_slot *hvf_find_overlap_slot(uint64_t, uint64_t);
 
-/* Returns 1 if HVF is available and enabled, 0 otherwise. */
-int hvf_enabled(void);
 /* 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);
@@ -82,13 +88,11 @@ 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 vmx_reset_vcpu(CPUState *);
-void __hvf_cpu_synchronize_state(CPUState *, run_on_cpu_data);
-void __hvf_cpu_synchronize_post_reset(CPUState *, run_on_cpu_data);
+void hvf_reset_vcpu(CPUState *);
 void vmx_update_tpr(CPUState *);
 void update_apic_tpr(CPUState *);
-int apic_get_highest_priority_irr(DeviceState *);
 int hvf_put_registers(CPUState *);
+void vmx_clear_int_window_exiting(CPUState *cpu);
 
 #define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf")
 
target/i386/hvf-all.c +226 -259

633 lines not on this page · raw message

target/i386/hvf-utils/x86.c +1 -1
index 045b520425..1f68287830 100644
@@ -26,7 +26,7 @@
 #include "x86_mmu.h"
 #include "x86_descr.h"
 
-static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var)
+/* static uint32_t x86_segment_access_rights(struct x86_segment_descriptor *var)
 {
    uint32_t ar;
 
target/i386/hvf-utils/x86_cpuid.h +1 -1
index 45d27c457a..da13ea8aca 100644
@@ -35,7 +35,7 @@ struct x86_cpuid {
     uint32_t features, ext_features, ext2_features, ext3_features;
     uint32_t kvm_features, svm_features;
     uint32_t xlevel;
-    char model_id[48];
+    char model_id[50];
     int vendor_override;
     uint32_t flags;
     uint32_t xlevel2;
target/i386/hvf-utils/x86_decode.h +8 -0
index 26932b7ff7..571931dc73 100644
@@ -314,3 +314,11 @@ addr_t decode_linear_addr(struct CPUState *cpu, struct x86_decode *decode,
                           addr_t addr, x86_reg_segment seg);
 
 void init_decoder(CPUState *cpu);
+void calc_modrm_operand16(CPUState *cpu, struct x86_decode *decode,
+                          struct x86_decode_op *op);
+void calc_modrm_operand32(CPUState *cpu, struct x86_decode *decode,
+                          struct x86_decode_op *op);
+void calc_modrm_operand64(CPUState *cpu, struct x86_decode *decode,
+                          struct x86_decode_op *op);
+void set_addressing_size(CPUState *cpu, struct x86_decode *decode);
+void set_operand_size(CPUState *cpu, struct x86_decode *decode);
target/i386/hvf-utils/x86_descr.h +6 -0
index e2d3f75054..1285dd3897 100644
@@ -47,3 +47,9 @@ void x86_segment_descriptor_to_vmx(struct CPUState *cpu,
                                    x68_segment_selector selector,
                                    struct x86_segment_descriptor *desc,
                                    struct vmx_segment *vmx_desc);
+
+uint32_t vmx_read_segment_limit(CPUState *cpu, x86_reg_segment seg);
+uint32_t vmx_read_segment_ar(CPUState *cpu, x86_reg_segment seg);
+void vmx_segment_to_x86_descriptor(struct CPUState *cpu,
+                                   struct vmx_segment *vmx_desc,
+                                   struct x86_segment_descriptor *desc);
target/i386/hvf-utils/x86_emu.c +1 -4
index bd6e4b6577..52c915419a 100644
@@ -45,7 +45,6 @@
 #include "vmcs.h"
 #include "vmx.h"
 
-static void print_debug(struct CPUState *cpu);
 void hvf_handle_io(struct CPUState *cpu, uint16_t port, void *data,
                    int direction, int size, uint32_t count);
 
@@ -1473,13 +1472,11 @@ void load_regs(struct CPUState *cpu)
     RRX(cpu, REG_RBP) = rreg(cpu->hvf_fd, HV_X86_RBP);
     for (i = 8; i < 16; i++) {
         RRX(cpu, i) = rreg(cpu->hvf_fd, HV_X86_RAX + i);
-    
     }
+
     RFLAGS(cpu) = rreg(cpu->hvf_fd, HV_X86_RFLAGS);
     rflags_to_lflags(cpu);
     RIP(cpu) = rreg(cpu->hvf_fd, HV_X86_RIP);
-
-    //print_debug(cpu);
 }
 
 void store_regs(struct CPUState *cpu)
target/i386/hvf-utils/x86_emu.h +15 -0
index f6feff5553..be80350ed8 100644
@@ -30,4 +30,19 @@ void store_regs(struct CPUState *cpu);
 void simulate_rdmsr(struct CPUState *cpu);
 void simulate_wrmsr(struct CPUState *cpu);
 
+addr_t read_reg(struct CPUState *cpu, int reg, int size);
+void write_reg(struct CPUState *cpu, int reg, addr_t val, int size);
+addr_t read_val_from_reg(addr_t reg_ptr, int size);
+void write_val_to_reg(addr_t reg_ptr, addr_t val, int size);
+void write_val_ext(struct CPUState *cpu, addr_t ptr, addr_t val, int size);
+uint8_t *read_mmio(struct CPUState *cpu, addr_t ptr, int bytes);
+addr_t read_val_ext(struct CPUState *cpu, addr_t ptr, int size);
+
+void exec_movzx(struct CPUState *cpu, struct x86_decode *decode);
+void exec_shl(struct CPUState *cpu, struct x86_decode *decode);
+void exec_movsx(struct CPUState *cpu, struct x86_decode *decode);
+void exec_ror(struct CPUState *cpu, struct x86_decode *decode);
+void exec_rol(struct CPUState *cpu, struct x86_decode *decode);
+void exec_rcl(struct CPUState *cpu, struct x86_decode *decode);
+void exec_rcr(struct CPUState *cpu, struct x86_decode *decode);
 #endif
target/i386/hvf-utils/x86_flags.h +2 -0
index 87a694b408..68a0c10b90 100644
@@ -242,4 +242,6 @@ void SET_FLAGS_SHL32(struct CPUState *cpu, uint32_t v, int count, uint32_t res);
 void SET_FLAGS_SHL16(struct CPUState *cpu, uint16_t v, int count, uint16_t res);
 void SET_FLAGS_SHL8(struct CPUState *cpu, uint8_t v, int count, uint8_t res);
 
+bool _get_OF(struct CPUState *cpu);
+bool _get_CF(struct CPUState *cpu);
 #endif /* __X86_FLAGS_H__ */
target/i386/hvf-utils/x86hvf.c +0 -3
index 1d2c49d50a..c920064659 100644
@@ -35,8 +35,6 @@
 #include <Hypervisor/hv_vmx.h>
 #include <stdint.h>
 
-void hvf_cpu_synchronize_state(struct CPUState* cpu_state);
-
 void hvf_set_segment(struct CPUState *cpu, struct vmx_segment *vmx_seg,
                      SegmentCache *qseg, bool is_tr)
 {
@@ -112,7 +110,6 @@ void hvf_put_xsave(CPUState *cpu_state)
     }
 }
 
-void vmx_update_tpr(CPUState *cpu);
 void hvf_put_segments(CPUState *cpu_state)
 {
     CPUX86State *env = &X86_CPU(cpu_state)->env;
target/i386/hvf-utils/x86hvf.h +2 -0
index ddc73ed114..26da3dab57 100644
@@ -34,4 +34,6 @@ void hvf_get_xsave(CPUState *cpu_state);
 void hvf_get_msrs(CPUState *cpu_state);
 void vmx_clear_int_window_exiting(CPUState *cpu);
 void hvf_get_segments(CPUState *cpu_state);
+void vmx_update_tpr(CPUState *cpu);
+void hvf_cpu_synchronize_state(CPUState *cpu_state);
 #endif
Signature · 1 line
2.14.1
#6 lore raw

PATCH v4 7/14 apic: add function to apic that will be used by hvf

In reply to Sergio Andres Gomez Del Real

This patch adds the function apic_get_highest_priority_irr to apic.c and exports it through the interface in apic.h for use by hvf.

---
 hw/intc/apic.c         | 12 ++++++++++++
 include/hw/i386/apic.h |  1 +
 2 files changed, 13 insertions(+)
hw/intc/apic.c +12 -0
index fe15fb6024..6fda52b86c 100644
@@ -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);
include/hw/i386/apic.h +1 -0
index ea48ea9389..a9f6c0aa33 100644
@@ -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);
Signature · 1 line
2.14.1
#7 lore raw

PATCH v4 8/14 hvf: add compilation rules to Makefile.objs

In reply to Sergio Andres Gomez Del Real

This patch adds to target/i386/Makefile.objs the necessary rules so that the new files for hvf are compiled by the build system.

---
 target/i386/Makefile.objs | 1 +
 1 file changed, 1 insertion(+)
target/i386/Makefile.objs +1 -0
index 6a26e9d9f0..0bef89c099 100644
@@ -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-utils/ hvf-all.o
 endif
Signature · 1 line
2.14.1
#8 lore raw

PATCH v4 9/14 hvf: use new helper functions for put/get xsave

In reply to Sergio Andres Gomez Del Real

This patch makes use of the helper functions for handling xsave in xsave_helper.c, which are shared with kvm.

---
 target/i386/hvf-utils/x86hvf.c | 63 ++++++------------------------------------
 1 file changed, 8 insertions(+), 55 deletions(-)
target/i386/hvf-utils/x86hvf.c +8 -55
index 1e687f4f89..dd0710d056 100644
@@ -76,36 +76,13 @@ void hvf_get_segment(SegmentCache *qseg, struct vmx_segment *vmx_seg)
 void hvf_put_xsave(CPUState *cpu_state)
 {
 
-    int x;
     struct hvf_xsave_buf *xsave;
-    
+
     xsave = X86_CPU(cpu_state)->env.kvm_xsave_buf;
-    memset(xsave, 0, sizeof(*xsave)); 
-    
-    memcpy(&xsave->data[4], &X86_CPU(cpu_state)->env.fpdp, sizeof(X86_CPU(cpu_state)->env.fpdp));
-    memcpy(&xsave->data[2], &X86_CPU(cpu_state)->env.fpip, sizeof(X86_CPU(cpu_state)->env.fpip));
-    memcpy(&xsave->data[8], &X86_CPU(cpu_state)->env.fpregs, sizeof(X86_CPU(cpu_state)->env.fpregs));
-    memcpy(&xsave->data[144], &X86_CPU(cpu_state)->env.ymmh_regs, sizeof(X86_CPU(cpu_state)->env.ymmh_regs));
-    memcpy(&xsave->data[288], &X86_CPU(cpu_state)->env.zmmh_regs, sizeof(X86_CPU(cpu_state)->env.zmmh_regs));
-    memcpy(&xsave->data[272], &X86_CPU(cpu_state)->env.opmask_regs, sizeof(X86_CPU(cpu_state)->env.opmask_regs));
-    memcpy(&xsave->data[240], &X86_CPU(cpu_state)->env.bnd_regs, sizeof(X86_CPU(cpu_state)->env.bnd_regs));
-    memcpy(&xsave->data[256], &X86_CPU(cpu_state)->env.bndcs_regs, sizeof(X86_CPU(cpu_state)->env.bndcs_regs));
-    memcpy(&xsave->data[416], &X86_CPU(cpu_state)->env.hi16_zmm_regs, sizeof(X86_CPU(cpu_state)->env.hi16_zmm_regs));
-    
-    xsave->data[0] = (uint16_t)X86_CPU(cpu_state)->env.fpuc;
-    xsave->data[0] |= (X86_CPU(cpu_state)->env.fpus << 16);
-    xsave->data[0] |= (X86_CPU(cpu_state)->env.fpstt & 7) << 11;
-    
-    for (x = 0; x < 8; ++x)
-        xsave->data[1] |= ((!X86_CPU(cpu_state)->env.fptags[x]) << x);
-    xsave->data[1] |= (uint32_t)(X86_CPU(cpu_state)->env.fpop << 16);
-    
-    memcpy(&xsave->data[40], &X86_CPU(cpu_state)->env.xmm_regs, sizeof(X86_CPU(cpu_state)->env.xmm_regs));
-    
-    xsave->data[6] = X86_CPU(cpu_state)->env.mxcsr;
-    *(uint64_t *)&xsave->data[128] = X86_CPU(cpu_state)->env.xstate_bv;
-    
-    if (hv_vcpu_write_fpstate(cpu_state->hvf_fd, xsave->data, 4096)){
+
+    x86_cpu_xsave_all_areas(X86_CPU(cpu_state), xsave);
+
+    if (hv_vcpu_write_fpstate(cpu_state->hvf_fd, xsave->data, 4096)) {
         abort();
     }
 }
@@ -187,39 +164,15 @@ void hvf_put_msrs(CPUState *cpu_state)
 
 void hvf_get_xsave(CPUState *cpu_state)
 {
-    int x;
     struct hvf_xsave_buf *xsave;
-    
+
     xsave = X86_CPU(cpu_state)->env.kvm_xsave_buf;
-    
+
     if (hv_vcpu_read_fpstate(cpu_state->hvf_fd, xsave->data, 4096)) {
         abort();
     }
 
-    memcpy(&X86_CPU(cpu_state)->env.fpdp, &xsave->data[4], sizeof(X86_CPU(cpu_state)->env.fpdp));
-    memcpy(&X86_CPU(cpu_state)->env.fpip, &xsave->data[2], sizeof(X86_CPU(cpu_state)->env.fpip));
-    memcpy(&X86_CPU(cpu_state)->env.fpregs, &xsave->data[8], sizeof(X86_CPU(cpu_state)->env.fpregs));
-    memcpy(&X86_CPU(cpu_state)->env.ymmh_regs, &xsave->data[144], sizeof(X86_CPU(cpu_state)->env.ymmh_regs));
-    memcpy(&X86_CPU(cpu_state)->env.zmmh_regs, &xsave->data[288], sizeof(X86_CPU(cpu_state)->env.zmmh_regs));
-    memcpy(&X86_CPU(cpu_state)->env.opmask_regs, &xsave->data[272], sizeof(X86_CPU(cpu_state)->env.opmask_regs));
-    memcpy(&X86_CPU(cpu_state)->env.bnd_regs, &xsave->data[240], sizeof(X86_CPU(cpu_state)->env.bnd_regs));
-    memcpy(&X86_CPU(cpu_state)->env.bndcs_regs, &xsave->data[256], sizeof(X86_CPU(cpu_state)->env.bndcs_regs));
-    memcpy(&X86_CPU(cpu_state)->env.hi16_zmm_regs, &xsave->data[416], sizeof(X86_CPU(cpu_state)->env.hi16_zmm_regs));
-    
-    
-    X86_CPU(cpu_state)->env.fpuc = (uint16_t)xsave->data[0];
-    X86_CPU(cpu_state)->env.fpus = (uint16_t)(xsave->data[0] >> 16);
-    X86_CPU(cpu_state)->env.fpstt = (X86_CPU(cpu_state)->env.fpus >> 11) & 7;
-    X86_CPU(cpu_state)->env.fpop = (uint16_t)(xsave->data[1] >> 16);
-    
-    for (x = 0; x < 8; ++x)
-       X86_CPU(cpu_state)->env.fptags[x] =
-        ((((uint16_t)xsave->data[1] >> x) & 1) == 0);
-    
-    memcpy(&X86_CPU(cpu_state)->env.xmm_regs, &xsave->data[40], sizeof(X86_CPU(cpu_state)->env.xmm_regs));
-
-    X86_CPU(cpu_state)->env.mxcsr = xsave->data[6];
-    X86_CPU(cpu_state)->env.xstate_bv = *(uint64_t *)&xsave->data[128];
+    x86_cpu_xrstor_all_areas(X86_CPU(cpu_state), xsave);
 }
 
 void hvf_get_segments(CPUState *cpu_state)
Signature · 1 line
2.14.1
#9 lore raw

PATCH v4 10/14 hvf: implement hvf_get_supported_cpuid

In reply to Sergio Andres Gomez Del Real

This patch implements hvf_get_supported_cpuid, which returns the set of features supported by both the host processor and the hypervisor.

---
 target/i386/hvf-utils/x86_cpuid.c | 138 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 138 insertions(+)
target/i386/hvf-utils/x86_cpuid.c +138 -0
index fe968cb638..0646588ae3 100644
@@ -24,6 +24,7 @@
 #include "x86_cpuid.h"
 #include "x86.h"
 #include "vmx.h"
+#include "sysemu/hvf.h"
 
 #define PPRO_FEATURES (CPUID_FP87 | CPUID_DE | CPUID_PSE | CPUID_TSC | \
     CPUID_MSR | CPUID_MCE | CPUID_CX8 | CPUID_PGE | CPUID_CMOV | \
@@ -94,6 +95,27 @@ struct x86_cpuid builtin_cpus[] = {
 
 static struct x86_cpuid *_cpuid;
 
+static uint64_t xgetbv(uint32_t xcr)
+{
+    uint32_t eax, edx;
+
+    __asm__ volatile ("xgetbv"
+                      : "=a" (eax), "=d" (edx)
+                      : "c" (xcr));
+
+    return (((uint64_t)edx) << 32) | eax;
+}
+
+static bool vmx_mpx_supported()
+{
+    uint64_t cap_exit, cap_entry;
+
+    hv_vmx_read_capability(HV_VMX_CAP_ENTRY, &cap_entry);
+    hv_vmx_read_capability(HV_VMX_CAP_EXIT, &cap_exit);
+
+    return ((cap_exit & (1 << 23)) && (cap_entry & (1 << 16)));
+}
+
 void init_cpuid(struct CPUState *cpu)
 {
     _cpuid = &builtin_cpus[2]; /* core2duo */
@@ -277,3 +299,119 @@ void get_cpuid_func(struct CPUState *cpu, int func, int cnt, uint32_t *eax,
         break;
     }
 }
+
+uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
+                                 int reg)
+{
+    uint64_t cap;
+    uint32_t eax, ebx, ecx, edx;
+
+    host_cpuid(func, idx, &eax, &ebx, &ecx, &edx);
+
+    switch (func) {
+    case 0:
+        eax = eax < (uint32_t)0xd ? eax : (uint32_t)0xd;
+        break;
+    case 1:
+        edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
+             CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
+             CPUID_SEP | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
+             CPUID_PAT | CPUID_PSE36 | CPUID_CLFLUSH | CPUID_MMX |
+             CPUID_FXSR | CPUID_SSE | CPUID_SSE2 | CPUID_SS;
+        ecx &= CPUID_EXT_SSE3 | CPUID_EXT_PCLMULQDQ | CPUID_EXT_SSSE3 |
+             CPUID_EXT_FMA | CPUID_EXT_CX16 | CPUID_EXT_PCID |
+             CPUID_EXT_SSE41 | CPUID_EXT_SSE42 | CPUID_EXT_MOVBE |
+             CPUID_EXT_POPCNT | CPUID_EXT_AES | CPUID_EXT_XSAVE |
+             CPUID_EXT_AVX | CPUID_EXT_F16C | CPUID_EXT_RDRAND;
+        break;
+    case 6:
+        eax = 4;
+        ebx = 0;
+        ecx = 0;
+        edx = 0;
+        break;
+    case 7:
+        if (idx == 0) {
+            ebx &= CPUID_7_0_EBX_FSGSBASE | CPUID_7_0_EBX_BMI1 |
+                    CPUID_7_0_EBX_HLE | CPUID_7_0_EBX_AVX2 |
+                    CPUID_7_0_EBX_SMEP | CPUID_7_0_EBX_BMI2 |
+                    CPUID_7_0_EBX_ERMS | CPUID_7_0_EBX_RTM |
+                    CPUID_7_0_EBX_RDSEED | CPUID_7_0_EBX_ADX |
+                    CPUID_7_0_EBX_SMAP | CPUID_7_0_EBX_AVX512IFMA |
+                    CPUID_7_0_EBX_AVX512F | CPUID_7_0_EBX_AVX512PF |
+                    CPUID_7_0_EBX_AVX512ER | CPUID_7_0_EBX_AVX512CD |
+                    CPUID_7_0_EBX_CLFLUSHOPT | CPUID_7_0_EBX_CLWB |
+                    CPUID_7_0_EBX_AVX512DQ | CPUID_7_0_EBX_SHA_NI |
+                    CPUID_7_0_EBX_AVX512BW | CPUID_7_0_EBX_AVX512VL |
+                    CPUID_7_0_EBX_INVPCID | CPUID_7_0_EBX_MPX;
+
+            if (!vmx_mpx_supported()) {
+                ebx &= ~CPUID_7_0_EBX_MPX;
+            }
+            hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
+            if (!(cap & CPU_BASED2_INVPCID)) {
+                ebx &= ~CPUID_7_0_EBX_INVPCID;
+            }
+
+            ecx &= CPUID_7_0_ECX_AVX512BMI | CPUID_7_0_ECX_AVX512_VPOPCNTDQ;
+            edx &= CPUID_7_0_EDX_AVX512_4VNNIW | CPUID_7_0_EDX_AVX512_4FMAPS;
+        } else {
+            ebx = 0;
+            ecx = 0;
+            edx = 0;
+        }
+        eax = 0;
+        break;
+    case 0xD:
+        if (idx == 0) {
+            uint64_t host_xcr0 = xgetbv(0);
+            uint64_t supp_xcr0 = host_xcr0 & (XSTATE_FP_MASK | XSTATE_SSE_MASK |
+                                  XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK |
+                                  XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK |
+                                  XSTATE_ZMM_Hi256_MASK | XSTATE_Hi16_ZMM_MASK);
+            eax &= supp_xcr0;
+            if (!vmx_mpx_supported()) {
+                eax &= ~(XSTATE_BNDREGS_MASK | XSTATE_BNDCSR_MASK);
+            }
+        } else if (idx == 1) {
+            hv_vmx_read_capability(HV_VMX_CAP_PROCBASED2, &cap);
+            eax &= CPUID_XSAVE_XSAVEOPT | CPUID_XSAVE_XGETBV1;
+            if (!(cap & CPU_BASED2_XSAVES_XRSTORS)) {
+                eax &= ~CPUID_XSAVE_XSAVES;
+            }
+        }
+        break;
+    case 0x80000001:
+        /* LM only if HVF in 64-bit mode */
+        edx &= CPUID_FP87 | CPUID_VME | CPUID_DE | CPUID_PSE | CPUID_TSC |
+                CPUID_MSR | CPUID_PAE | CPUID_MCE | CPUID_CX8 | CPUID_APIC |
+                CPUID_EXT2_SYSCALL | CPUID_MTRR | CPUID_PGE | CPUID_MCA | CPUID_CMOV |
+                CPUID_PAT | CPUID_PSE36 | CPUID_EXT2_MMXEXT | CPUID_MMX |
+                CPUID_FXSR | CPUID_EXT2_FXSR | CPUID_EXT2_PDPE1GB | CPUID_EXT2_3DNOWEXT |
+                CPUID_EXT2_3DNOW | CPUID_EXT2_LM | CPUID_EXT2_RDTSCP | CPUID_EXT2_NX;
+        hv_vmx_read_capability(HV_VMX_CAP_PROCBASED, &cap);
+        if (!(cap & CPU_BASED_TSC_OFFSET)) {
+            edx &= ~CPUID_EXT2_RDTSCP;
+        }
+        ecx &= CPUID_EXT3_LAHF_LM | CPUID_EXT3_CMP_LEG | CPUID_EXT3_CR8LEG |
+                CPUID_EXT3_ABM | CPUID_EXT3_SSE4A | CPUID_EXT3_MISALIGNSSE |
+                CPUID_EXT3_3DNOWPREFETCH | CPUID_EXT3_OSVW | CPUID_EXT3_XOP |
+                CPUID_EXT3_FMA4 | CPUID_EXT3_TBM;
+        break;
+    default:
+        return 0;
+    }
+
+    switch (reg) {
+    case R_EAX:
+        return eax;
+    case R_EBX:
+        return ebx;
+    case R_ECX:
+        return ecx;
+    case R_EDX:
+        return edx;
+    default:
+        return 0;
+    }
+}
Signature · 1 line
2.14.1
#10 lore raw

PATCH v4 11/14 hvf: refactor cpuid code

In reply to Sergio Andres Gomez Del Real

This patch generalizes some code in cpu.c, sharing code and data between hvf and kvm. It also begins calling the new hvf_get_supported_cpuid where appropriate.

---
 target/i386/cpu-qom.h |  4 +--
 target/i386/cpu.c     | 77 ++++++++++++++++++++++++++++++++++++++-------------
 2 files changed, 59 insertions(+), 22 deletions(-)
target/i386/cpu-qom.h +2 -2
index c2205e6077..22f95eb3a4 100644
@@ -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;
target/i386/cpu.c +57 -20

188 lines not on this page · raw message

Signature · 1 line
2.14.1
#11 lore raw

PATCH v4 12/14 hvf: implement vga dirty page tracking

In reply to Sergio Andres Gomez Del Real

This patch implements setting the tracking of dirty vga pages, using hvf's interface to protect guest memory. It uses the MemoryListener callback mechanism through .log_start/stop/sync

---
 include/sysemu/hvf.h  |  5 ++++
 target/i386/hvf-all.c | 74 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 72 insertions(+), 7 deletions(-)
include/sysemu/hvf.h +5 -0
index 9230c13851..f54e043955 100644
@@ -34,11 +34,16 @@ uint32_t hvf_get_supported_cpuid(uint32_t func, uint32_t idx,
 #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 {
target/i386/hvf-all.c +67 -7

116 lines not on this page · raw message

Signature · 1 line
2.14.1
#12 lore raw

PATCH v4 13/14 hvf: refactor event injection code for hvf

In reply to Sergio Andres Gomez Del Real

This patch refactors the event-injection code for hvf by using the appropriate fields already provided by CPUX86State. At vmexit, it fills these fields so that hvf_inject_interrupts can just retrieve them without calling into hvf.

---
 target/i386/cpu.c              |  3 ++
 target/i386/cpu.h              |  1 +
 target/i386/hvf-all.c          | 57 ++++++++++++++++++++++++++++++++----
 target/i386/hvf-utils/vmcs.h   |  3 ++
 target/i386/hvf-utils/vmx.h    |  8 ++++++
 target/i386/hvf-utils/x86hvf.c | 65 ++++++++++++++++++++----------------------
 target/i386/kvm.c              |  2 --
 7 files changed, 98 insertions(+), 41 deletions(-)
target/i386/cpu.c +3 -0
index 2bf8c0ce0f..76bfcc23f3 100644
@@ -3247,6 +3247,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);
target/i386/cpu.h +1 -0
index 630a4c2c0a..81e3f511a6 100644
@@ -1188,6 +1188,7 @@ 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;
target/i386/hvf-all.c +52 -5

76 lines not on this page · raw message

target/i386/hvf-utils/vmcs.h +3 -0
index c410dcfaaa..0fae73dce5 100644
@@ -299,6 +299,7 @@
 /*
  * 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)
@@ -306,6 +307,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
target/i386/hvf-utils/vmx.h +8 -0
index 44a5c6d554..102075d0d4 100644
@@ -181,6 +181,10 @@ static inline void macvm_set_rip(CPUState *cpu, uint64_t rip)
 
 static inline void vmx_clear_nmi_blocking(CPUState *cpu)
 {
+    X86CPU *x86_cpu = X86_CPU(cpu);
+    CPUX86State *env = &x86_cpu->env;
+
+    env->hflags2 &= ~HF2_NMI_MASK;
     uint32_t gi = (uint32_t) rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY);
     gi &= ~VMCS_INTERRUPTIBILITY_NMI_BLOCKING;
     wvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY, gi);
@@ -188,6 +192,10 @@ static inline void vmx_clear_nmi_blocking(CPUState *cpu)
 
 static inline void vmx_set_nmi_blocking(CPUState *cpu)
 {
+    X86CPU *x86_cpu = X86_CPU(cpu);
+    CPUX86State *env = &x86_cpu->env;
+
+    env->hflags2 |= HF2_NMI_MASK;
     uint32_t gi = (uint32_t)rvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY);
     gi |= VMCS_INTERRUPTIBILITY_NMI_BLOCKING;
     wvmcs(cpu->hvf_fd, VMCS_GUEST_INTERRUPTIBILITY, gi);
target/i386/hvf-utils/x86hvf.c +31 -34

95 lines not on this page · raw message

target/i386/kvm.c +0 -2
index 6db7783edc..a695b8cd4e 100644
@@ -1030,8 +1030,6 @@ void kvm_arch_reset_vcpu(X86CPU *cpu)
 {
     CPUX86State *env = &cpu->env;
 
-    env->exception_injected = -1;
-    env->interrupt_injected = -1;
     env->xcr0 = 1;
     if (kvm_irqchip_in_kernel()) {
         env->mp_state = cpu_is_bsp(cpu) ? KVM_MP_STATE_RUNNABLE :
Signature · 1 line
2.14.1
#13 lore raw

PATCH v4 14/14 hvf: inject General Protection Fault when vmexit through vmcall

In reply to Sergio Andres Gomez Del Real

This patch injects a GP fault when the guest vmexit's by executing a vmcall instruction.

---
 target/i386/hvf-all.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
target/i386/hvf-all.c +3 -1
index 105a63ad4f..0a544470ad 100644
@@ -903,7 +903,9 @@ int hvf_vcpu_exec(CPUState *cpu)
             macvm_set_rip(cpu, rip + ins_len);
             break;
         case VMX_REASON_VMCALL:
-            /* TODO: inject #GP fault */
+            env->exception_injected = EXCP0D_GPF;
+            env->has_error_code = true;
+            env->error_code = 0;
             break;
         default:
             error_report("%llx: unhandled exit %llx\n", rip, exit_reason);
Signature · 1 line
2.14.1
#14 lore raw
In reply to Sergio Andres Gomez Del Real
Quoted 5 lines · Sergio Andres Gomez Del Real

================
Changes in v4:
(1) Use g_new0 instead of g_malloc.
(2) hvf TODO's in cpu.c explained: in-kernel irqchip.
(3) Introduce ins_len field in patch where actually used.

Quoted 8 lines

(4) Remove outdated comment "/* Definition of hvf_state is here */"
(5) Treat vcpu_dirty as boolean throughout.
(6) checkpatch.pl patch only does styling changes.
(8) Add comment documenting meaning of -1 returned by apic_get_highest_priority_irr.
(9) Add TODO to move hvf's synchronization functions inside cpu_synchronize_*, along with kvm's and hax's.
================

Thanks Sergio, this is a good start. I have done a few more cleanup and sent my patches which, however, I could not test. In any case, it seems feasible to get this done for 2.11!

Regards,

Paolo

Quoted 129 lines

================
Changes in v3:
(1) Fixed licensing issues in patch 3.
(2) Revert to late adding of compilation rules in Makefile.objs (patch 8/14); files aren't ready to compile earlier.
(3) Make a single patch just for fixing style (patch 4/14).
(4) Fix data type for hvf_fd field.
(5) Add comment that return value of -1 in apic function added in 7/14 means "no interrupt".
================

================
Changes in v2:
(1) Removed legacy option "-enable-hvf" in favor of "-M accel=hvf"
(2) Added missing copyright headers; replace fprintfs for error_report; improved commit description.
(3) Moved patch that adds compilation rules in Makefile.objs right after the patch that adds the new files from Google's repo.
(4) Removed conditional macros from cpus.c and cpu.c
(5) Moved patch that fixes coding style to patch # 3
(6) Fix commit message in apic patch
(7) Squash some commits to avoid code churn
================

The following patchset adds to QEMU the supporting for macOS's native hypervisor, Hypervisor.framework (hvf). The code base is taken from Google's Android emulator at
https://android.googlesource.com/platform/external/qemu/+/emu-master-dev.
Notably missing is support for live migration.

Apart from general code refactoring, some additional features were implemented:
retrieve the set of features supported by host cpu and hvf (cpuid); dirty page tracking for VGA memory area; reimplementation of the event injection mechanism to allow injection of exceptions during vmexits, which is exemplified by the injection of a GP fault when the guest vmexits due to execution of the vmcall instruction; changing the emulator's use of CPUState structure in favor of CPUX86State, so as to in the future remove data structures that are uselessly specific to hvf and unified some of the state between kvm/tcg and hvf.
Some features initially planned to implement that didn't make it include:
page fault handling in the emulator and implementing the dummy_signal to handle the SIG_IPI signal without race conditions. Hopefully these can be implemented in the near future.
Event injection was tested through the eventinj kvm test. The latest Debian and Damn Small Linux images were executed, although by now ways it was an exhaustive testing.

Sergio Andres Gomez Del Real (14):
hvf: add support for Hypervisor.framework in the configure script
hvf: add code base from Google's QEMU repository
hvf: fix licensing issues; isolate task handling code (GPL v2-only)
hvf: run hvf code through checkpatch.pl and fix style issues
hvf: add code to cpus.c and do refactoring in preparation for
compiling
hvf: handle fields from CPUState and CPUX86State
apic: add function to apic that will be used by hvf
hvf: add compilation rules to Makefile.objs
hvf: use new helper functions for put/get xsave
hvf: implement hvf_get_supported_cpuid
hvf: refactor cpuid code
hvf: implement vga dirty page tracking
hvf: refactor event injection code for hvf
hvf: inject General Protection Fault when vmexit through vmcall

 configure                           |   38 +
 cpus.c                              |   89 ++
 hw/intc/apic.c                      |   12 +
 include/hw/i386/apic.h              |    1 +
 include/qom/cpu.h                   |    2 +
 include/sysemu/hvf.h                |  181 +++
 qemu-options.hx                     |   10 +-
 target/i386/Makefile.objs           |    1 +
 target/i386/cpu-qom.h               |    4 +-
 target/i386/cpu.c                   |   80 +-
 target/i386/cpu.h                   |   34 +-
 target/i386/hvf-all.c               |  963 +++++++++++++++
 target/i386/hvf-i386.h              |   50 +
 target/i386/hvf-utils/Makefile.objs |    1 +
 target/i386/hvf-utils/README.md     |    7 +
 target/i386/hvf-utils/vmcs.h        |  371 ++++++
 target/i386/hvf-utils/vmx.h         |  222 ++++
 target/i386/hvf-utils/x86.c         |  184 +++
 target/i386/hvf-utils/x86.h         |  394 +++++++
 target/i386/hvf-utils/x86_cpuid.c   |  417 +++++++
 target/i386/hvf-utils/x86_cpuid.h   |   52 +
 target/i386/hvf-utils/x86_decode.c  | 2186 +++++++++++++++++++++++++++++++++++
 target/i386/hvf-utils/x86_decode.h  |  325 ++++++
 target/i386/hvf-utils/x86_descr.c   |  124 ++
 target/i386/hvf-utils/x86_descr.h   |   55 +
 target/i386/hvf-utils/x86_emu.c     | 1536 ++++++++++++++++++++++++
 target/i386/hvf-utils/x86_emu.h     |   49 +
 target/i386/hvf-utils/x86_flags.c   |  333 ++++++
 target/i386/hvf-utils/x86_flags.h   |  243 ++++
 target/i386/hvf-utils/x86_gen.h     |   53 +
 target/i386/hvf-utils/x86_mmu.c     |  273 +++++
 target/i386/hvf-utils/x86_mmu.h     |   45 +
 target/i386/hvf-utils/x86_task.c    |  201 ++++
 target/i386/hvf-utils/x86_task.h    |   18 +
 target/i386/hvf-utils/x86hvf.c      |  463 ++++++++
 target/i386/hvf-utils/x86hvf.h      |   39 +
 target/i386/kvm.c                   |    2 -
 37 files changed, 9025 insertions(+), 33 deletions(-)
 create mode 100644 include/sysemu/hvf.h
 create mode 100644 target/i386/hvf-all.c
 create mode 100644 target/i386/hvf-i386.h
 create mode 100644 target/i386/hvf-utils/Makefile.objs
 create mode 100644 target/i386/hvf-utils/README.md
 create mode 100644 target/i386/hvf-utils/vmcs.h
 create mode 100644 target/i386/hvf-utils/vmx.h
 create mode 100644 target/i386/hvf-utils/x86.c
 create mode 100644 target/i386/hvf-utils/x86.h
 create mode 100644 target/i386/hvf-utils/x86_cpuid.c
 create mode 100644 target/i386/hvf-utils/x86_cpuid.h
 create mode 100644 target/i386/hvf-utils/x86_decode.c
 create mode 100644 target/i386/hvf-utils/x86_decode.h
 create mode 100644 target/i386/hvf-utils/x86_descr.c
 create mode 100644 target/i386/hvf-utils/x86_descr.h
 create mode 100644 target/i386/hvf-utils/x86_emu.c
 create mode 100644 target/i386/hvf-utils/x86_emu.h
 create mode 100644 target/i386/hvf-utils/x86_flags.c
 create mode 100644 target/i386/hvf-utils/x86_flags.h
 create mode 100644 target/i386/hvf-utils/x86_gen.h
 create mode 100644 target/i386/hvf-utils/x86_mmu.c
 create mode 100644 target/i386/hvf-utils/x86_mmu.h
 create mode 100644 target/i386/hvf-utils/x86_task.c
 create mode 100644 target/i386/hvf-utils/x86_task.h
 create mode 100644 target/i386/hvf-utils/x86hvf.c
 create mode 100644 target/i386/hvf-utils/x86hvf.h