|
|
|
@ -505,7 +505,7 @@ Result KPageTable::UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress
|
|
|
|
|
R_TRY(this->CheckMemoryStateContiguous(
|
|
|
|
|
std::addressof(num_dst_allocator_blocks), dst_address, size, KMemoryState::FlagCanCodeAlias,
|
|
|
|
|
KMemoryState::FlagCanCodeAlias, KMemoryPermission::None, KMemoryPermission::None,
|
|
|
|
|
KMemoryAttribute::All, KMemoryAttribute::None));
|
|
|
|
|
KMemoryAttribute::All & ~KMemoryAttribute::PermissionLocked, KMemoryAttribute::None));
|
|
|
|
|
|
|
|
|
|
// Determine whether any pages being unmapped are code.
|
|
|
|
|
bool any_code_pages = false;
|
|
|
|
@ -1770,7 +1770,11 @@ Result KPageTable::MapPhysicalMemory(KProcessAddress address, size_t size) {
|
|
|
|
|
m_memory_block_manager.UpdateIfMatch(
|
|
|
|
|
std::addressof(allocator), address, size / PageSize, KMemoryState::Free,
|
|
|
|
|
KMemoryPermission::None, KMemoryAttribute::None, KMemoryState::Normal,
|
|
|
|
|
KMemoryPermission::UserReadWrite, KMemoryAttribute::None);
|
|
|
|
|
KMemoryPermission::UserReadWrite, KMemoryAttribute::None,
|
|
|
|
|
address == this->GetAliasRegionStart()
|
|
|
|
|
? KMemoryBlockDisableMergeAttribute::Normal
|
|
|
|
|
: KMemoryBlockDisableMergeAttribute::None,
|
|
|
|
|
KMemoryBlockDisableMergeAttribute::None);
|
|
|
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
|
}
|
|
|
|
@ -1868,6 +1872,13 @@ Result KPageTable::UnmapPhysicalMemory(KProcessAddress address, size_t size) {
|
|
|
|
|
|
|
|
|
|
// Iterate over the memory, unmapping as we go.
|
|
|
|
|
auto it = m_memory_block_manager.FindIterator(cur_address);
|
|
|
|
|
|
|
|
|
|
const auto clear_merge_attr =
|
|
|
|
|
(it->GetState() == KMemoryState::Normal &&
|
|
|
|
|
it->GetAddress() == this->GetAliasRegionStart() && it->GetAddress() == address)
|
|
|
|
|
? KMemoryBlockDisableMergeAttribute::Normal
|
|
|
|
|
: KMemoryBlockDisableMergeAttribute::None;
|
|
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
|
// Check that the iterator is valid.
|
|
|
|
|
ASSERT(it != m_memory_block_manager.end());
|
|
|
|
@ -1905,7 +1916,7 @@ Result KPageTable::UnmapPhysicalMemory(KProcessAddress address, size_t size) {
|
|
|
|
|
m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize,
|
|
|
|
|
KMemoryState::Free, KMemoryPermission::None,
|
|
|
|
|
KMemoryAttribute::None, KMemoryBlockDisableMergeAttribute::None,
|
|
|
|
|
KMemoryBlockDisableMergeAttribute::None);
|
|
|
|
|
clear_merge_attr);
|
|
|
|
|
|
|
|
|
|
// We succeeded.
|
|
|
|
|
R_SUCCEED();
|
|
|
|
@ -2650,11 +2661,18 @@ Result KPageTable::SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mas
|
|
|
|
|
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,
|
|
|
|
|
AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask));
|
|
|
|
|
const KMemoryState state_test_mask =
|
|
|
|
|
static_cast<KMemoryState>(((mask & static_cast<u32>(KMemoryAttribute::Uncached))
|
|
|
|
|
? static_cast<u32>(KMemoryState::FlagCanChangeAttribute)
|
|
|
|
|
: 0) |
|
|
|
|
|
((mask & static_cast<u32>(KMemoryAttribute::PermissionLocked))
|
|
|
|
|
? static_cast<u32>(KMemoryState::FlagCanPermissionLock)
|
|
|
|
|
: 0));
|
|
|
|
|
R_TRY(this->CheckMemoryState(std::addressof(old_state), std::addressof(old_perm),
|
|
|
|
|
std::addressof(old_attr), std::addressof(num_allocator_blocks),
|
|
|
|
|
addr, size, state_test_mask, state_test_mask,
|
|
|
|
|
KMemoryPermission::None, KMemoryPermission::None,
|
|
|
|
|
AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask));
|
|
|
|
|
|
|
|
|
|
// Create an update allocator.
|
|
|
|
|
Result allocator_result{ResultSuccess};
|
|
|
|
@ -2662,18 +2680,17 @@ Result KPageTable::SetMemoryAttribute(KProcessAddress addr, size_t size, u32 mas
|
|
|
|
|
m_memory_block_slab_manager, num_allocator_blocks);
|
|
|
|
|
R_TRY(allocator_result);
|
|
|
|
|
|
|
|
|
|
// Determine the new attribute.
|
|
|
|
|
const KMemoryAttribute new_attr =
|
|
|
|
|
static_cast<KMemoryAttribute>(((old_attr & static_cast<KMemoryAttribute>(~mask)) |
|
|
|
|
|
static_cast<KMemoryAttribute>(attr & mask)));
|
|
|
|
|
|
|
|
|
|
// Perform operation.
|
|
|
|
|
this->Operate(addr, num_pages, old_perm, OperationType::ChangePermissionsAndRefresh);
|
|
|
|
|
// If we need to, perform a change attribute operation.
|
|
|
|
|
if (True(KMemoryAttribute::Uncached & static_cast<KMemoryAttribute>(mask))) {
|
|
|
|
|
// Perform operation.
|
|
|
|
|
R_TRY(this->Operate(addr, num_pages, old_perm,
|
|
|
|
|
OperationType::ChangePermissionsAndRefreshAndFlush, 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Update the blocks.
|
|
|
|
|
m_memory_block_manager.Update(std::addressof(allocator), addr, num_pages, old_state, old_perm,
|
|
|
|
|
new_attr, KMemoryBlockDisableMergeAttribute::None,
|
|
|
|
|
KMemoryBlockDisableMergeAttribute::None);
|
|
|
|
|
m_memory_block_manager.UpdateAttribute(std::addressof(allocator), addr, num_pages,
|
|
|
|
|
static_cast<KMemoryAttribute>(mask),
|
|
|
|
|
static_cast<KMemoryAttribute>(attr));
|
|
|
|
|
|
|
|
|
|
R_SUCCEED();
|
|
|
|
|
}
|
|
|
|
@ -3086,6 +3103,7 @@ Result KPageTable::Operate(KProcessAddress addr, size_t num_pages, KMemoryPermis
|
|
|
|
|
}
|
|
|
|
|
case OperationType::ChangePermissions:
|
|
|
|
|
case OperationType::ChangePermissionsAndRefresh:
|
|
|
|
|
case OperationType::ChangePermissionsAndRefreshAndFlush:
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
ASSERT(false);
|
|
|
|
|