فهرست منبع

kernel: memory: Add AddressSpaceInfo class, for managing the memory address space.

bunnei 6 سال پیش
والد
کامیت
14aa65ce00
3فایلهای تغییر یافته به همراه166 افزوده شده و 0 حذف شده
  1. 2 0
      src/core/CMakeLists.txt
  2. 113 0
      src/core/hle/kernel/memory/address_space_info.cpp
  3. 51 0
      src/core/hle/kernel/memory/address_space_info.h

+ 2 - 0
src/core/CMakeLists.txt

@@ -154,6 +154,8 @@ add_library(core STATIC
     hle/kernel/hle_ipc.h
     hle/kernel/kernel.cpp
     hle/kernel/kernel.h
+    hle/kernel/memory/address_space_info.cpp
+    hle/kernel/memory/address_space_info.h
     hle/kernel/mutex.cpp
     hle/kernel/mutex.h
     hle/kernel/object.cpp

+ 113 - 0
src/core/hle/kernel/memory/address_space_info.cpp

@@ -0,0 +1,113 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <array>
+
+#include "common/assert.h"
+#include "core/hle/kernel/memory/address_space_info.h"
+
+namespace Kernel::Memory {
+
+namespace {
+
+constexpr std::size_t Size_1_MB{0x100000};
+constexpr std::size_t Size_2_MB{2 * Size_1_MB};
+constexpr std::size_t Size_128_MB{128 * Size_1_MB};
+constexpr std::size_t Size_1_GB{0x40000000};
+constexpr std::size_t Size_2_GB{2 * Size_1_GB};
+constexpr std::size_t Size_4_GB{4 * Size_1_GB};
+constexpr std::size_t Size_6_GB{6 * Size_1_GB};
+constexpr std::size_t Size_64_GB{64 * Size_1_GB};
+constexpr std::size_t Size_512_GB{512 * Size_1_GB};
+constexpr u64 Invalid{std::numeric_limits<u64>::max()};
+
+// clang-format off
+constexpr std::array<AddressSpaceInfo, 13> AddressSpaceInfos{{
+   { 32 /*bit_width*/, Size_2_MB   /*addr*/, Size_1_GB   - Size_2_MB   /*size*/, AddressSpaceInfo::Type::Is32Bit,    },
+   { 32 /*bit_width*/, Size_1_GB   /*addr*/, Size_4_GB   - Size_1_GB   /*size*/, AddressSpaceInfo::Type::Small64Bit, },
+   { 32 /*bit_width*/, Invalid     /*addr*/, Size_1_GB                 /*size*/, AddressSpaceInfo::Type::Heap,       },
+   { 32 /*bit_width*/, Invalid     /*addr*/, Size_1_GB                 /*size*/, AddressSpaceInfo::Type::Alias,      },
+   { 36 /*bit_width*/, Size_128_MB /*addr*/, Size_2_GB   - Size_128_MB /*size*/, AddressSpaceInfo::Type::Is32Bit,    },
+   { 36 /*bit_width*/, Size_2_GB   /*addr*/, Size_64_GB  - Size_2_GB   /*size*/, AddressSpaceInfo::Type::Small64Bit, },
+   { 36 /*bit_width*/, Invalid     /*addr*/, Size_6_GB                 /*size*/, AddressSpaceInfo::Type::Heap,       },
+   { 36 /*bit_width*/, Invalid     /*addr*/, Size_6_GB                 /*size*/, AddressSpaceInfo::Type::Alias,      },
+   { 39 /*bit_width*/, Size_128_MB /*addr*/, Size_512_GB - Size_128_MB /*size*/, AddressSpaceInfo::Type::Large64Bit, },
+   { 39 /*bit_width*/, Invalid     /*addr*/, Size_64_GB                /*size*/, AddressSpaceInfo::Type::Is32Bit     },
+   { 39 /*bit_width*/, Invalid     /*addr*/, Size_6_GB                 /*size*/, AddressSpaceInfo::Type::Heap,       },
+   { 39 /*bit_width*/, Invalid     /*addr*/, Size_64_GB                /*size*/, AddressSpaceInfo::Type::Alias,      },
+   { 39 /*bit_width*/, Invalid     /*addr*/, Size_2_GB                 /*size*/, AddressSpaceInfo::Type::Stack,      },
+}};
+// clang-format on
+
+constexpr bool IsAllowedIndexForAddress(std::size_t index) {
+    return index < std::size(AddressSpaceInfos) && AddressSpaceInfos[index].GetAddress() != Invalid;
+}
+
+constexpr std::size_t
+    AddressSpaceIndices32Bit[static_cast<std::size_t>(AddressSpaceInfo::Type::Count)]{
+        0, 1, 0, 2, 0, 3,
+    };
+
+constexpr std::size_t
+    AddressSpaceIndices36Bit[static_cast<std::size_t>(AddressSpaceInfo::Type::Count)]{
+        4, 5, 4, 6, 4, 7,
+    };
+
+constexpr std::size_t
+    AddressSpaceIndices39Bit[static_cast<std::size_t>(AddressSpaceInfo::Type::Count)]{
+        9, 8, 8, 10, 12, 11,
+    };
+
+constexpr bool IsAllowed32BitType(AddressSpaceInfo::Type type) {
+    return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit &&
+           type != AddressSpaceInfo::Type::Stack;
+}
+
+constexpr bool IsAllowed36BitType(AddressSpaceInfo::Type type) {
+    return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Large64Bit &&
+           type != AddressSpaceInfo::Type::Stack;
+}
+
+constexpr bool IsAllowed39BitType(AddressSpaceInfo::Type type) {
+    return type < AddressSpaceInfo::Type::Count && type != AddressSpaceInfo::Type::Small64Bit;
+}
+
+} // namespace
+
+u64 AddressSpaceInfo::GetAddressSpaceStart(std::size_t width, AddressSpaceInfo::Type type) {
+    const std::size_t index{static_cast<std::size_t>(type)};
+    switch (width) {
+    case 32:
+        ASSERT(IsAllowed32BitType(type));
+        ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices32Bit[index]));
+        return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].GetAddress();
+    case 36:
+        ASSERT(IsAllowed36BitType(type));
+        ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices36Bit[index]));
+        return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].GetAddress();
+    case 39:
+        ASSERT(IsAllowed39BitType(type));
+        ASSERT(IsAllowedIndexForAddress(AddressSpaceIndices39Bit[index]));
+        return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].GetAddress();
+    }
+    UNREACHABLE();
+}
+
+std::size_t AddressSpaceInfo::GetAddressSpaceSize(std::size_t width, AddressSpaceInfo::Type type) {
+    const std::size_t index{static_cast<std::size_t>(type)};
+    switch (width) {
+    case 32:
+        ASSERT(IsAllowed32BitType(type));
+        return AddressSpaceInfos[AddressSpaceIndices32Bit[index]].GetSize();
+    case 36:
+        ASSERT(IsAllowed36BitType(type));
+        return AddressSpaceInfos[AddressSpaceIndices36Bit[index]].GetSize();
+    case 39:
+        ASSERT(IsAllowed39BitType(type));
+        return AddressSpaceInfos[AddressSpaceIndices39Bit[index]].GetSize();
+    }
+    UNREACHABLE();
+}
+
+} // namespace Kernel::Memory

