diff --git a/src/common/platform/platform.hpp b/src/common/platform/platform.hpp index b6ff1afb..91490952 100644 --- a/src/common/platform/platform.hpp +++ b/src/common/platform/platform.hpp @@ -25,15 +25,6 @@ #include "threading.hpp" #ifdef OS_WINDOWS -#pragma comment(lib, "ntdll") - -extern "C" -{ - NTSYSCALLAPI NTSTATUS NTAPI NtQuerySystemInformationEx( - _In_ SYSTEM_INFORMATION_CLASS SystemInformationClass, _In_reads_bytes_(InputBufferLength) PVOID InputBuffer, - _In_ ULONG InputBufferLength, _Out_writes_bytes_opt_(SystemInformationLength) PVOID SystemInformation, - _In_ ULONG SystemInformationLength, _Out_opt_ PULONG ReturnLength); -} #pragma warning(pop) #else #pragma GCC diagnostic pop diff --git a/src/common/platform/primitives.hpp b/src/common/platform/primitives.hpp index 36f6b6a3..ffec4630 100644 --- a/src/common/platform/primitives.hpp +++ b/src/common/platform/primitives.hpp @@ -11,7 +11,12 @@ #else -#define DWORD std::uint32_t +#define _Field_size_(...) +#define _Struct_size_bytes_(...) + +#define ANYSIZE_ARRAY 1 + +#define DWORD std::uint32_t using LONG = std::int32_t; using ULONG = DWORD; using DWORD64 = std::uint64_t; @@ -41,14 +46,14 @@ typedef union _LARGE_INTEGER } LARGE_INTEGER; using BYTE = std::uint8_t; -#define CHAR BYTE +#define CHAR BYTE #endif using WORD = std::uint16_t; #define UCHAR unsigned char - #define BOOLEAN bool + using CSHORT = short; using USHORT = WORD; diff --git a/src/common/platform/process.hpp b/src/common/platform/process.hpp index 79e41741..8467c2f9 100644 --- a/src/common/platform/process.hpp +++ b/src/common/platform/process.hpp @@ -905,3 +905,92 @@ struct EMU_RTL_SRWLOCK { typename Traits::PVOID Ptr; }; + +#ifndef OS_WINDOWS +typedef enum _PROCESSOR_CACHE_TYPE +{ + CacheUnified, + CacheInstruction, + CacheData, + CacheTrace +} PROCESSOR_CACHE_TYPE; + +typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP +{ + RelationProcessorCore, + RelationNumaNode, + RelationCache, + RelationProcessorPackage, + RelationGroup, + RelationProcessorDie, + RelationNumaNodeEx, + RelationProcessorModule, + RelationAll = 0xffff +} LOGICAL_PROCESSOR_RELATIONSHIP; +#endif + +struct EMU_NUMA_NODE_RELATIONSHIP64 +{ + DWORD NodeNumber; + BYTE Reserved[18]; + WORD GroupCount; + union + { + EMU_GROUP_AFFINITY64 GroupMask; + _Field_size_(GroupCount) EMU_GROUP_AFFINITY64 GroupMasks[ANYSIZE_ARRAY]; + }; +}; + +struct EMU_CACHE_RELATIONSHIP64 +{ + BYTE Level; + BYTE Associativity; + WORD LineSize; + DWORD CacheSize; + PROCESSOR_CACHE_TYPE Type; + BYTE Reserved[18]; + WORD GroupCount; + union + { + EMU_GROUP_AFFINITY64 GroupMask; + _Field_size_(GroupCount) EMU_GROUP_AFFINITY64 GroupMasks[ANYSIZE_ARRAY]; + }; +}; + +struct EMU_PROCESSOR_GROUP_INFO64 +{ + BYTE MaximumProcessorCount; + BYTE ActiveProcessorCount; + BYTE Reserved[38]; + EMULATOR_CAST(std::uint64_t, KAFFINITY) ActiveProcessorMask; +}; + +struct EMU_GROUP_RELATIONSHIP64 +{ + WORD MaximumGroupCount; + WORD ActiveGroupCount; + BYTE Reserved[20]; + _Field_size_(ActiveGroupCount) EMU_PROCESSOR_GROUP_INFO64 GroupInfo[ANYSIZE_ARRAY]; +}; + +struct EMU_PROCESSOR_RELATIONSHIP64 +{ + BYTE Flags; + BYTE EfficiencyClass; + BYTE Reserved[20]; + WORD GroupCount; + _Field_size_(GroupCount) EMU_GROUP_AFFINITY64 GroupMask[ANYSIZE_ARRAY]; +}; + +_Struct_size_bytes_(Size) struct EMU_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX64 +{ + LOGICAL_PROCESSOR_RELATIONSHIP Relationship; + DWORD Size; + union + { + EMU_PROCESSOR_RELATIONSHIP64 Processor; + EMU_NUMA_NODE_RELATIONSHIP64 NumaNode; + EMU_CACHE_RELATIONSHIP64 Cache; + EMU_GROUP_RELATIONSHIP64 Group; + }; +}; diff --git a/src/common/platform/status.hpp b/src/common/platform/status.hpp index ade2a62f..ceecb0d9 100644 --- a/src/common/platform/status.hpp +++ b/src/common/platform/status.hpp @@ -26,6 +26,7 @@ using NTSTATUS = std::uint32_t; #define STATUS_NO_MORE_FILES ((NTSTATUS)0x80000006L) +#define STATUS_INFO_LENGTH_MISMATCH ((NTSTATUS)0xC0000004L) #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) #define STATUS_OBJECT_NAME_NOT_FOUND ((NTSTATUS)0xC0000034L) diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index 87dc09e4..d5e6d1ad 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1067,39 +1067,83 @@ namespace info_class == SystemSupportedProcessorArchitectures2 || info_class == SystemFeatureConfigurationSectionInformation) { - // printf("Unsupported, but allowed system info class: %X\n", info_class); return STATUS_NOT_SUPPORTED; } if (info_class == SystemLogicalProcessorAndGroupInformation) { - void* buffer = calloc(1, input_buffer_length); - void* res_buff = calloc(1, system_information_length); - c.emu.read_memory(input_buffer, buffer, input_buffer_length); - - NTSTATUS code = STATUS_SUCCESS; - - return_length.access([&](uint32_t& len) { - (void)len; -#ifdef OS_WINDOWS - code = NtQuerySystemInformationEx(static_cast(info_class), buffer, - input_buffer_length, res_buff, system_information_length, - reinterpret_cast(&len)); -#else - // TODO: unsupported - code = STATUS_SUCCESS; -#endif - }); - - if (code == 0) + if (input_buffer_length != sizeof(LOGICAL_PROCESSOR_RELATIONSHIP)) { - c.emu.write_memory(system_information, res_buff, return_length.read()); + return STATUS_INVALID_PARAMETER; } - free(buffer); - free(res_buff); + const auto request = c.emu.read_memory(input_buffer); - return code; + if (request == RelationGroup) + { + constexpr auto root_size = offsetof(EMU_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX64, Group); + constexpr auto required_size = root_size + sizeof(EMU_GROUP_RELATIONSHIP64); + + if (return_length) + { + return_length.write(required_size); + } + + if (system_information_length < required_size) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + + EMU_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX64 proc_info{}; + proc_info.Size = required_size; + proc_info.Relationship = RelationGroup; + + c.emu.write_memory(system_information, &proc_info, root_size); + + EMU_GROUP_RELATIONSHIP64 group{}; + group.ActiveGroupCount = 1; + group.MaximumGroupCount = 1; + + auto& group_info = group.GroupInfo[0]; + group_info.ActiveProcessorCount = static_cast(c.proc.kusd.get().ActiveProcessorCount); + group_info.ActiveProcessorMask = (1 << group_info.ActiveProcessorCount) - 1; + group_info.MaximumProcessorCount = group_info.ActiveProcessorCount; + + c.emu.write_memory(system_information + root_size, group); + return STATUS_SUCCESS; + } + + if (request == RelationNumaNode || request == RelationNumaNodeEx) + { + constexpr auto root_size = offsetof(EMU_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX64, NumaNode); + constexpr auto required_size = root_size + sizeof(EMU_NUMA_NODE_RELATIONSHIP64); + + if (return_length) + { + return_length.write(required_size); + } + + if (system_information_length < required_size) + { + return STATUS_INFO_LENGTH_MISMATCH; + } + + EMU_SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX64 proc_info{}; + proc_info.Size = required_size; + proc_info.Relationship = RelationNumaNode; + + c.emu.write_memory(system_information, &proc_info, root_size); + + EMU_NUMA_NODE_RELATIONSHIP64 numa_node{}; + memset(&numa_node, 0, sizeof(numa_node)); + + c.emu.write_memory(system_information + root_size, numa_node); + return STATUS_SUCCESS; + } + + printf("Unsupported processor relationship: %X\n", request); + c.emu.stop(); + return STATUS_NOT_SUPPORTED; } if (info_class != SystemBasicInformation && info_class != SystemEmulationBasicInformation) @@ -1114,9 +1158,9 @@ namespace return_length.write(sizeof(SYSTEM_BASIC_INFORMATION64)); } - if (system_information_length != sizeof(SYSTEM_BASIC_INFORMATION64)) + if (system_information_length < sizeof(SYSTEM_BASIC_INFORMATION64)) { - return STATUS_BUFFER_TOO_SMALL; + return STATUS_INFO_LENGTH_MISMATCH; } const emulator_object info{c.emu, system_information};