From 7dce197ec45cdcfde4191a29d5b36e894492555f Mon Sep 17 00:00:00 2001 From: Elad <18193363+elad335@users.noreply.github.com> Date: Sat, 25 Apr 2026 02:44:21 +0300 Subject: [PATCH] sys_spu: Fix sys_isolated_spu_create --- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 35 +++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index ff4294a24f..263d871206 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -145,13 +145,34 @@ void sys_spu_image::deploy(u8* loc, std::span segs, bool sha1_update(&sha, reinterpret_cast(&seg.type), sizeof(seg.type)); + // Prevent possible segfault + const u32 masked_ls = seg.ls % SPU_LS_SIZE; + u32 masked_size = std::min(SPU_LS_SIZE - masked_ls, seg.size % SPU_LS_SIZE); + // Hash big-endian values if (seg.type == SYS_SPU_SEGMENT_TYPE_COPY) { - std::memcpy(loc + seg.ls, vm::base(seg.addr), seg.size); + if (!vm::check_addr(seg.addr, 0, seg.size)) + { + // Further clamp size to fit 4GB address space, preventing segfault + masked_size = masked_size ? std::min(u32{umax} - seg.addr, masked_size - 1) + 1 : 0; + spu_log.error("Dumping sys_spu_image log - illgal address:\n\n%s", dump); + } + + if ((seg.ls | seg.size) % 4) + { + spu_log.error("Unaligned SPU COPY type segment (ls=0x%x, size=0x%x)", seg.ls, seg.size); + } + + if (masked_ls != seg.ls || masked_size != seg.size) + { + spu_log.error("Illegal SPU COPY type segment (ls=0x%x, size=0x%x)", seg.ls, seg.size); + } + + std::memcpy(loc + masked_ls, vm::base(seg.addr), masked_size); sha1_update(&sha, reinterpret_cast(&seg.size), sizeof(seg.size)); sha1_update(&sha, reinterpret_cast(&seg.ls), sizeof(seg.ls)); - sha1_update(&sha, vm::_ptr(seg.addr), seg.size); + sha1_update(&sha, loc + masked_ls, masked_size); } else if (seg.type == SYS_SPU_SEGMENT_TYPE_FILL) { @@ -160,7 +181,12 @@ void sys_spu_image::deploy(u8* loc, std::span segs, bool spu_log.error("Unaligned SPU FILL type segment (ls=0x%x, size=0x%x)", seg.ls, seg.size); } - std::fill_n(reinterpret_cast*>(loc + seg.ls), seg.size / 4, seg.addr); + if (masked_ls != seg.ls || masked_size != seg.size) + { + spu_log.error("Illegal SPU FILL type segment (ls=0x%x, size=0x%x)", seg.ls, seg.size); + } + + std::fill_n(reinterpret_cast*>(loc + masked_ls), masked_size / 4, seg.addr); sha1_update(&sha, reinterpret_cast(&seg.size), sizeof(seg.size)); sha1_update(&sha, reinterpret_cast(&seg.ls), sizeof(seg.ls)); sha1_update(&sha, reinterpret_cast(&seg.addr), sizeof(seg.addr)); @@ -2517,6 +2543,9 @@ error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr>(nullptr, index, "", index, true); + ensure(vm::get(vm::spu)->falloc(thread->vm_offset(), SPU_LS_SIZE, &thread->shm, vm::page_size_64k)); + thread->map_ls(*thread->shm, thread->ls); + thread->gpr[3] = v128::from64(0, arg1); thread->gpr[4] = v128::from64(0, arg2); thread->gpr[5] = v128::from64(0, arg3);