From nobody Mon Feb 9 18:45:57 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1527788539912391.10673205245564; Thu, 31 May 2018 10:42:19 -0700 (PDT) Received: from localhost ([::1]:45414 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fORac-0001BQ-W5 for importer@patchew.org; Thu, 31 May 2018 13:42:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58752) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOR8k-0003s2-04 for qemu-devel@nongnu.org; Thu, 31 May 2018 13:13:32 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOR8h-0000Nw-SW for qemu-devel@nongnu.org; Thu, 31 May 2018 13:13:29 -0400 Received: from mx3-rdu2.redhat.com ([66.187.233.73]:41036 helo=mx1.redhat.com) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1fOR8h-0000NG-MC for qemu-devel@nongnu.org; Thu, 31 May 2018 13:13:27 -0400 Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5339D805A530; Thu, 31 May 2018 17:13:27 +0000 (UTC) Received: from donizetti.redhat.com (ovpn-117-47.ams2.redhat.com [10.36.117.47]) by smtp.corp.redhat.com (Postfix) with ESMTP id 1699E2026DEF; Thu, 31 May 2018 17:13:25 +0000 (UTC) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 19:12:34 +0200 Message-Id: <20180531171253.21012-35-pbonzini@redhat.com> In-Reply-To: <20180531171253.21012-1-pbonzini@redhat.com> References: <20180531171253.21012-1-pbonzini@redhat.com> X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Thu, 31 May 2018 17:13:27 +0000 (UTC) X-Greylist: inspected by milter-greylist-4.5.16 (mx1.redhat.com [10.11.55.8]); Thu, 31 May 2018 17:13:27 +0000 (UTC) for IP:'10.11.54.4' DOMAIN:'int-mx04.intmail.prod.int.rdu2.redhat.com' HELO:'smtp.corp.redhat.com' FROM:'pbonzini@redhat.com' RCPT:'' X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] [fuzzy] X-Received-From: 66.187.233.73 Subject: [Qemu-devel] [PULL 34/53] WHPX: dynamically load WHP libraries X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Lucian Petrut , Alessandro Pilotti , Justin Terry Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail: RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Lucian Petrut We're currently linking against import libraries of the WHP DLLs. By dynamically loading the libraries, we ensure that QEMU will work on previous Windows versions, where the WHP DLLs will be missing (assuming that WHP is not requested). Also, we're simplifying the build process, as we no longer require the import libraries. Signed-off-by: Alessandro Pilotti Signed-off-by: Justin Terry (VM) Signed-off-by: Lucian Petrut Message-Id: <1526405722-10887-2-git-send-email-lpetrut@cloudbasesolutions.c= om> Signed-off-by: Paolo Bonzini --- configure | 15 +-- target/i386/whpx-all.c | 212 ++++++++++++++++++++++++++++------------- 2 files changed, 145 insertions(+), 82 deletions(-) diff --git a/configure b/configure index a8498ab393..99b4a287dd 100755 --- a/configure +++ b/configure @@ -2524,20 +2524,7 @@ fi ########################################## # Windows Hypervisor Platform accelerator (WHPX) check if test "$whpx" !=3D "no" ; then - cat > $TMPC << EOF -#include -#include -#include -int main(void) { - WHV_CAPABILITY whpx_cap; - UINT32 writtenSize; - WHvGetCapability(WHvCapabilityCodeFeatures, &whpx_cap, sizeof(whpx_cap= ), - &writtenSize); - return 0; -} -EOF - if compile_prog "" "-lWinHvPlatform -lWinHvEmulation" ; then - libs_softmmu=3D"$libs_softmmu -lWinHvPlatform -lWinHvEmulation" + if check_include "WinHvPlatform.h" && check_include "WinHvEmulation.h"= ; then whpx=3D"yes" else if test "$whpx" =3D "yes"; then diff --git a/target/i386/whpx-all.c b/target/i386/whpx-all.c index bd7df10ba5..32695d47f9 100644 --- a/target/i386/whpx-all.c +++ b/target/i386/whpx-all.c @@ -24,6 +24,7 @@ #include "qemu/queue.h" #include "qapi/error.h" #include "migration/blocker.h" +#include "whp-dispatch.h" =20 #include #include @@ -159,8 +160,11 @@ struct whpx_vcpu { }; =20 static bool whpx_allowed; +static bool whp_dispatch_initialized; +static HMODULE hWinHvPlatform, hWinHvEmulation; =20 struct whpx_state whpx_global; +struct WHPDispatch whp_dispatch; =20 =20 /* @@ -354,10 +358,11 @@ static void whpx_set_registers(CPUState *cpu) =20 assert(idx =3D=3D RTL_NUMBER_OF(whpx_register_names)); =20 - hr =3D WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, - whpx_register_names, - RTL_NUMBER_OF(whpx_register_names= ), - &vcxt.values[0]); + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, + whpx_register_names, + RTL_NUMBER_OF(whpx_register_names), + &vcxt.values[0]); =20 if (FAILED(hr)) { error_report("WHPX: Failed to set virtual processor context, hr=3D= %08lx", @@ -381,10 +386,11 @@ static void whpx_get_registers(CPUState *cpu) =20 assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu)); =20 - hr =3D WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, - whpx_register_names, - RTL_NUMBER_OF(whpx_register_names= ), - &vcxt.values[0]); + hr =3D whp_dispatch.WHvGetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, + whpx_register_names, + RTL_NUMBER_OF(whpx_register_names), + &vcxt.values[0]); if (FAILED(hr)) { error_report("WHPX: Failed to get virtual processor context, hr=3D= %08lx", hr); @@ -544,9 +550,10 @@ static HRESULT CALLBACK whpx_emu_getreg_callback( struct whpx_state *whpx =3D &whpx_global; CPUState *cpu =3D (CPUState *)ctx; =20 - hr =3D WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, - RegisterNames, RegisterCount, - RegisterValues); + hr =3D whp_dispatch.WHvGetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, + RegisterNames, RegisterCount, + RegisterValues); if (FAILED(hr)) { error_report("WHPX: Failed to get virtual processor registers," " hr=3D%08lx", hr); @@ -565,9 +572,10 @@ static HRESULT CALLBACK whpx_emu_setreg_callback( struct whpx_state *whpx =3D &whpx_global; CPUState *cpu =3D (CPUState *)ctx; =20 - hr =3D WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, - RegisterNames, RegisterCount, - RegisterValues); + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, + RegisterNames, RegisterCount, + RegisterValues); if (FAILED(hr)) { error_report("WHPX: Failed to set virtual processor registers," " hr=3D%08lx", hr); @@ -594,8 +602,8 @@ static HRESULT CALLBACK whpx_emu_translate_callback( CPUState *cpu =3D (CPUState *)ctx; WHV_TRANSLATE_GVA_RESULT res; =20 - hr =3D WHvTranslateGva(whpx->partition, cpu->cpu_index, - Gva, TranslateFlags, &res, Gpa); + hr =3D whp_dispatch.WHvTranslateGva(whpx->partition, cpu->cpu_index, + Gva, TranslateFlags, &res, Gpa); if (FAILED(hr)) { error_report("WHPX: Failed to translate GVA, hr=3D%08lx", hr); } else { @@ -620,16 +628,18 @@ static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY= _ACCESS_CONTEXT *ctx) struct whpx_vcpu *vcpu =3D get_whpx_vcpu(cpu); WHV_EMULATOR_STATUS emu_status; =20 - hr =3D WHvEmulatorTryMmioEmulation(vcpu->emulator, cpu, - &vcpu->exit_ctx.VpContext, ctx, - &emu_status); + hr =3D whp_dispatch.WHvEmulatorTryMmioEmulation( + vcpu->emulator, cpu, + &vcpu->exit_ctx.VpContext, ctx, + &emu_status); if (FAILED(hr)) { error_report("WHPX: Failed to parse MMIO access, hr=3D%08lx", hr); return -1; } =20 if (!emu_status.EmulationSuccessful) { - error_report("WHPX: Failed to emulate MMIO access"); + error_report("WHPX: Failed to emulate MMIO access with" + " EmulatorReturnStatus: %u", emu_status.AsUINT32); return -1; } =20 @@ -643,16 +653,18 @@ static int whpx_handle_portio(CPUState *cpu, struct whpx_vcpu *vcpu =3D get_whpx_vcpu(cpu); WHV_EMULATOR_STATUS emu_status; =20 - hr =3D WHvEmulatorTryIoEmulation(vcpu->emulator, cpu, - &vcpu->exit_ctx.VpContext, ctx, - &emu_status); + hr =3D whp_dispatch.WHvEmulatorTryIoEmulation( + vcpu->emulator, cpu, + &vcpu->exit_ctx.VpContext, ctx, + &emu_status); if (FAILED(hr)) { error_report("WHPX: Failed to parse PortIO access, hr=3D%08lx", hr= ); return -1; } =20 if (!emu_status.EmulationSuccessful) { - error_report("WHPX: Failed to emulate PortMMIO access"); + error_report("WHPX: Failed to emulate PortIO access with" + " EmulatorReturnStatus: %u", emu_status.AsUINT32); return -1; } =20 @@ -767,8 +779,9 @@ static void whpx_vcpu_pre_run(CPUState *cpu) qemu_mutex_unlock_iothread(); =20 if (reg_count) { - hr =3D WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_i= ndex, - reg_names, reg_count, reg_val= ues); + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, + reg_names, reg_count, reg_values); if (FAILED(hr)) { error_report("WHPX: Failed to set interrupt state registers," " hr=3D%08lx", hr); @@ -876,8 +889,9 @@ static int whpx_vcpu_run(CPUState *cpu) whpx_vcpu_kick(cpu); } =20 - hr =3D WHvRunVirtualProcessor(whpx->partition, cpu->cpu_index, - &vcpu->exit_ctx, sizeof(vcpu->exit_ctx= )); + hr =3D whp_dispatch.WHvRunVirtualProcessor( + whpx->partition, cpu->cpu_index, + &vcpu->exit_ctx, sizeof(vcpu->exit_ctx)); =20 if (FAILED(hr)) { error_report("WHPX: Failed to exec a virtual processor," @@ -948,11 +962,11 @@ static int whpx_vcpu_run(CPUState *cpu) reg_values[3].Reg64 =3D rdx; reg_values[4].Reg64 =3D rbx; =20 - hr =3D WHvSetVirtualProcessorRegisters(whpx->partition, - cpu->cpu_index, - reg_names, - reg_count, - reg_values); + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters( + whpx->partition, cpu->cpu_index, + reg_names, + reg_count, + reg_values); =20 if (FAILED(hr)) { error_report("WHPX: Failed to set CpuidAccess state regist= ers," @@ -1064,8 +1078,8 @@ int whpx_init_vcpu(CPUState *cpu) (void)migrate_add_blocker(whpx_migration_blocker, &local_error); if (local_error) { error_report_err(local_error); - error_free(whpx_migration_blocker); migrate_del_blocker(whpx_migration_blocker); + error_free(whpx_migration_blocker); return -EINVAL; } } @@ -1077,7 +1091,9 @@ int whpx_init_vcpu(CPUState *cpu) return -ENOMEM; } =20 - hr =3D WHvEmulatorCreateEmulator(&whpx_emu_callbacks, &vcpu->emulator); + hr =3D whp_dispatch.WHvEmulatorCreateEmulator( + &whpx_emu_callbacks, + &vcpu->emulator); if (FAILED(hr)) { error_report("WHPX: Failed to setup instruction completion support= ," " hr=3D%08lx", hr); @@ -1085,11 +1101,12 @@ int whpx_init_vcpu(CPUState *cpu) return -EINVAL; } =20 - hr =3D WHvCreateVirtualProcessor(whpx->partition, cpu->cpu_index, 0); + hr =3D whp_dispatch.WHvCreateVirtualProcessor( + whpx->partition, cpu->cpu_index, 0); if (FAILED(hr)) { error_report("WHPX: Failed to create a virtual processor," " hr=3D%08lx", hr); - WHvEmulatorDestroyEmulator(vcpu->emulator); + whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator); g_free(vcpu); return -EINVAL; } @@ -1130,8 +1147,8 @@ void whpx_destroy_vcpu(CPUState *cpu) struct whpx_state *whpx =3D &whpx_global; struct whpx_vcpu *vcpu =3D get_whpx_vcpu(cpu); =20 - WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index); - WHvEmulatorDestroyEmulator(vcpu->emulator); + whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index= ); + whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator); g_free(cpu->hax_vcpu); return; } @@ -1139,7 +1156,8 @@ void whpx_destroy_vcpu(CPUState *cpu) void whpx_vcpu_kick(CPUState *cpu) { struct whpx_state *whpx =3D &whpx_global; - WHvCancelRunVirtualProcessor(whpx->partition, cpu->cpu_index, 0); + whp_dispatch.WHvCancelRunVirtualProcessor( + whpx->partition, cpu->cpu_index, 0); } =20 /* @@ -1165,17 +1183,17 @@ static void whpx_update_mapping(hwaddr start_pa, ra= m_addr_t size, */ =20 if (add) { - hr =3D WHvMapGpaRange(whpx->partition, - host_va, - start_pa, - size, - (WHvMapGpaRangeFlagRead | - WHvMapGpaRangeFlagExecute | - (rom ? 0 : WHvMapGpaRangeFlagWrite))); + hr =3D whp_dispatch.WHvMapGpaRange(whpx->partition, + host_va, + start_pa, + size, + (WHvMapGpaRangeFlagRead | + WHvMapGpaRangeFlagExecute | + (rom ? 0 : WHvMapGpaRangeFlagWri= te))); } else { - hr =3D WHvUnmapGpaRange(whpx->partition, - start_pa, - size); + hr =3D whp_dispatch.WHvUnmapGpaRange(whpx->partition, + start_pa, + size); } =20 if (FAILED(hr)) { @@ -1289,18 +1307,24 @@ static int whpx_accel_init(MachineState *ms) =20 whpx =3D &whpx_global; =20 + if (!init_whp_dispatch()) { + ret =3D -ENOSYS; + goto error; + } + memset(whpx, 0, sizeof(struct whpx_state)); whpx->mem_quota =3D ms->ram_size; =20 - hr =3D WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &whpx_cap, - sizeof(whpx_cap), &whpx_cap_size); + hr =3D whp_dispatch.WHvGetCapability( + WHvCapabilityCodeHypervisorPresent, &whpx_cap, + sizeof(whpx_cap), &whpx_cap_size); if (FAILED(hr) || !whpx_cap.HypervisorPresent) { error_report("WHPX: No accelerator found, hr=3D%08lx", hr); ret =3D -ENOSPC; goto error; } =20 - hr =3D WHvCreatePartition(&whpx->partition); + hr =3D whp_dispatch.WHvCreatePartition(&whpx->partition); if (FAILED(hr)) { error_report("WHPX: Failed to create partition, hr=3D%08lx", hr); ret =3D -EINVAL; @@ -1309,10 +1333,11 @@ static int whpx_accel_init(MachineState *ms) =20 memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); prop.ProcessorCount =3D smp_cpus; - hr =3D WHvSetPartitionProperty(whpx->partition, - WHvPartitionPropertyCodeProcessorCount, - &prop, - sizeof(WHV_PARTITION_PROPERTY)); + hr =3D whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeProcessorCount, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); =20 if (FAILED(hr)) { error_report("WHPX: Failed to set partition core count to %d," @@ -1323,10 +1348,11 @@ static int whpx_accel_init(MachineState *ms) =20 memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY)); prop.ExtendedVmExits.X64CpuidExit =3D 1; - hr =3D WHvSetPartitionProperty(whpx->partition, - WHvPartitionPropertyCodeExtendedVmExits, - &prop, - sizeof(WHV_PARTITION_PROPERTY)); + hr =3D whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeExtendedVmExits, + &prop, + sizeof(WHV_PARTITION_PROPERTY)); =20 if (FAILED(hr)) { error_report("WHPX: Failed to enable partition extended X64CpuidEx= it" @@ -1336,11 +1362,11 @@ static int whpx_accel_init(MachineState *ms) } =20 UINT32 cpuidExitList[] =3D {1}; - hr =3D WHvSetPartitionProperty(whpx->partition, - WHvPartitionPropertyCodeCpuidExitList, - cpuidExitList, - RTL_NUMBER_OF(cpuidExitList) * sizeof(UIN= T32)); - + hr =3D whp_dispatch.WHvSetPartitionProperty( + whpx->partition, + WHvPartitionPropertyCodeCpuidExitList, + cpuidExitList, + RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32)); if (FAILED(hr)) { error_report("WHPX: Failed to set partition CpuidExitList hr=3D%08= lx", hr); @@ -1348,7 +1374,7 @@ static int whpx_accel_init(MachineState *ms) goto error; } =20 - hr =3D WHvSetupPartition(whpx->partition); + hr =3D whp_dispatch.WHvSetupPartition(whpx->partition); if (FAILED(hr)) { error_report("WHPX: Failed to setup partition, hr=3D%08lx", hr); ret =3D -EINVAL; @@ -1365,7 +1391,7 @@ static int whpx_accel_init(MachineState *ms) error: =20 if (NULL !=3D whpx->partition) { - WHvDeletePartition(whpx->partition); + whp_dispatch.WHvDeletePartition(whpx->partition); whpx->partition =3D NULL; } =20 @@ -1397,4 +1423,54 @@ static void whpx_type_init(void) type_register_static(&whpx_accel_type); } =20 +bool init_whp_dispatch(void) +{ + const char *lib_name; + HMODULE hLib; + + if (whp_dispatch_initialized) { + return true; + } + + #define WHP_LOAD_FIELD(return_type, function_name, signature) \ + whp_dispatch.function_name =3D \ + (function_name ## _t)GetProcAddress(hLib, #function_name); \ + if (!whp_dispatch.function_name) { \ + error_report("Could not load function %s from library %s.", \ + #function_name, lib_name); \ + goto error; \ + } \ + + lib_name =3D "WinHvPlatform.dll"; + hWinHvPlatform =3D LoadLibrary(lib_name); + if (!hWinHvPlatform) { + error_report("Could not load library %s.", lib_name); + goto error; + } + hLib =3D hWinHvPlatform; + LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD) + + lib_name =3D "WinHvEmulation.dll"; + hWinHvEmulation =3D LoadLibrary(lib_name); + if (!hWinHvEmulation) { + error_report("Could not load library %s.", lib_name); + goto error; + } + hLib =3D hWinHvEmulation; + LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD) + + whp_dispatch_initialized =3D true; + return true; + + error: + + if (hWinHvPlatform) { + FreeLibrary(hWinHvPlatform); + } + if (hWinHvEmulation) { + FreeLibrary(hWinHvEmulation); + } + return false; +} + type_init(whpx_type_init); --=20 2.17.0