mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-01-02 15:02:11 +00:00
sys_ppu_thread_create: read function descriptor immediately and save it
This commit is contained in:
parent
8c838698af
commit
c948c9305c
@ -137,7 +137,7 @@ error_code sys_ppu_thread_create(ppu_thread& ppu, vm::ptr<u64> 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;
|
||||
}
|
||||
|
@ -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<typename AT, typename RT, typename... T>
|
||||
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 u32 pc = data[0];
|
||||
const u32 rtoc = data[1];
|
||||
const auto data = vm::_ptr<ppu_func_opd_t>(vm::cast(m_addr, HERE));
|
||||
const u32 pc = data->addr;
|
||||
const u32 rtoc = data->rtoc;
|
||||
|
||||
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)
|
||||
|
@ -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<ppu_func_opd_t>();
|
||||
cmd_pop(1), fast_call(opd.addr, opd.rtoc);
|
||||
break;
|
||||
}
|
||||
case ppu_cmd::ptr_call:
|
||||
{
|
||||
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_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<std::string>::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<u64>(entry_func),
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save entry for further use (interrupt handler workaround)
|
||||
gpr[2] = param.entry;
|
||||
}
|
||||
|
||||
// Trigger the scheduler
|
||||
state += cpu_flag::suspend;
|
||||
|
@ -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<u32> addr;
|
||||
be_t<u32> 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.
|
||||
|
@ -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<u64>(thread->entry_func),
|
||||
{ ppu_cmd::sleep, 0 }
|
||||
});
|
||||
|
||||
|
@ -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<u64> thread_id, vm::ptr<ppu_thread_par
|
||||
return CELL_EPERM;
|
||||
}
|
||||
|
||||
const ppu_func_opd_t entry = param->entry.opd();
|
||||
|
||||
// Clean some detached thread (hack)
|
||||
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_size = stack_size;
|
||||
p.tls_addr = param->tls;
|
||||
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<u64> thread_id, vm::ptr<ppu_thread_par
|
||||
}
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@ struct sys_ppu_thread_stack_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>
|
||||
};
|
||||
|
||||
|
@ -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<typename AT, typename RT, typename... T>
|
||||
|
Loading…
Reference in New Issue
Block a user