Loading an IOP module through LOADCORE will block the EE till its initialization is complete. This is needed to prevent race conditions.

This commit is contained in:
Jean-Philip Desjardins 2014-07-10 23:43:29 -04:00
parent 3bcac99f41
commit 290355bda4
5 changed files with 30 additions and 10 deletions

View File

@ -543,8 +543,7 @@ void CSIF::SendCallReply(uint32 serverId, const void* returnData)
if(replyIterator == m_callReplies.end()) return;
CALLREQUESTINFO& requestInfo(replyIterator->second);
//assert(requestInfo.call.nRecv != 0);
if(requestInfo.call.nRecv != 0)
if(requestInfo.call.nRecv != 0 && returnData != nullptr)
{
uint32 dstPtr = requestInfo.call.nRecv & (PS2::EE_RAM_SIZE - 1);
memcpy(m_eeRam + dstPtr, returnData, requestInfo.call.nRecvSize);

View File

@ -63,7 +63,8 @@
#define SYSCALL_RESCHEDULE 0x668
#define SYSCALL_SLEEPTHREAD 0x669
#define SYSCALL_PROCESSMODULELOAD 0x66A
#define SYSCALL_DELAYTHREADTICKS 0x66B
#define SYSCALL_FINISHMODULELOAD 0x66B
#define SYSCALL_DELAYTHREADTICKS 0x66C
#define STACK_FRAME_RESERVE_SIZE 0x10
@ -437,12 +438,18 @@ void CIopBios::ProcessModuleLoad()
}
m_cpu.m_State.nGPR[CMIPS::SP].nV0 -= 4;
m_cpu.m_State.nPC = moduleLoadRequest->entryPoint;
m_cpu.m_State.nGPR[CMIPS::GP].nV0 = moduleLoadRequest->gp;
m_cpu.m_State.nGPR[CMIPS::RA].nV0 = m_moduleLoaderThreadProcAddress;
m_cpu.m_State.nGPR[CMIPS::RA].nV0 = m_cpu.m_State.nPC;
m_cpu.m_State.nPC = moduleLoadRequest->entryPoint;
}
}
void CIopBios::FinishModuleLoad()
{
//We need to notify the EE that the load request is over
m_sifMan->SendCallReply(Iop::CLoadcore::MODULE_ID, nullptr);
}
void CIopBios::LoadAndStartModule(const char* path, const char* args, unsigned int argsLength)
{
uint32 handle = m_ioman->Open(Iop::Ioman::CDevice::OPEN_FLAG_RDONLY, path);
@ -1522,10 +1529,19 @@ uint32 CIopBios::AssembleIdleFunction(CMIPSAssembler& assembler)
uint32 CIopBios::AssembleModuleLoaderThreadProc(CMIPSAssembler& assembler)
{
uint32 address = BIOS_HANDLERS_BASE + assembler.GetProgramSize() * 4;
auto startLabel = assembler.CreateLabel();
assembler.MarkLabel(startLabel);
assembler.ADDIU(CMIPS::V0, CMIPS::R0, SYSCALL_SLEEPTHREAD);
assembler.SYSCALL();
assembler.ADDIU(CMIPS::V0, CMIPS::R0, SYSCALL_PROCESSMODULELOAD);
assembler.SYSCALL();
assembler.ADDIU(CMIPS::V0, CMIPS::R0, SYSCALL_FINISHMODULELOAD);
assembler.SYSCALL();
assembler.BEQ(CMIPS::R0, CMIPS::R0, startLabel);
assembler.NOP();
return address;
}
@ -1592,6 +1608,9 @@ void CIopBios::HandleException()
case SYSCALL_PROCESSMODULELOAD:
ProcessModuleLoad();
break;
case SYSCALL_FINISHMODULELOAD:
FinishModuleLoad();
break;
case SYSCALL_DELAYTHREADTICKS:
DelayThreadTicks(m_cpu.m_State.nGPR[CMIPS::A0].nV0);
break;

View File

@ -327,6 +327,7 @@ private:
void InitializeModuleLoader();
void ProcessModuleLoad();
void FinishModuleLoad();
void RequestModuleLoad(uint32, uint32, const char*, const char*, unsigned int);
void InsertLoadedModuleName(const std::string&);

View File

@ -71,6 +71,7 @@ bool CLoadcore::Invoke(uint32 method, uint32* args, uint32 argsSize, uint32* ret
{
case 0x00:
LoadModule(args, argsSize, ret, retSize);
return false; //Block EE till module is loaded
break;
case 0x01:
LoadExecutable(args, argsSize, ret, retSize);

View File

@ -12,6 +12,11 @@ namespace Iop
class CLoadcore : public CModule, public CSifModule
{
public:
enum MODULE_ID
{
MODULE_ID = 0x80000006
};
typedef std::function<uint32 (const char*, const char*)> LoadExecutableHandler;
CLoadcore(CIopBios&, uint8*, CSifMan&);
@ -25,11 +30,6 @@ namespace Iop
void SetLoadExecutableHandler(const LoadExecutableHandler&);
private:
enum MODULE_ID
{
MODULE_ID = 0x80000006
};
uint32 RegisterLibraryEntries(uint32*);
void LoadModule(uint32*, uint32, uint32*, uint32);
void LoadExecutable(uint32*, uint32, uint32*, uint32);