Skip to content

Commit

Permalink
rsx: Rewrite io mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Jan 17, 2020
1 parent ca5bc51 commit ae267ec
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 116 deletions.
67 changes: 33 additions & 34 deletions rpcs3/Emu/Cell/Modules/cellGcmSys.cpp
Expand Up @@ -77,6 +77,18 @@ u32 gcmGetLocalMemorySize(u32 sdk_version)
CellGcmOffsetTable offsetTable;
atomic_t<u16> IoMapTable[0xC00]{};

u32 gcmIoOffsetToAddress(u32 ioOffset)
{
const u32 upper12Bits = 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));
Expand All @@ -86,7 +98,6 @@ void InitOffsetTable()
memset(offsetTable.eaAddress.get_ptr(), 0xFF, 512 * sizeof(u16));
memset(IoMapTable, 0, 3072 * sizeof(u16));

memset(&RSXIOMem, 0xFF, sizeof(RSXIOMem));
reserved_size = 0;
}

Expand All @@ -111,7 +122,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::ptr<CellGcmReportData>::make(gcmIoOffsetToAddress(0x0e000000 + index * 0x10));
}

// Anything else is Local
Expand Down Expand Up @@ -204,24 +215,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 + 0x1400 + 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;
}

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -375,12 +370,6 @@ s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32
render->main_mem_size = 0x10000000;
}

if (gcmMapEaIoAddress(ioAddress, 0, ioSize, false) != CELL_OK)
{
cellGcmSys.error("cellGcmInit: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE;
}

gcm_cfg->current_config.ioSize = ioSize;
gcm_cfg->current_config.ioAddress = ioAddress;
gcm_cfg->current_config.localSize = local_size;
Expand Down Expand Up @@ -431,6 +420,13 @@ s32 _cellGcmInitBody(ppu_thread& ppu, vm::pptr<CellGcmContextData> context, u32
render->local_mem_size = local_size;
render->init(gcm_cfg->gcm_info.control_addr - 0x40);

if (gcmMapEaIoAddress(ioAddress, 0, ioSize, false) != CELL_OK)
{
//cellGcmSys.error("cellGcmInit: CELL_GCM_ERROR_FAILURE");
//return CELL_GCM_ERROR_FAILURE;
fmt::throw_exception("cellGcmInit() Failed to init" HERE);
}

return CELL_OK;
}

Expand Down Expand Up @@ -950,15 +946,15 @@ s32 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)
{
cellGcmSys.error("cellGcmIoOffsetToAddress: CELL_GCM_ERROR_FAILURE");
return CELL_GCM_ERROR_FAILURE;
}

*address = (upper12Bits << 20) | (ioOffset & 0xFFFFF);
*address = addr;

return CELL_OK;
}
Expand Down Expand Up @@ -1092,12 +1088,14 @@ s32 cellGcmUnmapEaIoAddress(u32 ea)

if (const u32 size = IoMapTable[ea >>= 20].exchange(0))
{
const auto render = rsx::get_current_renderer();

const u32 io = offsetTable.ioAddress[ea];

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;
render->iomap_table.io[ea + i] = static_cast<s16>(offsetTable.ioAddress[ea + i] = 0xFFFF);
render->iomap_table.ea[io + i] = static_cast<s16>(offsetTable.eaAddress[io + i] = 0xFFFF);
}

