Răsfoiți Sursa

hle: kernel: Migrate KTransferMemory to KAutoObject.

bunnei 5 ani în urmă
părinte
comite
c7d8b7421c

+ 2 - 2
src/core/CMakeLists.txt

@@ -221,6 +221,8 @@ add_library(core STATIC
     hle/kernel/k_thread.h
     hle/kernel/k_thread_queue.h
     hle/kernel/k_trace.h
+    hle/kernel/k_transfer_memory.cpp
+    hle/kernel/k_transfer_memory.h
     hle/kernel/k_writable_event.cpp
     hle/kernel/k_writable_event.h
     hle/kernel/kernel.cpp
@@ -247,8 +249,6 @@ add_library(core STATIC
     hle/kernel/svc_wrap.h
     hle/kernel/time_manager.cpp
     hle/kernel/time_manager.h
-    hle/kernel/transfer_memory.cpp
-    hle/kernel/transfer_memory.h
     hle/lock.cpp
     hle/lock.h
     hle/result.h

+ 2 - 1
src/core/hle/kernel/handle_table.cpp

@@ -59,7 +59,8 @@ ResultVal<Handle> HandleTable::Create(Object* obj) {
     case HandleType::WritableEvent:
     case HandleType::ClientSession:
     case HandleType::ServerSession:
-    case HandleType::Session: {
+    case HandleType::Session:
+    case HandleType::TransferMemory: {
         Handle handle{};
         Add(&handle, reinterpret_cast<KAutoObject*>(obj), {});
         return MakeResult<Handle>(handle);

+ 2 - 0
src/core/hle/kernel/init/init_slab_setup.cpp

@@ -14,6 +14,7 @@
 #include "core/hle/kernel/k_memory_manager.h"
 #include "core/hle/kernel/k_session.h"
 #include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/kernel/k_transfer_memory.h"
 #include "core/hle/kernel/k_system_control.h"
 #include "core/hle/kernel/k_thread.h"
 #include "core/hle/kernel/memory_types.h"
@@ -28,6 +29,7 @@ namespace Kernel::Init {
     HANDLER(Process, (SLAB_COUNT(Process)), ##__VA_ARGS__)                                         \
     HANDLER(KThread, (SLAB_COUNT(KThread)), ##__VA_ARGS__)                                         \
     HANDLER(KEvent, (SLAB_COUNT(KEvent)), ##__VA_ARGS__)                                           \
+    HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__)                         \
     HANDLER(KSharedMemory, (SLAB_COUNT(KSharedMemory)), ##__VA_ARGS__)                             \
     HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__)
 

+ 2 - 2
src/core/hle/kernel/k_page_table.h

@@ -216,8 +216,6 @@ public:
     constexpr PAddr GetPhysicalAddr(VAddr addr) {
         return page_table_impl.backing_addr[addr >> PageBits] + addr;
     }
-
-private:
     constexpr bool Contains(VAddr addr) const {
         return address_space_start <= addr && addr <= address_space_end - 1;
     }
@@ -225,6 +223,8 @@ private:
         return address_space_start <= addr && addr < addr + size &&
                addr + size - 1 <= address_space_end - 1;
     }
+
+private:
     constexpr bool IsKernel() const {
         return is_kernel;
     }

+ 45 - 0
src/core/hle/kernel/k_transfer_memory.cpp

@@ -0,0 +1,45 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include "core/hle/kernel/k_resource_limit.h"
+#include "core/hle/kernel/k_transfer_memory.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/process.h"
+
+namespace Kernel {
+
+KTransferMemory::KTransferMemory(KernelCore& kernel)
+    : KAutoObjectWithSlabHeapAndContainer{kernel} {}
+
+KTransferMemory::~KTransferMemory() = default;
+
+ResultCode KTransferMemory::Initialize(VAddr address_, std::size_t size_,
+                                       Svc::MemoryPermission owner_perm_) {
+    // Set members.
+    owner = kernel.CurrentProcess();
+
+    // TODO(bunnei): Lock for transfer memory
+
+    // Set remaining tracking members.
+    owner->Open();
+    owner_perm = owner_perm_;
+    address = address_;
+    size = size_;
+    is_initialized = true;
+
+    return RESULT_SUCCESS;
+}
+
+void KTransferMemory::Finalize() {
+    // Perform inherited finalization.
+    KAutoObjectWithSlabHeapAndContainer<KTransferMemory, KAutoObjectWithList>::Finalize();
+}
+
+void KTransferMemory::PostDestroy(uintptr_t arg) {
+    Process* owner = reinterpret_cast<Process*>(arg);
+    owner->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1);
+    owner->Close();
+}
+
+} // namespace Kernel

+ 82 - 0
src/core/hle/kernel/k_transfer_memory.h

@@ -0,0 +1,82 @@
+// Copyright 2021 yuzu emulator team
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+
+#include "core/hle/kernel/slab_helpers.h"
+#include "core/hle/kernel/svc_types.h"
+#include "core/hle/result.h"
+
+union ResultCode;
+
+namespace Core::Memory {
+class Memory;
+}
+
+namespace Kernel {
+
+class KernelCore;
+class Process;
+
+class KTransferMemory final
+    : public KAutoObjectWithSlabHeapAndContainer<KTransferMemory, KAutoObjectWithList> {
+    KERNEL_AUTOOBJECT_TRAITS(KTransferMemory, KAutoObject);
+
+public:
+    explicit KTransferMemory(KernelCore& kernel);
+    ~KTransferMemory() override;
+
+    static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
+
+    ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
+
+    virtual void Finalize() override;
+
+    virtual bool IsInitialized() const override {
+        return is_initialized;
+    }
+
+    virtual uintptr_t GetPostDestroyArgument() const override {
+        return reinterpret_cast<uintptr_t>(owner);
+    }
+
+    static void PostDestroy(uintptr_t arg);
+
+    Process* GetOwner() const {
+        return owner;
+    }
+
+    VAddr GetSourceAddress() const {
+        return address;
+    }
+
+    size_t GetSize() const {
+        return is_initialized ? size * PageSize : 0;
+    }
+
+    // DEPRECATED
+
+    std::string GetTypeName() const override {
+        return "TransferMemory";
+    }
+
+    std::string GetName() const override {
+        return GetTypeName();
+    }
+
+    HandleType GetHandleType() const override {
+        return HANDLE_TYPE;
+    }
+
+private:
+    Process* owner{};
+    VAddr address{};
+    Svc::MemoryPermission owner_perm{};
+    size_t size{};
+    bool is_initialized{};
+};
+
+} // namespace Kernel

+ 4 - 0
src/core/hle/kernel/kernel.h

@@ -42,6 +42,7 @@ class KScheduler;
 class KSession;
 class KSharedMemory;
 class KThread;
+class KTransferMemory;
 class KWritableEvent;
 class PhysicalCore;
 class Process;
@@ -278,6 +279,8 @@ public:
             return slab_heap_container->client_session;
         } else if constexpr (std::is_same_v<T, KSession>) {
             return slab_heap_container->session;
+        } else if constexpr (std::is_same_v<T, KTransferMemory>) {
+            return slab_heap_container->transfer_memory;
         }
     }
 
@@ -320,6 +323,7 @@ private:
         KSlabHeap<KWritableEvent> writeable_event;
         KSlabHeap<KClientSession> client_session;
         KSlabHeap<KSession> session;
+        KSlabHeap<KTransferMemory> transfer_memory;
     };
 
     std::unique_ptr<SlabHeapContainer> slab_heap_container;

+ 48 - 45
src/core/hle/kernel/svc.cpp

@@ -38,6 +38,7 @@
 #include "core/hle/kernel/k_shared_memory.h"
 #include "core/hle/kernel/k_synchronization_object.h"
 #include "core/hle/kernel/k_thread.h"
+#include "core/hle/kernel/k_transfer_memory.h"
 #include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/physical_core.h"
@@ -47,7 +48,6 @@
 #include "core/hle/kernel/svc_types.h"
 #include "core/hle/kernel/svc_wrap.h"
 #include "core/hle/kernel/time_manager.h"
-#include "core/hle/kernel/transfer_memory.h"
 #include "core/hle/lock.h"
 #include "core/hle/result.h"
 #include "core/hle/service/service.h"
@@ -1868,65 +1868,68 @@ static ResultCode ResetSignal32(Core::System& system, Handle handle) {
     return ResetSignal(system, handle);
 }
 
-/// Creates a TransferMemory object
-static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size,
-                                       u32 permissions) {
-    std::lock_guard lock{HLE::g_hle_lock};
-    LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size,
-              permissions);
-
-    if (!Common::Is4KBAligned(addr)) {
-        LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr);
-        return ResultInvalidAddress;
+static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) {
+    switch (perm) {
+    case MemoryPermission::None:
+    case MemoryPermission::Read:
+    case MemoryPermission::ReadWrite:
+        return true;
+    default:
+        return false;
     }
+}
 
-    if (!Common::Is4KBAligned(size) || size == 0) {
-        LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size);
-        return ResultInvalidAddress;
-    }
+/// Creates a TransferMemory object
+static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size,
+                                       MemoryPermission map_perm) {
+    auto& kernel = system.Kernel();
 
-    if (!IsValidAddressRange(addr, size)) {
-        LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})",
-                  addr, size);
-        return ResultInvalidCurrentMemory;
-    }
+    // Validate the size.
+    R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
+    R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
+    R_UNLESS(size > 0, ResultInvalidSize);
+    R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
 
