From 0804f0e3b56005a967dd9fec036b4216a553b94c Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sun, 8 Nov 2020 15:27:55 -0800 Subject: [PATCH] dd: implement DeviceAddressSpaceType api --- libstratosphere/include/stratosphere/dd.hpp | 6 +- .../dd/dd_device_address_space.hpp | 21 ++ .../dd/dd_device_address_space_api.hpp | 48 +++++ .../dd/dd_device_address_space_common.hpp | 26 +++ .../dd/dd_device_address_space_types.hpp | 49 +++++ .../stratosphere/dd/dd_io_mappings.hpp | 4 - .../stratosphere/dd/dd_process_handle.hpp | 4 +- .../include/stratosphere/dd/dd_types.hpp | 33 +++ .../source/dd/dd_device_address_space.cpp | 190 ++++++++++++++++++ .../dd/impl/dd_device_address_space_impl.hpp | 23 +++ ...d_device_address_space_impl.os.horizon.cpp | 101 ++++++++++ ...d_device_address_space_impl.os.horizon.hpp | 37 ++++ libvapours/include/vapours/results.hpp | 1 + .../include/vapours/results/dd_results.hpp | 35 ++++ 14 files changed, 570 insertions(+), 8 deletions(-) create mode 100644 libstratosphere/include/stratosphere/dd/dd_device_address_space.hpp create mode 100644 libstratosphere/include/stratosphere/dd/dd_device_address_space_api.hpp create mode 100644 libstratosphere/include/stratosphere/dd/dd_device_address_space_common.hpp create mode 100644 libstratosphere/include/stratosphere/dd/dd_device_address_space_types.hpp create mode 100644 libstratosphere/include/stratosphere/dd/dd_types.hpp create mode 100644 libstratosphere/source/dd/dd_device_address_space.cpp create mode 100644 libstratosphere/source/dd/impl/dd_device_address_space_impl.hpp create mode 100644 libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.cpp create mode 100644 libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.hpp create mode 100644 libvapours/include/vapours/results/dd_results.hpp diff --git a/libstratosphere/include/stratosphere/dd.hpp b/libstratosphere/include/stratosphere/dd.hpp index dc14d77b..a089ed30 100644 --- a/libstratosphere/include/stratosphere/dd.hpp +++ b/libstratosphere/include/stratosphere/dd.hpp @@ -16,5 +16,7 @@ #pragma once -#include "dd/dd_io_mappings.hpp" -#include "dd/dd_process_handle.hpp" +#include +#include +#include +#include diff --git a/libstratosphere/include/stratosphere/dd/dd_device_address_space.hpp b/libstratosphere/include/stratosphere/dd/dd_device_address_space.hpp new file mode 100644 index 00000000..0ae11940 --- /dev/null +++ b/libstratosphere/include/stratosphere/dd/dd_device_address_space.hpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +#include +#include +#include diff --git a/libstratosphere/include/stratosphere/dd/dd_device_address_space_api.hpp b/libstratosphere/include/stratosphere/dd/dd_device_address_space_api.hpp new file mode 100644 index 00000000..31d7148d --- /dev/null +++ b/libstratosphere/include/stratosphere/dd/dd_device_address_space_api.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include +#include +#include + +namespace ams::dd { + + Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 address, u64 size); + Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 size); + void DestroyDeviceAddressSpace(DeviceAddressSpaceType *das); + + void AttachDeviceAddressSpaceHandle(DeviceAddressSpaceType *das, Handle handle, bool managed); + + Handle GetDeviceAddressSpaceHandle(DeviceAddressSpaceType *das); + + Result MapDeviceAddressSpaceAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm); + Result MapDeviceAddressSpaceNotAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm); + void UnmapDeviceAddressSpace(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address); + + void InitializeDeviceAddressSpaceMapInfo(DeviceAddressSpaceMapInfo *info, DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm); + + Result MapNextDeviceAddressSpaceRegion(size_t *out_mapped_size, DeviceAddressSpaceMapInfo *info); + void UnmapDeviceAddressSpaceRegion(DeviceAddressSpaceMapInfo *info); + + u64 GetMappedProcessAddress(DeviceAddressSpaceMapInfo *info); + DeviceVirtualAddress GetMappedDeviceVirtualAddress(DeviceAddressSpaceMapInfo *info); + size_t GetMappedSize(DeviceAddressSpaceMapInfo *info); + + Result AttachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name); + void DetachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name); + +} diff --git a/libstratosphere/include/stratosphere/dd/dd_device_address_space_common.hpp b/libstratosphere/include/stratosphere/dd/dd_device_address_space_common.hpp new file mode 100644 index 00000000..13676348 --- /dev/null +++ b/libstratosphere/include/stratosphere/dd/dd_device_address_space_common.hpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include + +namespace ams::dd { + + using DeviceName = ::ams::svc::DeviceName; + + constexpr inline u64 DeviceAddressSpaceMemoryRegionAlignment = 4_KB; + +} diff --git a/libstratosphere/include/stratosphere/dd/dd_device_address_space_types.hpp b/libstratosphere/include/stratosphere/dd/dd_device_address_space_types.hpp new file mode 100644 index 00000000..7de417fb --- /dev/null +++ b/libstratosphere/include/stratosphere/dd/dd_device_address_space_types.hpp @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include +#include + +namespace ams::dd { + + using DeviceVirtualAddress = u64; + + using DeviceAddressSpaceHandle = ::Handle; + + struct DeviceAddressSpaceType { + enum State { + State_NotInitialized = 0, + State_Initialized = 1, + }; + DeviceAddressSpaceHandle device_handle; + u8 state; + bool is_handle_managed; + }; + static_assert(std::is_trivial::value); + + struct DeviceAddressSpaceMapInfo { + size_t last_mapped_size; + size_t size; + u64 process_address; + DeviceVirtualAddress device_start_address; + DeviceVirtualAddress device_end_address; + ProcessHandle process_handle; + MemoryPermission device_permission; + DeviceAddressSpaceType *device_address_space; + }; + static_assert(std::is_trivial::value); + +} diff --git a/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp b/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp index c0f3ac99..c3f2d11b 100644 --- a/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp +++ b/libstratosphere/include/stratosphere/dd/dd_io_mappings.hpp @@ -19,10 +19,6 @@ namespace ams::dd { - u32 ReadRegister(dd::PhysicalAddress phys_addr); - void WriteRegister(dd::PhysicalAddress phys_addr, u32 value); - u32 ReadWriteRegister(dd::PhysicalAddress phys_addr, u32 value, u32 mask); - /* Convenience Helper. */ inline uintptr_t GetIoMapping(dd::PhysicalAddress phys_addr, size_t size) { const uintptr_t io_mapping = dd::QueryIoMapping(phys_addr, size); diff --git a/libstratosphere/include/stratosphere/dd/dd_process_handle.hpp b/libstratosphere/include/stratosphere/dd/dd_process_handle.hpp index 6688682d..2f06ef2e 100644 --- a/libstratosphere/include/stratosphere/dd/dd_process_handle.hpp +++ b/libstratosphere/include/stratosphere/dd/dd_process_handle.hpp @@ -13,12 +13,12 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - #pragma once #include +#include namespace ams::dd { - ::Handle GetCurrentProcessHandle(); + ProcessHandle GetCurrentProcessHandle(); } diff --git a/libstratosphere/include/stratosphere/dd/dd_types.hpp b/libstratosphere/include/stratosphere/dd/dd_types.hpp new file mode 100644 index 00000000..2d158729 --- /dev/null +++ b/libstratosphere/include/stratosphere/dd/dd_types.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include +#include + +namespace ams::dd { + + using ProcessHandle = ::Handle; + + enum MemoryPermission { + MemoryPermission_None = 0, + MemoryPermission_ReadOnly = (1u << 0), + MemoryPermission_WriteOnly = (1u << 1), + + MemoryPermission_ReadWrite = MemoryPermission_ReadOnly | MemoryPermission_WriteOnly, + }; + +} diff --git a/libstratosphere/source/dd/dd_device_address_space.cpp b/libstratosphere/source/dd/dd_device_address_space.cpp new file mode 100644 index 00000000..43f6fee0 --- /dev/null +++ b/libstratosphere/source/dd/dd_device_address_space.cpp @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "impl/dd_device_address_space_impl.hpp" + +namespace ams::dd { + + Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 address, u64 size) { + /* Check pre-conditions. */ + AMS_ASSERT(util::IsAligned(address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + AMS_ASSERT(size > 0); + + /* Ensure we leave in a consistent state. */ + auto state_guard = SCOPE_GUARD { das->state = DeviceAddressSpaceType::State_NotInitialized; }; + + /* Create the address space. */ + DeviceAddressSpaceHandle handle; + R_TRY(impl::DeviceAddressSpaceImpl::Create(std::addressof(handle), address, size)); + + /* Set the values in the das. */ + das->device_handle = handle; + das->is_handle_managed = true; + das->state = DeviceAddressSpaceType::State_Initialized; + + /* We succeeded. */ + state_guard.Cancel(); + return ResultSuccess(); + } + + Result CreateDeviceAddressSpace(DeviceAddressSpaceType *das, u64 size) { + return CreateDeviceAddressSpace(das, 0, size); + } + + void DestroyDeviceAddressSpace(DeviceAddressSpaceType *das) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + + /* Destroy the handle. */ + if (das->is_handle_managed) { + impl::DeviceAddressSpaceImpl::Close(das->device_handle); + } + + das->device_handle = 0; + das->is_handle_managed = false; + das->state = DeviceAddressSpaceType::State_NotInitialized; + } + + void AttachDeviceAddressSpaceHandle(DeviceAddressSpaceType *das, Handle handle, bool managed) { + /* Check pre-conditions. */ + AMS_ASSERT(handle != svc::InvalidHandle); + + das->device_handle = handle; + das->is_handle_managed = managed; + das->state = DeviceAddressSpaceType::State_Initialized; + } + + Handle GetDeviceAddressSpaceHandle(DeviceAddressSpaceType *das) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + + return das->device_handle; + } + + Result MapDeviceAddressSpaceAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + AMS_ASSERT(process_address + size > process_address); + AMS_ASSERT(device_address + size > device_address); + AMS_ASSERT(size > 0); + AMS_ASSERT((process_address & (4_MB - 1)) == (device_address & (4_MB - 1))); + + return impl::DeviceAddressSpaceImpl::MapAligned(das->device_handle, process_handle, process_address, size, device_address, device_perm); + } + + Result MapDeviceAddressSpaceNotAligned(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + AMS_ASSERT(process_address + size > process_address); + AMS_ASSERT(device_address + size > device_address); + AMS_ASSERT(size > 0); + + return impl::DeviceAddressSpaceImpl::MapNotAligned(das->device_handle, process_handle, process_address, size, device_address, device_perm); + } + + void UnmapDeviceAddressSpace(DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + AMS_ASSERT(process_address + size > process_address); + AMS_ASSERT(device_address + size > device_address); + AMS_ASSERT(size > 0); + + return impl::DeviceAddressSpaceImpl::Unmap(das->device_handle, process_handle, process_address, size, device_address); + } + + void InitializeDeviceAddressSpaceMapInfo(DeviceAddressSpaceMapInfo *info, DeviceAddressSpaceType *das, ProcessHandle process_handle, u64 process_address, size_t size, DeviceVirtualAddress device_address, MemoryPermission device_perm) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + AMS_ASSERT(util::IsAligned(process_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(device_address, os::MemoryPageSize)); + AMS_ASSERT(util::IsAligned(size, os::MemoryPageSize)); + AMS_ASSERT(process_address + size > process_address); + AMS_ASSERT(device_address + size > device_address); + AMS_ASSERT(size > 0); + + info->last_mapped_size = 0; + info->process_address = process_address; + info->size = size; + info->device_start_address = device_address; + info->device_end_address = device_address + size; + info->process_handle = process_handle; + info->device_permission = device_perm; + info->device_address_space = das; + } + + Result MapNextDeviceAddressSpaceRegion(size_t *out_mapped_size, DeviceAddressSpaceMapInfo *info) { + /* Check pre-conditions. */ + AMS_ASSERT(info->last_mapped_size == 0); + + size_t mapped_size = 0; + if (info->device_start_address < info->device_end_address) { + R_TRY(impl::DeviceAddressSpaceImpl::MapPartially(std::addressof(mapped_size), info->device_address_space->device_handle, info->process_handle, info->process_address, info->size, info->device_start_address, info->device_permission)); + } + + info->last_mapped_size = mapped_size; + *out_mapped_size = mapped_size; + return ResultSuccess(); + } + + void UnmapDeviceAddressSpaceRegion(DeviceAddressSpaceMapInfo *info) { + /* Check pre-conditions. */ + const size_t last_mapped_size = info->last_mapped_size; + AMS_ASSERT(last_mapped_size > 0); + + impl::DeviceAddressSpaceImpl::Unmap(info->device_address_space->device_handle, info->process_handle, info->process_address, last_mapped_size, info->device_start_address); + + info->last_mapped_size = 0; + info->process_address += last_mapped_size; + info->device_start_address += last_mapped_size; + } + + u64 GetMappedProcessAddress(DeviceAddressSpaceMapInfo *info) { + return info->process_address; + } + + DeviceVirtualAddress GetMappedDeviceVirtualAddress(DeviceAddressSpaceMapInfo *info) { + return info->device_start_address; + } + + size_t GetMappedSize(DeviceAddressSpaceMapInfo *info) { + return info->last_mapped_size; + } + + Result AttachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + + return impl::DeviceAddressSpaceImpl::Attach(das, device_name); + } + + void DetachDeviceAddressSpace(DeviceAddressSpaceType *das, DeviceName device_name) { + /* Check pre-conditions. */ + AMS_ASSERT(das->state == DeviceAddressSpaceType::State_Initialized); + + return impl::DeviceAddressSpaceImpl::Detach(das, device_name); + } + +} diff --git a/libstratosphere/source/dd/impl/dd_device_address_space_impl.hpp b/libstratosphere/source/dd/impl/dd_device_address_space_impl.hpp new file mode 100644 index 00000000..de47bec3 --- /dev/null +++ b/libstratosphere/source/dd/impl/dd_device_address_space_impl.hpp @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +#if defined(ATMOSPHERE_OS_HORIZON) + #include "dd_device_address_space_impl.os.horizon.hpp" +#else + #error "Unknown os for dd::DeviceAddressSpaceImpl" +#endif diff --git a/libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.cpp b/libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.cpp new file mode 100644 index 00000000..e485de16 --- /dev/null +++ b/libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include +#include "dd_device_address_space_impl.os.horizon.hpp" + +namespace ams::dd::impl { + + static_assert(static_cast(dd::MemoryPermission_None) == static_cast(svc::MemoryPermission_None)); + static_assert(static_cast(dd::MemoryPermission_ReadOnly) == static_cast(svc::MemoryPermission_Read)); + static_assert(static_cast(dd::MemoryPermission_WriteOnly) == static_cast(svc::MemoryPermission_Write)); + static_assert(static_cast(dd::MemoryPermission_ReadWrite) == static_cast(svc::MemoryPermission_ReadWrite)); + + Result DeviceAddressSpaceImplByHorizon::Create(DeviceAddressSpaceHandle *out, u64 address, u64 size) { + /* Create the space. */ + svc::Handle handle; + R_TRY_CATCH(svc::CreateDeviceAddressSpace(std::addressof(handle), address, size)) { + R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory()) + R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + *out = static_cast(handle); + return ResultSuccess(); + } + + void DeviceAddressSpaceImplByHorizon::Close(DeviceAddressSpaceHandle handle) { + const auto svc_handle = svc::Handle(handle); + if (svc_handle == svc::PseudoHandle::CurrentThread || svc_handle == svc::PseudoHandle::CurrentProcess) { + return; + } + + R_ABORT_UNLESS(svc::CloseHandle(svc_handle)); + } + + Result DeviceAddressSpaceImplByHorizon::MapAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm) { + /* Check alignment. */ + AMS_ABORT_UNLESS((process_address & (4_MB - 1)) == (device_address & (4_MB - 1))); + + R_TRY_CATCH(svc::MapDeviceAddressSpaceAligned(svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address, static_cast(device_perm))) { + R_CONVERT(svc::ResultInvalidHandle, dd::ResultInvalidHandle()) + R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory()) + R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource()) + R_CONVERT(svc::ResultInvalidCurrentMemory, dd::ResultInvalidMemoryState()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + return ResultSuccess(); + } + + Result DeviceAddressSpaceImplByHorizon::MapNotAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm) { + R_TRY_CATCH(svc::MapDeviceAddressSpaceByForce(svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address, static_cast(device_perm))) { + R_CONVERT(svc::ResultInvalidHandle, dd::ResultInvalidHandle()) + R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory()) + R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource()) + R_CONVERT(svc::ResultInvalidCurrentMemory, dd::ResultInvalidMemoryState()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + return ResultSuccess(); + } + + Result DeviceAddressSpaceImplByHorizon::MapPartially(size_t *out_mapped_size, DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm) { + ams::svc::Size mapped_size = 0; + R_TRY_CATCH(svc::MapDeviceAddressSpace(std::addressof(mapped_size), svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address, static_cast(device_perm))) { + R_CONVERT(svc::ResultInvalidHandle, dd::ResultInvalidHandle()) + R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory()) + R_CONVERT(svc::ResultOutOfResource, dd::ResultOutOfResource()) + R_CONVERT(svc::ResultInvalidCurrentMemory, dd::ResultInvalidMemoryState()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + *out_mapped_size = mapped_size; + return ResultSuccess(); + } + + void DeviceAddressSpaceImplByHorizon::Unmap(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address) { + R_ABORT_UNLESS(svc::UnmapDeviceAddressSpace(svc::Handle(handle), svc::Handle(process_handle), process_address, process_size, device_address)); + } + + Result DeviceAddressSpaceImplByHorizon::Attach(DeviceAddressSpaceType *das, DeviceName device_name) { + R_TRY_CATCH(svc::AttachDeviceAddressSpace(static_cast(device_name), svc::Handle(das->device_handle))) { + R_CONVERT(svc::ResultOutOfMemory, dd::ResultOutOfMemory()) + } R_END_TRY_CATCH_WITH_ABORT_UNLESS; + + return ResultSuccess(); + } + + void DeviceAddressSpaceImplByHorizon::Detach(DeviceAddressSpaceType *das, DeviceName device_name) { + R_ABORT_UNLESS(svc::DetachDeviceAddressSpace(static_cast(device_name), svc::Handle(das->device_handle))); + } + +} \ No newline at end of file diff --git a/libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.hpp b/libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.hpp new file mode 100644 index 00000000..86225d43 --- /dev/null +++ b/libstratosphere/source/dd/impl/dd_device_address_space_impl.os.horizon.hpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#pragma once +#include + +namespace ams::dd::impl { + + class DeviceAddressSpaceImplByHorizon { + public: + static Result Create(DeviceAddressSpaceHandle *out, u64 address, u64 size); + static void Close(DeviceAddressSpaceHandle handle); + + static Result MapAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm); + static Result MapNotAligned(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm); + static Result MapPartially(size_t *out_mapped_size, DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address, dd::MemoryPermission device_perm); + static void Unmap(DeviceAddressSpaceHandle handle, ProcessHandle process_handle, u64 process_address, size_t process_size, DeviceVirtualAddress device_address); + + static Result Attach(DeviceAddressSpaceType *das, DeviceName device_name); + static void Detach(DeviceAddressSpaceType *das, DeviceName device_name); + }; + + using DeviceAddressSpaceImpl = DeviceAddressSpaceImplByHorizon; + +} \ No newline at end of file diff --git a/libvapours/include/vapours/results.hpp b/libvapours/include/vapours/results.hpp index b69533be..f10e5af3 100644 --- a/libvapours/include/vapours/results.hpp +++ b/libvapours/include/vapours/results.hpp @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include diff --git a/libvapours/include/vapours/results/dd_results.hpp b/libvapours/include/vapours/results/dd_results.hpp new file mode 100644 index 00000000..d64a4918 --- /dev/null +++ b/libvapours/include/vapours/results/dd_results.hpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018-2020 Atmosphère-NX + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once +#include + +namespace ams::dd { + + R_DEFINE_NAMESPACE_RESULT_MODULE(6); + + R_DEFINE_ERROR_RESULT(EndOfQuery, 1); + R_DEFINE_ERROR_RESULT(InvalidCurrentMemory, 2); + R_DEFINE_ERROR_RESULT(NotSingleRegion, 3); + R_DEFINE_ERROR_RESULT(InvalidMemoryState, 4); + R_DEFINE_ERROR_RESULT(OutOfMemory, 5); + R_DEFINE_ERROR_RESULT(OutOfResource, 6); + R_DEFINE_ERROR_RESULT(NotSupported, 7); + R_DEFINE_ERROR_RESULT(InvalidHandle, 8); + + R_DEFINE_ERROR_RESULT(InternalError, 1023); + +}