diff options
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 27 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 32 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc_wrap.h | 8 |
4 files changed, 67 insertions, 1 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index 99982e5a3..f2f88c147 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -806,6 +806,33 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) { | |||
| 806 | KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); | 806 | KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); |
| 807 | 807 | ||
| 808 | block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite); | 808 | block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite); |
| 809 | return ResultSuccess; | ||
| 810 | } | ||
| 811 | |||
| 812 | ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size, | ||
| 813 | Svc::MemoryPermission svc_perm) { | ||
| 814 | const size_t num_pages = size / PageSize; | ||
| 815 | |||
| 816 | // Lock the table. | ||
| 817 | std::lock_guard lock{page_table_lock}; | ||
| 818 | |||
| 819 | // Verify we can change the memory permission. | ||
| 820 | KMemoryState old_state; | ||
| 821 | KMemoryPermission old_perm; | ||
| 822 | R_TRY(this->CheckMemoryState( | ||
| 823 | std::addressof(old_state), std::addressof(old_perm), nullptr, addr, size, | ||
| 824 | KMemoryState::FlagCanReprotect, KMemoryState::FlagCanReprotect, KMemoryPermission::None, | ||
| 825 | KMemoryPermission::None, KMemoryAttribute::All, KMemoryAttribute::None)); | ||
| 826 | |||
| 827 | // Determine new perm. | ||
| 828 | const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm); | ||
| 829 | R_SUCCEED_IF(old_perm == new_perm); | ||
| 830 | |||
| 831 | // Perform mapping operation. | ||
| 832 | R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions)); | ||
| 833 | |||
| 834 | // Update the blocks. | ||
| 835 | block_manager->Update(addr, num_pages, old_state, new_perm, KMemoryAttribute::None); | ||
| 809 | 836 | ||
| 810 | return ResultSuccess; | 837 | return ResultSuccess; |
| 811 | } | 838 | } |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index d784aa67e..db08ea8ce 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -47,6 +47,7 @@ public: | |||
| 47 | KMemoryInfo QueryInfo(VAddr addr); | 47 | KMemoryInfo QueryInfo(VAddr addr); |
| 48 | ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); | 48 | ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); |
| 49 | ResultCode ResetTransferMemory(VAddr addr, std::size_t size); | 49 | ResultCode ResetTransferMemory(VAddr addr, std::size_t size); |
| 50 | ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm); | ||
| 50 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, | 51 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, |
| 51 | KMemoryAttribute value); | 52 | KMemoryAttribute value); |
| 52 | ResultCode SetHeapCapacity(std::size_t new_heap_capacity); | 53 | ResultCode SetHeapCapacity(std::size_t new_heap_capacity); |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 37d67b72e..68cb47211 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -164,6 +164,36 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s | |||
| 164 | return result; | 164 | return result; |
| 165 | } | 165 | } |
| 166 | 166 | ||
| 167 | constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) { | ||
| 168 | switch (perm) { | ||
| 169 | case MemoryPermission::None: | ||
| 170 | case MemoryPermission::Read: | ||
| 171 | case MemoryPermission::ReadWrite: | ||
| 172 | return true; | ||
| 173 | default: | ||
| 174 | return false; | ||
| 175 | } | ||
| 176 | } | ||
| 177 | |||
| 178 | static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size, | ||
| 179 | MemoryPermission perm) { | ||
| 180 | // Validate address / size. | ||
| 181 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); | ||
| 182 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | ||
| 183 | R_UNLESS(size > 0, ResultInvalidSize); | ||
| 184 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); | ||
| 185 | |||
| 186 | // Validate the permission. | ||
| 187 | R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission); | ||
| 188 | |||
| 189 | // Validate that the region is in range for the current process. | ||
| 190 | auto& page_table = system.Kernel().CurrentProcess()->PageTable(); | ||
| 191 | R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); | ||
| 192 | |||
| 193 | // Set the memory attribute. | ||
| 194 | return page_table.SetMemoryPermission(address, size, perm); | ||
| 195 | } | ||
| 196 | |||
| 167 | static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, | 197 | static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, |
| 168 | u32 attribute) { | 198 | u32 attribute) { |
| 169 | LOG_DEBUG(Kernel_SVC, | 199 | LOG_DEBUG(Kernel_SVC, |
| @@ -2724,7 +2754,7 @@ static const FunctionDef SVC_Table_32[] = { | |||
| 2724 | static const FunctionDef SVC_Table_64[] = { | 2754 | static const FunctionDef SVC_Table_64[] = { |
| 2725 | {0x00, nullptr, "Unknown"}, | 2755 | {0x00, nullptr, "Unknown"}, |
| 2726 | {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"}, | 2756 | {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"}, |
| 2727 | {0x02, nullptr, "SetMemoryPermission"}, | 2757 | {0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"}, |
| 2728 | {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"}, | 2758 | {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"}, |
| 2729 | {0x04, SvcWrap64<MapMemory>, "MapMemory"}, | 2759 | {0x04, SvcWrap64<MapMemory>, "MapMemory"}, |
| 2730 | {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"}, | 2760 | {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"}, |
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h index 86255fe6d..a60adfcab 100644 --- a/src/core/hle/kernel/svc_wrap.h +++ b/src/core/hle/kernel/svc_wrap.h | |||
| @@ -249,6 +249,14 @@ void SvcWrap64(Core::System& system) { | |||
| 249 | func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); | 249 | func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | // Used by SetMemoryPermission | ||
| 253 | template <ResultCode func(Core::System&, u64, u64, Svc::MemoryPermission)> | ||
| 254 | void SvcWrap64(Core::System& system) { | ||
| 255 | FuncReturn(system, func(system, Param(system, 0), Param(system, 1), | ||
| 256 | static_cast<Svc::MemoryPermission>(Param(system, 2))) | ||
| 257 | .raw); | ||
| 258 | } | ||
| 259 | |||
| 252 | // Used by MapSharedMemory | 260 | // Used by MapSharedMemory |
| 253 | template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)> | 261 | template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)> |
| 254 | void SvcWrap64(Core::System& system) { | 262 | void SvcWrap64(Core::System& system) { |