From c948c9305ccabd4f06a474699b334903789d0009 Mon Sep 17 00:00:00 2001 From: Eladash Date: Wed, 8 Apr 2020 14:26:31 +0300 Subject: [PATCH] sys_ppu_thread_create: read function descriptor immediately and save it --- rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp | 2 +- rpcs3/Emu/Cell/PPUCallback.h | 14 +++++++++++--- rpcs3/Emu/Cell/PPUThread.cpp | 14 ++++++++------ rpcs3/Emu/Cell/PPUThread.h | 11 ++++++++++- rpcs3/Emu/Cell/lv2/sys_interrupt.cpp | 2 +- rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp | 7 +++++-- rpcs3/Emu/Cell/lv2/sys_ppu_thread.h | 2 +- rpcs3/Emu/Memory/vm_ptr.h | 2 ++ 8 files changed, 39 insertions(+), 15 deletions(-) diff --git a/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp b/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp index 724b54cefd..5e0880e85d 100644 --- a/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp +++ b/rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp @@ -137,7 +137,7 @@ error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr thread_id, u32 en } // Call the syscall - if (error_code res = _sys_ppu_thread_create(thread_id, vm::make_var(ppu_thread_param_t{ entry, tls_addr + 0x7030 }), arg, 0, prio, stacksize, flags, threadname)) + if (error_code res = _sys_ppu_thread_create(thread_id, vm::make_var(ppu_thread_param_t{ vm::cast(entry), tls_addr + 0x7030 }), arg, 0, prio, stacksize, flags, threadname)) { return res; } diff --git a/rpcs3/Emu/Cell/PPUCallback.h b/rpcs3/Emu/Cell/PPUCallback.h index 71de6ead32..e9b4422609 100644 --- a/rpcs3/Emu/Cell/PPUCallback.h +++ b/rpcs3/Emu/Cell/PPUCallback.h @@ -2,6 +2,8 @@ #include "Emu/Cell/PPUThread.h" +struct ppu_func_opd_t; + namespace ppu_cb_detail { enum _func_arg_type @@ -179,12 +181,18 @@ namespace vm template FORCE_INLINE RT _ptr_base::operator()(ppu_thread& CPU, T... args) const { - const auto data = vm::_ptr(vm::cast(m_addr, HERE)); - const u32 pc = data[0]; - const u32 rtoc = data[1]; + const auto data = vm::_ptr(vm::cast(m_addr, HERE)); + const u32 pc = data->addr; + const u32 rtoc = data->rtoc; return ppu_cb_detail::_func_caller::call(CPU, pc, rtoc, args...); } + + template + FORCE_INLINE const ppu_func_opd_t& _ptr_base::opd() const + { + return vm::_ref(vm::cast(m_addr, HERE)); + } } template inline RT cb_call(ppu_thread& CPU, u32 pc, u32 rtoc, T... args) diff --git a/rpcs3/Emu/Cell/PPUThread.cpp b/rpcs3/Emu/Cell/PPUThread.cpp index 265e7863f5..e1f4e947d3 100644 --- a/rpcs3/Emu/Cell/PPUThread.cpp +++ b/rpcs3/Emu/Cell/PPUThread.cpp @@ -602,6 +602,12 @@ void ppu_thread::cpu_task() cmd_pop(), ppu_function_manager::get().at(arg)(*this); break; } + case ppu_cmd::opd_call: + { + const ppu_func_opd_t opd = cmd_get(1).as(); + cmd_pop(1), fast_call(opd.addr, opd.rtoc); + break; + } case ppu_cmd::ptr_call: { const ppu_function_t func = cmd_get(1).as(); @@ -747,6 +753,7 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3 , stack_size(param.stack_size) , stack_addr(param.stack_addr) , joiner(detached != 0 ? ppu_join_status::detached : ppu_join_status::joinable) + , entry_func(param.entry) , start_time(get_guest_system_time()) , ppu_tname(stx::shared_cptr::make(name)) { @@ -760,14 +767,9 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3 cmd_list ({ {ppu_cmd::set_args, 2}, param.arg0, param.arg1, - {ppu_cmd::lle_call, param.entry}, + {ppu_cmd::opd_call, 0}, std::bit_cast(entry_func), }); } - else - { - // Save entry for further use (interrupt handler workaround) - gpr[2] = param.entry; - } // Trigger the scheduler state += cpu_flag::suspend; diff --git a/rpcs3/Emu/Cell/PPUThread.h b/rpcs3/Emu/Cell/PPUThread.h index 8f04e02f24..a14bd452a0 100644 --- a/rpcs3/Emu/Cell/PPUThread.h +++ b/rpcs3/Emu/Cell/PPUThread.h @@ -16,6 +16,7 @@ enum class ppu_cmd : u32 lle_call, // Load addr and rtoc at *arg or *gpr[arg] and execute hle_call, // Execute function by index (arg) ptr_call, // Execute function by pointer + opd_call, // Execute function by provided rtoc and address (unlike lle_call, does not read memory) initialize, // ppu_initialize() sleep, reset_stack, // resets stack address @@ -35,13 +36,20 @@ enum class ppu_syscall_code : u64 { }; +// ppu function descriptor +struct ppu_func_opd_t +{ + be_t addr; + be_t rtoc; +}; + // ppu_thread constructor argument struct ppu_thread_params { vm::addr_t stack_addr; u32 stack_size; u32 tls_addr; - u32 entry; + ppu_func_opd_t entry; u64 arg0; u64 arg1; }; @@ -192,6 +200,7 @@ public: cmd64 cmd_wait(); // Empty command means caller must return, like true from cpu_thread::check_status(). cmd64 cmd_get(u32 index) { return cmd_queue[cmd_queue.peek() + index].load(); } + const ppu_func_opd_t entry_func; u64 start_time{0}; // Sleep start timepoint alignas(64) u64 syscall_args[4]{0}; // Last syscall arguments stored const char* current_function{}; // Current function name for diagnosis, optimized for speed. diff --git a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp index 18f58ee15d..c0e52ed59e 100644 --- a/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_interrupt.cpp @@ -15,7 +15,7 @@ void lv2_int_serv::exec() ({ { ppu_cmd::reset_stack, 0 }, { ppu_cmd::set_args, 2 }, arg1, arg2, - { ppu_cmd::lle_call, 2 }, + { ppu_cmd::opd_call, 0 }, std::bit_cast(thread->entry_func), { ppu_cmd::sleep, 0 } }); diff --git a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp index 750d6dc64f..70d97d42ea 100644 --- a/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp +++ b/rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp @@ -5,6 +5,7 @@ #include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/PPUThread.h" +#include "Emu/Cell/PPUCallback.h" #include "sys_event.h" #include "sys_process.h" #include "sys_mmapper.h" @@ -362,6 +363,8 @@ error_code _sys_ppu_thread_create(vm::ptr thread_id, vm::ptrentry.opd(); + // Clean some detached thread (hack) g_fxo->get()->clean(0); @@ -408,7 +411,7 @@ error_code _sys_ppu_thread_create(vm::ptr thread_id, vm::ptrtls; - p.entry = param->entry; + p.entry = entry; p.arg0 = arg; p.arg1 = unk; @@ -423,7 +426,7 @@ error_code _sys_ppu_thread_create(vm::ptr thread_id, vm::ptr entry; // vm::bptr + vm::bptr entry; be_t tls; // vm::bptr }; diff --git a/rpcs3/Emu/Memory/vm_ptr.h b/rpcs3/Emu/Memory/vm_ptr.h index dcb1568e4a..d9f71532c4 100644 --- a/rpcs3/Emu/Memory/vm_ptr.h +++ b/rpcs3/Emu/Memory/vm_ptr.h @@ -5,6 +5,7 @@ #include "vm.h" class ppu_thread; +struct ppu_func_opd_t; namespace vm { @@ -262,6 +263,7 @@ namespace vm // Callback; defined in PPUCallback.h, passing context is mandatory RT operator()(ppu_thread& ppu, T... args) const; + const ppu_func_opd_t& opd() const; }; template