Starting physical memory allocation routines.

These currently don't do anything special w.r.t. memory addresses/etc,
but will in the future.
This commit is contained in:
Ben Vanik 2013-05-27 20:09:40 -07:00
parent f78e7945d4
commit 16baef3591
3 changed files with 156 additions and 2 deletions

View File

@ -183,6 +183,138 @@ SHIM_CALL NtFreeVirtualMemory_shim(
}
uint32_t xeMmAllocatePhysicalMemoryEx(
uint32_t type, uint32_t region_size, uint32_t protect_bits,
uint32_t min_addr_range, uint32_t max_addr_range, uint32_t alignment) {
KernelState* state = shared_kernel_state_;
XEASSERTNOTNULL(state);
// Type will usually be 0 (user request?), where 1 and 2 are sometimes made
// by D3D/etc.
// Check protection bits.
if (!(protect_bits & (X_PAGE_READONLY | X_PAGE_READWRITE))) {
XELOGE("MmAllocatePhysicalMemoryEx: bad protection bits");
return 0;
}
// Either may be OR'ed into protect_bits:
// X_PAGE_NOCACHE
// X_PAGE_WRITECOMBINE
// We could use this to detect what's likely GPU-synchronized memory
// and let the GPU know we're messing with it (or even allocate from
// the GPU). At least the D3D command buffer is X_PAGE_WRITECOMBINE.
// Calculate page size.
// Default = 4KB
// X_MEM_LARGE_PAGES = 64KB
// X_MEM_16MB_PAGES = 16MB
uint32_t page_size = 4 * 1024;
if (protect_bits & X_MEM_LARGE_PAGES) {
page_size = 64 * 1024;
} else if (protect_bits & X_MEM_16MB_PAGES) {
page_size = 16 * 1024 * 1024;
}
// Round up the region size to the next page.
uint32_t adjusted_size = XEROUNDUP(region_size, page_size);
// Callers can pick an address to allocate with min_addr_range/max_addr_range
// and the memory must be allocated there. I haven't seen a game do this,
// and instead they all do min=0 / max=-1 to indicate the system should pick.
// If we have to suport arbitrary placement things will get nasty.
XEASSERT(min_addr_range == 0);
XEASSERT(max_addr_range == 0xFFFFFFFF);
// Allocate.
uint32_t flags = 0;
uint32_t base_address = xe_memory_heap_alloc(
state->memory(), 0, adjusted_size, flags);
if (!base_address) {
// Failed - assume no memory available.
return 0;
}
return base_address;
}
SHIM_CALL MmAllocatePhysicalMemoryEx_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
uint32_t type = SHIM_GET_ARG_32(0);
uint32_t region_size = SHIM_GET_ARG_32(1);
uint32_t protect_bits = SHIM_GET_ARG_32(2);
uint32_t min_addr_range = SHIM_GET_ARG_32(3);
uint32_t max_addr_range = SHIM_GET_ARG_32(4);
uint32_t alignment = SHIM_GET_ARG_32(5);
XELOGD(
"MmAllocatePhysicalMemoryEx(%d, %.8X, %.8X, %.8X, %.8X, %.8X)",
type, region_size, protect_bits,
min_addr_range, max_addr_range, alignment);
uint32_t base_address = xeMmAllocatePhysicalMemoryEx(
type, region_size, protect_bits,
min_addr_range, max_addr_range, alignment);
SHIM_SET_RETURN(base_address);
}
void xeMmFreePhysicalMemory(uint32_t type, uint32_t base_address) {
KernelState* state = shared_kernel_state_;
XEASSERTNOTNULL(state);
// base_address = result of MmAllocatePhysicalMemory.
uint32_t flags = 0;
xe_memory_heap_free(
state->memory(), base_address, flags);
}
SHIM_CALL MmFreePhysicalMemory_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
uint32_t type = SHIM_GET_ARG_32(0);
uint32_t base_address = SHIM_GET_ARG_32(1);
XELOGD(
"MmFreePhysicalAddress(%d, %.8X)",
type, base_address);
xeMmFreePhysicalMemory(type, base_address);
}
// http://msdn.microsoft.com/en-us/library/windows/hardware/ff554547(v=vs.85).aspx
uint32_t xeMmGetPhysicalAddress(uint32_t base_address) {
// PHYSICAL_ADDRESS MmGetPhysicalAddress(
// _In_ PVOID BaseAddress
// );
// base_address = result of MmAllocatePhysicalMemory.
// We are always using virtual addresses, right now, since we don't need
// physical ones. We could munge up the address here to another mapped view
// of memory.
return base_address;
}
SHIM_CALL MmGetPhysicalAddress_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
uint32_t base_address = SHIM_GET_ARG_32(0);
XELOGD(
"MmGetPhysicalAddress(%.8X)",
base_address);
uint32_t result = xeMmGetPhysicalAddress(base_address);
SHIM_SET_RETURN(result);
}
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe
@ -192,4 +324,8 @@ void xe::kernel::xboxkrnl::RegisterMemoryExports(
ExportResolver* export_resolver, KernelState* state) {
SHIM_SET_MAPPING("xboxkrnl.exe", NtAllocateVirtualMemory, state);
SHIM_SET_MAPPING("xboxkrnl.exe", NtFreeVirtualMemory, state);
//SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemory, state);
SHIM_SET_MAPPING("xboxkrnl.exe", MmAllocatePhysicalMemoryEx, state);
SHIM_SET_MAPPING("xboxkrnl.exe", MmFreePhysicalMemory, state);
SHIM_SET_MAPPING("xboxkrnl.exe", MmGetPhysicalAddress, state);
}

View File

@ -25,11 +25,16 @@ X_STATUS xeNtAllocateVirtualMemory(
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
uint32_t allocation_type, uint32_t protect_bits,
uint32_t unknown);
X_STATUS xeNtFreeVirtualMemory(
uint32_t* base_addr_ptr, uint32_t* region_size_ptr,
uint32_t free_type, uint32_t unknown);
uint32_t xeMmAllocatePhysicalMemoryEx(
uint32_t type, uint32_t region_size, uint32_t protect_bits,
uint32_t min_addr_range, uint32_t max_addr_range, uint32_t alignment);
void xeMmFreePhysicalMemory(uint32_t type, uint32_t base_address);
uint32_t xeMmGetPhysicalAddress(uint32_t base_address);
} // namespace xboxkrnl
} // namespace kernel

View File

@ -49,13 +49,26 @@ VOID xeVdQueryVideoMode(X_VIDEO_MODE *video_mode, bool swap) {
}
}
SHIM_CALL VdQueryVideoMode_shim(
xe_ppc_state_t* ppc_state, KernelState* state) {
X_VIDEO_MODE *video_mode = (X_VIDEO_MODE*)SHIM_MEM_ADDR(SHIM_GET_ARG_32(0));
uint32_t video_mode_ptr = SHIM_GET_ARG_32(0);
X_VIDEO_MODE *video_mode = (X_VIDEO_MODE*)SHIM_MEM_ADDR(video_mode_ptr);
XELOGD(
"VdQueryVideoMode(%.8X)",
video_mode_ptr);
xeVdQueryVideoMode(video_mode, true);
}
// VdInitializeRingBuffer
// r3 = result of MmGetPhysicalAddress
// r4 = number of pages? page size?
// 0x8000 -> cntlzw=16 -> 0x1C - 16 = 12
} // namespace xboxkrnl
} // namespace kernel
} // namespace xe