sys_ppu_thread_create: read function descriptor immediately and save it

This commit is contained in:
Eladash 2020-04-08 14:26:31 +03:00 committed by Ivan
parent 8c838698af
commit c948c9305c
8 changed files with 39 additions and 15 deletions

View file

@ -137,7 +137,7 @@ error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> thread_id, u32 en
} }
// Call the syscall // 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; return res;
} }

View file

@ -2,6 +2,8 @@
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
struct ppu_func_opd_t;
namespace ppu_cb_detail namespace ppu_cb_detail
{ {
enum _func_arg_type enum _func_arg_type
@ -179,12 +181,18 @@ namespace vm
template<typename AT, typename RT, typename... T> template<typename AT, typename RT, typename... T>
FORCE_INLINE RT _ptr_base<RT(T...), AT>::operator()(ppu_thread& CPU, T... args) const FORCE_INLINE RT _ptr_base<RT(T...), AT>::operator()(ppu_thread& CPU, T... args) const
{ {
const auto data = vm::_ptr<u32>(vm::cast(m_addr, HERE)); const auto data = vm::_ptr<ppu_func_opd_t>(vm::cast(m_addr, HERE));
const u32 pc = data[0]; const u32 pc = data->addr;
const u32 rtoc = data[1]; const u32 rtoc = data->rtoc;
return ppu_cb_detail::_func_caller<RT, T...>::call(CPU, pc, rtoc, args...); return ppu_cb_detail::_func_caller<RT, T...>::call(CPU, pc, rtoc, args...);
} }
template<typename AT, typename RT, typename... T>
FORCE_INLINE const ppu_func_opd_t& _ptr_base<RT(T...), AT>::opd() const
{
return vm::_ref<ppu_func_opd_t>(vm::cast(m_addr, HERE));
}
} }
template<typename RT, typename... T> inline RT cb_call(ppu_thread& CPU, u32 pc, u32 rtoc, T... args) template<typename RT, typename... T> inline RT cb_call(ppu_thread& CPU, u32 pc, u32 rtoc, T... args)

View file

