summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Subv2016-04-17 21:07:52 -0500
committerGravatar Subv2016-05-12 20:00:32 -0500
commit1bd0cf542ff8db1cda572c4d92462643296af121 (patch)
tree8004faa76770c076e2d84d51a64c6419f796a477 /src
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.
Diffstat (limited to 'src')
-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