Merge pull request #2353 from RadWolfie/fix-tls-data-emu

Fix tls data initialization from cxbxr's emulation threads end
This commit is contained in:
ergo720 2022-05-08 01:34:07 +02:00 committed by GitHub
commit 88a37ac496
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 61 additions and 5 deletions

View File

@ -25,8 +25,6 @@
// *
// ******************************************************************
#include <core\kernel\exports\xboxkrnl.h>
#ifdef _WIN32
#include <windows.h>
#endif
@ -36,6 +34,7 @@
#include "Timer.h"
#include "common\util\CxbxUtil.h"
#include "core\kernel\support\EmuFS.h"
#include "core/kernel/exports/EmuKrnlPs.hpp"
#ifdef __linux__
#include <time.h>
#endif
@ -218,7 +217,7 @@ void Timer_Start(TimerObject* Timer, uint64_t Expire_MS)
Timer->ExpireTime_MS.store(Expire_MS);
if (Timer->IsXboxTimer) {
xbox::HANDLE hThread;
xbox::PsCreateSystemThread(&hThread, xbox::zeroptr, ClockThread, Timer, FALSE);
CxbxrCreateThread(&hThread, xbox::zeroptr, ClockThread, Timer, FALSE);
}
else {
std::thread(ClockThread, Timer).detach();

View File

@ -154,7 +154,7 @@ static unsigned int WINAPI PCSTProxy
return 0; // will never be reached
}
// Placeholder system function, instead of XapiThreadStartup
// Placeholder system function
xbox::void_xt NTAPI PspSystemThreadStartup
(
IN xbox::PKSTART_ROUTINE StartRoutine,
@ -231,6 +231,35 @@ xbox::void_xt NTAPI PspReaperRoutine(
}
}
xbox::ntstatus_xt NTAPI CxbxrCreateThread
(
OUT xbox::PHANDLE ThreadHandle,
OUT xbox::PHANDLE ThreadId OPTIONAL,
IN xbox::PKSTART_ROUTINE StartRoutine,
IN xbox::PVOID StartContext,
IN xbox::boolean_xt DebuggerThread
)
{
Xbe::TLS* XbeTls = (Xbe::TLS*)CxbxKrnl_Xbe->m_Header.dwTLSAddr;
xbox::ulong_xt TlsDataSize = (XbeTls->dwDataEndAddr - XbeTls->dwDataStartAddr);
TlsDataSize += XbeTls->dwSizeofZeroFill + 15;
TlsDataSize = (TlsDataSize & ~15) + 4;
// Verify EmuGenerateFS's TlsData's setup is carry over to XapiThreadStartup function.
// Instead of using PspSystemThreadStartup which is entirely different function.
return xbox::PsCreateSystemThreadEx(
/*OUT*/ThreadHandle,
/*ThreadExtensionSize=*/0,
/*KernelStackSize=*/KERNEL_STACK_SIZE,
TlsDataSize,
/*OUT*/ThreadId,
/*StartRoutine=*/StartRoutine,
StartContext,
/*CreateSuspended=*/FALSE,
/*DebuggerThread=*/DebuggerThread,
/*SystemRoutine=*/PspSystemThreadStartup // should use XapiThreadStartup
);
}
static xbox::KDPC PsReaperDpc;
xbox::void_xt xbox::PsInitSystem()
{

View File

@ -26,3 +26,12 @@ namespace xbox
{
void_xt PsInitSystem();
};
xbox::ntstatus_xt NTAPI CxbxrCreateThread
(
OUT xbox::PHANDLE ThreadHandle,
OUT xbox::PHANDLE ThreadId OPTIONAL,
IN xbox::PKSTART_ROUTINE StartRoutine,
IN xbox::PVOID StartContext,
IN xbox::boolean_xt DebuggerThread
);

View File

@ -1432,7 +1432,7 @@ static void CxbxrKrnlInitHacks()
EmuX86_Init();
// Create the interrupt processing thread
xbox::HANDLE hThread;
xbox::PsCreateSystemThread(&hThread, xbox::zeroptr, CxbxKrnlInterruptThread, xbox::zeroptr, FALSE);
CxbxrCreateThread(&hThread, xbox::zeroptr, CxbxKrnlInterruptThread, xbox::zeroptr, FALSE);
// Start the kernel clock thread
TimerObject* KernelClockThr = Timer_Create(CxbxKrnlClockThread, nullptr, "Kernel clock thread", true);
Timer_Start(KernelClockThr, SCALE_MS_IN_NS);

View File

@ -770,6 +770,25 @@ void EmuGenerateFS(xbox::PETHREAD Ethread, unsigned Host2XbStackBaseReserved, un
}
#endif
// Initialize TlsData in order to avoid xbox's APIs attempt to try access null pointer from CxbxrCreateThread.
// As far as I have seen, Xapi's CreateThread's startup function is the only one that does the tls' initialization.
// It will repeat same process yet will not cause performance impact.
// NOTE: PsCreateSystemThread's startup function does not do tls' initialization.
if (Ethread->Tcb.TlsData) {
Xbe::TLS* XbeTls = (Xbe::TLS*)CxbxKrnl_Xbe->m_Header.dwTLSAddr;
uint32_t RawTlsDataSize = XbeTls->dwDataEndAddr - XbeTls->dwDataStartAddr;
// First index is a pointer to the array of tls datas.
xbox::addr_xt* TlsData = reinterpret_cast<xbox::addr_xt*>(Ethread->Tcb.TlsData);
*TlsData = reinterpret_cast<xbox::addr_xt>(Ethread->Tcb.TlsData) + sizeof(xbox::addr_xt);
// Set the actual tls data from xbe.
TlsData += 1;
std::memcpy(TlsData, reinterpret_cast<xbox::PVOID>(XbeTls->dwDataStartAddr), RawTlsDataSize);
if (XbeTls->dwSizeofZeroFill) {
std::memset(reinterpret_cast<xbox::PBYTE>(TlsData) + RawTlsDataSize, 0, XbeTls->dwSizeofZeroFill);
}
}
// Initialize a fake PrcbData.CurrentThread
{
// TODO: Do we need NtTib's overwrite in ENABLE_KTHREAD_SWITCHING usage?