|
|
|
@ -3280,21 +3280,16 @@ Result KPageTable::CheckMemoryStateContiguous(size_t* out_blocks_needed, KProces |
|
|
|
|
|
|
|
Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, |
|
|
|
KMemoryAttribute* out_attr, size_t* out_blocks_needed, |
|
|
|
KProcessAddress addr, size_t size, KMemoryState state_mask, |
|
|
|
KMemoryBlockManager::const_iterator it, |
|
|
|
KProcessAddress last_addr, KMemoryState state_mask, |
|
|
|
KMemoryState state, KMemoryPermission perm_mask, |
|
|
|
KMemoryPermission perm, KMemoryAttribute attr_mask, |
|
|
|
KMemoryAttribute attr, KMemoryAttribute ignore_attr) const { |
|
|
|
ASSERT(this->IsLockedByCurrentThread()); |
|
|
|
|
|
|
|
// Get information about the first block.
|
|
|
|
const KProcessAddress last_addr = addr + size - 1; |
|
|
|
KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr); |
|
|
|
KMemoryInfo info = it->GetMemoryInfo(); |
|
|
|
|
|
|
|
// If the start address isn't aligned, we need a block.
|
|
|
|
const size_t blocks_for_start_align = |
|
|
|
(Common::AlignDown(GetInteger(addr), PageSize) != info.GetAddress()) ? 1 : 0; |
|
|
|
|
|
|
|
// Validate all blocks in the range have correct state.
|
|
|
|
const KMemoryState first_state = info.m_state; |
|
|
|
const KMemoryPermission first_perm = info.m_permission; |
|
|
|
@ -3320,10 +3315,6 @@ Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* |
|
|
|
info = it->GetMemoryInfo(); |
|
|
|
} |
|
|
|
|
|
|
|
// If the end address isn't aligned, we need a block.
|
|
|
|
const size_t blocks_for_end_align = |
|
|
|
(Common::AlignUp(GetInteger(addr) + size, PageSize) != info.GetEndAddress()) ? 1 : 0; |
|
|
|
|
|
|
|
// Write output state.
|
|
|
|
if (out_state != nullptr) { |
|
|
|
*out_state = first_state; |
|
|
|
@ -3334,9 +3325,39 @@ Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* |
|
|
|
if (out_attr != nullptr) { |
|
|
|
*out_attr = static_cast<KMemoryAttribute>(first_attr & ~ignore_attr); |
|
|
|
} |
|
|
|
|
|
|
|
// If the end address isn't aligned, we need a block.
|
|
|
|
if (out_blocks_needed != nullptr) { |
|
|
|
*out_blocks_needed = blocks_for_start_align + blocks_for_end_align; |
|
|
|
const size_t blocks_for_end_align = |
|
|
|
(Common::AlignDown(GetInteger(last_addr), PageSize) + PageSize != info.GetEndAddress()) |
|
|
|
? 1 |
|
|
|
: 0; |
|
|
|
*out_blocks_needed = blocks_for_end_align; |
|
|
|
} |
|
|
|
|
|
|
|
R_SUCCEED(); |
|
|
|
} |
|
|
|
|
|
|
|
Result KPageTable::CheckMemoryState(KMemoryState* out_state, KMemoryPermission* out_perm, |
|
|
|
KMemoryAttribute* out_attr, size_t* out_blocks_needed, |
|
|
|
KProcessAddress addr, size_t size, KMemoryState state_mask, |
|
|
|
KMemoryState state, KMemoryPermission perm_mask, |
|
|
|
KMemoryPermission perm, KMemoryAttribute attr_mask, |
|
|
|
KMemoryAttribute attr, KMemoryAttribute ignore_attr) const { |
|
|
|
ASSERT(this->IsLockedByCurrentThread()); |
|
|
|
|
|
|
|
// Check memory state.
|
|
|
|
const KProcessAddress last_addr = addr + size - 1; |
|
|
|
KMemoryBlockManager::const_iterator it = m_memory_block_manager.FindIterator(addr); |
|
|
|
R_TRY(this->CheckMemoryState(out_state, out_perm, out_attr, out_blocks_needed, it, last_addr, |
|
|
|
state_mask, state, perm_mask, perm, attr_mask, attr, ignore_attr)); |
|
|
|
|
|
|
|
// If the start address isn't aligned, we need a block.
|
|
|
|
if (out_blocks_needed != nullptr && |
|
|
|
Common::AlignDown(GetInteger(addr), PageSize) != it->GetAddress()) { |
|
|
|
++(*out_blocks_needed); |
|
|
|
} |
|
|
|
|
|
|
|
R_SUCCEED(); |
|
|
|
} |
|
|
|
|
|
|
|
|