diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp index 931ef0e1d..f6f27c019 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table.hpp @@ -216,7 +216,7 @@ namespace ams::kern::arch::arm64 { ALWAYS_INLINE Result SeparatePagesImpl(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll); Result SeparatePages(KProcessAddress virt_addr, size_t block_size, PageLinkedList *page_list, bool reuse_ll); - Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll); + Result ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, bool flush_mapping, PageLinkedList *page_list, bool reuse_ll); static ALWAYS_INLINE void PteDataMemoryBarrier() { cpu::DataMemoryBarrierInnerShareableStore(); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index 13f0ec10d..3bdfe1776 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -72,13 +72,14 @@ namespace ams::kern { }; enum OperationType { - OperationType_Map = 0, - OperationType_MapFirst = 1, - OperationType_MapGroup = 2, - OperationType_Unmap = 3, - OperationType_ChangePermissions = 4, - OperationType_ChangePermissionsAndRefresh = 5, - OperationType_Separate = 6, + OperationType_Map = 0, + OperationType_MapFirst = 1, + OperationType_MapGroup = 2, + OperationType_Unmap = 3, + OperationType_ChangePermissions = 4, + OperationType_ChangePermissionsAndRefresh = 5, + OperationType_ChangePermissionsAndRefreshAndFlush = 6, + OperationType_Separate = 7, }; static constexpr size_t MaxPhysicalMapAlignment = 1_GB; diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp index e7c733851..ae569f998 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table.cpp @@ -378,9 +378,11 @@ namespace ams::kern::arch::arm64 { case OperationType_MapFirst: R_RETURN(this->MapContiguous(virt_addr, phys_addr, num_pages, entry_template, properties.disable_merge_attributes == DisableMergeAttribute_DisableHead, operation != OperationType_MapFirst, page_list, reuse_ll)); case OperationType_ChangePermissions: - R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, false, page_list, reuse_ll)); + R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, false, false, page_list, reuse_ll)); case OperationType_ChangePermissionsAndRefresh: - R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, true, page_list, reuse_ll)); + R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, true, false, page_list, reuse_ll)); + case OperationType_ChangePermissionsAndRefreshAndFlush: + R_RETURN(this->ChangePermissions(virt_addr, num_pages, entry_template, properties.disable_merge_attributes, true, true, page_list, reuse_ll)); MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); } } @@ -1233,7 +1235,7 @@ namespace ams::kern::arch::arm64 { R_RETURN(this->SeparatePagesImpl(virt_addr, block_size, page_list, reuse_ll)); } - Result KPageTable::ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, PageLinkedList *page_list, bool reuse_ll) { + Result KPageTable::ChangePermissions(KProcessAddress virt_addr, size_t num_pages, PageTableEntry entry_template, DisableMergeAttribute disable_merge_attr, bool refresh_mapping, bool flush_mapping, PageLinkedList *page_list, bool reuse_ll) { MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); /* Separate pages before we change permissions. */ @@ -1451,8 +1453,8 @@ namespace ams::kern::arch::arm64 { KScopedSchedulerLock sl; } - /* Finally, apply the changes as directed, flushing the mappings before they're applied. */ - ApplyEntryTemplate(entry_template, ApplyOption_FlushDataCache); + /* Finally, apply the changes as directed, flushing the mappings before they're applied (if we should). */ + ApplyEntryTemplate(entry_template, flush_mapping ? ApplyOption_FlushDataCache : ApplyOption_None); } /* We've succeeded, now perform what coalescing we can. */ diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 155fd0091..46e23435c 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -1600,7 +1600,7 @@ namespace ams::kern { /* Perform mapping operation. */ const KPageProperties properties = { new_perm, false, false, DisableMergeAttribute_None }; - const auto operation = was_x ? OperationType_ChangePermissionsAndRefresh : OperationType_ChangePermissions; + const auto operation = was_x ? OperationType_ChangePermissionsAndRefreshAndFlush : OperationType_ChangePermissions; R_TRY(this->Operate(updater.GetPageList(), addr, num_pages, Null, false, properties, operation, false)); /* Update the blocks. */ @@ -1649,7 +1649,7 @@ namespace ams::kern { /* Perform operation. */ const KPageProperties properties = { old_perm, false, (new_attr & KMemoryAttribute_Uncached) != 0, DisableMergeAttribute_None }; - R_TRY(this->Operate(updater.GetPageList(), addr, num_pages, Null, false, properties, OperationType_ChangePermissionsAndRefresh, false)); + R_TRY(this->Operate(updater.GetPageList(), addr, num_pages, Null, false, properties, OperationType_ChangePermissionsAndRefreshAndFlush, false)); /* Update the blocks. */ m_memory_block_manager.Update(std::addressof(allocator), addr, num_pages, old_state, old_perm, new_attr, KMemoryBlockDisableMergeAttribute_None, KMemoryBlockDisableMergeAttribute_None);