PPU: fixup for Accurate 128-byte reservations (#8998)

This commit is contained in:
Eladash 2020-10-01 18:15:07 +03:00 committed by GitHub
parent ef0faf03fd
commit 871b15f6e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 14 deletions

View File

@ -74,7 +74,7 @@ extern atomic_t<u32> g_progr_ptotal;
extern atomic_t<u32> g_progr_pdone;
// Should be of the same type
using spu_rdata_t = decltype(ppu_thread::full_rdata);
using spu_rdata_t = decltype(ppu_thread::rdata);
extern void mov_rdata(spu_rdata_t& _dst, const spu_rdata_t& _src);
extern bool cmp_rdata(const spu_rdata_t& _lhs, const spu_rdata_t& _rhs);
@ -1182,12 +1182,11 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr)
continue;
}
const u64 rdata = data;
const auto rdata = data.load();
if (ppu.use_full_rdata)
{
mov_rdata(ppu.full_rdata, vm::_ref<spu_rdata_t>(addr & -128));
reinterpret_cast<be_t<u64>&>(ppu.full_rdata[addr & 0x78]) = rdata; // Must match with rdata and must be of atomic 64-bits load
mov_rdata(ppu.rdata, vm::_ref<spu_rdata_t>(addr & -128));
}
if ((vm::reservation_acquire(addr, sizeof(T)) & mask_res) == ppu.rtime) [[likely]]
@ -1197,8 +1196,8 @@ static T ppu_load_acquire_reservation(ppu_thread& ppu, u32 addr)
ppu_log.warning("%s took too long: %u", sizeof(T) == 4 ? "LWARX" : "LDARX", count);
}
ppu.rdata = rdata;
return static_cast<T>(ppu.rdata << data_off >> size_off);
std::memcpy(&ppu.rdata[addr & 0x78], &rdata, 8); // Store atomic 64bits of rdata
return static_cast<T>(rdata << data_off >> size_off);
}
}
}
@ -1384,7 +1383,7 @@ const auto ppu_stcx_accurate_tx = build_function_asm<u32(*)(u32 raddr, u64 rtime
c.bind(fall);
c.sar(x86::eax, 24);
c.js(fail);
c.lock().bts(x86::dword_ptr(args[2], ::offset32(&ppu_thread::state) - ::offset32(&ppu_thread::full_rdata)), static_cast<u32>(cpu_flag::wait));
c.lock().bts(x86::dword_ptr(args[2], ::offset32(&ppu_thread::state) - ::offset32(&ppu_thread::rdata)), static_cast<u32>(cpu_flag::wait));
// Touch memory if transaction failed without RETRY flag on the first attempt
c.cmp(x86::r12, 1);
@ -1514,7 +1513,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
auto& data = vm::_ref<atomic_be_t<u64>>(addr & -8);
auto& res = vm::reservation_acquire(addr, sizeof(T));
const u64 old_data = ppu.rdata;
const u64 old_data = reinterpret_cast<be_t<u64>&>(ppu.rdata[addr & 0x78]);
const u64 rtime = ppu.rtime;
if constexpr (sizeof(T) == sizeof(u32))
@ -1564,7 +1563,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
{
if (g_use_rtm) [[likely]]
{
switch (ppu_stcx_accurate_tx(addr & -8, rtime, ppu.full_rdata, reg_value))
switch (ppu_stcx_accurate_tx(addr & -8, rtime, ppu.rdata, reg_value))
{
case 0:
{
@ -1581,7 +1580,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
cpu_thread::suspend_all cpu_lock(&ppu);
// Give up if PUTLLUC happened
if (res == (rtime | 1) && cmp_rdata(ppu.full_rdata, vm::_ref<spu_rdata_t>(addr & -128)))
if (res == (rtime | 1) && cmp_rdata(ppu.rdata, vm::_ref<spu_rdata_t>(addr & -128)))
{
data.release(reg_value);
res.release(rtime + 128);
@ -1616,7 +1615,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
// TODO: vm::check_addr
vm::writer_lock lock(addr);
if (cmp_rdata(ppu.full_rdata, super_data))
if (cmp_rdata(ppu.rdata, super_data))
{
data.release(reg_value);
res.release(rtime + 128);
@ -1665,7 +1664,7 @@ static bool ppu_store_reservation(ppu_thread& ppu, u32 addr, u64 reg_value)
return false;
}
if (!vm::reservation_trylock(res, ppu.rtime))
if (!vm::reservation_trylock(res, rtime))
{
return false;
}

View File

@ -193,8 +193,7 @@ public:
u32 raddr{0}; // Reservation addr
u64 rtime{0};
u64 rdata{0}; // Reservation data
alignas(64) std::byte full_rdata[128]{}; // Full reservation data
alignas(64) std::byte rdata[128]{}; // Reservation data
bool use_full_rdata{};
atomic_t<s32> prio{0}; // Thread priority (0..3071)