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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
    LOG_WARNING(Kernel, "(STUBBED) called");
 | 
			
		||||
    return 0xF8000000;
 | 
			
		||||
 | 
			
		||||
@ -6,6 +6,7 @@
 | 
			
		||||
 | 
			
		||||
#include <map>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <tuple>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include "common/common_types.h"
 | 
			
		||||
#include "core/hle/result.h"
 | 
			
		||||
@ -256,6 +257,16 @@ struct PageInfo {
 | 
			
		||||
 * also backed by a single host memory allocation.
 | 
			
		||||
 */
 | 
			
		||||
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.
 | 
			
		||||
    VAddr base = 0;
 | 
			
		||||
    /// Size of the region.
 | 
			
		||||
@ -517,6 +528,35 @@ private:
 | 
			
		||||
    /// Clears out the page table
 | 
			
		||||
    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
 | 
			
		||||
     * VMA. It must always be modified by splitting or merging VMAs, so that the invariant
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user