Skip to content

Commit

Permalink
sys_ppu_thread_create: read function descriptor immedialty and save it
Browse files Browse the repository at this point in the history
  • Loading branch information
elad335 committed Apr 8, 2020
1 parent 2e18df7 commit 60399f7
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 15 deletions.
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/Modules/sys_ppu_thread_.cpp
Expand Up @@ -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;
}
Expand Down
14 changes: 11 additions & 3 deletions rpcs3/Emu/Cell/PPUCallback.h
Expand Up @@ -2,6 +2,8 @@

#include "Emu/Cell/PPUThread.h"

struct ppu_func_opd_t;

namespace ppu_cb_detail
{
enum _func_arg_type
Expand Down Expand Up @@ -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)
Expand Down
14 changes: 8 additions & 6 deletions rpcs3/Emu/Cell/PPUThread.cpp
Expand Up @@ -600,6 +600,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>();
Expand Down Expand Up @@ -746,6 +752,7 @@ ppu_thread::ppu_thread(const ppu_thread_params& param, std::string_view name, u3
, stack_addr(param.stack_addr)
, joiner(detached != 0 ? ppu_join_status::detached : ppu_join_status::joinable)
, start_time(get_guest_system_time())
, entry_func(param.entry)
, ppu_tname(stx::shared_cptr<std::string>::make(name))
{
gpr[1] = stack_addr + stack_size - 0x70;
Expand All @@ -758,14 +765,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;
Expand Down
12 changes: 11 additions & 1 deletion rpcs3/Emu/Cell/PPUThread.h
Expand Up @@ -14,8 +14,10 @@ enum class ppu_cmd : u32
set_gpr, // Set gpr[arg] (+1 cmd)
set_args, // Set general-purpose args (+arg cmd)
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
Expand All @@ -35,13 +37,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;
};
Expand Down Expand Up @@ -192,6 +201,7 @@ class ppu_thread : public cpu_thread
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.
Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_interrupt.cpp
Expand Up @@ -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 }
});

Expand Down
7 changes: 5 additions & 2 deletions rpcs3/Emu/Cell/lv2/sys_ppu_thread.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;

Expand All @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion rpcs3/Emu/Cell/lv2/sys_ppu_thread.h
Expand Up @@ -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>
};

Expand Down
2 changes: 2 additions & 0 deletions rpcs3/Emu/Memory/vm_ptr.h
Expand Up @@ -5,6 +5,7 @@
#include "vm.h"

class ppu_thread;
struct ppu_func_opd_t;

namespace vm
{
Expand Down Expand Up @@ -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>
Expand Down

0 comments on commit 60399f7

Please sign in to comment.