std::atomic_thread_fence(std::memory_order_seq_cst);
Expand All @@ -1115,14 +1113,15 @@ s32 cellGcmUnmapIoAddress(u32 io)
{
cellGcmSys.trace("cellGcmUnmapIoAddress(io=0x%x)", io);

if (u32 size = IoMapTable[RSXIOMem.ea[io >>= 20]].exchange(0))
if (u32 size = IoMapTable[offsetTable.eaAddress[io >>= 20]].exchange(0))
{
const auto render = rsx::get_current_renderer();
const u32 ea = offsetTable.eaAddress[io];

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;
render->iomap_table.io[ea + i] = static_cast<s16>(offsetTable.ioAddress[ea + i] = 0xFFFF);
render->iomap_table.ea[io + i] = static_cast<s16>(offsetTable.eaAddress[io + i] = 0xFFFF);
}

std::atomic_thread_fence(std::memory_order_seq_cst);
Expand Down
44 changes: 33 additions & 11 deletions rpcs3/Emu/Cell/lv2/sys_rsx.cpp
Expand Up @@ -40,6 +40,22 @@ u64 rsxTimeStamp()
return get_timebased_time();
}

struct rsx_lock
{
rsx::thread& m_rsx;

rsx_lock(rsx::thread* rsx)
: m_rsx(*rsx)
{
m_rsx.pause();
}

~rsx_lock()
{
m_rsx.unpause();
}
};

error_code sys_rsx_device_open()
{
sys_rsx.todo("sys_rsx_device_open()");
Expand Down Expand Up @@ -188,8 +204,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
Expand Down Expand Up @@ -251,12 +265,17 @@ 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;
}

// Mapping must be atomic, enforce that by pausing rsx
::rsx_lock rsxlock(render);

vm::reader_lock rlock;

for (u32 addr = ea, end = ea + size; addr < end; addr += 0x100000)
Expand All @@ -273,9 +292,9 @@ 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;
const u32 prev_ea = std::exchange(render->iomap_table.ea[io + i], (ea + i) << 20);
if (prev_ea + 1) render->iomap_table.io[prev_ea >> 20] = -1; // Clear previous mapping if exists
render->iomap_table.io[ea + i] = (io + i) << 20;
}

return CELL_OK;
Expand All @@ -291,8 +310,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;
}
Expand All @@ -305,8 +326,8 @@ error_code sys_rsx_context_iounmap(u32 context_id, u32 io, u32 size)

while (io < end)
{
const u32 ea_entry = std::exchange(RSXIOMem.ea[io++].raw(), 0xFFFF);
if (ea_entry < 0xC00) RSXIOMem.io[ea_entry].raw() = 0xFFFF;
const u32 ea_entry = std::exchange(render->iomap_table.ea[io++], -1);
if (ea_entry + 1) render->iomap_table.io[ea_entry >> 20] = -1;
}

return CELL_OK;
Expand Down Expand Up @@ -344,12 +365,13 @@ error_code sys_rsx_context_attribute(u32 context_id, u32 package_id, u64 a3, u64
switch (package_id)
{
case 0x001: // FIFO
render->pause();
{
::rsx_lock rsxlock(render);
render->ctrl->get = a3;
render->ctrl->put = a4;
render->restore_point = a3;
render->unpause();
break;
}

case 0x100: // Display mode set
break;
Expand Down
11 changes: 6 additions & 5 deletions rpcs3/Emu/RSX/RSXFIFO.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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_ioaddr(m_memwatch_addr); addr + 1)
{
m_memwatch_addr = get;
m_memwatch_cmp = vm::read32(addr);
Expand Down Expand Up @@ -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_ioaddr(m_memwatch_addr); addr + 1)
{
if (vm::read32(addr) == m_memwatch_cmp)
{
Expand All @@ -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_ioaddr(m_internal_get); addr + 1)
{
m_cmd = vm::read32(addr);
}
Expand Down Expand Up @@ -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 (UNLIKELY(!m_args_ptr))
m_args_ptr = m_iotable->get_ioaddr(m_internal_get + 4);
if (!LIKELY(m_args_ptr + 1))
{
// Optional recovery
data.reg = FIFO_ERROR;
Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/RSX/RSXFIFO.h
Expand Up @@ -9,6 +9,7 @@
namespace rsx
{
class thread;
struct rsx_iomap_table;

namespace FIFO
{
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit ae267ec

Please sign in to comment.