Working with XState Context
This document contains an example that demonstrates how to use the XState context functions to retrieve and set extended features on a thread. The following examples manipulate Intel Advanced Vector Extensions (AVX) state which is defined by FeatureId 2 (Feature Mask 4). Intel AVX is defined in the "Intel Advanced Vector Extensions Programming Reference" available from http://go.microsoft.com/fwlink/p/?linkid=212716.
Windows 7 with SP1: The AVX API is first implemented on Windows 7 with SP1. Since there is no SDK for Windows 7 with SP1, that means there are no available headers and library files to work with. In this situation, a caller must declare the needed functions from this documentation and get pointers to them using GetModuleHandle on "Kernel32.dll", followed by calls to GetProcAddress.
#include <stdlib.h> #include <stdio.h> #include <tchar.h> #include <windows.h> #include <winerror.h> // Windows 7 SP1 is the first version of Windows to support the AVX API. // The value for CONTEXT_XSTATE has changed between Windows 7 and // Windows 7 SP1 and greater. // While the value will be correct for future SDK headers, we need to set // this value manually when building with a Windows 7 SDK for running on // Windows 7 SPI OS bits. #undef CONTEXT_XSTATE #if defined(_M_X64) #define CONTEXT_XSTATE (0x00100040) #else #define CONTEXT_XSTATE (0x00010040) #endif // Since the AVX API is not declared in the Windows 7 SDK headers and // since we don't have the proper libs to work with, we will declare // the API as function pointers and get them with GetProcAddress calls // from kernel32.dll. We also need to set some #defines. #define XSTATE_AVX (XSTATE_GSSE) #define XSTATE_MASK_AVX (XSTATE_MASK_GSSE) typedef DWORD64 (WINAPI *PGETENABLEDXSTATEFEATURES)(); PGETENABLEDXSTATEFEATURES pfnGetEnabledXStateFeatures = NULL; typedef BOOL (WINAPI *PINITIALIZECONTEXT)(PVOID Buffer, DWORD ContextFlags, PCONTEXT* Context, PDWORD ContextLength); PINITIALIZECONTEXT pfnInitializeContext = NULL; typedef BOOL (WINAPI *PGETXSTATEFEATURESMASK)(PCONTEXT Context, PDWORD64 FeatureMask); PGETXSTATEFEATURESMASK pfnGetXStateFeaturesMask = NULL; typedef PVOID (WINAPI *LOCATEXSTATEFEATURE)(PCONTEXT Context, DWORD FeatureId, PDWORD Length); LOCATEXSTATEFEATURE pfnLocateXStateFeature = NULL; typedef BOOL (WINAPI *SETXSTATEFEATURESMASK)(PCONTEXT Context, DWORD64 FeatureMask); SETXSTATEFEATURESMASK pfnSetXStateFeaturesMask = NULL; VOID PrintThreadAvxState ( __in HANDLE hThread ) { PVOID Buffer; PCONTEXT Context; DWORD ContextSize; DWORD64 FeatureMask; DWORD FeatureLength; ULONG Index; BOOL Success; PM128A Xmm; PM128A Ymm; // If this function was called before and we were not running on // at least Windws 7 SP1, then bail. if (pfnGetEnabledXStateFeatures == (PGETENABLEDXSTATEFEATURES)-1) { _tprintf(_T("This needs to run on Windows 7 SP1 or greater.\n")); return; } // Get the addresses of the AVX XState functions. if (pfnGetEnabledXStateFeatures == NULL) { HMODULE hm = GetModuleHandle(_T("kernel32.dll")); if (hm == NULL) { pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1; _tprintf(_T("GetModuleHandle failed (error == %d).\n"), GetLastError()); return; } pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)GetProcAddress(hm, "GetEnabledXStateFeatures"); pfnInitializeContext = (PINITIALIZECONTEXT)GetProcAddress(hm, "InitializeContext"); pfnGetXStateFeaturesMask = (PGETXSTATEFEATURESMASK)GetProcAddress(hm, "GetXStateFeaturesMask"); pfnLocateXStateFeature = (LOCATEXSTATEFEATURE)GetProcAddress(hm, "LocateXStateFeature"); pfnSetXStateFeaturesMask = (SETXSTATEFEATURESMASK)GetProcAddress(hm, "SetXStateFeaturesMask"); if (pfnGetEnabledXStateFeatures == NULL || pfnInitializeContext == NULL || pfnGetXStateFeaturesMask == NULL || pfnLocateXStateFeature == NULL || pfnSetXStateFeaturesMask == NULL) { pfnGetEnabledXStateFeatures = (PGETENABLEDXSTATEFEATURES)-1; _tprintf(_T("This needs to run on Windows 7 SP1 or greater.\n")); return; } } FeatureMask = pfnGetEnabledXStateFeatures(); if ((FeatureMask & XSTATE_MASK_AVX) == 0) { _tprintf(_T("The AVX feature is not enabled.\n")); return; } ContextSize = 0; Success = pfnInitializeContext(NULL, CONTEXT_ALL | CONTEXT_XSTATE, NULL, &ContextSize); if ((Success == TRUE) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) { _tprintf(_T("Unexpected result from InitializeContext (success == %d, error == %d).\n"), Success, GetLastError()); } Buffer = malloc(ContextSize); if (Buffer == NULL) { _tprintf(_T("Out of memory.\n")); return; } Success = pfnInitializeContext(Buffer, CONTEXT_ALL | CONTEXT_XSTATE, &Context, &ContextSize); if (Success == FALSE) { _tprintf(_T("InitializeContext failed (error == %d).\n"), GetLastError()); goto Cleanup; } Success = pfnSetXStateFeaturesMask(Context, XSTATE_MASK_AVX); if (Success == FALSE) { _tprintf(_T("SetXStateFeaturesMask failed (error == %d).\n"), GetLastError()); goto Cleanup; } Success = GetThreadContext(hThread, Context); // Note: Thread state may not be accurate. For best results, suspend // the thread and use the CONTEXT_EXCEPTION_REQUEST flags prior to // calling GetThreadContext. if (Success == FALSE) { _tprintf(_T("GetThreadContext failed (error == %d).\n"), GetLastError()); goto Cleanup; } Success = pfnGetXStateFeaturesMask(Context, &FeatureMask); if (Success == FALSE) { _tprintf(_T("GetXStateFeatureMask failed (error == %d).\n"), GetLastError()); goto Cleanup; } // // The AVX feature consists of 8 (x86) or 16 (x64) 256-bit Ymm registers. // The lower 128 bits share storage with the corresponding Xmm (SSE) // registers and the high 128 bits are denoted by Ymm_H0 - Ymm_Hn. // if ((FeatureMask & XSTATE_MASK_AVX) == 0) { _tprintf(_T("AVX is in the INIT state (YMM_H registers are all zero).\n")); goto Cleanup; } Xmm = (PM128A)pfnLocateXStateFeature(Context, XSTATE_LEGACY_SSE, &FeatureLength); Ymm = (PM128A)pfnLocateXStateFeature(Context, XSTATE_AVX, NULL); // // Print values in the YMM registers. // for (Index = 0; Index < FeatureLength / sizeof(Xmm[0]); Index += 1) { _tprintf(_T("Ymm%d: %I64d %I64d %I64d %I64d\n"), Index, Xmm[Index].Low, Xmm[Index].High, Ymm[Index].Low, Ymm[Index].High); } Cleanup: free(Buffer); return; }
Related topics
- CopyContext
- InitializeContext
- GetEnabledXStateFeatures
- LocateXStateFeature
- GetXStateFeaturesMask
- SetXStateFeaturesMask