@ -602,6 +602,12 @@ void ppu_thread::cpu_task()
cmd_pop(), ppu_function_manager::get().at(arg)(*this); cmd_pop(), ppu_function_manager::get().at(arg)(*this);
break; break;
} }
case ppu_cmd::opd_call:
{
const ppu_func_opd_t opd = cmd_get(1).as<ppu_func_opd_t>();
cmd_pop(1), fast_call(opd.addr, opd.rtoc);
break;
}
case ppu_cmd::ptr_call: case ppu_cmd::ptr_call:
{ {
const ppu_function_t func = cmd_get(1).as<ppu_function_t>(); const ppu_function_t func = cmd_get(1).as<ppu_function_t>();
@ -747,6 +753,7 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3
, stack_size(param.stack_size) , stack_size(param.stack_size)
, stack_addr(param.stack_addr) , stack_addr(param.stack_addr)
, joiner(detached != 0 ? ppu_join_status::detached : ppu_join_status::joinable) , joiner(detached != 0 ? ppu_join_status::detached : ppu_join_status::joinable)
, entry_func(param.entry)
, start_time(get_guest_system_time()) , start_time(get_guest_system_time())
, ppu_tname(stx::shared_cptr<std::string>::make(name)) , ppu_tname(stx::shared_cptr<std::string>::make(name))
{ {
@ -760,14 +767,9 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3
cmd_list cmd_list
({ ({
{ppu_cmd::set_args, 2}, param.arg0, param.arg1, {ppu_cmd::set_args, 2}, param.arg0, param.arg1,
{ppu_cmd::lle_call, param.entry}, {ppu_cmd::opd_call, 0}, std::bit_cast<u64>(entry_func),
}); });
} }
else
{
// Save entry for further use (interrupt handler workaround)
gpr[2] = param.entry;
}
// Trigger the scheduler // Trigger the scheduler
state += cpu_flag::suspend; state += cpu_flag::suspend;

View file

@ -16,6 +16,7 @@ enum class ppu_cmd : u32
lle_call, // Load addr and rtoc at *arg or *gpr[arg] and execute lle_call, // Load addr and rtoc at *arg or *gpr[arg] and execute
hle_call, // Execute function by index (arg) hle_call, // Execute function by index (arg)
ptr_call, // Execute function by pointer 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() initialize, // ppu_initialize()
sleep, sleep,
reset_stack, // resets stack address 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<u32> addr;
be_t<u32> rtoc;
};
// ppu_thread constructor argument // ppu_thread constructor argument
struct ppu_thread_params struct ppu_thread_params
{ {
vm::addr_t stack_addr; vm::addr_t stack_addr;
u32 stack_size; u32 stack_size;
u32 tls_addr; u32 tls_addr;
u32 entry; ppu_func_opd_t entry;
u64 arg0; u64 arg0;
u64 arg1; 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_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(); } 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 u64 start_time{0}; // Sleep start timepoint
alignas(64) u64 syscall_args[4]{0}; // Last syscall arguments stored alignas(64) u64 syscall_args[4]{0}; // Last syscall arguments stored
const char* current_function{}; // Current function name for diagnosis, optimized for speed. const char* current_function{}; // Current function name for diagnosis, optimized for speed.

View file

@ -15,7 +15,7 @@ void lv2_int_serv::exec()
({ ({
{ ppu_cmd::reset_stack, 0 }, { ppu_cmd::reset_stack, 0 },
{ ppu_cmd::set_args, 2 }, arg1, arg2, { ppu_cmd::set_args, 2 }, arg1, arg2,
{ ppu_cmd::lle_call, 2 }, { ppu_cmd::opd_call, 0 }, std::bit_cast<u64>(thread->entry_func),
{ ppu_cmd::sleep, 0 } { ppu_cmd::sleep, 0 }
}); });

View file

@ -5,6 +5,7 @@
#include "Emu/Cell/ErrorCodes.h" #include "Emu/Cell/ErrorCodes.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/PPUCallback.h"
#include "sys_event.h" #include "sys_event.h"
#include "sys_process.h" #include "sys_process.h"
#include "sys_mmapper.h" #include "sys_mmapper.h"
@ -362,6 +363,8 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
return CELL_EPERM; return CELL_EPERM;
} }
const ppu_func_opd_t entry = param->entry.opd();
// Clean some detached thread (hack) // Clean some detached thread (hack)
g_fxo->get<ppu_thread_cleaner>()->clean(0); g_fxo->get<ppu_thread_cleaner>()->clean(0);
@ -408,7 +411,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
p.stack_addr = stack_base; p.stack_addr = stack_base;
p.stack_size = stack_size; p.stack_size = stack_size;
p.tls_addr = param->tls; p.tls_addr = param->tls;
p.entry = param->entry; p.entry = entry;
p.arg0 = arg; p.arg0 = arg;
p.arg1 = unk; p.arg1 = unk;
@ -423,7 +426,7 @@ error_code _sys_ppu_thread_create(vm::ptr<u64> thread_id, vm::ptr<ppu_thread_par
} }
*thread_id = tid; *thread_id = tid;
sys_ppu_thread.warning(u8"_sys_ppu_thread_create(): Thread “%s” created (id=0x%x)", ppu_name, tid); sys_ppu_thread.warning(u8"_sys_ppu_thread_create(): Thread “%s” created (id=0x%x, func=*0x%x, rtoc=0x%x)", ppu_name, tid, entry.addr, entry.rtoc);
return CELL_OK; return CELL_OK;
} }

View file

@ -26,7 +26,7 @@ struct sys_ppu_thread_stack_t
struct ppu_thread_param_t struct ppu_thread_param_t
{ {
be_t<u32> entry; // vm::bptr<void(u64)> vm::bptr<void(u64)> entry;
be_t<u32> tls; // vm::bptr<void> be_t<u32> tls; // vm::bptr<void>
}; };

View file

@ -5,6 +5,7 @@
#include "vm.h" #include "vm.h"
class ppu_thread; class ppu_thread;
struct ppu_func_opd_t;
namespace vm namespace vm
{ {
@ -262,6 +263,7 @@ namespace vm
// Callback; defined in PPUCallback.h, passing context is mandatory // Callback; defined in PPUCallback.h, passing context is mandatory
RT operator()(ppu_thread& ppu, T... args) const; RT operator()(ppu_thread& ppu, T... args) const;
const ppu_func_opd_t& opd() const;
}; };
template<typename AT, typename RT, typename... T> template<typename AT, typename RT, typename... T>