From 8afdc71215e4e115cfd5bd1d4a4c5574eccbfc22 Mon Sep 17 00:00:00 2001 From: eladash Date: Thu, 21 Feb 2019 13:14:00 +0200 Subject: [PATCH] check address in sys_rsx_context_iomap * Fix 0 vm page flags to behave like 1m flags, follows c8a681e60 * check if address exists and valid for rsx io allcations (must be allocated on 1m pages) --- rpcs3/Emu/Cell/Modules/cellGcmSys.cpp | 35 ++++++++++++++++++--------- rpcs3/Emu/Cell/lv2/sys_mmapper.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_rsx.cpp | 12 ++++++++- rpcs3/Emu/Memory/vm.cpp | 18 +++++++------- 4 files changed, 44 insertions(+), 23 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp index 86b44cc20cf4..784f193af5fb 100644 --- a/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp +++ b/rpcs3/Emu/Cell/Modules/cellGcmSys.cpp @@ -1,4 +1,4 @@ -#include "stdafx.h" +#include "stdafx.h" #include "Emu/System.h" #include "Emu/IdManager.h" #include "Emu/Cell/PPUModule.h" @@ -6,6 +6,8 @@ #include "Emu/Memory/vm.h" #include "Emu/RSX/GSRender.h" #include "Emu/Cell/lv2/sys_ppu_thread.h" +#include "Emu/Cell/lv2/sys_rsx.h" + #include "cellGcmSys.h" #include "sysPrxForUser.h" @@ -951,21 +953,26 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr address) s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict) { - if (!size || (ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF) - || rsx::get_current_renderer()->main_mem_size < io + size) + if (!size || (ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF)) + { + return CELL_GCM_ERROR_FAILURE; + } + + // TODO: Pass correct flags and context + if (s32 error = sys_rsx_context_iomap(0, io, ea, size, 0)) { - return CELL_GCM_ERROR_FAILURE; + return error; } - ea >>=20, io >>= 20, size >>= 20; + ea >>= 20, io >>= 20, size >>= 20; IoMapTable[ea] = size; - // Fill the offset table and map memory + // Fill the offset table for (u32 i = 0; i < size; i++) { - RSXIOMem.io[ea + i] = offsetTable.ioAddress[ea + i] = io + i; - RSXIOMem.ea[io + i] = offsetTable.eaAddress[io + i] = ea + i; + offsetTable.ioAddress[ea + i] = io + i; + offsetTable.eaAddress[io + i] = ea + i; } return CELL_OK; @@ -1018,19 +1025,23 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr offset) { if (unmap_count >= (size >> 20)) { - *offset = io << 20; + if (s32 error = sys_rsx_context_iomap(0, io << 20, ea, size, 0)) + { + return error; + } ea >>= 20, size >>= 20; IoMapTable[ea] = size; - // Fill the offset table and map memory + // Fill the offset table for (u32 i = 0; i < size; i++) { - RSXIOMem.io[ea + i] = offsetTable.ioAddress[ea + i] = io + i; - RSXIOMem.ea[io + i] = offsetTable.eaAddress[io + i] = ea + i; + offsetTable.ioAddress[ea + i] = io + i; + offsetTable.eaAddress[io + i] = ea + i; } + *offset = io << 20; return CELL_OK; } } diff --git a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp index ba02cb2a2256..bcd65c8cd2a8 100644 --- a/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_mmapper.cpp @@ -283,7 +283,7 @@ error_code sys_mmapper_map_shared_memory(u32 addr, u32 mem_id, u64 flags) const auto mem = idm::get(mem_id, [&](lv2_memory& mem) -> CellError { - const u32 page_alignment = area->flags & SYS_MEMORY_PAGE_SIZE_1M ? 0x100000 : 0x10000; + const u32 page_alignment = area->flags & SYS_MEMORY_PAGE_SIZE_64K ? 0x10000 : 0x100000; if (mem.align < page_alignment) { diff --git a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp index c7b0248ebe43..b1e620d14ce2 100644 --- a/rpcs3/Emu/Cell/lv2/sys_rsx.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_rsx.cpp @@ -176,12 +176,22 @@ s32 sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 flags) { sys_rsx.warning("sys_rsx_context_iomap(context_id=0x%x, io=0x%x, ea=0x%x, size=0x%x, flags=0x%llx)", context_id, io, ea, size, flags); - if (!size || io & 0xFFFFF || ea & 0xFFFFF || size & 0xFFFFF || + if (!size || io & 0xFFFFF || ea >= 0xC0000000 || ea & 0xFFFFF || size & 0xFFFFF || rsx::get_current_renderer()->main_mem_size < io + size) { return CELL_EINVAL; } + vm::reader_lock rlock; + + for (u32 addr = ea, end = ea + size; addr < end; addr += 0x100000) + { + if (!vm::check_addr(addr, 1, vm::page_allocated | vm::page_1m_size)) + { + return CELL_EINVAL; + } + } + io >>= 20, ea >>= 20, size >>= 20; for (u32 i = 0; i < size; i++) diff --git a/rpcs3/Emu/Memory/vm.cpp b/rpcs3/Emu/Memory/vm.cpp index 8b2974915fb2..f5835b81c0d9 100644 --- a/rpcs3/Emu/Memory/vm.cpp +++ b/rpcs3/Emu/Memory/vm.cpp @@ -689,13 +689,13 @@ namespace vm u8 pflags = page_readable | page_writable; - if (align >= 0x100000) + if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K) { - pflags |= page_1m_size; + pflags |= page_64k_size; } - else if (align >= 0x10000) + else if (!(flags & (SYS_MEMORY_PAGE_SIZE_MASK & ~SYS_MEMORY_PAGE_SIZE_1M))) { - pflags |= page_64k_size; + pflags |= page_1m_size; } // Create or import shared memory object @@ -738,13 +738,13 @@ namespace vm u8 pflags = page_readable | page_writable; - if ((flags & SYS_MEMORY_PAGE_SIZE_1M) == SYS_MEMORY_PAGE_SIZE_1M) + if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K) { - pflags |= page_1m_size; + pflags |= page_64k_size; } - else if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K) + else if (!(flags & (SYS_MEMORY_PAGE_SIZE_MASK & ~SYS_MEMORY_PAGE_SIZE_1M))) { - pflags |= page_64k_size; + pflags |= page_1m_size; } // Create or import shared memory object @@ -1027,7 +1027,7 @@ namespace vm { g_locations = { - std::make_shared(0x00010000, 0x1FFF0000), // main + std::make_shared(0x00010000, 0x1FFF0000, 0x200), // main std::make_shared(0x20000000, 0x10000000, 0x201), // user 64k pages nullptr, // user 1m pages std::make_shared(0xC0000000, 0x10000000), // video