From 76e963bfe759c35798a2a9d06d3ee72a13c84494 Mon Sep 17 00:00:00 2001 From: Zephyron Date: Sat, 1 Nov 2025 15:44:21 +1000 Subject: [PATCH] kernel: Implement code address offset for Skyline compatibility Add support for the Skyline 32-bit modding framework by implementing a code address offset and improving memory state verification. Changes: - Add CodeStartOffset constant (0x500000) applied to 32-bit code address space types (Is32Bit and Is32BitNoMap) in KProcess::LoadFromMetadata - Add debug logging for 32-bit syscall argument tracking in SetProcessMemoryPermission, MapProcessCodeMemory, and UnmapProcessCodeMemory wrapper functions - Replace CheckMemoryStateContiguous with CheckMemoryState in KPageTableBase::UnmapCodeMemory for more flexible memory state verification This implementation enables compatibility with: - Skyline 32-bit modding framework - CTGP-DX (Mario Kart 8 Deluxe mod) - Other homebrew using 32-bit Skyline Based on similar fixes in Ryujinx (commit 5e9678c8fe) and Eden emulator. Co-authored-by: JPikachu Co-authored-by: JPikachu Signed-off-by: Zephyron --- src/core/hle/kernel/k_page_table_base.cpp | 3 ++- src/core/hle/kernel/k_process.cpp | 11 +++++++++-- src/core/hle/kernel/svc.cpp | 16 ++++++++++++++++ 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index 5e00f0c81..986093234 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include "common/scope_exit.h" @@ -1274,7 +1275,7 @@ Result KPageTableBase::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddr // Verify that the destination memory is aliasable code. size_t num_dst_allocator_blocks; - R_TRY(this->CheckMemoryStateContiguous( + R_TRY(this->CheckMemoryState( std::addressof(num_dst_allocator_blocks), dst_address, size, KMemoryState::FlagCanCodeAlias, KMemoryState::FlagCanCodeAlias, KMemoryPermission::None, KMemoryPermission::None, KMemoryAttribute::All & ~KMemoryAttribute::PermissionLocked, KMemoryAttribute::None)); diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 80566b7e7..0a4aee3c2 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include @@ -25,6 +26,12 @@ namespace Kernel { namespace { +// Code offset for 32-bit processes to ensure compatibility with Skyline modding framework. +// Skyline assumes memory exists before the entry point. This matches the approach used for +// 39-bit processes (which load at 0x8000'0000 instead of 0x800'0000 for the same reason). +// This can only be removed if Skyline is updated to not depend on pre-entry-point memory. +constexpr u64 CodeStartOffset = 0x500000UL; + Result TerminateChildren(KernelCore& kernel, KProcess* process, const KThread* thread_to_not_terminate) { // Request that all children threads terminate. @@ -1195,11 +1202,11 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: break; case FileSys::ProgramAddressSpaceType::Is32Bit: flag |= Svc::CreateProcessFlag::AddressSpace32Bit; - code_address = 0x20'0000; + code_address = 0x20'0000 + CodeStartOffset; break; case FileSys::ProgramAddressSpaceType::Is32BitNoMap: flag |= Svc::CreateProcessFlag::AddressSpace32BitWithoutAlias; - code_address = 0x20'0000; + code_address = 0x20'0000 + CodeStartOffset; break; } diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index c55dc0c8a..38fd90af5 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -1,4 +1,5 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 citron Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later // This file is automatically generated using svc_generator.py. @@ -1825,6 +1826,10 @@ static void SvcWrap_SetProcessMemoryPermission64From32(Core::System& system, std uint64_t size{}; MemoryPermission perm{}; + LOG_DEBUG(Kernel_SVC, "Raw args, [0]={:#x} [1]={:#x} [2]={:#x} [3]={:#x} [4]={:#x} [5]={:#x}", + GetArg32(args, 0), GetArg32(args, 1), GetArg32(args, 2), + GetArg32(args, 3), GetArg32(args, 4), GetArg32(args, 5)); + process_handle = Convert(GetArg32(args, 0)); std::array address_gather{}; address_gather[0] = GetArg32(args, 2); @@ -1912,6 +1917,10 @@ static void SvcWrap_MapProcessCodeMemory64From32(Core::System& system, std::span uint64_t src_address{}; uint64_t size{}; + LOG_DEBUG(Kernel_SVC, "Raw args, [0]={:#x} [1]={:#x} [2]={:#x} [3]={:#x} [4]={:#x} [5]={:#x} [6]={:#x}", + GetArg32(args, 0), GetArg32(args, 1), GetArg32(args, 2), + GetArg32(args, 3), GetArg32(args, 4), GetArg32(args, 5), GetArg32(args, 6)); + process_handle = Convert(GetArg32(args, 0)); std::array dst_address_gather{}; dst_address_gather[0] = GetArg32(args, 2); @@ -1939,6 +1948,10 @@ static void SvcWrap_UnmapProcessCodeMemory64From32(Core::System& system, std::sp uint64_t src_address{}; uint64_t size{}; + LOG_DEBUG(Kernel_SVC, "Raw args, [0]={:#x} [1]={:#x} [2]={:#x} [3]={:#x} [4]={:#x} [5]={:#x} [6]={:#x}", + GetArg32(args, 0), GetArg32(args, 1), GetArg32(args, 2), + GetArg32(args, 3), GetArg32(args, 4), GetArg32(args, 5), GetArg32(args, 6)); + process_handle = Convert(GetArg32(args, 0)); std::array dst_address_gather{}; dst_address_gather[0] = GetArg32(args, 2); @@ -1953,6 +1966,9 @@ static void SvcWrap_UnmapProcessCodeMemory64From32(Core::System& system, std::sp size_gather[1] = GetArg32(args, 6); size = Convert(size_gather); + LOG_DEBUG(Kernel_SVC, "Reconstructed, handle={:#x} dst={:#x} src={:#x} size={:#x}", + process_handle, dst_address, src_address, size); + ret = UnmapProcessCodeMemory64From32(system, process_handle, dst_address, src_address, size); SetArg32(args, 0, Convert(ret));