Skip to content

Commit

Permalink
SPU: add the concept of inaccurate reservations for non-TSX
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Aug 18, 2022
1 parent 1f1509c commit 64445ea
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 16 deletions.
84 changes: 68 additions & 16 deletions rpcs3/Emu/Cell/Modules/cellSpurs.cpp
Expand Up @@ -1853,9 +1853,9 @@ s32 cellSpursSetPriority(vm::ptr<CellSpurs> spurs, u32 wid, u32 spuId, u32 prior
if (spurs->exception)
return CELL_SPURS_CORE_ERROR_STAT;

vm::light_op(spurs->wklInfo(wid).priority[spuId], [&](u8& v){ atomic_storage<u8>::release(v, priority); });
vm::light_op(spurs->sysSrvMsgUpdateWorkload, [&](atomic_t<u8>& v){ v.bit_test_set(spuId); });
vm::light_op(spurs->sysSrvMessage, [&](atomic_t<u8>& v){ v.bit_test_set(spuId); });
vm::light_op<true>(spurs->wklInfo(wid).priority[spuId], [&](u8& v){ atomic_storage<u8>::release(v, priority); });
vm::light_op<true>(spurs->sysSrvMsgUpdateWorkload, [&](atomic_t<u8>& v){ v.bit_test_set(spuId); });
vm::light_op<true>(spurs->sysSrvMessage, [&](atomic_t<u8>& v){ v.bit_test_set(spuId); });
return CELL_OK;
}

Expand Down Expand Up @@ -2360,14 +2360,45 @@ s32 _spurs::add_workload(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32>
return CELL_SPURS_POLICY_MODULE_ERROR_AGAIN;
}

auto& spurs_res = vm::reservation_acquire(spurs.addr());
auto& spurs_res2 = vm::reservation_acquire(spurs.addr() + 0x80);

if (!spurs_res2.fetch_op([&](u64& r)
{
if (r & vm::rsrv_unique_lock)
{
return false;
}

r += 1;
return true;
}).second)
{
vm::reservation_shared_lock_internal(spurs_res2);
}

if (!spurs_res.fetch_op([&](u64& r)
{
if (r & vm::rsrv_unique_lock)
{
return false;
}

r += 1;
return true;
}).second)
{
vm::reservation_shared_lock_internal(spurs_res);
}

u32 index = wnum & 0xf;
if (wnum <= 15)
{
ensure((spurs->wklCurrentContention[wnum] & 0xf) == 0);
ensure((spurs->wklPendingContention[wnum] & 0xf) == 0);
spurs->wklState1[wnum] = SPURS_WKL_STATE_PREPARING;
spurs->wklState1[wnum].release(SPURS_WKL_STATE_PREPARING);
spurs->wklStatus1[wnum] = 0;
spurs->wklEvent1[wnum] = 0;
spurs->wklEvent1[wnum].release(0);
spurs->wklInfo1[wnum].addr = pm;
spurs->wklInfo1[wnum].arg = data;
spurs->wklInfo1[wnum].size = size;
Expand Down Expand Up @@ -2395,15 +2426,15 @@ s32 _spurs::add_workload(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32>
spurs->wklMinContention[wnum] = minContention > 8 ? 8 : minContention;
}

spurs->wklReadyCount1[wnum] = 0;
spurs->wklReadyCount1[wnum].release(0);
}
else
{
ensure((spurs->wklCurrentContention[index] & 0xf0) == 0);
ensure((spurs->wklPendingContention[index] & 0xf0) == 0);
spurs->wklState2[index] = SPURS_WKL_STATE_PREPARING;
spurs->wklState2[index].release(SPURS_WKL_STATE_PREPARING);
spurs->wklStatus2[index] = 0;
spurs->wklEvent2[index] = 0;
spurs->wklEvent2[index].release(0);
spurs->wklInfo2[index].addr = pm;
spurs->wklInfo2[index].arg = data;
spurs->wklInfo2[index].size = size;
Expand All @@ -2425,21 +2456,30 @@ s32 _spurs::add_workload(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32>
spurs->wklEvent2[index] |= 2;
}

spurs->wklIdleSpuCountOrReadyCount2[wnum] = 0;
spurs->wklIdleSpuCountOrReadyCount2[wnum].release(0);
}

vm::atomic_op(spurs->wklMaxContention[index], [&](u8& v)
spurs->wklMaxContention[index].atomic_op([&](u8& v)
{
v &= (wnum <= 15 ? 0xf0 : 0x0f);
v |= (maxContention > 8 ? 8 : maxContention) << (wnum < CELL_SPURS_MAX_WORKLOAD ? 0 : 4);
});

vm::atomic_op<true>((wnum <= 15 ? spurs->wklSignal1 : spurs->wklSignal2), [&](be_t<u16>& data)
(wnum <= 15 ? spurs->wklSignal1 : spurs->wklSignal2).atomic_op([&](be_t<u16>& data)
{
data &= ~(0x8000 >> index);
});

spurs->wklFlagReceiver.compare_and_swap(wnum, 0xff);
if (spurs->wklFlagReceiver == wnum)
{
spurs->wklFlagReceiver.compare_and_swap(wnum, 0xff);
}

spurs_res += 127;
spurs_res2 += 127;

spurs_res.notify_all(-128);
spurs_res2.notify_all(-128);

u32 res_wkl;
const auto wkl = &spurs->wklInfo(wnum);
Expand Down Expand Up @@ -2473,15 +2513,15 @@ s32 _spurs::add_workload(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32>
});

ensure((res_wkl <= 31));
vm::light_op(spurs->sysSrvMsgUpdateWorkload, [](atomic_t<u8>& v){ v.release(0xff); });
vm::light_op<true>(spurs->sysSrvMsgUpdateWorkload, [](atomic_t<u8>& v){ v.release(0xff); });
vm::light_op<true>(spurs->sysSrvMessage, [](atomic_t<u8>& v){ v.release(0xff); });
return CELL_OK;
}

