summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Subv2016-04-17 21:07:52 -0500
committerGravatar Subv2016-05-12 20:00:32 -0500
commit1bd0cf542ff8db1cda572c4d92462643296af121 (patch)
tree8004faa76770c076e2d84d51a64c6419f796a477
parentKernel/SVC: Fixed the register order for svcCreateMemoryBlock. (diff)
downloadyuzu-1bd0cf542ff8db1cda572c4d92462643296af121.tar.gz
yuzu-1bd0cf542ff8db1cda572c4d92462643296af121.tar.xz
yuzu-1bd0cf542ff8db1cda572c4d92462643296af121.zip
Kernel/SharedMemory: Properly implemented shared memory support.
Applications can request the kernel to allocate a piece of the linear heap for them when creating a shared memory object. Shared memory areas are now properly mapped into the target processes when calling svcMapMemoryBlock. Removed the APT Shared Font hack as it is no longer needed.
-rw-r--r--src/core/hle/applets/mii_selector.cpp4
-rw-r--r--src/core/hle/applets/swkbd.cpp4
-rw-r--r--src/core/hle/kernel/shared_memory.cpp116
-rw-r--r--src/core/hle/kernel/shared_memory.h28
-rw-r--r--src/core/hle/service/apt/apt.cpp38
-rw-r--r--src/core/hle/service/csnd_snd.cpp13
-rw-r--r--src/core/hle/service/gsp_gpu.cpp5
-rw-r--r--src/core/hle/service/hid/hid.cpp5
-rw-r--r--src/core/hle/service/ir/ir.cpp5
-rw-r--r--src/core/hle/svc.cpp47
10 files changed, 147 insertions, 118 deletions
diff --git a/src/core/hle/applets/mii_selector.cpp b/src/core/hle/applets/mii_selector.cpp
index b4456ca90..7f174f3e6 100644
--- a/src/core/hle/applets/mii_selector.cpp
+++ b/src/core/hle/applets/mii_selector.cpp
@@ -36,8 +36,8 @@ ResultCode MiiSelector::ReceiveParameter(const Service::APT::MessageParameter& p
36 36
37 memcpy(&capture_info, parameter.data, sizeof(capture_info)); 37 memcpy(&capture_info, parameter.data, sizeof(capture_info));
38 using Kernel::MemoryPermission; 38 using Kernel::MemoryPermission;
39 framebuffer_memory = Kernel::SharedMemory::Create(capture_info.size, MemoryPermission::ReadWrite, 39 framebuffer_memory = Kernel::SharedMemory::Create(nullptr, capture_info.size, MemoryPermission::ReadWrite,
40 MemoryPermission::ReadWrite, "MiiSelector Memory"); 40 MemoryPermission::ReadWrite, 0, Kernel::MemoryRegion::BASE, "MiiSelector Memory");
41 41
42 // Send the response message with the newly created SharedMemory 42 // Send the response message with the newly created SharedMemory
43 Service::APT::MessageParameter result; 43 Service::APT::MessageParameter result;
diff --git a/src/core/hle/applets/swkbd.cpp b/src/core/hle/applets/swkbd.cpp
index 87238aa1c..e0c134182 100644
--- a/src/core/hle/applets/swkbd.cpp
+++ b/src/core/hle/applets/swkbd.cpp
@@ -40,8 +40,8 @@ ResultCode SoftwareKeyboard::ReceiveParameter(Service::APT::MessageParameter con
40 memcpy(&capture_info, parameter.data, sizeof(capture_info)); 40 memcpy(&capture_info, parameter.data, sizeof(capture_info));
41 41
42 using Kernel::MemoryPermission; 42 using Kernel::MemoryPermission;
43 framebuffer_memory = Kernel::SharedMemory::Create(capture_info.size, MemoryPermission::ReadWrite, 43 framebuffer_memory = Kernel::SharedMemory::Create(nullptr, capture_info.size, MemoryPermission::ReadWrite,
44 MemoryPermission::ReadWrite, "SoftwareKeyboard Memory"); 44 MemoryPermission::ReadWrite, 0, Kernel::MemoryRegion::BASE, "SoftwareKeyboard Memory");
45 45
46 // Send the response message with the newly created SharedMemory 46 // Send the response message with the newly created SharedMemory
47 Service::APT::MessageParameter result; 47 Service::APT::MessageParameter result;
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index d90f0f00f..6f731f317 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -7,6 +7,7 @@
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8 8
9#include "core/memory.h" 9#include "core/memory.h"
10#include "core/hle/kernel/memory.h"
10#include "core/hle/kernel/shared_memory.h" 11#include "core/hle/kernel/shared_memory.h"
11 12
12namespace Kernel { 13namespace Kernel {
@@ -14,93 +15,94 @@ namespace Kernel {
14SharedMemory::SharedMemory() {} 15SharedMemory::SharedMemory() {}
15SharedMemory::~SharedMemory() {} 16SharedMemory::~SharedMemory() {}
16 17
17SharedPtr<SharedMemory> SharedMemory::Create(u32 size, MemoryPermission permissions, 18SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions,
18 MemoryPermission other_permissions, std::string name) { 19 MemoryPermission other_permissions, VAddr address, MemoryRegion region, std::string name) {
19 SharedPtr<SharedMemory> shared_memory(new SharedMemory); 20 SharedPtr<SharedMemory> shared_memory(new SharedMemory);
20 21
22 shared_memory->owner_process = owner_process;
21 shared_memory->name = std::move(name); 23 shared_memory->name = std::move(name);
22 shared_memory->base_address = 0x0;
23 shared_memory->fixed_address = 0x0;
24 shared_memory->size = size; 24 shared_memory->size = size;
25 shared_memory->permissions = permissions; 25 shared_memory->permissions = permissions;
26 shared_memory->other_permissions = other_permissions; 26 shared_memory->other_permissions = other_permissions;
27 27
28 if (address == 0) {
29 // We need to allocate a block from the Linear Heap ourselves.
30 // We'll manually allocate some memory from the linear heap in the specified region.
31 MemoryRegionInfo* memory_region = GetMemoryRegion(region);
32 auto& linheap_memory = memory_region->linear_heap_memory;
33
34 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, "Not enough space in region to allocate shared memory!");
35
36 shared_memory->backing_block = linheap_memory;
37 shared_memory->backing_block_offset = linheap_memory->size();
38 // Allocate some memory from the end of the linear heap for this region.
39 linheap_memory->insert(linheap_memory->end(), size, 0);
40 memory_region->used += size;
41
42 shared_memory->linear_heap_phys_address = Memory::FCRAM_PADDR + memory_region->base + shared_memory->backing_block_offset;
43
44 // Refresh the address mappings for the current process.
45 if (Kernel::g_current_process != nullptr) {
46 Kernel::g_current_process->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
47 }
48 } else {
49 auto& vm_manager = shared_memory->owner_process->vm_manager;
50 // The memory is already available and mapped in the owner process.
51 auto vma = vm_manager.FindVMA(address)->second;
52 // Copy it over to our own storage
53 shared_memory->backing_block = std::make_shared<std::vector<u8>>(vma.backing_block->data() + vma.offset,
54 vma.backing_block->data() + vma.offset + size);
55 // Unmap the existing pages
56 vm_manager.UnmapRange(address, size);
57 // Map our own block into the address space
58 vm_manager.MapMemoryBlock(address, shared_memory->backing_block, 0, size, MemoryState::Shared);
59 }
60
61 shared_memory->base_address = address;
28 return shared_memory; 62 return shared_memory;
29} 63}
30 64
31ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, 65ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermission permissions,
32 MemoryPermission other_permissions) { 66 MemoryPermission other_permissions) {
33 67
34 if (base_address != 0) {
35 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s: already mapped at 0x%08X!",
36 GetObjectId(), address, name.c_str(), base_address);
37 // TODO: Verify error code with hardware
38 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
39 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
40 }
41
42 // TODO(Subv): Return E0E01BEE when permissions and other_permissions don't 68 // TODO(Subv): Return E0E01BEE when permissions and other_permissions don't
43 // match what was specified when the memory block was created. 69 // match what was specified when the memory block was created.
44 70
45 // TODO(Subv): Return E0E01BEE when address should be 0. 71 // TODO(Subv): Check for the Shared Device Mem flag in the creator process.
46 // Note: Find out when that's the case. 72 /*if (was_created_with_shared_device_mem && address != 0) {
73 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
74 }*/
47 75
48 if (fixed_address != 0) { 76 // TODO(Subv): The same process that created a SharedMemory object
49 if (address != 0 && address != fixed_address) { 77 // can not map it in its own address space unless it was created with addr=0, result 0xD900182C.
50 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s: fixed_addres is 0x%08X!",
51 GetObjectId(), address, name.c_str(), fixed_address);
52 // TODO: Verify error code with hardware
53 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel,
54 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
55 }
56
57 // HACK(yuriks): This is only here to support the APT shared font mapping right now.
58 // Later, this should actually map the memory block onto the address space.
59 return RESULT_SUCCESS;
60 }
61 78
62 if (address < Memory::SHARED_MEMORY_VADDR || address + size >= Memory::SHARED_MEMORY_VADDR_END) { 79 if (address < Memory::HEAP_VADDR || address + size >= Memory::SHARED_MEMORY_VADDR_END) {
63 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s outside of shared mem bounds!", 80 LOG_ERROR(Kernel, "cannot map id=%u, address=0x%08X name=%s, invalid address",
64 GetObjectId(), address, name.c_str()); 81 GetObjectId(), address, name.c_str());
65 // TODO: Verify error code with hardware 82 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS,
66 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::Kernel, 83 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
67 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
68 } 84 }
69 85
70 // TODO: Test permissions 86 VAddr target_address = address;
71 87
72 // HACK: Since there's no way to write to the memory block without mapping it onto the game 88 if (base_address == 0 && target_address == 0) {
73 // process yet, at least initialize memory the first time it's mapped. 89 // Calculate the address at which to map the memory block.
74 if (address != this->base_address) { 90 target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address);
75 std::memset(Memory::GetPointer(address), 0, size);
76 } 91 }
77 92
78 this->base_address = address; 93 // Map the memory block into the target process
94 target_process->vm_manager.MapMemoryBlock(target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
79 95
80 return RESULT_SUCCESS; 96 return RESULT_SUCCESS;
81} 97}
82 98
83ResultCode SharedMemory::Unmap(VAddr address) { 99ResultCode SharedMemory::Unmap(Process* target_process, VAddr address) {
84 if (base_address == 0) { 100 // TODO(Subv): Verify what happens if the application tries to unmap an address that is not mapped to a SharedMemory.
85 // TODO(Subv): Verify what actually happens when you want to unmap a memory block that 101 return target_process->vm_manager.UnmapRange(address, size);
86 // was originally mapped with address = 0
87 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
88 }
89
90 if (base_address != address)
91 return ResultCode(ErrorDescription::WrongAddress, ErrorModule::OS, ErrorSummary::InvalidState, ErrorLevel::Usage);
92
93 base_address = 0;
94
95 return RESULT_SUCCESS;
96} 102}
97 103
98u8* SharedMemory::GetPointer(u32 offset) { 104u8* SharedMemory::GetPointer(u32 offset) {
99 if (base_address != 0) 105 return backing_block->data() + backing_block_offset + offset;
100 return Memory::GetPointer(base_address + offset);
101
102 LOG_ERROR(Kernel_SVC, "memory block id=%u not mapped!", GetObjectId());
103 return nullptr;
104} 106}
105 107
106} // namespace 108} // namespace
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index b51049ad0..b442cb764 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -9,6 +9,7 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10 10
11#include "core/hle/kernel/kernel.h" 11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/process.h"
12#include "core/hle/result.h" 13#include "core/hle/result.h"
13 14
14namespace Kernel { 15namespace Kernel {
@@ -30,13 +31,16 @@ class SharedMemory final : public Object {
30public: 31public:
31 /** 32 /**
32 * Creates a shared memory object 33 * Creates a shared memory object
34 * @param owner_process Process that created this shared memory object.
33 * @param size Size of the memory block. Must be page-aligned. 35 * @param size Size of the memory block. Must be page-aligned.
34 * @param permissions Permission restrictions applied to the process which created the block. 36 * @param permissions Permission restrictions applied to the process which created the block.
35 * @param other_permissions Permission restrictions applied to other processes mapping the block. 37 * @param other_permissions Permission restrictions applied to other processes mapping the block.
38 * @param address The address from which to map the Shared Memory.
39 * @param region If the address is 0, the shared memory will be allocated in this region of the linear heap.
36 * @param name Optional object name, used for debugging purposes. 40 * @param name Optional object name, used for debugging purposes.
37 */ 41 */
38 static SharedPtr<SharedMemory> Create(u32 size, MemoryPermission permissions, 42 static SharedPtr<SharedMemory> Create(SharedPtr<Process> owner_process, u32 size, MemoryPermission permissions,
39 MemoryPermission other_permissions, std::string name = "Unknown"); 43 MemoryPermission other_permissions, VAddr address = 0, MemoryRegion region = MemoryRegion::BASE, std::string name = "Unknown");
40 44
41 std::string GetTypeName() const override { return "SharedMemory"; } 45 std::string GetTypeName() const override { return "SharedMemory"; }
42 std::string GetName() const override { return name; } 46 std::string GetName() const override { return name; }
@@ -45,19 +49,21 @@ public:
45 HandleType GetHandleType() const override { return HANDLE_TYPE; } 49 HandleType GetHandleType() const override { return HANDLE_TYPE; }
46 50
47 /** 51 /**
48 * Maps a shared memory block to an address in system memory 52 * Maps a shared memory block to an address in the target process' address space
53 * @param target_process Process on which to map the memory block.
49 * @param address Address in system memory to map shared memory block to 54 * @param address Address in system memory to map shared memory block to
50 * @param permissions Memory block map permissions (specified by SVC field) 55 * @param permissions Memory block map permissions (specified by SVC field)
51 * @param other_permissions Memory block map other permissions (specified by SVC field) 56 * @param other_permissions Memory block map other permissions (specified by SVC field)
52 */ 57 */
53 ResultCode Map(VAddr address, MemoryPermission permissions, MemoryPermission other_permissions); 58 ResultCode Map(Process* target_process, VAddr address, MemoryPermission permissions, MemoryPermission other_permissions);
54 59
55 /** 60 /**
56 * Unmaps a shared memory block from the specified address in system memory 61 * Unmaps a shared memory block from the specified address in system memory
62 * @param target_process Process from which to umap the memory block.
57 * @param address Address in system memory where the shared memory block is mapped 63 * @param address Address in system memory where the shared memory block is mapped
58 * @return Result code of the unmap operation 64 * @return Result code of the unmap operation
59 */ 65 */
60 ResultCode Unmap(VAddr address); 66 ResultCode Unmap(Process* target_process, VAddr address);
61 67
62 /** 68 /**
63 * Gets a pointer to the shared memory block 69 * Gets a pointer to the shared memory block
@@ -66,10 +72,16 @@ public:
66 */ 72 */
67 u8* GetPointer(u32 offset = 0); 73 u8* GetPointer(u32 offset = 0);
68 74
69 /// Address of shared memory block in the process. 75 /// Process that created this shared memory block.
76 SharedPtr<Process> owner_process;
77 /// Address of shared memory block in the owner process if specified.
70 VAddr base_address; 78 VAddr base_address;
71 /// Fixed address to allow mapping to. Used for blocks created from the linear heap. 79 /// Physical address of the shared memory block in the linear heap if no address was specified during creation.
72 VAddr fixed_address; 80 PAddr linear_heap_phys_address;
81 /// Backing memory for this shared memory block.
82 std::shared_ptr<std::vector<u8>> backing_block;
83 /// Offset into the backing block for this shared memory.
84 u32 backing_block_offset;
73 /// Size of the memory block. Page-aligned. 85 /// Size of the memory block. Page-aligned.
74 u32 size; 86 u32 size;
75 /// Permission restrictions applied to the process which created the block. 87 /// Permission restrictions applied to the process which created the block.
diff --git a/src/core/hle/service/apt/apt.cpp b/src/core/hle/service/apt/apt.cpp
index 6d72e8188..e7b8f5305 100644
--- a/src/core/hle/service/apt/apt.cpp
+++ b/src/core/hle/service/apt/apt.cpp
@@ -37,8 +37,6 @@ static Kernel::SharedPtr<Kernel::Mutex> lock;
37static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event 37static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event
38static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event 38static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event
39 39
40static std::shared_ptr<std::vector<u8>> shared_font;
41
42static u32 cpu_percent; ///< CPU time available to the running application 40static u32 cpu_percent; ///< CPU time available to the running application
43 41
44/// Parameter data to be returned in the next call to Glance/ReceiveParameter 42/// Parameter data to be returned in the next call to Glance/ReceiveParameter
@@ -74,23 +72,14 @@ void Initialize(Service::Interface* self) {
74void GetSharedFont(Service::Interface* self) { 72void GetSharedFont(Service::Interface* self) {
75 u32* cmd_buff = Kernel::GetCommandBuffer(); 73 u32* cmd_buff = Kernel::GetCommandBuffer();
76 74
77 if (shared_font != nullptr) { 75 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2);
78 // TODO(yuriks): This is a hack to keep this working right now even with our completely 76 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
79 // broken shared memory system. 77 // Since the SharedMemory interface doesn't provide the address at which the memory was allocated,
80 shared_font_mem->fixed_address = SHARED_FONT_VADDR; 78 // the APT service calculates this address by scanning the entire address space (using svcQueryMemory)
81 Kernel::g_current_process->vm_manager.MapMemoryBlock(shared_font_mem->fixed_address, 79 // and searches for an allocation of the same size as the Shared Font.
82 shared_font, 0, shared_font_mem->size, Kernel::MemoryState::Shared); 80 cmd_buff[2] = Memory::PhysicalToVirtualAddress(shared_font_mem->linear_heap_phys_address);
83 81 cmd_buff[3] = IPC::MoveHandleDesc();
84 cmd_buff[0] = IPC::MakeHeader(0x44, 2, 2); 82 cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom();
85 cmd_buff[1] = RESULT_SUCCESS.raw; // No error
86 cmd_buff[2] = SHARED_FONT_VADDR;
87 cmd_buff[3] = IPC::MoveHandleDesc();
88 cmd_buff[4] = Kernel::g_handle_table.Create(shared_font_mem).MoveFrom();
89 } else {
90 cmd_buff[0] = IPC::MakeHeader(0x44, 1, 0);
91 cmd_buff[1] = -1; // Generic error (not really possible to verify this on hardware)
92 LOG_ERROR(Kernel_SVC, "called, but %s has not been loaded!", SHARED_FONT);
93 }
94} 83}
95 84
96void NotifyToWait(Service::Interface* self) { 85void NotifyToWait(Service::Interface* self) {
@@ -433,14 +422,12 @@ void Init() {
433 FileUtil::IOFile file(filepath, "rb"); 422 FileUtil::IOFile file(filepath, "rb");
434 423
435 if (file.IsOpen()) { 424 if (file.IsOpen()) {
436 // Read shared font data
437 shared_font = std::make_shared<std::vector<u8>>((size_t)file.GetSize());
438 file.ReadBytes(shared_font->data(), shared_font->size());
439
440 // Create shared font memory object 425 // Create shared font memory object
441 using Kernel::MemoryPermission; 426 using Kernel::MemoryPermission;
442 shared_font_mem = Kernel::SharedMemory::Create(3 * 1024 * 1024, // 3MB 427 shared_font_mem = Kernel::SharedMemory::Create(nullptr, 0x332000, // 3272 KB
443 MemoryPermission::ReadWrite, MemoryPermission::Read, "APT_U:shared_font_mem"); 428 MemoryPermission::ReadWrite, MemoryPermission::Read, 0, Kernel::MemoryRegion::SYSTEM, "APT:SharedFont");
429 // Read shared font data
430 file.ReadBytes(shared_font_mem->GetPointer(), file.GetSize());
444 } else { 431 } else {
445 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str()); 432 LOG_WARNING(Service_APT, "Unable to load shared font: %s", filepath.c_str());
446 shared_font_mem = nullptr; 433 shared_font_mem = nullptr;
@@ -459,7 +446,6 @@ void Init() {
459} 446}
460 447
461void Shutdown() { 448void Shutdown() {
462 shared_font = nullptr;
463 shared_font_mem = nullptr; 449 shared_font_mem = nullptr;
464 lock = nullptr; 450 lock = nullptr;
465 notification_event = nullptr; 451 notification_event = nullptr;
diff --git a/src/core/hle/service/csnd_snd.cpp b/src/core/hle/service/csnd_snd.cpp
index 6318bf2a7..d2bb8941c 100644
--- a/src/core/hle/service/csnd_snd.cpp
+++ b/src/core/hle/service/csnd_snd.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <cstring> 5#include <cstring>
6#include "common/alignment.h"
6#include "core/hle/hle.h" 7#include "core/hle/hle.h"
7#include "core/hle/kernel/mutex.h" 8#include "core/hle/kernel/mutex.h"
8#include "core/hle/kernel/shared_memory.h" 9#include "core/hle/kernel/shared_memory.h"
@@ -41,14 +42,16 @@ static Kernel::SharedPtr<Kernel::Mutex> mutex = nullptr;
41void Initialize(Service::Interface* self) { 42void Initialize(Service::Interface* self) {
42 u32* cmd_buff = Kernel::GetCommandBuffer(); 43 u32* cmd_buff = Kernel::GetCommandBuffer();
43 44
44 shared_memory = Kernel::SharedMemory::Create(cmd_buff[1], 45 u32 size = Common::AlignUp(cmd_buff[1], Memory::PAGE_SIZE);
45 Kernel::MemoryPermission::ReadWrite, 46 using Kernel::MemoryPermission;
46 Kernel::MemoryPermission::ReadWrite, "CSNDSharedMem"); 47 shared_memory = Kernel::SharedMemory::Create(nullptr, size,
48 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
49 0, Kernel::MemoryRegion::BASE, "CSND:SharedMemory");
47 50
48 mutex = Kernel::Mutex::Create(false); 51 mutex = Kernel::Mutex::Create(false);
49 52
50 cmd_buff[1] = 0; 53 cmd_buff[1] = RESULT_SUCCESS.raw;
51 cmd_buff[2] = 0x4000000; 54 cmd_buff[2] = IPC::MoveHandleDesc(2);
52 cmd_buff[3] = Kernel::g_handle_table.Create(mutex).MoveFrom(); 55 cmd_buff[3] = Kernel::g_handle_table.Create(mutex).MoveFrom();
53 cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).MoveFrom(); 56 cmd_buff[4] = Kernel::g_handle_table.Create(shared_memory).MoveFrom();
54} 57}
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index b4c146e08..8ded9b09b 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -335,8 +335,9 @@ static void RegisterInterruptRelayQueue(Service::Interface* self) {
335 g_interrupt_event->name = "GSP_GPU::interrupt_event"; 335 g_interrupt_event->name = "GSP_GPU::interrupt_event";
336 336
337 using Kernel::MemoryPermission; 337 using Kernel::MemoryPermission;
338 g_shared_memory = Kernel::SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, 338 g_shared_memory = Kernel::SharedMemory::Create(nullptr, 0x1000,
339 MemoryPermission::ReadWrite, "GSPSharedMem"); 339 MemoryPermission::ReadWrite, MemoryPermission::ReadWrite,
340 0, Kernel::MemoryRegion::BASE, "GSP:SharedMemory");
340 341
341 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom(); 342 Handle shmem_handle = Kernel::g_handle_table.Create(g_shared_memory).MoveFrom();
342 343
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 1053d0f40..d216cecb4 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -280,8 +280,9 @@ void Init() {
280 AddService(new HID_SPVR_Interface); 280 AddService(new HID_SPVR_Interface);
281 281
282 using Kernel::MemoryPermission; 282 using Kernel::MemoryPermission;
283 shared_mem = SharedMemory::Create(0x1000, MemoryPermission::ReadWrite, 283 shared_mem = SharedMemory::Create(nullptr, 0x1000,
284 MemoryPermission::Read, "HID:SharedMem"); 284 MemoryPermission::ReadWrite, MemoryPermission::Read,
285 0, Kernel::MemoryRegion::BASE, "HID:SharedMemory");
285 286
286 next_pad_index = 0; 287 next_pad_index = 0;
287 next_touch_index = 0; 288 next_touch_index = 0;
diff --git a/src/core/hle/service/ir/ir.cpp b/src/core/hle/service/ir/ir.cpp
index 505c441c6..079a87e48 100644
--- a/src/core/hle/service/ir/ir.cpp
+++ b/src/core/hle/service/ir/ir.cpp
@@ -94,8 +94,9 @@ void Init() {
94 AddService(new IR_User_Interface); 94 AddService(new IR_User_Interface);
95 95
96 using Kernel::MemoryPermission; 96 using Kernel::MemoryPermission;
97 shared_memory = SharedMemory::Create(0x1000, Kernel::MemoryPermission::ReadWrite, 97 shared_memory = SharedMemory::Create(nullptr, 0x1000,
98 Kernel::MemoryPermission::ReadWrite, "IR:SharedMemory"); 98 Kernel::MemoryPermission::ReadWrite, Kernel::MemoryPermission::ReadWrite,
99 0, Kernel::MemoryRegion::BASE, "IR:SharedMemory");
99 transfer_shared_memory = nullptr; 100 transfer_shared_memory = nullptr;
100 101
101 // Create event handle(s) 102 // Create event handle(s)
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 60c8747f3..701dffef3 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -160,8 +160,6 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
160 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d", 160 LOG_TRACE(Kernel_SVC, "called memblock=0x%08X, addr=0x%08X, mypermissions=0x%08X, otherpermission=%d",
161 handle, addr, permissions, other_permissions); 161 handle, addr, permissions, other_permissions);
162 162
163 // TODO(Subv): The same process that created a SharedMemory object can not map it in its own address space
164
165 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle); 163 SharedPtr<SharedMemory> shared_memory = Kernel::g_handle_table.Get<SharedMemory>(handle);
166 if (shared_memory == nullptr) 164 if (shared_memory == nullptr)
167 return ERR_INVALID_HANDLE; 165 return ERR_INVALID_HANDLE;
@@ -176,7 +174,7 @@ static ResultCode MapMemoryBlock(Handle handle, u32 addr, u32 permissions, u32 o
176 case MemoryPermission::WriteExecute: 174 case MemoryPermission::WriteExecute:
177 case MemoryPermission::ReadWriteExecute: 175 case MemoryPermission::ReadWriteExecute:
178 case MemoryPermission::DontCare: 176 case MemoryPermission::DontCare:
179 return shared_memory->Map(addr, permissions_type, 177 return shared_memory->Map(Kernel::g_current_process.get(), addr, permissions_type,
180 static_cast<MemoryPermission>(other_permissions)); 178 static_cast<MemoryPermission>(other_permissions));
181 default: 179 default:
182 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 180 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
@@ -196,7 +194,7 @@ static ResultCode UnmapMemoryBlock(Handle handle, u32 addr) {
196 if (shared_memory == nullptr) 194 if (shared_memory == nullptr)
197 return ERR_INVALID_HANDLE; 195 return ERR_INVALID_HANDLE;
198 196
199 return shared_memory->Unmap(addr); 197 return shared_memory->Unmap(Kernel::g_current_process.get(), addr);
200} 198}
201 199
202/// Connect to an OS service given the port name, returns the handle to the port to out 200/// Connect to an OS service given the port name, returns the handle to the port to out
@@ -790,18 +788,43 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
790 if (size % Memory::PAGE_SIZE != 0) 788 if (size % Memory::PAGE_SIZE != 0)
791 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage); 789 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
792 790
793 // TODO(Subv): Return E0A01BF5 if the address is not in the application's heap 791 SharedPtr<SharedMemory> shared_memory = nullptr;
794
795 // TODO(Subv): Implement this function properly
796 792
797 using Kernel::MemoryPermission; 793 using Kernel::MemoryPermission;
798 SharedPtr<SharedMemory> shared_memory = SharedMemory::Create(size, 794 auto VerifyPermissions = [](MemoryPermission permission) {
799 (MemoryPermission)my_permission, (MemoryPermission)other_permission); 795 // SharedMemory blocks can not be created with Execute permissions
800 // Map the SharedMemory to the specified address 796 switch (permission) {
801 shared_memory->base_address = addr; 797 case MemoryPermission::None:
798 case MemoryPermission::Read:
799 case MemoryPermission::Write:
800 case MemoryPermission::ReadWrite:
801 return true;
802 default:
803 return false;
804 }
805 };
806
807 if (!VerifyPermissions(static_cast<MemoryPermission>(my_permission)) ||
808 !VerifyPermissions(static_cast<MemoryPermission>(other_permission)))
809 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS,
810 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
811
812 if (addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) {
813 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, ErrorSummary::InvalidArgument, ErrorLevel::Usage);
814 }
815
816 // When trying to create a memory block with address = 0,
817 // if the process has the Shared Device Memory flag in the exheader,
818 // then we have to allocate from the same region as the caller process instead of the BASE region.
819 Kernel::MemoryRegion region = Kernel::MemoryRegion::BASE;
820 if (addr == 0 && Kernel::g_current_process->flags.shared_device_mem)
821 region = Kernel::g_current_process->flags.memory_region;
822
823 shared_memory = SharedMemory::Create(Kernel::g_current_process, size,
824 static_cast<MemoryPermission>(my_permission), static_cast<MemoryPermission>(other_permission), addr, region);
802 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory))); 825 CASCADE_RESULT(*out_handle, Kernel::g_handle_table.Create(std::move(shared_memory)));
803 826
804 LOG_WARNING(Kernel_SVC, "(STUBBED) called addr=0x%08X", addr); 827 LOG_WARNING(Kernel_SVC, "called addr=0x%08X", addr);
805 return RESULT_SUCCESS; 828 return RESULT_SUCCESS;
806} 829}
807 830