diff options
Diffstat (limited to '')
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 348a22904..c826dfd96 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -254,11 +254,52 @@ static ResultCode SetMemoryPermission(VAddr addr, u64 size, u32 prot) { | |||
| 254 | return vm_manager.ReprotectRange(addr, size, converted_permissions); | 254 | return vm_manager.ReprotectRange(addr, size, converted_permissions); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| 257 | static ResultCode SetMemoryAttribute(VAddr addr, u64 size, u32 state0, u32 state1) { | 257 | static ResultCode SetMemoryAttribute(VAddr address, u64 size, u32 mask, u32 attribute) { |
| 258 | LOG_WARNING(Kernel_SVC, | 258 | LOG_DEBUG(Kernel_SVC, |
| 259 | "(STUBBED) called, addr=0x{:X}, size=0x{:X}, state0=0x{:X}, state1=0x{:X}", addr, | 259 | "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, |
| 260 | size, state0, state1); | 260 | size, mask, attribute); |
| 261 | return RESULT_SUCCESS; | 261 | |
| 262 | if (!Common::Is4KBAligned(address)) { | ||
| 263 | LOG_ERROR(Kernel_SVC, "Address not page aligned (0x{:016X})", address); | ||
| 264 | return ERR_INVALID_ADDRESS; | ||
| 265 | } | ||
| 266 | |||
| 267 | if (size == 0 || !Common::Is4KBAligned(size)) { | ||
| 268 | LOG_ERROR(Kernel_SVC, "Invalid size (0x{:X}). Size must be non-zero and page aligned.", | ||
| 269 | size); | ||
| 270 | return ERR_INVALID_ADDRESS; | ||
| 271 | } | ||
| 272 | |||
| 273 | if (!IsValidAddressRange(address, size)) { | ||
| 274 | LOG_ERROR(Kernel_SVC, "Address range overflowed (Address: 0x{:016X}, Size: 0x{:016X})", | ||
| 275 | address, size); | ||
| 276 | return ERR_INVALID_ADDRESS_STATE; | ||
| 277 | } | ||
| 278 | |||
| 279 | const auto mem_attribute = static_cast<MemoryAttribute>(attribute); | ||
| 280 | const auto mem_mask = static_cast<MemoryAttribute>(mask); | ||
| 281 | const auto attribute_with_mask = mem_attribute | mem_mask; | ||
| 282 | |||
| 283 | if (attribute_with_mask != mem_mask) { | ||
| 284 | LOG_ERROR(Kernel_SVC, | ||
| 285 | "Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}", | ||
| 286 | attribute, mask); | ||
| 287 | return ERR_INVALID_COMBINATION; | ||
| 288 | } | ||
| 289 | |||
| 290 | if ((attribute_with_mask | MemoryAttribute::Uncached) != MemoryAttribute::Uncached) { | ||
| 291 | LOG_ERROR(Kernel_SVC, "Specified attribute isn't equal to MemoryAttributeUncached (8)."); | ||
| 292 | return ERR_INVALID_COMBINATION; | ||
| 293 | } | ||
| 294 | |||
| 295 | auto& vm_manager = Core::CurrentProcess()->VMManager(); | ||
| 296 | if (!IsInsideAddressSpace(vm_manager, address, size)) { | ||
| 297 | LOG_ERROR(Kernel_SVC, | ||
| 298 | "Given address (0x{:016X}) is outside the bounds of the address space.", address); | ||
| 299 | return ERR_INVALID_ADDRESS_STATE; | ||
| 300 | } | ||
| 301 | |||
| 302 | return vm_manager.SetMemoryAttribute(address, size, mem_mask, mem_attribute); | ||
| 262 | } | 303 | } |
| 263 | 304 | ||
| 264 | /// Maps a memory range into a different range. | 305 | /// Maps a memory range into a different range. |