From e588a772d4d36b7c3f6828689d7769ef03e05601 Mon Sep 17 00:00:00 2001 From: Anton Dorozhkin Date: Sat, 29 Nov 2025 18:01:29 +0700 Subject: [PATCH] [XBDM] Implement DmQueryTitleMemoryStatistics --- src/xenia/kernel/xbdm/xbdm_misc.cc | 50 ++++++++++++++++++++ src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc | 32 +++---------- src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h | 27 +++++++++++ src/xenia/xbox.h | 2 + 4 files changed, 85 insertions(+), 26 deletions(-) diff --git a/src/xenia/kernel/xbdm/xbdm_misc.cc b/src/xenia/kernel/xbdm/xbdm_misc.cc index 58c837896..264b3d50c 100644 --- a/src/xenia/kernel/xbdm/xbdm_misc.cc +++ b/src/xenia/kernel/xbdm/xbdm_misc.cc @@ -13,6 +13,7 @@ #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/util/shim_utils.h" #include "xenia/kernel/xbdm/xbdm_private.h" +#include "xenia/kernel/xboxkrnl/xboxkrnl_memory.h" #include "xenia/kernel/xthread.h" #include "xenia/vfs/devices/host_path_device.h" #include "xenia/xbox.h" @@ -465,6 +466,55 @@ dword_result_t DmSetDumpMode_entry(dword_t dump_mode) { } DECLARE_XBDM_EXPORT1(DmSetDumpMode, kDebug, kStub); +struct X_DM_QUERY_MEMORY_STATISTICS_RESULT { + xe::be size; + xe::be total_pages; + xe::be available_pages; + xe::be stack_pages; + xe::be virtual_page_table_pages; + xe::be system_page_table_pages; + xe::be pool_pages; + xe::be virtual_mapped_pages; + xe::be image_pages; + xe::be file_cache_pages; + xe::be contiguous_pages; + xe::be debugger_pages; +}; +static_assert_size(X_DM_QUERY_MEMORY_STATISTICS_RESULT, 48); + +dword_result_t DmQueryTitleMemoryStatistics_entry( + pointer_t stats_ptr) { + if (stats_ptr->size != sizeof(X_DM_QUERY_MEMORY_STATISTICS_RESULT)) { + return X_E_INVALIDARG; + } + + xe::kernel::xboxkrnl::X_MM_QUERY_STATISTICS_RESULT stats; + stats.size = sizeof(xe::kernel::xboxkrnl::X_MM_QUERY_STATISTICS_RESULT); + dword_result_t result = xe::kernel::xboxkrnl::xeMmQueryStatistics(&stats); + if (result < 0) { + return X_HRESULT_FROM_NT(result); + } + + stats_ptr->available_pages = stats.title.available_pages; + stats_ptr->stack_pages = stats.title.stack_pages; + stats_ptr->virtual_page_table_pages = stats.title.page_table_pages; + stats_ptr->system_page_table_pages = 0; + stats_ptr->pool_pages = stats.title.pool_pages; + stats_ptr->virtual_mapped_pages = + stats.title.heap_pages + stats.title.virtual_pages; + stats_ptr->image_pages = stats.title.image_pages; + stats_ptr->file_cache_pages = stats.title.cache_pages; + stats_ptr->contiguous_pages = stats.title.physical_pages; + stats_ptr->debugger_pages = 0; + stats_ptr->total_pages = + stats_ptr->available_pages + stats_ptr->stack_pages + + stats_ptr->virtual_page_table_pages + stats_ptr->pool_pages + + stats_ptr->virtual_mapped_pages + stats_ptr->image_pages + + stats_ptr->file_cache_pages + stats_ptr->contiguous_pages; + return XBDM_SUCCESSFUL; +} +DECLARE_XBDM_EXPORT1(DmQueryTitleMemoryStatistics, kDebug, kStub); + dword_result_t DmIsFastCAPEnabled_entry() { return XBDM_UNSUCCESSFUL; } DECLARE_XBDM_EXPORT1(DmIsFastCAPEnabled, kDebug, kStub); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc index 7aa93d686..9ac3aea94 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc @@ -557,32 +557,7 @@ dword_result_t MmQueryAllocationSize_entry(lpvoid_t base_address) { } DECLARE_XBOXKRNL_EXPORT1(MmQueryAllocationSize, kMemory, kImplemented); -// https://code.google.com/p/vdash/source/browse/trunk/vdash/include/kernel.h -struct X_MM_QUERY_STATISTICS_SECTION { - xe::be available_pages; - xe::be total_virtual_memory_bytes; - xe::be reserved_virtual_memory_bytes; - xe::be physical_pages; - xe::be pool_pages; - xe::be stack_pages; - xe::be image_pages; - xe::be heap_pages; - xe::be virtual_pages; - xe::be page_table_pages; - xe::be cache_pages; -}; - -struct X_MM_QUERY_STATISTICS_RESULT { - xe::be size; - xe::be total_physical_pages; - xe::be kernel_pages; - X_MM_QUERY_STATISTICS_SECTION title; - X_MM_QUERY_STATISTICS_SECTION system; - xe::be highest_physical_page; -}; -static_assert_size(X_MM_QUERY_STATISTICS_RESULT, 104); - -dword_result_t MmQueryStatistics_entry( +dword_result_t xeMmQueryStatistics( pointer_t stats_ptr) { if (!stats_ptr) { return X_STATUS_INVALID_PARAMETER; @@ -649,6 +624,11 @@ dword_result_t MmQueryStatistics_entry( return X_STATUS_SUCCESS; } + +dword_result_t MmQueryStatistics_entry( + pointer_t stats_ptr) { + return xeMmQueryStatistics(stats_ptr); +} DECLARE_XBOXKRNL_EXPORT2(MmQueryStatistics, kMemory, kImplemented, kHighFrequency); diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h index 545d9a355..b25795f73 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.h @@ -17,11 +17,38 @@ namespace xe { namespace kernel { namespace xboxkrnl { +// https://code.google.com/p/vdash/source/browse/trunk/vdash/include/kernel.h +struct X_MM_QUERY_STATISTICS_SECTION { + xe::be available_pages; + xe::be total_virtual_memory_bytes; + xe::be reserved_virtual_memory_bytes; + xe::be physical_pages; + xe::be pool_pages; + xe::be stack_pages; + xe::be image_pages; + xe::be heap_pages; + xe::be virtual_pages; + xe::be page_table_pages; + xe::be cache_pages; +}; + +struct X_MM_QUERY_STATISTICS_RESULT { + xe::be size; + xe::be total_physical_pages; + xe::be kernel_pages; + X_MM_QUERY_STATISTICS_SECTION title; + X_MM_QUERY_STATISTICS_SECTION system; + xe::be highest_physical_page; +}; +static_assert_size(X_MM_QUERY_STATISTICS_RESULT, 104); + uint32_t xeMmAllocatePhysicalMemoryEx(uint32_t flags, uint32_t region_size, uint32_t protect_bits, uint32_t min_addr_range, uint32_t max_addr_range, uint32_t alignment); +dword_result_t xeMmQueryStatistics( + pointer_t stats_ptr); uint32_t xeAllocatePoolTypeWithTag(PPCContext* context, uint32_t size, uint32_t tag, uint32_t zero); diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 3831d5816..876dc9ff4 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -26,6 +26,7 @@ typedef uint32_t X_HANDLE; // https://msdn.microsoft.com/en-us/library/cc704588.aspx // Adding as needed. typedef uint32_t X_STATUS; +#define X_FACILITY_NT_BIT 0x10000000 #define XSUCCEEDED(s) ((s & 0xC0000000) == 0) #define XFAILED(s) (!XSUCCEEDED(s)) #define X_STATUS_SUCCESS ((X_STATUS)0x00000000L) @@ -111,6 +112,7 @@ typedef uint32_t X_RESULT; // HRESULT codes typedef uint32_t X_HRESULT; +#define X_HRESULT_FROM_NT(x) (static_cast((x) | X_FACILITY_NT_BIT)) #define X_HRESULT_FROM_WIN32(x) ((int32_t)(x) <= 0 \ ? (static_cast(x)) \ : (static_cast(((x) & 0xFFFF) | (X_FACILITY_WIN32 << 16) | \