wineboot: Initialize XState features in user_shared_data.

Signed-off-by: Paul Gofman <pgofman@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Paul Gofman 2020-08-20 00:22:59 +03:00 committed by Alexandre Julliard
parent 0e544824f5
commit 97b5ad7597
2 changed files with 126 additions and 0 deletions

View File

@ -516,9 +516,34 @@ static void test_NtMapViewOfSection(void)
CloseHandle(process);
}
#define SUPPORTED_XSTATE_FEATURES ((1 << XSTATE_LEGACY_FLOATING_POINT) | (1 << XSTATE_LEGACY_SSE) | (1 << XSTATE_AVX))
static void test_user_shared_data(void)
{
struct old_xstate_configuration
{
ULONG64 EnabledFeatures;
ULONG Size;
ULONG OptimizedSave:1;
ULONG CompactionEnabled:1;
XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES];
};
static const ULONG feature_offsets[] =
{
0,
160, /*offsetof(XMM_SAVE_AREA32, XmmRegisters)*/
512 /* sizeof(XMM_SAVE_AREA32) */ + offsetof(XSTATE, YmmContext),
};
static const ULONG feature_sizes[] =
{
160,
256, /*sizeof(M128A) * 16 */
sizeof(YMMCONTEXT),
};
const KSHARED_USER_DATA *user_shared_data = (void *)0x7ffe0000;
XSTATE_CONFIGURATION xstate = user_shared_data->XState;
unsigned int i;
ok(user_shared_data->NumberOfPhysicalPages == sbi.MmNumberOfPhysicalPages,
"Got number of physical pages %#x, expected %#x.\n",
@ -534,6 +559,48 @@ static void test_user_shared_data(void)
ok(user_shared_data->ActiveGroupCount == 1
|| broken(!user_shared_data->ActiveGroupCount) /* before Win7 */,
"Got unexpected ActiveGroupCount %u.\n", user_shared_data->ActiveGroupCount);
if (!xstate.EnabledFeatures)
{
struct old_xstate_configuration *xs_old
= (struct old_xstate_configuration *)((char *)user_shared_data + 0x3e0);
if (!xs_old->EnabledFeatures)
{
skip("XState features are not supported.\n");
return;
}
memset(&xstate, 0, sizeof(xstate));
xstate.EnabledFeatures = xstate.EnabledVolatileFeatures = xs_old->EnabledFeatures;
memcpy(&xstate.Size, &xs_old->Size, sizeof(*xs_old) - offsetof(struct old_xstate_configuration, Size));
for (i = 0; i < 3; ++i)
xstate.AllFeatures[i] = xs_old->Features[i].Size;
xstate.AllFeatureSize = 512 + sizeof(XSTATE);
}
trace("XState EnabledFeatures %s.\n", wine_dbgstr_longlong(xstate.EnabledFeatures));
ok((xstate.EnabledFeatures & SUPPORTED_XSTATE_FEATURES) == SUPPORTED_XSTATE_FEATURES,
"Got unexpected EnabledFeatures %s.\n", wine_dbgstr_longlong(xstate.EnabledFeatures));
ok((xstate.EnabledVolatileFeatures & SUPPORTED_XSTATE_FEATURES) == xstate.EnabledFeatures,
"Got unexpected EnabledVolatileFeatures %s.\n", wine_dbgstr_longlong(xstate.EnabledVolatileFeatures));
ok(xstate.Size >= 512 + sizeof(XSTATE), "Got unexpected Size %u.\n", xstate.Size);
if (xstate.CompactionEnabled)
ok(xstate.OptimizedSave, "Got zero OptimizedSave with compaction enabled.\n");
ok(!xstate.AlignedFeatures, "Got unexpected AlignedFeatures %s.\n",
wine_dbgstr_longlong(xstate.AlignedFeatures));
ok(xstate.AllFeatureSize >= 512 + sizeof(XSTATE), "Got unexpected AllFeatureSize %u.\n",
xstate.AllFeatureSize);
for (i = 0; i < ARRAY_SIZE(feature_sizes); ++i)
{
ok(xstate.AllFeatures[i] == feature_sizes[i], "Got unexpected AllFeatures[%u] %u, expected %u.\n", i,
xstate.AllFeatures[i], feature_sizes[i]);
ok(xstate.Features[i].Size == feature_sizes[i], "Got unexpected Features[%u].Size %u, expected %u.\n", i,
xstate.Features[i].Size, feature_sizes[i]);
ok(xstate.Features[i].Offset == feature_offsets[i], "Got unexpected Features[%u].Offset %u, expected %u.\n",
i, xstate.Features[i].Offset, feature_offsets[i]);
}
}
START_TEST(virtual)

