diff options
| author | maufeat <sahyno1996@gmail.com> | 2026-05-05 01:29:46 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-05-05 01:29:46 +0200 |
| commit | fee603f0b97d2d8a6ecb793326e844e066d2f4cf (patch) | |
| tree | 4f3e246f426c2a8282856dafcd2d6851f5b46529 /src/core/hle/kernel | |
| parent | fc5fa7f1b2dc4a67f5cdff43e499991956692a56 (diff) | |
[kernel, hle] Initial 22.0.0 kernel changes and cmd stubs (#3761)
- KProcess::Run() and CreateThread() SVC now write the current thread handle to TLS+0x110
- KPageTableBase::LockForMapDeviceAddressSpace now checks for a new KPageTableBase boolean, m_allowed_exec_device_mapping
- Stub `am` + `acc` + `settings` cmd module that needs to work for qlaunch
Thanks to: @alula and @yellows8
Source for changes: https://github.com/Atmosphere-NX/Atmosphere/pull/2744, https://switchbrew.org/, https://yls8.mtheall.com/
Co-authored-by: PavelBARABANOV <pavelbarabanov94@gmail.com>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3761
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table_base.h | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process_page_table.h | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_thread.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc/svc_thread.cpp | 9 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_version.h | 6 |
7 files changed, 53 insertions, 23 deletions
diff --git a/src/core/hle/kernel/k_page_table_base.cpp b/src/core/hle/kernel/k_page_table_base.cpp index e5b2ed7041..3696f9f251 100644 --- a/src/core/hle/kernel/k_page_table_base.cpp +++ b/src/core/hle/kernel/k_page_table_base.cpp @@ -268,6 +268,7 @@ Result KPageTableBase::InitializeForProcess(Svc::CreateProcessFlag as_type, bool // Set other basic fields. m_enable_aslr = enable_aslr; m_enable_device_address_space_merge = enable_das_merge; + m_allowed_exec_device_mapping = false; m_address_space_start = start; m_address_space_end = end; m_is_kernel = false; diff --git a/src/core/hle/kernel/k_page_table_base.h b/src/core/hle/kernel/k_page_table_base.h index 90f8124a24..726fad989f 100644 --- a/src/core/hle/kernel/k_page_table_base.h +++ b/src/core/hle/kernel/k_page_table_base.h @@ -223,6 +223,7 @@ private: bool m_is_kernel{}; bool m_enable_aslr{}; bool m_enable_device_address_space_merge{}; + bool m_allowed_exec_device_mapping{}; KMemoryBlockSlabManager* m_memory_block_slab_manager{}; KBlockInfoManager* m_block_info_manager{}; KResourceLimit* m_resource_limit{}; @@ -255,6 +256,10 @@ public: return m_enable_aslr; } + void AllowDeviceMappingOfExecPages() { + m_allowed_exec_device_mapping = true; + } + bool Contains(KProcessAddress addr) const { return m_address_space_start <= addr && addr <= m_address_space_end - 1; } diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index bd50f74c27..70e578f22a 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -341,6 +341,11 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa // Initialize capabilities. R_TRY(m_capabilities.InitializeForKip(caps, std::addressof(m_page_table))); + // Enable mapping device pages as executable on legacy processes. + if (m_capabilities.GetIntendedKernelMajorVersion() < 26) { + m_page_table.AllowDeviceMappingOfExecPages(); + } + // Initialize the process id. m_process_id = m_kernel.CreateNewUserProcessID(); ASSERT(InitialProcessIdMin <= m_process_id); @@ -437,6 +442,11 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, // Initialize capabilities. R_TRY(m_capabilities.InitializeForUser(user_caps, std::addressof(m_page_table))); + // Enable mapping device pages as executable on legacy processes. + if (m_capabilities.GetIntendedKernelMajorVersion() < 26) { + m_page_table.AllowDeviceMappingOfExecPages(); + } + // Initialize the process id. m_process_id = m_kernel.CreateNewUserProcessID(); ASSERT(ProcessIdMin <= m_process_id); @@ -989,6 +999,9 @@ Result KProcess::Run(s32 priority, size_t stack_size) { main_thread->GetContext().r[0] = 0; main_thread->GetContext().r[1] = thread_handle; + // Pass the thread handle to the thread local region. + this->GetMemory().Write32(GetInteger(main_thread->GetTlsAddress()) + 0x110, thread_handle); + // Update our state. this->ChangeState((state == State::Created) ? State::Running : State::RunningAttached); ON_RESULT_FAILURE_2 { diff --git a/src/core/hle/kernel/k_process_page_table.h b/src/core/hle/kernel/k_process_page_table.h index 6462e44a99..97c9238907 100644 --- a/src/core/hle/kernel/k_process_page_table.h +++ b/src/core/hle/kernel/k_process_page_table.h @@ -33,6 +33,10 @@ public: m_page_table.Finalize(); } + void AllowDeviceMappingOfExecPages() { + m_page_table.AllowDeviceMappingOfExecPages(); + } + [[nodiscard]] Core::Memory::Memory& GetMemory() noexcept { return m_page_table.GetMemory(); } [[nodiscard]] Core::Memory::Memory const& GetMemory() const noexcept { return m_page_table.GetMemory(); } [[nodiscard]] Common::PageTable& GetImpl() noexcept { return m_page_table.GetImpl(); } diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index ea9b7eb114..0af315d726 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -76,11 +76,13 @@ namespace Kernel { std::atomic_uint16_t interrupt_flag; std::atomic_uint8_t cache_maintenance_flag; std::atomic_int64_t thread_cpu_time; + std::atomic_uint32_t current_thread_handle; }; static_assert(offsetof(ThreadLocalRegion, disable_count) == 0x100); static_assert(offsetof(ThreadLocalRegion, interrupt_flag) == 0x102); static_assert(offsetof(ThreadLocalRegion, cache_maintenance_flag) == 0x104); static_assert(offsetof(ThreadLocalRegion, thread_cpu_time) == 0x108); + static_assert(offsetof(ThreadLocalRegion, current_thread_handle) == 0x110); class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait { public: @@ -128,24 +130,24 @@ namespace Kernel { // Next, assert things based on the type. switch (type) { - case ThreadType::Main: - ASSERT(arg == 0); - [[fallthrough]]; - case ThreadType::User: - ASSERT(((owner == nullptr) || - (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); - ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) || - (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask())); - break; - case ThreadType::HighPriority: - case ThreadType::Dummy: - break; - case ThreadType::Kernel: - UNIMPLEMENTED(); - break; - default: - ASSERT_MSG(false, "KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type)); - break; + case ThreadType::Main: + ASSERT(arg == 0); + [[fallthrough]]; + case ThreadType::User: + ASSERT(((owner == nullptr) || + (owner->GetCoreMask() | (1ULL << virt_core)) == owner->GetCoreMask())); + ASSERT(((owner == nullptr) || (prio > Svc::LowestThreadPriority) || + (owner->GetPriorityMask() | (1ULL << prio)) == owner->GetPriorityMask())); + break; + case ThreadType::HighPriority: + case ThreadType::Dummy: + break; + case ThreadType::Kernel: + UNIMPLEMENTED(); + break; + default: + ASSERT_MSG(false, "KThread::Initialize: Unknown ThreadType {}", static_cast<u32>(type)); + break; } m_thread_type = type; diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index ca5ce6fe07..1aa6f87c04 100644 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -75,7 +75,12 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u KThread::Register(kernel, thread); // Add the thread to the handle table. - R_RETURN(process.GetHandleTable().Add(out_handle, thread)); + R_TRY(process.GetHandleTable().Add(out_handle, thread)); + + // Pass the thread handle to the thread local region. + process.GetMemory().Write32(GetInteger(thread->GetTlsAddress()) + 0x110, *out_handle); + + R_SUCCEED(); } /// Starts the thread for the provided handle diff --git a/src/core/hle/kernel/svc_version.h b/src/core/hle/kernel/svc_version.h index b47874dcde..ec5c5a006a 100644 --- a/src/core/hle/kernel/svc_version.h +++ b/src/core/hle/kernel/svc_version.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -53,8 +53,8 @@ constexpr inline u32 RequiredKernelVersion = // This is the highest SVC version supported, to be updated on new kernel releases. // NOTE: Official kernel versions have SVC major = SDK major + 4, SVC minor = SDK minor. -constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(20); -constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion(5); +constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(22); +constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion(2); constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion); |
