diff options
| author | 2022-01-08 03:16:59 -0800 | |
|---|---|---|
| committer | 2022-01-08 12:18:14 -0800 | |
| commit | af4696657c5401b3cf352d34e2515d45ead2144d (patch) | |
| tree | 7a7d0a7849364668cb4083cccc9ecaee9e73b2a6 /src | |
| parent | core: hle: kernel: k_page_table: Update CheckMemoryState. (diff) | |
| download | yuzu-af4696657c5401b3cf352d34e2515d45ead2144d.tar.gz yuzu-af4696657c5401b3cf352d34e2515d45ead2144d.tar.xz yuzu-af4696657c5401b3cf352d34e2515d45ead2144d.zip | |
core: hle: kernel: svc: Updates to SetMemoryAttribute and SetMemoryPermission.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/kernel/k_page_table.cpp | 38 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_page_table.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 50 |
3 files changed, 46 insertions, 45 deletions
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index e86ded58b..6077985b5 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp | |||
| @@ -837,24 +837,36 @@ ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size, | |||
| 837 | return ResultSuccess; | 837 | return ResultSuccess; |
| 838 | } | 838 | } |
| 839 | 839 | ||
| 840 | ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, | 840 | ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr) { |
| 841 | KMemoryAttribute value) { | 841 | const size_t num_pages = size / PageSize; |
| 842 | std::lock_guard lock{page_table_lock}; | 842 | ASSERT((static_cast<KMemoryAttribute>(mask) | KMemoryAttribute::SetMask) == |
| 843 | KMemoryAttribute::SetMask); | ||
| 843 | 844 | ||
| 844 | KMemoryState state{}; | 845 | // Lock the table. |
| 845 | KMemoryPermission perm{}; | 846 | std::lock_guard lock{page_table_lock}; |
| 846 | KMemoryAttribute attribute{}; | ||
| 847 | 847 | ||
| 848 | CASCADE_CODE(CheckMemoryState( | 848 | // Verify we can change the memory attribute. |
| 849 | &state, &perm, &attribute, nullptr, addr, size, KMemoryState::FlagCanChangeAttribute, | 849 | KMemoryState old_state; |
| 850 | KMemoryPermission old_perm; | ||
| 851 | KMemoryAttribute old_attr; | ||
| 852 | size_t num_allocator_blocks; | ||
| 853 | constexpr auto AttributeTestMask = | ||
| 854 | ~(KMemoryAttribute::SetMask | KMemoryAttribute::DeviceShared); | ||
| 855 | R_TRY(this->CheckMemoryState( | ||
| 856 | std::addressof(old_state), std::addressof(old_perm), std::addressof(old_attr), | ||
| 857 | std::addressof(num_allocator_blocks), addr, size, KMemoryState::FlagCanChangeAttribute, | ||
| 850 | KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, | 858 | KMemoryState::FlagCanChangeAttribute, KMemoryPermission::None, KMemoryPermission::None, |
| 851 | KMemoryAttribute::LockedAndIpcLocked, KMemoryAttribute::None, | 859 | AttributeTestMask, KMemoryAttribute::None, ~AttributeTestMask)); |
| 852 | KMemoryAttribute::DeviceSharedAndUncached)); | 860 | |
| 861 | // Determine the new attribute. | ||
| 862 | const auto new_attr = ((old_attr & static_cast<KMemoryAttribute>(~mask)) | | ||
| 863 | static_cast<KMemoryAttribute>(attr & mask)); | ||
| 853 | 864 | ||
| 854 | attribute = attribute & ~mask; | 865 | // Perform operation. |
| 855 | attribute = attribute | (mask & value); | 866 | this->Operate(addr, num_pages, old_perm, OperationType::ChangePermissionsAndRefresh); |
| 856 | 867 | ||
| 857 | block_manager->Update(addr, size / PageSize, state, perm, attribute); | 868 | // Update the blocks. |
| 869 | block_manager->Update(addr, num_pages, old_state, old_perm, new_attr); | ||
| 858 | 870 | ||
| 859 | return ResultSuccess; | 871 | return ResultSuccess; |
| 860 | } | 872 | } |
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h index 07c1d18ac..9235b822a 100644 --- a/src/core/hle/kernel/k_page_table.h +++ b/src/core/hle/kernel/k_page_table.h | |||
| @@ -48,8 +48,7 @@ public: | |||
| 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 SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm); |
| 51 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, | 51 | ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, u32 mask, u32 attr); |
| 52 | KMemoryAttribute value); | ||
| 53 | ResultCode SetMaxHeapSize(std::size_t size); | 52 | ResultCode SetMaxHeapSize(std::size_t size); |
| 54 | ResultCode SetHeapSize(VAddr* out, std::size_t size); | 53 | ResultCode SetHeapSize(VAddr* out, std::size_t size); |
| 55 | ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, | 54 | ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, |
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 250ef9042..4362508a3 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -168,6 +168,9 @@ constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) { | |||
| 168 | 168 | ||
| 169 | static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size, | 169 | static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size, |
| 170 | MemoryPermission perm) { | 170 | MemoryPermission perm) { |
| 171 | LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size=0x{:X}, perm=0x{:08X", address, size, | ||
| 172 | perm); | ||
| 173 | |||
| 171 | // Validate address / size. | 174 | // Validate address / size. |
| 172 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); | 175 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); |
| 173 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); | 176 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); |
| @@ -186,46 +189,33 @@ static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 s | |||
| 186 | } | 189 | } |
| 187 | 190 | ||
| 188 | static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, | 191 | static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, |
| 189 | u32 attribute) { | 192 | u32 attr) { |
| 190 | LOG_DEBUG(Kernel_SVC, | 193 | LOG_DEBUG(Kernel_SVC, |
| 191 | "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, | 194 | "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, |
| 192 | size, mask, attribute); | 195 | size, mask, attr); |
| 193 | |||
| 194 | if (!Common::Is4KBAligned(address)) { | ||
| 195 | LOG_ERROR(Kernel_SVC, "Address not page aligned (0x{:016X})", address); | ||
| 196 | return ResultInvalidAddress; | ||
| 197 | } | ||
| 198 | 196 | ||
| 199 | if (size == 0 || !Common::Is4KBAligned(size)) { | 197 | // Validate address / size. |
| 200 | LOG_ERROR(Kernel_SVC, "Invalid size (0x{:X}). Size must be non-zero and page aligned.", | 198 | R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress); |
| 201 | size); | 199 | R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize); |
| 202 | return ResultInvalidAddress; | 200 | R_UNLESS(size > 0, ResultInvalidSize); |
| 203 | } | 201 | R_UNLESS((address < address + size), ResultInvalidCurrentMemory); |
| 204 | |||
| 205 | if (!IsValidAddressRange(address, size)) { | ||
| 206 | LOG_ERROR(Kernel_SVC, "Address range overflowed (Address: 0x{:016X}, Size: 0x{:016X})", | ||
| 207 | address, size); | ||
| 208 | return ResultInvalidCurrentMemory; | ||
| 209 | } | ||
| 210 | 202 | ||
| 211 | const auto attributes{static_cast<MemoryAttribute>(mask | attribute)}; | 203 | // Validate the attribute and mask. |
| 212 | if (attributes != static_cast<MemoryAttribute>(mask) || | 204 | constexpr u32 SupportedMask = static_cast<u32>(MemoryAttribute::Uncached); |
| 213 | (attributes | MemoryAttribute::Uncached) != MemoryAttribute::Uncached) { | 205 | R_UNLESS((mask | attr) == mask, ResultInvalidCombination); |
| 214 | LOG_ERROR(Kernel_SVC, | 206 | R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination); |
| 215 | "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}", | ||
| 216 | attribute, mask); | ||
| 217 | return ResultInvalidCombination; | ||
| 218 | } | ||
| 219 | 207 | ||
| 208 | // Validate that the region is in range for the current process. | ||
| 220 | auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; | 209 | auto& page_table{system.Kernel().CurrentProcess()->PageTable()}; |
| 210 | R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory); | ||
| 221 | 211 | ||
| 222 | return page_table.SetMemoryAttribute(address, size, static_cast<KMemoryAttribute>(mask), | 212 | // Set the memory attribute. |
| 223 | static_cast<KMemoryAttribute>(attribute)); | 213 | return page_table.SetMemoryAttribute(address, size, mask, attr); |
| 224 | } | 214 | } |
| 225 | 215 | ||
| 226 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, | 216 | static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, |
| 227 | u32 attribute) { | 217 | u32 attr) { |
| 228 | return SetMemoryAttribute(system, address, size, mask, attribute); | 218 | return SetMemoryAttribute(system, address, size, mask, attr); |
| 229 | } | 219 | } |
| 230 | 220 | ||
| 231 | /// Maps a memory range into a different range. | 221 | /// Maps a memory range into a different range. |