mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Kernel: Allow allocating FPLs in volatile memory.
This commit is contained in:
parent
ef5eecce56
commit
fca9b77bd2
2 changed files with 32 additions and 39 deletions
|
@ -840,7 +840,7 @@ const HLEFunction ThreadManForUser[] =
|
|||
{0X1D371B8A, &WrapI_IU<sceKernelCancelVpl>, "sceKernelCancelVpl", 'i', "ix" },
|
||||
{0X39810265, &WrapI_IU<sceKernelReferVplStatus>, "sceKernelReferVplStatus", 'i', "ip" },
|
||||
|
||||
{0XC07BB470, &WrapI_CUUUUU<sceKernelCreateFpl>, "sceKernelCreateFpl", 'i', "sxxxxx" },
|
||||
{0XC07BB470, &WrapI_CUUUUU<sceKernelCreateFpl>, "sceKernelCreateFpl", 'i', "sixxxp" },
|
||||
{0XED1410E0, &WrapI_I<sceKernelDeleteFpl>, "sceKernelDeleteFpl", 'i', "i" },
|
||||
{0XD979E9BF, &WrapI_IUU<sceKernelAllocateFpl>, "sceKernelAllocateFpl", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0XE7282CB6, &WrapI_IUU<sceKernelAllocateFplCB>, "sceKernelAllocateFplCB", 'i', "ixx", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
|
@ -908,7 +908,7 @@ const HLEFunction ThreadManForKernel[] =
|
|||
{0x1fb15a32, &WrapU_IU<sceKernelSetEventFlag>, "sceKernelSetEventFlag", 'x', "ix", HLE_KERNEL_SYSCALL },
|
||||
{0x812346e4, &WrapU_IU<sceKernelClearEventFlag>, "sceKernelClearEventFlag", 'x', "ix", HLE_KERNEL_SYSCALL },
|
||||
{0x402fcf22, &WrapI_IUUUU<sceKernelWaitEventFlag>, "sceKernelWaitEventFlag", 'i', "ixxpp", HLE_NOT_IN_INTERRUPT | HLE_KERNEL_SYSCALL},
|
||||
{0xc07bb470, &WrapI_CUUUUU<sceKernelCreateFpl>, "sceKernelCreateFpl", 'i', "sxxxxx" ,HLE_KERNEL_SYSCALL },
|
||||
{0xc07bb470, &WrapI_CUUUUU<sceKernelCreateFpl>, "sceKernelCreateFpl", 'i', "sixxxp" ,HLE_KERNEL_SYSCALL },
|
||||
{0xed1410e0, &WrapI_I<sceKernelDeleteFpl>, "sceKernelDeleteFpl", 'i', "i" ,HLE_KERNEL_SYSCALL },
|
||||
{0x623ae665, &WrapI_IU<sceKernelTryAllocateFpl>, "sceKernelTryAllocateFpl", 'i', "ix" ,HLE_KERNEL_SYSCALL },
|
||||
{0x616403ba, &WrapI_I<sceKernelTerminateThread>, "sceKernelTerminateThread", 'i', "i" ,HLE_KERNEL_SYSCALL },
|
||||
|
|
|
@ -539,6 +539,17 @@ static int BlockAllocatorToID(const BlockAllocator *alloc) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static BlockAllocator *BlockAllocatorFromAddr(u32 addr) {
|
||||
addr &= 0x3FFFFFFF;
|
||||
if (Memory::IsKernelAndNotVolatileAddress(addr))
|
||||
return &kernelMemory;
|
||||
if (Memory::IsKernelAddress(addr))
|
||||
return &volatileMemory;
|
||||
if (Memory::IsRAMAddress(addr))
|
||||
return &userMemory;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
enum SceKernelFplAttr
|
||||
{
|
||||
PSP_FPL_ATTR_FIFO = 0x0000,
|
||||
|
@ -624,29 +635,18 @@ static void __KernelSortFplThreads(FPL *fpl)
|
|||
std::stable_sort(fpl->waitingThreads.begin(), fpl->waitingThreads.end(), __FplThreadSortPriority);
|
||||
}
|
||||
|
||||
int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 numBlocks, u32 optPtr)
|
||||
{
|
||||
int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 numBlocks, u32 optPtr) {
|
||||
if (!name)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid name", SCE_KERNEL_ERROR_NO_MEMORY);
|
||||
return SCE_KERNEL_ERROR_NO_MEMORY;
|
||||
}
|
||||
return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_NO_MEMORY, "invalid name");
|
||||
if (mpid < 1 || mpid > 9 || mpid == 7)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, mpid);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
// We only support user right now.
|
||||
if (mpid != 2 && mpid != 6)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid partition %d", SCE_KERNEL_ERROR_ILLEGAL_PERM, mpid);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_PERM;
|
||||
}
|
||||
return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "invalid partition %d", mpid);
|
||||
|
||||
BlockAllocator *allocator = BlockAllocatorFromID(mpid);
|
||||
if (allocator == nullptr)
|
||||
return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_PERM, "invalid partition %d", mpid);
|
||||
if (((attr & ~PSP_FPL_ATTR_KNOWN) & ~0xFF) != 0)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid attr parameter: %08x", SCE_KERNEL_ERROR_ILLEGAL_ATTR, attr);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ATTR;
|
||||
}
|
||||
return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ATTR, "invalid attr parameter: %08x", attr);
|
||||
|
||||
// There's probably a simpler way to get this same basic formula...
|
||||
// This is based on results from a PSP.
|
||||
bool illegalMemSize = blockSize == 0 || numBlocks == 0;
|
||||
|
@ -655,25 +655,16 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32
|
|||
if (!illegalMemSize && (u64) numBlocks >= 0x100000000ULL / (((u64) blockSize + 3ULL) & ~3ULL))
|
||||
illegalMemSize = true;
|
||||
if (illegalMemSize)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid blockSize/count", SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE;
|
||||
}
|
||||
return hleReportWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_MEMSIZE, "invalid blockSize/count");
|
||||
|
||||
int alignment = 4;
|
||||
if (optPtr != 0)
|
||||
{
|
||||
u32 size = Memory::Read_U32(optPtr);
|
||||
if (size > 8)
|
||||
WARN_LOG_REPORT(SCEKERNEL, "sceKernelCreateFpl(): unsupported extra options, size = %d", size);
|
||||
if (Memory::IsValidRange(optPtr, 4)) {
|
||||
u32 size = Memory::ReadUnchecked_U32(optPtr);
|
||||
if (size >= 4)
|
||||
alignment = Memory::Read_U32(optPtr + 4);
|
||||
// Must be a power of 2 to be valid.
|
||||
if ((alignment & (alignment - 1)) != 0)
|
||||
{
|
||||
WARN_LOG_REPORT(SCEKERNEL, "%08x=sceKernelCreateFpl(): invalid alignment %d", SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, alignment);
|
||||
return SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT;
|
||||
}
|
||||
return hleLogWarning(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ARGUMENT, "invalid alignment %d", alignment);
|
||||
}
|
||||
|
||||
if (alignment < 4)
|
||||
|
@ -682,9 +673,8 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32
|
|||
int alignedSize = ((int)blockSize + alignment - 1) & ~(alignment - 1);
|
||||
u32 totalSize = alignedSize * numBlocks;
|
||||
bool atEnd = (attr & PSP_FPL_ATTR_HIGHMEM) != 0;
|
||||
u32 address = userMemory.Alloc(totalSize, atEnd, "FPL");
|
||||
if (address == (u32)-1)
|
||||
{
|
||||
u32 address = allocator->Alloc(totalSize, atEnd, "FPL");
|
||||
if (address == (u32)-1) {
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelCreateFpl(\"%s\", partition=%i, attr=%08x, bsize=%i, nb=%i) FAILED - out of ram",
|
||||
name, mpid, attr, blockSize, numBlocks);
|
||||
return SCE_KERNEL_ERROR_NO_MEMORY;
|
||||
|
@ -726,7 +716,10 @@ int sceKernelDeleteFpl(SceUID uid)
|
|||
if (wokeThreads)
|
||||
hleReSchedule("fpl deleted");
|
||||
|
||||
userMemory.Free(fpl->address);
|
||||
BlockAllocator *alloc = BlockAllocatorFromAddr(fpl->address);
|
||||
_assert_msg_(alloc != nullptr, "Should always have a valid allocator/address");
|
||||
if (alloc)
|
||||
alloc->Free(fpl->address);
|
||||
return kernelObjects.Destroy<FPL>(uid);
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Add table
Reference in a new issue