mirror of https://github.com/RPCS3/rpcs3.git
parent
6296453ef3
commit
fc9fdca3f6
|
@ -377,9 +377,9 @@ namespace _spurs
|
||||||
|
|
||||||
s32 _spurs::get_sdk_version()
|
s32 _spurs::get_sdk_version()
|
||||||
{
|
{
|
||||||
const s32 version = Emu.GetSDKVersion();
|
s32 version = -1;
|
||||||
|
|
||||||
return version == -1 ? 0x465000 : version;
|
return process_get_sdk_version(process_getpid(), version) || version == -1 ? 0x465000 : version;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool _spurs::is_libprof_loaded()
|
bool _spurs::is_libprof_loaded()
|
||||||
|
|
|
@ -14,44 +14,44 @@ extern fs::file g_tty;
|
||||||
|
|
||||||
vm::gvar<s32> sys_prx_version; // ???
|
vm::gvar<s32> sys_prx_version; // ???
|
||||||
|
|
||||||
#define TLS_SYS 0x30
|
static u32 s_tls_addr = 0; // TLS image address
|
||||||
|
static u32 s_tls_file = 0; // TLS image size
|
||||||
u32 g_tls_size = 0; // Size of TLS area per thread
|
static u32 s_tls_zero = 0; // TLS zeroed area size (TLS mem size - TLS image size)
|
||||||
u32 g_tls_addr = 0; // Start of TLS memory area
|
static u32 s_tls_size = 0; // Size of TLS area per thread
|
||||||
u32 g_tls_max = 0; // Max number of threads
|
static u32 s_tls_area = 0; // Start of TLS memory area
|
||||||
|
static u32 s_tls_max = 0; // Max number of threads
|
||||||
std::unique_ptr<atomic_t<bool>[]> g_tls_map; // I'd like to make it std::vector but it won't work
|
static std::unique_ptr<atomic_t<bool>[]> s_tls_map; // I'd like to make it std::vector but it won't work
|
||||||
|
|
||||||
u32 ppu_alloc_tls()
|
u32 ppu_alloc_tls()
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < g_tls_max; i++)
|
for (u32 i = 0; i < s_tls_max; i++)
|
||||||
{
|
{
|
||||||
if (g_tls_map[i].exchange(true) == false)
|
if (!s_tls_map[i] && s_tls_map[i].exchange(true) == false)
|
||||||
{
|
{
|
||||||
const u32 addr = g_tls_addr + i * g_tls_size; // Calculate TLS address
|
const u32 addr = s_tls_area + i * s_tls_size; // Calculate TLS address
|
||||||
std::memset(vm::base(addr), 0, TLS_SYS); // Clear system area (TODO)
|
std::memset(vm::base(addr), 0, 0x30); // Clear system area (TODO)
|
||||||
std::memcpy(vm::base(addr + TLS_SYS), vm::base(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // Copy TLS image
|
std::memcpy(vm::base(addr + 0x30), vm::base(s_tls_addr), s_tls_file); // Copy TLS image
|
||||||
std::memset(vm::base(addr + TLS_SYS + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // Clear the rest
|
std::memset(vm::base(addr + 0x30 + s_tls_file), 0, s_tls_zero); // Clear the rest
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sysPrxForUser.error("ppu_alloc_tls(): out of TLS memory (max=%zu)", g_tls_max);
|
sysPrxForUser.error("ppu_alloc_tls(): out of TLS memory (max=%zu)", s_tls_max);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ppu_free_tls(u32 addr)
|
void ppu_free_tls(u32 addr)
|
||||||
{
|
{
|
||||||
// Calculate TLS position
|
// Calculate TLS position
|
||||||
const u32 i = (addr - g_tls_addr) / g_tls_size;
|
const u32 i = (addr - s_tls_area) / s_tls_size;
|
||||||
|
|
||||||
if (addr < g_tls_addr || i >= g_tls_max || (addr - g_tls_addr) % g_tls_size)
|
if (addr < s_tls_area || i >= s_tls_max || (addr - s_tls_area) % s_tls_size)
|
||||||
{
|
{
|
||||||
sysPrxForUser.error("ppu_free_tls(0x%x): invalid address", addr);
|
sysPrxForUser.error("ppu_free_tls(0x%x): invalid address", addr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_tls_map[i].exchange(false) == false)
|
if (s_tls_map[i].exchange(false) == false)
|
||||||
{
|
{
|
||||||
sysPrxForUser.error("ppu_free_tls(0x%x): deallocation failed", addr);
|
sysPrxForUser.error("ppu_free_tls(0x%x): deallocation failed", addr);
|
||||||
return;
|
return;
|
||||||
|
@ -66,15 +66,18 @@ void sys_initialize_tls(PPUThread& ppu, u64 main_thread_id, u32 tls_seg_addr, u3
|
||||||
if (ppu.GPR[13] != 0) return;
|
if (ppu.GPR[13] != 0) return;
|
||||||
|
|
||||||
// Initialize TLS memory
|
// Initialize TLS memory
|
||||||
g_tls_size = Emu.GetTLSMemsz() + TLS_SYS;
|
s_tls_addr = tls_seg_addr;
|
||||||
g_tls_addr = vm::alloc(0x20000, vm::main) + 0x30;
|
s_tls_file = tls_seg_size;
|
||||||
g_tls_max = (0xffd0 / g_tls_size) + (0x10000 / g_tls_size);
|
s_tls_zero = tls_mem_size - tls_seg_size;
|
||||||
g_tls_map = std::make_unique<atomic_t<bool>[]>(g_tls_max);
|
s_tls_size = tls_mem_size + 0x30; // 0x30 is system area size
|
||||||
|
s_tls_area = vm::alloc(0x20000, vm::main) + 0x30;
|
||||||
|
s_tls_max = (0xffd0 / s_tls_size) + (0x10000 / s_tls_size);
|
||||||
|
s_tls_map = std::make_unique<atomic_t<bool>[]>(s_tls_max);
|
||||||
|
|
||||||
// Allocate TLS for main thread
|
// Allocate TLS for main thread
|
||||||
ppu.GPR[13] = ppu_alloc_tls() + 0x7000 + TLS_SYS;
|
ppu.GPR[13] = ppu_alloc_tls() + 0x7000 + 0x30;
|
||||||
|
|
||||||
sysPrxForUser.notice("TLS initialized (addr=0x%x, size=0x%x, max=0x%x)", g_tls_addr - 0x30, g_tls_size, g_tls_max);
|
sysPrxForUser.notice("TLS initialized (addr=0x%x, size=0x%x, max=0x%x)", s_tls_area - 0x30, s_tls_size, s_tls_max);
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
g_spu_printf_agcb = vm::null;
|
g_spu_printf_agcb = vm::null;
|
||||||
|
|
|
@ -118,6 +118,8 @@ extern void sys_initialize_tls(PPUThread&, u64, u32, u32, u32);
|
||||||
|
|
||||||
extern void ppu_initialize(const std::string& name, const std::vector<ppu_function>& set, u32 entry);
|
extern void ppu_initialize(const std::string& name, const std::vector<ppu_function>& set, u32 entry);
|
||||||
|
|
||||||
|
extern u32 g_ps3_sdk_version;
|
||||||
|
|
||||||
// Function lookup table. Not supposed to grow after emulation start.
|
// Function lookup table. Not supposed to grow after emulation start.
|
||||||
std::vector<ppu_function_t> g_ppu_function_cache;
|
std::vector<ppu_function_t> g_ppu_function_cache;
|
||||||
|
|
||||||
|
@ -946,6 +948,15 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||||
// Functions
|
// Functions
|
||||||
std::vector<ppu_function> exec_set;
|
std::vector<ppu_function> exec_set;
|
||||||
|
|
||||||
|
// TLS information
|
||||||
|
u32 tls_vaddr{0}, tls_fsize{0}, tls_vsize{0};
|
||||||
|
|
||||||
|
// Process information
|
||||||
|
u32 sdk_version = 0x360001;
|
||||||
|
s32 primary_prio = 0x50;
|
||||||
|
u32 primary_stacksize = 0x100000;
|
||||||
|
u32 malloc_pagesize = 0x100000;
|
||||||
|
|
||||||
// Allocate memory at fixed positions
|
// Allocate memory at fixed positions
|
||||||
for (const auto& prog : elf.progs)
|
for (const auto& prog : elf.progs)
|
||||||
{
|
{
|
||||||
|
@ -992,13 +1003,9 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||||
|
|
||||||
case 0x00000007: //TLS
|
case 0x00000007: //TLS
|
||||||
{
|
{
|
||||||
const u32 addr = vm::cast(prog.p_vaddr, HERE);
|
tls_vaddr = vm::cast(prog.p_vaddr, HERE);
|
||||||
const u32 filesz = fmt::narrow<u32>("Invalid p_filesz (0x%llx)" HERE, prog.p_filesz);
|
tls_fsize = fmt::narrow<u32>("Invalid p_filesz (0x%llx)" HERE, prog.p_filesz);
|
||||||
const u32 memsz = fmt::narrow<u32>("Invalid p_memsz (0x%llx)" HERE, prog.p_memsz);
|
tls_vsize = fmt::narrow<u32>("Invalid p_memsz (0x%llx)" HERE, prog.p_memsz);
|
||||||
Emu.SetTLSData(addr, filesz, memsz);
|
|
||||||
LOG_NOTICE(LOADER, "*** TLS segment addr: 0x%08x", Emu.GetTLSAddr());
|
|
||||||
LOG_NOTICE(LOADER, "*** TLS segment size: 0x%08x", Emu.GetTLSFilesz());
|
|
||||||
LOG_NOTICE(LOADER, "*** TLS memory size: 0x%08x", Emu.GetTLSMemsz());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1025,20 +1032,24 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||||
{
|
{
|
||||||
LOG_WARNING(LOADER, "Bad process_param size! [0x%x : 0x%x]", info.size, SIZE_32(process_param_t));
|
LOG_WARNING(LOADER, "Bad process_param size! [0x%x : 0x%x]", info.size, SIZE_32(process_param_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info.magic != 0x13bcc5f6)
|
if (info.magic != 0x13bcc5f6)
|
||||||
{
|
{
|
||||||
LOG_ERROR(LOADER, "Bad process_param magic! [0x%x]", info.magic);
|
LOG_ERROR(LOADER, "Bad process_param magic! [0x%x]", info.magic);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
sdk_version = info.sdk_version;
|
||||||
|
primary_prio = info.primary_prio;
|
||||||
|
primary_stacksize = info.primary_stacksize;
|
||||||
|
malloc_pagesize = info.malloc_pagesize;
|
||||||
|
|
||||||
LOG_NOTICE(LOADER, "*** sdk version: 0x%x", info.sdk_version);
|
LOG_NOTICE(LOADER, "*** sdk version: 0x%x", info.sdk_version);
|
||||||
LOG_NOTICE(LOADER, "*** primary prio: %d", info.primary_prio);
|
LOG_NOTICE(LOADER, "*** primary prio: %d", info.primary_prio);
|
||||||
LOG_NOTICE(LOADER, "*** primary stacksize: 0x%x", info.primary_stacksize);
|
LOG_NOTICE(LOADER, "*** primary stacksize: 0x%x", info.primary_stacksize);
|
||||||
LOG_NOTICE(LOADER, "*** malloc pagesize: 0x%x", info.malloc_pagesize);
|
LOG_NOTICE(LOADER, "*** malloc pagesize: 0x%x", info.malloc_pagesize);
|
||||||
LOG_NOTICE(LOADER, "*** ppc seg: 0x%x", info.ppc_seg);
|
LOG_NOTICE(LOADER, "*** ppc seg: 0x%x", info.ppc_seg);
|
||||||
//LOG_NOTICE(LOADER, "*** crash dump param addr: 0x%x", info.crash_dump_param_addr);
|
//LOG_NOTICE(LOADER, "*** crash dump param addr: 0x%x", info.crash_dump_param_addr);
|
||||||
|
|
||||||
Emu.SetParams(info.sdk_version, info.malloc_pagesize, std::max<u32>(info.primary_stacksize, 0x4000), info.primary_prio);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -1337,16 +1348,19 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||||
// Initialize recompiler
|
// Initialize recompiler
|
||||||
ppu_initialize("", exec_set, static_cast<u32>(elf.header.e_entry));
|
ppu_initialize("", exec_set, static_cast<u32>(elf.header.e_entry));
|
||||||
|
|
||||||
|
// Set SDK version
|
||||||
|
g_ps3_sdk_version = sdk_version;
|
||||||
|
|
||||||
auto ppu = idm::make_ptr<PPUThread>("main_thread");
|
auto ppu = idm::make_ptr<PPUThread>("main_thread");
|
||||||
|
|
||||||
ppu->pc = entry.addr() & -0x1000;
|
ppu->pc = entry.addr() & -0x1000;
|
||||||
ppu->stack_size = Emu.GetPrimaryStackSize();
|
ppu->stack_size = std::max<u32>(primary_stacksize, 0x4000);
|
||||||
ppu->prio = Emu.GetPrimaryPrio();
|
ppu->prio = primary_prio;
|
||||||
ppu->cpu_init();
|
ppu->cpu_init();
|
||||||
|
|
||||||
ppu->GPR[2] = 0xdeadbeef; // rtoc
|
ppu->GPR[2] = 0xdeadbeef; // rtoc
|
||||||
ppu->GPR[11] = 0xabadcafe; // OPD ???
|
ppu->GPR[11] = 0xabadcafe; // OPD ???
|
||||||
ppu->GPR[12] = Emu.GetMallocPageSize();
|
ppu->GPR[12] = malloc_pagesize;
|
||||||
|
|
||||||
std::initializer_list<std::string> args = { Emu.GetPath()/*, "-emu"s*/ };
|
std::initializer_list<std::string> args = { Emu.GetPath()/*, "-emu"s*/ };
|
||||||
|
|
||||||
|
@ -1371,9 +1385,9 @@ void ppu_load_exec(const ppu_exec_object& elf)
|
||||||
|
|
||||||
// Arguments for sys_initialize_tls()
|
// Arguments for sys_initialize_tls()
|
||||||
ppu->GPR[7] = ppu->id;
|
ppu->GPR[7] = ppu->id;
|
||||||
ppu->GPR[8] = Emu.GetTLSAddr();
|
ppu->GPR[8] = tls_vaddr;
|
||||||
ppu->GPR[9] = Emu.GetTLSFilesz();
|
ppu->GPR[9] = tls_fsize;
|
||||||
ppu->GPR[10] = Emu.GetTLSMemsz();
|
ppu->GPR[10] = tls_vsize;
|
||||||
|
|
||||||
//ppu->state += cpu_state::interrupt;
|
//ppu->state += cpu_state::interrupt;
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
|
|
||||||
logs::channel sys_process("sys_process", logs::level::notice);
|
logs::channel sys_process("sys_process", logs::level::notice);
|
||||||
|
|
||||||
|
u32 g_ps3_sdk_version;
|
||||||
|
|
||||||
s32 process_getpid()
|
s32 process_getpid()
|
||||||
{
|
{
|
||||||
// TODO: get current process id
|
// TODO: get current process id
|
||||||
|
@ -194,7 +196,7 @@ s32 _sys_process_get_paramsfo(vm::ptr<char> buffer)
|
||||||
s32 process_get_sdk_version(u32 pid, s32& ver)
|
s32 process_get_sdk_version(u32 pid, s32& ver)
|
||||||
{
|
{
|
||||||
// get correct SDK version for selected pid
|
// get correct SDK version for selected pid
|
||||||
ver = Emu.GetSDKVersion();
|
ver = g_ps3_sdk_version;
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "ARMv7Opcodes.h"
|
#include "ARMv7Opcodes.h"
|
||||||
#include "ARMv7Function.h"
|
#include "ARMv7Function.h"
|
||||||
#include "ARMv7Module.h"
|
#include "ARMv7Module.h"
|
||||||
|
#include "Modules/sceLibKernel.h"
|
||||||
|
|
||||||
LOG_CHANNEL(sceAppMgr);
|
LOG_CHANNEL(sceAppMgr);
|
||||||
LOG_CHANNEL(sceAppUtil);
|
LOG_CHANNEL(sceAppUtil);
|
||||||
|
@ -71,8 +72,6 @@ LOG_CHANNEL(sceVideodec);
|
||||||
LOG_CHANNEL(sceVoice);
|
LOG_CHANNEL(sceVoice);
|
||||||
LOG_CHANNEL(sceVoiceQoS);
|
LOG_CHANNEL(sceVoiceQoS);
|
||||||
|
|
||||||
extern void armv7_init_tls();
|
|
||||||
|
|
||||||
extern std::string arm_get_function_name(const std::string& module, u32 fnid);
|
extern std::string arm_get_function_name(const std::string& module, u32 fnid);
|
||||||
extern std::string arm_get_variable_name(const std::string& module, u32 vnid);
|
extern std::string arm_get_variable_name(const std::string& module, u32 vnid);
|
||||||
|
|
||||||
|
@ -429,8 +428,6 @@ void arm_load_exec(const arm_exec_object& elf)
|
||||||
LOG_NOTICE(LOADER, "** tls_fsize=0x%x", tls_fsize);
|
LOG_NOTICE(LOADER, "** tls_fsize=0x%x", tls_fsize);
|
||||||
LOG_NOTICE(LOADER, "** tls_vsize=0x%x", tls_vsize);
|
LOG_NOTICE(LOADER, "** tls_vsize=0x%x", tls_vsize);
|
||||||
|
|
||||||
Emu.SetTLSData(tls_faddr + start_addr, tls_fsize, tls_vsize);
|
|
||||||
|
|
||||||
// Process exports
|
// Process exports
|
||||||
while (libent.addr() < start_addr + module_info->libent_end)
|
while (libent.addr() < start_addr + module_info->libent_end)
|
||||||
{
|
{
|
||||||
|
@ -635,8 +632,6 @@ void arm_load_exec(const arm_exec_object& elf)
|
||||||
stop_code[1] = 1; // Predefined function index (HLE return)
|
stop_code[1] = 1; // Predefined function index (HLE return)
|
||||||
Emu.SetCPUThreadStop(stop_code.addr());
|
Emu.SetCPUThreadStop(stop_code.addr());
|
||||||
|
|
||||||
armv7_init_tls();
|
|
||||||
|
|
||||||
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
|
const std::string& thread_name = proc_param->sceUserMainThreadName ? proc_param->sceUserMainThreadName.get_ptr() : "main_thread";
|
||||||
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? proc_param->sceUserMainThreadStackSize->value() : 256 * 1024;
|
const u32 stack_size = proc_param->sceUserMainThreadStackSize ? proc_param->sceUserMainThreadStackSize->value() : 256 * 1024;
|
||||||
const u32 priority = proc_param->sceUserMainThreadPriority ? proc_param->sceUserMainThreadPriority->value() : 160;
|
const u32 priority = proc_param->sceUserMainThreadPriority ? proc_param->sceUserMainThreadPriority->value() : 160;
|
||||||
|
@ -647,6 +642,7 @@ void arm_load_exec(const arm_exec_object& elf)
|
||||||
thread->stack_size = stack_size;
|
thread->stack_size = stack_size;
|
||||||
thread->prio = priority;
|
thread->prio = priority;
|
||||||
thread->cpu_init();
|
thread->cpu_init();
|
||||||
|
thread->TLS = fxm::make_always<arm_tls_manager>(tls_faddr + start_addr, tls_fsize, tls_vsize)->alloc();
|
||||||
|
|
||||||
// Initialize args
|
// Initialize args
|
||||||
std::vector<char> argv_data;
|
std::vector<char> argv_data;
|
||||||
|
|
|
@ -10,67 +10,6 @@ namespace vm { using namespace psv; }
|
||||||
|
|
||||||
const arm_decoder<arm_interpreter> s_arm_interpreter;
|
const arm_decoder<arm_interpreter> s_arm_interpreter;
|
||||||
|
|
||||||
#define TLS_MAX 128
|
|
||||||
|
|
||||||
u32 g_armv7_tls_start;
|
|
||||||
|
|
||||||
std::array<atomic_t<u32>, TLS_MAX> g_armv7_tls_owners;
|
|
||||||
|
|
||||||
void armv7_init_tls()
|
|
||||||
{
|
|
||||||
g_armv7_tls_start = Emu.GetTLSMemsz() ? vm::alloc(Emu.GetTLSMemsz() * TLS_MAX, vm::main) : 0;
|
|
||||||
|
|
||||||
for (auto& v : g_armv7_tls_owners)
|
|
||||||
{
|
|
||||||
v = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 armv7_get_tls(u32 thread)
|
|
||||||
{
|
|
||||||
if (!Emu.GetTLSMemsz() || !thread)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < TLS_MAX; i++)
|
|
||||||
{
|
|
||||||
if (g_armv7_tls_owners[i] == thread)
|
|
||||||
{
|
|
||||||
return g_armv7_tls_start + i * Emu.GetTLSMemsz(); // if already initialized, return TLS address
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (u32 i = 0; i < TLS_MAX; i++)
|
|
||||||
{
|
|
||||||
if (g_armv7_tls_owners[i].compare_and_swap_test(0, thread))
|
|
||||||
{
|
|
||||||
const u32 addr = g_armv7_tls_start + i * Emu.GetTLSMemsz(); // get TLS address
|
|
||||||
std::memcpy(vm::base(addr), vm::base(Emu.GetTLSAddr()), Emu.GetTLSFilesz()); // initialize from TLS image
|
|
||||||
std::memset(vm::base(addr + Emu.GetTLSFilesz()), 0, Emu.GetTLSMemsz() - Emu.GetTLSFilesz()); // fill the rest with zeros
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw EXCEPTION("Out of TLS memory");
|
|
||||||
}
|
|
||||||
|
|
||||||
void armv7_free_tls(u32 thread)
|
|
||||||
{
|
|
||||||
if (!Emu.GetTLSMemsz())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto& v : g_armv7_tls_owners)
|
|
||||||
{
|
|
||||||
if (v.compare_and_swap_test(thread, 0))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ARMv7Thread::get_name() const
|
std::string ARMv7Thread::get_name() const
|
||||||
{
|
{
|
||||||
return fmt::format("ARMv7[0x%x] Thread (%s)", id, m_name);
|
return fmt::format("ARMv7[0x%x] Thread (%s)", id, m_name);
|
||||||
|
@ -119,7 +58,7 @@ void ARMv7Thread::cpu_init()
|
||||||
PC = PC & ~1; // and fix PC
|
PC = PC & ~1; // and fix PC
|
||||||
ITSTATE.IT = 0;
|
ITSTATE.IT = 0;
|
||||||
SP = stack_addr + stack_size;
|
SP = stack_addr + stack_size;
|
||||||
TLS = armv7_get_tls(id);
|
TLS = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
extern thread_local std::string(*g_tls_log_prefix)();
|
extern thread_local std::string(*g_tls_log_prefix)();
|
||||||
|
@ -174,8 +113,6 @@ void ARMv7Thread::cpu_task_main()
|
||||||
|
|
||||||
ARMv7Thread::~ARMv7Thread()
|
ARMv7Thread::~ARMv7Thread()
|
||||||
{
|
{
|
||||||
armv7_free_tls(id);
|
|
||||||
|
|
||||||
if (stack_addr)
|
if (stack_addr)
|
||||||
{
|
{
|
||||||
vm::dealloc_verbose_nothrow(stack_addr, vm::main);
|
vm::dealloc_verbose_nothrow(stack_addr, vm::main);
|
||||||
|
|
|
@ -15,6 +15,59 @@ logs::channel sceLibKernel("sceLibKernel", logs::level::notice);
|
||||||
|
|
||||||
extern u64 get_system_time();
|
extern u64 get_system_time();
|
||||||
|
|
||||||
|
arm_tls_manager::arm_tls_manager(u32 vaddr, u32 fsize, u32 vsize)
|
||||||
|
: vaddr(vaddr)
|
||||||
|
, fsize(fsize)
|
||||||
|
, vsize(vsize)
|
||||||
|
, start(vsize ? vm::alloc(vsize * ::size32(m_map), vm::main) : 0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 arm_tls_manager::alloc()
|
||||||
|
{
|
||||||
|
if (!vsize)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_map.size(); i++)
|
||||||
|
{
|
||||||
|
if (!m_map[i] && m_map[i].exchange(true) == false)
|
||||||
|
{
|
||||||
|
const u32 addr = start + i * vsize; // Get TLS address
|
||||||
|
std::memcpy(vm::base(addr), vm::base(vaddr), fsize); // Initialize from TLS image
|
||||||
|
std::memset(vm::base(addr + fsize), 0, vsize - fsize); // Fill the rest with zeros
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sceLibKernel.error("arm_tls_manager::alloc(): out of TLS memory (max=%zu)", m_map.size());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void arm_tls_manager::free(u32 addr)
|
||||||
|
{
|
||||||
|
if (!addr)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate TLS index
|
||||||
|
const u32 i = (addr - start) / vsize;
|
||||||
|
|
||||||
|
if (addr < start || i >= m_map.size() || (addr - start) % vsize)
|
||||||
|
{
|
||||||
|
sceLibKernel.error("arm_tls_manager::free(0x%x): invalid address", addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_map[i].exchange(false) == false)
|
||||||
|
{
|
||||||
|
sceLibKernel.error("arm_tls_manager::free(0x%x): deallocation failed", addr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
s32 sceKernelAllocMemBlock(vm::cptr<char> name, s32 type, u32 vsize, vm::ptr<SceKernelAllocMemBlockOpt> pOpt)
|
s32 sceKernelAllocMemBlock(vm::cptr<char> name, s32 type, u32 vsize, vm::ptr<SceKernelAllocMemBlockOpt> pOpt)
|
||||||
{
|
{
|
||||||
throw EXCEPTION("");
|
throw EXCEPTION("");
|
||||||
|
@ -46,6 +99,7 @@ arm_error_code sceKernelCreateThread(vm::cptr<char> pName, vm::ptr<SceKernelThre
|
||||||
thread->prio = initPriority;
|
thread->prio = initPriority;
|
||||||
thread->stack_size = stackSize;
|
thread->stack_size = stackSize;
|
||||||
thread->cpu_init();
|
thread->cpu_init();
|
||||||
|
thread->TLS = fxm::get<arm_tls_manager>()->alloc();
|
||||||
|
|
||||||
return NOT_AN_ERROR(thread->id);
|
return NOT_AN_ERROR(thread->id);
|
||||||
}
|
}
|
||||||
|
@ -109,6 +163,7 @@ arm_error_code sceKernelDeleteThread(s32 threadId)
|
||||||
// return SCE_KERNEL_ERROR_NOT_DORMANT;
|
// return SCE_KERNEL_ERROR_NOT_DORMANT;
|
||||||
//}
|
//}
|
||||||
|
|
||||||
|
fxm::get<arm_tls_manager>()->free(thread->TLS);
|
||||||
idm::remove<ARMv7Thread>(threadId);
|
idm::remove<ARMv7Thread>(threadId);
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
}
|
}
|
||||||
|
@ -120,6 +175,7 @@ arm_error_code sceKernelExitDeleteThread(ARMv7Thread& cpu, s32 exitStatus)
|
||||||
//cpu.state += cpu_state::stop;
|
//cpu.state += cpu_state::stop;
|
||||||
|
|
||||||
// Delete current thread; exit status is stored in r0
|
// Delete current thread; exit status is stored in r0
|
||||||
|
fxm::get<arm_tls_manager>()->free(cpu.TLS);
|
||||||
idm::remove<ARMv7Thread>(cpu.id);
|
idm::remove<ARMv7Thread>(cpu.id);
|
||||||
|
|
||||||
return SCE_OK;
|
return SCE_OK;
|
||||||
|
|
|
@ -3,6 +3,27 @@
|
||||||
#include "Emu/PSP2/ErrorCodes.h"
|
#include "Emu/PSP2/ErrorCodes.h"
|
||||||
#include "Emu/PSP2/Modules/Common.h"
|
#include "Emu/PSP2/Modules/Common.h"
|
||||||
|
|
||||||
|
// Kernel internal TLS manager (TODO)
|
||||||
|
class arm_tls_manager
|
||||||
|
{
|
||||||
|
std::array<atomic_t<bool>, 128> m_map{};
|
||||||
|
|
||||||
|
public:
|
||||||
|
const u32 vaddr;
|
||||||
|
const u32 fsize;
|
||||||
|
const u32 vsize;
|
||||||
|
const u32 start;
|
||||||
|
|
||||||
|
// Initialize from ELF process parameters
|
||||||
|
arm_tls_manager(u32 vaddr, u32 fsize, u32 vsize);
|
||||||
|
|
||||||
|
// Allocate and initialize TLS
|
||||||
|
u32 alloc();
|
||||||
|
|
||||||
|
// Deallocate by address
|
||||||
|
void free(u32 addr);
|
||||||
|
};
|
||||||
|
|
||||||
// Error Codes
|
// Error Codes
|
||||||
enum SceLibKernelError : s32
|
enum SceLibKernelError : s32
|
||||||
{
|
{
|
||||||
|
|
|
@ -189,7 +189,7 @@ void Emulator::Load()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetInfo();
|
SetCPUThreadStop(0);
|
||||||
|
|
||||||
LOG_NOTICE(LOADER, "Path: %s", m_path);
|
LOG_NOTICE(LOADER, "Path: %s", m_path);
|
||||||
|
|
||||||
|
|
|
@ -34,25 +34,6 @@ class EmulationStopped {};
|
||||||
|
|
||||||
class CallbackManager;
|
class CallbackManager;
|
||||||
|
|
||||||
struct EmuInfo
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
friend class Emulator;
|
|
||||||
|
|
||||||
u32 m_tls_addr = 0;
|
|
||||||
u32 m_tls_filesz = 0;
|
|
||||||
u32 m_tls_memsz = 0;
|
|
||||||
u32 m_sdk_version = 0x360001;
|
|
||||||
u32 m_malloc_pagesize = 0x100000;
|
|
||||||
u32 m_primary_stacksize = 0x100000;
|
|
||||||
s32 m_primary_prio = 0x50;
|
|
||||||
|
|
||||||
public:
|
|
||||||
EmuInfo()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class Emulator final
|
class Emulator final
|
||||||
{
|
{
|
||||||
atomic_t<u32> m_status;
|
atomic_t<u32> m_status;
|
||||||
|
@ -66,8 +47,6 @@ class Emulator final
|
||||||
|
|
||||||
std::unique_ptr<CallbackManager> m_callback_manager;
|
std::unique_ptr<CallbackManager> m_callback_manager;
|
||||||
|
|
||||||
EmuInfo m_info;
|
|
||||||
|
|
||||||
std::string m_path;
|
std::string m_path;
|
||||||
std::string m_elf_path;
|
std::string m_elf_path;
|
||||||
std::string m_title_id;
|
std::string m_title_id;
|
||||||
|
@ -133,41 +112,11 @@ public:
|
||||||
return *m_callback_manager;
|
return *m_callback_manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ResetInfo()
|
|
||||||
{
|
|
||||||
m_info = {};
|
|
||||||
m_cpu_thr_stop = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetTLSData(u32 addr, u32 filesz, u32 memsz)
|
|
||||||
{
|
|
||||||
m_info.m_tls_addr = addr;
|
|
||||||
m_info.m_tls_filesz = filesz;
|
|
||||||
m_info.m_tls_memsz = memsz;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetParams(u32 sdk_ver, u32 malloc_pagesz, u32 stacksz, s32 prio)
|
|
||||||
{
|
|
||||||
m_info.m_sdk_version = sdk_ver;
|
|
||||||
m_info.m_malloc_pagesize = malloc_pagesz;
|
|
||||||
m_info.m_primary_stacksize = stacksz;
|
|
||||||
m_info.m_primary_prio = prio;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetCPUThreadStop(u32 addr)
|
void SetCPUThreadStop(u32 addr)
|
||||||
{
|
{
|
||||||
m_cpu_thr_stop = addr;
|
m_cpu_thr_stop = addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetTLSAddr() const { return m_info.m_tls_addr; }
|
|
||||||
u32 GetTLSFilesz() const { return m_info.m_tls_filesz; }
|
|
||||||
u32 GetTLSMemsz() const { return m_info.m_tls_memsz; }
|
|
||||||
|
|
||||||
u32 GetMallocPageSize() { return m_info.m_malloc_pagesize; }
|
|
||||||
u32 GetSDKVersion() { return m_info.m_sdk_version; }
|
|
||||||
u32 GetPrimaryStackSize() { return m_info.m_primary_stacksize; }
|
|
||||||
s32 GetPrimaryPrio() { return m_info.m_primary_prio; }
|
|
||||||
|
|
||||||
u32 GetCPUThreadStop() const { return m_cpu_thr_stop; }
|
u32 GetCPUThreadStop() const { return m_cpu_thr_stop; }
|
||||||
|
|
||||||
bool BootGame(const std::string& path, bool direct = false);
|
bool BootGame(const std::string& path, bool direct = false);
|
||||||
|
|
Loading…
Reference in New Issue