diff options
| author | 2016-04-17 21:07:52 -0500 | |
|---|---|---|
| committer | 2016-05-12 20:00:32 -0500 | |
| commit | 1bd0cf542ff8db1cda572c4d92462643296af121 (patch) | |
| tree | 8004faa76770c076e2d84d51a64c6419f796a477 /src/core/hle/svc.cpp | |
| 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.
Diffstat (limited to 'src/core/hle/svc.cpp')
| -rw-r--r-- | src/core/hle/svc.cpp | 47 |
1 files changed, 35 insertions, 12 deletions
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 | ||