summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbunnei <bunneidev@gmail.com>2021-02-16 06:30:46 +0100
committerbunnei <bunneidev@gmail.com>2021-03-21 22:45:02 +0100
commit3fb64da452c4c7cbead05cc5489598b30f4c13f4 (patch)
tree7391c347418d53c8561b1fc48c1fd66c6bc266a0
parenthle: kernel: Migrate some code from Common::SpinLock to KSpinLock. (diff)
downloadyuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.tar
yuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.tar.gz
yuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.tar.bz2
yuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.tar.lz
yuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.tar.xz
yuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.tar.zst
yuzu-3fb64da452c4c7cbead05cc5489598b30f4c13f4.zip
-rw-r--r--src/core/hle/kernel/k_memory_region_type.h327
1 files changed, 327 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_memory_region_type.h b/src/core/hle/kernel/k_memory_region_type.h
index 6fb5abde9..243e2fd3d 100644
--- a/src/core/hle/kernel/k_memory_region_type.h
+++ b/src/core/hle/kernel/k_memory_region_type.h
@@ -4,6 +4,8 @@
#pragma once
+#include "common/bit_util.h"
+#include "common/common_funcs.h"
#include "common/common_types.h"
namespace Kernel {
@@ -18,5 +20,330 @@ enum class KMemoryRegionAttr : typename std::underlying_type<KMemoryRegionType>:
NoUserMap = 0x40000000,
LinearMapped = 0x80000000,
};
+DECLARE_ENUM_FLAG_OPERATORS(KMemoryRegionAttr);
+
+namespace impl {
+
+constexpr size_t BitsForDeriveSparse(size_t n) {
+ return n + 1;
+}
+
+constexpr size_t BitsForDeriveDense(size_t n) {
+ size_t low = 0, high = 1;
+ for (size_t i = 0; i < n - 1; ++i) {
+ if ((++low) == high) {
+ ++high;
+ low = 0;
+ }
+ }
+ return high + 1;
+}
+
+class KMemoryRegionTypeValue {
+private:
+ using ValueType = typename std::underlying_type<KMemoryRegionType>::type;
+
+private:
+ ValueType m_value{};
+ size_t m_next_bit{};
+ bool m_finalized{};
+ bool m_sparse_only{};
+ bool m_dense_only{};
+
+private:
+ constexpr KMemoryRegionTypeValue(ValueType v) : m_value(v) {}
+
+public:
+ constexpr KMemoryRegionTypeValue() = default;
+
+ constexpr operator KMemoryRegionType() const {
+ return static_cast<KMemoryRegionType>(m_value);
+ }
+
+ constexpr ValueType GetValue() const {
+ return m_value;
+ }
+
+ constexpr const KMemoryRegionTypeValue& Finalize() {
+ m_finalized = true;
+ return *this;
+ }
+
+ constexpr const KMemoryRegionTypeValue& SetSparseOnly() {
+ m_sparse_only = true;
+ return *this;
+ }
+
+ constexpr const KMemoryRegionTypeValue& SetDenseOnly() {
+ m_dense_only = true;
+ return *this;
+ }
+
+ constexpr KMemoryRegionTypeValue& SetAttribute(KMemoryRegionAttr attr) {
+ m_value |= static_cast<u32>(attr);
+ return *this;
+ }
+
+ constexpr KMemoryRegionTypeValue DeriveInitial(
+ size_t i, size_t next = Common::BitSize<ValueType>()) const {
+ KMemoryRegionTypeValue new_type = *this;
+ new_type.m_value = (ValueType{1} << i);
+ new_type.m_next_bit = next;
+ return new_type;
+ }
+
+ constexpr KMemoryRegionTypeValue DeriveAttribute(KMemoryRegionAttr attr) const {
+ KMemoryRegionTypeValue new_type = *this;
+ new_type.m_value |= static_cast<u32>(attr);
+ return new_type;
+ }
+
+ constexpr KMemoryRegionTypeValue DeriveTransition(size_t ofs = 0, size_t adv = 1) const {
+ KMemoryRegionTypeValue new_type = *this;
+ new_type.m_value |= (ValueType{1} << (m_next_bit + ofs));
+ new_type.m_next_bit += adv;
+ return new_type;
+ }
+
+ constexpr KMemoryRegionTypeValue DeriveSparse(size_t ofs, size_t n, size_t i) const {
+ KMemoryRegionTypeValue new_type = *this;
+ new_type.m_value |= (ValueType{1} << (m_next_bit + ofs));
+ new_type.m_value |= (ValueType{1} << (m_next_bit + ofs + 1 + i));
+ new_type.m_next_bit += ofs + n + 1;
+ return new_type;
+ }
+
+ constexpr KMemoryRegionTypeValue Derive(size_t n, size_t i) const {
+ size_t low = 0, high = 1;
+ for (size_t j = 0; j < i; ++j) {
+ if ((++low) == high) {
+ ++high;
+ low = 0;
+ }
+ }
+
+ KMemoryRegionTypeValue new_type = *this;
+ new_type.m_value |= (ValueType{1} << (m_next_bit + low));
+ new_type.m_value |= (ValueType{1} << (m_next_bit + high));
+ new_type.m_next_bit += BitsForDeriveDense(n);
+ return new_type;
+ }
+
+ constexpr KMemoryRegionTypeValue Advance(size_t n) const {
+ KMemoryRegionTypeValue new_type = *this;
+ new_type.m_next_bit += n;
+ return new_type;
+ }
+
+ constexpr bool IsAncestorOf(ValueType v) const {
+ return (m_value | v) == v;
+ }
+};
+
+} // namespace impl
+
+constexpr auto KMemoryRegionType_None = impl::KMemoryRegionTypeValue();
+constexpr auto KMemoryRegionType_Kernel = KMemoryRegionType_None.DeriveInitial(0, 2);
+constexpr auto KMemoryRegionType_Dram = KMemoryRegionType_None.DeriveInitial(1, 2);
+static_assert(KMemoryRegionType_Kernel.GetValue() == 0x1);
+static_assert(KMemoryRegionType_Dram.GetValue() == 0x2);
+
+constexpr auto KMemoryRegionType_DramKernelBase =
+ KMemoryRegionType_Dram.DeriveSparse(0, 3, 0)
+ .SetAttribute(KMemoryRegionAttr::NoUserMap)
+ .SetAttribute(KMemoryRegionAttr::CarveoutProtected);
+constexpr auto KMemoryRegionType_DramReservedBase = KMemoryRegionType_Dram.DeriveSparse(0, 3, 1);
+constexpr auto KMemoryRegionType_DramHeapBase =
+ KMemoryRegionType_Dram.DeriveSparse(0, 3, 2).SetAttribute(KMemoryRegionAttr::LinearMapped);
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramKernelBase.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0xE) | KMemoryRegionAttr::CarveoutProtected |
+ KMemoryRegionAttr::NoUserMap));
+static_assert(KMemoryRegionType_DramReservedBase.GetValue() == (0x16));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramHeapBase.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x26) | KMemoryRegionAttr::LinearMapped));
+
+constexpr auto KMemoryRegionType_DramKernelCode =
+ KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 0);
+constexpr auto KMemoryRegionType_DramKernelSlab =
+ KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 1);
+constexpr auto KMemoryRegionType_DramKernelPtHeap =
+ KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 2).SetAttribute(
+ KMemoryRegionAttr::LinearMapped);
+constexpr auto KMemoryRegionType_DramKernelInitPt =
+ KMemoryRegionType_DramKernelBase.DeriveSparse(0, 4, 3).SetAttribute(
+ KMemoryRegionAttr::LinearMapped);
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramKernelCode.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0xCE) | KMemoryRegionAttr::CarveoutProtected |
+ KMemoryRegionAttr::NoUserMap));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramKernelSlab.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x14E) | KMemoryRegionAttr::CarveoutProtected |
+ KMemoryRegionAttr::NoUserMap));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramKernelPtHeap.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x24E) | KMemoryRegionAttr::CarveoutProtected |
+ KMemoryRegionAttr::NoUserMap | KMemoryRegionAttr::LinearMapped));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramKernelInitPt.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x44E) | KMemoryRegionAttr::CarveoutProtected |
+ KMemoryRegionAttr::NoUserMap | KMemoryRegionAttr::LinearMapped));
+
+constexpr auto KMemoryRegionType_DramReservedEarly =
+ KMemoryRegionType_DramReservedBase.DeriveAttribute(KMemoryRegionAttr::NoUserMap);
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramReservedEarly.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x16) | KMemoryRegionAttr::NoUserMap));
+
+constexpr auto KMemoryRegionType_KernelTraceBuffer =
+ KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 0)
+ .SetAttribute(KMemoryRegionAttr::LinearMapped)
+ .SetAttribute(KMemoryRegionAttr::UserReadOnly);
+constexpr auto KMemoryRegionType_OnMemoryBootImage =
+ KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 1);
+constexpr auto KMemoryRegionType_DTB = KMemoryRegionType_DramReservedBase.DeriveSparse(0, 3, 2);
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_KernelTraceBuffer.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0xD6) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::UserReadOnly));
+static_assert(KMemoryRegionType_OnMemoryBootImage.GetValue() == 0x156);
+static_assert(KMemoryRegionType_DTB.GetValue() == 0x256);
+
+constexpr auto KMemoryRegionType_DramPoolPartition =
+ KMemoryRegionType_DramHeapBase.DeriveAttribute(KMemoryRegionAttr::NoUserMap);
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramPoolPartition.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x26) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap));
+
+constexpr auto KMemoryRegionType_DramPoolManagement =
+ KMemoryRegionType_DramPoolPartition.DeriveTransition(0, 2).DeriveTransition().SetAttribute(
+ KMemoryRegionAttr::CarveoutProtected);
+constexpr auto KMemoryRegionType_DramUserPool =
+ KMemoryRegionType_DramPoolPartition.DeriveTransition(1, 2).DeriveTransition();
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramPoolManagement.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x166) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap | KMemoryRegionAttr::CarveoutProtected));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramUserPool.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x1A6) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap));
+
+constexpr auto KMemoryRegionType_DramApplicationPool = KMemoryRegionType_DramUserPool.Derive(4, 0);
+constexpr auto KMemoryRegionType_DramAppletPool = KMemoryRegionType_DramUserPool.Derive(4, 1);
+constexpr auto KMemoryRegionType_DramSystemNonSecurePool =
+ KMemoryRegionType_DramUserPool.Derive(4, 2);
+constexpr auto KMemoryRegionType_DramSystemPool =
+ KMemoryRegionType_DramUserPool.Derive(4, 3).SetAttribute(KMemoryRegionAttr::CarveoutProtected);
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramApplicationPool.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x7A6) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramAppletPool.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0xBA6) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap));
+static_assert(
+ static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramSystemNonSecurePool.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0xDA6) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap));
+static_assert(static_cast<KMemoryRegionAttr>(KMemoryRegionType_DramSystemPool.GetValue()) ==
+ (static_cast<KMemoryRegionAttr>(0x13A6) | KMemoryRegionAttr::LinearMapped |
+ KMemoryRegionAttr::NoUserMap | KMemoryRegionAttr::CarveoutProtected));
+
+constexpr auto KMemoryRegionType_VirtualDramHeapBase = KMemoryRegionType_Dram.DeriveSparse(1, 3, 0);
+constexpr auto KMemoryRegionType_VirtualDramKernelPtHeap =
+ KMemoryRegionType_Dram.DeriveSparse(1, 3, 1);
+constexpr auto KMemoryRegionType_VirtualDramKernelTraceBuffer =
+ KMemoryRegionType_Dram.DeriveSparse(1, 3, 2);
+static_assert(KMemoryRegionType_VirtualDramHeapBase.GetValue() == 0x1A);
+static_assert(KMemoryRegionType_VirtualDramKernelPtHeap.GetValue() == 0x2A);
+static_assert(KMemoryRegionType_VirtualDramKernelTraceBuffer.GetValue() == 0x4A);
+
+constexpr auto KMemoryRegionType_VirtualDramKernelInitPt =
+ KMemoryRegionType_VirtualDramHeapBase.Derive(3, 0);
+constexpr auto KMemoryRegionType_VirtualDramPoolManagement =
+ KMemoryRegionType_VirtualDramHeapBase.Derive(3, 1);
+constexpr auto KMemoryRegionType_VirtualDramUserPool =
+ KMemoryRegionType_VirtualDramHeapBase.Derive(3, 2);
+static_assert(KMemoryRegionType_VirtualDramKernelInitPt.GetValue() == 0x19A);
+static_assert(KMemoryRegionType_VirtualDramPoolManagement.GetValue() == 0x29A);
+static_assert(KMemoryRegionType_VirtualDramUserPool.GetValue() == 0x31A);
+
+// NOTE: For unknown reason, the pools are derived out-of-order here. It's worth eventually trying
+// to understand why Nintendo made this choice.
+// UNUSED: .Derive(6, 0);
+// UNUSED: .Derive(6, 1);
+constexpr auto KMemoryRegionType_VirtualDramAppletPool =
+ KMemoryRegionType_VirtualDramUserPool.Derive(6, 2);
+constexpr auto KMemoryRegionType_VirtualDramApplicationPool =
+ KMemoryRegionType_VirtualDramUserPool.Derive(6, 3);
+constexpr auto KMemoryRegionType_VirtualDramSystemNonSecurePool =
+ KMemoryRegionType_VirtualDramUserPool.Derive(6, 4);
+constexpr auto KMemoryRegionType_VirtualDramSystemPool =
+ KMemoryRegionType_VirtualDramUserPool.Derive(6, 5);
+static_assert(KMemoryRegionType_VirtualDramAppletPool.GetValue() == 0x1B1A);
+static_assert(KMemoryRegionType_VirtualDramApplicationPool.GetValue() == 0x271A);
+static_assert(KMemoryRegionType_VirtualDramSystemNonSecurePool.GetValue() == 0x2B1A);
+static_assert(KMemoryRegionType_VirtualDramSystemPool.GetValue() == 0x331A);
+
+constexpr auto KMemoryRegionType_ArchDeviceBase =
+ KMemoryRegionType_Kernel.DeriveTransition(0, 1).SetSparseOnly();
+constexpr auto KMemoryRegionType_BoardDeviceBase =
+ KMemoryRegionType_Kernel.DeriveTransition(0, 2).SetDenseOnly();
+static_assert(KMemoryRegionType_ArchDeviceBase.GetValue() == 0x5);
+static_assert(KMemoryRegionType_BoardDeviceBase.GetValue() == 0x5);
+
+#if defined(ATMOSPHERE_ARCH_ARM64)
+#include <mesosphere/arch/arm64/kern_k_memory_region_device_types.inc>
+#elif defined(ATMOSPHERE_ARCH_ARM)
+#include <mesosphere/arch/arm/kern_k_memory_region_device_types.inc>
+#else
+// Default to no architecture devices.
+constexpr auto NumArchitectureDeviceRegions = 0;
+#endif
+static_assert(NumArchitectureDeviceRegions >= 0);
+
+#if defined(ATMOSPHERE_BOARD_NINTENDO_NX)
+#include <mesosphere/board/nintendo/nx/kern_k_memory_region_device_types.inc>
+#else
+// Default to no board devices.
+constexpr auto NumBoardDeviceRegions = 0;
+#endif
+static_assert(NumBoardDeviceRegions >= 0);
+
+constexpr auto KMemoryRegionType_KernelCode = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 0);
+constexpr auto KMemoryRegionType_KernelStack = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 1);
+constexpr auto KMemoryRegionType_KernelMisc = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 2);
+constexpr auto KMemoryRegionType_KernelSlab = KMemoryRegionType_Kernel.DeriveSparse(1, 4, 3);
+static_assert(KMemoryRegionType_KernelCode.GetValue() == 0x19);
+static_assert(KMemoryRegionType_KernelStack.GetValue() == 0x29);
+static_assert(KMemoryRegionType_KernelMisc.GetValue() == 0x49);
+static_assert(KMemoryRegionType_KernelSlab.GetValue() == 0x89);
+
+constexpr auto KMemoryRegionType_KernelMiscDerivedBase =
+ KMemoryRegionType_KernelMisc.DeriveTransition();
+static_assert(KMemoryRegionType_KernelMiscDerivedBase.GetValue() == 0x149);
+
+// UNUSED: .Derive(7, 0);
+constexpr auto KMemoryRegionType_KernelMiscMainStack =
+ KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 1);
+constexpr auto KMemoryRegionType_KernelMiscMappedDevice =
+ KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 2);
+constexpr auto KMemoryRegionType_KernelMiscExceptionStack =
+ KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 3);
+constexpr auto KMemoryRegionType_KernelMiscUnknownDebug =
+ KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 4);
+// UNUSED: .Derive(7, 5);
+constexpr auto KMemoryRegionType_KernelMiscIdleStack =
+ KMemoryRegionType_KernelMiscDerivedBase.Derive(7, 6);
+static_assert(KMemoryRegionType_KernelMiscMainStack.GetValue() == 0xB49);
+static_assert(KMemoryRegionType_KernelMiscMappedDevice.GetValue() == 0xD49);
+static_assert(KMemoryRegionType_KernelMiscExceptionStack.GetValue() == 0x1349);
+static_assert(KMemoryRegionType_KernelMiscUnknownDebug.GetValue() == 0x1549);
+static_assert(KMemoryRegionType_KernelMiscIdleStack.GetValue() == 0x2349);
+
+constexpr auto KMemoryRegionType_KernelTemp = KMemoryRegionType_Kernel.Advance(2).Derive(2, 0);
+static_assert(KMemoryRegionType_KernelTemp.GetValue() == 0x31);
+
+constexpr KMemoryRegionType GetTypeForVirtualLinearMapping(u32 type_id) {
+ if (KMemoryRegionType_KernelTraceBuffer.IsAncestorOf(type_id)) {
+ return KMemoryRegionType_VirtualDramKernelTraceBuffer;
+ } else if (KMemoryRegionType_DramKernelPtHeap.IsAncestorOf(type_id)) {
+ return KMemoryRegionType_VirtualDramKernelPtHeap;
+ } else {
+ return KMemoryRegionType_Dram;
+ }
+}
} // namespace Kernel