Merge pull request #6420 from JJenkx/feat/kernel-error-conversion-upstream

feat(libkernel): convert guest POSIX error values
This commit is contained in:
Adrià authored and GitHub committed 2026-10-19 02:40:46 +02:00
commit 347c0a7934
4 files changed
+47

No files matched your search

+10
View File
@@ -67,6 +67,7 @@ add_library(libkernel SHARED EXCLUDE_FROM_ALL
${CMAKE_CURRENT_SOURCE_DIR}/System/src/SystemConfiguration.cpp
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Login.cpp
${CMAKE_CURRENT_SOURCE_DIR}/System/src/SoftwareVersion.cpp
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Error.cpp
${CMAKE_CURRENT_SOURCE_DIR}/System/src/ThermalSensors.cpp
${CMAKE_CURRENT_SOURCE_DIR}/System/src/Signals.cpp
${CMAKE_CURRENT_SOURCE_DIR}/System/src/SignalSets.cpp
@@ -92,6 +93,15 @@ endif()
configure_windows_unwind(libkernel)
if(BUILD_TESTING)
add_test_executable(kernel_error_tests ${LIBS_INCLUDE_DIR}/tests/KernelError.cpp)
target_include_directories(kernel_error_tests PRIVATE ${LIBS_INCLUDE_DIR})
target_link_libraries(kernel_error_tests PRIVATE libkernel libc)
configure_windows_unwind(kernel_error_tests)
add_test(NAME kernel_error COMMAND kernel_error_tests)
if(WIN32)
set_tests_properties(kernel_error PROPERTIES ENVIRONMENT_MODIFICATION
"PATH=path_list_prepend:$<TARGET_FILE_DIR:libkernel>")
endif()
if(NOT WIN32)
add_library(guest_memory_lifetime_module MODULE ${LIBS_INCLUDE_DIR}/tests/GuestMemoryLifetimeModule.cpp)
target_include_directories(guest_memory_lifetime_module PRIVATE ${LIBS_INCLUDE_DIR})
@@ -0,0 +1,8 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include <bit>
#include <cstdint>
extern "C" std::int32_t APS5_VABI sceKernelError(std::int32_t posixError) {
if (posixError == 0) return 0;
return std::bit_cast<std::int32_t>(static_cast<std::uint32_t>(posixError) + 0x80020000u);
}
+28
View File
@@ -0,0 +1,28 @@
#include "prx/libc/include/general/VabiMacros.hpp"
#include "prx/libkernel/KernelErrors.hpp"
#include <array>
#include <cstdint>
#include <limits>
#include <stdexcept>
#include <utility>
extern "C" std::int32_t APS5_VABI sceKernelError(std::int32_t);
extern "C" int* APS5_VABI __error_nid_postfix();
static void Require(bool value) { if (!value) throw std::runtime_error("Kernel error conversion check failed"); }
int main() {
*__error_nid_postfix() = 123;
const std::array<std::pair<std::int32_t, std::int32_t>, 6> cases{{
{0, 0}, {1, SCE_KERNEL_ERROR_EPERM}, {2, SCE_KERNEL_ERROR_ENOENT},
{4, SCE_KERNEL_ERROR_EINTR}, {14, SCE_KERNEL_ERROR_EFAULT}, {22, SCE_KERNEL_ERROR_EINVAL}
}};
for (const auto [input, expected] : cases) {
Require(sceKernelError(input) == expected);
Require(*__error_nid_postfix() == 123);
}
Require(sceKernelError(-1) == static_cast<std::int32_t>(0x8001ffffu));
Require(sceKernelError(std::numeric_limits<std::int32_t>::max()) == 0x1ffff);
Require(sceKernelError(std::numeric_limits<std::int32_t>::min()) == 0x20000);
Require(*__error_nid_postfix() == 123);
}
+1
View File
@@ -12,6 +12,7 @@
### Unknown function info
- [sceKernelError](../../../core/libs/prx/libkernel/System/src/Error.cpp) follows [shadPS4's kernel implementation](https://github.com/shadps4-emu/shadPS4/blob/23c41333822fe8eca4c609b43119180af63ae4ac/src/core/libraries/kernel/kernel.cpp): zero returns zero; other guest POSIX error values receive the `0x80020000` bias without modifying errno. Arithmetic is defined modulo 32 bits to avoid signed overflow for inputs outside the errno domain. Console behavior for those inputs and PS5 equivalence have not been measured.
- [getlogin_r](../../../core/libs/prx/libkernel/System/src/Login.cpp) (libkernel) returns the host effective account name: `GetUserNameW` as UTF-8 on Windows and `getpwuid_r(geteuid())` on POSIX. A valid account returns a name even without a login session; host `getlogin_r`, `USER` and `LOGNAME` are not consulted. The console's login name and behaviour without a session are unknown. Account lookup or encoding failures, a missing or empty account name, and POSIX account records exceeding the 16 KiB lookup buffer throw; there is no replacement name or retry. A short guest buffer returns `ERANGE` without modifying it, and a null output returns `EFAULT`.
- [sceKernelGetSystemSwVersion](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) reports baseline system software version `0x01000000` ("01.000.000") for ProsperoStore (PPSA99000); the console's firmware version is not modeled. Measured on PS5 firmware 13.42: record values 0, 24, 39, 40, 41, 48 and 64 in the leading 64-bit field are accepted and preserved, the 28-byte string at offset 8 and packed version at 0x24 are filled, and bytes from 0x28 onward remain untouched. This API reports "13.590.001" / `0x13590001` in that environment, while the Prospero variant reports "13.420.000" / `0x13420000`; their values must not be assumed identical. A null pointer still returns `SCE_KERNEL_ERROR_EFAULT`, which was not measured; other firmware versions and record values remain unverified.
- [kern.rng_pseudo](../../../core/libs/prx/libkernel/System/src/SystemConfiguration.cpp) (libkernel) - `sysctlbyname` fills the whole output buffer with bytes from the host's `std::random_device` and leaves the length unchanged; a write returns -1 with `EPERM` and a call without an output buffer throws. The only caller seen is mbedTLS's `mbedtls_hardware_poll` in the catalog's ProsperoLight boilerplate, which asks for 64-byte blocks and fails if fewer come back. The console's generator, its per-call maximum and its answer to a size query are unknown