summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/hle/kernel/k_page_table.cpp38
-rw-r--r--src/core/hle/kernel/k_page_table.h3
-rw-r--r--src/core/hle/kernel/svc.cpp50
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
840ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, 840ResultCode 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
169static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size, 169static 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
188static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, 191static 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
226static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, 216static 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.