Paul Gofman : wineboot: Initialize XState features in user_shared_data.

Alexandre Julliard julliard at winehq.org
Thu Aug 20 16:03:36 CDT 2020


Module: wine
Branch: master
Commit: 97b5ad7597bf2add39251d7379fc607bf1578478
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=97b5ad7597bf2add39251d7379fc607bf1578478

Author: Paul Gofman <pgofman at codeweavers.com>
Date:   Thu Aug 20 00:22:59 2020 +0300

wineboot: Initialize XState features in user_shared_data.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/tests/virtual.c   | 67 ++++++++++++++++++++++++++++++++++++++++++++
 programs/wineboot/wineboot.c | 59 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 126 insertions(+)

diff --git a/dlls/ntdll/tests/virtual.c b/dlls/ntdll/tests/virtual.c
index beab744178..4a0a4a6b8e 100644
--- a/dlls/ntdll/tests/virtual.c
+++ b/dlls/ntdll/tests/virtual.c
@@ -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)
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index 902f6af042..2f8b7169cf 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -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 );
 }
 




More information about the wine-cvs mailing list