diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index e3162be12..e95bfa4b7 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -104,6 +104,18 @@ namespace ams::kern::arch::arm64 { return this->page_table.MakeAndOpenPageGroup(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr); } + Result MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) { + return this->page_table.MakeAndOpenPageGroupContiguous(out, address, num_pages, state_mask, state, perm_mask, perm, attr_mask, attr); + } + + Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) { + return this->page_table.LockForDeviceAddressSpace(out, address, size, perm, is_aligned); + } + + Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) { + return this->page_table.UnlockForDeviceAddressSpace(address, size); + } + Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size) { return this->page_table.LockForIpcUserBuffer(out, address, size); } diff --git a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_device_page_table.hpp b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_device_page_table.hpp index 1c39d7772..a547dc181 100644 --- a/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_device_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/board/nintendo/nx/kern_k_device_page_table.hpp @@ -58,6 +58,9 @@ namespace ams::kern::board::nintendo::nx { Result Attach(ams::svc::DeviceName device_name, u64 space_address, u64 space_size); Result Detach(ams::svc::DeviceName device_name); + + Result Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings); + Result Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address); public: static void Initialize(); }; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp index 19439ddd1..8595b7936 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_block.hpp @@ -389,6 +389,30 @@ namespace ams::kern { this->num_pages -= block->num_pages; } + constexpr void ShareToDevice(KMemoryPermission new_perm) { + /* We must either be shared or have a zero lock count. */ + MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_DeviceShared) == KMemoryAttribute_DeviceShared || this->device_use_count == 0); + + /* Share. */ + const u16 new_count = ++this->device_use_count; + MESOSPHERE_ABORT_UNLESS(new_count > 0); + + this->attribute = static_cast(this->attribute | KMemoryAttribute_DeviceShared); + } + + constexpr void UnshareToDevice(KMemoryPermission new_perm) { + /* We must be shared. */ + MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_DeviceShared) == KMemoryAttribute_DeviceShared); + + /* Unhare. */ + const u16 old_count = this->device_use_count--; + MESOSPHERE_ABORT_UNLESS(old_count > 0); + + if (old_count == 1) { + this->attribute = static_cast(this->attribute & ~KMemoryAttribute_DeviceShared); + } + } + constexpr void LockForIpc(KMemoryPermission new_perm) { /* We must either be locked or have a zero lock count. */ MESOSPHERE_ASSERT((this->attribute & KMemoryAttribute_IpcLocked) == KMemoryAttribute_IpcLocked || this->ipc_lock_count == 0); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index de6f50e3f..d2a9c60a3 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -300,7 +300,10 @@ namespace ams::kern { Result UnmapPageGroup(KProcessAddress address, const KPageGroup &pg, KMemoryState state); Result MakeAndOpenPageGroup(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr); + Result MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr); + Result LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned); + Result UnlockForDeviceAddressSpace(KProcessAddress address, size_t size); Result LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size); Result UnlockForIpcUserBuffer(KProcessAddress address, size_t size); diff --git a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp index 7b4c2b93e..9d3d26a08 100644 --- a/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp +++ b/libraries/libmesosphere/include/mesosphere/svc/kern_svc_results.hpp @@ -37,7 +37,7 @@ namespace ams::kern::svc { /* 105 */ using ::ams::svc::ResultOutOfHandles; /* 106 */ using ::ams::svc::ResultInvalidCurrentMemory; - /* 108 */ using ::ams::svc::ResultInvalidNewMemoryPermissions; + /* 108 */ using ::ams::svc::ResultInvalidNewMemoryPermission; /* 110 */ using ::ams::svc::ResultInvalidMemoryRegion; diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp index a0ad01bb0..700855782 100644 --- a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_device_page_table.cpp @@ -583,4 +583,12 @@ namespace ams::kern::board::nintendo::nx { MESOSPHERE_UNIMPLEMENTED(); } + Result KDevicePageTable::Map(size_t *out_mapped_size, const KPageGroup &pg, KDeviceVirtualAddress device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings) { + MESOSPHERE_UNIMPLEMENTED(); + } + + Result KDevicePageTable::Unmap(const KPageGroup &pg, KDeviceVirtualAddress device_address) { + MESOSPHERE_UNIMPLEMENTED(); + } + } diff --git a/libraries/libmesosphere/source/kern_k_device_address_space.cpp b/libraries/libmesosphere/source/kern_k_device_address_space.cpp index 175ef8319..a83eb141b 100644 --- a/libraries/libmesosphere/source/kern_k_device_address_space.cpp +++ b/libraries/libmesosphere/source/kern_k_device_address_space.cpp @@ -57,15 +57,71 @@ namespace ams::kern { } Result KDeviceAddressSpace::Detach(ams::svc::DeviceName device_name) { - MESOSPHERE_UNIMPLEMENTED(); + /* Lock the address space. */ + KScopedLightLock lk(this->lock); + + /* Detach. */ + return this->table.Detach(device_name); } Result KDeviceAddressSpace::Map(size_t *out_mapped_size, KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address, ams::svc::MemoryPermission device_perm, bool is_aligned, bool refresh_mappings) { - MESOSPHERE_UNIMPLEMENTED(); + /* Check that the address falls within the space. */ + R_UNLESS((this->space_address <= device_address && device_address + size - 1 <= this->space_address + this->space_size - 1), svc::ResultInvalidCurrentMemory()); + + /* Lock the address space. */ + KScopedLightLock lk(this->lock); + + /* Lock the pages. */ + KPageGroup pg(page_table->GetBlockInfoManager()); + R_TRY(page_table->LockForDeviceAddressSpace(std::addressof(pg), process_address, size, ConvertToKMemoryPermission(device_perm), is_aligned)); + + /* Ensure that if we fail, we don't keep unmapped pages locked. */ + ON_SCOPE_EXIT { + if (*out_mapped_size != size) { + page_table->UnlockForDeviceAddressSpace(process_address + *out_mapped_size, size - *out_mapped_size); + }; + }; + + /* Map the pages. */ + { + /* Clear the output size to zero on failure. */ + auto map_guard = SCOPE_GUARD { *out_mapped_size = 0; }; + + /* Perform the mapping. */ + R_TRY(this->table.Map(out_mapped_size, pg, device_address, device_perm, refresh_mappings)); + + /* We succeeded, so cancel our guard. */ + map_guard.Cancel(); + } + + + return ResultSuccess(); } Result KDeviceAddressSpace::Unmap(KProcessPageTable *page_table, KProcessAddress process_address, size_t size, u64 device_address) { - MESOSPHERE_UNIMPLEMENTED(); + /* Check that the address falls within the space. */ + R_UNLESS((this->space_address <= device_address && device_address + size - 1 <= this->space_address + this->space_size - 1), svc::ResultInvalidCurrentMemory()); + + /* Lock the address space. */ + KScopedLightLock lk(this->lock); + + /* Make and open a page group for the unmapped region. */ + KPageGroup pg(page_table->GetBlockInfoManager()); + R_TRY(page_table->MakeAndOpenPageGroupContiguous(std::addressof(pg), process_address, size / PageSize, + KMemoryState_FlagCanDeviceMap, KMemoryState_FlagCanDeviceMap, + KMemoryPermission_None, KMemoryPermission_None, + KMemoryAttribute_AnyLocked | KMemoryAttribute_DeviceShared | KMemoryAttribute_Locked, KMemoryAttribute_DeviceShared)); + + /* Ensure the page group is closed on scope exit. */ + ON_SCOPE_EXIT { pg.Close(); }; + + /* Unmap. */ + R_TRY(this->table.Unmap(pg, device_address)); + + /* Unlock the pages. */ + R_TRY(page_table->UnlockForDeviceAddressSpace(process_address, size)); + + return ResultSuccess(); } } diff --git a/libraries/libmesosphere/source/kern_k_page_table_base.cpp b/libraries/libmesosphere/source/kern_k_page_table_base.cpp index 535e5ef56..2614d34cd 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -1370,6 +1370,85 @@ namespace ams::kern { return ResultSuccess(); } + Result KPageTableBase::MakeAndOpenPageGroupContiguous(KPageGroup *out, KProcessAddress address, size_t num_pages, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr) { + /* Ensure that the page group isn't null. */ + MESOSPHERE_ASSERT(out != nullptr); + + /* Make sure that the region we're mapping is valid for the table. */ + const size_t size = num_pages * PageSize; + R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); + + /* Lock the table. */ + KScopedLightLock lk(this->general_lock); + + /* Check if state allows us to create the group. */ + R_TRY(this->CheckMemoryStateContiguous(address, size, state_mask | KMemoryState_FlagReferenceCounted, state | KMemoryState_FlagReferenceCounted, perm_mask, perm, attr_mask, attr)); + + /* Create a new page group for the region. */ + R_TRY(this->MakePageGroup(*out, address, num_pages)); + + /* Open a new reference to the pages in the group. */ + out->Open(); + + return ResultSuccess(); + } + + Result KPageTableBase::LockForDeviceAddressSpace(KPageGroup *out, KProcessAddress address, size_t size, KMemoryPermission perm, bool is_aligned) { + /* Lightly validate the range before doing anything else. */ + const size_t num_pages = size / PageSize; + R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); + + /* Lock the table. */ + KScopedLightLock lk(this->general_lock); + + /* Check the memory state. */ + const u32 test_state = (is_aligned ? KMemoryState_FlagCanAlignedDeviceMap : KMemoryState_FlagCanDeviceMap); + R_TRY(this->CheckMemoryState(address, size, test_state, test_state, perm, perm, KMemoryAttribute_AnyLocked | KMemoryAttribute_IpcLocked | KMemoryAttribute_Locked, 0, KMemoryAttribute_DeviceShared)); + + /* Make the page group, if we should. */ + if (out != nullptr) { + R_TRY(this->MakePageGroup(*out, address, num_pages)); + } + + /* Create an update allocator. */ + KMemoryBlockManagerUpdateAllocator allocator(this->memory_block_slab_manager); + R_TRY(allocator.GetResult()); + + /* Update the memory blocks. */ + this->memory_block_manager.UpdateLock(std::addressof(allocator), address, num_pages, &KMemoryBlock::ShareToDevice, KMemoryPermission_None); + + /* Open the page group. */ + if (out != nullptr) { + out->Open(); + } + + return ResultSuccess(); + } + + Result KPageTableBase::UnlockForDeviceAddressSpace(KProcessAddress address, size_t size) { + /* Lightly validate the range before doing anything else. */ + const size_t num_pages = size / PageSize; + R_UNLESS(this->Contains(address, size), svc::ResultInvalidCurrentMemory()); + + /* Lock the table. */ + KScopedLightLock lk(this->general_lock); + + /* Check the memory state. */ + R_TRY(this->CheckMemoryStateContiguous(address, size, + KMemoryState_FlagCanDeviceMap, KMemoryState_FlagCanDeviceMap, + KMemoryPermission_None, KMemoryPermission_None, + KMemoryAttribute_AnyLocked | KMemoryAttribute_DeviceShared | KMemoryAttribute_Locked, KMemoryAttribute_DeviceShared)); + + /* Create an update allocator. */ + KMemoryBlockManagerUpdateAllocator allocator(this->memory_block_slab_manager); + R_TRY(allocator.GetResult()); + + /* Update the memory blocks. */ + this->memory_block_manager.UpdateLock(std::addressof(allocator), address, num_pages, &KMemoryBlock::UnshareToDevice, KMemoryPermission_None); + + return ResultSuccess(); + } + Result KPageTableBase::LockForIpcUserBuffer(KPhysicalAddress *out, KProcessAddress address, size_t size) { return this->LockMemoryAndOpen(nullptr, out, address, size, KMemoryState_FlagCanIpcUserBuffer, KMemoryState_FlagCanIpcUserBuffer, diff --git a/libraries/libmesosphere/source/svc/kern_svc_device_address_space.cpp b/libraries/libmesosphere/source/svc/kern_svc_device_address_space.cpp index 9a8686719..67a31326a 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_device_address_space.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_device_address_space.cpp @@ -21,6 +21,12 @@ namespace ams::kern::svc { namespace { + constexpr inline u64 DeviceAddressSpaceAlignMask = (1ul << 22) - 1; + + constexpr bool IsProcessAndDeviceAligned(uint64_t process_address, uint64_t device_address) { + return (process_address & DeviceAddressSpaceAlignMask) == (device_address & DeviceAddressSpaceAlignMask); + } + Result CreateDeviceAddressSpace(ams::svc::Handle *out, uint64_t das_address, uint64_t das_size) { /* Validate input. */ R_UNLESS(util::IsAligned(das_address, PageSize), svc::ResultInvalidMemoryRegion()); @@ -62,6 +68,97 @@ namespace ams::kern::svc { return das->Detach(device_name); } + constexpr bool IsValidDeviceMemoryPermission(ams::svc::MemoryPermission device_perm) { + switch (device_perm) { + case ams::svc::MemoryPermission_Read: + case ams::svc::MemoryPermission_Write: + case ams::svc::MemoryPermission_ReadWrite: + return true; + default: + return false; + } + } + + Result MapDeviceAddressSpace(size_t *out_mapped_size, ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address, ams::svc::MemoryPermission device_perm, bool refresh_mappings) { + /* Validate input. */ + R_UNLESS(util::IsAligned(process_address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS(util::IsAligned(device_address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize()); + R_UNLESS(size > 0, svc::ResultInvalidSize()); + R_UNLESS((process_address < process_address + size), svc::ResultInvalidCurrentMemory()); + R_UNLESS((device_address < device_address + size), svc::ResultInvalidMemoryRegion()); + R_UNLESS((process_address == static_cast(process_address)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(IsValidDeviceMemoryPermission(device_perm), svc::ResultInvalidNewMemoryPermission()); + + /* Get the device address space. */ + KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject(das_handle); + R_UNLESS(das.IsNotNull(), svc::ResultInvalidHandle()); + + /* Get the process. */ + KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject(process_handle); + R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle()); + + /* Validate that the process address is within range. */ + auto &page_table = process->GetPageTable(); + R_UNLESS(page_table.Contains(process_address, size), svc::ResultInvalidCurrentMemory()); + + /* Map. */ + return das->Map(out_mapped_size, std::addressof(page_table), KProcessAddress(process_address), size, device_address, device_perm, refresh_mappings); + } + + Result MapDeviceAddressSpaceAligned(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { + /* Validate input. */ + R_UNLESS(util::IsAligned(process_address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS(util::IsAligned(device_address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS(IsProcessAndDeviceAligned(process_address, device_address), svc::ResultInvalidAddress()); + R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize()); + R_UNLESS(size > 0, svc::ResultInvalidSize()); + R_UNLESS((process_address < process_address + size), svc::ResultInvalidCurrentMemory()); + R_UNLESS((device_address < device_address + size), svc::ResultInvalidMemoryRegion()); + R_UNLESS((process_address == static_cast(process_address)), svc::ResultInvalidCurrentMemory()); + R_UNLESS(IsValidDeviceMemoryPermission(device_perm), svc::ResultInvalidNewMemoryPermission()); + + /* Get the device address space. */ + KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject(das_handle); + R_UNLESS(das.IsNotNull(), svc::ResultInvalidHandle()); + + /* Get the process. */ + KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject(process_handle); + R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle()); + + /* Validate that the process address is within range. */ + auto &page_table = process->GetPageTable(); + R_UNLESS(page_table.Contains(process_address, size), svc::ResultInvalidCurrentMemory()); + + /* Map. */ + return das->MapAligned(std::addressof(page_table), KProcessAddress(process_address), size, device_address, device_perm); + } + + Result UnmapDeviceAddressSpace(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, size_t size, uint64_t device_address) { + /* Validate input. */ + R_UNLESS(util::IsAligned(process_address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS(util::IsAligned(device_address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize()); + R_UNLESS(size > 0, svc::ResultInvalidSize()); + R_UNLESS((process_address < process_address + size), svc::ResultInvalidCurrentMemory()); + R_UNLESS((device_address < device_address + size), svc::ResultInvalidMemoryRegion()); + R_UNLESS((process_address == static_cast(process_address)), svc::ResultInvalidCurrentMemory()); + + /* Get the device address space. */ + KScopedAutoObject das = GetCurrentProcess().GetHandleTable().GetObject(das_handle); + R_UNLESS(das.IsNotNull(), svc::ResultInvalidHandle()); + + /* Get the process. */ + KScopedAutoObject process = GetCurrentProcess().GetHandleTable().GetObject(process_handle); + R_UNLESS(process.IsNotNull(), svc::ResultInvalidHandle()); + + /* Validate that the process address is within range. */ + auto &page_table = process->GetPageTable(); + R_UNLESS(page_table.Contains(process_address, size), svc::ResultInvalidCurrentMemory()); + + return das->Unmap(std::addressof(page_table), KProcessAddress(process_address), size, device_address); + } + } /* ============================= 64 ABI ============================= */ @@ -79,19 +176,21 @@ namespace ams::kern::svc { } Result MapDeviceAddressSpaceByForce64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { - MESOSPHERE_PANIC("Stubbed SvcMapDeviceAddressSpaceByForce64 was called."); + size_t dummy_map_size; + return MapDeviceAddressSpace(std::addressof(dummy_map_size), das_handle, process_handle, process_address, size, device_address, device_perm, false); } Result MapDeviceAddressSpaceAligned64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { - MESOSPHERE_PANIC("Stubbed SvcMapDeviceAddressSpaceAligned64 was called."); + return MapDeviceAddressSpaceAligned(das_handle, process_handle, process_address, size, device_address, device_perm); } Result MapDeviceAddressSpace64(ams::svc::Size *out_mapped_size, ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { - MESOSPHERE_PANIC("Stubbed SvcMapDeviceAddressSpace64 was called."); + static_assert(sizeof(*out_mapped_size) == sizeof(size_t)); + return MapDeviceAddressSpace(reinterpret_cast(out_mapped_size), das_handle, process_handle, process_address, size, device_address, device_perm, true); } Result UnmapDeviceAddressSpace64(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address) { - MESOSPHERE_PANIC("Stubbed SvcUnmapDeviceAddressSpace64 was called."); + return UnmapDeviceAddressSpace(das_handle, process_handle, process_address, size, device_address); } /* ============================= 64From32 ABI ============================= */ @@ -109,19 +208,21 @@ namespace ams::kern::svc { } Result MapDeviceAddressSpaceByForce64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { - MESOSPHERE_PANIC("Stubbed SvcMapDeviceAddressSpaceByForce64From32 was called."); + size_t dummy_map_size; + return MapDeviceAddressSpace(std::addressof(dummy_map_size), das_handle, process_handle, process_address, size, device_address, device_perm, false); } Result MapDeviceAddressSpaceAligned64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { - MESOSPHERE_PANIC("Stubbed SvcMapDeviceAddressSpaceAligned64From32 was called."); + return MapDeviceAddressSpaceAligned(das_handle, process_handle, process_address, size, device_address, device_perm); } Result MapDeviceAddressSpace64From32(ams::svc::Size *out_mapped_size, ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address, ams::svc::MemoryPermission device_perm) { - MESOSPHERE_PANIC("Stubbed SvcMapDeviceAddressSpace64From32 was called."); + static_assert(sizeof(*out_mapped_size) == sizeof(size_t)); + return MapDeviceAddressSpace(reinterpret_cast(out_mapped_size), das_handle, process_handle, process_address, size, device_address, device_perm, true); } Result UnmapDeviceAddressSpace64From32(ams::svc::Handle das_handle, ams::svc::Handle process_handle, uint64_t process_address, ams::svc::Size size, uint64_t device_address) { - MESOSPHERE_PANIC("Stubbed SvcUnmapDeviceAddressSpace64From32 was called."); + return UnmapDeviceAddressSpace(das_handle, process_handle, process_address, size, device_address); } } diff --git a/libraries/libmesosphere/source/svc/kern_svc_register.cpp b/libraries/libmesosphere/source/svc/kern_svc_register.cpp index 4e4fca545..261330a15 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_register.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_register.cpp @@ -22,6 +22,10 @@ namespace ams::kern::svc { namespace { Result ReadWriteRegister(uint32_t *out, ams::svc::PhysicalAddress address, uint32_t mask, uint32_t value) { + /* Clear the output unconditionally. */ + *out = 0; + + /* Read/write the register. */ return KSystemControl::ReadWriteRegister(out, address, mask, value); } diff --git a/libraries/libvapours/include/vapours/results/svc_results.hpp b/libraries/libvapours/include/vapours/results/svc_results.hpp index 31672c97e..4adeacaf2 100644 --- a/libraries/libvapours/include/vapours/results/svc_results.hpp +++ b/libraries/libvapours/include/vapours/results/svc_results.hpp @@ -40,7 +40,7 @@ namespace ams::svc { R_DEFINE_ERROR_RESULT(OutOfHandles, 105); R_DEFINE_ERROR_RESULT(InvalidCurrentMemory, 106); - R_DEFINE_ERROR_RESULT(InvalidNewMemoryPermissions, 108); + R_DEFINE_ERROR_RESULT(InvalidNewMemoryPermission, 108); R_DEFINE_ERROR_RESULT(InvalidMemoryRegion, 110);