mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
rsx: rewrite io mappings
Along with some with fixes to cellGcmSys HLE.
This commit is contained in:
parent
f47333997f
commit
bdab26ec09
9 changed files with 233 additions and 186 deletions
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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 };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue