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; if (!size || (ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
u32 io = RSXIOMem.Map(ea, size); // 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++)
const auto render = rsx::get_current_renderer();
//check if the mapping was successfull
if (RSXIOMem.RealAddr(io) == ea)
{ {
//fill the offset table if (static_cast<s16>(offsetTable.eaAddress[io]) < 0)
for (u32 i = 0; i<(size >> 20); i++)
{ {
offsetTable.ioAddress[(ea >> 20) + i] = (u16)((io >> 20) + i); if (unmap_count >= (size >> 20))
offsetTable.eaAddress[(io >> 20) + i] = (u16)((ea >> 20) + i); {
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; cellGcmSys.error("cellGcmMapMainMemory: CELL_GCM_ERROR_NO_IO_PAGE_TABLE");
return CELL_GCM_ERROR_NO_IO_PAGE_TABLE;
return CELL_OK;
} }
s32 cellGcmReserveIoMapSize(u32 size) s32 cellGcmReserveIoMapSize(u32 size)

View file

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

View file

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

View file

@ -99,6 +99,12 @@ struct RsxDisplayInfo
be_t<u32> height; be_t<u32> height;
}; };
struct SysRsxConfig
{
be_t<u32> rsx_event_port{ 0 };
u32 driverInfo{ 0 };
};
// SysCalls // SysCalls
s32 sys_rsx_device_open(); s32 sys_rsx_device_open();
s32 sys_rsx_device_close(); 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) 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(); return addr >= m_range_start && addr + size <= m_range_start + m_range_size - 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;
} }
bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr) bool VirtualMemoryBlock::Map(u32 realaddr, u32 size, u32 addr)
@ -117,7 +89,7 @@ bool VirtualMemoryBlock::getRealAddr(u32 addr, u32& result)
return false; return false;
} }
u32 VirtualMemoryBlock::getMappedAddress(u32 realAddress) s32 VirtualMemoryBlock::getMappedAddress(u32 realAddress)
{ {
for (u32 i = 0; i<m_mapped_memory.size(); ++i) 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) bool VirtualMemoryBlock::Reserve(u32 size)
@ -152,3 +124,13 @@ u32 VirtualMemoryBlock::GetReservedAmount()
{ {
return m_reserve_size; 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; } u32 GetSize() const { return m_range_size; }
bool IsInMyRange(const u32 addr, const u32 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 // maps real address to virtual address space
// first mappable space is used)
bool Map(u32 realaddr, u32 size, u32 addr); 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 // 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); bool UnmapRealAddress(u32 realaddr, u32& size);
@ -71,6 +69,12 @@ public:
// Return the total amount of reserved memory // Return the total amount of reserved memory
u32 GetReservedAmount(); 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 Read32(const u32 addr, u32* value);
bool Write32(const u32 addr, const u32 value); bool Write32(const u32 addr, const u32 value);
@ -92,6 +96,6 @@ public:
return realAddr; return realAddr;
} }
// return the mapped address given a real address, if not mapped return 0 // return the mapped address given a real address, if not mapped return minus one
u32 getMappedAddress(u32 realAddress); s32 getMappedAddress(u32 realAddress);
}; };

View file

@ -11,6 +11,8 @@
#include "Capture/rsx_capture.h" #include "Capture/rsx_capture.h"
#include "rsx_methods.h" #include "rsx_methods.h"
#include "rsx_utils.h" #include "rsx_utils.h"
#include "Emu/Cell/lv2/sys_event.h"
#include "Emu/Cell/Modules/cellGcmSys.h"
#include "Utilities/GSL.h" #include "Utilities/GSL.h"
#include "Utilities/StrUtil.h" #include "Utilities/StrUtil.h"
@ -27,6 +29,8 @@ bool user_asked_for_frame_capture = false;
rsx::frame_trace_data frame_debug; rsx::frame_trace_data frame_debug;
rsx::frame_capture_data frame_capture; rsx::frame_capture_data frame_capture;
extern CellGcmOffsetTable offsetTable;
namespace rsx namespace rsx
{ {
std::function<bool(u32 addr, bool is_writing)> g_access_violation_handler; 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) 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); writer_lock lock(m_mtx_task);
m_invalidated_memory_ranges.push_back({ base_address, size }); m_invalidated_memory_ranges.push_back({ base_address, size });
} }