-    const auto perms{static_cast<MemoryPermission>(permissions)};
-    if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) {
-        LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
-                  permissions);
-        return ResultInvalidNewMemoryPermission;
-    }
+    // Validate the permissions.
+    R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission);
+
+    // Get the current process and handle table.
+    auto& process = *kernel.CurrentProcess();
+    auto& handle_table = process.GetHandleTable();
 
-    auto& kernel = system.Kernel();
     // Reserve a new transfer memory from the process resource limit.
     KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(),
                                                  LimitableResource::TransferMemory);
-    if (!trmem_reservation.Succeeded()) {
-        LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
-        return ResultLimitReached;
-    }
-    auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size,
-                                                      static_cast<KMemoryPermission>(perms));
+    R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached);
 
-    if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
-        return reserve_result;
-    }
+    // Create the transfer memory.
+    KTransferMemory* trmem = KTransferMemory::Create(kernel);
+    R_UNLESS(trmem != nullptr, ResultOutOfResource);
 
-    auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
-    const auto result{handle_table.Create(transfer_mem_handle.get())};
-    if (result.Failed()) {
-        return result.Code();
-    }
+    // Ensure the only reference is in the handle table when we're done.
+    SCOPE_EXIT({ trmem->Close(); });
+
+    // Ensure that the region is in range.
+    R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory);
+
+    // Initialize the transfer memory.
+    R_TRY(trmem->Initialize(address, size, map_perm));
+
+    // Commit the reservation.
     trmem_reservation.Commit();
 
