From 34b24a47e9515a6a80d1961fc2e83bcfc84b7889 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Fri, 14 Dec 2018 18:19:12 -0500
Subject: [PATCH] vm_manager: Add backing functionality for memory attributes

Adds the barebones enumeration constants and functions in place to
handle memory attributes, while also essentially leaving the attribute
itself non-functional.
---
 src/core/hle/kernel/vm_manager.cpp |  3 +-
 src/core/hle/kernel/vm_manager.h   | 83 ++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index d3b55a51ec..ea3f59935b 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -38,7 +38,7 @@ static const char* GetMemoryStateName(MemoryState state) {
 bool VirtualMemoryArea::CanBeMergedWith(const VirtualMemoryArea& next) const {
     ASSERT(base + size == next.base);
     if (permissions != next.permissions || meminfo_state != next.meminfo_state ||
-        type != next.type) {
+        attribute != next.attribute || type != next.type) {
         return false;
     }
     if (type == VMAType::AllocatedMemoryBlock &&
@@ -308,6 +308,7 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const {
 
     if (IsValidHandle(vma)) {
         memory_info.base_address = vma->second.base;
+        memory_info.attributes = ToSvcMemoryAttribute(vma->second.attribute);
         memory_info.permission = static_cast<u32>(vma->second.permissions);
         memory_info.size = vma->second.size;
         memory_info.state = ToSvcMemoryState(vma->second.meminfo_state);
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 10bacac3e4..99eeeffaaa 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -43,6 +43,88 @@ enum class VMAPermission : u8 {
     ReadWriteExecute = Read | Write | Execute,
 };
 
+constexpr VMAPermission operator|(VMAPermission lhs, VMAPermission rhs) {
+    return static_cast<VMAPermission>(u32(lhs) | u32(rhs));
+}
+
+constexpr VMAPermission operator&(VMAPermission lhs, VMAPermission rhs) {
+    return static_cast<VMAPermission>(u32(lhs) & u32(rhs));
+}
+
+constexpr VMAPermission operator^(VMAPermission lhs, VMAPermission rhs) {
+    return static_cast<VMAPermission>(u32(lhs) ^ u32(rhs));
+}
+
+constexpr VMAPermission operator~(VMAPermission permission) {
+    return static_cast<VMAPermission>(~u32(permission));
+}
+
+constexpr VMAPermission& operator|=(VMAPermission& lhs, VMAPermission rhs) {
+    lhs = lhs | rhs;
+    return lhs;
+}
+
+constexpr VMAPermission& operator&=(VMAPermission& lhs, VMAPermission rhs) {
+    lhs = lhs & rhs;
+    return lhs;
+}
+
+constexpr VMAPermission& operator^=(VMAPermission& lhs, VMAPermission rhs) {
+    lhs = lhs ^ rhs;
+    return lhs;
+}
+
+/// Attribute flags that can be applied to a VMA
+enum class MemoryAttribute : u32 {
+    Mask = 0xFF,
+
+    /// No particular qualities
+    None = 0,
+    /// Memory locked/borrowed for use. e.g. This would be used by transfer memory.
+    Locked = 1,
+    /// Memory locked for use by IPC-related internals.
+    LockedForIPC = 2,
+    /// Mapped as part of the device address space.
+    DeviceMapped = 4,
+    /// Uncached memory
+    Uncached = 8,
+};
+
+constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) {
+    return static_cast<MemoryAttribute>(u32(lhs) | u32(rhs));
+}
+
+constexpr MemoryAttribute operator&(MemoryAttribute lhs, MemoryAttribute rhs) {
+    return static_cast<MemoryAttribute>(u32(lhs) & u32(rhs));
+}
+
+constexpr MemoryAttribute operator^(MemoryAttribute lhs, MemoryAttribute rhs) {
+    return static_cast<MemoryAttribute>(u32(lhs) ^ u32(rhs));
+}
+
+constexpr MemoryAttribute operator~(MemoryAttribute attribute) {
+    return static_cast<MemoryAttribute>(~u32(attribute));
+}
+
+constexpr MemoryAttribute& operator|=(MemoryAttribute& lhs, MemoryAttribute rhs) {
+    lhs = lhs | rhs;
+    return lhs;
+}
+
+constexpr MemoryAttribute& operator&=(MemoryAttribute& lhs, MemoryAttribute rhs) {
+    lhs = lhs & rhs;
+    return lhs;
+}
+
+constexpr MemoryAttribute& operator^=(MemoryAttribute& lhs, MemoryAttribute rhs) {
+    lhs = lhs ^ rhs;
+    return lhs;
+}
+
+constexpr u32 ToSvcMemoryAttribute(MemoryAttribute attribute) {
+    return static_cast<u32>(attribute & MemoryAttribute::Mask);
+}
+
 // clang-format off
 /// Represents memory states and any relevant flags, as used by the kernel.
 /// svcQueryMemory interprets these by masking away all but the first eight
@@ -183,6 +265,7 @@ struct VirtualMemoryArea {
     VMAPermission permissions = VMAPermission::None;
     /// Tag returned by svcQueryMemory. Not otherwise used.
     MemoryState meminfo_state = MemoryState::Unmapped;
+    MemoryAttribute attribute = MemoryAttribute::None;
 
     // Settings for type = AllocatedMemoryBlock
     /// Memory block backing this VMA.