View File

@ -191,6 +191,63 @@ static DWORD set_reg_value_dword( HKEY hkey, const WCHAR *name, DWORD value )
return RegSetValueExW( hkey, name, 0, REG_DWORD, (const BYTE *)&value, sizeof(value) );
}
#if defined(__i386__) || defined(__x86_64__)
static void initialize_xstate_features(struct _KUSER_SHARED_DATA *data)
{
XSTATE_CONFIGURATION *xstate = &data->XState;
unsigned int i;
int regs[4];
if (!data->ProcessorFeatures[PF_AVX_INSTRUCTIONS_AVAILABLE])
return;
__cpuidex(regs, 0, 0);
TRACE("Max cpuid level %#x.\n", regs[0]);
if (regs[0] < 0xd)
return;
__cpuidex(regs, 1, 0);
TRACE("CPU features %#x, %#x, %#x, %#x.\n", regs[0], regs[1], regs[2], regs[3]);
if (!(regs[2] & (0x1 << 27))) /* xsave OS enabled */
return;
__cpuidex(regs, 0xd, 0);
TRACE("XSAVE details %#x, %#x, %#x, %#x.\n", regs[0], regs[1], regs[2], regs[3]);
if (!(regs[0] & XSTATE_AVX))
return;
xstate->EnabledFeatures = (1 << XSTATE_LEGACY_FLOATING_POINT) | (1 << XSTATE_LEGACY_SSE) | (1 << XSTATE_AVX);
xstate->EnabledVolatileFeatures = xstate->EnabledFeatures;
xstate->Size = sizeof(XSAVE_FORMAT) + sizeof(XSTATE);
xstate->AllFeatureSize = regs[1];
xstate->AllFeatures[0] = offsetof(XSAVE_FORMAT, XmmRegisters);
xstate->AllFeatures[1] = sizeof(M128A) * 16;
xstate->AllFeatures[2] = sizeof(YMMCONTEXT);
for (i = 0; i < 3; ++i)
xstate->Features[i].Size = xstate->AllFeatures[i];
xstate->Features[1].Offset = xstate->Features[0].Size;
xstate->Features[2].Offset = sizeof(XSAVE_FORMAT) + offsetof(XSTATE, YmmContext);
__cpuidex(regs, 0xd, 1);
xstate->OptimizedSave = regs[0] & 1;
xstate->CompactionEnabled = !!(regs[0] & 2);
__cpuidex(regs, 0xd, 2);
TRACE("XSAVE feature 2 %#x, %#x, %#x, %#x.\n", regs[0], regs[1], regs[2], regs[3]);
}
#else
static void initialize_xstate_features(struct _KUSER_SHARED_DATA *data)
{
}
#endif
static void create_user_shared_data(void)
{
struct _KUSER_SHARED_DATA *data;
@ -276,6 +333,8 @@ static void create_user_shared_data(void)
data->ActiveProcessorCount = NtCurrentTeb()->Peb->NumberOfProcessors;
data->ActiveGroupCount = 1;
initialize_xstate_features( data );
UnmapViewOfFile( data );
}