diff options
| author | 2021-04-17 00:52:53 -0700 | |
|---|---|---|
| committer | 2021-05-05 16:40:51 -0700 | |
| commit | c7d8b7421cd6bdb64410bbb0094ce540f0280c27 (patch) | |
| tree | 0b24ec86f194395fac5f5688a6e14fc5dec0b7dd /src/core/hle/kernel/svc.cpp | |
| parent | hle: kernel: Migrate KSession, KClientSession, and KServerSession to KAutoObj... (diff) | |
| download | yuzu-c7d8b7421cd6bdb64410bbb0094ce540f0280c27.tar.gz yuzu-c7d8b7421cd6bdb64410bbb0094ce540f0280c27.tar.xz yuzu-c7d8b7421cd6bdb64410bbb0094ce540f0280c27.zip | |
hle: kernel: Migrate KTransferMemory to KAutoObject.
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 93 |
1 files changed, 48 insertions, 45 deletions
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 @@ | |||
| 38 | #include "core/hle/kernel/k_shared_memory.h" | 38 | #include "core/hle/kernel/k_shared_memory.h" |
| 39 | #include "core/hle/kernel/k_synchronization_object.h" | 39 | #include "core/hle/kernel/k_synchronization_object.h" |
| 40 | #include "core/hle/kernel/k_thread.h" | 40 | #include "core/hle/kernel/k_thread.h" |
| 41 | #include "core/hle/kernel/k_transfer_memory.h" | ||
| 41 | #include "core/hle/kernel/k_writable_event.h" | 42 | #include "core/hle/kernel/k_writable_event.h" |
| 42 | #include "core/hle/kernel/kernel.h" | 43 | #include "core/hle/kernel/kernel.h" |
| 43 | #include "core/hle/kernel/physical_core.h" | 44 | #include "core/hle/kernel/physical_core.h" |
| @@ -47,7 +48,6 @@ | |||
| 47 | #include "core/hle/kernel/svc_types.h" | 48 | #include "core/hle/kernel/svc_types.h" |
| 48 | #include "core/hle/kernel/svc_wrap.h" | 49 | #include "core/hle/kernel/svc_wrap.h" |
| 49 | #include "core/hle/kernel/time_manager.h" | 50 | #include "core/hle/kernel/time_manager.h" |
| 50 | #include "core/hle/kernel/transfer_memory.h" | ||
| 51 | #include "core/hle/lock.h" | 51 | #include "core/hle/lock.h" |
| 52 | #include "core/hle/result.h" | 52 | #include "core/hle/result.h" |
| 53 | #include "core/hle/service/service.h" | 53 | #include "core/hle/service/service.h" |
| @@ -1868,65 +1868,68 @@ static ResultCode ResetSignal32(Core::System& system, Handle handle) { | |||
| 1868 | return ResetSignal(system, handle); | 1868 | return ResetSignal(system, handle); |
| 1869 | } | 1869 | } |
| 1870 | 1870 | ||
| 1871 | /// Creates a TransferMemory object | 1871 | static constexpr bool IsValidTransferMemoryPermission(MemoryPermission perm) { |
| 1872 | static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAddr addr, u64 size, | 1872 | switch (perm) { |
| 1873 | u32 permissions) { | 1873 | case MemoryPermission::None: |
| 1874 | std::lock_guard lock{HLE::g_hle_lock}; | 1874 | case MemoryPermission::Read: |
| 1875 | LOG_DEBUG(Kernel_SVC, "called addr=0x{:X}, size=0x{:X}, perms=0x{:08X}", addr, size, | 1875 | case MemoryPermission::ReadWrite: |
| 1876 | permissions); | 1876 | return true; |
| 1877 | 1877 | default: | |
| 1878 | if (!Common::Is4KBAligned(addr)) { | 1878 | return false; |
| 1879 | LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr); | ||
| 1880 | return ResultInvalidAddress; | ||
| 1881 | } | 1879 | } |
| 1880 | } | ||
| 1882 | 1881 | ||
| 1883 | if (!Common::Is4KBAligned(size) || size == 0) { | 1882 | /// Creates a TransferMemory object |
| 1884 | LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size); | 1883 | static ResultCode CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size, |
| 1885 | return ResultInvalidAddress; | 1884 | MemoryPermission map_perm) { |
| 1886 | } | 1885 | auto& kernel = system.Kernel(); |
| 1887 | 1886 | ||
| 1888 | if (!IsValidAddressRange(addr, size)) { | 1887 | // Validate the size. |
| 1889 | LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})", | 1888 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); |
| 1890 | addr, size); | 1889 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); |
| 1891 | return ResultInvalidCurrentMemory; | 1890 | R_UNLESS(size > 0, ResultInvalidSize); |
| 1892 | } | 1891 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); |
| 1893 | 1892 | ||
| 1894 | const auto perms{static_cast<MemoryPermission>(permissions)}; | 1893 | // Validate the permissions. |
| 1895 | if (perms > MemoryPermission::ReadWrite || perms == MemoryPermission::Write) { | 1894 | R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission); |
| 1896 | LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})", | 1895 | |
| 1897 | permissions); | 1896 | // Get the current process and handle table. |
| 1898 | return ResultInvalidNewMemoryPermission; | 1897 | auto& process = *kernel.CurrentProcess(); |
| 1899 | } | 1898 | auto& handle_table = process.GetHandleTable(); |
| 1900 | 1899 | ||
| 1901 | auto& kernel = system.Kernel(); | ||
| 1902 | // Reserve a new transfer memory from the process resource limit. | 1900 | // Reserve a new transfer memory from the process resource limit. |
| 1903 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), | 1901 | KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), |
| 1904 | LimitableResource::TransferMemory); | 1902 | LimitableResource::TransferMemory); |
| 1905 | if (!trmem_reservation.Succeeded()) { | 1903 | R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); |
| 1906 | LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory"); | ||
| 1907 | return ResultLimitReached; | ||
| 1908 | } | ||
| 1909 | auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, | ||
| 1910 | static_cast<KMemoryPermission>(perms)); | ||
| 1911 | 1904 | ||
| 1912 | if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) { | 1905 | // Create the transfer memory. |
| 1913 | return reserve_result; | 1906 | KTransferMemory* trmem = KTransferMemory::Create(kernel); |
| 1914 | } | 1907 | R_UNLESS(trmem != nullptr, ResultOutOfResource); |
| 1915 | 1908 | ||
| 1916 | auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 1909 | // Ensure the only reference is in the handle table when we're done. |
| 1917 | const auto result{handle_table.Create(transfer_mem_handle.get())}; | 1910 | SCOPE_EXIT({ trmem->Close(); }); |
| 1918 | if (result.Failed()) { | 1911 | |
| 1919 | return result.Code(); | 1912 | // Ensure that the region is in range. |
| 1920 | } | 1913 | R_UNLESS(process.PageTable().Contains(address, size), ResultInvalidCurrentMemory); |
| 1914 | |||
| 1915 | // Initialize the transfer memory. | ||
| 1916 | R_TRY(trmem->Initialize(address, size, map_perm)); | ||
| 1917 | |||
| 1918 | // Commit the reservation. | ||
| 1921 | trmem_reservation.Commit(); | 1919 | trmem_reservation.Commit(); |
| 1922 | 1920 | ||
| 1923 | *handle = *result; | 1921 | // Register the transfer memory. |
| 1922 | KTransferMemory::Register(kernel, trmem); | ||
| 1923 | |||
| 1924 | // Add the transfer memory to the handle table. | ||
| 1925 | R_TRY(handle_table.Add(out, trmem)); | ||
| 1926 | |||
| 1924 | return RESULT_SUCCESS; | 1927 | return RESULT_SUCCESS; |
| 1925 | } | 1928 | } |
| 1926 | 1929 | ||
| 1927 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u32 addr, u32 size, | 1930 | static ResultCode CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size, |
| 1928 | u32 permissions) { | 1931 | MemoryPermission map_perm) { |
| 1929 | return CreateTransferMemory(system, handle, addr, size, permissions); | 1932 | return CreateTransferMemory(system, out, address, size, map_perm); |
| 1930 | } | 1933 | } |
| 1931 | 1934 | ||
| 1932 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, | 1935 | static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, |