WHPX: dynamically load WHP libraries
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 <apilotti@cloudbasesolutions.com> Signed-off-by: Justin Terry (VM) <juterry@microsoft.com> Signed-off-by: Lucian Petrut <lpetrut@cloudbasesolutions.com> Message-Id: <1526405722-10887-2-git-send-email-lpetrut@cloudbasesolutions.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
8347c18506
commit
327fccb288
15
configure
vendored
15
configure
vendored
|
@ -2524,20 +2524,7 @@ fi
|
||||||
##########################################
|
##########################################
|
||||||
# Windows Hypervisor Platform accelerator (WHPX) check
|
# Windows Hypervisor Platform accelerator (WHPX) check
|
||||||
if test "$whpx" != "no" ; then
|
if test "$whpx" != "no" ; then
|
||||||
cat > $TMPC << EOF
|
if check_include "WinHvPlatform.h" && check_include "WinHvEmulation.h"; then
|
||||||
#include <windows.h>
|
|
||||||
#include <WinHvPlatform.h>
|
|
||||||
#include <WinHvEmulation.h>
|
|
||||||
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="$libs_softmmu -lWinHvPlatform -lWinHvEmulation"
|
|
||||||
whpx="yes"
|
whpx="yes"
|
||||||
else
|
else
|
||||||
if test "$whpx" = "yes"; then
|
if test "$whpx" = "yes"; then
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include "qemu/queue.h"
|
#include "qemu/queue.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
#include "migration/blocker.h"
|
#include "migration/blocker.h"
|
||||||
|
#include "whp-dispatch.h"
|
||||||
|
|
||||||
#include <WinHvPlatform.h>
|
#include <WinHvPlatform.h>
|
||||||
#include <WinHvEmulation.h>
|
#include <WinHvEmulation.h>
|
||||||
|
@ -159,8 +160,11 @@ struct whpx_vcpu {
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool whpx_allowed;
|
static bool whpx_allowed;
|
||||||
|
static bool whp_dispatch_initialized;
|
||||||
|
static HMODULE hWinHvPlatform, hWinHvEmulation;
|
||||||
|
|
||||||
struct whpx_state whpx_global;
|
struct whpx_state whpx_global;
|
||||||
|
struct WHPDispatch whp_dispatch;
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -354,7 +358,8 @@ static void whpx_set_registers(CPUState *cpu)
|
||||||
|
|
||||||
assert(idx == RTL_NUMBER_OF(whpx_register_names));
|
assert(idx == RTL_NUMBER_OF(whpx_register_names));
|
||||||
|
|
||||||
hr = WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
|
||||||
|
whpx->partition, cpu->cpu_index,
|
||||||
whpx_register_names,
|
whpx_register_names,
|
||||||
RTL_NUMBER_OF(whpx_register_names),
|
RTL_NUMBER_OF(whpx_register_names),
|
||||||
&vcxt.values[0]);
|
&vcxt.values[0]);
|
||||||
|
@ -381,7 +386,8 @@ static void whpx_get_registers(CPUState *cpu)
|
||||||
|
|
||||||
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
|
assert(cpu_is_stopped(cpu) || qemu_cpu_is_self(cpu));
|
||||||
|
|
||||||
hr = WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvGetVirtualProcessorRegisters(
|
||||||
|
whpx->partition, cpu->cpu_index,
|
||||||
whpx_register_names,
|
whpx_register_names,
|
||||||
RTL_NUMBER_OF(whpx_register_names),
|
RTL_NUMBER_OF(whpx_register_names),
|
||||||
&vcxt.values[0]);
|
&vcxt.values[0]);
|
||||||
|
@ -544,7 +550,8 @@ static HRESULT CALLBACK whpx_emu_getreg_callback(
|
||||||
struct whpx_state *whpx = &whpx_global;
|
struct whpx_state *whpx = &whpx_global;
|
||||||
CPUState *cpu = (CPUState *)ctx;
|
CPUState *cpu = (CPUState *)ctx;
|
||||||
|
|
||||||
hr = WHvGetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvGetVirtualProcessorRegisters(
|
||||||
|
whpx->partition, cpu->cpu_index,
|
||||||
RegisterNames, RegisterCount,
|
RegisterNames, RegisterCount,
|
||||||
RegisterValues);
|
RegisterValues);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -565,7 +572,8 @@ static HRESULT CALLBACK whpx_emu_setreg_callback(
|
||||||
struct whpx_state *whpx = &whpx_global;
|
struct whpx_state *whpx = &whpx_global;
|
||||||
CPUState *cpu = (CPUState *)ctx;
|
CPUState *cpu = (CPUState *)ctx;
|
||||||
|
|
||||||
hr = WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
|
||||||
|
whpx->partition, cpu->cpu_index,
|
||||||
RegisterNames, RegisterCount,
|
RegisterNames, RegisterCount,
|
||||||
RegisterValues);
|
RegisterValues);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -594,7 +602,7 @@ static HRESULT CALLBACK whpx_emu_translate_callback(
|
||||||
CPUState *cpu = (CPUState *)ctx;
|
CPUState *cpu = (CPUState *)ctx;
|
||||||
WHV_TRANSLATE_GVA_RESULT res;
|
WHV_TRANSLATE_GVA_RESULT res;
|
||||||
|
|
||||||
hr = WHvTranslateGva(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvTranslateGva(whpx->partition, cpu->cpu_index,
|
||||||
Gva, TranslateFlags, &res, Gpa);
|
Gva, TranslateFlags, &res, Gpa);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to translate GVA, hr=%08lx", hr);
|
error_report("WHPX: Failed to translate GVA, hr=%08lx", hr);
|
||||||
|
@ -620,7 +628,8 @@ static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)
|
||||||
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
|
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
|
||||||
WHV_EMULATOR_STATUS emu_status;
|
WHV_EMULATOR_STATUS emu_status;
|
||||||
|
|
||||||
hr = WHvEmulatorTryMmioEmulation(vcpu->emulator, cpu,
|
hr = whp_dispatch.WHvEmulatorTryMmioEmulation(
|
||||||
|
vcpu->emulator, cpu,
|
||||||
&vcpu->exit_ctx.VpContext, ctx,
|
&vcpu->exit_ctx.VpContext, ctx,
|
||||||
&emu_status);
|
&emu_status);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -629,7 +638,8 @@ static int whpx_handle_mmio(CPUState *cpu, WHV_MEMORY_ACCESS_CONTEXT *ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!emu_status.EmulationSuccessful) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -643,7 +653,8 @@ static int whpx_handle_portio(CPUState *cpu,
|
||||||
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
|
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
|
||||||
WHV_EMULATOR_STATUS emu_status;
|
WHV_EMULATOR_STATUS emu_status;
|
||||||
|
|
||||||
hr = WHvEmulatorTryIoEmulation(vcpu->emulator, cpu,
|
hr = whp_dispatch.WHvEmulatorTryIoEmulation(
|
||||||
|
vcpu->emulator, cpu,
|
||||||
&vcpu->exit_ctx.VpContext, ctx,
|
&vcpu->exit_ctx.VpContext, ctx,
|
||||||
&emu_status);
|
&emu_status);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -652,7 +663,8 @@ static int whpx_handle_portio(CPUState *cpu,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!emu_status.EmulationSuccessful) {
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -767,7 +779,8 @@ static void whpx_vcpu_pre_run(CPUState *cpu)
|
||||||
qemu_mutex_unlock_iothread();
|
qemu_mutex_unlock_iothread();
|
||||||
|
|
||||||
if (reg_count) {
|
if (reg_count) {
|
||||||
hr = WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
|
||||||
|
whpx->partition, cpu->cpu_index,
|
||||||
reg_names, reg_count, reg_values);
|
reg_names, reg_count, reg_values);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to set interrupt state registers,"
|
error_report("WHPX: Failed to set interrupt state registers,"
|
||||||
|
@ -876,7 +889,8 @@ static int whpx_vcpu_run(CPUState *cpu)
|
||||||
whpx_vcpu_kick(cpu);
|
whpx_vcpu_kick(cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = WHvRunVirtualProcessor(whpx->partition, cpu->cpu_index,
|
hr = whp_dispatch.WHvRunVirtualProcessor(
|
||||||
|
whpx->partition, cpu->cpu_index,
|
||||||
&vcpu->exit_ctx, sizeof(vcpu->exit_ctx));
|
&vcpu->exit_ctx, sizeof(vcpu->exit_ctx));
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
|
@ -948,8 +962,8 @@ static int whpx_vcpu_run(CPUState *cpu)
|
||||||
reg_values[3].Reg64 = rdx;
|
reg_values[3].Reg64 = rdx;
|
||||||
reg_values[4].Reg64 = rbx;
|
reg_values[4].Reg64 = rbx;
|
||||||
|
|
||||||
hr = WHvSetVirtualProcessorRegisters(whpx->partition,
|
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
|
||||||
cpu->cpu_index,
|
whpx->partition, cpu->cpu_index,
|
||||||
reg_names,
|
reg_names,
|
||||||
reg_count,
|
reg_count,
|
||||||
reg_values);
|
reg_values);
|
||||||
|
@ -1064,8 +1078,8 @@ int whpx_init_vcpu(CPUState *cpu)
|
||||||
(void)migrate_add_blocker(whpx_migration_blocker, &local_error);
|
(void)migrate_add_blocker(whpx_migration_blocker, &local_error);
|
||||||
if (local_error) {
|
if (local_error) {
|
||||||
error_report_err(local_error);
|
error_report_err(local_error);
|
||||||
error_free(whpx_migration_blocker);
|
|
||||||
migrate_del_blocker(whpx_migration_blocker);
|
migrate_del_blocker(whpx_migration_blocker);
|
||||||
|
error_free(whpx_migration_blocker);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1077,7 +1091,9 @@ int whpx_init_vcpu(CPUState *cpu)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = WHvEmulatorCreateEmulator(&whpx_emu_callbacks, &vcpu->emulator);
|
hr = whp_dispatch.WHvEmulatorCreateEmulator(
|
||||||
|
&whpx_emu_callbacks,
|
||||||
|
&vcpu->emulator);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to setup instruction completion support,"
|
error_report("WHPX: Failed to setup instruction completion support,"
|
||||||
" hr=%08lx", hr);
|
" hr=%08lx", hr);
|
||||||
|
@ -1085,11 +1101,12 @@ int whpx_init_vcpu(CPUState *cpu)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = WHvCreateVirtualProcessor(whpx->partition, cpu->cpu_index, 0);
|
hr = whp_dispatch.WHvCreateVirtualProcessor(
|
||||||
|
whpx->partition, cpu->cpu_index, 0);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to create a virtual processor,"
|
error_report("WHPX: Failed to create a virtual processor,"
|
||||||
" hr=%08lx", hr);
|
" hr=%08lx", hr);
|
||||||
WHvEmulatorDestroyEmulator(vcpu->emulator);
|
whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
|
||||||
g_free(vcpu);
|
g_free(vcpu);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
@ -1130,8 +1147,8 @@ void whpx_destroy_vcpu(CPUState *cpu)
|
||||||
struct whpx_state *whpx = &whpx_global;
|
struct whpx_state *whpx = &whpx_global;
|
||||||
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
|
struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu);
|
||||||
|
|
||||||
WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
|
whp_dispatch.WHvDeleteVirtualProcessor(whpx->partition, cpu->cpu_index);
|
||||||
WHvEmulatorDestroyEmulator(vcpu->emulator);
|
whp_dispatch.WHvEmulatorDestroyEmulator(vcpu->emulator);
|
||||||
g_free(cpu->hax_vcpu);
|
g_free(cpu->hax_vcpu);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1139,7 +1156,8 @@ void whpx_destroy_vcpu(CPUState *cpu)
|
||||||
void whpx_vcpu_kick(CPUState *cpu)
|
void whpx_vcpu_kick(CPUState *cpu)
|
||||||
{
|
{
|
||||||
struct whpx_state *whpx = &whpx_global;
|
struct whpx_state *whpx = &whpx_global;
|
||||||
WHvCancelRunVirtualProcessor(whpx->partition, cpu->cpu_index, 0);
|
whp_dispatch.WHvCancelRunVirtualProcessor(
|
||||||
|
whpx->partition, cpu->cpu_index, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1165,7 +1183,7 @@ static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (add) {
|
if (add) {
|
||||||
hr = WHvMapGpaRange(whpx->partition,
|
hr = whp_dispatch.WHvMapGpaRange(whpx->partition,
|
||||||
host_va,
|
host_va,
|
||||||
start_pa,
|
start_pa,
|
||||||
size,
|
size,
|
||||||
|
@ -1173,7 +1191,7 @@ static void whpx_update_mapping(hwaddr start_pa, ram_addr_t size,
|
||||||
WHvMapGpaRangeFlagExecute |
|
WHvMapGpaRangeFlagExecute |
|
||||||
(rom ? 0 : WHvMapGpaRangeFlagWrite)));
|
(rom ? 0 : WHvMapGpaRangeFlagWrite)));
|
||||||
} else {
|
} else {
|
||||||
hr = WHvUnmapGpaRange(whpx->partition,
|
hr = whp_dispatch.WHvUnmapGpaRange(whpx->partition,
|
||||||
start_pa,
|
start_pa,
|
||||||
size);
|
size);
|
||||||
}
|
}
|
||||||
|
@ -1289,10 +1307,16 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
|
|
||||||
whpx = &whpx_global;
|
whpx = &whpx_global;
|
||||||
|
|
||||||
|
if (!init_whp_dispatch()) {
|
||||||
|
ret = -ENOSYS;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
memset(whpx, 0, sizeof(struct whpx_state));
|
memset(whpx, 0, sizeof(struct whpx_state));
|
||||||
whpx->mem_quota = ms->ram_size;
|
whpx->mem_quota = ms->ram_size;
|
||||||
|
|
||||||
hr = WHvGetCapability(WHvCapabilityCodeHypervisorPresent, &whpx_cap,
|
hr = whp_dispatch.WHvGetCapability(
|
||||||
|
WHvCapabilityCodeHypervisorPresent, &whpx_cap,
|
||||||
sizeof(whpx_cap), &whpx_cap_size);
|
sizeof(whpx_cap), &whpx_cap_size);
|
||||||
if (FAILED(hr) || !whpx_cap.HypervisorPresent) {
|
if (FAILED(hr) || !whpx_cap.HypervisorPresent) {
|
||||||
error_report("WHPX: No accelerator found, hr=%08lx", hr);
|
error_report("WHPX: No accelerator found, hr=%08lx", hr);
|
||||||
|
@ -1300,7 +1324,7 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = WHvCreatePartition(&whpx->partition);
|
hr = whp_dispatch.WHvCreatePartition(&whpx->partition);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to create partition, hr=%08lx", hr);
|
error_report("WHPX: Failed to create partition, hr=%08lx", hr);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -1309,7 +1333,8 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
|
|
||||||
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
|
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
|
||||||
prop.ProcessorCount = smp_cpus;
|
prop.ProcessorCount = smp_cpus;
|
||||||
hr = WHvSetPartitionProperty(whpx->partition,
|
hr = whp_dispatch.WHvSetPartitionProperty(
|
||||||
|
whpx->partition,
|
||||||
WHvPartitionPropertyCodeProcessorCount,
|
WHvPartitionPropertyCodeProcessorCount,
|
||||||
&prop,
|
&prop,
|
||||||
sizeof(WHV_PARTITION_PROPERTY));
|
sizeof(WHV_PARTITION_PROPERTY));
|
||||||
|
@ -1323,7 +1348,8 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
|
|
||||||
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
|
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
|
||||||
prop.ExtendedVmExits.X64CpuidExit = 1;
|
prop.ExtendedVmExits.X64CpuidExit = 1;
|
||||||
hr = WHvSetPartitionProperty(whpx->partition,
|
hr = whp_dispatch.WHvSetPartitionProperty(
|
||||||
|
whpx->partition,
|
||||||
WHvPartitionPropertyCodeExtendedVmExits,
|
WHvPartitionPropertyCodeExtendedVmExits,
|
||||||
&prop,
|
&prop,
|
||||||
sizeof(WHV_PARTITION_PROPERTY));
|
sizeof(WHV_PARTITION_PROPERTY));
|
||||||
|
@ -1336,11 +1362,11 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT32 cpuidExitList[] = {1};
|
UINT32 cpuidExitList[] = {1};
|
||||||
hr = WHvSetPartitionProperty(whpx->partition,
|
hr = whp_dispatch.WHvSetPartitionProperty(
|
||||||
|
whpx->partition,
|
||||||
WHvPartitionPropertyCodeCpuidExitList,
|
WHvPartitionPropertyCodeCpuidExitList,
|
||||||
cpuidExitList,
|
cpuidExitList,
|
||||||
RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32));
|
RTL_NUMBER_OF(cpuidExitList) * sizeof(UINT32));
|
||||||
|
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx",
|
error_report("WHPX: Failed to set partition CpuidExitList hr=%08lx",
|
||||||
hr);
|
hr);
|
||||||
|
@ -1348,7 +1374,7 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
hr = WHvSetupPartition(whpx->partition);
|
hr = whp_dispatch.WHvSetupPartition(whpx->partition);
|
||||||
if (FAILED(hr)) {
|
if (FAILED(hr)) {
|
||||||
error_report("WHPX: Failed to setup partition, hr=%08lx", hr);
|
error_report("WHPX: Failed to setup partition, hr=%08lx", hr);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
|
@ -1365,7 +1391,7 @@ static int whpx_accel_init(MachineState *ms)
|
||||||
error:
|
error:
|
||||||
|
|
||||||
if (NULL != whpx->partition) {
|
if (NULL != whpx->partition) {
|
||||||
WHvDeletePartition(whpx->partition);
|
whp_dispatch.WHvDeletePartition(whpx->partition);
|
||||||
whpx->partition = NULL;
|
whpx->partition = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1397,4 +1423,54 @@ static void whpx_type_init(void)
|
||||||
type_register_static(&whpx_accel_type);
|
type_register_static(&whpx_accel_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 = \
|
||||||
|
(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 = "WinHvPlatform.dll";
|
||||||
|
hWinHvPlatform = LoadLibrary(lib_name);
|
||||||
|
if (!hWinHvPlatform) {
|
||||||
|
error_report("Could not load library %s.", lib_name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
hLib = hWinHvPlatform;
|
||||||
|
LIST_WINHVPLATFORM_FUNCTIONS(WHP_LOAD_FIELD)
|
||||||
|
|
||||||
|
lib_name = "WinHvEmulation.dll";
|
||||||
|
hWinHvEmulation = LoadLibrary(lib_name);
|
||||||
|
if (!hWinHvEmulation) {
|
||||||
|
error_report("Could not load library %s.", lib_name);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
hLib = hWinHvEmulation;
|
||||||
|
LIST_WINHVEMULATION_FUNCTIONS(WHP_LOAD_FIELD)
|
||||||
|
|
||||||
|
whp_dispatch_initialized = true;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
error:
|
||||||
|
|
||||||
|
if (hWinHvPlatform) {
|
||||||
|
FreeLibrary(hWinHvPlatform);
|
||||||
|
}
|
||||||
|
if (hWinHvEmulation) {
|
||||||
|
FreeLibrary(hWinHvEmulation);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
type_init(whpx_type_init);
|
type_init(whpx_type_init);
|
||||||
|
|
Loading…
Reference in a new issue