rsx: rewrite io mappings

Along with some with fixes to cellGcmSys HLE.
This commit is contained in:
Eladash 2020-01-16 22:40:47 +02:00 committed by Ani
parent f47333997f
commit bdab26ec09
9 changed files with 233 additions and 186 deletions

View file

@ -49,23 +49,6 @@ const u32 tiled_pitches[] = {
0x00010000
};
struct gcm_config
{
u32 zculls_addr;
vm::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null;
u32 tiles_addr;
u32 ctxt_addr;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
};
u64 system_mode = 0;
u32 local_size = 0;
u32 local_addr = 0;
atomic_t<u32> reserved_size = 0;
// Auxiliary functions
/*
@ -93,22 +76,31 @@ u32 gcmGetLocalMemorySize(u32 sdk_version)
return 0x0E000000; // 224MB
}
CellGcmOffsetTable offsetTable;
atomic_t<u16> IoMapTable[0xC00]{};
error_code gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict);
u32 gcmIoOffsetToAddress(u32 ioOffset)
{
const u32 upper12Bits = g_fxo->get<gcm_config>()->offsetTable.eaAddress[ioOffset >> 20];
if (static_cast<s16>(upper12Bits) < 0)
{
return 0;
}
return (upper12Bits << 20) | (ioOffset & 0xFFFFF);
}
void InitOffsetTable()
{
offsetTable.ioAddress.set(vm::alloc(3072 * sizeof(u16), vm::main));
offsetTable.eaAddress.set(vm::alloc(512 * sizeof(u16), vm::main));
const auto cfg = g_fxo->get<gcm_config>();
memset(offsetTable.ioAddress.get_ptr(), 0xFF, 3072 * sizeof(u16));
memset(offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16));
memset(IoMapTable, 0, 3072 * sizeof(u16));
cfg->offsetTable.ioAddress.set(vm::alloc(3072 * sizeof(u16), vm::main));
cfg->offsetTable.eaAddress.set(vm::alloc(512 * sizeof(u16), vm::main));
memset(&RSXIOMem, 0xFF, sizeof(RSXIOMem));
reserved_size = 0;
std::memset(cfg->offsetTable.ioAddress.get_ptr(), 0xFF, 3072 * sizeof(u16));
std::memset(cfg->offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16));
cfg->reserved_size = 0;
}
//----------------------------------------------------------------------------
@ -132,7 +124,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong main index (%d)", index);
}
return vm::ptr<CellGcmReportData>::make(RSXIOMem.RealAddr(0x0e000000 + index * 0x10));
return vm::cast(gcmIoOffsetToAddress(0x0e000000 + index * 0x10));
}
// Anything else is Local
@ -142,7 +134,7 @@ vm::ptr<CellGcmReportData> cellGcmGetReportDataAddressLocation(u32 index, u32 lo
cellGcmSys.error("cellGcmGetReportDataAddressLocation: Wrong local index (%d)", index);
}
return vm::ptr<CellGcmReportData>::make(g_fxo->get<gcm_config>()->gcm_info.label_addr + ::offset32(&RsxReports::report) + index * 0x10);
return vm::cast(g_fxo->get<gcm_config>()->gcm_info.label_addr + ::offset32(&RsxReports::report) + index * 0x10);
}
u64 cellGcmGetTimeStamp(u32 index)
@ -168,7 +160,7 @@ u32 cellGcmGetNotifyDataAddress(u32 index)
cellGcmSys.warning("cellGcmGetNotifyDataAddress(index=%d)", index);
// If entry not in use, return NULL
u16 entry = offsetTable.eaAddress[241];
u16 entry = g_fxo->get<gcm_config>()->offsetTable.eaAddress[241];
if (entry == 0xFFFF) {
return 0;
}
@ -225,24 +217,8 @@ u64 cellGcmGetTimeStampLocation(u32 index, u32 location)
{
cellGcmSys.warning("cellGcmGetTimeStampLocation(index=%d, location=%d)", index, location);
if (location == CELL_GCM_LOCATION_LOCAL) {
if (index >= 2048) {
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong local index (%d)", index);
return 0;
}
return vm::read64(g_fxo->get<gcm_config>()->gcm_info.label_addr + ::offset32(&RsxReports::report) + index * 0x10);
}
if (location == CELL_GCM_LOCATION_MAIN) {
if (index >= 1024 * 1024) {
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong main index (%d)", index);
return 0;
}
return vm::read64(RSXIOMem.RealAddr(index * 0x10));
}
cellGcmSys.error("cellGcmGetTimeStampLocation: Wrong location (%d)", location);
return 0;
// NOTE: No error checkings
return cellGcmGetReportDataAddressLocation(index, location)->timer;
}
//----------------------------------------------------------------------------
@ -365,25 +341,26 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
cellGcmSys.warning("_cellGcmInitBody(context=**0x%x, cmdSize=0x%x, ioSize=0x%x, ioAddress=0x%x)", context, cmdSize, ioSize, ioAddress);
const auto gcm_cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(gcm_cfg->gcmio_mutex);
gcm_cfg->current_config.ioAddress = 0;
gcm_cfg->current_config.localAddress = 0;
local_size = 0;
local_addr = 0;
gcm_cfg->local_size = 0;
gcm_cfg->local_addr = 0;
if (!local_size && !local_addr)
//if (!gcm_cfg->local_size && !gcm_cfg->local_addr)
{
local_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize
local_addr = rsx::constants::local_mem_base;
vm::falloc(local_addr, local_size, vm::video);
gcm_cfg->local_size = 0xf900000; // TODO: Get sdk_version in _cellGcmFunc15 and pass it to gcmGetLocalMemorySize
gcm_cfg->local_addr = rsx::constants::local_mem_base;
vm::falloc(gcm_cfg->local_addr, gcm_cfg->local_size, vm::video);
}
cellGcmSys.warning("*** local memory(addr=0x%x, size=0x%x)", local_addr, local_size);
cellGcmSys.warning("*** local memory(addr=0x%x, size=0x%x)", gcm_cfg->local_addr, gcm_cfg->local_size);
InitOffsetTable();
const auto render = rsx::get_current_renderer();
if (system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
if (gcm_cfg->system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB)
{
cellGcmSys.warning("cellGcmInit(): 512MB io address space used");
render->main_mem_size = 0x20000000;
@ -401,8 +378,8 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
gcm_cfg->current_config.ioSize = ioSize;
gcm_cfg->current_config.ioAddress = ioAddress;
gcm_cfg->current_config.localSize = local_size;
gcm_cfg->current_config.localAddress = local_addr;
gcm_cfg->current_config.localSize = gcm_cfg->local_size;
gcm_cfg->current_config.localAddress = gcm_cfg->local_addr;
gcm_cfg->current_config.memoryFrequency = 650000000;
gcm_cfg->current_config.coreFrequency = 500000000;
@ -446,7 +423,7 @@ error_code _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> contex
render->isHLE = true;
render->label_addr = gcm_cfg->gcm_info.label_addr;
render->device_addr = gcm_cfg->gcm_info.context_addr;
render->local_mem_size = local_size;
render->local_mem_size = gcm_cfg->local_size;
render->init(gcm_cfg->gcm_info.control_addr - 0x40);
return CELL_OK;
@ -855,7 +832,7 @@ error_code cellGcmInitSystemMode(u64 mode)
{
cellGcmSys.trace("cellGcmInitSystemMode(mode=0x%x)", mode);
system_mode = mode;
g_fxo->get<gcm_config>()->system_mode = mode;
return CELL_OK;
}
@ -930,7 +907,7 @@ error_code cellGcmAddressToOffset(u32 address, vm::ptr<u32> offset)
// Address in main memory else check
else
{
const u32 upper12Bits = offsetTable.ioAddress[address >> 20];
const u32 upper12Bits = g_fxo->get<gcm_config>()->offsetTable.ioAddress[address >> 20];
// If the address is mapped in IO
if (upper12Bits != 0xFFFF)
@ -951,29 +928,31 @@ u32 cellGcmGetMaxIoMapSize()
{
cellGcmSys.trace("cellGcmGetMaxIoMapSize()");
return rsx::get_current_renderer()->main_mem_size - reserved_size;
return rsx::get_current_renderer()->main_mem_size - g_fxo->get<gcm_config>()->reserved_size;
}
void cellGcmGetOffsetTable(vm::ptr<CellGcmOffsetTable> table)
{
cellGcmSys.trace("cellGcmGetOffsetTable(table=*0x%x)", table);
table->ioAddress = offsetTable.ioAddress;
table->eaAddress = offsetTable.eaAddress;
const auto cfg = g_fxo->get<gcm_config>();
table->ioAddress = cfg->offsetTable.ioAddress;
table->eaAddress = cfg->offsetTable.eaAddress;
}
error_code cellGcmIoOffsetToAddress(u32 ioOffset, vm::ptr<u32> address)
{
cellGcmSys.trace("cellGcmIoOffsetToAddress(ioOffset=0x%x, address=*0x%x)", ioOffset, address);
const u32 upper12Bits = offsetTable.eaAddress[ioOffset >> 20];
const u32 addr = gcmIoOffsetToAddress(ioOffset);
if (static_cast<s16>(upper12Bits) < 0)
if (!addr)
{
return CELL_GCM_ERROR_FAILURE;
}
*address = (upper12Bits << 20) | (ioOffset & 0xFFFFF);
*address = addr;
return CELL_OK;
}
@ -990,16 +969,18 @@ error_code gcmMapEaIoAddress(u32 ea, u32 io, u32 size, bool is_strict)
return error;
}
// Assume lock is acquired
const auto cfg = g_fxo->get<gcm_config>();
ea >>= 20, io >>= 20, size >>= 20;
// Fill the offset table
for (u32 i = 0; i < size; i++)
{
offsetTable.ioAddress[ea + i] = io + i;
offsetTable.eaAddress[io + i] = ea + i;
cfg->offsetTable.ioAddress[ea + i] = io + i;
cfg->offsetTable.eaAddress[io + i] = ea + i;
}
IoMapTable[ea] = size;
cfg->IoMapTable[ea] = size;
return CELL_OK;
}
@ -1007,6 +988,9 @@ error_code cellGcmMapEaIoAddress(u32 ea, u32 io, u32 size)
{
cellGcmSys.warning("cellGcmMapEaIoAddress(ea=0x%x, io=0x%x, size=0x%x)", ea, io, size);
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
return gcmMapEaIoAddress(ea, io, size, false);
}
@ -1016,6 +1000,9 @@ error_code cellGcmMapEaIoAddressWithFlags(u32 ea, u32 io, u32 size, u32 flags)
verify(HERE), flags == 2 /*CELL_GCM_IOMAP_FLAG_STRICT_ORDERING*/;
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
return gcmMapEaIoAddress(ea, io, size, true);
}
@ -1023,17 +1010,17 @@ error_code cellGcmMapLocalMemory(vm::ptr<u32> address, vm::ptr<u32> size)
{
cellGcmSys.warning("cellGcmMapLocalMemory(address=*0x%x, size=*0x%x)", address, size);
if (!local_addr && !local_size && vm::falloc(local_addr = rsx::constants::local_mem_base, local_size = 0xf900000 /* TODO */, vm::video))
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
if (!cfg->local_addr && !cfg->local_size && vm::falloc(cfg->local_addr = rsx::constants::local_mem_base, cfg->local_size = 0xf900000 /* TODO */, vm::video))
{
*address = local_addr;
*size = local_size;
}
else
{
return CELL_GCM_ERROR_FAILURE;
*address = cfg->local_addr;
*size = cfg->local_size;
return CELL_OK;
}
return CELL_OK;
return CELL_GCM_ERROR_FAILURE;
}
error_code cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
@ -1042,10 +1029,13 @@ error_code cellGcmMapMainMemory(u32 ea, u32 size, vm::ptr<u32> offset)
if (!size || (ea & 0xFFFFF) || (size & 0xFFFFF)) return CELL_GCM_ERROR_FAILURE;
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
// Use the offset table to find the next free io address
for (u32 io = 0, end = (rsx::get_current_renderer()->main_mem_size - reserved_size) >> 20, unmap_count = 1; io < end; unmap_count++)
for (u32 io = 0, end = (rsx::get_current_renderer()->main_mem_size - cfg->reserved_size) >> 20, unmap_count = 1; io < end; unmap_count++)
{
if (static_cast<s16>(offsetTable.eaAddress[io + unmap_count - 1]) < 0)
if (static_cast<s16>(cfg->offsetTable.eaAddress[io + unmap_count - 1]) < 0)
{
if (unmap_count >= (size >> 20))
{
@ -1079,12 +1069,15 @@ error_code cellGcmReserveIoMapSize(u32 size)
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
}
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
if (size > cellGcmGetMaxIoMapSize())
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
reserved_size += size;
cfg->reserved_size += size;
return CELL_OK;
}
@ -1092,48 +1085,60 @@ error_code cellGcmUnmapEaIoAddress(u32 ea)
{
cellGcmSys.warning("cellGcmUnmapEaIoAddress(ea=0x%x)", ea);
if (const u32 size = IoMapTable[ea >>= 20].exchange(0))
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
if (const u32 size = cfg->IoMapTable[ea >> 20])
{
const u32 io = offsetTable.ioAddress[ea];
u32 io = cfg->offsetTable.ioAddress[ea];
if (auto error = sys_rsx_context_iounmap(0x55555555, io, size))
{
return error;
}
ea >>= 20, io >>= 20;
const auto render = rsx::get_current_renderer();
for (u32 i = 0; i < size; i++)
{
RSXIOMem.io[ea + i].raw() = offsetTable.ioAddress[ea + i] = 0xFFFF;
RSXIOMem.ea[io + i].raw() = offsetTable.eaAddress[io + i] = 0xFFFF;
cfg->offsetTable.ioAddress[ea + i] = 0xFFFF;
cfg->offsetTable.eaAddress[io + i] = 0xFFFF;
}
std::atomic_thread_fence(std::memory_order_seq_cst);
}
else
{
return CELL_GCM_ERROR_FAILURE;
cfg->IoMapTable[ea] = 0;
return CELL_OK;
}
return CELL_OK;
return CELL_GCM_ERROR_FAILURE;
}
error_code cellGcmUnmapIoAddress(u32 io)
{
cellGcmSys.warning("cellGcmUnmapIoAddress(io=0x%x)", io);
if (u32 size = IoMapTable[RSXIOMem.ea[io >>= 20]].exchange(0))
{
const u32 ea = offsetTable.eaAddress[io];
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
for (u32 i = 0; i < size; i++)
if (u32 ea = cfg->offsetTable.eaAddress[io >>= 20], size = cfg->IoMapTable[ea]; size)
{
if (auto error = sys_rsx_context_iounmap(0x55555555, io, size))
{
RSXIOMem.io[ea + i].raw() = offsetTable.ioAddress[ea + i] = 0xFFFF;
RSXIOMem.ea[io + i].raw() = offsetTable.eaAddress[io + i] = 0xFFFF;
return error;
}
std::atomic_thread_fence(std::memory_order_seq_cst);
}
else
{
return CELL_GCM_ERROR_FAILURE;
const auto render = rsx::get_current_renderer();
for (u32 i = 0; i < size; i++)
{
cfg->offsetTable.ioAddress[ea + i] = 0xFFFF;
cfg->offsetTable.eaAddress[io + i] = 0xFFFF;
}
return CELL_OK;
}
return CELL_OK;
return CELL_GCM_ERROR_FAILURE;
}
error_code cellGcmUnreserveIoMapSize(u32 size)
@ -1145,12 +1150,15 @@ error_code cellGcmUnreserveIoMapSize(u32 size)
return CELL_GCM_ERROR_INVALID_ALIGNMENT;
}
if (size > reserved_size)
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
if (size > cfg->reserved_size)
{
return CELL_GCM_ERROR_INVALID_VALUE;
}
reserved_size -= size;
cfg->reserved_size -= size;
return CELL_OK;
}
@ -1375,7 +1383,7 @@ static std::pair<u32, u32> getNextCommandBufferBeginEnd(u32 current)
static u32 getOffsetFromAddress(u32 address)
{
const u32 upper = offsetTable.ioAddress[address >> 20]; // 12 bits
const u32 upper = g_fxo->get<gcm_config>()->offsetTable.ioAddress[address >> 20]; // 12 bits
verify(HERE), (upper != 0xFFFF);
return (upper << 20) | (address & 0xFFFFF);
}

