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
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user