summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/k_page_table.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/core/hle/kernel/k_page_table.cpp38
1 files changed, 25 insertions, 13 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index e86ded58b..6077985b5 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -837,24 +837,36 @@ ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
return ResultSuccess;
}
-ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
- KMemoryAttribute value) {
- std::lock_guard lock{page_table_lock};
+ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr) {
+ const size_t num_pages = size / PageSize;
+ ASSERT((static_cast<KMemoryAttribute>(mask) | KMemoryAttribute::SetMask) ==
+ KMemoryAttribute::SetMask);
- KMemoryState state{};
- KMemoryPermission perm{};
- KMemoryAttribute attribute{};
+ // Lock the table.
+ std::lock_guard lock{page_table_lock};
- CASCADE_CODE(CheckMemoryState(
- &state, &perm, &attribute, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute,
+ // Verify we can change the memory attribute.
+ KMemoryState old_state;
+ KMemoryPermission old_perm;
+ KMemoryAttribute old_attr;
+ size_t num_allocator_blocks;
+ constexpr auto AttributeTestMask =
+ ~(KMemoryAttribute::SetMask | KMemoryAttribute::DeviceShared);
+ R_TRY(this->CheckMemoryState(
+ std::addressof(old_state), std::addressof(old_perm), std::addressof(old_attr),
+ std::addressof(num_allocator_blocks), addr, size, KMemoryState::FlagCanChangeAttribute,
KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None,
- KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None,
- KMemoryAttribute::DeviceSharedAndUncached));
+ AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask));
+
+ // Determine the new attribute.
+ const auto new_attr = ((old_attr & static_cast<KMemoryAttribute>(~mask)) |
+ static_cast<KMemoryAttribute>(attr & mask));
- attribute = attribute & ~mask;
- attribute = attribute | (mask & value);
+ // Perform operation.
+ this->Operate(addr, num_pages, old_perm, OperationType::ChangePermissionsAndRefresh);
- block_manager->Update(addr, size / PageSize, state, perm, attribute);
+ // Update the blocks.
+ block_manager->Update(addr, num_pages, old_state, old_perm, new_attr);
return ResultSuccess;
}