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/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<u32> 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;
return CELL_GCM_ERROR_FAILURE;
}
ea >>=20, io >>= 20, size >>= 20;
// 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;
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<u32> 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;
}
}

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 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)
{

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);
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++)

View File

@ -689,14 +689,14 @@ namespace vm
u8 pflags = page_readable | page_writable;
if (align >= 0x100000)
{
pflags |= page_1m_size;
}
else if (align >= 0x10000)
if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K)
{
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
std::shared_ptr<utils::shm> shm;
@ -738,14 +738,14 @@ namespace vm
u8 pflags = page_readable | page_writable;
if ((flags & SYS_MEMORY_PAGE_SIZE_1M) == SYS_MEMORY_PAGE_SIZE_1M)
{
pflags |= page_1m_size;
}
else if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K)
if ((flags & SYS_MEMORY_PAGE_SIZE_64K) == SYS_MEMORY_PAGE_SIZE_64K)
{
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
std::shared_ptr<utils::shm> shm;
@ -1027,7 +1027,7 @@ namespace vm
{
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
nullptr, // user 1m pages
std::make_shared<block_t>(0xC0000000, 0x10000000), // video