vm_manager: Add member function for checking a memory range adheres to certain attributes, permissions and states
This commit is contained in:
parent
4dc8a7da3f
commit
603cc72168
|
@ -592,6 +592,66 @@ void VMManager::ClearPageTable() {
|
||||||
Memory::PageType::Unmapped);
|
Memory::PageType::Unmapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VMManager::CheckResults VMManager::CheckRangeState(VAddr address, u64 size, MemoryState state_mask,
|
||||||
|
MemoryState state, VMAPermission permission_mask,
|
||||||
|
VMAPermission permissions,
|
||||||
|
MemoryAttribute attribute_mask,
|
||||||
|
MemoryAttribute attribute,
|
||||||
|
MemoryAttribute ignore_mask) const {
|
||||||
|
auto iter = FindVMA(address);
|
||||||
|
|
||||||
|
// If we don't have a valid VMA handle at this point, then it means this is
|
||||||
|
// being called with an address outside of the address space, which is definitely
|
||||||
|
// indicative of a bug, as this function only operates on mapped memory regions.
|
||||||
|
DEBUG_ASSERT(IsValidHandle(iter));
|
||||||
|
|
||||||
|
const VAddr end_address = address + size - 1;
|
||||||
|
const MemoryAttribute initial_attributes = iter->second.attribute;
|
||||||
|
const VMAPermission initial_permissions = iter->second.permissions;
|
||||||
|
const MemoryState initial_state = iter->second.state;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// The iterator should be valid throughout the traversal. Hitting the end of
|
||||||
|
// the mapped VMA regions is unquestionably indicative of a bug.
|
||||||
|
DEBUG_ASSERT(IsValidHandle(iter));
|
||||||
|
|
||||||
|
const auto& vma = iter->second;
|
||||||
|
|
||||||
|
if (vma.state != initial_state) {
|
||||||
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vma.state & state_mask) != state) {
|
||||||
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vma.permissions != initial_permissions) {
|
||||||
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vma.permissions & permission_mask) != permissions) {
|
||||||
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vma.attribute | ignore_mask) != (initial_attributes | ignore_mask)) {
|
||||||
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((vma.attribute & attribute_mask) != attribute) {
|
||||||
|
return ERR_INVALID_ADDRESS_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (end_address <= vma.EndAddress()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
++iter;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MakeResult(
|
||||||
|
std::make_tuple(initial_state, initial_permissions, initial_attributes & ~ignore_mask));
|
||||||
|
}
|
||||||
|
|
||||||
u64 VMManager::GetTotalMemoryUsage() const {
|
u64 VMManager::GetTotalMemoryUsage() const {
|
||||||
LOG_WARNING(Kernel, "(STUBBED) called");
|
LOG_WARNING(Kernel, "(STUBBED) called");
|
||||||
return 0xF8000000;
|
return 0xF8000000;
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <tuple>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
@ -256,6 +257,16 @@ struct PageInfo {
|
||||||
* also backed by a single host memory allocation.
|
* also backed by a single host memory allocation.
|
||||||
*/
|
*/
|
||||||
struct VirtualMemoryArea {
|
struct VirtualMemoryArea {
|
||||||
|
/// Gets the starting (base) address of this VMA.
|
||||||
|
VAddr StartAddress() const {
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the ending address of this VMA.
|
||||||
|
VAddr EndAddress() const {
|
||||||
|
return base + size - 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// Virtual base address of the region.
|
/// Virtual base address of the region.
|
||||||
VAddr base = 0;
|
VAddr base = 0;
|
||||||
/// Size of the region.
|
/// Size of the region.
|
||||||
|
@ -517,6 +528,35 @@ private:
|
||||||
/// Clears out the page table
|
/// Clears out the page table
|
||||||
void ClearPageTable();
|
void ClearPageTable();
|
||||||
|
|
||||||
|
using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
|
||||||
|
|
||||||
|
/// Checks if an address range adheres to the specified states provided.
|
||||||
|
///
|
||||||
|
/// @param address The starting address of the address range.
|
||||||
|
/// @param size The size of the address range.
|
||||||
|
/// @param state_mask The memory state mask.
|
||||||
|
/// @param state The state to compare the individual VMA states against,
|
||||||
|
/// which is done in the form of: (vma.state & state_mask) != state.
|
||||||
|
/// @param permission_mask The memory permissions mask.
|
||||||
|
/// @param permissions The permission to compare the individual VMA permissions against,
|
||||||
|
/// which is done in the form of:
|
||||||
|
/// (vma.permission & permission_mask) != permission.
|
||||||
|
/// @param attribute_mask The memory attribute mask.
|
||||||
|
/// @param attribute The memory attributes to compare the individual VMA attributes
|
||||||
|
/// against, which is done in the form of:
|
||||||
|
/// (vma.attributes & attribute_mask) != attribute.
|
||||||
|
/// @param ignore_mask The memory attributes to ignore during the check.
|
||||||
|
///
|
||||||
|
/// @returns If successful, returns a tuple containing the memory attributes
|
||||||
|
/// (with ignored bits specified by ignore_mask unset), memory permissions, and
|
||||||
|
/// memory state across the memory range.
|
||||||
|
/// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
|
||||||
|
///
|
||||||
|
CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
|
||||||
|
VMAPermission permission_mask, VMAPermission permissions,
|
||||||
|
MemoryAttribute attribute_mask, MemoryAttribute attribute,
|
||||||
|
MemoryAttribute ignore_mask) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map covering the entirety of the managed address space, keyed by the `base` field of each
|
* A map covering the entirety of the managed address space, keyed by the `base` field of each
|
||||||
* VMA. It must always be modified by splitting or merging VMAs, so that the invariant
|
* VMA. It must always be modified by splitting or merging VMAs, so that the invariant
|
||||||
|
|
Reference in New Issue