diff --git a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp index 83142f7de..657af7f52 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_cpu.cpp @@ -38,6 +38,25 @@ namespace ams::kern::arch::arm64::cpu { ALWAYS_INLINE ~KScopedCoreMigrationDisable() { GetCurrentThread().EnableCoreMigration(); } }; + class KScopedCacheMaintenance { + private: + bool m_active; + public: + ALWAYS_INLINE KScopedCacheMaintenance() { + __asm__ __volatile__("" ::: "memory"); + if (m_active = !GetCurrentThread().IsInCacheMaintenanceOperation(); m_active) { + GetCurrentThread().SetInCacheMaintenanceOperation(); + } + } + + ALWAYS_INLINE ~KScopedCacheMaintenance() { + if (m_active) { + GetCurrentThread().ClearInCacheMaintenanceOperation(); + } + __asm__ __volatile__("" ::: "memory"); + } + }; + /* Nintendo registers a handler for a SGI on thread termination, but does not handle anything. */ /* This is sufficient, because post-interrupt scheduling is all they really intend to occur. */ class KThreadTerminationInterruptHandler : public KInterruptHandler { @@ -432,9 +451,7 @@ namespace ams::kern::arch::arm64::cpu { Result InvalidateDataCache(void *addr, size_t size) { /* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */ - __asm__ __volatile__("" ::: "memory"); - GetCurrentThread().SetInCacheMaintenanceOperation(); - ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); }; + KScopedCacheMaintenance cm; const uintptr_t start = reinterpret_cast(addr); const uintptr_t end = start + size; @@ -460,9 +477,7 @@ namespace ams::kern::arch::arm64::cpu { Result StoreDataCache(const void *addr, size_t size) { /* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */ - __asm__ __volatile__("" ::: "memory"); - GetCurrentThread().SetInCacheMaintenanceOperation(); - ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); }; + KScopedCacheMaintenance cm; const uintptr_t start = util::AlignDown(reinterpret_cast(addr), DataCacheLineSize); const uintptr_t end = util::AlignUp( reinterpret_cast(addr) + size, DataCacheLineSize); @@ -472,9 +487,7 @@ namespace ams::kern::arch::arm64::cpu { Result FlushDataCache(const void *addr, size_t size) { /* Mark ourselves as in a cache maintenance operation, and prevent re-ordering. */ - __asm__ __volatile__("" ::: "memory"); - GetCurrentThread().SetInCacheMaintenanceOperation(); - ON_SCOPE_EXIT { GetCurrentThread().ClearInCacheMaintenanceOperation(); __asm__ __volatile__("" ::: "memory"); }; + KScopedCacheMaintenance cm; const uintptr_t start = util::AlignDown(reinterpret_cast(addr), DataCacheLineSize); const uintptr_t end = util::AlignUp( reinterpret_cast(addr) + size, DataCacheLineSize); diff --git a/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_exception_asm.s b/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_exception_asm.s index da0b65fb8..2194c594d 100644 --- a/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_exception_asm.s +++ b/libraries/libmesosphere/source/arch/arm64/svc/kern_svc_exception_asm.s @@ -86,9 +86,10 @@ _ZN3ams4kern3svc14RestoreContextEm: /* Get our exception flags. */ ldrb w9, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)] - /* Clear in-svc and needs-fpu-restore flags. */ + /* Clear in-svc, in-user-exception, and needs-fpu-restore flags. */ and w10, w9, #(~(THREAD_EXCEPTION_FLAG_IS_FPU_CONTEXT_RESTORE_NEEDED)) and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_CALLING_SVC)) + and w10, w10, #(~(THREAD_EXCEPTION_FLAG_IS_IN_USERMODE_EXCEPTION_HANDLER)) strb w10, [sp, #(EXCEPTION_CONTEXT_SIZE + THREAD_STACK_PARAMETERS_EXCEPTION_FLAGS)] /* If we don't need to restore the fpu, skip restoring it. */ diff --git a/libraries/libmesosphere/source/kern_k_thread.cpp b/libraries/libmesosphere/source/kern_k_thread.cpp index d29bec692..4149409d4 100644 --- a/libraries/libmesosphere/source/kern_k_thread.cpp +++ b/libraries/libmesosphere/source/kern_k_thread.cpp @@ -509,7 +509,8 @@ namespace ams::kern { void KThread::OnLeaveUsermodeException() { this->ClearUsermodeExceptionSvcPermissions(); - this->ClearInUsermodeExceptionHandler(); + + /* NOTE: InUsermodeExceptionHandler will be cleared by RestoreContext. */ } void KThread::Pin() { diff --git a/libraries/libvapours/include/vapours/svc/svc_version.hpp b/libraries/libvapours/include/vapours/svc/svc_version.hpp index 2d72fa1ee..3c20c7490 100644 --- a/libraries/libvapours/include/vapours/svc/svc_version.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_version.hpp @@ -57,7 +57,7 @@ namespace ams::svc { /* This is the highest SVC version supported by Atmosphere, 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(14); + constexpr inline u32 SupportedKernelMajorVersion = ConvertToSvcMajorVersion(15); constexpr inline u32 SupportedKernelMinorVersion = ConvertToSvcMinorVersion( 3); constexpr inline u32 SupportedKernelVersion = EncodeKernelVersion(SupportedKernelMajorVersion, SupportedKernelMinorVersion);