mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-05-08 11:38:02 +03:00

* sceKernelDebugOutText Some homebrew use this for logging, and these logs do show up in console klogs. I wasn't sure where the most suitable place for this function would be, so I made a separate file for these debug functions. * Implement kernel exit Some homebrew I have use this exit when an error occurs. Since actually closing the emulator isn't implemented yet, I've used an unreachable message that logs the status code. I've placed it in process.cpp for now, let me know if I should change that. * Improved implementations for sceKernelDebugRaiseException functions These functions take in two parameters, an error code and some other value that I have no idea what is for. If that second parameter is not zero, they return ORBIS_KERNEL_ERROR_EINVAL before any calls to mdbg_service. These improved implementations add the early error return and a message with the error code to the unreachable. * Add missing exports Homebrew apps like to use these kernel exports of posix functions instead. * Clang
239 lines
6.9 KiB
C++
239 lines
6.9 KiB
C++
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#include <thread>
|
|
#include <boost/asio/io_context.hpp>
|
|
|
|
#include "common/assert.h"
|
|
#include "common/debug.h"
|
|
#include "common/logging/log.h"
|
|
#include "common/polyfill_thread.h"
|
|
#include "common/thread.h"
|
|
#include "common/va_ctx.h"
|
|
#include "core/file_sys/fs.h"
|
|
#include "core/libraries/error_codes.h"
|
|
#include "core/libraries/kernel/debug.h"
|
|
#include "core/libraries/kernel/equeue.h"
|
|
#include "core/libraries/kernel/file_system.h"
|
|
#include "core/libraries/kernel/kernel.h"
|
|
#include "core/libraries/kernel/memory.h"
|
|
#include "core/libraries/kernel/orbis_error.h"
|
|
#include "core/libraries/kernel/posix_error.h"
|
|
#include "core/libraries/kernel/process.h"
|
|
#include "core/libraries/kernel/threads.h"
|
|
#include "core/libraries/kernel/threads/exception.h"
|
|
#include "core/libraries/kernel/time.h"
|
|
#include "core/libraries/libs.h"
|
|
|
|
#ifdef _WIN64
|
|
#include <Rpc.h>
|
|
#endif
|
|
#include <common/singleton.h>
|
|
#include "aio.h"
|
|
|
|
namespace Libraries::Kernel {
|
|
|
|
static u64 g_stack_chk_guard = 0xDEADBEEF54321ABC; // dummy return
|
|
|
|
boost::asio::io_context io_context;
|
|
static std::mutex m_asio_req;
|
|
static std::condition_variable_any cv_asio_req;
|
|
static std::atomic<u32> asio_requests;
|
|
static std::jthread service_thread;
|
|
|
|
void KernelSignalRequest() {
|
|
std::unique_lock lock{m_asio_req};
|
|
++asio_requests;
|
|
cv_asio_req.notify_one();
|
|
}
|
|
|
|
static void KernelServiceThread(std::stop_token stoken) {
|
|
Common::SetCurrentThreadName("shadPS4:KernelServiceThread");
|
|
|
|
while (!stoken.stop_requested()) {
|
|
HLE_TRACE;
|
|
{
|
|
std::unique_lock lock{m_asio_req};
|
|
Common::CondvarWait(cv_asio_req, lock, stoken, [] { return asio_requests != 0; });
|
|
}
|
|
if (stoken.stop_requested()) {
|
|
break;
|
|
}
|
|
|
|
io_context.run();
|
|
io_context.restart();
|
|
|
|
asio_requests = 0;
|
|
}
|
|
}
|
|
|
|
static PS4_SYSV_ABI void stack_chk_fail() {
|
|
UNREACHABLE();
|
|
}
|
|
|
|
static thread_local int g_posix_errno = 0;
|
|
|
|
int* PS4_SYSV_ABI __Error() {
|
|
return &g_posix_errno;
|
|
}
|
|
|
|
void ErrSceToPosix(int error) {
|
|
g_posix_errno = error - ORBIS_KERNEL_ERROR_UNKNOWN;
|
|
}
|
|
|
|
int ErrnoToSceKernelError(int error) {
|
|
return error + ORBIS_KERNEL_ERROR_UNKNOWN;
|
|
}
|
|
|
|
void SetPosixErrno(int e) {
|
|
// Some error numbers are different between supported OSes
|
|
switch (e) {
|
|
case EPERM:
|
|
g_posix_errno = POSIX_EPERM;
|
|
break;
|
|
case ENOENT:
|
|
g_posix_errno = POSIX_ENOENT;
|
|
break;
|
|
case EDEADLK:
|
|
g_posix_errno = POSIX_EDEADLK;
|
|
break;
|
|
case ENOMEM:
|
|
g_posix_errno = POSIX_ENOMEM;
|
|
break;
|
|
case EACCES:
|
|
g_posix_errno = POSIX_EACCES;
|
|
break;
|
|
case EINVAL:
|
|
g_posix_errno = POSIX_EINVAL;
|
|
break;
|
|
case ENOSPC:
|
|
g_posix_errno = POSIX_ENOSPC;
|
|
break;
|
|
case ERANGE:
|
|
g_posix_errno = POSIX_ERANGE;
|
|
break;
|
|
case EAGAIN:
|
|
g_posix_errno = POSIX_EAGAIN;
|
|
break;
|
|
case ETIMEDOUT:
|
|
g_posix_errno = POSIX_ETIMEDOUT;
|
|
break;
|
|
default:
|
|
LOG_WARNING(Kernel, "Unhandled errno {}", e);
|
|
g_posix_errno = e;
|
|
}
|
|
}
|
|
|
|
static uint64_t g_mspace_atomic_id_mask = 0;
|
|
static uint64_t g_mstate_table[64] = {0};
|
|
|
|
struct HeapInfoInfo {
|
|
uint64_t size = sizeof(HeapInfoInfo);
|
|
uint32_t flag;
|
|
uint32_t getSegmentInfo;
|
|
uint64_t* mspace_atomic_id_mask;
|
|
uint64_t* mstate_table;
|
|
};
|
|
|
|
void PS4_SYSV_ABI sceLibcHeapGetTraceInfo(HeapInfoInfo* info) {
|
|
info->mspace_atomic_id_mask = &g_mspace_atomic_id_mask;
|
|
info->mstate_table = g_mstate_table;
|
|
info->getSegmentInfo = 0;
|
|
}
|
|
|
|
struct OrbisKernelUuid {
|
|
u32 timeLow;
|
|
u16 timeMid;
|
|
u16 timeHiAndVersion;
|
|
u8 clockSeqHiAndReserved;
|
|
u8 clockSeqLow;
|
|
u8 node[6];
|
|
};
|
|
|
|
int PS4_SYSV_ABI sceKernelUuidCreate(OrbisKernelUuid* orbisUuid) {
|
|
#ifdef _WIN64
|
|
UUID uuid;
|
|
UuidCreate(&uuid);
|
|
orbisUuid->timeLow = uuid.Data1;
|
|
orbisUuid->timeMid = uuid.Data2;
|
|
orbisUuid->timeHiAndVersion = uuid.Data3;
|
|
orbisUuid->clockSeqHiAndReserved = uuid.Data4[0];
|
|
orbisUuid->clockSeqLow = uuid.Data4[1];
|
|
for (int i = 0; i < 6; i++) {
|
|
orbisUuid->node[i] = uuid.Data4[2 + i];
|
|
}
|
|
#else
|
|
LOG_ERROR(Kernel, "sceKernelUuidCreate: Add linux");
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
int PS4_SYSV_ABI kernel_ioctl(int fd, u64 cmd, VA_ARGS) {
|
|
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
|
|
auto* file = h->GetFile(fd);
|
|
if (file == nullptr) {
|
|
LOG_INFO(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} file == nullptr", fd, cmd);
|
|
g_posix_errno = POSIX_EBADF;
|
|
return -1;
|
|
}
|
|
if (file->type != Core::FileSys::FileType::Device) {
|
|
LOG_WARNING(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} file->type != Device", fd, cmd);
|
|
g_posix_errno = ENOTTY;
|
|
return -1;
|
|
}
|
|
VA_CTX(ctx);
|
|
int result = file->device->ioctl(cmd, &ctx);
|
|
LOG_TRACE(Lib_Kernel, "ioctl: fd = {:X} cmd = {:X} result = {}", fd, cmd, result);
|
|
if (result < 0) {
|
|
ErrSceToPosix(result);
|
|
return -1;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
const char* PS4_SYSV_ABI sceKernelGetFsSandboxRandomWord() {
|
|
const char* path = "sys";
|
|
return path;
|
|
}
|
|
|
|
int PS4_SYSV_ABI posix_connect() {
|
|
return -1;
|
|
}
|
|
|
|
int PS4_SYSV_ABI _sigprocmask() {
|
|
return ORBIS_OK;
|
|
}
|
|
|
|
int PS4_SYSV_ABI posix_getpagesize() {
|
|
return 16_KB;
|
|
}
|
|
|
|
void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
|
|
service_thread = std::jthread{KernelServiceThread};
|
|
|
|
Libraries::Kernel::RegisterFileSystem(sym);
|
|
Libraries::Kernel::RegisterTime(sym);
|
|
Libraries::Kernel::RegisterThreads(sym);
|
|
Libraries::Kernel::RegisterKernelEventFlag(sym);
|
|
Libraries::Kernel::RegisterMemory(sym);
|
|
Libraries::Kernel::RegisterEventQueue(sym);
|
|
Libraries::Kernel::RegisterProcess(sym);
|
|
Libraries::Kernel::RegisterException(sym);
|
|
Libraries::Kernel::RegisterAio(sym);
|
|
Libraries::Kernel::RegisterDebug(sym);
|
|
|
|
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
|
|
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);
|
|
LIB_FUNCTION("JGfTMBOdUJo", "libkernel", 1, "libkernel", 1, 1, sceKernelGetFsSandboxRandomWord);
|
|
LIB_FUNCTION("XVL8So3QJUk", "libkernel", 1, "libkernel", 1, 1, posix_connect);
|
|
LIB_FUNCTION("6xVpy0Fdq+I", "libkernel", 1, "libkernel", 1, 1, _sigprocmask);
|
|
LIB_FUNCTION("Xjoosiw+XPI", "libkernel", 1, "libkernel", 1, 1, sceKernelUuidCreate);
|
|
LIB_FUNCTION("Ou3iL1abvng", "libkernel", 1, "libkernel", 1, 1, stack_chk_fail);
|
|
LIB_FUNCTION("9BcDykPmo1I", "libkernel", 1, "libkernel", 1, 1, __Error);
|
|
LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize);
|
|
LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize);
|
|
LIB_FUNCTION("NWtTN10cJzE", "libSceLibcInternalExt", 1, "libSceLibcInternal", 1, 1,
|
|
sceLibcHeapGetTraceInfo);
|
|
}
|
|
|
|
} // namespace Libraries::Kernel
|