SPU: Validate reservation in GET commands (Accurate DMA) (#9062)

This commit is contained in:
Eladash 2020-10-12 15:20:06 +03:00 committed by GitHub
parent 5bd5a382c0
commit 95c1443e30
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 39 additions and 14 deletions

View File

@ -1378,57 +1378,82 @@ void spu_thread::do_dma_transfer(const spu_mfc_cmd& args)
continue;
}
const auto cpu = static_cast<spu_thread*>(get_current_cpu_thread());
alignas(64) u8 temp[128];
u8* dst0 = cpu && cpu->id_type() != 1 && (eal & -128) == cpu->raddr ? temp : dst;
if (dst0 == +temp && time0 != cpu->rtime)
{
// Validate rtime for read data
cpu->set_events(SPU_EVENT_LR);
cpu->raddr = 0;
}
switch (size0)
{
case 1:
{
*reinterpret_cast<u8*>(dst) = *reinterpret_cast<const u8*>(src);
*reinterpret_cast<u8*>(dst0) = *reinterpret_cast<const u8*>(src);
break;
}
case 2:
{
*reinterpret_cast<u16*>(dst) = *reinterpret_cast<const u16*>(src);
*reinterpret_cast<u16*>(dst0) = *reinterpret_cast<const u16*>(src);
break;
}
case 4:
{
*reinterpret_cast<u32*>(dst) = *reinterpret_cast<const u32*>(src);
*reinterpret_cast<u32*>(dst0) = *reinterpret_cast<const u32*>(src);
break;
}
case 8:
{
*reinterpret_cast<u64*>(dst) = *reinterpret_cast<const u64*>(src);
*reinterpret_cast<u64*>(dst0) = *reinterpret_cast<const u64*>(src);
break;
}
case 128:
{
mov_rdata(*reinterpret_cast<spu_rdata_t*>(dst), *reinterpret_cast<const spu_rdata_t*>(src));
mov_rdata(*reinterpret_cast<spu_rdata_t*>(dst0), *reinterpret_cast<const spu_rdata_t*>(src));
break;
}
default:
{
auto _dst = dst;
auto _src = src;
auto _size = size0;
auto dst1 = dst0;
auto src1 = src;
auto size1 = size0;
while (_size)
while (size1)
{
*reinterpret_cast<v128*>(_dst) = *reinterpret_cast<const v128*>(_src);
*reinterpret_cast<v128*>(dst1) = *reinterpret_cast<const v128*>(src1);
_dst += 16;
_src += 16;
_size -= 16;
dst1 += 16;
src1 += 16;
size1 -= 16;
}
break;
}
}
if (time0 != vm::reservation_acquire(eal, size0) || (size0 == 128 && !cmp_rdata(*reinterpret_cast<spu_rdata_t*>(dst), *reinterpret_cast<const spu_rdata_t*>(src))))
if (time0 != vm::reservation_acquire(eal, size0) || (size0 == 128 && !cmp_rdata(*reinterpret_cast<spu_rdata_t*>(dst0), *reinterpret_cast<const spu_rdata_t*>(src))))
{
continue;
}
if (dst0 == +temp)
{
// Write to LS
std::memcpy(dst, dst0, size0);
// Validate data
if (std::memcmp(dst0, &cpu->rdata[eal & 127], size0) != 0)
{
cpu->set_events(SPU_EVENT_LR);
cpu->raddr = 0;
}
}
break;
}