WHPX: support for xcr0

Support for xcr0 to be able to enable xsave/xrstor. This by itself
is not sufficient to enable xsave/xrstor. WHPX XSAVE API's also
needs to be hooked up.

Signed-off-by: Sunil Muthuswamy <sunilmut@microsoft.com>
Message-Id: <MW2PR2101MB1116F07C07A26FD7A7ED8DCFC0780@MW2PR2101MB1116.namprd21.prod.outlook.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Sunil Muthuswamy 2019-11-07 19:48:32 +00:00 committed by Paolo Bonzini
parent 13220a46e2
commit b6b3da9998
2 changed files with 90 additions and 0 deletions

View File

@ -246,9 +246,15 @@ static bool whpx_allowed;
static bool whp_dispatch_initialized;
static HMODULE hWinHvPlatform, hWinHvEmulation;
static uint32_t max_vcpu_index;
static WHV_PROCESSOR_XSAVE_FEATURES whpx_xsave_cap;
struct whpx_state whpx_global;
struct WHPDispatch whp_dispatch;
static bool whpx_has_xsave(void)
{
return whpx_xsave_cap.XsaveSupport;
}
/*
* VP support
@ -300,6 +306,28 @@ static SegmentCache whpx_seg_h2q(const WHV_X64_SEGMENT_REGISTER *hs)
return qs;
}
/* X64 Extended Control Registers */
static void whpx_set_xcrs(CPUState *cpu)
{
CPUX86State *env = cpu->env_ptr;
HRESULT hr;
struct whpx_state *whpx = &whpx_global;
WHV_REGISTER_VALUE xcr0;
WHV_REGISTER_NAME xcr0_name = WHvX64RegisterXCr0;
if (!whpx_has_xsave()) {
return;
}
/* Only xcr0 is supported by the hypervisor currently */
xcr0.Reg64 = env->xcr0;
hr = whp_dispatch.WHvSetVirtualProcessorRegisters(
whpx->partition, cpu->cpu_index, &xcr0_name, 1, &xcr0);
if (FAILED(hr)) {
error_report("WHPX: Failed to set register xcr0, hr=%08lx", hr);
}
}
static int whpx_set_tsc(CPUState *cpu)
{
CPUX86State *env = cpu->env_ptr;
@ -435,6 +463,12 @@ static void whpx_set_registers(CPUState *cpu, int level)
/* 8 Debug Registers - Skipped */
/*
* Extended control registers needs to be handled separately depending
* on whether xsave is supported/enabled or not.
*/
whpx_set_xcrs(cpu);
/* 16 XMM registers */
assert(whpx_register_names[idx] == WHvX64RegisterXmm0);
idx_next = idx + 16;
@ -541,6 +575,30 @@ static int whpx_get_tsc(CPUState *cpu)
return 0;
}
/* X64 Extended Control Registers */
static void whpx_get_xcrs(CPUState *cpu)
{
CPUX86State *env = cpu->env_ptr;
HRESULT hr;
struct whpx_state *whpx = &whpx_global;
WHV_REGISTER_VALUE xcr0;
WHV_REGISTER_NAME xcr0_name = WHvX64RegisterXCr0;
if (!whpx_has_xsave()) {
return;
}
/* Only xcr0 is supported by the hypervisor currently */
hr = whp_dispatch.WHvGetVirtualProcessorRegisters(
whpx->partition, cpu->cpu_index, &xcr0_name, 1, &xcr0);
if (FAILED(hr)) {
error_report("WHPX: Failed to get register xcr0, hr=%08lx", hr);
return;
}
env->xcr0 = xcr0.Reg64;
}
static void whpx_get_registers(CPUState *cpu)
{
struct whpx_state *whpx = &whpx_global;
@ -634,6 +692,12 @@ static void whpx_get_registers(CPUState *cpu)
/* 8 Debug Registers - Skipped */
/*
* Extended control registers needs to be handled separately depending
* on whether xsave is supported/enabled or not.
*/
whpx_get_xcrs(cpu);
/* 16 XMM registers */
assert(whpx_register_names[idx] == WHvX64RegisterXmm0);
idx_next = idx + 16;
@ -2513,6 +2577,29 @@ static int whpx_accel_init(MachineState *ms)
goto error;
}
/*
* Query the XSAVE capability of the partition. Any error here is not
* considered fatal.
*/
hr = whp_dispatch.WHvGetPartitionProperty(
whpx->partition,
WHvPartitionPropertyCodeProcessorXsaveFeatures,
&whpx_xsave_cap,
sizeof(whpx_xsave_cap),
&whpx_cap_size);
/*
* Windows version which don't support this property will return with the
* specific error code.
*/
if (FAILED(hr) && hr != WHV_E_UNKNOWN_PROPERTY) {
error_report("WHPX: Failed to query XSAVE capability, hr=%08lx", hr);
}
if (!whpx_has_xsave()) {
printf("WHPX: Partition is not XSAVE capable\n");
}
memset(&prop, 0, sizeof(WHV_PARTITION_PROPERTY));
prop.ProcessorCount = ms->smp.cpus;
hr = whp_dispatch.WHvSetPartitionProperty(

View File

@ -48,6 +48,9 @@ void whpx_apic_get(DeviceState *s);
#define WHV_E_UNKNOWN_CAPABILITY 0x80370300L
/* This should eventually come from the Windows SDK */
#define WHV_E_UNKNOWN_PROPERTY 0x80370302
#define LIST_WINHVPLATFORM_FUNCTIONS(X) \
X(HRESULT, WHvGetCapability, (WHV_CAPABILITY_CODE CapabilityCode, VOID* CapabilityBuffer, UINT32 CapabilityBufferSizeInBytes, UINT32* WrittenSizeInBytes)) \
X(HRESULT, WHvCreatePartition, (WHV_PARTITION_HANDLE* Partition)) \