mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-07 07:21:25 +12:00
Fixed TLS for PPU threads
This commit is contained in:
parent
2be045593a
commit
4ea1b8cffc
4 changed files with 72 additions and 3 deletions
|
@ -18,6 +18,8 @@ namespace sce_libc_func
|
||||||
{
|
{
|
||||||
sceLibc.Error("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso);
|
sceLibc.Error("__cxa_atexit(func=0x%x, arg=0x%x, dso=0x%x)", func, arg, dso);
|
||||||
|
|
||||||
|
LV2_LOCK(0);
|
||||||
|
|
||||||
g_atexit.insert(g_atexit.begin(), [func, arg, dso](ARMv7Context& context)
|
g_atexit.insert(g_atexit.begin(), [func, arg, dso](ARMv7Context& context)
|
||||||
{
|
{
|
||||||
func(context, arg);
|
func(context, arg);
|
||||||
|
@ -28,6 +30,8 @@ namespace sce_libc_func
|
||||||
{
|
{
|
||||||
sceLibc.Error("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso);
|
sceLibc.Error("__aeabi_atexit(arg=0x%x, func=0x%x, dso=0x%x)", arg, func, dso);
|
||||||
|
|
||||||
|
LV2_LOCK(0);
|
||||||
|
|
||||||
g_atexit.insert(g_atexit.begin(), [func, arg, dso](ARMv7Context& context)
|
g_atexit.insert(g_atexit.begin(), [func, arg, dso](ARMv7Context& context)
|
||||||
{
|
{
|
||||||
func(context, arg);
|
func(context, arg);
|
||||||
|
@ -38,6 +42,8 @@ namespace sce_libc_func
|
||||||
{
|
{
|
||||||
sceLibc.Error("exit()");
|
sceLibc.Error("exit()");
|
||||||
|
|
||||||
|
LV2_LOCK(0);
|
||||||
|
|
||||||
for (auto func : g_atexit)
|
for (auto func : g_atexit)
|
||||||
{
|
{
|
||||||
func(context);
|
func(context);
|
||||||
|
|
|
@ -15,6 +15,9 @@
|
||||||
|
|
||||||
u64 rotate_mask[64][64];
|
u64 rotate_mask[64][64];
|
||||||
|
|
||||||
|
extern u32 ppu_get_tls(u32 thread);
|
||||||
|
extern void ppu_free_tls(u32 thread);
|
||||||
|
|
||||||
PPUThread& GetCurrentPPUThread()
|
PPUThread& GetCurrentPPUThread()
|
||||||
{
|
{
|
||||||
PPCThread* thread = GetCurrentPPCThread();
|
PPCThread* thread = GetCurrentPPCThread();
|
||||||
|
@ -32,6 +35,7 @@ PPUThread::PPUThread() : PPCThread(CPU_THREAD_PPU)
|
||||||
|
|
||||||
PPUThread::~PPUThread()
|
PPUThread::~PPUThread()
|
||||||
{
|
{
|
||||||
|
ppu_free_tls(GetId());
|
||||||
}
|
}
|
||||||
|
|
||||||
void PPUThread::DoReset()
|
void PPUThread::DoReset()
|
||||||
|
@ -92,7 +96,7 @@ void PPUThread::InitRegs()
|
||||||
GPR[2] = rtoc;
|
GPR[2] = rtoc;
|
||||||
//GPR[11] = entry;
|
//GPR[11] = entry;
|
||||||
//GPR[12] = Emu.GetMallocPageSize();
|
//GPR[12] = Emu.GetMallocPageSize();
|
||||||
GPR[13] = Memory.PRXMem.GetStartAddr() + 0x7060;
|
GPR[13] = ppu_get_tls(GetId()) + 0x7000; // 0x7000 is usually subtracted from r13 to access first TLS element (details are not clear)
|
||||||
|
|
||||||
LR = Emu.GetCPUThreadExit();
|
LR = Emu.GetCPUThreadExit();
|
||||||
CTR = PC;
|
CTR = PC;
|
||||||
|
|
|
@ -23,11 +23,62 @@
|
||||||
|
|
||||||
Module *sysPrxForUser = nullptr;
|
Module *sysPrxForUser = nullptr;
|
||||||
|
|
||||||
|
u32 g_tls_size; // size of every thread's storage
|
||||||
|
u32 g_tls_start; // start of TLS memory area
|
||||||
|
u32 g_tls_image_addr; // address of TLS initialization area
|
||||||
|
u32 g_tls_image_size; // size of TLS initialization area
|
||||||
|
|
||||||
|
const u32 TLS_MAX = 256;
|
||||||
|
std::array<std::atomic<u32>, TLS_MAX> g_tls_owners;
|
||||||
|
|
||||||
void sys_initialize_tls()
|
void sys_initialize_tls()
|
||||||
{
|
{
|
||||||
sysPrxForUser->Log("sys_initialize_tls()");
|
sysPrxForUser->Log("sys_initialize_tls()");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ppu_get_tls(u32 thread)
|
||||||
|
{
|
||||||
|
if (!g_tls_start)
|
||||||
|
{
|
||||||
|
g_tls_size = vm::cast(Emu.GetTLSMemsz(), "Emu.GetTLSMemsz"); // (not an address for vm::cast, but fine)
|
||||||
|
g_tls_start = vm::cast(Memory.Alloc(g_tls_size * TLS_MAX, 4096)); // memory for up to TLS_MAX threads
|
||||||
|
g_tls_image_addr = vm::cast(Emu.GetTLSAddr(), "Emu.GetTLSAddr");
|
||||||
|
g_tls_image_size = vm::cast(Emu.GetTLSFilesz(), "Emu.GetTLSFilesz");
|
||||||
|
|
||||||
|
sysPrxForUser->Warning("TLS initialized (g_tls_size=0x%x, g_tls_start=0x%x, g_tls_image_addr=0x%x, g_tls_image_size=0x%x)", g_tls_size, g_tls_start, g_tls_image_addr, g_tls_image_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& v : g_tls_owners)
|
||||||
|
{
|
||||||
|
u32 old = 0;
|
||||||
|
if (v.compare_exchange_strong(old, thread))
|
||||||
|
{
|
||||||
|
const u32 addr = g_tls_start + (&v - g_tls_owners.data()) * g_tls_size; // get TLS address
|
||||||
|
memset(vm::get_ptr(addr), 0, g_tls_size); // fill TLS area with zeros
|
||||||
|
memcpy(vm::get_ptr(addr), vm::get_ptr(g_tls_image_addr), g_tls_image_size); // initialize from TLS image
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
else if (old == thread)
|
||||||
|
{
|
||||||
|
return g_tls_start + (&v - g_tls_owners.data()) * g_tls_size; // if already initialized, return TLS address again
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw "Out of TLS memory";
|
||||||
|
}
|
||||||
|
|
||||||
|
void ppu_free_tls(u32 thread)
|
||||||
|
{
|
||||||
|
for (auto& v : g_tls_owners)
|
||||||
|
{
|
||||||
|
u32 old = thread;
|
||||||
|
if (v.compare_exchange_strong(old, 0))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size)
|
int _sys_heap_create_heap(const u32 heap_addr, const u32 align, const u32 size)
|
||||||
{
|
{
|
||||||
sysPrxForUser->Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size);
|
sysPrxForUser->Warning("_sys_heap_create_heap(heap_addr=0x%x, align=0x%x, size=0x%x)", heap_addr, align, size);
|
||||||
|
@ -365,6 +416,15 @@ void sysPrxForUser_init(Module *pxThis)
|
||||||
{
|
{
|
||||||
sysPrxForUser = pxThis;
|
sysPrxForUser = pxThis;
|
||||||
|
|
||||||
|
g_tls_size = 0;
|
||||||
|
g_tls_start = 0;
|
||||||
|
g_tls_image_addr = 0;
|
||||||
|
g_tls_image_size = 0;
|
||||||
|
for (auto& v : g_tls_owners)
|
||||||
|
{
|
||||||
|
v.store(0, std::memory_order_relaxed);
|
||||||
|
}
|
||||||
|
|
||||||
// Setup random number generator
|
// Setup random number generator
|
||||||
srand(time(NULL));
|
srand(time(NULL));
|
||||||
|
|
||||||
|
|
|
@ -356,7 +356,7 @@ namespace loader
|
||||||
ppu_thr_stop_data[1] = BLR();
|
ppu_thr_stop_data[1] = BLR();
|
||||||
Emu.SetCPUThreadStop(ppu_thr_stop_data.addr());
|
Emu.SetCPUThreadStop(ppu_thr_stop_data.addr());
|
||||||
|
|
||||||
vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE);
|
//vm::write64(Memory.PRXMem.AllocAlign(0x10000), 0xDEADBEEFABADCAFE);
|
||||||
/*
|
/*
|
||||||
//TODO
|
//TODO
|
||||||
static const int branch_size = 6 * 4;
|
static const int branch_size = 6 * 4;
|
||||||
|
@ -423,7 +423,6 @@ namespace loader
|
||||||
|
|
||||||
case 0x00000007: //TLS
|
case 0x00000007: //TLS
|
||||||
Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value());
|
Emu.SetTLSData(phdr.p_vaddr.addr(), phdr.p_filesz.value(), phdr.p_memsz.value());
|
||||||
LOG_ERROR(LOADER, "TLS: addr=0x%x, filesz=0x%x, memsz=0x%x", Emu.GetTLSAddr(), Emu.GetTLSFilesz(), Emu.GetTLSMemsz());
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x60000001: //LOOS+1
|
case 0x60000001: //LOOS+1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue