diff options
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 50 |
1 files changed, 20 insertions, 30 deletions
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. |