summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar bunnei2020-01-30 22:39:07 -0500
committerGravatar bunnei2020-02-05 23:06:54 -0500
commitba53543da6126b5fe7b3f26e2688272cf11024a3 (patch)
tree6056b75468249a9841a0e521d7a381efd087e0f2 /src/core/hle/kernel
parentwait_object: Make wait behavior only require one object to signal. (diff)
downloadyuzu-ba53543da6126b5fe7b3f26e2688272cf11024a3.tar.gz
yuzu-ba53543da6126b5fe7b3f26e2688272cf11024a3.tar.xz
yuzu-ba53543da6126b5fe7b3f26e2688272cf11024a3.zip
kernel: transfer_memory: Properly reserve and reset memory region.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/svc.cpp8
-rw-r--r--src/core/hle/kernel/transfer_memory.cpp66
-rw-r--r--src/core/hle/kernel/transfer_memory.h19
-rw-r--r--src/core/hle/kernel/vm_manager.cpp3
-rw-r--r--src/core/hle/kernel/vm_manager.h60
5 files changed, 116 insertions, 40 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 1d99bf7a2..9cae5c73d 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -1863,10 +1863,14 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
1863 } 1863 }
1864 1864
1865 auto& kernel = system.Kernel(); 1865 auto& kernel = system.Kernel();
1866 auto transfer_mem_handle = TransferMemory::Create(kernel, addr, size, perms); 1866 auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms);
1867
1868 if (const auto reserve_result{transfer_mem_handle->Reserve()}; reserve_result.IsError()) {
1869 return reserve_result;
1870 }
1867 1871
1868 auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1872 auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1869 const auto result = handle_table.Create(std::move(transfer_mem_handle)); 1873 const auto result{handle_table.Create(std::move(transfer_mem_handle))};
1870 if (result.Failed()) { 1874 if (result.Failed()) {
1871 return result.Code(); 1875 return result.Code();
1872 } 1876 }
diff --git a/src/core/hle/kernel/transfer_memory.cpp b/src/core/hle/kernel/transfer_memory.cpp
index f0e73f57b..f2d3f8b49 100644
--- a/src/core/hle/kernel/transfer_memory.cpp
+++ b/src/core/hle/kernel/transfer_memory.cpp
@@ -8,15 +8,23 @@
8#include "core/hle/kernel/shared_memory.h" 8#include "core/hle/kernel/shared_memory.h"
9#include "core/hle/kernel/transfer_memory.h" 9#include "core/hle/kernel/transfer_memory.h"
10#include "core/hle/result.h" 10#include "core/hle/result.h"
11#include "core/memory.h"
11 12
12namespace Kernel { 13namespace Kernel {
13 14
14TransferMemory::TransferMemory(KernelCore& kernel) : Object{kernel} {} 15TransferMemory::TransferMemory(KernelCore& kernel, Memory::Memory& memory)
15TransferMemory::~TransferMemory() = default; 16 : Object{kernel}, memory{memory} {}
16 17
17std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr base_address, 18TransferMemory::~TransferMemory() {
18 u64 size, MemoryPermission permissions) { 19 // Release memory region when transfer memory is destroyed
19 std::shared_ptr<TransferMemory> transfer_memory{std::make_shared<TransferMemory>(kernel)}; 20 Reset();
21}
22
23std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, Memory::Memory& memory,
24 VAddr base_address, u64 size,
25 MemoryPermission permissions) {
26 std::shared_ptr<TransferMemory> transfer_memory{
27 std::make_shared<TransferMemory>(kernel, memory)};
20 28
21 transfer_memory->base_address = base_address; 29 transfer_memory->base_address = base_address;
22 transfer_memory->memory_size = size; 30 transfer_memory->memory_size = size;
@@ -27,7 +35,7 @@ std::shared_ptr<TransferMemory> TransferMemory::Create(KernelCore& kernel, VAddr
27} 35}
28 36
29const u8* TransferMemory::GetPointer() const { 37const u8* TransferMemory::GetPointer() const {
30 return backing_block.get()->data(); 38 return memory.GetPointer(base_address);
31} 39}
32 40
33u64 TransferMemory::GetSize() const { 41u64 TransferMemory::GetSize() const {
@@ -62,6 +70,52 @@ ResultCode TransferMemory::MapMemory(VAddr address, u64 size, MemoryPermission p
62 return RESULT_SUCCESS; 70 return RESULT_SUCCESS;
63} 71}
64 72
73ResultCode TransferMemory::Reserve() {
74 auto& vm_manager{owner_process->VMManager()};
75 const auto check_range_result{vm_manager.CheckRangeState(
76 base_address, memory_size, MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated,
77 MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, VMAPermission::All,
78 VMAPermission::ReadWrite, MemoryAttribute::Mask, MemoryAttribute::None,
79 MemoryAttribute::IpcAndDeviceMapped)};
80
81 if (check_range_result.Failed()) {
82 return check_range_result.Code();
83 }
84
85 auto [state_, permissions_, attribute] = *check_range_result;
86
87 if (const auto result{vm_manager.ReprotectRange(
88 base_address, memory_size, SharedMemory::ConvertPermissions(owner_permissions))};
89 result.IsError()) {
90 return result;
91 }
92
93 return vm_manager.SetMemoryAttribute(base_address, memory_size, MemoryAttribute::Mask,
94 attribute | MemoryAttribute::Locked);
95}
96
97ResultCode TransferMemory::Reset() {
98 auto& vm_manager{owner_process->VMManager()};
99 if (const auto result{vm_manager.CheckRangeState(
100 base_address, memory_size,
101 MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated,
102 MemoryState::FlagTransfer | MemoryState::FlagMemoryPoolAllocated, VMAPermission::None,
103 VMAPermission::None, MemoryAttribute::Mask, MemoryAttribute::Locked,
104 MemoryAttribute::IpcAndDeviceMapped)};
105 result.Failed()) {
106 return result.Code();
107 }
108
109 if (const auto result{
110 vm_manager.ReprotectRange(base_address, memory_size, VMAPermission::ReadWrite)};
111 result.IsError()) {
112 return result;
113 }
114
115 return vm_manager.SetMemoryAttribute(base_address, memory_size, MemoryAttribute::Mask,
116 MemoryAttribute::None);
117}
118
65ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) { 119ResultCode TransferMemory::UnmapMemory(VAddr address, u64 size) {
66 if (memory_size != size) { 120 if (memory_size != size) {
67 return ERR_INVALID_SIZE; 121 return ERR_INVALID_SIZE;
diff --git a/src/core/hle/kernel/transfer_memory.h b/src/core/hle/kernel/transfer_memory.h
index 0a6e15d18..6e388536a 100644
--- a/src/core/hle/kernel/transfer_memory.h
+++ b/src/core/hle/kernel/transfer_memory.h
@@ -11,6 +11,10 @@
11 11
12union ResultCode; 12union ResultCode;
13 13
14namespace Memory {
15class Memory;
16}
17
14namespace Kernel { 18namespace Kernel {
15 19
16class KernelCore; 20class KernelCore;
@@ -26,12 +30,13 @@ enum class MemoryPermission : u32;
26/// 30///
27class TransferMemory final : public Object { 31class TransferMemory final : public Object {
28public: 32public:
29 explicit TransferMemory(KernelCore& kernel); 33 explicit TransferMemory(KernelCore& kernel, Memory::Memory& memory);
30 ~TransferMemory() override; 34 ~TransferMemory() override;
31 35
32 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory; 36 static constexpr HandleType HANDLE_TYPE = HandleType::TransferMemory;
33 37
34 static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, VAddr base_address, u64 size, 38 static std::shared_ptr<TransferMemory> Create(KernelCore& kernel, Memory::Memory& memory,
39 VAddr base_address, u64 size,
35 MemoryPermission permissions); 40 MemoryPermission permissions);
36 41
37 TransferMemory(const TransferMemory&) = delete; 42 TransferMemory(const TransferMemory&) = delete;
@@ -80,6 +85,14 @@ public:
80 /// 85 ///
81 ResultCode UnmapMemory(VAddr address, u64 size); 86 ResultCode UnmapMemory(VAddr address, u64 size);
82 87
88 /// Reserves the region to be used for the transfer memory, called after the transfer memory is
89 /// created.
90 ResultCode Reserve();
91
92 /// Resets the region previously used for the transfer memory, called after the transfer memory
93 /// is closed.
94 ResultCode Reset();
95
83private: 96private:
84 /// Memory block backing this instance. 97 /// Memory block backing this instance.
85 std::shared_ptr<PhysicalMemory> backing_block; 98 std::shared_ptr<PhysicalMemory> backing_block;
@@ -98,6 +111,8 @@ private:
98 111
99 /// Whether or not this transfer memory instance has mapped memory. 112 /// Whether or not this transfer memory instance has mapped memory.
100 bool is_mapped = false; 113 bool is_mapped = false;
114
115 Memory::Memory& memory;
101}; 116};
102 117
103} // namespace Kernel 118} // namespace Kernel
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 0b3500fce..024c22901 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -544,7 +544,8 @@ MemoryInfo VMManager::QueryMemory(VAddr address) const {
544 544
545ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask, 545ResultCode VMManager::SetMemoryAttribute(VAddr address, u64 size, MemoryAttribute mask,
546 MemoryAttribute attribute) { 546 MemoryAttribute attribute) {
547 constexpr auto ignore_mask = MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped; 547 constexpr auto ignore_mask =
548 MemoryAttribute::Uncached | MemoryAttribute::DeviceMapped | MemoryAttribute::Locked;
548 constexpr auto attribute_mask = ~ignore_mask; 549 constexpr auto attribute_mask = ~ignore_mask;
549 550
550 const auto result = CheckRangeState( 551 const auto result = CheckRangeState(
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h
index 850a7ebc3..90b4b006a 100644
--- a/src/core/hle/kernel/vm_manager.h
+++ b/src/core/hle/kernel/vm_manager.h
@@ -98,6 +98,8 @@ enum class MemoryAttribute : u32 {
98 DeviceMapped = 4, 98 DeviceMapped = 4,
99 /// Uncached memory 99 /// Uncached memory
100 Uncached = 8, 100 Uncached = 8,
101
102 IpcAndDeviceMapped = LockedForIPC | DeviceMapped,
101}; 103};
102 104
103constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) { 105constexpr MemoryAttribute operator|(MemoryAttribute lhs, MemoryAttribute rhs) {
@@ -654,6 +656,35 @@ public:
654 /// is scheduled. 656 /// is scheduled.
655 Common::PageTable page_table{Memory::PAGE_BITS}; 657 Common::PageTable page_table{Memory::PAGE_BITS};
656 658
659 using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
660
661 /// Checks if an address range adheres to the specified states provided.
662 ///
663 /// @param address The starting address of the address range.
664 /// @param size The size of the address range.
665 /// @param state_mask The memory state mask.
666 /// @param state The state to compare the individual VMA states against,
667 /// which is done in the form of: (vma.state & state_mask) != state.
668 /// @param permission_mask The memory permissions mask.
669 /// @param permissions The permission to compare the individual VMA permissions against,
670 /// which is done in the form of:
671 /// (vma.permission & permission_mask) != permission.
672 /// @param attribute_mask The memory attribute mask.
673 /// @param attribute The memory attributes to compare the individual VMA attributes
674 /// against, which is done in the form of:
675 /// (vma.attributes & attribute_mask) != attribute.
676 /// @param ignore_mask The memory attributes to ignore during the check.
677 ///
678 /// @returns If successful, returns a tuple containing the memory attributes
679 /// (with ignored bits specified by ignore_mask unset), memory permissions, and
680 /// memory state across the memory range.
681 /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
682 ///
683 CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
684 VMAPermission permission_mask, VMAPermission permissions,
685 MemoryAttribute attribute_mask, MemoryAttribute attribute,
686 MemoryAttribute ignore_mask) const;
687
657private: 688private:
658 using VMAIter = VMAMap::iterator; 689 using VMAIter = VMAMap::iterator;
659 690
@@ -707,35 +738,6 @@ private:
707 /// Clears out the page table 738 /// Clears out the page table
708 void ClearPageTable(); 739 void ClearPageTable();
709 740
710 using CheckResults = ResultVal<std::tuple<MemoryState, VMAPermission, MemoryAttribute>>;
711
712 /// Checks if an address range adheres to the specified states provided.
713 ///
714 /// @param address The starting address of the address range.
715 /// @param size The size of the address range.
716 /// @param state_mask The memory state mask.
717 /// @param state The state to compare the individual VMA states against,
718 /// which is done in the form of: (vma.state & state_mask) != state.
719 /// @param permission_mask The memory permissions mask.
720 /// @param permissions The permission to compare the individual VMA permissions against,
721 /// which is done in the form of:
722 /// (vma.permission & permission_mask) != permission.
723 /// @param attribute_mask The memory attribute mask.
724 /// @param attribute The memory attributes to compare the individual VMA attributes
725 /// against, which is done in the form of:
726 /// (vma.attributes & attribute_mask) != attribute.
727 /// @param ignore_mask The memory attributes to ignore during the check.
728 ///
729 /// @returns If successful, returns a tuple containing the memory attributes
730 /// (with ignored bits specified by ignore_mask unset), memory permissions, and
731 /// memory state across the memory range.
732 /// @returns If not successful, returns ERR_INVALID_ADDRESS_STATE.
733 ///
734 CheckResults CheckRangeState(VAddr address, u64 size, MemoryState state_mask, MemoryState state,
735 VMAPermission permission_mask, VMAPermission permissions,
736 MemoryAttribute attribute_mask, MemoryAttribute attribute,
737 MemoryAttribute ignore_mask) const;
738
739 /// Gets the amount of memory currently mapped (state != Unmapped) in a range. 741 /// Gets the amount of memory currently mapped (state != Unmapped) in a range.
740 ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const; 742 ResultVal<std::size_t> SizeOfAllocatedVMAsInRange(VAddr address, std::size_t size) const;
741 743