+ 51 - 0
src/core/hle/kernel/memory/address_space_info.h

@@ -0,0 +1,51 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include "common/common_funcs.h"
+#include "common/common_types.h"
+
+namespace Kernel::Memory {
+
+class AddressSpaceInfo final : NonCopyable {
+public:
+    enum class Type : u32 {
+        Is32Bit = 0,
+        Small64Bit = 1,
+        Large64Bit = 2,
+        Heap = 3,
+        Stack = 4,
+        Alias = 5,
+        Count,
+    };
+
+private:
+    std::size_t bit_width{};
+    std::size_t addr{};
+    std::size_t size{};
+    Type type{};
+
+public:
+    static u64 GetAddressSpaceStart(std::size_t width, Type type);
+    static std::size_t GetAddressSpaceSize(std::size_t width, Type type);
+
+    constexpr AddressSpaceInfo(std::size_t bit_width, std::size_t addr, std::size_t size, Type type)
+        : bit_width{bit_width}, addr{addr}, size{size}, type{type} {}
+
+    constexpr std::size_t GetWidth() const {
+        return bit_width;
+    }
+    constexpr std::size_t GetAddress() const {
+        return addr;
+    }
+    constexpr std::size_t GetSize() const {
+        return size;
+    }
+    constexpr Type GetType() const {
+        return type;
+    }
+};
+
+} // namespace Kernel::Memory