mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 15:01:28 +12:00
SPU reservations: Do not illegally dereference reservation data
This commit is contained in:
parent
a28ab0a408
commit
6dcd482dd0
4 changed files with 90 additions and 8 deletions
|
@ -2599,10 +2599,14 @@ bool spu_thread::do_putllc(const spu_mfc_cmd& args)
|
|||
if (raddr)
|
||||
{
|
||||
// Last check for event before we clear the reservation
|
||||
if (raddr == addr || rtime != vm::reservation_acquire(raddr, 128) || !cmp_rdata(rdata, vm::_ref<spu_rdata_t>(raddr)))
|
||||
if (raddr == addr)
|
||||
{
|
||||
set_events(SPU_EVENT_LR);
|
||||
}
|
||||
else
|
||||
{
|
||||
get_events(SPU_EVENT_LR);
|
||||
}
|
||||
}
|
||||
|
||||
if (!vm::check_addr(addr, 1, vm::page_writable))
|
||||
|
@ -2974,7 +2978,7 @@ bool spu_thread::process_mfc_cmd()
|
|||
if (raddr && raddr != addr)
|
||||
{
|
||||
// Last check for event before we replace the reservation with a new one
|
||||
if (vm::reservation_acquire(raddr, 128) != rtime || !cmp_rdata(temp, vm::_ref<spu_rdata_t>(raddr)))
|
||||
if (reservation_check(raddr, temp))
|
||||
{
|
||||
set_events(SPU_EVENT_LR);
|
||||
}
|
||||
|
@ -3146,6 +3150,28 @@ bool spu_thread::process_mfc_cmd()
|
|||
ch_mfc_cmd.cmd, ch_mfc_cmd.lsa, ch_mfc_cmd.eal, ch_mfc_cmd.tag, ch_mfc_cmd.size);
|
||||
}
|
||||
|
||||
bool spu_thread::reservation_check(u32 addr, const decltype(rdata)& data)
|
||||
{
|
||||
if (!addr)
|
||||
{
|
||||
// No reservation to be lost in the first place
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((vm::reservation_acquire(addr, 128) & -128) != rtime)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Ensure data is allocated (HACK: would raise LR event if not)
|
||||
vm::range_lock<false>(range_lock, addr, 128);
|
||||
|
||||
const bool res = *range_lock && cmp_rdata(data, vm::_ref<decltype(rdata)>(addr));
|
||||
|
||||
range_lock->release(0);
|
||||
return !res;
|
||||
}
|
||||
|
||||
spu_thread::ch_events_t spu_thread::get_events(u32 mask_hint, bool waiting, bool reading)
|
||||
{
|
||||
if (auto mask1 = ch_events.load().mask; mask1 & ~SPU_EVENT_IMPLEMENTED)
|
||||
|
@ -3157,10 +3183,13 @@ retry:
|
|||
u32 collect = 0;
|
||||
|
||||
// Check reservation status and set SPU_EVENT_LR if lost
|
||||
if (mask_hint & SPU_EVENT_LR && raddr && ((vm::reservation_acquire(raddr, sizeof(rdata)) & -128) != rtime || !cmp_rdata(rdata, vm::_ref<spu_rdata_t>(raddr))))
|
||||
if (mask_hint & SPU_EVENT_LR)
|
||||
{
|
||||
collect |= SPU_EVENT_LR;
|
||||
raddr = 0;
|
||||
if (reservation_check(raddr, rdata))
|
||||
{
|
||||
collect |= SPU_EVENT_LR;
|
||||
raddr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// SPU Decrementer Event on underflow (use the upper 32-bits to determine it)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue