From a3f2dfa2325804993dafc7feaaae8af3bd294c66 Mon Sep 17 00:00:00 2001 From: Eladash Date: Wed, 15 Apr 2020 12:55:01 +0300 Subject: [PATCH] sys_isolated_spu --- rpcs3/Emu/Cell/RawSPUThread.cpp | 2 +- rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp | 3 + rpcs3/Emu/Cell/SPURecompiler.cpp | 1 + rpcs3/Emu/Cell/SPUThread.cpp | 10 +- rpcs3/Emu/Cell/SPUThread.h | 9 +- rpcs3/Emu/Cell/lv2/lv2.cpp | 26 +-- rpcs3/Emu/Cell/lv2/sys_spu.cpp | 266 ++++++++++++++++++++++--- rpcs3/Emu/Cell/lv2/sys_spu.h | 12 ++ rpcs3/Emu/Cell/lv2/sys_ss.cpp | 21 ++ rpcs3/Emu/Cell/lv2/sys_ss.h | 1 + 10 files changed, 296 insertions(+), 55 deletions(-) diff --git a/rpcs3/Emu/Cell/RawSPUThread.cpp b/rpcs3/Emu/Cell/RawSPUThread.cpp index 93b74fc587..0d23353139 100644 --- a/rpcs3/Emu/Cell/RawSPUThread.cpp +++ b/rpcs3/Emu/Cell/RawSPUThread.cpp @@ -17,7 +17,7 @@ inline void try_start(spu_thread& spu) return false; } - value.status = SPU_STATUS_RUNNING; + value.status = SPU_STATUS_RUNNING | (value.status & SPU_STATUS_IS_ISOLATED); return true; }).second) { diff --git a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp index 608a0e78f7..55baa2aa0e 100644 --- a/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp +++ b/rpcs3/Emu/Cell/SPUASMJITRecompiler.cpp @@ -1659,6 +1659,9 @@ void spu_recompiler::RDCH(spu_opcode_t op) { const XmmLink& vr = XmmAlloc(); c->movzx(*addr, SPU_OFF_8(interrupts_enabled)); + c->movzx(arg1->r32(), SPU_OFF_8(is_isolated)); + c->shl(arg1->r32(), 1); + c->or_(addr->r32(), arg1->r32()); c->movd(vr, *addr); c->pslldq(vr, 12); c->movdqa(SPU_OFF_128(gpr, op.rt), vr); diff --git a/rpcs3/Emu/Cell/SPURecompiler.cpp b/rpcs3/Emu/Cell/SPURecompiler.cpp index 58dee0d012..7256e7c150 100644 --- a/rpcs3/Emu/Cell/SPURecompiler.cpp +++ b/rpcs3/Emu/Cell/SPURecompiler.cpp @@ -5500,6 +5500,7 @@ public: case SPU_RdMachStat: { res.value = m_ir->CreateZExt(m_ir->CreateLoad(spu_ptr(&spu_thread::interrupts_enabled)), get_type()); + res.value = m_ir->CreateOr(res.value, m_ir->CreateShl(m_ir->CreateZExt(m_ir->CreateLoad(spu_ptr(&spu_thread::is_isolated)), get_type()), m_ir->getInt32(1))); break; } diff --git a/rpcs3/Emu/Cell/SPUThread.cpp b/rpcs3/Emu/Cell/SPUThread.cpp index 7f79952849..c15fcf29cb 100644 --- a/rpcs3/Emu/Cell/SPUThread.cpp +++ b/rpcs3/Emu/Cell/SPUThread.cpp @@ -1131,8 +1131,8 @@ void spu_thread::cpu_init() mfc_prxy_write_state = {}; } + status_npc.raw() = {is_isolated ? SPU_STATUS_IS_ISOLATED : 0, 0}; run_ctrl.raw() = 0; - status_npc.raw() = {}; int_ctrl[0].clear(); int_ctrl[1].clear(); @@ -1218,7 +1218,7 @@ void spu_thread::cpu_task() name_cache = cpu->spu_tname.load(); } - return fmt::format("%sSPU[0x%07x] Thread (%s) [0x%05x]", cpu->offset >= RAW_SPU_BASE_ADDR ? "Raw" : "", cpu->lv2_id, *name_cache.get(), cpu->pc); + return fmt::format("%sSPU[0x%07x] Thread (%s) [0x%05x]", cpu->offset >= RAW_SPU_BASE_ADDR ? cpu->is_isolated ? "Iso" : "Raw" : "", cpu->lv2_id, *name_cache.get(), cpu->pc); }; if (jit) @@ -1286,8 +1286,9 @@ spu_thread::~spu_thread() } } -spu_thread::spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id) +spu_thread::spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated) : cpu_thread(idm::last_id()) + , is_isolated(is_isolated) , index(index) , offset(ls) , group(group) @@ -2591,9 +2592,8 @@ s64 spu_thread::get_ch_value(u32 ch) case SPU_RdMachStat: { - // HACK: "Not isolated" status // Return SPU Interrupt status in LSB - return interrupts_enabled == true; + return u32{interrupts_enabled} | (u32{is_isolated} << 1); } } diff --git a/rpcs3/Emu/Cell/SPUThread.h b/rpcs3/Emu/Cell/SPUThread.h index 52cf9985a1..6845ce0f20 100644 --- a/rpcs3/Emu/Cell/SPUThread.h +++ b/rpcs3/Emu/Cell/SPUThread.h @@ -100,14 +100,14 @@ enum : u64 SPU_INT2_STAT_SPU_MAILBOX_THRESHOLD_INT = (1ull << 4), }; -enum +enum : u32 { SPU_RUNCNTL_STOP_REQUEST = 0, SPU_RUNCNTL_RUN_REQUEST = 1, }; // SPU Status Register bits (not accurate) -enum +enum : u32 { SPU_STATUS_STOPPED = 0x0, SPU_STATUS_RUNNING = 0x1, @@ -115,6 +115,7 @@ enum SPU_STATUS_STOPPED_BY_HALT = 0x4, SPU_STATUS_WAITING_FOR_CHANNEL = 0x8, SPU_STATUS_SINGLE_STEP = 0x10, + SPU_STATUS_IS_ISOLATED = 0x80, }; enum : u32 @@ -514,7 +515,7 @@ public: static const u32 id_step = 1; static const u32 id_count = 2048; - spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id); + spu_thread(vm::addr_t ls, lv2_spu_group* group, u32 index, std::string_view name, u32 lv2_id, bool is_isolated = false); u32 pc = 0; @@ -592,8 +593,8 @@ public: u32 npc; // SPU Next Program Counter register }; + const bool is_isolated; atomic_t status_npc; - std::array int_ctrl; // SPU Class 0, 1, 2 Interrupt Management std::array>, 32> spuq; // Event Queue Keys for SPU Thread diff --git a/rpcs3/Emu/Cell/lv2/lv2.cpp b/rpcs3/Emu/Cell/lv2/lv2.cpp index 19ecbcb9e7..a83bd977db 100644 --- a/rpcs3/Emu/Cell/lv2/lv2.cpp +++ b/rpcs3/Emu/Cell/lv2/lv2.cpp @@ -289,17 +289,17 @@ const std::array s_ppu_syscall_table null_func, null_func, null_func, null_func, null_func, //224 UNS null_func, null_func, null_func, null_func, null_func, //229 UNS? - null_func,//BIND_FUNC(sys_isolated_spu_create) //230 (0x0E6) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_destroy) //231 (0x0E7) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_start) //232 (0x0E8) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_create_interrupt_tag) //233 (0x0E9) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_set_int_mask) //234 (0x0EA) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_get_int_mask) //235 (0x0EB) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_set_int_stat) //236 (0x0EC) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_get_int_stat) //237 (0x0ED) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_set_spu_cfg) //238 (0x0EE) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_get_spu_cfg) //239 (0x0EF) ROOT - null_func,//BIND_FUNC(sys_isolated_spu_read_puint_mb) //240 (0x0F0) ROOT + BIND_FUNC(sys_isolated_spu_create), //230 (0x0E6) ROOT + BIND_FUNC(sys_isolated_spu_destroy), //231 (0x0E7) ROOT + BIND_FUNC(sys_isolated_spu_start), //232 (0x0E8) ROOT + BIND_FUNC(sys_isolated_spu_create_interrupt_tag), //233 (0x0E9) ROOT + BIND_FUNC(sys_isolated_spu_set_int_mask), //234 (0x0EA) ROOT + BIND_FUNC(sys_isolated_spu_get_int_mask), //235 (0x0EB) ROOT + BIND_FUNC(sys_isolated_spu_set_int_stat), //236 (0x0EC) ROOT + BIND_FUNC(sys_isolated_spu_get_int_stat), //237 (0x0ED) ROOT + BIND_FUNC(sys_isolated_spu_set_spu_cfg), //238 (0x0EE) ROOT + BIND_FUNC(sys_isolated_spu_get_spu_cfg), //239 (0x0EF) ROOT + BIND_FUNC(sys_isolated_spu_read_puint_mb), //240 (0x0F0) ROOT uns_func, uns_func, uns_func, //241-243 ROOT UNS null_func,//BIND_FUNC(sys_spu_thread_group_system_set_next_group) //244 (0x0F4) ROOT null_func,//BIND_FUNC(sys_spu_thread_group_system_unset_next_group) //245 (0x0F5) ROOT @@ -778,9 +778,9 @@ const std::array s_ppu_syscall_table null_func,//BIND_FUNC(sys_ss_update_manager) //863 ROOT null_func,//BIND_FUNC(sys_ss_sec_hw_framework) //864 DBG BIND_FUNC(sys_ss_random_number_generator), //865 (0x361) - null_func,//BIND_FUNC(sys_ss_secure_rtc) //866 ROOT + BIND_FUNC(sys_ss_secure_rtc), //866 ROOT null_func,//BIND_FUNC(sys_ss_appliance_info_manager) //867 ROOT - null_func,//BIND_FUNC(sys_ss_individual_info_manager) //868 ROOT / DBG AUTHID + BIND_FUNC(sys_ss_individual_info_manager), //868 ROOT / DBG AUTHID null_func,//BIND_FUNC(sys_ss_factory_data_manager) //869 ROOT BIND_FUNC(sys_ss_get_console_id), //870 (0x366) BIND_FUNC(sys_ss_access_control_engine), //871 (0x367) DBG diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.cpp b/rpcs3/Emu/Cell/lv2/sys_spu.cpp index 28ebbd6c42..66e5d44b78 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_spu.cpp @@ -12,6 +12,7 @@ #include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/RawSPUThread.h" #include "sys_interrupt.h" #include "sys_process.h" @@ -1684,22 +1685,86 @@ error_code sys_raw_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr at return CELL_OK; } -error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) +error_code sys_isolated_spu_create(ppu_thread& ppu, vm::ptr id, vm::ptr image, u64 arg1, u64 arg2, u64 arg3, u64 arg4) { vm::temporary_unlock(ppu); - sys_spu.warning("sys_raw_spu_destroy(id=%d)", id); + sys_spu.todo("sys_isolated_spu_create(id=*0x%x, image=*0x%x, arg1=0x%llx, arg2=0x%llx, arg3=0x%llx, arg4=0x%llx)", id, image, arg1, arg2, arg3, arg4); + // TODO: More accurate SPU image memory size calculation + u32 max = image.addr() & -4096; + + while (max != 0u - 4096 && vm::check_addr(max)) + { + max += 4096; + } + + const auto obj = decrypt_self(fs::file{image.get_ptr(), max - image.addr()}); + + if (!obj) + { + return CELL_EAUTHFAIL; + } + + // TODO: check number set by sys_spu_initialize() + + if (!spu_thread::g_raw_spu_ctr.try_inc(5)) + { + return CELL_EAGAIN; + } + + u32 index = 0; + + // Find free RawSPU ID + while (!spu_thread::g_raw_spu_id[index].try_inc(1)) + { + if (++index == 5) + index = 0; + } + + const vm::addr_t ls_addr{verify(HERE, vm::falloc(RAW_SPU_BASE_ADDR + RAW_SPU_OFFSET * index, 0x40000, vm::spu))}; + + const auto thread = idm::make_ptr>(fmt::format("IsoSPU[0x%x] Thread", index), ls_addr, nullptr, index, "", index, true); + + thread->gpr[3] = v128::from64(0, arg1); + thread->gpr[4] = v128::from64(0, arg2); + thread->gpr[5] = v128::from64(0, arg3); + thread->gpr[6] = v128::from64(0, arg4); + + spu_thread::g_raw_spu_id[index] = verify("IsoSPU ID" HERE, thread->id); + + sys_spu_image img; + img.load(obj); + + auto image_info = idm::get(img.entry_point); + img.deploy(ls_addr, image_info->segs.get_ptr(), image_info->nsegs); + + thread->write_reg(ls_addr + RAW_SPU_PROB_OFFSET + SPU_NPC_offs, image_info->e_entry); + verify(HERE), idm::remove_verify(img.entry_point, std::move(image_info)); + + *id = index; + return CELL_OK; +} + +template +error_code raw_spu_destroy(ppu_thread& ppu, u32 id) +{ const u32 idm_id = spu_thread::find_raw_spu(id); auto thread = idm::get>(idm_id, [](named_thread& thread) { + if (thread.is_isolated != isolated) + { + return false; + } + // Stop thread thread.state += cpu_flag::exit; thread = thread_state::aborting; + return true; }); - if (!thread) [[unlikely]] + if (!thread || !thread.ret) [[unlikely]] { return CELL_ESRCH; } @@ -1749,7 +1814,7 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) (*thread)(); - if (!idm::remove_verify>(idm_id, std::move(thread))) + if (!idm::remove_verify>(idm_id, std::move(thread.ptr))) { // Other thread destroyed beforehead return CELL_ESRCH; @@ -1758,12 +1823,27 @@ error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) return CELL_OK; } -error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_id, u32 hwthread, vm::ptr intrtag) +error_code sys_raw_spu_destroy(ppu_thread& ppu, u32 id) { vm::temporary_unlock(ppu); - sys_spu.warning("sys_raw_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag=*0x%x)", id, class_id, hwthread, intrtag); + sys_spu.warning("sys_raw_spu_destroy(id=%d)", id); + return raw_spu_destroy(ppu, id); +} + +error_code sys_isolated_spu_destroy(ppu_thread& ppu, u32 id) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_destroy(id=%d)", id); + + return raw_spu_destroy(ppu, id); +} + +template +error_code raw_spu_create_interrupt_tag(u32 id, u32 class_id, u32 hwthread, vm::ptr intrtag) +{ if (class_id != 0 && class_id != 2) { return CELL_EINVAL; @@ -1777,7 +1857,7 @@ error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_i auto thread = idm::check_unlocked>(spu_thread::find_raw_spu(id)); - if (!thread || *thread == thread_state::aborting) + if (!thread || *thread == thread_state::aborting || thread->is_isolated != isolated) { error = CELL_ESRCH; return result; @@ -1805,12 +1885,27 @@ error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_i return error; } -error_code sys_raw_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 mask) +error_code sys_raw_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_id, u32 hwthread, vm::ptr intrtag) { vm::temporary_unlock(ppu); - sys_spu.trace("sys_raw_spu_set_int_mask(id=%d, class_id=%d, mask=0x%llx)", id, class_id, mask); + sys_spu.warning("sys_raw_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag=*0x%x)", id, class_id, hwthread, intrtag); + return raw_spu_create_interrupt_tag(id, class_id, hwthread, intrtag); +} + +error_code sys_isolated_spu_create_interrupt_tag(ppu_thread& ppu, u32 id, u32 class_id, u32 hwthread, vm::ptr intrtag) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_create_interrupt_tag(id=%d, class_id=%d, hwthread=0x%x, intrtag=*0x%x)", id, class_id, hwthread, intrtag); + + return raw_spu_create_interrupt_tag(id, class_id, hwthread, intrtag); +} + +template +error_code raw_spu_set_int_mask(u32 id, u32 class_id, u64 mask) +{ if (class_id != 0 && class_id != 2) { return CELL_EINVAL; @@ -1818,7 +1913,7 @@ error_code sys_raw_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 m const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (!thread) [[unlikely]] + if (!thread || thread->is_isolated != isolated) [[unlikely]] { return CELL_ESRCH; } @@ -1828,12 +1923,28 @@ error_code sys_raw_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 m return CELL_OK; } -error_code sys_raw_spu_get_int_mask(ppu_thread& ppu, u32 id, u32 class_id, vm::ptr mask) +error_code sys_raw_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 mask) { vm::temporary_unlock(ppu); - sys_spu.trace("sys_raw_spu_get_int_mask(id=%d, class_id=%d, mask=*0x%x)", id, class_id, mask); + sys_spu.trace("sys_raw_spu_set_int_mask(id=%d, class_id=%d, mask=0x%llx)", id, class_id, mask); + return raw_spu_set_int_mask(id, class_id, mask); +} + + +error_code sys_isolated_spu_set_int_mask(ppu_thread& ppu, u32 id, u32 class_id, u64 mask) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_set_int_mask(id=%d, class_id=%d, mask=0x%llx)", id, class_id, mask); + + return raw_spu_set_int_mask(id, class_id, mask); +} + +template +error_code raw_spu_set_int_stat(u32 id, u32 class_id, u64 stat) +{ if (class_id != 0 && class_id != 2) { return CELL_EINVAL; @@ -1841,12 +1952,12 @@ error_code sys_raw_spu_get_int_mask(ppu_thread& ppu, u32 id, u32 class_id, vm::p const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (!thread) [[unlikely]] + if (!thread || thread->is_isolated != isolated) [[unlikely]] { return CELL_ESRCH; } - *mask = thread->int_ctrl[class_id].mask; + thread->int_ctrl[class_id].clear(stat); return CELL_OK; } @@ -1857,6 +1968,21 @@ error_code sys_raw_spu_set_int_stat(ppu_thread& ppu, u32 id, u32 class_id, u64 s sys_spu.trace("sys_raw_spu_set_int_stat(id=%d, class_id=%d, stat=0x%llx)", id, class_id, stat); + return raw_spu_set_int_stat(id, class_id, stat); +} + +error_code sys_isolated_spu_set_int_stat(ppu_thread& ppu, u32 id, u32 class_id, u64 stat) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_set_int_stat(id=%d, class_id=%d, stat=0x%llx)", id, class_id, stat); + + return raw_spu_set_int_stat(id, class_id, stat); +} + +template +error_code raw_spu_get_int_control(u32 id, u32 class_id, vm::ptr value, atomic_t spu_int_ctrl_t::* control) +{ if (class_id != 0 && class_id != 2) { return CELL_EINVAL; @@ -1864,35 +1990,63 @@ error_code sys_raw_spu_set_int_stat(ppu_thread& ppu, u32 id, u32 class_id, u64 s const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (!thread) [[unlikely]] + if (!thread || thread->is_isolated != isolated) [[unlikely]] { return CELL_ESRCH; } - thread->int_ctrl[class_id].clear(stat); + *value = thread->int_ctrl[class_id].*control; return CELL_OK; } +error_code sys_raw_spu_get_int_mask(ppu_thread& ppu, u32 id, u32 class_id, vm::ptr mask) +{ + vm::temporary_unlock(ppu); + + sys_spu.trace("sys_raw_spu_get_int_mask(id=%d, class_id=%d, mask=*0x%x)", id, class_id, mask); + + return raw_spu_get_int_control(id, class_id, mask, &spu_int_ctrl_t::mask); +} + +error_code sys_isolated_spu_get_int_mask(ppu_thread& ppu, u32 id, u32 class_id, vm::ptr mask) +{ + vm::temporary_unlock(ppu); + + sys_spu.trace("sys_isolated_spu_get_int_mask(id=%d, class_id=%d, mask=*0x%x)", id, class_id, mask); + + return raw_spu_get_int_control(id, class_id, mask, &spu_int_ctrl_t::mask); +} + error_code sys_raw_spu_get_int_stat(ppu_thread& ppu, u32 id, u32 class_id, vm::ptr stat) { vm::temporary_unlock(ppu); sys_spu.trace("sys_raw_spu_get_int_stat(id=%d, class_id=%d, stat=*0x%x)", id, class_id, stat); - if (class_id != 0 && class_id != 2) - { - return CELL_EINVAL; - } + return raw_spu_get_int_control(id, class_id, stat, &spu_int_ctrl_t::stat); +} +error_code sys_isolated_spu_get_int_stat(ppu_thread& ppu, u32 id, u32 class_id, vm::ptr stat) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_get_int_stat(id=%d, class_id=%d, stat=*0x%x)", id, class_id, stat); + + return raw_spu_get_int_control(id, class_id, stat, &spu_int_ctrl_t::stat); +} + +template +error_code raw_spu_read_puint_mb(u32 id, vm::ptr value) +{ const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (!thread) [[unlikely]] + if (!thread || thread->is_isolated != isolated) [[unlikely]] { return CELL_ESRCH; } - *stat = thread->int_ctrl[class_id].stat; + *value = thread->ch_out_intr_mbox.pop(*thread); return CELL_OK; } @@ -1903,14 +2057,34 @@ error_code sys_raw_spu_read_puint_mb(ppu_thread& ppu, u32 id, vm::ptr value sys_spu.trace("sys_raw_spu_read_puint_mb(id=%d, value=*0x%x)", id, value); + return raw_spu_read_puint_mb(id, value); +} + +error_code sys_isolated_spu_read_puint_mb(ppu_thread& ppu, u32 id, vm::ptr value) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_read_puint_mb(id=%d, value=*0x%x)", id, value); + + return raw_spu_read_puint_mb(id, value); +} + +template +error_code raw_spu_set_spu_cfg(u32 id, u32 value) +{ + if (value > 3) + { + fmt::throw_exception("Unexpected value (0x%x)" HERE, value); + } + const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (!thread) [[unlikely]] + if (!thread || thread->is_isolated != isolated) [[unlikely]] { return CELL_ESRCH; } - *value = thread->ch_out_intr_mbox.pop(*thread); + thread->snr_config = value; return CELL_OK; } @@ -1921,19 +2095,29 @@ error_code sys_raw_spu_set_spu_cfg(ppu_thread& ppu, u32 id, u32 value) sys_spu.trace("sys_raw_spu_set_spu_cfg(id=%d, value=0x%x)", id, value); - if (value > 3) - { - fmt::throw_exception("Unexpected value (0x%x)" HERE, value); - } + return raw_spu_set_spu_cfg(id, value); +} +error_code sys_isolated_spu_set_spu_cfg(ppu_thread& ppu, u32 id, u32 value) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_set_spu_cfg(id=%d, value=0x%x)", id, value); + + return raw_spu_set_spu_cfg(id, value); +} + +template +error_code raw_spu_get_spu_cfg(u32 id, vm::ptr value) +{ const auto thread = idm::get>(spu_thread::find_raw_spu(id)); - if (!thread) [[unlikely]] + if (!thread || thread->is_isolated != isolated) [[unlikely]] { return CELL_ESRCH; } - thread->snr_config = value; + *value = static_cast(thread->snr_config); return CELL_OK; } @@ -1944,6 +2128,24 @@ error_code sys_raw_spu_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr value) sys_spu.trace("sys_raw_spu_get_spu_afg(id=%d, value=*0x%x)", id, value); + return raw_spu_get_spu_cfg(id, value); +} + +error_code sys_isolated_spu_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr value) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_get_spu_afg(id=%d, value=*0x%x)", id, value); + + return raw_spu_get_spu_cfg(id, value); +} + +error_code sys_isolated_spu_start(ppu_thread& ppu, u32 id) +{ + vm::temporary_unlock(ppu); + + sys_spu.todo("sys_isolated_spu_start(id=%d)", id); + const auto thread = idm::get>(spu_thread::find_raw_spu(id)); if (!thread) [[unlikely]] @@ -1951,7 +2153,7 @@ error_code sys_raw_spu_get_spu_cfg(ppu_thread& ppu, u32 id, vm::ptr value) return CELL_ESRCH; } - *value = static_cast(thread->snr_config); - + // TODO: Can return ESTAT if called twice + thread->write_reg(thread->offset + RAW_SPU_PROB_OFFSET + SPU_RunCntl_offs, SPU_RUNCNTL_RUN_REQUEST); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/lv2/sys_spu.h b/rpcs3/Emu/Cell/lv2/sys_spu.h index 0ddda9e788..e9cb133021 100644 --- a/rpcs3/Emu/Cell/lv2/sys_spu.h +++ b/rpcs3/Emu/Cell/lv2/sys_spu.h @@ -380,3 +380,15 @@ error_code sys_raw_spu_read_puint_mb(ppu_thread&, u32 id, vm::ptr value); error_code sys_raw_spu_set_spu_cfg(ppu_thread&, u32 id, u32 value); error_code sys_raw_spu_get_spu_cfg(ppu_thread&, u32 id, vm::ptr value); error_code sys_raw_spu_recover_page_fault(ppu_thread&, u32 id); + +error_code sys_isolated_spu_create(ppu_thread&, vm::ptr id, vm::ptr image, u64 arg1, u64 arg2, u64 arg3, u64 arg4); +error_code sys_isolated_spu_start(ppu_thread&, u32 id); +error_code sys_isolated_spu_destroy(ppu_thread& ppu, u32 id); +error_code sys_isolated_spu_create_interrupt_tag(ppu_thread&, u32 id, u32 class_id, u32 hwthread, vm::ptr intrtag); +error_code sys_isolated_spu_set_int_mask(ppu_thread&, u32 id, u32 class_id, u64 mask); +error_code sys_isolated_spu_get_int_mask(ppu_thread&, u32 id, u32 class_id, vm::ptr mask); +error_code sys_isolated_spu_set_int_stat(ppu_thread&, u32 id, u32 class_id, u64 stat); +error_code sys_isolated_spu_get_int_stat(ppu_thread&, u32 id, u32 class_id, vm::ptr stat); +error_code sys_isolated_spu_read_puint_mb(ppu_thread&, u32 id, vm::ptr value); +error_code sys_isolated_spu_set_spu_cfg(ppu_thread&, u32 id, u32 value); +error_code sys_isolated_spu_get_spu_cfg(ppu_thread&, u32 id, vm::ptr value); diff --git a/rpcs3/Emu/Cell/lv2/sys_ss.cpp b/rpcs3/Emu/Cell/lv2/sys_ss.cpp index 86fab523a8..df5fff3f89 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ss.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ss.cpp @@ -190,3 +190,24 @@ error_code sys_ss_virtual_trm_manager(u64 pkg_id, u64 a1, u64 a2, u64 a3, u64 a4 return CELL_OK; } + +error_code sys_ss_individual_info_manager(u64 pkg_id, u64 a2, vm::ptr out_size, u64 a4, u64 a5, u64 a6) +{ + sys_ss.todo("sys_ss_individual_info_manager(pkg=0x%llx, a2=0x%llx, out_size=*0x%llx, a4=0x%llx, a5=0x%llx, a6=0x%llx)", pkg_id, a2, out_size, a4, a5, a6); + + switch (pkg_id) + { + // Read EID + case 0x17002: + { + // TODO + vm::_ref(a5) = a4; // Write back size of buffer + break; + } + // Get EID size + case 0x17001: *out_size = 0x100; break; + default: break; + } + + return CELL_OK; +} \ No newline at end of file diff --git a/rpcs3/Emu/Cell/lv2/sys_ss.h b/rpcs3/Emu/Cell/lv2/sys_ss.h index b07991a8dd..19890e9900 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ss.h +++ b/rpcs3/Emu/Cell/lv2/sys_ss.h @@ -29,3 +29,4 @@ error_code sys_ss_get_cache_of_flash_ext_flag(vm::ptr flag); error_code sys_ss_get_boot_device(vm::ptr dev); error_code sys_ss_update_manager(u64 pkg_id, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6); error_code sys_ss_virtual_trm_manager(u64 pkg_id, u64 a1, u64 a2, u64 a3, u64 a4); +error_code sys_ss_individual_info_manager(u64 pkg_id, u64 a2, vm::ptr out_size, u64 a4, u64, u64 a5);