Improved error handling in sceKernelAllocateDirectMemory (#2037)

* Handle errors in sceKernelAllocateDirectMemory

* Improve accuracy of error cases

Some of our existing cases are normally EAGAIN returns.

* Improve logging on errors

* Clang

* TEMPORARY HACK FOR NBA TESTS

This will be removed before this PR is marked as ready, and is only here to make sure the other NBA games (and perhaps DOA3) work if some missing init behavior is handled.

* Revert "TEMPORARY HACK FOR NBA TESTS"

This reverts commit a0e27b0229.

* Change error message
This commit is contained in:
Stephen Miller 2025-02-05 09:21:05 -06:00 committed by GitHub
parent 131b6f90e0
commit e757063d31
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 26 additions and 7 deletions

View file

@ -26,17 +26,20 @@ u64 PS4_SYSV_ABI sceKernelGetDirectMemorySize() {
int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u64 len,
u64 alignment, int memoryType, s64* physAddrOut) {
if (searchStart < 0 || searchEnd <= searchStart) {
LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!");
if (searchStart < 0 || searchEnd < 0) {
LOG_ERROR(Kernel_Vmm, "Invalid parameters!");
return ORBIS_KERNEL_ERROR_EINVAL;
}
const bool is_in_range = searchEnd - searchStart >= len;
if (len <= 0 || !Common::Is16KBAligned(len) || !is_in_range) {
LOG_ERROR(Kernel_Vmm, "Provided address range is invalid!");
if (len <= 0 || !Common::Is16KBAligned(len)) {
LOG_ERROR(Kernel_Vmm, "Length {:#x} is invalid!", len);
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (alignment != 0 && !Common::Is16KBAligned(alignment)) {
LOG_ERROR(Kernel_Vmm, "Alignment value is invalid!");
LOG_ERROR(Kernel_Vmm, "Alignment {:#x} is invalid!", alignment);
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (memoryType > 10) {
LOG_ERROR(Kernel_Vmm, "Memory type {:#x} is invalid!", memoryType);
return ORBIS_KERNEL_ERROR_EINVAL;
}
if (physAddrOut == nullptr) {
@ -44,8 +47,21 @@ int PS4_SYSV_ABI sceKernelAllocateDirectMemory(s64 searchStart, s64 searchEnd, u
return ORBIS_KERNEL_ERROR_EINVAL;
}
const bool is_in_range = searchEnd - searchStart >= len;
if (searchEnd <= searchStart || searchEnd < len || !is_in_range) {
LOG_ERROR(Kernel_Vmm,
"Provided address range is too small!"
" searchStart = {:#x}, searchEnd = {:#x}, length = {:#x}",
searchStart, searchEnd, len);
return ORBIS_KERNEL_ERROR_EAGAIN;
}
auto* memory = Core::Memory::Instance();
PAddr phys_addr = memory->Allocate(searchStart, searchEnd, len, alignment, memoryType);
if (phys_addr == -1) {
return ORBIS_KERNEL_ERROR_EAGAIN;
}
*physAddrOut = static_cast<s64>(phys_addr);
LOG_INFO(Kernel_Vmm,

View file

@ -117,7 +117,10 @@ PAddr MemoryManager::Allocate(PAddr search_start, PAddr search_end, size_t size,
dmem_area->second.GetEnd() <= search_end) {
++dmem_area;
}
ASSERT_MSG(is_suitable(), "Unable to find free direct memory area: size = {:#x}", size);
if (!is_suitable()) {
LOG_ERROR(Kernel_Vmm, "Unable to find free direct memory area: size = {:#x}", size);
return -1;
}
// Align free position
PAddr free_addr = dmem_area->second.base;