summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2019-03-24 16:00:23 -0400
committerGravatar GitHub2019-03-24 16:00:23 -0400
commit3f74518e19331f1344960ae522c7439446febcd0 (patch)
treeabe0a23c3aa974ca3ada91c384b9c757f102c9a6
parentMerge pull request #2221 from DarkLordZach/firmware-version (diff)
parentcore/hle/kernel/svc: Implement svcUnmapTransferMemory (diff)
downloadyuzu-3f74518e19331f1344960ae522c7439446febcd0.tar.gz
yuzu-3f74518e19331f1344960ae522c7439446febcd0.tar.xz
yuzu-3f74518e19331f1344960ae522c7439446febcd0.zip
Merge pull request #2232 from lioncash/transfer-memory
core/hle/kernel: Split transfer memory handling out into its own class
Diffstat (limited to '')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/object.cpp1
-rw-r--r--src/core/hle/kernel/object.h1
-rw-r--r--src/core/hle/kernel/svc.cpp120
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp73
-rw-r--r--src/core/hle/kernel/transfer_memory.h91
6 files changed, 282 insertions, 6 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index f156bca40..9e23afe85 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -146,6 +146,8 @@ add_library(core STATIC
146 hle/kernel/svc_wrap.h 146 hle/kernel/svc_wrap.h
147 hle/kernel/thread.cpp 147 hle/kernel/thread.cpp
148 hle/kernel/thread.h 148 hle/kernel/thread.h
149 hle/kernel/transfer_memory.cpp
150 hle/kernel/transfer_memory.h
149 hle/kernel/vm_manager.cpp 151 hle/kernel/vm_manager.cpp
150 hle/kernel/vm_manager.h 152 hle/kernel/vm_manager.h
151 hle/kernel/wait_object.cpp 153 hle/kernel/wait_object.cpp
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 8870463d0..217144efc 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -23,6 +23,7 @@ bool Object::IsWaitable() const {
23 case HandleType::Unknown: 23 case HandleType::Unknown:
24 case HandleType::WritableEvent: 24 case HandleType::WritableEvent:
25 case HandleType::SharedMemory: 25 case HandleType::SharedMemory:
26 case HandleType::TransferMemory:
26 case HandleType::AddressArbiter: 27 case HandleType::AddressArbiter:
27 case HandleType::ResourceLimit: 28 case HandleType::ResourceLimit:
28 case HandleType::ClientPort: 29 case HandleType::ClientPort:
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 4c2505908..3f6baa094 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -22,6 +22,7 @@ enum class HandleType : u32 {
22 WritableEvent, 22 WritableEvent,
23 ReadableEvent, 23 ReadableEvent,
24 SharedMemory, 24 SharedMemory,
25 TransferMemory,
25 Thread, 26 Thread,
26 Process, 27 Process,
27 AddressArbiter, 28 AddressArbiter,
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index a6a17efe7..e5e7f99e1 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -32,6 +32,7 @@
32#include "core/hle/kernel/svc.h" 32#include "core/hle/kernel/svc.h"
33#include "core/hle/kernel/svc_wrap.h" 33#include "core/hle/kernel/svc_wrap.h"
34#include "core/hle/kernel/thread.h" 34#include "core/hle/kernel/thread.h"
35#include "core/hle/kernel/transfer_memory.h"
35#include "core/hle/kernel/writable_event.h" 36#include "core/hle/kernel/writable_event.h"
36#include "core/hle/lock.h" 37#include "core/hle/lock.h"
37#include "core/hle/result.h" 38#include "core/hle/result.h"
@@ -1586,14 +1587,121 @@ static ResultCode CreateTransferMemory(Handle* handle, VAddr addr, u64 size, u32
1586 } 1587 }
1587 1588
1588 auto& kernel = Core::System::GetInstance().Kernel(); 1589 auto& kernel = Core::System::GetInstance().Kernel();
1589 auto process = kernel.CurrentProcess(); 1590 auto transfer_mem_handle = TransferMemory::Create(kernel, addr, size, perms);
1590 auto& handle_table = process->GetHandleTable();
1591 const auto shared_mem_handle = SharedMemory::Create(kernel, process, size, perms, perms, addr);
1592 1591
1593 CASCADE_RESULT(*handle, handle_table.Create(shared_mem_handle)); 1592 auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1593 const auto result = handle_table.Create(std::move(transfer_mem_handle));
1594 if (result.Failed()) {
1595 return result.Code();
1596 }
1597
1598 *handle = *result;
1594 return RESULT_SUCCESS; 1599 return RESULT_SUCCESS;
1595} 1600}
1596 1601
1602static ResultCode MapTransferMemory(Handle handle, VAddr address, u64 size, u32 permission_raw) {
1603 LOG_DEBUG(Kernel_SVC,
1604 "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}, permissions=0x{:08X}",
1605 handle, address, size, permission_raw);
1606
1607 if (!Common::Is4KBAligned(address)) {
1608 LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
1609 address);
1610 return ERR_INVALID_ADDRESS;
1611 }
1612
1613 if (size == 0 || !Common::Is4KBAligned(size)) {
1614 LOG_ERROR(Kernel_SVC,
1615 "Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
1616 size);
1617 return ERR_INVALID_SIZE;
1618 }
1619
1620 if (!IsValidAddressRange(address, size)) {
1621 LOG_ERROR(Kernel_SVC,
1622 "Given address and size overflows the 64-bit range (address=0x{:016X}, "
1623 "size=0x{:016X}).",
1624 address, size);
1625 return ERR_INVALID_ADDRESS_STATE;
1626 }
1627
1628 const auto permissions = static_cast<MemoryPermission>(permission_raw);
1629 if (permissions != MemoryPermission::None && permissions != MemoryPermission::Read &&
1630 permissions != MemoryPermission::ReadWrite) {
1631 LOG_ERROR(Kernel_SVC, "Invalid transfer memory permissions given (permissions=0x{:08X}).",
1632 permission_raw);
1633 return ERR_INVALID_STATE;
1634 }
1635
1636 const auto& kernel = Core::System::GetInstance().Kernel();
1637 const auto* const current_process = kernel.CurrentProcess();
1638 const auto& handle_table = current_process->GetHandleTable();
1639
1640 auto transfer_memory = handle_table.Get<TransferMemory>(handle);
1641 if (!transfer_memory) {
1642 LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
1643 handle);
1644 return ERR_INVALID_HANDLE;
1645 }
1646
1647 if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
1648 LOG_ERROR(Kernel_SVC,
1649 "Given address and size don't fully fit within the ASLR region "
1650 "(address=0x{:016X}, size=0x{:016X}).",
1651 address, size);
1652 return ERR_INVALID_MEMORY_RANGE;
1653 }
1654
1655 return transfer_memory->MapMemory(address, size, permissions);
1656}
1657
1658static ResultCode UnmapTransferMemory(Handle handle, VAddr address, u64 size) {
1659 LOG_DEBUG(Kernel_SVC, "called. handle=0x{:08X}, address=0x{:016X}, size=0x{:016X}", handle,
1660 address, size);
1661
1662 if (!Common::Is4KBAligned(address)) {
1663 LOG_ERROR(Kernel_SVC, "Transfer memory addresses must be 4KB aligned (size=0x{:016X}).",
1664 address);
1665 return ERR_INVALID_ADDRESS;
1666 }
1667
1668 if (size == 0 || !Common::Is4KBAligned(size)) {
1669 LOG_ERROR(Kernel_SVC,
1670 "Transfer memory sizes must be 4KB aligned and not be zero (size=0x{:016X}).",
1671 size);
1672 return ERR_INVALID_SIZE;
1673 }
1674
1675 if (!IsValidAddressRange(address, size)) {
1676 LOG_ERROR(Kernel_SVC,
1677 "Given address and size overflows the 64-bit range (address=0x{:016X}, "
1678 "size=0x{:016X}).",
1679 address, size);
1680 return ERR_INVALID_ADDRESS_STATE;
1681 }
1682
1683 const auto& kernel = Core::System::GetInstance().Kernel();
1684 const auto* const current_process = kernel.CurrentProcess();
1685 const auto& handle_table = current_process->GetHandleTable();
1686
1687 auto transfer_memory = handle_table.Get<TransferMemory>(handle);
1688 if (!transfer_memory) {
1689 LOG_ERROR(Kernel_SVC, "Nonexistent transfer memory handle given (handle=0x{:08X}).",
1690 handle);
1691 return ERR_INVALID_HANDLE;
1692 }
1693
1694 if (!current_process->VMManager().IsWithinASLRRegion(address, size)) {
1695 LOG_ERROR(Kernel_SVC,
1696 "Given address and size don't fully fit within the ASLR region "
1697 "(address=0x{:016X}, size=0x{:016X}).",
1698 address, size);
1699 return ERR_INVALID_MEMORY_RANGE;
1700 }
1701
1702 return transfer_memory->UnmapMemory(address, size);
1703}
1704
1597static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) { 1705static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask) {
1598 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); 1706 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
1599 1707
@@ -1969,8 +2077,8 @@ static const FunctionDef SVC_Table[] = {
1969 {0x4E, nullptr, "ReadWriteRegister"}, 2077 {0x4E, nullptr, "ReadWriteRegister"},
1970 {0x4F, nullptr, "SetProcessActivity"}, 2078 {0x4F, nullptr, "SetProcessActivity"},
1971 {0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"}, 2079 {0x50, SvcWrap<CreateSharedMemory>, "CreateSharedMemory"},
1972 {0x51, nullptr, "MapTransferMemory"}, 2080 {0x51, SvcWrap<MapTransferMemory>, "MapTransferMemory"},
1973 {0x52, nullptr, "UnmapTransferMemory"}, 2081 {0x52, SvcWrap<UnmapTransferMemory>, "UnmapTransferMemory"},
1974 {0x53, nullptr, "CreateInterruptEvent"}, 2082 {0x53, nullptr, "CreateInterruptEvent"},
1975 {0x54, nullptr, "QueryPhysicalAddress"}, 2083 {0x54, nullptr, "QueryPhysicalAddress"},
1976 {0x55, nullptr, "QueryIoMapping"}, 2084 {0x55, nullptr, "QueryIoMapping"},
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp
new file mode 100644
index 000000000..23228e1b5
--- /dev/null
+++ b/src/core/hle/kernel/transfer_memory.cpp
@@ -0,0 +1,73 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "core/hle/kernel/errors.h"
6#include "core/hle/kernel/kernel.h"
7#include "core/hle/kernel/process.h"
8#include "core/hle/kernel/shared_memory.h"
9#include "core/hle/kernel/transfer_memory.h"
10#include "core/hle/result.h"
11
12namespace Kernel {
13
14TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {}
15TransferMemory::~TransferMemory() = default;
16
17SharedPtr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address,
18 size_t size, MemoryPermission permissions) {
19 SharedPtr<TransferMemory> transfer_memory{new TransferMemory(kernel)};
20
21 transfer_memory->base_address = base_address;
22 transfer_memory->memory_size = size;
23 transfer_memory->owner_permissions = permissions;
24 transfer_memory->owner_process = kernel.CurrentProcess();
25
26 return transfer_memory;
27}
28
29ResultCode TransferMemory::MapMemory(VAddr address, size_t size, MemoryPermission permissions) {
30 if (memory_size != size) {
31 return ERR_INVALID_SIZE;
32 }
33
34 if (owner_permissions != permissions) {
35 return ERR_INVALID_STATE;
36 }
37
38 if (is_mapped) {
39 return ERR_INVALID_STATE;
40 }
41
42 const auto map_state = owner_permissions == MemoryPermission::None
43 ? MemoryState::TransferMemoryIsolated
44 : MemoryState::TransferMemory;
45 auto& vm_manager = owner_process->VMManager();
46 const auto map_result = vm_manager.MapMemoryBlock(
47 address, std::make_shared<std::vector<u8>>(size), 0, size, map_state);
48
49 if (map_result.Failed()) {
50 return map_result.Code();
51 }
52
53 is_mapped = true;
54 return RESULT_SUCCESS;
55}
56
57ResultCode TransferMemory::UnmapMemory(VAddr address, size_t size) {
58 if (memory_size != size) {
59 return ERR_INVALID_SIZE;
60 }
61
62 auto& vm_manager = owner_process->VMManager();
63 const auto result = vm_manager.UnmapRange(address, size);
64
65 if (result.IsError()) {
66 return result;
67 }
68
69 is_mapped = false;
70 return RESULT_SUCCESS;
71}
72
73} // namespace Kernel
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h
new file mode 100644
index 000000000..ec294951e
--- /dev/null
+++ b/src/core/hle/kernel/transfer_memory.h
@@ -0,0 +1,91 @@
1// Copyright 2019 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "core/hle/kernel/object.h"
8
9union ResultCode;
10
11namespace Kernel {
12
13class KernelCore;
14class Process;
15
16enum class MemoryPermission : u32;
17
18/// Defines the interface for transfer memory objects.
19///
20/// Transfer memory is typically used for the purpose of
21/// transferring memory between separate process instances,
22/// thus the name.
23///
24class TransferMemory final : public Object {
25public:
26 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
27
28 static SharedPtr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, size_t size,
29 MemoryPermission permissions);
30
31 TransferMemory(const TransferMemory&) = delete;
32 TransferMemory& operator=(const TransferMemory&) = delete;
33
34 TransferMemory(TransferMemory&&) = delete;
35 TransferMemory& operator=(TransferMemory&&) = delete;
36
37 std::string GetTypeName() const override {
38 return "TransferMemory";
39 }
40
41 std::string GetName() const override {
42 return GetTypeName();
43 }
44
45 HandleType GetHandleType() const override {
46 return HANDLE_TYPE;
47 }
48
49 /// Attempts to map transfer memory with the given range and memory permissions.
50 ///
51 /// @param address The base address to being mapping memory at.
52 /// @param size The size of the memory to map, in bytes.
53 /// @param permissions The memory permissions to check against when mapping memory.
54 ///
55 /// @pre The given address, size, and memory permissions must all match
56 /// the same values that were given when creating the transfer memory
57 /// instance.
58 ///
59 ResultCode MapMemory(VAddr address, size_t size, MemoryPermission permissions);
60
61 /// Unmaps the transfer memory with the given range
62 ///
63 /// @param address The base address to begin unmapping memory at.
64 /// @param size The size of the memory to unmap, in bytes.
65 ///
66 /// @pre The given address and size must be the same as the ones used
67 /// to create the transfer memory instance.
68 ///
69 ResultCode UnmapMemory(VAddr address, size_t size);
70
71private:
72 explicit TransferMemory(KernelCore& kernel);
73 ~TransferMemory() override;
74
75 /// The base address for the memory managed by this instance.
76 VAddr base_address = 0;
77
78 /// Size of the memory, in bytes, that this instance manages.
79 size_t memory_size = 0;
80
81 /// The memory permissions that are applied to this instance.
82 MemoryPermission owner_permissions{};
83
84 /// The process that this transfer memory instance was created under.
85 Process* owner_process = nullptr;
86
87 /// Whether or not this transfer memory instance has mapped memory.
88 bool is_mapped = false;
89};
90
91} // namespace Kernel