summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bunnei2020-04-08 18:53:52 -0400
committerGravatar bunnei2020-04-17 00:59:32 -0400
commitd0162fc3d7841190bf163afc754b0ec0cdbd7462 (patch)
tree28617dc6c379ed3814d08e771dfbc0b172f35b8c /src/core
parentcore: device_memory: Update to use VirtualBuffer class. (diff)
downloadyuzu-d0162fc3d7841190bf163afc754b0ec0cdbd7462.tar.gz
yuzu-d0162fc3d7841190bf163afc754b0ec0cdbd7462.tar.xz
yuzu-d0162fc3d7841190bf163afc754b0ec0cdbd7462.zip
kernel: shared_memory: Refactor for new VMM.
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/kernel/shared_memory.cpp151
-rw-r--r--src/core/hle/kernel/shared_memory.h127
2 files changed, 58 insertions, 220 deletions
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index afb2e3fc2..e28da6869 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -2,149 +2,56 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <utility>
6
7#include "common/assert.h" 5#include "common/assert.h"
8#include "common/logging/log.h" 6#include "core/core.h"
9#include "core/hle/kernel/errors.h"
10#include "core/hle/kernel/kernel.h" 7#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/memory/page_table.h"
11#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
12 10
13namespace Kernel { 11namespace Kernel {
14 12
15SharedMemory::SharedMemory(KernelCore& kernel) : Object{kernel} {} 13SharedMemory::SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory)
16SharedMemory::~SharedMemory() = default; 14 : Object{kernel}, device_memory{device_memory} {}
17
18std::shared_ptr<SharedMemory> SharedMemory::Create(KernelCore& kernel, Process* owner_process,
19 u64 size, MemoryPermission permissions,
20 MemoryPermission other_permissions,
21 VAddr address, MemoryRegion region,
22 std::string name) {
23 std::shared_ptr<SharedMemory> shared_memory = std::make_shared<SharedMemory>(kernel);
24
25 shared_memory->owner_process = owner_process;
26 shared_memory->name = std::move(name);
27 shared_memory->size = size;
28 shared_memory->permissions = permissions;
29 shared_memory->other_permissions = other_permissions;
30
31 if (address == 0) {
32 shared_memory->backing_block = std::make_shared<Kernel::PhysicalMemory>(size);
33 shared_memory->backing_block_offset = 0;
34
35 // Refresh the address mappings for the current process.
36 if (kernel.CurrentProcess() != nullptr) {
37 kernel.CurrentProcess()->VMManager().RefreshMemoryBlockMappings(
38 shared_memory->backing_block.get());
39 }
40 } else {
41 const auto& vm_manager = shared_memory->owner_process->VMManager();
42 15
43 // The memory is already available and mapped in the owner process. 16SharedMemory::~SharedMemory() = default;
44 const auto vma = vm_manager.FindVMA(address);
45 ASSERT_MSG(vm_manager.IsValidHandle(vma), "Invalid memory address");
46 ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address");
47
48 // The returned VMA might be a bigger one encompassing the desired address.
49 const auto vma_offset = address - vma->first;
50 ASSERT_MSG(vma_offset + size <= vma->second.size,
51 "Shared memory exceeds bounds of mapped block");
52
53 shared_memory->backing_block = vma->second.backing_block;
54 shared_memory->backing_block_offset = vma->second.offset + vma_offset;
55 }
56
57 shared_memory->base_address = address;
58 17
59 return shared_memory; 18std::shared_ptr<SharedMemory> SharedMemory::Create(
60} 19 KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
20 Memory::PageLinkedList&& page_list, Memory::MemoryPermission owner_permission,
21 Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size,
22 std::string name) {
61 23
62std::shared_ptr<SharedMemory> SharedMemory::CreateForApplet( 24 std::shared_ptr<SharedMemory> shared_memory{
63 KernelCore& kernel, std::shared_ptr<Kernel::PhysicalMemory> heap_block, std::size_t offset, 25 std::make_shared<SharedMemory>(kernel, device_memory)};
64 u64 size, MemoryPermission permissions, MemoryPermission other_permissions, std::string name) {
65 std::shared_ptr<SharedMemory> shared_memory = std::make_shared<SharedMemory>(kernel);
66 26
67 shared_memory->owner_process = nullptr; 27 shared_memory->owner_process = owner_process;
68 shared_memory->name = std::move(name); 28 shared_memory->page_list = std::move(page_list);
29 shared_memory->owner_permission = owner_permission;
30 shared_memory->user_permission = user_permission;
31 shared_memory->physical_address = physical_address;
69 shared_memory->size = size; 32 shared_memory->size = size;
70 shared_memory->permissions = permissions; 33 shared_memory->name = name;
71 shared_memory->other_permissions = other_permissions;
72 shared_memory->backing_block = std::move(heap_block);
73 shared_memory->backing_block_offset = offset;
74 shared_memory->base_address =
75 kernel.CurrentProcess()->VMManager().GetHeapRegionBaseAddress() + offset;
76 34
77 return shared_memory; 35 return shared_memory;
78} 36}
79 37
80ResultCode SharedMemory::Map(Process& target_process, VAddr address, MemoryPermission permissions, 38ResultCode SharedMemory::Map(Process& target_process, VAddr address, std::size_t size,
81 MemoryPermission other_permissions) { 39 Memory::MemoryPermission permission) {
82 const MemoryPermission own_other_permissions = 40 const u64 page_count{(size + Memory::PageSize - 1) / Memory::PageSize};
83 &target_process == owner_process ? this->permissions : this->other_permissions;
84
85 // Automatically allocated memory blocks can only be mapped with other_permissions = DontCare
86 if (base_address == 0 && other_permissions != MemoryPermission::DontCare) {
87 return ERR_INVALID_MEMORY_PERMISSIONS;
88 }
89
90 // Error out if the requested permissions don't match what the creator process allows.
91 if (static_cast<u32>(permissions) & ~static_cast<u32>(own_other_permissions)) {
92 LOG_ERROR(Kernel, "cannot map id={}, address=0x{:X} name={}, permissions don't match",
93 GetObjectId(), address, name);
94 return ERR_INVALID_MEMORY_PERMISSIONS;
95 }
96 41
97 // Error out if the provided permissions are not compatible with what the creator process needs. 42 if (page_list.GetNumPages() != page_count) {
98 if (other_permissions != MemoryPermission::DontCare && 43 UNIMPLEMENTED();
99 static_cast<u32>(this->permissions) & ~static_cast<u32>(other_permissions)) {
100 LOG_ERROR(Kernel, "cannot map id={}, address=0x{:X} name={}, permissions don't match",
101 GetObjectId(), address, name);
102 return ERR_INVALID_MEMORY_PERMISSIONS;
103 } 44 }
104 45
105 VAddr target_address = address; 46 Memory::MemoryPermission expected =
47 &target_process == owner_process ? owner_permission : user_permission;
106 48
107 // Map the memory block into the target process 49 if (permission != expected) {
108 auto result = target_process.VMManager().MapMemoryBlock( 50 UNIMPLEMENTED();
109 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
110 if (result.Failed()) {
111 LOG_ERROR(
112 Kernel,
113 "cannot map id={}, target_address=0x{:X} name={}, error mapping to virtual memory",
114 GetObjectId(), target_address, name);
115 return result.Code();
116 } 51 }
117 52
118 return target_process.VMManager().ReprotectRange(target_address, size, 53 return target_process.PageTable().MapPages(address, page_list, Memory::MemoryState::Shared,
119 ConvertPermissions(permissions)); 54 permission);
120}
121
122ResultCode SharedMemory::Unmap(Process& target_process, VAddr address, u64 unmap_size) {
123 if (unmap_size != size) {
124 LOG_ERROR(Kernel,
125 "Invalid size passed to Unmap. Size must be equal to the size of the "
126 "memory managed. Shared memory size=0x{:016X}, Unmap size=0x{:016X}",
127 size, unmap_size);
128 return ERR_INVALID_SIZE;
129 }
130
131 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not
132 // mapped to a SharedMemory.
133 return target_process.VMManager().UnmapRange(address, size);
134}
135
136VMAPermission SharedMemory::ConvertPermissions(MemoryPermission permission) {
137 u32 masked_permissions =
138 static_cast<u32>(permission) & static_cast<u32>(MemoryPermission::ReadWriteExecute);
139 return static_cast<VMAPermission>(masked_permissions);
140}
141
142u8* SharedMemory::GetPointer(std::size_t offset) {
143 return backing_block->data() + backing_block_offset + offset;
144}
145
146const u8* SharedMemory::GetPointer(std::size_t offset) const {
147 return backing_block->data() + backing_block_offset + offset;
148} 55}
149 56
150} // namespace Kernel 57} // namespace Kernel
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 014951d82..06fe693de 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -8,8 +8,10 @@
8#include <string> 8#include <string>
9 9
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "core/device_memory.h"
12#include "core/hle/kernel/memory/memory_block.h"
13#include "core/hle/kernel/memory/page_linked_list.h"
11#include "core/hle/kernel/object.h" 14#include "core/hle/kernel/object.h"
12#include "core/hle/kernel/physical_memory.h"
13#include "core/hle/kernel/process.h" 15#include "core/hle/kernel/process.h"
14#include "core/hle/result.h" 16#include "core/hle/result.h"
15 17
@@ -17,63 +19,21 @@ namespace Kernel {
17 19
18class KernelCore; 20class KernelCore;
19 21
20/// Permissions for mapped shared memory blocks
21enum class MemoryPermission : u32 {
22 None = 0,
23 Read = (1u << 0),
24 Write = (1u << 1),
25 ReadWrite = (Read | Write),
26 Execute = (1u << 2),
27 ReadExecute = (Read | Execute),
28 WriteExecute = (Write | Execute),
29 ReadWriteExecute = (Read | Write | Execute),
30 DontCare = (1u << 28)
31};
32
33class SharedMemory final : public Object { 22class SharedMemory final : public Object {
34public: 23public:
35 explicit SharedMemory(KernelCore& kernel); 24 explicit SharedMemory(KernelCore& kernel, Core::DeviceMemory& device_memory);
36 ~SharedMemory() override; 25 ~SharedMemory() override;
37 26
38 /** 27 static std::shared_ptr<SharedMemory> Create(
39 * Creates a shared memory object. 28 KernelCore& kernel, Core::DeviceMemory& device_memory, Process* owner_process,
40 * @param kernel The kernel instance to create a shared memory instance under. 29 Memory::PageLinkedList&& page_list, Memory::MemoryPermission owner_permission,
41 * @param owner_process Process that created this shared memory object. 30 Memory::MemoryPermission user_permission, PAddr physical_address, std::size_t size,
42 * @param size Size of the memory block. Must be page-aligned. 31 std::string name = "Unknown");
43 * @param permissions Permission restrictions applied to the process which created the block.
44 * @param other_permissions Permission restrictions applied to other processes mapping the
45 * block.
46 * @param address The address from which to map the Shared Memory.
47 * @param region If the address is 0, the shared memory will be allocated in this region of the
48 * linear heap.
49 * @param name Optional object name, used for debugging purposes.
50 */
51 static std::shared_ptr<SharedMemory> Create(KernelCore& kernel, Process* owner_process,
52 u64 size, MemoryPermission permissions,
53 MemoryPermission other_permissions,
54 VAddr address = 0,
55 MemoryRegion region = MemoryRegion::BASE,
56 std::string name = "Unknown");
57
58 /**
59 * Creates a shared memory object from a block of memory managed by an HLE applet.
60 * @param kernel The kernel instance to create a shared memory instance under.
61 * @param heap_block Heap block of the HLE applet.
62 * @param offset The offset into the heap block that the SharedMemory will map.
63 * @param size Size of the memory block. Must be page-aligned.
64 * @param permissions Permission restrictions applied to the process which created the block.
65 * @param other_permissions Permission restrictions applied to other processes mapping the
66 * block.
67 * @param name Optional object name, used for debugging purposes.
68 */
69 static std::shared_ptr<SharedMemory> CreateForApplet(
70 KernelCore& kernel, std::shared_ptr<Kernel::PhysicalMemory> heap_block, std::size_t offset,
71 u64 size, MemoryPermission permissions, MemoryPermission other_permissions,
72 std::string name = "Unknown Applet");
73 32
74 std::string GetTypeName() const override { 33 std::string GetTypeName() const override {
75 return "SharedMemory"; 34 return "SharedMemory";
76 } 35 }
36
77 std::string GetName() const override { 37 std::string GetName() const override {
78 return name; 38 return name;
79 } 39 }
@@ -83,71 +43,42 @@ public:
83 return HANDLE_TYPE; 43 return HANDLE_TYPE;
84 } 44 }
85 45
86 /// Gets the size of the underlying memory block in bytes.
87 u64 GetSize() const {
88 return size;
89 }
90
91 /**
92 * Converts the specified MemoryPermission into the equivalent VMAPermission.
93 * @param permission The MemoryPermission to convert.
94 */
95 static VMAPermission ConvertPermissions(MemoryPermission permission);
96
97 /** 46 /**
98 * Maps a shared memory block to an address in the target process' address space 47 * Maps a shared memory block to an address in the target process' address space
99 * @param target_process Process on which to map the memory block. 48 * @param target_process Process on which to map the memory block
100 * @param address Address in system memory to map shared memory block to 49 * @param address Address in system memory to map shared memory block to
50 * @param size Size of the shared memory block to map
101 * @param permissions Memory block map permissions (specified by SVC field) 51 * @param permissions Memory block map permissions (specified by SVC field)
102 * @param other_permissions Memory block map other permissions (specified by SVC field)
103 */
104 ResultCode Map(Process& target_process, VAddr address, MemoryPermission permissions,
105 MemoryPermission other_permissions);
106
107 /**
108 * Unmaps a shared memory block from the specified address in system memory
109 *
110 * @param target_process Process from which to unmap the memory block.
111 * @param address Address in system memory where the shared memory block is mapped.
112 * @param unmap_size The amount of bytes to unmap from this shared memory instance.
113 *
114 * @return Result code of the unmap operation
115 *
116 * @pre The given size to unmap must be the same size as the amount of memory managed by
117 * the SharedMemory instance itself, otherwise ERR_INVALID_SIZE will be returned.
118 */ 52 */
119 ResultCode Unmap(Process& target_process, VAddr address, u64 unmap_size); 53 ResultCode Map(Process& target_process, VAddr address, std::size_t size,
54 Memory::MemoryPermission permission);
120 55
121 /** 56 /**
122 * Gets a pointer to the shared memory block 57 * Gets a pointer to the shared memory block
123 * @param offset Offset from the start of the shared memory block to get pointer 58 * @param offset Offset from the start of the shared memory block to get pointer
124 * @return A pointer to the shared memory block from the specified offset 59 * @return A pointer to the shared memory block from the specified offset
125 */ 60 */
126 u8* GetPointer(std::size_t offset = 0); 61 u8* GetPointer(std::size_t offset = 0) {
62 return device_memory.GetPointer(physical_address + offset);
63 }
127 64
128 /** 65 /**
129 * Gets a constant pointer to the shared memory block 66 * Gets a pointer to the shared memory block
130 * @param offset Offset from the start of the shared memory block to get pointer 67 * @param offset Offset from the start of the shared memory block to get pointer
131 * @return A constant pointer to the shared memory block from the specified offset 68 * @return A pointer to the shared memory block from the specified offset
132 */ 69 */
133 const u8* GetPointer(std::size_t offset = 0) const; 70 const u8* GetPointer(std::size_t offset = 0) const {
71 return device_memory.GetPointer(physical_address + offset);
72 }
134 73
135private: 74private:
136 /// Backing memory for this shared memory block. 75 Core::DeviceMemory& device_memory;
137 std::shared_ptr<PhysicalMemory> backing_block; 76 Process* owner_process{};
138 /// Offset into the backing block for this shared memory. 77 Memory::PageLinkedList page_list;
139 std::size_t backing_block_offset = 0; 78 Memory::MemoryPermission owner_permission{};
140 /// Size of the memory block. Page-aligned. 79 Memory::MemoryPermission user_permission{};
141 u64 size = 0; 80 PAddr physical_address{};
142 /// Permission restrictions applied to the process which created the block. 81 std::size_t size{};
143 MemoryPermission permissions{};
144 /// Permission restrictions applied to other processes mapping the block.
145 MemoryPermission other_permissions{};
146 /// Process that created this shared memory block.
147 Process* owner_process;
148 /// Address of shared memory block in the owner process if specified.
149 VAddr base_address = 0;
150 /// Name of shared memory object.
151 std::string name; 82 std::string name;
152}; 83};
153 84