summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar Lioncash2018-12-15 13:49:40 -0500
committerGravatar Lioncash2018-12-19 10:59:36 -0500
commit603cc72168b2165a0aa77a39a14ca63a879cf8f9 (patch)
treeb6e8f3b8a53739c2ffdc857017666ad7e3b53188 /src/core
parentvm_manager: Rename meminfo_state to state (diff)
downloadyuzu-603cc72168b2165a0aa77a39a14ca63a879cf8f9.tar.gz
yuzu-603cc72168b2165a0aa77a39a14ca63a879cf8f9.tar.xz
yuzu-603cc72168b2165a0aa77a39a14ca63a879cf8f9.zip
vm_manager: Add member function for checking a memory range adheres to certain attributes, permissions and states
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/vm_manager.cpp60
-rw-r--r--src/core/hle/kernel/vm_manager.h40
2 files changed, 100 insertions, 0 deletions
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 252f92df2..02504d750 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -592,6 +592,66 @@ void VMManager::ClearPageTable() {
592 Memory::PageType::Unmapped); 592 Memory::PageType::Unmapped);
593} 593}
594 594
595VMManager::CheckResults VMManager::CheckRangeState(VAddr address, u64 size, MemoryState state_mask,
596 MemoryState state, VMAPermission permission_mask,
597 VMAPermission permissions,
598 MemoryAttribute attribute_mask,
599 MemoryAttribute attribute,
600 MemoryAttribute ignore_mask) const {
601 auto iter = FindVMA(address);
602
603 // If we don't have a valid VMA handle at this point, then it means this is
604 // being called with an address outside of the address space, which is definitely
605 // indicative of a bug, as this function only operates on mapped memory regions.
606 DEBUG_ASSERT(IsValidHandle(iter));
607
608 const VAddr end_address = address + size - 1;
609 const MemoryAttribute initial_attributes = iter->second.attribute;
610 const VMAPermission initial_permissions = iter->second.permissions;
611 const MemoryState initial_state = iter->second.state;
612
613 while (true) {
614 // The iterator should be valid throughout the traversal. Hitting the end of
615 // the mapped VMA regions is unquestionably indicative of a bug.
616 DEBUG_ASSERT(IsValidHandle(iter));
617
618 const auto& vma = iter->second;
619
620 if (vma.state != initial_state) {
621 return ERR_INVALID_ADDRESS_STATE;
622 }
623
624 if ((vma.state & state_mask) != state) {
625 return ERR_INVALID_ADDRESS_STATE;
626 }
627
628 if (vma.permissions != initial_permissions) {
629 return ERR_INVALID_ADDRESS_STATE;
630 }
631
632 if ((vma.permissions & permission_mask) != permissions) {
633 return ERR_INVALID_ADDRESS_STATE;
634 }
635
636 if ((vma.attribute | ignore_mask) != (initial_attributes | ignore_mask)) {
637 return ERR_INVALID_ADDRESS_STATE;
638 }
639
640 if ((vma.attribute & attribute_mask) != attribute) {
641 return ERR_INVALID_ADDRESS_STATE;
642 }
643
644 if (end_address <= vma.EndAddress()) {
645 break;
646 }
647
648 ++iter;
649 }
650
651 return MakeResult(
652 std::make_tuple(initial_state, initial_permissions, initial_attributes & ~ignore_mask));
653}
654
595u64 VMManager::GetTotalMemoryUsage() const { 655u64 VMManager::GetTotalMemoryUsage() const {
596 LOG_WARNING(Kernel, "(STUBBED) called"); 656 LOG_WARNING(Kernel, "(STUBBED) called");
597 return 0xF8000000; 657 return 0xF8000000;
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index e2614cd4c..9fa9a18fb 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -6,6 +6,7 @@
6 6
7#include <map> 7#include <map>
8#include <memory> 8#include <memory>
9#include <tuple>
9#include <vector> 10#include <vector>
10#include "common/common_types.h" 11#include "common/common_types.h"
11#include "core/hle/result.h" 12#include "core/hle/result.h"
@@ -256,6 +257,16 @@ struct PageInfo {
256 * also backed by a single host memory allocation. 257 * also backed by a single host memory allocation.
257 */ 258 */
258struct VirtualMemoryArea { 259struct VirtualMemoryArea {
260 /// Gets the starting (base) address of this VMA.
261 VAddr StartAddress() const {
262 return base;
263 }
264
265 /// Gets the ending address of this VMA.
266 VAddr EndAddress() const {
267 return base + size - 1;
268 }
269
259 /// Virtual base address of the region. 270 /// Virtual base address of the region.
260 VAddr base = 0; 271 VAddr base = 0;
261 /// Size of the region. 272 /// Size of the region.
@@ -517,6 +528,35 @@ private:
517 /// Clears out the page table 528 /// Clears out the page table
518 void ClearPageTable(); 529 void ClearPageTable();
519 530
531 using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
532
533 /// Checks if an address range adheres to the specified states provided.
534 ///
535 /// @param address The starting address of the address range.
536 /// @param size The size of the address range.
537 /// @param state_mask The memory state mask.
538 /// @param state The state to compare the individual VMA states against,
539 /// which is done in the form of: (vma.state & state_mask) != state.
540 /// @param permission_mask The memory permissions mask.
541 /// @param permissions The permission to compare the individual VMA permissions against,
542 /// which is done in the form of:
543 /// (vma.permission & permission_mask) != permission.
544 /// @param attribute_mask The memory attribute mask.
545 /// @param attribute The memory attributes to compare the individual VMA attributes
546 /// against, which is done in the form of:
547 /// (vma.attributes & attribute_mask) != attribute.
548 /// @param ignore_mask The memory attributes to ignore during the check.
549 ///
550 /// @returns If successful, returns a tuple containing the memory attributes
551 /// (with ignored bits specified by ignore_mask unset), memory permissions, and
552 /// memory state across the memory range.
553 /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
554 ///
555 CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
556 VMAPermission permission_mask, VMAPermission permissions,
557 MemoryAttribute attribute_mask, MemoryAttribute attribute,
558 MemoryAttribute ignore_mask) const;
559
520 /** 560 /**
521 * A map covering the entirety of the managed address space, keyed by the `base` field of each 561 * A map covering the entirety of the managed address space, keyed by the `base` field of each
522 * VMA. It must always be modified by splitting or merging VMAs, so that the invariant 562 * VMA. It must always be modified by splitting or merging VMAs, so that the invariant