-    *handle = *result;
+    // Register the transfer memory.
+    KTransferMemory::Register(kernel, trmem);
+
+    // Add the transfer memory to the handle table.
+    R_TRY(handle_table.Add(out, trmem));
+
     return RESULT_SUCCESS;
 }
 
-static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size,
-                                         u32 permissions) {
-    return CreateTransferMemory(system, handle, addr, size, permissions);
+static ResultCode CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size,
+                                         MemoryPermission map_perm) {
+    return CreateTransferMemory(system, out, address, size, map_perm);
 }
 
 static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,

+ 7 - 5
src/core/hle/kernel/svc_wrap.h

@@ -273,11 +273,12 @@ void SvcWrap64(Core::System& system) {
     FuncReturn(system, retval);
 }
 
-template <ResultCode func(Core::System&, u32*, u64, u64, u32)>
+// Used by CreateTransferMemory
+template <ResultCode func(Core::System&, Handle*, u64, u64, Svc::MemoryPermission)>
 void SvcWrap64(Core::System& system) {
     u32 param_1 = 0;
     const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
-                            static_cast<u32>(Param(system, 3)))
+                            static_cast<Svc::MemoryPermission>(Param(system, 3)))
                            .raw;
 
     system.CurrentArmInterface().SetReg(1, param_1);
@@ -586,11 +587,12 @@ void SvcWrap32(Core::System& system) {
 }
 
 // Used by CreateTransferMemory32
-template <ResultCode func(Core::System&, Handle*, u32, u32, u32)>
+template <ResultCode func(Core::System&, Handle*, u32, u32, Svc::MemoryPermission)>
 void SvcWrap32(Core::System& system) {
     Handle handle = 0;
-    const u32 retval =
-        func(system, &handle, Param32(system, 1), Param32(system, 2), Param32(system, 3)).raw;
+    const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2),
+                            static_cast<Svc::MemoryPermission>(Param32(system, 3)))
+                           .raw;
     system.CurrentArmInterface().SetReg(1, handle);
     FuncReturn(system, retval);
 }

