diff --git a/src/common/virtual_buffer.cpp b/src/common/virtual_buffer.cpp index d444e81edf..7a6e7b8352 100644 --- a/src/common/virtual_buffer.cpp +++ b/src/common/virtual_buffer.cpp @@ -14,6 +14,9 @@ #include #include #include +#include +typedef void (*SceKernelExceptionHandler)(int32_t, void*); +extern "C" int32_t sceKernelInstallExceptionHandler(int32_t signum, SceKernelExceptionHandler handler); #endif #include "common/assert.h" @@ -38,44 +41,90 @@ namespace Common { #ifdef __OPENORBIS__ -static struct sigaction old_sa_segv; + +namespace Orbis { +struct Ucontext { + struct Sigset { + u64 bits[2]; + } uc_sigmask; + int field1_0x10[12]; + struct Mcontext { + u64 mc_onstack; + u64 mc_rdi; + u64 mc_rsi; + u64 mc_rdx; + u64 mc_rcx; + u64 mc_r8; + u64 mc_r9; + u64 mc_rax; + u64 mc_rbx; + u64 mc_rbp; + u64 mc_r10; + u64 mc_r11; + u64 mc_r12; + u64 mc_r13; + u64 mc_r14; + u64 mc_r15; + int mc_trapno; + u16 mc_fs; + u16 mc_gs; + u64 mc_addr; + int mc_flags; + u16 mc_es; + u16 mc_ds; + u64 mc_err; + u64 mc_rip; + u64 mc_cs; + u64 mc_rflags; + u64 mc_rsp; + u64 mc_ss; + u64 mc_len; + u64 mc_fpformat; + u64 mc_ownedfp; + u64 mc_lbrfrom; + u64 mc_lbrto; + u64 mc_aux1; + u64 mc_aux2; + u64 mc_fpstate[104]; + u64 mc_fsbase; + u64 mc_gsbase; + u64 mc_spare[6]; + } uc_mcontext; + struct Ucontext* uc_link; + struct ExStack { + void* ss_sp; + std::size_t ss_size; + int ss_flags; + int _align; + } uc_stack; + int uc_flags; + int __spare[4]; + int field7_0x4f4[3]; +}; +} + static boost::container::static_vector, 16> swap_regions; -static void SwapHandler(int sig, siginfo_t* si, void* raw_context) { - if (std::ranges::find_if(swap_regions, [addr = si->si_addr](auto const& e) { +static void SwapHandler(int sig, void* raw_context) { + auto& mctx = ((Orbis::Ucontext*)raw_context)->uc_mcontext; + if (std::ranges::find_if(swap_regions, [addr = mctx.mc_addr](auto const& e) { return uintptr_t(addr) >= uintptr_t(e.first) && uintptr_t(addr) < uintptr_t(e.first) + e.second; }) != swap_regions.end()) { size_t const page_size = 4096; size_t const page_mask = ~0xfff; // should replace the existing mapping... ugh - void* aligned_addr = reinterpret_cast(uintptr_t(si->si_addr) & page_mask); + void* aligned_addr = reinterpret_cast(uintptr_t(mctx.mc_addr) & page_mask); void* res = mmap(aligned_addr, page_size, PROT_READ | PROT_WRITE, MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0); ASSERT(res != MAP_FAILED); } else { - struct sigaction* retry_sa = &old_sa_segv; - if ((retry_sa->sa_flags & SA_SIGINFO) != 0) { - retry_sa->sa_sigaction(sig, si, raw_context); - } else if (retry_sa->sa_handler == SIG_DFL) { - signal(sig, SIG_DFL); - } else if (retry_sa->sa_handler == SIG_IGN) { - // ignore? - } else { - retry_sa->sa_handler(sig); - } + LOG_ERROR(HW_Memory, "fault in addr {:#x}", mctx.mc_addr); + sceSystemServiceLoadExec("EXIT", nullptr); } } - -bool InitSwap() noexcept { - struct sigaction sa; - sa.sa_handler = NULL; - sa.sa_sigaction = &SwapHandler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_SIGINFO | SA_RESTART; - return sigaction(SIGSEGV, &sa, &old_sa_segv) == 0; +void InitSwap() noexcept { + sceKernelInstallExceptionHandler(SIGSEGV, &SwapHandler); } #else -bool InitSwap() noexcept { - return true; -} +void InitSwap() noexcept {} #endif void* AllocateMemoryPages(std::size_t size) noexcept { @@ -83,7 +132,7 @@ void* AllocateMemoryPages(std::size_t size) noexcept { void* addr = VirtualAlloc(nullptr, size, MEM_COMMIT, PAGE_READWRITE); ASSERT(addr != nullptr); #elif defined(__OPENORBIS__) - void* addr = mmap(nullptr, size, PROT_NONE, MAP_VOID | MAP_PRIVATE, -1, 0); + void* addr = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_VOID | MAP_PRIVATE, -1, 0); ASSERT(addr != MAP_FAILED); swap_regions.emplace_back(addr, size); #else diff --git a/src/common/virtual_buffer.h b/src/common/virtual_buffer.h index 407f6eb3d3..c25b52a51a 100644 --- a/src/common/virtual_buffer.h +++ b/src/common/virtual_buffer.h @@ -12,7 +12,7 @@ namespace Common { void* AllocateMemoryPages(std::size_t size) noexcept; void FreeMemoryPages(void* base, std::size_t size) noexcept; -bool InitSwap() noexcept; +void InitSwap() noexcept; template class VirtualBuffer final { diff --git a/src/qt_common/config/uisettings.h b/src/qt_common/config/uisettings.h index c5a7d0b483..f925bc06ed 100644 --- a/src/qt_common/config/uisettings.h +++ b/src/qt_common/config/uisettings.h @@ -159,7 +159,13 @@ struct Values { Setting enable_discord_presence{linkage, false, "enable_discord_presence", Category::Ui}; // logging - Setting show_console{linkage, false, "showConsole", Category::Ui}; + Setting show_console{linkage, +#ifdef __OPENORBIS__ + true, +#else + false, +#endif + "showConsole", Category::Ui}; // Screenshots Setting enable_screenshot_save_as{linkage, true, "enable_screenshot_save_as", diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 0a50e44d85..27da752047 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp @@ -53,8 +53,10 @@ #ifdef __OPENORBIS__ #include +#include +#include <__thread/support.h> # define STUB_WEAK(name) extern "C" void name() { printf("called " #name); asm volatile("ud2"); } -STUB_WEAK(__cxa_thread_atexit) +void *__cxa_thread_atexit_impl = nullptr; STUB_WEAK(__assert) STUB_WEAK(ZSTD_trace_compress_begin) STUB_WEAK(ZSTD_trace_compress_end) @@ -235,7 +237,6 @@ int main(int argc, char** argv) { {0, 0, 0, 0}, // clang-format on }; - #ifdef __OPENORBIS__ // PS4 will use this path by default UNLESS overriden; this is so users // can quickly launch whatever they want.