diff options
| author | 2016-04-17 21:07:52 -0500 | |
|---|---|---|
| committer | 2016-05-12 20:00:32 -0500 | |
| commit | 1bd0cf542ff8db1cda572c4d92462643296af121 (patch) | |
| tree | 8004faa76770c076e2d84d51a64c6419f796a477 | |
| parent | Kernel/SVC: Fixed the register order for svcCreateMemoryBlock. (diff) | |
| download | yuzu-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.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/applets/swkbd.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.cpp | 116 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.h | 28 | ||||
| -rw-r--r-- | src/core/hle/service/apt/apt.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/service/csnd_snd.cpp | 13 | ||||
| -rw-r--r-- | src/core/hle/service/gsp_gpu.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/hid/hid.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/ir/ir.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 47 |
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 | ||
| 12 | namespace Kernel { | 13 | namespace Kernel { |
| @@ -14,93 +15,94 @@ namespace Kernel { | |||
| 14 | SharedMemory::SharedMemory() {} | 15 | SharedMemory::SharedMemory() {} |
| 15 | SharedMemory::~SharedMemory() {} | 16 | SharedMemory::~SharedMemory() {} |
| 16 | 17 | ||
| 17 | SharedPtr<SharedMemory> SharedMemory::Create(u32 size, MemoryPermission permissions, | 18 | SharedPtr<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 | ||
| 31 | ResultCode SharedMemory::Map(VAddr address, MemoryPermission permissions, | 65 | ResultCode 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 | ||
| 83 | ResultCode SharedMemory::Unmap(VAddr address) { | 99 | ResultCode 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 | ||
| 98 | u8* SharedMemory::GetPointer(u32 offset) { | 104 | u8* 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 | ||
| 14 | namespace Kernel { | 15 | namespace Kernel { |
| @@ -30,13 +31,16 @@ class SharedMemory final : public Object { | |||
| 30 | public: | 31 | public: |
| 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; | |||
| 37 | static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event | 37 | static Kernel::SharedPtr<Kernel::Event> notification_event; ///< APT notification event |
| 38 | static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event | 38 | static Kernel::SharedPtr<Kernel::Event> parameter_event; ///< APT parameter event |
| 39 | 39 | ||
| 40 | static std::shared_ptr<std::vector<u8>> shared_font; | ||
| 41 | |||
| 42 | static u32 cpu_percent; ///< CPU time available to the running application | 40 | static 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) { | |||
| 74 | void GetSharedFont(Service::Interface* self) { | 72 | void 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 | ||
| 96 | void NotifyToWait(Service::Interface* self) { | 85 | void 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 | ||
| 461 | void Shutdown() { | 448 | void 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; | |||
| 41 | void Initialize(Service::Interface* self) { | 42 | void 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 | ||