+ 5 - 4
src/core/hle/service/am/am.cpp

@@ -16,10 +16,10 @@
 #include "core/hle/ipc_helpers.h"
 #include "core/hle/kernel/k_event.h"
 #include "core/hle/kernel/k_readable_event.h"
+#include "core/hle/kernel/k_transfer_memory.h"
 #include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
 #include "core/hle/kernel/process.h"
-#include "core/hle/kernel/transfer_memory.h"
 #include "core/hle/service/acc/profile_manager.h"
 #include "core/hle/service/am/am.h"
 #include "core/hle/service/am/applet_ae.h"
@@ -42,6 +42,7 @@
 #include "core/hle/service/set/set.h"
 #include "core/hle/service/sm/sm.h"
 #include "core/hle/service/vi/vi.h"
+#include "core/memory.h"
 
 namespace Service::AM {
 
@@ -1248,16 +1249,16 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx)
     }
 
     auto transfer_mem =
-        system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(handle);
+        system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
 
-    if (transfer_mem == nullptr) {
+    if (transfer_mem.IsNull()) {
         LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_UNKNOWN);
         return;
     }
 
-    const u8* const mem_begin = transfer_mem->GetPointer();
+    const u8* const mem_begin = system.Memory().GetPointer(transfer_mem->GetSourceAddress());
     const u8* const mem_end = mem_begin + transfer_mem->GetSize();
     std::vector<u8> memory{mem_begin, mem_end};
 

+ 1 - 1
src/core/hle/service/am/am.h

@@ -13,7 +13,7 @@
 
 namespace Kernel {
 class KernelCore;
-class TransferMemory;
+class KTransferMemory;
 } // namespace Kernel
 
 namespace Service::NVFlinger {

+ 9 - 8
src/core/hle/service/hid/hid.cpp

@@ -16,14 +16,15 @@
 #include "core/hle/kernel/client_port.h"
 #include "core/hle/kernel/k_readable_event.h"
 #include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/kernel/k_transfer_memory.h"
 #include "core/hle/kernel/k_writable_event.h"
 #include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/transfer_memory.h"
 #include "core/hle/service/hid/errors.h"
 #include "core/hle/service/hid/hid.h"
 #include "core/hle/service/hid/irs.h"
 #include "core/hle/service/hid/xcd.h"
 #include "core/hle/service/service.h"
+#include "core/memory.h"
 
 #include "core/hle/service/hid/controllers/console_sixaxis.h"
 #include "core/hle/service/hid/controllers/controller_base.h"
@@ -1493,20 +1494,20 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
     ASSERT_MSG(t_mem_1_size == 0x1000, "t_mem_1_size is not 0x1000 bytes");
     ASSERT_MSG(t_mem_2_size == 0x7F000, "t_mem_2_size is not 0x7F000 bytes");
 
-    auto t_mem_1 =
-        system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_1_handle);
+    auto t_mem_1 = system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
+        t_mem_1_handle);
 
-    if (t_mem_1 == nullptr) {
+    if (t_mem_1.IsNull()) {
         LOG_ERROR(Service_HID, "t_mem_1 is a nullptr for handle=0x{:08X}", t_mem_1_handle);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_UNKNOWN);
         return;
     }
 
-    auto t_mem_2 =
-        system.CurrentProcess()->GetHandleTable().Get<Kernel::TransferMemory>(t_mem_2_handle);
+    auto t_mem_2 = system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(
+        t_mem_2_handle);
 
-    if (t_mem_2 == nullptr) {
+    if (t_mem_2.IsNull()) {
         LOG_ERROR(Service_HID, "t_mem_2 is a nullptr for handle=0x{:08X}", t_mem_2_handle);
         IPC::ResponseBuilder rb{ctx, 2};
         rb.Push(RESULT_UNKNOWN);
@@ -1521,7 +1522,7 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) {
         .ActivateController();
 
     applet_resource->GetController<Controller_ConsoleSixAxis>(HidController::ConsoleSixAxisSensor)
-        .SetTransferMemoryPointer(t_mem_1->GetPointer());
+        .SetTransferMemoryPointer(system.Memory().GetPointer(t_mem_1->GetSourceAddress()));
 
     LOG_WARNING(Service_HID,
                 "called, t_mem_1_handle=0x{:08X}, t_mem_2_handle=0x{:08X}, "