1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 02:32:36 +01:00

Fix SPU LS MMIO

This commit is contained in:
Eladash 2020-11-23 20:02:05 +02:00 committed by Ivan
parent f0cba1371c
commit 3f028fbb83
2 changed files with 26 additions and 22 deletions

View File

@ -1668,12 +1668,12 @@ spu_thread::spu_thread(lv2_spu_group* group, u32 index, std::string_view name, u
if (!group) if (!group)
{ {
vm::get(vm::spu)->falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, &shm); verify(HERE), vm::get(vm::spu)->falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, SPU_LS_SIZE, &shm);
} }
else else
{ {
// 0x1000 indicates falloc to allocate page with no access rights in base memory // 0x1000 indicates falloc to allocate page with no access rights in base memory
vm::get(vm::spu)->falloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (cpu_thread::id & 0xffffff), SPU_LS_SIZE, &shm, 0x1000); verify(HERE), vm::get(vm::spu)->falloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (cpu_thread::id & 0xffffff), SPU_LS_SIZE, &shm, 0x1000);
} }
vm::writer_lock(0); vm::writer_lock(0);
@ -1811,6 +1811,23 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
u32 eal = args.eal; u32 eal = args.eal;
u32 lsa = args.lsa & 0x3ffff; u32 lsa = args.lsa & 0x3ffff;
// Keep src point to const
u8* dst = nullptr;
const u8* src = nullptr;
std::tie(dst, src) = [&]() -> std::pair<u8*, const u8*>
{
u8* dst = vm::_ptr<u8>(eal);
u8* src = ls + lsa;
if (is_get)
{
std::swap(src, dst);
}
return {dst, src};
}();
// SPU Thread Group MMIO (LS and SNR) and RawSPU MMIO // SPU Thread Group MMIO (LS and SNR) and RawSPU MMIO
if (_this && eal >= RAW_SPU_BASE_ADDR) if (_this && eal >= RAW_SPU_BASE_ADDR)
{ {
@ -1851,9 +1868,13 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
{ {
auto& spu = static_cast<spu_thread&>(*_this->group->threads[_this->group->threads_map[index]]); auto& spu = static_cast<spu_thread&>(*_this->group->threads[_this->group->threads_map[index]]);
if (offset + args.size - 1 < SPU_LS_SIZE) // LS access if (offset + args.size <= SPU_LS_SIZE) // LS access
{ {
eal = SPU_FAKE_BASE_ADDR * (spu.id & 0xffffff) + offset; // redirect access // redirect access
if (auto ptr = spu.ls + offset; is_get)
src = ptr;
else
dst = ptr;
} }
else if (!is_get && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2)) else if (!is_get && args.size == 4 && (offset == SYS_SPU_THREAD_SNR1 || offset == SYS_SPU_THREAD_SNR2))
{ {
@ -1871,29 +1892,12 @@ void spu_thread::do_dma_transfer(spu_thread* _this, const spu_mfc_cmd& args, u8*
} }
} }
// Keep src point to const
u8* dst = nullptr;
const u8* src = nullptr;
// Cleanup: if PUT or GET happens after PUTLLC failure, it's too complicated and it's easier to just give up // Cleanup: if PUT or GET happens after PUTLLC failure, it's too complicated and it's easier to just give up
if (_this) if (_this)
{ {
_this->last_faddr = 0; _this->last_faddr = 0;
} }
std::tie(dst, src) = [&]() -> std::pair<u8*, const u8*>
{
u8* dst = vm::_ptr<u8>(eal);
u8* src = ls + lsa;
if (is_get)
{
std::swap(src, dst);
}
return {dst, src};
}();
// It is so rare that optimizations are not implemented (TODO) // It is so rare that optimizations are not implemented (TODO)
alignas(64) static constexpr u8 zero_buf[0x10000]{}; alignas(64) static constexpr u8 zero_buf[0x10000]{};

View File

@ -682,7 +682,7 @@ error_code sys_spu_thread_group_destroy(ppu_thread& ppu, u32 id)
if (auto thread = t.get()) if (auto thread = t.get())
{ {
// Deallocate LS // Deallocate LS
vm::get(vm::spu)->dealloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (thread->id & 0xffffff), &thread->shm); verify(HERE), vm::get(vm::spu)->dealloc(SPU_FAKE_BASE_ADDR + SPU_LS_SIZE * (thread->id & 0xffffff), &thread->shm);
// Remove ID from IDM (destruction will occur in group destructor) // Remove ID from IDM (destruction will occur in group destructor)
idm::remove<named_thread<spu_thread>>(thread->id); idm::remove<named_thread<spu_thread>>(thread->id);