View file

@ -19,4 +19,26 @@ struct CellGcmOffsetTable
vm::bptr<u16> eaAddress;
};
struct gcm_config
{
u32 zculls_addr;
vm::ptr<CellGcmDisplayInfo> gcm_buffers = vm::null;
u32 tiles_addr;
u32 ctxt_addr;
CellGcmConfig current_config;
CellGcmContextData current_context;
gcmInfo gcm_info;
CellGcmOffsetTable offsetTable;
u16 IoMapTable[0xC00]{};
shared_mutex gcmio_mutex;
u64 system_mode = 0;
u32 local_size = 0;
u32 local_addr = 0;
atomic_t<u32> reserved_size = 0;
};
void InitOffsetTable();

View file

@ -188,8 +188,6 @@ error_code sys_rsx_context_allocate(vm::ptr<u32> context_id, vm::ptr<u64> lpar_d
dmaControl.put = 0;
dmaControl.ref = 0; // Set later to -1 by cellGcmSys
memset(&RSXIOMem, 0xFF, sizeof(RSXIOMem));
if (false/*system_mode == CELL_GCM_SYSTEM_MODE_IOMAP_512MB*/)
rsx::get_current_renderer()->main_mem_size = 0x20000000; //512MB
else
@ -251,8 +249,10 @@ error_code sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 f
{
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);
const auto render = rsx::get_current_renderer();
if (!size || io & 0xFFFFF || ea + u64{size} > rsx::constants::local_mem_base || ea & 0xFFFFF || size & 0xFFFFF ||
context_id != 0x55555555 || rsx::get_current_renderer()->main_mem_size < io + u64{size})
context_id != 0x55555555 || render->main_mem_size < io + u64{size})
{
return CELL_EINVAL;
}
@ -273,9 +273,13 @@ error_code sys_rsx_context_iomap(u32 context_id, u32 io, u32 ea, u32 size, u64 f
for (u32 i = 0; i < size; i++)
{
const u32 prev_ea = std::exchange(RSXIOMem.ea[io + i].raw(), ea + i);
if (prev_ea < 0xC00) RSXIOMem.io[prev_ea].raw() = 0xFFFF; // Clear previous mapping if exists
RSXIOMem.io[ea + i].raw() = io + i;
auto& table = render->iomap_table;
// TODO: Investigate relaxed memory ordering
const u32 prev_ea = table.ea[io + i];
table.ea[io + i].release((ea + i) << 20);
if (prev_ea + 1) table.io[prev_ea >> 20].release(-1); // Clear previous mapping if exists
table.io[ea + i].release((io + i) << 20);
}
return CELL_OK;
@ -291,8 +295,10 @@ error_code sys_rsx_context_iounmap(u32 context_id, u32 io, u32 size)
{
sys_rsx.warning("sys_rsx_context_iounmap(context_id=0x%x, io=0x%x, size=0x%x)", context_id, io, size);
const auto render = rsx::get_current_renderer();
if (!size || size & 0xFFFFF || io & 0xFFFFF || context_id != 0x55555555 ||
rsx::get_current_renderer()->main_mem_size < io + u64{size})
render->main_mem_size < io + u64{size})
{
return CELL_EINVAL;
}
@ -301,12 +307,13 @@ error_code sys_rsx_context_iounmap(u32 context_id, u32 io, u32 size)
std::scoped_lock lock(s_rsxmem_mtx);
const u32 end = (io >>= 20) + (size >>= 20);
while (io < end)
for (const u32 end = (io >>= 20) + (size >>= 20); io < end;)
{
const u32 ea_entry = std::exchange(RSXIOMem.ea[io++].raw(), 0xFFFF);
if (ea_entry < 0xC00) RSXIOMem.io[ea_entry].raw() = 0xFFFF;
auto& table = render->iomap_table;
const u32 ea_entry = table.ea[io];
table.ea[io++].release(-1);
if (ea_entry + 1) table.io[ea_entry >> 20].release(-1);
}
return CELL_OK;

View file

@ -11,6 +11,7 @@ namespace rsx
FIFO_control::FIFO_control(::rsx::thread* pctrl)
{
m_ctrl = pctrl->ctrl;
m_iotable = &pctrl->iomap_table;
}
void FIFO_control::inc_get(bool wait)
@ -57,7 +58,7 @@ namespace rsx
{
if (m_ctrl->get == get)
{
if (const auto addr = RSXIOMem.RealAddr(m_memwatch_addr))
if (const u32 addr = m_iotable->get_addr(m_memwatch_addr); addr + 1)
{
m_memwatch_addr = get;
m_memwatch_cmp = vm::read32(addr);
@ -119,7 +120,7 @@ namespace rsx
{
if (m_internal_get == m_memwatch_addr)
{
if (const auto addr = RSXIOMem.RealAddr(m_memwatch_addr))
if (const u32 addr = m_iotable->get_addr(m_memwatch_addr); addr + 1)
{
if (vm::read32(addr) == m_memwatch_cmp)
{
@ -134,7 +135,7 @@ namespace rsx
m_memwatch_cmp = 0;
}
if (u32 addr = RSXIOMem.RealAddr(m_internal_get))
if (const u32 addr = m_iotable->get_addr(m_internal_get); addr + 1)
{
m_cmd = vm::read32(addr);
}
@ -163,8 +164,8 @@ namespace rsx
}
// Validate the args ptr if the command attempts to read from it
m_args_ptr = RSXIOMem.RealAddr(m_internal_get + 4);
if (!m_args_ptr) [[unlikely]]
m_args_ptr = m_iotable->get_addr(m_internal_get + 4);
if (m_args_ptr == -1) [[unlikely]]
{
// Optional recovery
data.reg = FIFO_ERROR;

View file

@ -9,6 +9,7 @@
namespace rsx
{
class thread;
struct rsx_iomap_table;
namespace FIFO
{
@ -112,6 +113,7 @@ namespace rsx
{
private:
RsxDmaControl* m_ctrl = nullptr;
rsx::rsx_iomap_table* m_iotable;
u32 m_internal_get = 0;
u32 m_memwatch_addr = 0;

View file

@ -35,7 +35,6 @@ bool user_asked_for_frame_capture = false;
bool capture_current_frame = false;
rsx::frame_trace_data frame_debug;
rsx::frame_capture_data frame_capture;
RSXIOTable RSXIOMem;
extern CellGcmOffsetTable offsetTable;
extern thread_local std::string(*g_tls_log_prefix)();
@ -68,9 +67,9 @@ namespace rsx
case CELL_GCM_CONTEXT_DMA_MEMORY_HOST_BUFFER:
case CELL_GCM_LOCATION_MAIN:
{
if (u32 result = RSXIOMem.RealAddr(offset))
if (const u32 ea = render->iomap_table.get_addr(offset); ea + 1)
{
return result;
return ea;
}
msg = "RSXIO memory not mapped!"sv;
@ -90,9 +89,9 @@ namespace rsx
case CELL_GCM_CONTEXT_DMA_REPORT_LOCATION_MAIN:
{
if (u32 result = offset < 0x1000000 ? RSXIOMem.RealAddr(0x0e000000 + offset) : 0)
if (const u32 ea = offset < 0x1000000 ? render->iomap_table.get_addr(0x0e000000 + offset) : -1; ea + 1)
{
return result;
return ea;
}
msg = "RSXIO REPORT memory not mapped!"sv;
@ -617,10 +616,11 @@ namespace rsx
while (true)
{
// Wait for external pause events
if (external_interrupt_lock.load())
if (external_interrupt_lock)
{
external_interrupt_ack.store(true);
while (external_interrupt_lock.load()) _mm_pause();
while (external_interrupt_lock) _mm_pause();
}
// Note a possible rollback address
@ -2390,13 +2390,13 @@ namespace rsx
for (u32 ea = address >> 20, end = ea + (size >> 20); ea < end; ea++)
{
u32 io = RSXIOMem.io[ea];
const u32 io = utils::ror32(iomap_table.io[ea], 20);
if (io < 512)
if (io + 1)
{
unmap_status[io / 64] |= 1ull << (io & 63);
RSXIOMem.ea[io].raw() = 0xFFFF;
RSXIOMem.io[ea].raw() = 0xFFFF;
iomap_table.ea[io].release(-1);
iomap_table.io[ea].release(-1);
}
}
@ -2414,12 +2414,20 @@ namespace rsx
else
{
// TODO: Fix this
u32 ea = address >> 20, io = RSXIOMem.io[ea];
u32 ea = address >> 20, io = iomap_table.io[ea];
for (const u32 end = ea + (size >> 20); ea < end;)
if (io + 1)
{
offsetTable.ioAddress[ea++] = 0xFFFF;
offsetTable.eaAddress[io++] = 0xFFFF;
io >>= 20;
const auto cfg = g_fxo->get<gcm_config>();
std::lock_guard lock(cfg->gcmio_mutex);
for (const u32 end = ea + (size >> 20); ea < end;)
{
cfg->offsetTable.ioAddress[ea++] = 0xFFFF;
cfg->offsetTable.eaAddress[io++] = 0xFFFF;
}
}
}
@ -2460,14 +2468,19 @@ namespace rsx
//Pause/cont wrappers for FIFO ctrl. Never call this from rsx thread itself!
void thread::pause()
{
external_interrupt_lock.store(true);
while (!external_interrupt_ack.load())
while (external_interrupt_lock.exchange(true)) [[unlikely]]
{
_mm_pause();
}
while (!external_interrupt_ack)
{
if (Emu.IsStopped())
break;
_mm_pause();
}
external_interrupt_ack.store(false);
}

View file

@ -27,38 +27,32 @@
extern u64 get_guest_system_time();
extern u64 get_system_time();
struct RSXIOTable
{
atomic_t<u16> ea[4096];
atomic_t<u16> io[3072];
// try to get the real address given a mapped address
// return non zero on success
inline u32 RealAddr(u32 offs)
{
u32 result = this->ea[offs >> 20].load();
if (static_cast<s16>(result) < 0)
{
return 0;
}
result <<= 20; result |= (offs & 0xFFFFF);
ASSUME(result != 0);
return result;
}
};
extern bool user_asked_for_frame_capture;
extern bool capture_current_frame;
extern rsx::frame_trace_data frame_debug;
extern rsx::frame_capture_data frame_capture;
extern RSXIOTable RSXIOMem;
namespace rsx
{
struct rsx_iomap_table
{
std::array<atomic_t<u32>, 4096> ea;
std::array<atomic_t<u32>, 4096> io;
rsx_iomap_table() noexcept
{
std::fill(ea.begin(), ea.end(), -1);
std::fill(io.begin(), io.end(), -1);
}
// Try to get the real address given a mapped address
// Returns -1 on failure
u32 get_addr(u32 offs) const noexcept
{
return this->ea[offs >> 20] | (offs & 0xFFFFF);
}
};
enum framebuffer_creation_context : u8
{
context_draw = 0,
@ -603,6 +597,7 @@ namespace rsx
public:
RsxDmaControl* ctrl = nullptr;
rsx_iomap_table iomap_table;
u32 restore_point = 0;
atomic_t<bool> external_interrupt_lock{ false };
atomic_t<bool> external_interrupt_ack{ false };

View file

@ -208,7 +208,11 @@ namespace rsx
return;
}
vm::_ref<atomic_t<RsxNotify>>(verify(HERE, RSXIOMem.RealAddr(0xf100000 + (index * 0x40)))).store(
const u32 addr = rsx->iomap_table.get_addr(0xf100000 + (index * 0x40));
verify(HERE), addr != -1;
vm::_ref<atomic_t<RsxNotify>>(addr).store(
{
rsx->timestamp(),
0

View file

@ -120,12 +120,10 @@ rsx_debugger::rsx_debugger(std::shared_ptr<gui_settings> gui_settings, QWidget*
return table;
};
if (const auto render = rsx::get_current_renderer())
if (const auto render = rsx::get_current_renderer(); render &&
render->iomap_table.get_addr(render->ctrl->get) + 1)
{
if (RSXIOMem.RealAddr(render->ctrl->get.load()))
{
m_addr = render->ctrl->get.load();
}
m_addr = render->ctrl->get;
}
m_list_commands = l_addRSXTab(m_list_commands, tr("RSX Commands"), 4);
@ -210,24 +208,20 @@ rsx_debugger::rsx_debugger(std::shared_ptr<gui_settings> gui_settings, QWidget*
//Events
connect(b_goto_get, &QAbstractButton::clicked, [this]()
{
if (const auto render = rsx::get_current_renderer())
if (const auto render = rsx::get_current_renderer(); render &&
render->iomap_table.get_addr(render->ctrl->get) + 1)
{
if (RSXIOMem.RealAddr(render->ctrl->get.load()))
{
m_addr = render->ctrl->get.load();
UpdateInformation();
}
m_addr = render->ctrl->get;
UpdateInformation();
}
});
connect(b_goto_put, &QAbstractButton::clicked, [this]()
{
if (const auto render = rsx::get_current_renderer())
if (const auto render = rsx::get_current_renderer(); render &&
render->iomap_table.get_addr(render->ctrl->put) + 1)
{
if (RSXIOMem.RealAddr(render->ctrl->put.load()))
{
m_addr = render->ctrl->put.load();
UpdateInformation();
}
m_addr = render->ctrl->put;
UpdateInformation();
}
});
connect(m_addr_line, &QLineEdit::returnPressed, [this]()
@ -604,9 +598,10 @@ void rsx_debugger::GetMemory()
address_item->setData(Qt::UserRole, addr);
m_list_commands->setItem(i, 0, address_item);
if (vm::check_addr(RSXIOMem.RealAddr(addr)))
if (const u32 ea = rsx::get_current_renderer()->iomap_table.get_addr(addr);
ea + 1)
{
u32 cmd = *vm::get_super_ptr<u32>(RSXIOMem.RealAddr(addr));
u32 cmd = *vm::get_super_ptr<u32>(ea);
u32 count = (cmd >> 18) & 0x7ff;
m_list_commands->setItem(i, 1, new QTableWidgetItem(qstr(fmt::format("%08x", cmd))));
m_list_commands->setItem(i, 2, new QTableWidgetItem(DisAsmCommand(cmd, count, addr)));
@ -843,7 +838,7 @@ QString rsx_debugger::DisAsmCommand(u32 cmd, u32 count, u32 ioAddr)
}
else
{
auto args = vm::get_super_ptr<u32>(RSXIOMem.RealAddr(ioAddr + 4));
const auto args = vm::get_super_ptr<u32>(rsx::get_current_renderer()->iomap_table.get_addr(ioAddr + 4));
u32 index = 0;
switch((cmd & 0x3ffff) >> 2)