diff options
-rw-r--r-- | src/core/CMakeLists.txt | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/handle_table.cpp | 3 | ||||
-rw-r--r-- | src/core/hle/kernel/init/init_slab_setup.cpp | 2 | ||||
-rw-r--r-- | src/core/hle/kernel/k_page_table.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/k_transfer_memory.cpp | 45 | ||||
-rw-r--r-- | src/core/hle/kernel/k_transfer_memory.h | 82 | ||||
-rw-r--r-- | src/core/hle/kernel/kernel.h | 4 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 93 | ||||
-rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 12 | ||||
-rw-r--r-- | src/core/hle/service/am/am.cpp | 9 | ||||
-rw-r--r-- | src/core/hle/service/am/am.h | 2 | ||||
-rw-r--r-- | src/core/hle/service/hid/hid.cpp | 17 |
12 files changed, 209 insertions, 68 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e30a30823..8e3b51ae7 100644 --- a/src/core/CMakeLists.txt +++ b/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 diff --git a/src/core/hle/kernel/handle_table.cpp b/src/core/hle/kernel/handle_table.cpp index ddb1e6fb2..9291f0a76 100644 --- a/src/core/hle/kernel/handle_table.cpp +++ b/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); diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index 84d509d52..ce7a24c40 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/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__) diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 49b824379..80a1586db 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/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; } diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp new file mode 100644 index 000000000..09c067f95 --- /dev/null +++ b/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 diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h new file mode 100644 index 000000000..f43725c7f --- /dev/null +++ b/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 diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index ecced1034..f07f0276e 100644 --- a/src/core/hle/kernel/kernel.h +++ b/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; diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 28c45e8a3..0b7eb0740 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/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, diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 96afd544b..819eadfbb 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/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, ¶m_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); } diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 937020a6e..47d194119 100644 --- a/src/core/hle/service/am/am.cpp +++ b/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}; diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index fbac7b2cf..184030a8e 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -13,7 +13,7 @@ namespace Kernel { class KernelCore; -class TransferMemory; +class KTransferMemory; } // namespace Kernel namespace Service::NVFlinger { diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 6b3ebeb8f..d831aa214 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/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}, " |