Memory: Added a function to change the memory state of an address range.

This will be useful when implementing memory aliasing operations.
This commit is contained in:
Subv 2017-11-19 11:24:23 -05:00
parent 44d07574b1
commit e4f35f70ac
2 changed files with 49 additions and 1 deletions

View file

@ -129,6 +129,39 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMMIO(VAddr target, PAddr paddr, u3
return MakeResult<VMAHandle>(MergeAdjacent(vma_handle)); return MakeResult<VMAHandle>(MergeAdjacent(vma_handle));
} }
ResultCode VMManager::ChangeMemoryState(VAddr target, u32 size, MemoryState expected_state,
VMAPermission expected_perms, MemoryState new_state,
VMAPermission new_perms) {
VAddr target_end = target + size;
VMAIter begin_vma = StripIterConstness(FindVMA(target));
VMAIter i_end = vma_map.lower_bound(target_end);
if (begin_vma == vma_map.end())
return ERR_INVALID_ADDRESS;
for (auto i = begin_vma; i != i_end; ++i) {
auto& vma = i->second;
if (vma.meminfo_state != expected_state) {
return ERR_INVALID_ADDRESS_STATE;
}
u32 perms = static_cast<u32>(expected_perms);
if ((static_cast<u32>(vma.permissions) & perms) != perms) {
return ERR_INVALID_ADDRESS_STATE;
}
}
CASCADE_RESULT(auto vma, CarveVMARange(target, size));
ASSERT(vma->second.size == size);
vma->second.permissions = new_perms;
vma->second.meminfo_state = new_state;
UpdatePageTableForVMA(vma->second);
MergeAdjacent(vma);
return RESULT_SUCCESS;
}
VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) { VMManager::VMAIter VMManager::Unmap(VMAIter vma_handle) {
VirtualMemoryArea& vma = vma_handle->second; VirtualMemoryArea& vma = vma_handle->second;
vma.type = VMAType::Free; vma.type = VMAType::Free;

View file

@ -166,6 +166,21 @@ public:
ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state, ResultVal<VMAHandle> MapMMIO(VAddr target, PAddr paddr, u32 size, MemoryState state,
Memory::MMIORegionPointer mmio_handler); Memory::MMIORegionPointer mmio_handler);
/**
* Updates the memory state and permissions of the specified range. The range's original memory
* state and permissions must match the `expected` parameters.
*
* @param target The guest address of the beginning of the range.
* @param size The size of the range
* @param expected_state Expected MemoryState of the range.
* @param expected_perms Expected VMAPermission of the range.
* @param new_state New MemoryState for the range.
* @param new_perms New VMAPermission for the range.
*/
ResultCode ChangeMemoryState(VAddr target, u32 size, MemoryState expected_state,
VMAPermission expected_perms, MemoryState new_state,
VMAPermission new_perms);
/// Unmaps a range of addresses, splitting VMAs as necessary. /// Unmaps a range of addresses, splitting VMAs as necessary.
ResultCode UnmapRange(VAddr target, u32 size); ResultCode UnmapRange(VAddr target, u32 size);
@ -224,4 +239,4 @@ private:
/// Updates the pages corresponding to this VMA so they match the VMA's attributes. /// Updates the pages corresponding to this VMA so they match the VMA's attributes.
void UpdatePageTableForVMA(const VirtualMemoryArea& vma); void UpdatePageTableForVMA(const VirtualMemoryArea& vma);
}; };
} } // namespace Kernel