mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-01 07:13:36 +00:00
Fixed errors, improvements
cellSync review, MFC channel AtomicStat added, draft implementation of MFC_GETLLAR_CMD, MFC_PUTLLC_CMD etc, memory allocating hacks for alignment.
This commit is contained in:
parent
76695a97b9
commit
1be7454bc4
@ -21,6 +21,15 @@ enum
|
||||
MFC_MASK_CMD = 0xffff,
|
||||
};
|
||||
|
||||
// Atomic Status Update
|
||||
enum
|
||||
{
|
||||
MFC_PUTLLC_SUCCESS = 0,
|
||||
MFC_PUTLLC_FAILURE = 1, //reservation was lost
|
||||
MFC_PUTLLUC_SUCCESS = 2,
|
||||
MFC_GETLLAR_SUCCESS = 4,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
MFC_SPU_TO_PPU_MAILBOX_STATUS_MASK = 0x000000FF,
|
||||
|
@ -470,6 +470,7 @@ public:
|
||||
Channel<1> QueryType;
|
||||
Channel<1> QueryMask;
|
||||
Channel<1> TagStatus;
|
||||
Channel<1> AtomicStat;
|
||||
} Prxy;
|
||||
|
||||
struct
|
||||
@ -519,6 +520,58 @@ public:
|
||||
}
|
||||
break;
|
||||
|
||||
case MFC_GETLLAR_CMD:
|
||||
case MFC_PUTLLC_CMD:
|
||||
case MFC_PUTLLUC_CMD:
|
||||
{
|
||||
extern wxMutex g_SyncMutex;
|
||||
const CPUThread& current = *GetCurrentPPCThread();
|
||||
if (op == MFC_GETLLAR_CMD)
|
||||
{
|
||||
g_SyncMutex.Lock();
|
||||
/* for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++)
|
||||
{
|
||||
CPUThread& t = *Emu.GetCPU().GetThread(i);
|
||||
if (&t != ¤t && &t)
|
||||
{
|
||||
while (!t.IsRunning()) Sleep(1);
|
||||
t.Pause();
|
||||
}
|
||||
}
|
||||
for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++)
|
||||
{
|
||||
CPUThread& t = *Emu.GetCPU().GetThread(i);
|
||||
if (&t != ¤t && &t)
|
||||
{
|
||||
if (!t.IsPaused()) Sleep(1);
|
||||
}
|
||||
} */
|
||||
}
|
||||
|
||||
ConLog.Warning("DMA %s: lsa=0x%x, ea = 0x%llx, (tag) = 0x%x, (size) = 0x%x, cmd = 0x%x",
|
||||
op == MFC_GETLLAR_CMD ? "GETLLAR" : op == MFC_PUTLLC_CMD ? "PUTLLC" : "PUTLLUC",
|
||||
lsa, ea, tag, size, cmd);
|
||||
//draft implementation
|
||||
_mm_mfence();
|
||||
dmac.ProcessCmd(op == MFC_GETLLAR_CMD ? MFC_GET_CMD : MFC_PUT_CMD, tag, lsa, ea, 128);
|
||||
Prxy.AtomicStat.PushUncond(op == MFC_GETLLAR_CMD ? MFC_GETLLAR_SUCCESS : op == MFC_PUTLLC_CMD ? MFC_PUTLLC_SUCCESS : MFC_PUTLLUC_SUCCESS);
|
||||
_mm_mfence();
|
||||
|
||||
if (op != MFC_GETLLAR_CMD)
|
||||
{
|
||||
/*for (u32 i = 0; i < Emu.GetCPU().GetThreads().GetCount(); i++)
|
||||
{
|
||||
CPUThread& t = *Emu.GetCPU().GetThread(i);
|
||||
if (&t != ¤t && &t)
|
||||
{
|
||||
t.Resume(); //it's wrong (some threads shall not be resumed)
|
||||
}
|
||||
}*/
|
||||
g_SyncMutex.Unlock();
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("Unknown MFC cmd. (opcode=0x%x, cmd=0x%x, lsa = 0x%x, ea = 0x%llx, tag = 0x%x, size = 0x%x)",
|
||||
op, cmd, lsa, ea, tag, size);
|
||||
@ -549,6 +602,9 @@ public:
|
||||
case SPU_RdSigNotify2:
|
||||
return SPU.SNR[1].GetCount();
|
||||
|
||||
case MFC_RdAtomicStat:
|
||||
return Prxy.AtomicStat.GetCount();
|
||||
|
||||
default:
|
||||
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
||||
break;
|
||||
@ -641,6 +697,10 @@ public:
|
||||
//ConLog.Warning("%s: 0x%x = %s", __FUNCTION__, v, spu_ch_name[ch]);
|
||||
break;
|
||||
|
||||
case MFC_RdAtomicStat:
|
||||
while (!Prxy.AtomicStat.Pop(v) && !Emu.IsStopped()) Sleep(1);
|
||||
break;
|
||||
|
||||
default:
|
||||
ConLog.Error("%s error: unknown/illegal channel (%d [%s]).", __FUNCTION__, ch, spu_ch_name[ch]);
|
||||
break;
|
||||
|
@ -425,9 +425,9 @@ public:
|
||||
return Memory.IsGoodAddr(m_addr, sizeof(T));
|
||||
}
|
||||
|
||||
__forceinline operator bool() const
|
||||
__forceinline operator u32() const
|
||||
{
|
||||
return m_addr != 0;
|
||||
return m_addr;
|
||||
}
|
||||
|
||||
__forceinline bool operator != (nullptr_t) const
|
||||
@ -592,6 +592,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
__forceinline T GetValue()
|
||||
{
|
||||
return (be_t<T>&)Memory[this->m_addr];
|
||||
}
|
||||
|
||||
operator const T() const
|
||||
{
|
||||
return (be_t<T>&)Memory[this->m_addr];
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
void cellSync_init();
|
||||
Module cellSync("cellSync", cellSync_init);
|
||||
wxMutex g_SyncMutex;
|
||||
|
||||
// Return Codes
|
||||
enum
|
||||
@ -22,77 +23,93 @@ enum
|
||||
CELL_SYNC_ERROR_NO_SPU_CONTEXT_STORAGE = 0x80410114,
|
||||
};
|
||||
|
||||
int cellSyncMutexInitialize(mem32_t mutex)
|
||||
struct CellSyncMutex {
|
||||
be_t<u16> m_freed;
|
||||
be_t<u16> m_order;
|
||||
/*
|
||||
(???) Lock: increase m_order and wait until m_freed == old m_order
|
||||
(???) Unlock: increase m_freed
|
||||
(???) TryLock: ?????
|
||||
*/
|
||||
};
|
||||
|
||||
int cellSyncMutexInitialize(mem_ptr_t<CellSyncMutex> mutex)
|
||||
{
|
||||
cellSync.Log("cellSyncMutexInitialize(mutex=0x%x)", mutex.GetAddr());
|
||||
const u32 mutex_addr = mutex.GetAddr();
|
||||
if (!mutex_addr)
|
||||
|
||||
if (!mutex.IsGood())
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (mutex_addr % 4)
|
||||
if (mutex.GetAddr() % 4)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
mutex = 0;
|
||||
_mm_sfence();
|
||||
{
|
||||
wxMutexLocker lock(g_SyncMutex);
|
||||
mutex->m_freed = 0;
|
||||
mutex->m_order = 0;
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellSyncMutexLock(mem32_t mutex)
|
||||
int cellSyncMutexLock(mem_ptr_t<CellSyncMutex> mutex)
|
||||
{
|
||||
cellSync.Log("cellSyncMutexLock(mutex=0x%x)", mutex.GetAddr());
|
||||
const u32 mutex_addr = mutex.GetAddr();
|
||||
if (!mutex_addr)
|
||||
if (!mutex.IsGood())
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (mutex_addr % 4)
|
||||
if (mutex.GetAddr() % 4)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
while (_InterlockedExchange((volatile long*)(Memory + mutex_addr), 1 << 24));
|
||||
//need to check how does SPU work with these mutexes, also obtainment order is not guaranteed
|
||||
_mm_lfence();
|
||||
|
||||
be_t<u16> old_order;
|
||||
{
|
||||
wxMutexLocker lock(g_SyncMutex);
|
||||
cellSync.Log("cellSyncMutexLock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed);
|
||||
old_order = mutex->m_order;
|
||||
mutex->m_order = mutex->m_order + 1;
|
||||
}
|
||||
while (old_order != mutex->m_freed) Sleep(1);
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellSyncMutexTryLock(mem32_t mutex)
|
||||
int cellSyncMutexTryLock(mem_ptr_t<CellSyncMutex> mutex)
|
||||
{
|
||||
cellSync.Log("cellSyncMutexTryLock(mutex=0x%x)", mutex.GetAddr());
|
||||
const u32 mutex_addr = mutex.GetAddr();
|
||||
if (!mutex_addr)
|
||||
if (!mutex.IsGood())
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (mutex_addr % 4)
|
||||
if (mutex.GetAddr() % 4)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
//check cellSyncMutexLock
|
||||
if (_InterlockedExchange((volatile long*)(Memory + mutex_addr), 1 << 24))
|
||||
|
||||
wxMutexLocker lock(g_SyncMutex);
|
||||
cellSync.Log("cellSyncMutexTryLock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed);
|
||||
if (mutex->m_order != mutex->m_freed)
|
||||
{
|
||||
return CELL_SYNC_ERROR_BUSY;
|
||||
}
|
||||
_mm_lfence();
|
||||
mutex->m_order = mutex->m_order + 1;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
int cellSyncMutexUnlock(mem32_t mutex)
|
||||
int cellSyncMutexUnlock(mem_ptr_t<CellSyncMutex> mutex)
|
||||
{
|
||||
cellSync.Log("cellSyncMutexUnlock(mutex=0x%x)", mutex.GetAddr());
|
||||
const u32 mutex_addr = mutex.GetAddr();
|
||||
if (!mutex_addr)
|
||||
if (!mutex.IsGood())
|
||||
{
|
||||
return CELL_SYNC_ERROR_NULL_POINTER;
|
||||
}
|
||||
if (mutex_addr % 4)
|
||||
if (mutex.GetAddr() % 4)
|
||||
{
|
||||
return CELL_SYNC_ERROR_ALIGN;
|
||||
}
|
||||
//check cellSyncMutexLock
|
||||
_mm_sfence();
|
||||
_InterlockedExchange((volatile long*)(Memory + mutex_addr), 0);
|
||||
|
||||
wxMutexLocker lock(g_SyncMutex);
|
||||
cellSync.Log("cellSyncMutexUnlock(mutex=0x%x[order=%d,freed=%d])", mutex.GetAddr(), (u16)mutex->m_order, (u16)mutex->m_freed);
|
||||
mutex->m_freed = mutex->m_freed + 1;
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -238,10 +238,12 @@ int cellSysutilGetSystemParamString(s32 id, mem_list_ptr_t<u8> buf, u32 bufsize)
|
||||
{
|
||||
case CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME:
|
||||
cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_NICKNAME");
|
||||
memcpy(buf, "Unknown", 8); //for example
|
||||
break;
|
||||
|
||||
case CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME:
|
||||
cellSysutil.Warning("cellSysutilGetSystemParamString: CELL_SYSUTIL_SYSTEMPARAM_ID_CURRENT_USERNAME");
|
||||
memcpy(buf, "Unknown", 8);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -143,7 +143,6 @@ int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
|
||||
u32 fd = (u32)aio->fd;
|
||||
if(!sys_fs.CheckId(fd, id)) return CELL_ESRCH;
|
||||
vfsFileBase& orig_file = *(vfsFileBase*)id.m_data;
|
||||
//open the file again (to prevent access conflicts roughly)
|
||||
|
||||
u64 nbytes = (u64)aio->size;
|
||||
const u32 buf_addr = (u32)aio->buf_addr;
|
||||
@ -153,7 +152,8 @@ int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
|
||||
|
||||
if(Memory.IsGoodAddr(buf_addr))
|
||||
{
|
||||
vfsFile file(orig_file.GetPath().AfterFirst('/'), vfsRead);
|
||||
//open the file again (to prevent access conflicts roughly)
|
||||
vfsLocalFile file(orig_file.GetPath().AfterFirst('/'), vfsRead);
|
||||
if(!Memory.IsGoodAddr(buf_addr, nbytes))
|
||||
{
|
||||
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
|
||||
@ -178,8 +178,7 @@ int cellFsAioRead(mem_ptr_t<CellFsAio> aio, mem32_t aio_id, mem_func_ptr_t<void
|
||||
sys_fs.Warning("cellFsAioRead(aio_addr: 0x%x[%s], id_addr: 0x%x, func_addr: 0x%x[res=%d, addr=0x%x])", aio.GetAddr(),
|
||||
orig_file.GetPath().c_str(), aio_id.GetAddr(), func.GetAddr(), res, (u32)aio->buf_addr);
|
||||
|
||||
if(func)
|
||||
func(aio, error, xid, res);
|
||||
//if(func) func.async(aio, error, xid, res);
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -95,6 +95,7 @@ int cellFsOpen(u32 path_addr, int flags, mem32_t fd, mem32_t arg, u64 size)
|
||||
}
|
||||
|
||||
fd = sys_fs.GetNewId(stream, flags);
|
||||
sys_fs.Warning("cellFsOpen(path: %s): fd == %d", path.mb_str(), fd.GetValue());
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
@ -6,20 +6,26 @@ SysCallBase sc_mem("memory");
|
||||
|
||||
int sys_memory_container_create(u32 cid_addr, u32 yield_size)
|
||||
{
|
||||
sc_mem.Warning("sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
|
||||
sc_mem.Warning("(HACK!) sys_memory_container_create(cid_addr=0x%x,yield_size=0x%x)", cid_addr, yield_size);
|
||||
|
||||
if(!Memory.IsGoodAddr(cid_addr, 4))
|
||||
{
|
||||
return CELL_EFAULT;
|
||||
}
|
||||
|
||||
u64 addr = Memory.Alloc(yield_size, 1);
|
||||
yield_size &= ~0xfffff; //round down to 1 MB granularity
|
||||
|
||||
//alignment hack (Memory.Alloc does not support alignment yet): alloc size is increased
|
||||
u64 addr = Memory.Alloc(yield_size + 0x100000, 0x100000); //1 MB alignment (???)
|
||||
|
||||
if(!addr)
|
||||
{
|
||||
return CELL_ENOMEM;
|
||||
}
|
||||
|
||||
//fix alignment:
|
||||
addr = (addr + 0x100000) & ~0xfffff;
|
||||
|
||||
Memory.Write32(cid_addr, sc_mem.GetNewId(new MemoryContainerInfo(addr, yield_size)));
|
||||
return CELL_OK;
|
||||
}
|
||||
@ -43,18 +49,20 @@ int sys_memory_container_destroy(u32 cid)
|
||||
int sys_memory_allocate(u32 size, u32 flags, u32 alloc_addr_addr)
|
||||
{
|
||||
//0x30000100;
|
||||
sc_mem.Log("sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
|
||||
sc_mem.Warning("(HACK!) sys_memory_allocate(size=0x%x, flags=0x%x)", size, flags);
|
||||
u32 addr;
|
||||
switch(flags)
|
||||
{
|
||||
case SYS_MEMORY_PAGE_SIZE_1M:
|
||||
if(size & 0xfffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size, 0x100000);
|
||||
addr = Memory.Alloc(size + 0x100000, 0x100000);
|
||||
addr = (addr + 0x100000) & ~0xfffff;
|
||||
break;
|
||||
|
||||
case SYS_MEMORY_PAGE_SIZE_64K:
|
||||
if(size & 0xffff) return CELL_EALIGN;
|
||||
addr = Memory.Alloc(size, 0x10000);
|
||||
addr = Memory.Alloc(size + 0x10000, 0x10000);
|
||||
addr = (addr + 0x10000) & ~0xffff;
|
||||
break;
|
||||
|
||||
default: return CELL_EINVAL;
|
||||
|
Loading…
x
Reference in New Issue
Block a user