/// Add workload
s32 cellSpursAddWorkload(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<void> pm, u32 size, u64 data, vm::cptr<u8[8]> priority, u32 minCnt, u32 maxCnt)
{
cellSpurs.warning("cellSpursAddWorkload(spurs=*0x%x, wid=*0x%x, pm=*0x%x, size=0x%x, data=0x%llx, priority=*0x%x, minCnt=0x%x, maxCnt=0x%x)",
cellSpurs.trace("cellSpursAddWorkload(spurs=*0x%x, wid=*0x%x, pm=*0x%x, size=0x%x, data=0x%llx, priority=*0x%x, minCnt=0x%x, maxCnt=0x%x)",
spurs, wid, pm, size, data, priority, minCnt, maxCnt);

return _spurs::add_workload(ppu, spurs, wid, pm, size, data, *priority, minCnt, maxCnt, vm::null, vm::null, vm::null, vm::null);
Expand All @@ -2490,7 +2530,7 @@ s32 cellSpursAddWorkload(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32>
/// Add workload
s32 cellSpursAddWorkloadWithAttribute(ppu_thread& ppu, vm::ptr<CellSpurs> spurs, vm::ptr<u32> wid, vm::cptr<CellSpursWorkloadAttribute> attr)
{
cellSpurs.warning("cellSpursAddWorkloadWithAttribute(spurs=*0x%x, wid=*0x%x, attr=*0x%x)", spurs, wid, attr);
cellSpurs.trace("cellSpursAddWorkloadWithAttribute(spurs=*0x%x, wid=*0x%x, attr=*0x%x)", spurs, wid, attr);

if (!attr)
{
Expand Down Expand Up @@ -5224,7 +5264,7 @@ s32 cellSpursSemaphoreGetTasksetAddress()
return CELL_OK;
}

DECLARE(ppu_module_manager::cellSpurs)("cellSpurs", []()
DECLARE(ppu_module_manager::cellSpurs)("cellSpurs", [](ppu_static_module* _this)
{
// Core
REG_FUNC(cellSpurs, cellSpursInitialize);
Expand Down Expand Up @@ -5386,4 +5426,16 @@ DECLARE(ppu_module_manager::cellSpurs)("cellSpurs", []()
REG_FUNC(cellSpurs, cellSpursTraceStart);
REG_FUNC(cellSpurs, cellSpursTraceStop);
REG_FUNC(cellSpurs, cellSpursTraceFinalize);

_this->add_init_func([](ppu_static_module*)
{
REINIT_FUNC(cellSpursSetPriorities).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursAddWorkload).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursAddWorkloadWithAttribute).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursShutdownWorkload).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursReadyCountStore).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursSetPriority).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursTraceInitialize).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
REINIT_FUNC(cellSpursWaitForWorkloadShutdown).flag(g_cfg.core.spu_inaccurate_reservations ? MFF_FORCED_HLE : MFF_PERFECT);
});
});
21 changes: 21 additions & 0 deletions rpcs3/Emu/Cell/SPUThread.cpp
Expand Up @@ -1453,6 +1453,20 @@ void spu_thread::cpu_task()
return fmt::format("%sSPU[0x%07x] Thread (%s) [0x%05x]", type >= spu_type::raw ? type == spu_type::isolated ? "Iso" : "Raw" : "", cpu->lv2_id, *name_cache.get(), cpu->pc);
};

if (!spurs_addr)
{
// Evaluate it
if (!group)
{
spurs_addr = -0x80; // Some invalid non-0 address
}
else
{
const u32 arg = static_cast<u32>(group->args[index][1]);
spurs_addr = group->name.ends_with("CellSpursKernelGroup"sv) && vm::check_addr(arg) ? arg : 0u - 0x80;
}
}

if (jit)
{
while (true)
Expand Down Expand Up @@ -2908,6 +2922,13 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
return true;
}

if (g_cfg.core.spu_inaccurate_reservations && s_tls_spurs_addr == (addr & -256))
{
mov_rdata(vm::_ref<spu_rdata_t>(addr), to_write);
res += 64;
return true;
}

vm::_ref<atomic_t<u32>>(addr) += 0;

auto& super_data = *vm::get_super_ptr<spu_rdata_t>(addr);
Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/Cell/SPUThread.h
Expand Up @@ -814,6 +814,7 @@ class spu_thread : public cpu_thread
const std::add_pointer_t<u8> ls; // SPU LS pointer
const u32 option; // sys_spu_thread_initialize option
const u32 lv2_id; // The actual id that is used by syscalls
u32 spurs_addr = 0;

spu_thread* next_cpu{}; // LV2 thread queues' node link

Expand Down
1 change: 1 addition & 0 deletions rpcs3/Emu/system_config.h
Expand Up @@ -41,6 +41,7 @@ struct cfg_root : cfg::node
cfg::_enum<spu_block_size_type> spu_block_size{ this, "SPU Block Size", spu_block_size_type::safe };
cfg::_bool spu_accurate_getllar{ this, "Accurate GETLLAR", false, true };
cfg::_bool spu_accurate_dma{ this, "Accurate SPU DMA", false };
cfg::_bool spu_inaccurate_reservations{ this, "Inaccurate SPU Reservations", false };
cfg::_bool accurate_cache_line_stores{ this, "Accurate Cache Line Stores", false };
cfg::_bool rsx_accurate_res_access{this, "Accurate RSX reservation access", false, true};

Expand Down

0 comments on commit 64445ea

Please sign in to comment.