1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 03:02:53 +01:00

_cellSpursWorkloadFlagReceiver, cellSpursReadyCountStore

This commit is contained in:
Nekotekina 2014-09-29 19:39:44 +04:00
parent 7d95311a01
commit 6b53479ac3
2 changed files with 222 additions and 97 deletions

View File

@ -94,12 +94,12 @@ s64 spursInit(
{
spurs->m.wklMsk1.write_relaxed(be_t<u32>::make(0xffff));
}
spurs->m.unk6[0xC] = 0;
spurs->m.unk6[0xD] = 0;
spurs->m.unk6[0xE] = 0;
spurs->m.xCC = 0;
spurs->m.xCD = 0;
spurs->m.xCE = 0;
for (u32 i = 0; i < 8; i++)
{
spurs->m.unk6[i] = -1;
spurs->m.xC0[i] = -1;
}
#ifdef PRX_DEBUG
spurs->m.unk7 = vm::read32(libsre_rtoc - 0x7EA4); // write 64-bit pointer to unknown data
@ -131,10 +131,7 @@ s64 spursInit(
spurs->m.unk11 = -1;
spurs->m.unk12 = -1;
spurs->m.unk13 = 0;
spurs->m.x70.direct_op([nSpus](CellSpurs::_sub_x70& x70)
{
x70.nSpus = nSpus;
});
spurs->m.nSpus = nSpus;
spurs->m.spuPriority = spuPriority;
#ifdef PRX_DEBUG
assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK);
@ -187,12 +184,9 @@ s64 spursInit(
assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK);
assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK);
spurs->m.x70.direct_op([flags, isSecond](CellSpurs::_sub_x70& x70)
{
x70.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0);
x70.unk7 = -1;
});
spurs->m.unk18 = -1;
spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK) << 7 | (isSecond ? 0x40 : 0);
spurs->m.flagRecv.write_relaxed(0xff);
spurs->m.wklFlag.flag.write_relaxed(be_t<u32>::make(-1));
spurs->_u8[0xD64] = 0;
spurs->_u8[0xD65] = 0;
spurs->_u8[0xD66] = 0;
@ -569,7 +563,7 @@ s64 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> po
{
return CELL_SPURS_CORE_ERROR_ALIGN;
}
if (spurs->m.unk21.ToBE())
if (spurs->m.exception.ToBE())
{
return CELL_SPURS_CORE_ERROR_STAT;
}
@ -773,13 +767,13 @@ s64 spursWakeUp(vm::ptr<CellSpurs> spurs)
{
return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN;
}
if (spurs->m.unk21.ToBE())
if (spurs->m.exception.ToBE())
{
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
}
spurs->m.unk19[0].exchange(1);
if (spurs->m.unk19[1].read_sync())
spurs->m.xD64.exchange(1);
if (spurs->m.xD65.read_sync())
{
assert(sys_lwmutex_lock(vm::ptr<sys_lwmutex_t>::make(spurs.addr() + 0xdb0), 0) == 0);
assert(sys_lwcond_signal(vm::ptr<sys_lwcond_t>::make(spurs.addr() + 0xdc8)) == 0);
@ -826,13 +820,13 @@ s32 spursAddWorkload(
{
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
}
if (spurs->m.unk21.ToBE())
if (spurs->m.exception.ToBE())
{
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
}
u32 wnum;
const u32 wmax = spurs->m.x70.read_relaxed().flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed)
const u32 wmax = spurs->m.flags1 & 0x40 ? 0x20 : 0x10; // check isSecond (TODO: check if can be changed)
spurs->m.wklMsk1.atomic_op([spurs, wmax, &wnum](be_t<u32>& value)
{
wnum = cntlz32(~(u32)value); // found empty position
@ -853,7 +847,7 @@ s32 spursAddWorkload(
{
assert((spurs->m.wklA[wnum] & 0xf) == 0);
assert((spurs->m.wklB[wnum] & 0xf) == 0);
spurs->m.wklC1[wnum] = 1;
spurs->m.wklStat1[wnum].write_relaxed(1);
spurs->m.wklD1[wnum] = 0;
spurs->m.wklE1[wnum] = 0;
spurs->m.wklG1[wnum].wklPm = pm;
@ -870,10 +864,9 @@ s32 spursAddWorkload(
spurs->m.wklF1[wnum].hookArg = hookArg;
spurs->m.wklE1[wnum] |= 2;
}
spurs->m.wklZ1[wnum] = 0;
if ((spurs->m.x70.read_relaxed().flags1 & 0x40) == 0)
if ((spurs->m.flags1 & 0x40) == 0)
{
spurs->m.wklZ2[wnum] = 0;
spurs->m.wklReadyCount[wnum + 16].write_relaxed(0);
spurs->m.wklMinCnt[wnum] = minContention > 8 ? 8 : minContention;
}
}
@ -881,7 +874,7 @@ s32 spursAddWorkload(
{
assert((spurs->m.wklA[index] & 0xf0) == 0);
assert((spurs->m.wklB[index] & 0xf0) == 0);
spurs->m.wklC2[index] = 1;
spurs->m.wklStat2[index].write_relaxed(1);
spurs->m.wklD2[index] = 0;
spurs->m.wklE2[index] = 0;
spurs->m.wklG2[index].wklPm = pm;
@ -898,8 +891,8 @@ s32 spursAddWorkload(
spurs->m.wklF2[index].hookArg = hookArg;
spurs->m.wklE2[index] |= 2;
}
spurs->m.wklZ2[index] = 0;
}
spurs->m.wklReadyCount[wnum].write_relaxed(0);
u32 pos = ((~wnum * 8) | (wnum / 4)) & 0x1c;
spurs->m.wklMaxCnt[index / 4].atomic_op([pos, maxContention](be_t<u32>& v)
@ -910,26 +903,26 @@ s32 spursAddWorkload(
if (wnum <= 15)
{
spurs->m.x70._and_not({ be_t<u16>::make(0x8000 >> index) }); // clear bit in wklFlag1
spurs->m.wklSet1._and_not({ be_t<u16>::make(0x8000 >> index) }); // clear bit in wklFlag1
}
else
{
spurs->m.x78._and_not({ be_t<u16>::make(0x8000 >> index) }); // clear bit in wklFlag2
spurs->m.wklSet2._and_not({ be_t<u16>::make(0x8000 >> index) }); // clear bit in wklFlag2
}
spurs->m.x70.atomic_op([wnum](CellSpurs::_sub_x70& x70)
spurs->m.flagRecv.atomic_op([wnum](u8& FR)
{
if (x70.unk7 == wnum)
if (FR == wnum)
{
x70.unk7 = 0xff;
FR = 0xff;
}
});
u32 res_wkl;
spurs->m.wklMsk2.atomic_op_sync([spurs, wnum, &res_wkl](be_t<u32>& v)
CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf];
spurs->m.wklMsk2.atomic_op_sync([spurs, &wkl, wnum, &res_wkl](be_t<u32>& v)
{
CellSpurs::_sub_str3& wkl = wnum <= 15 ? spurs->m.wklG1[wnum] : spurs->m.wklG2[wnum & 0xf];
const u32 mask = v.ToLE() & ~(0x80000000 >> wnum);
const u32 mask = v.ToLE() & ~(0x80000000u >> wnum);
res_wkl = 0;
for (u32 i = 0, m = 0x80000000, k = 0; i < 32; i++, m >>= 1)
@ -952,21 +945,13 @@ s32 spursAddWorkload(
}
wkl.wklCopy.exchange((u8)res_wkl);
v = mask | (0x80000000u >> wnum);
});
assert(res_wkl <= 31);
if (wnum <= 15)
{
spurs->m.wklC1[wnum] = 2;
}
else
{
spurs->m.wklC2[index] = 2;
}
spurs->m.unk23[5].exchange(-1); // write 0xff byte at 0xbd
spurs->m.x70._and_not({ {}, -1 }); // clear byte at 0x72
spurs->wklStat(wnum).exchange(2);
spurs->m.xBD.exchange(0xff);
spurs->m.x72.exchange(0);
return CELL_OK;
}
@ -1162,26 +1147,94 @@ s64 cellSpursShutdownWorkload()
#endif
}
s64 _cellSpursWorkloadFlagReceiver()
s64 _cellSpursWorkloadFlagReceiver(vm::ptr<CellSpurs> spurs, u32 wid, u32 is_set)
{
#ifdef PRX_DEBUG
cellSpurs->Warning("%s()", __FUNCTION__);
cellSpurs->Warning("%s(spurs_addr=0x%x, wid=%d, is_set=%d)", __FUNCTION__, spurs.addr(), wid, is_set);
#ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall2(libsre + 0xF158, libsre_rtoc);
#else
UNIMPLEMENTED_FUNC(cellSpurs);
return CELL_OK;
#endif
if (!spurs)
{
return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER;
}
if (spurs.addr() % 128)
{
return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN;
}
if (wid >= (spurs->m.flags1 & 0x40 ? 0x20u : 0x10u))
{
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
}
if ((spurs->m.wklMsk1.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0)
{
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
}
if (spurs->m.exception.ToBE())
{
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
}
if (s32 res = spurs->m.wklFlag.flag.atomic_op_sync(0, [spurs, wid, is_set](be_t<u32>& flag) -> s32
{
if (is_set)
{
if (spurs->m.flagRecv.read_relaxed() != 0xff)
{
return CELL_SPURS_POLICY_MODULE_ERROR_BUSY;
}
}
else
{
if (spurs->m.flagRecv.read_relaxed() != wid)
{
return CELL_SPURS_POLICY_MODULE_ERROR_PERM;
}
}
flag = -1;
return 0;
}))
{
return res;
}
spurs->m.flagRecv.atomic_op([wid, is_set](u8& FR)
{
if (is_set)
{
if (FR == 0xff)
{
FR = (u8)wid;
}
}
else
{
if (FR == wid)
{
FR = 0xff;
}
}
});
return CELL_OK;
}
s64 cellSpursGetWorkloadFlag()
s64 cellSpursGetWorkloadFlag(vm::ptr<CellSpurs> spurs, vm::ptr<vm::bptr<CellSpursWorkloadFlag>> flag)
{
#ifdef PRX_DEBUG
cellSpurs->Warning("%s()", __FUNCTION__);
cellSpurs->Warning("%s(spurs_addr=0x%x, flag_addr=0x%x)", __FUNCTION__, spurs.addr(), flag.addr());
#ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall2(libsre + 0xEC00, libsre_rtoc);
#else
UNIMPLEMENTED_FUNC(cellSpurs);
return CELL_OK;
#endif
if (!spurs || !flag)
{
return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER;
}
if (spurs.addr() % 128)
{
return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN;
}
*flag = vm::bptr<CellSpursWorkloadFlag>::make(Memory.RealToVirtualAddr(&spurs->m.wklFlag));
return CELL_OK;
}
s64 cellSpursSendWorkloadSignal()
@ -1206,15 +1259,36 @@ s64 cellSpursGetWorkloadData()
#endif
}
s64 cellSpursReadyCountStore()
s64 cellSpursReadyCountStore(vm::ptr<CellSpurs> spurs, u32 wid, u32 value)
{
#ifdef PRX_DEBUG
cellSpurs->Warning("%s()", __FUNCTION__);
cellSpurs->Warning("%s(spurs_addr=0x%x, wid=%d, value=0x%x)", __FUNCTION__, spurs.addr(), wid, value);
#ifdef PRX_DEBUG_XXX
return GetCurrentPPUThread().FastCall2(libsre + 0xAB2C, libsre_rtoc);
#else
UNIMPLEMENTED_FUNC(cellSpurs);
return CELL_OK;
#endif
if (!spurs)
{
return CELL_SPURS_POLICY_MODULE_ERROR_NULL_POINTER;
}
if (spurs.addr() % 128)
{
return CELL_SPURS_POLICY_MODULE_ERROR_ALIGN;
}
if (wid >= (spurs->m.flags1 & 0x40 ? 0x20u : 0x10u) || value > 0xff)
{
return CELL_SPURS_POLICY_MODULE_ERROR_INVAL;
}
if ((spurs->m.wklMsk1.read_relaxed().ToLE() & (0x80000000u >> wid)) == 0)
{
return CELL_SPURS_POLICY_MODULE_ERROR_SRCH;
}
if (spurs->m.exception.ToBE() || spurs->wklStat(wid).read_relaxed() != 2)
{
return CELL_SPURS_POLICY_MODULE_ERROR_STAT;
}
spurs->m.wklReadyCount[wid].exchange((u8)value);
return CELL_OK;
}
s64 cellSpursReadyCountAdd()

View File

@ -56,6 +56,38 @@ enum
CELL_SPURS_TASK_ERROR_SHUTDOWN = 0x80410920,
};
enum
{
CELL_SPURS_JOB_ERROR_AGAIN = 0x80410A01,
CELL_SPURS_JOB_ERROR_INVAL = 0x80410A02,
CELL_SPURS_JOB_ERROR_NOSYS = 0x80410A03,
CELL_SPURS_JOB_ERROR_NOMEM = 0x80410A04,
CELL_SPURS_JOB_ERROR_SRCH = 0x80410A05,
CELL_SPURS_JOB_ERROR_NOENT = 0x80410A06,
CELL_SPURS_JOB_ERROR_NOEXEC = 0x80410A07,
CELL_SPURS_JOB_ERROR_DEADLK = 0x80410A08,
CELL_SPURS_JOB_ERROR_PERM = 0x80410A09,
CELL_SPURS_JOB_ERROR_BUSY = 0x80410A0A,
CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR = 0x80410A0B,
CELL_SPURS_JOB_ERROR_JOB_DESCRIPTOR_SIZE = 0x80410A0C,
CELL_SPURS_JOB_ERROR_FAULT = 0x80410A0D,
CELL_SPURS_JOB_ERROR_CHILD = 0x80410A0E,
CELL_SPURS_JOB_ERROR_STAT = 0x80410A0F,
CELL_SPURS_JOB_ERROR_ALIGN = 0x80410A10,
CELL_SPURS_JOB_ERROR_NULL_POINTER = 0x80410A11,
CELL_SPURS_JOB_ERROR_MEMORY_CORRUPTED = 0x80410A12,
CELL_SPURS_JOB_ERROR_MEMORY_SIZE = 0x80410A17,
CELL_SPURS_JOB_ERROR_UNKNOWN_COMMAND = 0x80410A18,
CELL_SPURS_JOB_ERROR_JOBLIST_ALIGNMENT = 0x80410A19,
CELL_SPURS_JOB_ERROR_JOB_ALIGNMENT = 0x80410A1a,
CELL_SPURS_JOB_ERROR_CALL_OVERFLOW = 0x80410A1b,
CELL_SPURS_JOB_ERROR_ABORT = 0x80410A1c,
CELL_SPURS_JOB_ERROR_DMALIST_ELEMENT = 0x80410A1d,
CELL_SPURS_JOB_ERROR_NUM_CACHE = 0x80410A1e,
CELL_SPURS_JOB_ERROR_INVALID_BINARY = 0x80410A1f,
};
// SPURS defines.
enum SPURSKernelInterfaces
{
@ -160,6 +192,13 @@ struct CellSpursAttribute
};
};
struct CellSpursWorkloadFlag
{
be_t<u64> unused0;
be_t<u32> unused1;
atomic_t<u32> flag;
};
typedef void(*CellSpursShutdownCompletionEventHook)(vm::ptr<CellSpurs>, u32 wid, vm::ptr<void> arg);
// Core CellSpurs structures
@ -213,23 +252,6 @@ struct CellSpurs
vm::bptr<const char, 1, u64> nameInstance;
};
struct _sub_x70
{
be_t<u16> wklFlag1; // 0x70
u8 unk2; // 0x72
u8 unk3;
u8 flags1;
u8 unk5;
u8 nSpus;
u8 unk7;
};
struct _sub_x78
{
be_t<u16> wklFlag2;
u8 unk[6];
};
union
{
// raw data
@ -239,27 +261,42 @@ struct CellSpurs
// real data
struct
{
u8 wklZ1[0x10]; // 0x0
u8 wklZ2[0x10]; // 0x10
atomic_t<u8> wklReadyCount[0x20];
u8 wklA[0x10]; // 0x20
u8 wklB[0x10]; // 0x30
u8 wklMinCnt[0x10]; // 0x40
atomic_t<u32> wklMaxCnt[4]; // 0x50
u8 unknown0[0x6C - 0x60];
be_t<u32> unk18; // 0x6C
atomic_t<_sub_x70> x70; // 0x70
atomic_t<_sub_x78> x78; // 0x78
u8 wklC1[0x10]; // 0x80
CellSpursWorkloadFlag wklFlag; // 0x60
atomic_t<u16> wklSet1; // 0x70
atomic_t<u8> x72; // 0x72
u8 x73; // 0x73
u8 flags1; // 0x74
u8 x75; // 0x75
u8 nSpus; // 0x76
atomic_t<u8> flagRecv; // 0x77
atomic_t<u16> wklSet2; // 0x78
u8 x7A[6]; // 0x7A
atomic_t<u8> wklStat1[0x10]; // 0x80
u8 wklD1[0x10]; // 0x90
u8 wklE1[0x10]; // 0xA0
atomic_t<u32> wklMsk1;// 0xB0
atomic_t<u32> wklMsk2;// 0xB4
atomic_t<u8> unk23[8];// 0xB8
u8 unk6[0x10]; // 0xC0 (SPU port at 0xc9)
u8 wklC2[0x10]; // 0xD0
atomic_t<u32> wklMsk1; // 0xB0
atomic_t<u32> wklMsk2; // 0xB4
u8 xB8[5]; // 0xB8
atomic_t<u8> xBD; // 0xBD
u8 xBE[2]; // 0xBE
u8 xC0[8]; // 0xC0
u8 xC8; // 0xC8
u8 spuPort; // 0xC9
u8 xCA; // 0xCA
u8 xCB; // 0xCB
u8 xCC; // 0xCC
u8 xCD; // 0xCD
u8 xCE; // 0xCE
u8 xCF; // 0xCF
atomic_t<u8> wklStat2[0x10]; // 0xD0
u8 wklD2[0x10]; // 0xE0
u8 wklE2[0x10]; // 0xF0
_sub_str1 wklF1[0x10];// 0x100
_sub_str1 wklF1[0x10]; // 0x100
be_t<u64> unk22; // 0x900
u8 unknown7[0x980 - 0x908];
be_t<u64> semPrv; // 0x980
@ -280,9 +317,11 @@ struct CellSpurs
u8 unknown3[0xD5C - 0xD54];
be_t<u32> queue; // 0xD5C
be_t<u32> port; // 0xD60
atomic_t<u8> unk19[4]; // 0xD64 (used in wakeup)
atomic_t<u8> xD64; // 0xD64
atomic_t<u8> xD65; // 0xD65
atomic_t<u8> xD66; // 0xD66
atomic_t<u32> enableEH; // 0xD68
be_t<u32> unk21; // 0xD6C
be_t<u32> exception; // 0xD6C
sys_spu_image spuImg; // 0xD70
be_t<u32> flags; // 0xD80
be_t<s32> spuPriority;// 0xD84
@ -292,7 +331,7 @@ struct CellSpurs
be_t<u32> unk5; // 0xD9C
be_t<u32> revision; // 0xDA0
be_t<u32> sdkVersion; // 0xDA4
atomic_t<u64> spups;// 0xDA8
atomic_t<u64> spups; // 0xDA8
sys_lwmutex_t mutex; // 0xDB0
sys_lwcond_t cond; // 0xDC8
u8 unknown9[0xE00 - 0xDD0];
@ -310,6 +349,18 @@ struct CellSpurs
SPURSManager *spurs;
} c;
};
__forceinline atomic_t<u8>& wklStat(const u32 wid)
{
if (wid & 0x10)
{
return m.wklStat2[wid & 0xf];
}
else
{
return m.wklStat1[wid & 0xf];
}
}
};
typedef CellSpurs CellSpurs2;