allow deallocations to unmap rsx mapped memory

This commit is contained in:
eladash 2018-05-27 13:48:21 +03:00 committed by kd-11
parent ce98c962f8
commit 23b380eb41
7 changed files with 84 additions and 64 deletions

View file

@ -997,31 +997,39 @@ s32 cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
if (!size || (ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
u32 io = RSXIOMem.Map(ea, size);
const auto render = rsx::get_current_renderer();
//check if the mapping was successfull
if (RSXIOMem.RealAddr(io) == ea)
// Use the offset table to find the next free io address
for (u32 io = RSXIOMem.GetRangeStart() >> 20, end = RSXIOMem.GetRangeEnd() >> 20, unmap_count = 1; io < end; unmap_count++)
{
//fill the offset table
for (u32 i = 0; i<(size >> 20); i++)
if (static_cast<s16>(offsetTable.eaAddress[io]) < 0)
{
offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i);
offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i);
if (unmap_count >= (size >> 20))
{
io <<= 20;
RSXIOMem.Map(ea, size, io);
*offset = io;
io >>= 20, ea >>= 20;
//fill the offset table
for (u32 i = 0; i<(size >> 20); ++i)
{
offsetTable.ioAddress[ea + i] = io + i;
offsetTable.eaAddress[io + i] = ea + i;
}
return CELL_OK;
}
}
else
{
io += unmap_count;
unmap_count = 0;
}
*offset = io;
}
else
{
cellGcmSys.error("cellGcmMapMainMemory: CELL_GCM_ERROR_NO_IO_PAGE_TABLE");
return CELL_GCM_ERROR_NO_IO_PAGE_TABLE;
}
render->main_mem_addr = render->ioAddress;
return CELL_OK;
cellGcmSys.error("cellGcmMapMainMemory: CELL_GCM_ERROR_NO_IO_PAGE_TABLE");
return CELL_GCM_ERROR_NO_IO_PAGE_TABLE;
}
s32 cellGcmReserveIoMapSize(u32 size)

View file

@ -1,7 +1,5 @@
#pragma once
#include "Emu/RSX/GCM.h"
enum
@ -20,5 +18,7 @@ struct CellGcmOffsetTable
vm::bptr<u16> eaAddress;
};
void InitOffsetTable();
// Auxiliary functions
s32 gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict);

View file

@ -9,16 +9,10 @@
#include "sys_event.h"
logs::channel sys_rsx("sys_rsx");
extern u64 get_timebased_time();
struct SysRsxConfig {
be_t<u32> rsx_event_port{ 0 };
u32 driverInfo{ 0 };
};
u64 rsxTimeStamp() {
return get_timebased_time();
}

View file

@ -99,6 +99,12 @@ struct RsxDisplayInfo
be_t<u32> height;
};
struct SysRsxConfig
{
be_t<u32> rsx_event_port{ 0 };
u32 driverInfo{ 0 };
};
// SysCalls
s32 sys_rsx_device_open();
s32 sys_rsx_device_close();

View file

@ -13,35 +13,7 @@ VirtualMemoryBlock* VirtualMemoryBlock::SetRange(const u32 start, const u32 size
bool VirtualMemoryBlock::IsInMyRange(const u32 addr, const u32 size)
{
return addr >= m_range_start && addr + size - 1 <= m_range_start + m_range_size - 1 - GetReservedAmount();
}
u32 VirtualMemoryBlock::Map(u32 realaddr, u32 size)
{
for (u32 addr = m_range_start; addr <= m_range_start + m_range_size - 1 - GetReservedAmount() - size;)
{
bool is_good_addr = true;
// check if address is already mapped
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
if ((addr >= m_mapped_memory[i].addr && addr < m_mapped_memory[i].addr + m_mapped_memory[i].size) ||
(m_mapped_memory[i].addr >= addr && m_mapped_memory[i].addr < addr + size))
{
is_good_addr = false;
addr = m_mapped_memory[i].addr + m_mapped_memory[i].size;
break;
}
}
if (!is_good_addr) continue;
m_mapped_memory.emplace_back(addr, realaddr, size);
return addr;
}
return 0;
return addr >= m_range_start && addr + size <= m_range_start + m_range_size - GetReservedAmount();
}
bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr)
@ -117,7 +89,7 @@ bool VirtualMemoryBlock::getRealAddr(u32 addr, u32& result)
return false;
}
u32 VirtualMemoryBlock::getMappedAddress(u32 realAddress)
s32 VirtualMemoryBlock::getMappedAddress(u32 realAddress)
{
for (u32 i = 0; i<m_mapped_memory.size(); ++i)
{
@ -127,7 +99,7 @@ u32 VirtualMemoryBlock::getMappedAddress(u32 realAddress)
}
}
return 0;
return -1;
}
bool VirtualMemoryBlock::Reserve(u32 size)
@ -152,3 +124,13 @@ u32 VirtualMemoryBlock::GetReservedAmount()
{
return m_reserve_size;
}
u32 VirtualMemoryBlock::GetRangeStart()
{
return m_range_start;
}
u32 VirtualMemoryBlock::GetRangeEnd()
{
return m_range_start + m_range_size - GetReservedAmount();
}

View file

@ -51,10 +51,8 @@ public:
u32 GetSize() const { return m_range_size; }
bool IsInMyRange(const u32 addr, const u32 size);
// maps real address to virtual address space, returns the mapped address or 0 on failure (if no address is specified the
// first mappable space is used)
// maps real address to virtual address space
bool Map(u32 realaddr, u32 size, u32 addr);
u32 Map(u32 realaddr, u32 size);
// Unmap real address (please specify only starting point, no midway memory will be unmapped), returns the size of the unmapped area
bool UnmapRealAddress(u32 realaddr, u32& size);
@ -71,6 +69,12 @@ public:
// Return the total amount of reserved memory
u32 GetReservedAmount();
// Return the start of the mapped space
u32 GetRangeStart();
// Return the end of the mapped space
u32 GetRangeEnd();
bool Read32(const u32 addr, u32* value);
bool Write32(const u32 addr, const u32 value);
@ -92,6 +96,6 @@ public:
return realAddr;
}
// return the mapped address given a real address, if not mapped return 0
u32 getMappedAddress(u32 realAddress);
// return the mapped address given a real address, if not mapped return minus one
s32 getMappedAddress(u32 realAddress);
};

View file

@ -11,6 +11,8 @@
#include "Capture/rsx_capture.h"
#include "rsx_methods.h"
#include "rsx_utils.h"
#include "Emu/Cell/lv2/sys_event.h"
#include "Emu/Cell/Modules/cellGcmSys.h"
#include "Utilities/GSL.h"
#include "Utilities/StrUtil.h"
@ -27,6 +29,8 @@ bool user_asked_for_frame_capture = false;
rsx::frame_trace_data frame_debug;
rsx::frame_capture_data frame_capture;
extern CellGcmOffsetTable offsetTable;
namespace rsx
{
std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler;
@ -2332,6 +2336,28 @@ namespace rsx
void thread::on_notify_memory_unmapped(u32 base_address, u32 size)
{
{
s32 io_addr = RSXIOMem.getMappedAddress(base_address);
if (io_addr >= 0)
{
if (!isHLE)
{
const u64 unmap_key = u64((1ull << (size >> 20)) - 1) << ((io_addr >> 20) & 0x3f);
const u64 gcm_flag = 0x100000000ull << (io_addr >> 26);
sys_event_port_send(fxm::get<SysRsxConfig>()->rsx_event_port, 0, gcm_flag, unmap_key);
}
else
{
const u32 end = (base_address + size) >> 20;
for (base_address >>= 20, io_addr >>= 20; base_address < end;)
{
offsetTable.ioAddress[base_address++] = 0xFFFF;
offsetTable.eaAddress[io_addr++] = 0xFFFF;
}
}
}
}
writer_lock lock(m_mtx_task);
m_invalidated_memory_ranges.push_back({ base_address, size });
}