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)
This commit is contained in:
eladash 2019-02-21 13:14:00 +02:00 committed by Ivan
parent d82362fa1d
commit e38b7aee5a
4 changed files with 46 additions and 25 deletions

View file

@ -1,4 +1,4 @@
#include "stdafx.h" #include "stdafx.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/IdManager.h" #include "Emu/IdManager.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
@ -6,6 +6,8 @@
#include "Emu/Memory/vm.h" #include "Emu/Memory/vm.h"
#include "Emu/RSX/GSRender.h" #include "Emu/RSX/GSRender.h"
#include "Emu/Cell/lv2/sys_ppu_thread.h" #include "Emu/Cell/lv2/sys_ppu_thread.h"
#include "Emu/Cell/lv2/sys_rsx.h"
#include "cellGcmSys.h" #include "cellGcmSys.h"
#include "sysPrxForUser.h" #include "sysPrxForUser.h"
@ -951,21 +953,26 @@ s32 cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict) s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
{ {
if (!size || (ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF) if (!size || (ea & 0xFFFFF) || (io & 0xFFFFF) || (size & 0xFFFFF))
|| rsx::get_current_renderer()->main_mem_size < io + size)
{ {
return CELL_GCM_ERROR_FAILURE; return CELL_GCM_ERROR_FAILURE;
} }
// TODO: Pass correct flags and context
if (s32 error = sys_rsx_context_iomap(0, io, ea, size, 0))
{
return error;
}
ea >>= 20, io >>= 20, size >>= 20; ea >>= 20, io >>= 20, size >>= 20;
IoMapTable[ea] = size; IoMapTable[ea] = size;
// Fill the offset table and map memory // Fill the offset table
for (u32 i = 0; i < size; i++) for (u32 i = 0; i < size; i++)
{ {
RSXIOMem.io[ea + i] = offsetTable.ioAddress[ea + i] = io + i; offsetTable.ioAddress[ea + i] = io + i;
RSXIOMem.ea[io + i] = offsetTable.eaAddress[io + i] = ea + i; offsetTable.eaAddress[io + i] = ea + i;
} }
return CELL_OK; return CELL_OK;
@ -1018,19 +1025,23 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
{ {
if (unmap_count >= (size >> 20)) 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; ea >>= 20, size >>= 20;
IoMapTable[ea] = size; IoMapTable[ea] = size;
// Fill the offset table and map memory // Fill the offset table
for (u32 i = 0; i < size; i++) for (u32 i = 0; i < size; i++)
{ {
RSXIOMem.io[ea + i] = offsetTable.ioAddress[ea + i] = io + i; offsetTable.ioAddress[ea + i] = io + i;
RSXIOMem.ea[io + i] = offsetTable.eaAddress[io + i] = ea + i; offsetTable.eaAddress[io + i] = ea + i;
} }
*offset = io << 20;
return CELL_OK; return CELL_OK;
} }
} }

View file

@ -283,7 +283,7 @@ error_code sys_mmapper_map_shared_memory(u32 addr, u32 mem_id, u64 flags)
const auto mem = idm::get<lv2_obj, lv2_memory>(mem_id, [&](lv2_memory& mem) -> CellError const auto mem = idm::get<lv2_obj, lv2_memory>(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) if (mem.align < page_alignment)
{ {

View file

@ -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); 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) rsx::get_current_renderer()->main_mem_size < io + size)
{ {
return CELL_EINVAL; 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; io >>= 20, ea >>= 20, size >>= 20;
for (u32 i = 0; i < size; i++) for (u32 i = 0; i < size; i++)

View file

@ -689,14 +689,14 @@ namespace vm
u8 pflags = page_readable | page_writable; 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;
}
else if (align >= 0x10000)
{ {
pflags |= page_64k_size; pflags |= page_64k_size;
} }
else if (!(flags & (SYS_MEMORY_PAGE_SIZE_MASK & ~SYS_MEMORY_PAGE_SIZE_1M)))
{
pflags |= page_1m_size;
}
// Create or import shared memory object // Create or import shared memory object
std::shared_ptr<utils::shm> shm; std::shared_ptr<utils::shm> shm;
@ -738,14 +738,14 @@ namespace vm
u8 pflags = page_readable | page_writable; 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;
}
else if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K)
{ {
pflags |= page_64k_size; pflags |= page_64k_size;
} }
else if (!(flags & (SYS_MEMORY_PAGE_SIZE_MASK & ~SYS_MEMORY_PAGE_SIZE_1M)))
{
pflags |= page_1m_size;
}
// Create or import shared memory object // Create or import shared memory object
std::shared_ptr<utils::shm> shm; std::shared_ptr<utils::shm> shm;
@ -1027,7 +1027,7 @@ namespace vm
{ {
g_locations = g_locations =
{ {
std::make_shared<block_t>(0x00010000, 0x1FFF0000), // main std::make_shared<block_t>(0x00010000, 0x1FFF0000, 0x200), // main
std::make_shared<block_t>(0x20000000, 0x10000000, 0x201), // user 64k pages std::make_shared<block_t>(0x20000000, 0x10000000, 0x201), // user 64k pages
nullptr, // user 1m pages nullptr, // user 1m pages
std::make_shared<block_t>(0xC0000000, 0x10000000), // video std::make_shared<block_t>(0xC0000000, 0x10000000), // video