mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-10 08:51:28 +12:00
SPURS: Implement SPURS SPU thread exit using throw
Conflicts: rpcs3/Emu/SysCalls/Modules/cellSpursSpu.cpp
This commit is contained in:
parent
c0fdef7a12
commit
5b7f701878
2 changed files with 47 additions and 25 deletions
|
@ -1192,7 +1192,7 @@ void SPUThread::halt()
|
||||||
{
|
{
|
||||||
if (Ini.HLELogging.GetValue())
|
if (Ini.HLELogging.GetValue())
|
||||||
{
|
{
|
||||||
LOG_NOTICE(SPU, "halt(code=0x%x)");
|
LOG_NOTICE(SPU, "halt()");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_type == CPU_THREAD_RAW_SPU)
|
if (m_type == CPU_THREAD_RAW_SPU)
|
||||||
|
|
|
@ -11,6 +11,17 @@
|
||||||
#include "Loader/ELF32.h"
|
#include "Loader/ELF32.h"
|
||||||
#include "Emu/FS/vfsStreamMemory.h"
|
#include "Emu/FS/vfsStreamMemory.h"
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Types
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
class SpursModuleExit {
|
||||||
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Function prototypes
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//
|
//
|
||||||
// SPURS utility functions
|
// SPURS utility functions
|
||||||
//
|
//
|
||||||
|
@ -67,6 +78,10 @@ s32 spursTasksetProcessSyscall(SPUThread & spu, u32 syscallNum, u32 args);
|
||||||
void spursTasksetInit(SPUThread & spu, u32 pollStatus);
|
void spursTasksetInit(SPUThread & spu, u32 pollStatus);
|
||||||
s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments);
|
s32 spursTasksetLoadElf(SPUThread & spu, u32 * entryPoint, u32 * lowestLoadAddr, u64 elfAddr, bool skipWriteableSegments);
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Externs
|
||||||
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
extern Module cellSpurs;
|
extern Module cellSpurs;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -102,6 +117,7 @@ u32 cellSpursModulePollStatus(SPUThread & spu, u32 * status) {
|
||||||
void cellSpursModuleExit(SPUThread & spu) {
|
void cellSpursModuleExit(SPUThread & spu) {
|
||||||
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
|
auto ctxt = vm::get_ptr<SpursKernelContext>(spu.offset + 0x100);
|
||||||
spu.SetBranch(ctxt->exitToKernelAddr);
|
spu.SetBranch(ctxt->exitToKernelAddr);
|
||||||
|
throw SpursModuleExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Execute a DMA operation
|
/// Execute a DMA operation
|
||||||
|
@ -576,6 +592,7 @@ bool spursSysServiceEntry(SPUThread & spu) {
|
||||||
auto arg = spu.GPR[4]._u64[1];
|
auto arg = spu.GPR[4]._u64[1];
|
||||||
auto pollStatus = spu.GPR[5]._u32[3];
|
auto pollStatus = spu.GPR[5]._u32[3];
|
||||||
|
|
||||||
|
try {
|
||||||
if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
|
if (ctxt->wklCurrentId == CELL_SPURS_SYS_SERVICE_WORKLOAD_ID) {
|
||||||
spursSysServiceMain(spu, pollStatus);
|
spursSysServiceMain(spu, pollStatus);
|
||||||
} else {
|
} else {
|
||||||
|
@ -584,6 +601,11 @@ bool spursSysServiceEntry(SPUThread & spu) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cellSpursModuleExit(spu);
|
cellSpursModuleExit(spu);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (SpursModuleExit) {
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -660,7 +682,7 @@ void spursSysServiceIdleHandler(SPUThread & spu, SpursKernelContext * ctxt) {
|
||||||
if (spuIdling && shouldExit == false && foundReadyWorkload == false) {
|
if (spuIdling && shouldExit == false && foundReadyWorkload == false) {
|
||||||
// The system service blocks by making a reservation and waiting on the lock line reservation lost event.
|
// The system service blocks by making a reservation and waiting on the lock line reservation lost event.
|
||||||
spu.WaitForAnySignal(1);
|
spu.WaitForAnySignal(1);
|
||||||
if (Emu.IsStopped()) return;
|
if (Emu.IsStopped()) throw SpursModuleExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vm::reservation_update(vm::cast(ctxt->spurs.addr()), vm::get_ptr(spu.offset + 0x100), 128) && (shouldExit || foundReadyWorkload)) {
|
if (vm::reservation_update(vm::cast(ctxt->spurs.addr()), vm::get_ptr(spu.offset + 0x100), 128) && (shouldExit || foundReadyWorkload)) {
|
||||||
|
@ -679,8 +701,7 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) {
|
||||||
|
|
||||||
if (!ctxt->spurs.aligned()) {
|
if (!ctxt->spurs.aligned()) {
|
||||||
assert(!"spursSysServiceMain(): invalid spurs alignment");
|
assert(!"spursSysServiceMain(): invalid spurs alignment");
|
||||||
//spursHalt(spu);
|
spursHalt(spu);
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialise the system service if this is the first time its being started on this SPU
|
// Initialise the system service if this is the first time its being started on this SPU
|
||||||
|
@ -695,8 +716,7 @@ void spursSysServiceMain(SPUThread & spu, u32 pollStatus) {
|
||||||
// Halt if already initialised
|
// Halt if already initialised
|
||||||
if (spurs->sysSrvOnSpu & (1 << ctxt->spuNum)) {
|
if (spurs->sysSrvOnSpu & (1 << ctxt->spuNum)) {
|
||||||
assert(!"spursSysServiceMain(): already initialized");
|
assert(!"spursSysServiceMain(): already initialized");
|
||||||
//spursHalt(spu);
|
spursHalt(spu);
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spurs->sysSrvOnSpu |= 1 << ctxt->spuNum;
|
spurs->sysSrvOnSpu |= 1 << ctxt->spuNum;
|
||||||
|
@ -1084,11 +1104,17 @@ bool spursTasksetEntry(SPUThread & spu) {
|
||||||
spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry);
|
spu.RegisterHleFunction(CELL_SPURS_TASKSET_PM_ENTRY_ADDR, spursTasksetEntry);
|
||||||
spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry);
|
spu.RegisterHleFunction(ctxt->syscallAddr, spursTasksetSyscallEntry);
|
||||||
|
|
||||||
|
try {
|
||||||
// Initialise the taskset policy module
|
// Initialise the taskset policy module
|
||||||
spursTasksetInit(spu, pollStatus);
|
spursTasksetInit(spu, pollStatus);
|
||||||
|
|
||||||
// Dispatch
|
// Dispatch
|
||||||
spursTasksetDispatch(spu);
|
spursTasksetDispatch(spu);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch (SpursModuleExit) {
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1159,8 +1185,7 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
|
||||||
if ((taskset->waiting & taskset->running) != _0 || (taskset->ready & taskset->pending_ready) != _0 ||
|
if ((taskset->waiting & taskset->running) != _0 || (taskset->ready & taskset->pending_ready) != _0 ||
|
||||||
((taskset->running | taskset->ready | taskset->pending_ready | taskset->signalled | taskset->waiting) & be_t<u128>::make(~taskset->enabled.value())) != _0) {
|
((taskset->running | taskset->ready | taskset->pending_ready | taskset->signalled | taskset->waiting) & be_t<u128>::make(~taskset->enabled.value())) != _0) {
|
||||||
assert(!"Invalid taskset state");
|
assert(!"Invalid taskset state");
|
||||||
//spursHalt(spu);
|
spursHalt(spu);
|
||||||
//return CELL_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the number of tasks that have become ready since the last iteration
|
// Find the number of tasks that have become ready since the last iteration
|
||||||
|
@ -1277,8 +1302,7 @@ s32 spursTasksetProcessRequest(SPUThread & spu, s32 request, u32 * taskId, u32 *
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(!"Unknown taskset request");
|
assert(!"Unknown taskset request");
|
||||||
//spursHalt(spu);
|
spursHalt(spu);
|
||||||
//return CELL_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
taskset->pending_ready = _0;
|
taskset->pending_ready = _0;
|
||||||
|
@ -1455,8 +1479,7 @@ void spursTasksetDispatch(SPUThread & spu) {
|
||||||
u32 lowestLoadAddr;
|
u32 lowestLoadAddr;
|
||||||
if (spursTasksetLoadElf(spu, &entryPoint, &lowestLoadAddr, taskInfo->elf_addr.addr(), false) != CELL_OK) {
|
if (spursTasksetLoadElf(spu, &entryPoint, &lowestLoadAddr, taskInfo->elf_addr.addr(), false) != CELL_OK) {
|
||||||
assert(!"spursTaskLoadElf() failed");
|
assert(!"spursTaskLoadElf() failed");
|
||||||
//spursHalt(spu);
|
spursHalt(spu);
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId);
|
//spursDmaWaitForCompletion(spu, 1 << ctxt->dmaTagId);
|
||||||
|
@ -1497,8 +1520,7 @@ void spursTasksetDispatch(SPUThread & spu) {
|
||||||
u32 entryPoint;
|
u32 entryPoint;
|
||||||
if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf_addr.addr(), true) != CELL_OK) {
|
if (spursTasksetLoadElf(spu, &entryPoint, nullptr, taskInfo->elf_addr.addr(), true) != CELL_OK) {
|
||||||
assert(!"spursTasksetLoadElf() failed");
|
assert(!"spursTasksetLoadElf() failed");
|
||||||
//spursHalt(spu);
|
spursHalt(spu);
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue