From f6fb5f2c8dac1625ea70dc3b796e8464e1c05bd3 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 18 Sep 2021 13:26:21 -0700 Subject: [PATCH] kern/svc: implement IoPool/Region svc support --- .../libmesosphere/include/mesosphere.hpp | 3 +- .../arch/arm64/kern_k_process_page_table.hpp | 8 + .../mesosphere/init/kern_init_slab_setup.hpp | 4 +- .../include/mesosphere/kern_k_alpha.hpp | 39 --- .../include/mesosphere/kern_k_class_token.hpp | 6 +- .../{kern_k_beta.hpp => kern_k_io_pool.hpp} | 30 +- .../include/mesosphere/kern_k_io_region.hpp | 66 +++++ .../mesosphere/kern_k_page_table_base.hpp | 2 + .../include/mesosphere/kern_k_process.hpp | 9 +- .../nx/kern_k_io_pool.board.nintendo_nx.inc | 26 ++ .../source/init/kern_init_slab_setup.cpp | 12 +- .../source/kern_k_dump_object.cpp | 4 +- .../libmesosphere/source/kern_k_io_pool.cpp | 129 +++++++++ .../source/kern_k_io_pool.unsupported.inc | 27 ++ .../libmesosphere/source/kern_k_io_region.cpp | 99 +++++++ .../source/kern_k_page_table_base.cpp | 115 ++++++-- .../libmesosphere/source/kern_k_process.cpp | 38 ++- .../source/svc/kern_svc_alpha_beta.cpp | 79 ------ .../source/svc/kern_svc_io_pool.cpp | 214 +++++++++++++++ .../board/nintendo/nx/svc_io_pool_type.hpp | 27 ++ .../include/vapours/svc/svc_definitions.hpp | 258 +++++++++--------- .../vapours/svc/svc_select_io_pool_type.hpp | 43 +++ .../include/vapours/svc/svc_types.hpp | 1 + .../include/vapours/svc/svc_types_common.hpp | 6 + 24 files changed, 944 insertions(+), 301 deletions(-) delete mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_alpha.hpp rename libraries/libmesosphere/include/mesosphere/{kern_k_beta.hpp => kern_k_io_pool.hpp} (54%) create mode 100644 libraries/libmesosphere/include/mesosphere/kern_k_io_region.hpp create mode 100644 libraries/libmesosphere/source/board/nintendo/nx/kern_k_io_pool.board.nintendo_nx.inc create mode 100644 libraries/libmesosphere/source/kern_k_io_pool.cpp create mode 100644 libraries/libmesosphere/source/kern_k_io_pool.unsupported.inc create mode 100644 libraries/libmesosphere/source/kern_k_io_region.cpp delete mode 100644 libraries/libmesosphere/source/svc/kern_svc_alpha_beta.cpp create mode 100644 libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp create mode 100644 libraries/libvapours/include/vapours/svc/board/nintendo/nx/svc_io_pool_type.hpp create mode 100644 libraries/libvapours/include/vapours/svc/svc_select_io_pool_type.hpp diff --git a/libraries/libmesosphere/include/mesosphere.hpp b/libraries/libmesosphere/include/mesosphere.hpp index 2c538e33c..e7c3edb2d 100644 --- a/libraries/libmesosphere/include/mesosphere.hpp +++ b/libraries/libmesosphere/include/mesosphere.hpp @@ -78,8 +78,7 @@ #include #include #include -#include -#include +#include /* More Miscellaneous objects. */ #include 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 89d1ddf38..3b2a8f980 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 @@ -96,6 +96,14 @@ namespace ams::kern::arch::arm64 { return m_page_table.MapIo(phys_addr, size, perm); } + Result MapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm) { + return m_page_table.MapIoRegion(dst_address, phys_addr, size, mapping, perm); + } + + Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size) { + return m_page_table.UnmapIoRegion(dst_address, phys_addr, size); + } + Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) { return m_page_table.MapStatic(phys_addr, size, perm); } diff --git a/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp b/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp index ab3a3ca8f..f18a2fd17 100644 --- a/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp +++ b/libraries/libmesosphere/include/mesosphere/init/kern_init_slab_setup.hpp @@ -34,8 +34,8 @@ namespace ams::kern::init { size_t num_KObjectName; size_t num_KResourceLimit; size_t num_KDebug; - size_t num_KAlpha; - size_t num_KBeta; + size_t num_KIoPool; + size_t num_KIoRegion; }; NOINLINE void InitializeSlabResourceCounts(); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_alpha.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_alpha.hpp deleted file mode 100644 index f7a4fb6d4..000000000 --- a/libraries/libmesosphere/include/mesosphere/kern_k_alpha.hpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 - -namespace ams::kern { - - class KAlpha final : public KAutoObjectWithSlabHeapAndContainer { - MESOSPHERE_AUTOOBJECT_TRAITS(KAlpha, KAutoObject); - private: - /* NOTE: Official KAlpha has size 0x50, corresponding to 0x20 bytes of fields. */ - /* TODO: Add these fields, if KAlpha is ever instantiable in the NX kernel. */ - public: - explicit KAlpha() { - /* ... */ - } - - /* virtual void Finalize() override; */ - - virtual bool IsInitialized() const override { return false /* TODO */; } - static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ } - }; - -} diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp index 503510a4b..c64f226d2 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_class_token.hpp @@ -110,10 +110,8 @@ namespace ams::kern { KDeviceAddressSpace, KSessionRequest, KCodeMemory, - - /* NOTE: True order for these has not been determined yet. */ - KAlpha, - KBeta, + KIoPool, + KIoRegion, FinalClassesEnd = FinalClassesStart + NumFinalClasses, }; diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_beta.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_io_pool.hpp similarity index 54% rename from libraries/libmesosphere/include/mesosphere/kern_k_beta.hpp rename to libraries/libmesosphere/include/mesosphere/kern_k_io_pool.hpp index 37e78b6c5..00cb6e212 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_beta.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_io_pool.hpp @@ -17,30 +17,34 @@ #include #include #include +#include namespace ams::kern { - class KProcess; - - class KBeta final : public KAutoObjectWithSlabHeapAndContainer { - MESOSPHERE_AUTOOBJECT_TRAITS(KBeta, KAutoObject); + class KIoPool final : public KAutoObjectWithSlabHeapAndContainer { + MESOSPHERE_AUTOOBJECT_TRAITS(KIoPool, KAutoObject); private: - friend class KProcess; + using IoRegionList = util::IntrusiveListMemberTraits<&KIoRegion::m_pool_list_node>::ListType; private: - /* NOTE: Official KBeta has size 0x88, corresponding to 0x58 bytes of fields. */ - /* TODO: Add these fields, if KBeta is ever instantiable in the NX kernel. */ - util::IntrusiveListNode m_process_list_node; + KLightLock m_lock; + IoRegionList m_io_region_list; + ams::svc::IoPoolType m_pool_type; + bool m_is_initialized; public: - explicit KBeta() - : m_process_list_node() - { + static bool IsValidIoPoolType(ams::svc::IoPoolType pool_type); + public: + explicit KIoPool() : m_lock(), m_io_region_list(), m_is_initialized(false) { /* ... */ } - /* virtual void Finalize() override; */ + Result Initialize(ams::svc::IoPoolType pool_type); + virtual void Finalize() override; - virtual bool IsInitialized() const override { return false /* TODO */; } + virtual bool IsInitialized() const override { return m_is_initialized; } static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ } + + Result AddIoRegion(KIoRegion *region); + void RemoveIoRegion(KIoRegion *region); }; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_io_region.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_io_region.hpp new file mode 100644 index 000000000..62de364de --- /dev/null +++ b/libraries/libmesosphere/include/mesosphere/kern_k_io_region.hpp @@ -0,0 +1,66 @@ +/* + * 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 + +namespace ams::kern { + + class KProcess; + class KIoPool; + + class KIoRegion final : public KAutoObjectWithSlabHeapAndContainer { + MESOSPHERE_AUTOOBJECT_TRAITS(KIoRegion, KAutoObject); + private: + friend class KProcess; + friend class KIoPool; + private: + KLightLock m_lock; + KIoPool *m_pool; + KPhysicalAddress m_physical_address; + size_t m_size; + ams::svc::MemoryMapping m_mapping; + ams::svc::MemoryPermission m_perm; + bool m_is_initialized; + bool m_is_mapped; + util::IntrusiveListNode m_process_list_node; + util::IntrusiveListNode m_pool_list_node; + public: + explicit KIoRegion() + : m_lock(), m_pool(nullptr), m_is_initialized(false), m_process_list_node(), m_pool_list_node() + { + /* ... */ + } + + Result Initialize(KIoPool *pool, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm); + virtual void Finalize() override; + + virtual bool IsInitialized() const override { return m_is_initialized; } + static void PostDestroy(uintptr_t arg) { MESOSPHERE_UNUSED(arg); /* ... */ } + + Result Map(KProcessAddress address, size_t size, ams::svc::MemoryPermission map_perm); + Result Unmap(KProcessAddress address, size_t size); + + bool Overlaps(KPhysicalAddress address, size_t size) const { + return m_physical_address <= (address + size - 1) && address <= (m_physical_address + m_size - 1); + } + + ALWAYS_INLINE KPhysicalAddress GetAddress() const { return m_physical_address; } + ALWAYS_INLINE size_t GetSize() const { return m_size; } + }; + +} 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 cddca1a6f..0b1823445 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -339,6 +339,8 @@ namespace ams::kern { Result MapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size); Result UnmapCodeMemory(KProcessAddress dst_address, KProcessAddress src_address, size_t size); Result MapIo(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm); + Result MapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm); + Result UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size); Result MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm); Result MapRegion(KMemoryRegionType region_type, KMemoryPermission perm); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index 41606d3fc..941f8d17c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -22,7 +22,7 @@ #include #include #include -#include +#include #include #include #include @@ -53,7 +53,7 @@ namespace ams::kern { static constexpr size_t AslrAlignment = KernelAslrAlignment; private: using SharedMemoryInfoList = util::IntrusiveListBaseTraits::ListType; - using BetaList = util::IntrusiveListMemberTraits<&KBeta::m_process_list_node>::ListType; + using IoRegionList = util::IntrusiveListMemberTraits<&KIoRegion::m_process_list_node>::ListType; using TLPTree = util::IntrusiveRedBlackTreeBaseTraits::TreeType; using TLPIterator = TLPTree::iterator; private: @@ -96,7 +96,7 @@ namespace ams::kern { KThread *m_exception_thread{}; ThreadList m_thread_list{}; SharedMemoryInfoList m_shared_memory_list{}; - BetaList m_beta_list{}; + IoRegionList m_io_region_list{}; bool m_is_suspended{}; bool m_is_immortal{}; bool m_is_jit_debug{}; @@ -275,6 +275,9 @@ namespace ams::kern { Result AddSharedMemory(KSharedMemory *shmem, KProcessAddress address, size_t size); void RemoveSharedMemory(KSharedMemory *shmem, KProcessAddress address, size_t size); + void AddIoRegion(KIoRegion *io_region); + void RemoveIoRegion(KIoRegion *io_region); + Result CreateThreadLocalRegion(KProcessAddress *out); Result DeleteThreadLocalRegion(KProcessAddress addr); void *GetThreadLocalRegionPointer(KProcessAddress addr); diff --git a/libraries/libmesosphere/source/board/nintendo/nx/kern_k_io_pool.board.nintendo_nx.inc b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_io_pool.board.nintendo_nx.inc new file mode 100644 index 000000000..6354588ef --- /dev/null +++ b/libraries/libmesosphere/source/board/nintendo/nx/kern_k_io_pool.board.nintendo_nx.inc @@ -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 . + */ + +constexpr IoRegionExtents g_io_region_extents[4] = { + { KPhysicalAddress(0x12000000), 224_MB }, /* PCIE_A2 */ + { Null, 0 }, + { Null, 0 }, + { Null, 0 }, +}; + +constexpr bool IsValidIoPoolTypeImpl(ams::svc::IoPoolType pool_type) { + return pool_type == ams::svc::IoPoolType_PcieA2; +} diff --git a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp index 16fab4703..80733ea6b 100644 --- a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp +++ b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp @@ -39,8 +39,8 @@ namespace ams::kern::init { HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ## __VA_ARGS__) \ HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ## __VA_ARGS__) \ HANDLER(KDebug, (SLAB_COUNT(KDebug)), ## __VA_ARGS__) \ - HANDLER(KAlpha, (SLAB_COUNT(KAlpha)), ## __VA_ARGS__) \ - HANDLER(KBeta, (SLAB_COUNT(KBeta)), ## __VA_ARGS__) + HANDLER(KIoPool, (SLAB_COUNT(KIoPool)), ## __VA_ARGS__) \ + HANDLER(KIoRegion, (SLAB_COUNT(KIoRegion)), ## __VA_ARGS__) namespace { @@ -69,8 +69,8 @@ namespace ams::kern::init { constexpr size_t SlabCountKObjectName = 7; constexpr size_t SlabCountKResourceLimit = 5; constexpr size_t SlabCountKDebug = cpu::NumCores; - constexpr size_t SlabCountKAlpha = 1; - constexpr size_t SlabCountKBeta = 6; + constexpr size_t SlabCountKIoPool = 1; + constexpr size_t SlabCountKIoRegion = 6; constexpr size_t SlabCountExtraKThread = 160; @@ -97,8 +97,8 @@ namespace ams::kern::init { .num_KObjectName = SlabCountKObjectName, .num_KResourceLimit = SlabCountKResourceLimit, .num_KDebug = SlabCountKDebug, - .num_KAlpha = SlabCountKAlpha, - .num_KBeta = SlabCountKBeta, + .num_KIoPool = SlabCountKIoPool, + .num_KIoRegion = SlabCountKIoRegion, }; template diff --git a/libraries/libmesosphere/source/kern_k_dump_object.cpp b/libraries/libmesosphere/source/kern_k_dump_object.cpp index 024780003..f74512010 100644 --- a/libraries/libmesosphere/source/kern_k_dump_object.cpp +++ b/libraries/libmesosphere/source/kern_k_dump_object.cpp @@ -346,8 +346,8 @@ namespace ams::kern::KDumpObject { DUMP_KSLABOBJ(KEventInfo); DUMP_KSLABOBJ(KSessionRequest); DUMP_KSLABOBJ(KResourceLimit); - DUMP_KSLABOBJ(KAlpha); - DUMP_KSLABOBJ(KBeta); + DUMP_KSLABOBJ(KIoPool); + DUMP_KSLABOBJ(KIoRegion); #undef DUMP_KSLABOBJ diff --git a/libraries/libmesosphere/source/kern_k_io_pool.cpp b/libraries/libmesosphere/source/kern_k_io_pool.cpp new file mode 100644 index 000000000..2b9746e31 --- /dev/null +++ b/libraries/libmesosphere/source/kern_k_io_pool.cpp @@ -0,0 +1,129 @@ +/* + * 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 + +namespace ams::kern { + + namespace { + + constinit KLightLock g_io_pool_lock; + constinit bool g_pool_used[ams::svc::IoPoolType_Count]; + + struct IoRegionExtents { + KPhysicalAddress address; + size_t size; + }; + + #if defined(ATMOSPHERE_BOARD_NINTENDO_NX) + + #include "board/nintendo/nx/kern_k_io_pool.board.nintendo_nx.inc" + + #elif defined(AMS_SVC_IO_POOL_NOT_SUPPORTED) + + #include "kern_k_io_pool.unsupported.inc" + + #else + + #error "Unknown context for IoPoolType!" + + #endif + + constexpr bool IsValidIoRegionImpl(ams::svc::IoPoolType pool_type, KPhysicalAddress address, size_t size) { + /* NOTE: It seems likely this depends on pool type, but this isn't confirmable as of now. */ + MESOSPHERE_UNUSED(pool_type); + + /* Check if the address/size falls within any allowable extents. */ + for (const auto &extents : g_io_region_extents) { + if (extents.address <= address && address + size - 1 <= extents.address + extents.size - 1) { + return true; + } + } + + return false; + } + + } + + bool KIoPool::IsValidIoPoolType(ams::svc::IoPoolType pool_type) { + return IsValidIoPoolTypeImpl(pool_type); + } + + Result KIoPool::Initialize(ams::svc::IoPoolType pool_type) { + MESOSPHERE_ASSERT_THIS(); + + /* Register the pool type. */ + { + /* Lock the pool used table. */ + KScopedLightLock lk(g_io_pool_lock); + + /* Check that the pool isn't already used. */ + R_UNLESS(!g_pool_used[pool_type], svc::ResultBusy()); + + /* Set the pool as used. */ + g_pool_used[pool_type] = true; + } + + /* Set our fields. */ + m_pool_type = pool_type; + m_is_initialized = true; + + return ResultSuccess(); + } + + void KIoPool::Finalize() { + MESOSPHERE_ASSERT_THIS(); + + /* Lock the pool used table. */ + KScopedLightLock lk(g_io_pool_lock); + + /* Check that the pool is used. */ + MESOSPHERE_ASSERT(g_pool_used[m_pool_type]); + + /* Set the pool as unused. */ + g_pool_used[m_pool_type] = false; + } + + Result KIoPool::AddIoRegion(KIoRegion *new_region) { + MESOSPHERE_ASSERT_THIS(); + + /* Check that the region is allowed. */ + R_UNLESS(IsValidIoRegionImpl(m_pool_type, new_region->GetAddress(), new_region->GetSize()), svc::ResultInvalidMemoryRegion()); + + /* Lock ourselves. */ + KScopedLightLock lk(m_lock); + + /* Check that the desired range isn't already in our pool. */ + for (const auto ®ion : m_io_region_list) { + R_UNLESS(!region.Overlaps(new_region->GetAddress(), new_region->GetSize()), svc::ResultBusy()); + } + + /* Add the region to our pool. */ + m_io_region_list.push_back(*new_region); + + return ResultSuccess(); + } + + void KIoPool::RemoveIoRegion(KIoRegion *region) { + MESOSPHERE_ASSERT_THIS(); + + /* Lock ourselves. */ + KScopedLightLock lk(m_lock); + + /* Remove the region from our list. */ + m_io_region_list.erase(m_io_region_list.iterator_to(*region)); + } + +} diff --git a/libraries/libmesosphere/source/kern_k_io_pool.unsupported.inc b/libraries/libmesosphere/source/kern_k_io_pool.unsupported.inc new file mode 100644 index 000000000..d3077ccb5 --- /dev/null +++ b/libraries/libmesosphere/source/kern_k_io_pool.unsupported.inc @@ -0,0 +1,27 @@ +/* + * 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 . + */ + +constexpr IoRegionExtents g_io_region_extents[4] = { + { Null, 0 }, + { Null, 0 }, + { Null, 0 }, + { Null, 0 }, +}; + +constexpr bool IsValidIoPoolTypeImpl(ams::svc::IoPoolType pool_type) { + MESOSPHERE_UNUSED(pool_type); + return false; +} \ No newline at end of file diff --git a/libraries/libmesosphere/source/kern_k_io_region.cpp b/libraries/libmesosphere/source/kern_k_io_region.cpp new file mode 100644 index 000000000..35e2c31fd --- /dev/null +++ b/libraries/libmesosphere/source/kern_k_io_region.cpp @@ -0,0 +1,99 @@ +/* + * 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 + +namespace ams::kern { + + Result KIoRegion::Initialize(KIoPool *pool, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm) { + MESOSPHERE_ASSERT_THIS(); + + /* Set fields. */ + m_physical_address = phys_addr; + m_size = size; + m_mapping = mapping; + m_perm = perm; + m_pool = pool; + m_is_mapped = false; + + /* Add ourselves to our pool. */ + R_TRY(m_pool->AddIoRegion(this)); + + /* Open a reference to our pool. */ + m_pool->Open(); + + /* Mark ourselves as initialized. */ + m_is_initialized = true; + + return ResultSuccess(); + } + + void KIoRegion::Finalize() { + /* Remove ourselves from our pool. */ + m_pool->RemoveIoRegion(this); + + /* Close our reference to our pool. */ + m_pool->Close(); + } + + Result KIoRegion::Map(KProcessAddress address, size_t size, ams::svc::MemoryPermission map_perm) { + MESOSPHERE_ASSERT_THIS(); + + /* Check that the desired perm is allowable. */ + R_UNLESS((m_perm | map_perm) == m_perm, svc::ResultInvalidNewMemoryPermission()); + + /* Check that the size is correct. */ + R_UNLESS(size == m_size, svc::ResultInvalidSize()); + + /* Lock ourselves. */ + KScopedLightLock lk(m_lock); + + /* Check that we're not already mapped. */ + R_UNLESS(!m_is_mapped, svc::ResultInvalidState()); + + /* Map ourselves. */ + R_TRY(GetCurrentProcess().GetPageTable().MapIoRegion(address, m_physical_address, size, m_mapping, map_perm)); + + /* Add ourselves to the current process. */ + GetCurrentProcess().AddIoRegion(this); + + /* Note that we're mapped. */ + m_is_mapped = true; + + return ResultSuccess(); + } + + Result KIoRegion::Unmap(KProcessAddress address, size_t size) { + MESOSPHERE_ASSERT_THIS(); + + /* Check that the size is correct. */ + R_UNLESS(size == m_size, svc::ResultInvalidSize()); + + /* Lock ourselves. */ + KScopedLightLock lk(m_lock); + + /* Unmap ourselves. */ + R_TRY(GetCurrentProcess().GetPageTable().UnmapIoRegion(address, m_physical_address, size)); + + /* Remove ourselves from the current process. */ + GetCurrentProcess().RemoveIoRegion(this); + + /* Note that we're unmapped. */ + m_is_mapped = false; + + 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 cf97c8449..f03081dfe 100644 --- a/libraries/libmesosphere/source/kern_k_page_table_base.cpp +++ b/libraries/libmesosphere/source/kern_k_page_table_base.cpp @@ -163,23 +163,23 @@ namespace ams::kern { heap_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Heap); stack_region_size = GetSpaceSize(KAddressSpaceInfo::Type_Stack); kernel_map_region_size = GetSpaceSize(KAddressSpaceInfo::Type_MapSmall); - m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit); - m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit); - m_alias_code_region_start = m_code_region_start; - m_alias_code_region_end = m_code_region_end; + m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_Map39Bit); + m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_Map39Bit); + m_alias_code_region_start = m_code_region_start; + m_alias_code_region_end = m_code_region_end; process_code_start = util::AlignDown(GetInteger(code_address), RegionAlignment); process_code_end = util::AlignUp(GetInteger(code_address) + code_size, RegionAlignment); } else { stack_region_size = 0; kernel_map_region_size = 0; - m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapSmall); - m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapSmall); - m_stack_region_start = m_code_region_start; - m_alias_code_region_start = m_code_region_start; - m_alias_code_region_end = GetSpaceStart(KAddressSpaceInfo::Type_MapLarge) + GetSpaceSize(KAddressSpaceInfo::Type_MapLarge); - m_stack_region_end = m_code_region_end; - m_kernel_map_region_start = m_code_region_start; - m_kernel_map_region_end = m_code_region_end; + m_code_region_start = GetSpaceStart(KAddressSpaceInfo::Type_MapSmall); + m_code_region_end = m_code_region_start + GetSpaceSize(KAddressSpaceInfo::Type_MapSmall); + m_stack_region_start = m_code_region_start; + m_alias_code_region_start = m_code_region_start; + m_alias_code_region_end = GetSpaceStart(KAddressSpaceInfo::Type_MapLarge) + GetSpaceSize(KAddressSpaceInfo::Type_MapLarge); + m_stack_region_end = m_code_region_end; + m_kernel_map_region_start = m_code_region_start; + m_kernel_map_region_end = m_code_region_end; process_code_start = m_code_region_start; process_code_end = m_code_region_end; } @@ -368,10 +368,10 @@ namespace ams::kern { return m_alias_region_start; case KMemoryState_Stack: return m_stack_region_start; - case KMemoryState_Io: case KMemoryState_Static: case KMemoryState_ThreadLocal: return m_kernel_map_region_start; + case KMemoryState_Io: case KMemoryState_Shared: case KMemoryState_AliasCode: case KMemoryState_AliasCodeData: @@ -402,10 +402,10 @@ namespace ams::kern { return m_alias_region_end - m_alias_region_start; case KMemoryState_Stack: return m_stack_region_end - m_stack_region_start; - case KMemoryState_Io: case KMemoryState_Static: case KMemoryState_ThreadLocal: return m_kernel_map_region_end - m_kernel_map_region_start; + case KMemoryState_Io: case KMemoryState_Shared: case KMemoryState_AliasCode: case KMemoryState_AliasCodeData: @@ -1823,10 +1823,12 @@ namespace ams::kern { const KPhysicalAddress last = phys_addr + size - 1; /* Get region extents. */ - const KProcessAddress region_start = this->GetRegionAddress(KMemoryState_Io); - const size_t region_size = this->GetRegionSize(KMemoryState_Io); + const KProcessAddress region_start = m_kernel_map_region_start; + const size_t region_size = m_kernel_map_region_end - m_kernel_map_region_start; const size_t region_num_pages = region_size / PageSize; + MESOSPHERE_ASSERT(this->CanContain(region_start, region_size, KMemoryState_Io)); + /* Locate the memory region. */ const KMemoryRegion *region = KMemoryLayout::Find(phys_addr); R_UNLESS(region != nullptr, svc::ResultInvalidAddress()); @@ -1906,6 +1908,87 @@ namespace ams::kern { return ResultSuccess(); } + Result KPageTableBase::MapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission svc_perm) { + const size_t num_pages = size / PageSize; + + /* Lock the table. */ + KScopedLightLock lk(m_general_lock); + + /* Validate the memory state. */ + size_t num_allocator_blocks; + R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), dst_address, size, KMemoryState_All, KMemoryState_None, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_None, KMemoryAttribute_None)); + + /* Create an update allocator. */ + Result allocator_result; + KMemoryBlockManagerUpdateAllocator allocator(std::addressof(allocator_result), m_memory_block_slab_manager, num_allocator_blocks); + R_TRY(allocator_result); + + /* We're going to perform an update, so create a helper. */ + KScopedPageTableUpdater updater(this); + + /* Perform mapping operation. */ + const KMemoryPermission perm = ConvertToKMemoryPermission(svc_perm); + const KPageProperties properties = { perm, mapping == ams::svc::MemoryMapping_IoRegister, mapping == ams::svc::MemoryMapping_Uncached, DisableMergeAttribute_DisableHead }; + R_TRY(this->Operate(updater.GetPageList(), dst_address, num_pages, phys_addr, true, properties, OperationType_Map, false)); + + /* Update the blocks. */ + m_memory_block_manager.Update(std::addressof(allocator), dst_address, num_pages, KMemoryState_Io, perm, KMemoryAttribute_None, KMemoryBlockDisableMergeAttribute_Normal, KMemoryBlockDisableMergeAttribute_None); + + /* We successfully mapped the pages. */ + return ResultSuccess(); + } + + Result KPageTableBase::UnmapIoRegion(KProcessAddress dst_address, KPhysicalAddress phys_addr, size_t size) { + const size_t num_pages = size / PageSize; + + /* Lock the table. */ + KScopedLightLock lk(m_general_lock); + + /* Validate the memory state. */ + size_t num_allocator_blocks; + R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), dst_address, size, KMemoryState_All, KMemoryState_Io, KMemoryPermission_None, KMemoryPermission_None, KMemoryAttribute_All, KMemoryAttribute_None)); + + /* Validate that the region being unmapped corresponds to the physical range described. */ + { + /* Get the impl. */ + auto &impl = this->GetImpl(); + + /* Begin traversal. */ + TraversalContext context; + TraversalEntry next_entry; + MESOSPHERE_ABORT_UNLESS(impl.BeginTraversal(std::addressof(next_entry), std::addressof(context), dst_address)); + + /* Check that the physical region matches. */ + R_UNLESS(next_entry.phys_addr == phys_addr, svc::ResultInvalidMemoryRegion()); + + /* Iterate. */ + for (size_t checked_size = next_entry.block_size - (GetInteger(phys_addr) & (next_entry.block_size - 1)); checked_size < size; checked_size += next_entry.block_size) { + /* Continue the traversal. */ + MESOSPHERE_ABORT_UNLESS(impl.ContinueTraversal(std::addressof(next_entry), std::addressof(context))); + + /* Check that the physical region matches. */ + R_UNLESS(next_entry.phys_addr == phys_addr + checked_size, svc::ResultInvalidMemoryRegion()); + } + } + + /* Create an update allocator. */ + Result allocator_result; + KMemoryBlockManagerUpdateAllocator allocator(std::addressof(allocator_result), m_memory_block_slab_manager, num_allocator_blocks); + R_TRY(allocator_result); + + /* We're going to perform an update, so create a helper. */ + KScopedPageTableUpdater updater(this); + + /* Perform the unmap. */ + const KPageProperties unmap_properties = { KMemoryPermission_None, false, false, DisableMergeAttribute_None }; + R_TRY(this->Operate(updater.GetPageList(), dst_address, num_pages, Null, false, unmap_properties, OperationType_Unmap, false)); + + /* Update the blocks. */ + m_memory_block_manager.Update(std::addressof(allocator), dst_address, num_pages, KMemoryState_Free, KMemoryPermission_None, KMemoryAttribute_None, KMemoryBlockDisableMergeAttribute_None, KMemoryBlockDisableMergeAttribute_Normal); + + return ResultSuccess(); + } + Result KPageTableBase::MapStatic(KPhysicalAddress phys_addr, size_t size, KMemoryPermission perm) { MESOSPHERE_ASSERT(util::IsAligned(GetInteger(phys_addr), PageSize)); MESOSPHERE_ASSERT(util::IsAligned(size, PageSize)); diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index b69e1eeeb..a19386d32 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -141,14 +141,14 @@ namespace ams::kern { } } - /* Close all references to our betas. */ + /* Close all references to our io regions. */ { - auto it = m_beta_list.begin(); - while (it != m_beta_list.end()) { - KBeta *beta = std::addressof(*it); - it = m_beta_list.erase(it); + auto it = m_io_region_list.begin(); + while (it != m_io_region_list.end()) { + KIoRegion *io_region = std::addressof(*it); + it = m_io_region_list.erase(it); - beta->Close(); + io_region->Close(); } } @@ -597,6 +597,32 @@ namespace ams::kern { shmem->Close(); } + void KProcess::AddIoRegion(KIoRegion *io_region) { + /* Lock ourselves, to prevent concurrent access. */ + KScopedLightLock lk(m_state_lock); + + /* Open a reference to the region. */ + io_region->Open(); + + /* Add the region to our list. */ + m_io_region_list.push_back(*io_region); + + } + + void KProcess::RemoveIoRegion(KIoRegion *io_region) { + /* Remove the region from our list. */ + { + /* Lock ourselves, to prevent concurrent access. */ + KScopedLightLock lk(m_state_lock); + + /* Remove the region from our list. */ + m_io_region_list.erase(m_io_region_list.iterator_to(*io_region)); + } + + /* Close our reference to the io region. */ + io_region->Close(); + } + Result KProcess::CreateThreadLocalRegion(KProcessAddress *out) { KThreadLocalPage *tlp = nullptr; KProcessAddress tlr = Null; diff --git a/libraries/libmesosphere/source/svc/kern_svc_alpha_beta.cpp b/libraries/libmesosphere/source/svc/kern_svc_alpha_beta.cpp deleted file mode 100644 index 3aa3b8958..000000000 --- a/libraries/libmesosphere/source/svc/kern_svc_alpha_beta.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * 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 - -namespace ams::kern::svc { - - /* ============================= Common ============================= */ - - namespace { - - Result Unknown39() { - return svc::ResultNotImplemented(); - } - - Result Unknown3A() { - return svc::ResultNotImplemented(); - } - - Result Unknown46() { - return svc::ResultNotImplemented(); - } - - Result Unknown47() { - return svc::ResultNotImplemented(); - } - - } - - /* ============================= 64 ABI ============================= */ - - Result Unknown3964() { - return Unknown39(); - } - - Result Unknown3A64() { - /* NOTE: From official stubs, true API to this is something like Unknown3A(u64 *, u32_or_u64, u64, u64, u64_or_u32, u64_or_u32); */ - return Unknown3A(); - } - - Result Unknown4664() { - return Unknown46(); - } - - Result Unknown4764() { - return Unknown47(); - } - - /* ============================= 64From32 ABI ============================= */ - - Result Unknown3964From32() { - return Unknown39(); - } - - Result Unknown3A64From32() { - return Unknown3A(); - } - - Result Unknown4664From32() { - return Unknown46(); - } - - Result Unknown4764From32() { - return Unknown47(); - } - -} diff --git a/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp b/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp new file mode 100644 index 000000000..f98a1d2ef --- /dev/null +++ b/libraries/libmesosphere/source/svc/kern_svc_io_pool.cpp @@ -0,0 +1,214 @@ +/* + * 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 + +namespace ams::kern::svc { + + /* ============================= Common ============================= */ + + namespace { + + #if defined(AMS_SVC_IO_POOL_NOT_SUPPORTED) + constexpr bool IsIoPoolApiSupported = false; + #else + constexpr bool IsIoPoolApiSupported = true; + #endif + + [[maybe_unused]] constexpr bool IsValidIoRegionMapping(ams::svc::MemoryMapping mapping) { + switch (mapping) { + case ams::svc::MemoryMapping_IoRegister: + case ams::svc::MemoryMapping_Uncached: + case ams::svc::MemoryMapping_Memory: + return true; + default: + return false; + } + } + + [[maybe_unused]] constexpr bool IsValidIoRegionPermission(ams::svc::MemoryPermission perm) { + switch (perm) { + case ams::svc::MemoryPermission_Read: + case ams::svc::MemoryPermission_ReadWrite: + return true; + default: + return false; + } + } + + Result CreateIoPool(ams::svc::Handle *out, ams::svc::IoPoolType pool_type) { + if constexpr (IsIoPoolApiSupported) { + /* Validate that we're allowed to create a pool for the given type. */ + R_UNLESS(KIoPool::IsValidIoPoolType(pool_type), svc::ResultNotFound()); + + /* Create the io pool. */ + KIoPool *io_pool = KIoPool::Create(); + R_UNLESS(io_pool != nullptr, svc::ResultOutOfResource()); + + /* Ensure the only reference is in the handle table when we're done. */ + ON_SCOPE_EXIT { io_pool->Close(); }; + + /* Initialize the io pool. */ + R_TRY(io_pool->Initialize(pool_type)); + + /* Register the io pool. */ + KIoPool::Register(io_pool); + + /* Add the io pool to the handle table. */ + R_TRY(GetCurrentProcess().GetHandleTable().Add(out, io_pool)); + + return ResultSuccess(); + } else { + MESOSPHERE_UNUSED(out, pool_type); + return svc::ResultNotImplemented(); + } + } + + Result CreateIoRegion(ams::svc::Handle *out, ams::svc::Handle io_pool_handle, uint64_t phys_addr, size_t size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm) { + if constexpr (IsIoPoolApiSupported) { + /* Validate the address/size. */ + R_UNLESS(size > 0, svc::ResultInvalidSize()); + R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize()); + R_UNLESS(util::IsAligned(phys_addr, PageSize), svc::ResultInvalidAddress()); + R_UNLESS((phys_addr < phys_addr + size), svc::ResultInvalidMemoryRegion()); + + /* Validate the mapping/permissions. */ + R_UNLESS(IsValidIoRegionMapping(mapping), svc::ResultInvalidEnumValue()); + R_UNLESS(IsValidIoRegionPermission(perm), svc::ResultInvalidEnumValue()); + + /* Get the current handle table. */ + auto &handle_table = GetCurrentProcess().GetHandleTable(); + + /* Get the io pool. */ + KScopedAutoObject io_pool = handle_table.GetObject(io_pool_handle); + R_UNLESS(io_pool.IsNotNull(), svc::ResultInvalidHandle()); + + /* Create the io region. */ + KIoRegion *io_region = KIoRegion::Create(); + R_UNLESS(io_region != nullptr, svc::ResultOutOfResource()); + + /* Ensure the only reference is in the handle table when we're done. */ + ON_SCOPE_EXIT { io_region->Close(); }; + + /* Initialize the io region. */ + R_TRY(io_region->Initialize(io_pool.GetPointerUnsafe(), phys_addr, size, mapping, perm)); + + /* Register the io region. */ + KIoRegion::Register(io_region); + + /* Add the io region to the handle table. */ + R_TRY(handle_table.Add(out, io_region)); + + return ResultSuccess(); + } else { + MESOSPHERE_UNUSED(out, io_pool_handle, phys_addr, size, mapping, perm); + return svc::ResultNotImplemented(); + } + } + + Result MapIoRegion(ams::svc::Handle io_region_handle, uintptr_t address, size_t size, ams::svc::MemoryPermission map_perm) { + if constexpr (IsIoPoolApiSupported) { + /* Validate the address/size. */ + R_UNLESS(size > 0, svc::ResultInvalidSize()); + R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize()); + R_UNLESS(util::IsAligned(address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory()); + + /* Verify that the mapping is in range. */ + R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_Io), svc::ResultInvalidMemoryRegion()); + + /* Validate the map permission. */ + R_UNLESS(IsValidIoRegionPermission(map_perm), svc::ResultInvalidNewMemoryPermission()); + + /* Get the io region. */ + KScopedAutoObject io_region = GetCurrentProcess().GetHandleTable().GetObject(io_region_handle); + R_UNLESS(io_region.IsNotNull(), svc::ResultInvalidHandle()); + + /* Map the io region. */ + R_TRY(io_region->Map(address, size, map_perm)); + + /* We succeeded. */ + return ResultSuccess(); + } else { + MESOSPHERE_UNUSED(io_region_handle, address, size, map_perm); + return svc::ResultNotImplemented(); + } + } + + Result UnmapIoRegion(ams::svc::Handle io_region_handle, uintptr_t address, size_t size) { + if constexpr (IsIoPoolApiSupported) { + /* Validate the address/size. */ + R_UNLESS(size > 0, svc::ResultInvalidSize()); + R_UNLESS(util::IsAligned(size, PageSize), svc::ResultInvalidSize()); + R_UNLESS(util::IsAligned(address, PageSize), svc::ResultInvalidAddress()); + R_UNLESS((address < address + size), svc::ResultInvalidCurrentMemory()); + + /* Verify that the mapping is in range. */ + R_UNLESS(GetCurrentProcess().GetPageTable().CanContain(address, size, KMemoryState_Io), svc::ResultInvalidMemoryRegion()); + + /* Get the io region. */ + KScopedAutoObject io_region = GetCurrentProcess().GetHandleTable().GetObject(io_region_handle); + R_UNLESS(io_region.IsNotNull(), svc::ResultInvalidHandle()); + + /* Unmap the io region. */ + R_TRY(io_region->Unmap(address, size)); + + /* We succeeded. */ + return ResultSuccess(); + } else { + MESOSPHERE_UNUSED(io_region_handle, address, size); + return svc::ResultNotImplemented(); + } + } + + } + + /* ============================= 64 ABI ============================= */ + + Result CreateIoPool64(ams::svc::Handle *out_handle, ams::svc::IoPoolType pool_type) { + return CreateIoPool(out_handle, pool_type); + } + + Result CreateIoRegion64(ams::svc::Handle *out_handle, ams::svc::Handle io_pool, ams::svc::PhysicalAddress physical_address, ams::svc::Size size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm) { + return CreateIoRegion(out_handle, io_pool, physical_address, size, mapping, perm); + } + + Result MapIoRegion64(ams::svc::Handle io_region, ams::svc::Address address, ams::svc::Size size, ams::svc::MemoryPermission perm) { + return MapIoRegion(io_region, address, size, perm); + } + + Result UnmapIoRegion64(ams::svc::Handle io_region, ams::svc::Address address, ams::svc::Size size) { + return UnmapIoRegion(io_region, address, size); + } + + /* ============================= 64From32 ABI ============================= */ + + Result CreateIoPool64From32(ams::svc::Handle *out_handle, ams::svc::IoPoolType pool_type) { + return CreateIoPool(out_handle, pool_type); + } + + Result CreateIoRegion64From32(ams::svc::Handle *out_handle, ams::svc::Handle io_pool, ams::svc::PhysicalAddress physical_address, ams::svc::Size size, ams::svc::MemoryMapping mapping, ams::svc::MemoryPermission perm) { + return CreateIoRegion(out_handle, io_pool, physical_address, size, mapping, perm); + } + + Result MapIoRegion64From32(ams::svc::Handle io_region, ams::svc::Address address, ams::svc::Size size, ams::svc::MemoryPermission perm) { + return MapIoRegion(io_region, address, size, perm); + } + + Result UnmapIoRegion64From32(ams::svc::Handle io_region, ams::svc::Address address, ams::svc::Size size) { + return UnmapIoRegion(io_region, address, size); + } + +} diff --git a/libraries/libvapours/include/vapours/svc/board/nintendo/nx/svc_io_pool_type.hpp b/libraries/libvapours/include/vapours/svc/board/nintendo/nx/svc_io_pool_type.hpp new file mode 100644 index 000000000..077ecc29a --- /dev/null +++ b/libraries/libvapours/include/vapours/svc/board/nintendo/nx/svc_io_pool_type.hpp @@ -0,0 +1,27 @@ +/* + * 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::svc::board::nintendo::nx { + + enum IoPoolType : u32 { + IoPoolType_PcieA2 = 0, /* NOTE: Name is not official. */ + + IoPoolType_Count = 1, + }; + +} diff --git a/libraries/libvapours/include/vapours/svc/svc_definitions.hpp b/libraries/libvapours/include/vapours/svc/svc_definitions.hpp index a506b753b..df886af90 100644 --- a/libraries/libvapours/include/vapours/svc/svc_definitions.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_definitions.hpp @@ -28,135 +28,135 @@ #define AMS_SVC_USER_INPTR_HANDLER(TYPE, NAME) ::ams::svc::UserPointer NAME #define AMS_SVC_USER_OUTPTR_HANDLER(TYPE, NAME) ::ams::svc::UserPointer NAME -#define AMS_SVC_FOREACH_DEFINITION_IMPL(HANDLER, NAMESPACE, INPUT, OUTPUT, INPTR, OUTPTR) \ - HANDLER(0x01, Result, SetHeapSize, OUTPUT(::ams::svc::Address, out_address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x02, Result, SetMemoryPermission, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, perm)) \ - HANDLER(0x03, Result, SetMemoryAttribute, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(uint32_t, mask), INPUT(uint32_t, attr)) \ - HANDLER(0x04, Result, MapMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Address, src_address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x05, Result, UnmapMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Address, src_address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x06, Result, QueryMemory, OUTPTR(::ams::svc::NAMESPACE::MemoryInfo, out_memory_info), OUTPUT(::ams::svc::PageInfo, out_page_info), INPUT(::ams::svc::Address, address)) \ - HANDLER(0x07, void, ExitProcess) \ - HANDLER(0x08, Result, CreateThread, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::ThreadFunc, func), INPUT(::ams::svc::Address, arg), INPUT(::ams::svc::Address, stack_bottom), INPUT(int32_t, priority), INPUT(int32_t, core_id)) \ - HANDLER(0x09, Result, StartThread, INPUT(::ams::svc::Handle, thread_handle)) \ - HANDLER(0x0A, void, ExitThread) \ - HANDLER(0x0B, void, SleepThread, INPUT(int64_t, ns)) \ - HANDLER(0x0C, Result, GetThreadPriority, OUTPUT(int32_t, out_priority), INPUT(::ams::svc::Handle, thread_handle)) \ - HANDLER(0x0D, Result, SetThreadPriority, INPUT(::ams::svc::Handle, thread_handle), INPUT(int32_t, priority)) \ - HANDLER(0x0E, Result, GetThreadCoreMask, OUTPUT(int32_t, out_core_id), OUTPUT(uint64_t, out_affinity_mask), INPUT(::ams::svc::Handle, thread_handle)) \ - HANDLER(0x0F, Result, SetThreadCoreMask, INPUT(::ams::svc::Handle, thread_handle), INPUT(int32_t, core_id), INPUT(uint64_t, affinity_mask)) \ - HANDLER(0x10, int32_t, GetCurrentProcessorNumber) \ - HANDLER(0x11, Result, SignalEvent, INPUT(::ams::svc::Handle, event_handle)) \ - HANDLER(0x12, Result, ClearEvent, INPUT(::ams::svc::Handle, event_handle)) \ - HANDLER(0x13, Result, MapSharedMemory, INPUT(::ams::svc::Handle, shmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, map_perm)) \ - HANDLER(0x14, Result, UnmapSharedMemory, INPUT(::ams::svc::Handle, shmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x15, Result, CreateTransferMemory, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, map_perm)) \ - HANDLER(0x16, Result, CloseHandle, INPUT(::ams::svc::Handle, handle)) \ - HANDLER(0x17, Result, ResetSignal, INPUT(::ams::svc::Handle, handle)) \ - HANDLER(0x18, Result, WaitSynchronization, OUTPUT(int32_t, out_index), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(int64_t, timeout_ns)) \ - HANDLER(0x19, Result, CancelSynchronization, INPUT(::ams::svc::Handle, handle)) \ - HANDLER(0x1A, Result, ArbitrateLock, INPUT(::ams::svc::Handle, thread_handle), INPUT(::ams::svc::Address, address), INPUT(uint32_t, tag)) \ - HANDLER(0x1B, Result, ArbitrateUnlock, INPUT(::ams::svc::Address, address)) \ - HANDLER(0x1C, Result, WaitProcessWideKeyAtomic, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Address, cv_key), INPUT(uint32_t, tag), INPUT(int64_t, timeout_ns)) \ - HANDLER(0x1D, void, SignalProcessWideKey, INPUT(::ams::svc::Address, cv_key), INPUT(int32_t, count)) \ - HANDLER(0x1E, int64_t, GetSystemTick) \ - HANDLER(0x1F, Result, ConnectToNamedPort, OUTPUT(::ams::svc::Handle, out_handle), INPTR(char, name)) \ - HANDLER(0x20, Result, SendSyncRequestLight, INPUT(::ams::svc::Handle, session_handle)) \ - HANDLER(0x21, Result, SendSyncRequest, INPUT(::ams::svc::Handle, session_handle)) \ - HANDLER(0x22, Result, SendSyncRequestWithUserBuffer, INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPUT(::ams::svc::Handle, session_handle)) \ - HANDLER(0x23, Result, SendAsyncRequestWithUserBuffer, OUTPUT(::ams::svc::Handle, out_event_handle), INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPUT(::ams::svc::Handle, session_handle)) \ - HANDLER(0x24, Result, GetProcessId, OUTPUT(uint64_t, out_process_id), INPUT(::ams::svc::Handle, process_handle)) \ - HANDLER(0x25, Result, GetThreadId, OUTPUT(uint64_t, out_thread_id), INPUT(::ams::svc::Handle, thread_handle)) \ - HANDLER(0x26, void, Break, INPUT(::ams::svc::BreakReason, break_reason), INPUT(::ams::svc::Address, arg), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x27, Result, OutputDebugString, INPTR(char, debug_str), INPUT(::ams::svc::Size, len)) \ - HANDLER(0x28, void, ReturnFromException, INPUT(::ams::Result, result)) \ - HANDLER(0x29, Result, GetInfo, OUTPUT(uint64_t, out), INPUT(::ams::svc::InfoType, info_type), INPUT(::ams::svc::Handle, handle), INPUT(uint64_t, info_subtype)) \ - HANDLER(0x2A, void, FlushEntireDataCache) \ - HANDLER(0x2B, Result, FlushDataCache, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x2C, Result, MapPhysicalMemory, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x2D, Result, UnmapPhysicalMemory, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x2E, Result, GetDebugFutureThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(uint64_t, thread_id), INPUT(::ams::svc::Handle, debug_handle), INPUT(int64_t, ns)) \ - HANDLER(0x2F, Result, GetLastThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(::ams::svc::Address, out_tls_address), OUTPUT(uint32_t, out_flags)) \ - HANDLER(0x30, Result, GetResourceLimitLimitValue, OUTPUT(int64_t, out_limit_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \ - HANDLER(0x31, Result, GetResourceLimitCurrentValue, OUTPUT(int64_t, out_current_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \ - HANDLER(0x32, Result, SetThreadActivity, INPUT(::ams::svc::Handle, thread_handle), INPUT(::ams::svc::ThreadActivity, thread_activity)) \ - HANDLER(0x33, Result, GetThreadContext3, OUTPTR(::ams::svc::ThreadContext, out_context), INPUT(::ams::svc::Handle, thread_handle)) \ - HANDLER(0x34, Result, WaitForAddress, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::ArbitrationType, arb_type), INPUT(int32_t, value), INPUT(int64_t, timeout_ns)) \ - HANDLER(0x35, Result, SignalToAddress, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::SignalType, signal_type), INPUT(int32_t, value), INPUT(int32_t, count)) \ - HANDLER(0x36, void, SynchronizePreemptionState) \ - HANDLER(0x37, Result, GetResourceLimitPeakValue, OUTPUT(int64_t, out_peak_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \ - \ - HANDLER(0x39, Result, Unknown39) \ - HANDLER(0x3A, Result, Unknown3A) \ - \ - HANDLER(0x3C, void, KernelDebug, INPUT(::ams::svc::KernelDebugType, kern_debug_type), INPUT(uint64_t, arg0), INPUT(uint64_t, arg1), INPUT(uint64_t, arg2)) \ - HANDLER(0x3D, void, ChangeKernelTraceState, INPUT(::ams::svc::KernelTraceState, kern_trace_state)) \ - \ - HANDLER(0x40, Result, CreateSession, OUTPUT(::ams::svc::Handle, out_server_session_handle), OUTPUT(::ams::svc::Handle, out_client_session_handle), INPUT(bool, is_light), INPUT(::ams::svc::Address, name)) \ - HANDLER(0x41, Result, AcceptSession, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Handle, port)) \ - HANDLER(0x42, Result, ReplyAndReceiveLight, INPUT(::ams::svc::Handle, handle)) \ - HANDLER(0x43, Result, ReplyAndReceive, OUTPUT(int32_t, out_index), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(::ams::svc::Handle, reply_target), INPUT(int64_t, timeout_ns)) \ - HANDLER(0x44, Result, ReplyAndReceiveWithUserBuffer, OUTPUT(int32_t, out_index), INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(::ams::svc::Handle, reply_target), INPUT(int64_t, timeout_ns)) \ - HANDLER(0x45, Result, CreateEvent, OUTPUT(::ams::svc::Handle, out_write_handle), OUTPUT(::ams::svc::Handle, out_read_handle)) \ - HANDLER(0x46, Result, Unknown46) \ - HANDLER(0x47, Result, Unknown47) \ - HANDLER(0x48, Result, MapPhysicalMemoryUnsafe, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x49, Result, UnmapPhysicalMemoryUnsafe, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x4A, Result, SetUnsafeLimit, INPUT(::ams::svc::Size, limit)) \ - HANDLER(0x4B, Result, CreateCodeMemory, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x4C, Result, ControlCodeMemory, INPUT(::ams::svc::Handle, code_memory_handle), INPUT(::ams::svc::CodeMemoryOperation, operation), INPUT(uint64_t, address), INPUT(uint64_t, size), INPUT(::ams::svc::MemoryPermission, perm)) \ - HANDLER(0x4D, void, SleepSystem) \ - HANDLER(0x4E, Result, ReadWriteRegister, OUTPUT(uint32_t, out_value), INPUT(::ams::svc::PhysicalAddress, address), INPUT(uint32_t, mask), INPUT(uint32_t, value)) \ - HANDLER(0x4F, Result, SetProcessActivity, INPUT(::ams::svc::Handle, process_handle), INPUT(::ams::svc::ProcessActivity, process_activity)) \ - HANDLER(0x50, Result, CreateSharedMemory, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, owner_perm), INPUT(::ams::svc::MemoryPermission, remote_perm)) \ - HANDLER(0x51, Result, MapTransferMemory, INPUT(::ams::svc::Handle, trmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, owner_perm)) \ - HANDLER(0x52, Result, UnmapTransferMemory, INPUT(::ams::svc::Handle, trmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x53, Result, CreateInterruptEvent, OUTPUT(::ams::svc::Handle, out_read_handle), INPUT(int32_t, interrupt_id), INPUT(::ams::svc::InterruptType, interrupt_type)) \ - HANDLER(0x54, Result, QueryPhysicalAddress, OUTPUT(::ams::svc::NAMESPACE::PhysicalMemoryInfo, out_info), INPUT(::ams::svc::Address, address)) \ - HANDLER(0x55, Result, QueryIoMapping, OUTPUT(::ams::svc::Address, out_address), OUTPUT(::ams::svc::Size, out_size), INPUT(::ams::svc::PhysicalAddress, physical_address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x56, Result, CreateDeviceAddressSpace, OUTPUT(::ams::svc::Handle, out_handle), INPUT(uint64_t, das_address), INPUT(uint64_t, das_size)) \ - HANDLER(0x57, Result, AttachDeviceAddressSpace, INPUT(::ams::svc::DeviceName, device_name), INPUT(::ams::svc::Handle, das_handle)) \ - HANDLER(0x58, Result, DetachDeviceAddressSpace, INPUT(::ams::svc::DeviceName, device_name), INPUT(::ams::svc::Handle, das_handle)) \ - HANDLER(0x59, Result, MapDeviceAddressSpaceByForce, INPUT(::ams::svc::Handle, das_handle), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, process_address), INPUT(::ams::svc::Size, size), INPUT(uint64_t, device_address), INPUT(::ams::svc::MemoryPermission, device_perm)) \ - HANDLER(0x5A, Result, MapDeviceAddressSpaceAligned, INPUT(::ams::svc::Handle, das_handle), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, process_address), INPUT(::ams::svc::Size, size), INPUT(uint64_t, device_address), INPUT(::ams::svc::MemoryPermission, device_perm)) \ - HANDLER(0x5C, Result, UnmapDeviceAddressSpace, INPUT(::ams::svc::Handle, das_handle), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, process_address), INPUT(::ams::svc::Size, size), INPUT(uint64_t, device_address)) \ - HANDLER(0x5D, Result, InvalidateProcessDataCache, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size)) \ - HANDLER(0x5E, Result, StoreProcessDataCache, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size)) \ - HANDLER(0x5F, Result, FlushProcessDataCache, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size)) \ - HANDLER(0x60, Result, DebugActiveProcess, OUTPUT(::ams::svc::Handle, out_handle), INPUT(uint64_t, process_id)) \ - HANDLER(0x61, Result, BreakDebugProcess, INPUT(::ams::svc::Handle, debug_handle)) \ - HANDLER(0x62, Result, TerminateDebugProcess, INPUT(::ams::svc::Handle, debug_handle)) \ - HANDLER(0x63, Result, GetDebugEvent, OUTPTR(::ams::svc::NAMESPACE::DebugEventInfo, out_info), INPUT(::ams::svc::Handle, debug_handle)) \ - HANDLER(0x64, Result, ContinueDebugEvent, INPUT(::ams::svc::Handle, debug_handle), INPUT(uint32_t, flags), INPTR(uint64_t, thread_ids), INPUT(int32_t, num_thread_ids)) \ - HANDLER(0x65, Result, GetProcessList, OUTPUT(int32_t, out_num_processes), OUTPTR(uint64_t, out_process_ids), INPUT(int32_t, max_out_count)) \ - HANDLER(0x66, Result, GetThreadList, OUTPUT(int32_t, out_num_threads), OUTPTR(uint64_t, out_thread_ids), INPUT(int32_t, max_out_count), INPUT(::ams::svc::Handle, debug_handle)) \ - HANDLER(0x67, Result, GetDebugThreadContext, OUTPTR(::ams::svc::ThreadContext, out_context), INPUT(::ams::svc::Handle, debug_handle), INPUT(uint64_t, thread_id), INPUT(uint32_t, context_flags)) \ - HANDLER(0x68, Result, SetDebugThreadContext, INPUT(::ams::svc::Handle, debug_handle), INPUT(uint64_t, thread_id), INPTR(::ams::svc::ThreadContext, context), INPUT(uint32_t, context_flags)) \ - HANDLER(0x69, Result, QueryDebugProcessMemory, OUTPTR(::ams::svc::NAMESPACE::MemoryInfo, out_memory_info), OUTPUT(::ams::svc::PageInfo, out_page_info), INPUT(::ams::svc::Handle, process_handle), INPUT(::ams::svc::Address, address)) \ - HANDLER(0x6A, Result, ReadDebugProcessMemory, INPUT(::ams::svc::Address, buffer), INPUT(::ams::svc::Handle, debug_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x6B, Result, WriteDebugProcessMemory, INPUT(::ams::svc::Handle, debug_handle), INPUT(::ams::svc::Address, buffer), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x6C, Result, SetHardwareBreakPoint, INPUT(::ams::svc::HardwareBreakPointRegisterName, name), INPUT(uint64_t, flags), INPUT(uint64_t, value)) \ - HANDLER(0x6D, Result, GetDebugThreadParam, OUTPUT(uint64_t, out_64), OUTPUT(uint32_t, out_32), INPUT(::ams::svc::Handle, debug_handle), INPUT(uint64_t, thread_id), INPUT(::ams::svc::DebugThreadParam, param)) \ - \ - HANDLER(0x6F, Result, GetSystemInfo, OUTPUT(uint64_t, out), INPUT(::ams::svc::SystemInfoType, info_type), INPUT(::ams::svc::Handle, handle), INPUT(uint64_t, info_subtype)) \ - HANDLER(0x70, Result, CreatePort, OUTPUT(::ams::svc::Handle, out_server_handle), OUTPUT(::ams::svc::Handle, out_client_handle), INPUT(int32_t, max_sessions), INPUT(bool, is_light), INPUT(::ams::svc::Address, name)) \ - HANDLER(0x71, Result, ManageNamedPort, OUTPUT(::ams::svc::Handle, out_server_handle), INPTR(char, name), INPUT(int32_t, max_sessions)) \ - HANDLER(0x72, Result, ConnectToPort, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Handle, port)) \ - HANDLER(0x73, Result, SetProcessMemoryPermission, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size), INPUT(::ams::svc::MemoryPermission, perm)) \ - HANDLER(0x74, Result, MapProcessMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, src_address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x75, Result, UnmapProcessMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, src_address), INPUT(::ams::svc::Size, size)) \ - HANDLER(0x76, Result, QueryProcessMemory, OUTPTR(::ams::svc::NAMESPACE::MemoryInfo, out_memory_info), OUTPUT(::ams::svc::PageInfo, out_page_info), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address)) \ - HANDLER(0x77, Result, MapProcessCodeMemory, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, dst_address), INPUT(uint64_t, src_address), INPUT(uint64_t, size)) \ - HANDLER(0x78, Result, UnmapProcessCodeMemory, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, dst_address), INPUT(uint64_t, src_address), INPUT(uint64_t, size)) \ - HANDLER(0x79, Result, CreateProcess, OUTPUT(::ams::svc::Handle, out_handle), INPTR(::ams::svc::NAMESPACE::CreateProcessParameter, parameters), INPTR(uint32_t, caps), INPUT(int32_t, num_caps)) \ - HANDLER(0x7A, Result, StartProcess, INPUT(::ams::svc::Handle, process_handle), INPUT(int32_t, priority), INPUT(int32_t, core_id), INPUT(uint64_t, main_thread_stack_size)) \ - HANDLER(0x7B, Result, TerminateProcess, INPUT(::ams::svc::Handle, process_handle)) \ - HANDLER(0x7C, Result, GetProcessInfo, OUTPUT(int64_t, out_info), INPUT(::ams::svc::Handle, process_handle), INPUT(::ams::svc::ProcessInfoType, info_type)) \ - HANDLER(0x7D, Result, CreateResourceLimit, OUTPUT(::ams::svc::Handle, out_handle)) \ - HANDLER(0x7E, Result, SetResourceLimitLimitValue, INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which), INPUT(int64_t, limit_value)) \ - HANDLER(0x7F, void, CallSecureMonitor, OUTPUT(::ams::svc::NAMESPACE::SecureMonitorArguments, args)) \ - \ - HANDLER(0x2E, Result, LegacyGetFutureThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(::ams::svc::Address, out_tls_address), OUTPUT(uint32_t, out_flags), INPUT(int64_t, ns)) \ - HANDLER(0x55, Result, LegacyQueryIoMapping, OUTPUT(::ams::svc::Address, out_address), INPUT(::ams::svc::PhysicalAddress, physical_address), INPUT(::ams::svc::Size, size)) \ +#define AMS_SVC_FOREACH_DEFINITION_IMPL(HANDLER, NAMESPACE, INPUT, OUTPUT, INPTR, OUTPTR) \ + HANDLER(0x01, Result, SetHeapSize, OUTPUT(::ams::svc::Address, out_address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x02, Result, SetMemoryPermission, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, perm)) \ + HANDLER(0x03, Result, SetMemoryAttribute, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(uint32_t, mask), INPUT(uint32_t, attr)) \ + HANDLER(0x04, Result, MapMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Address, src_address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x05, Result, UnmapMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Address, src_address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x06, Result, QueryMemory, OUTPTR(::ams::svc::NAMESPACE::MemoryInfo, out_memory_info), OUTPUT(::ams::svc::PageInfo, out_page_info), INPUT(::ams::svc::Address, address)) \ + HANDLER(0x07, void, ExitProcess) \ + HANDLER(0x08, Result, CreateThread, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::ThreadFunc, func), INPUT(::ams::svc::Address, arg), INPUT(::ams::svc::Address, stack_bottom), INPUT(int32_t, priority), INPUT(int32_t, core_id)) \ + HANDLER(0x09, Result, StartThread, INPUT(::ams::svc::Handle, thread_handle)) \ + HANDLER(0x0A, void, ExitThread) \ + HANDLER(0x0B, void, SleepThread, INPUT(int64_t, ns)) \ + HANDLER(0x0C, Result, GetThreadPriority, OUTPUT(int32_t, out_priority), INPUT(::ams::svc::Handle, thread_handle)) \ + HANDLER(0x0D, Result, SetThreadPriority, INPUT(::ams::svc::Handle, thread_handle), INPUT(int32_t, priority)) \ + HANDLER(0x0E, Result, GetThreadCoreMask, OUTPUT(int32_t, out_core_id), OUTPUT(uint64_t, out_affinity_mask), INPUT(::ams::svc::Handle, thread_handle)) \ + HANDLER(0x0F, Result, SetThreadCoreMask, INPUT(::ams::svc::Handle, thread_handle), INPUT(int32_t, core_id), INPUT(uint64_t, affinity_mask)) \ + HANDLER(0x10, int32_t, GetCurrentProcessorNumber) \ + HANDLER(0x11, Result, SignalEvent, INPUT(::ams::svc::Handle, event_handle)) \ + HANDLER(0x12, Result, ClearEvent, INPUT(::ams::svc::Handle, event_handle)) \ + HANDLER(0x13, Result, MapSharedMemory, INPUT(::ams::svc::Handle, shmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, map_perm)) \ + HANDLER(0x14, Result, UnmapSharedMemory, INPUT(::ams::svc::Handle, shmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x15, Result, CreateTransferMemory, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, map_perm)) \ + HANDLER(0x16, Result, CloseHandle, INPUT(::ams::svc::Handle, handle)) \ + HANDLER(0x17, Result, ResetSignal, INPUT(::ams::svc::Handle, handle)) \ + HANDLER(0x18, Result, WaitSynchronization, OUTPUT(int32_t, out_index), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(int64_t, timeout_ns)) \ + HANDLER(0x19, Result, CancelSynchronization, INPUT(::ams::svc::Handle, handle)) \ + HANDLER(0x1A, Result, ArbitrateLock, INPUT(::ams::svc::Handle, thread_handle), INPUT(::ams::svc::Address, address), INPUT(uint32_t, tag)) \ + HANDLER(0x1B, Result, ArbitrateUnlock, INPUT(::ams::svc::Address, address)) \ + HANDLER(0x1C, Result, WaitProcessWideKeyAtomic, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Address, cv_key), INPUT(uint32_t, tag), INPUT(int64_t, timeout_ns)) \ + HANDLER(0x1D, void, SignalProcessWideKey, INPUT(::ams::svc::Address, cv_key), INPUT(int32_t, count)) \ + HANDLER(0x1E, int64_t, GetSystemTick) \ + HANDLER(0x1F, Result, ConnectToNamedPort, OUTPUT(::ams::svc::Handle, out_handle), INPTR(char, name)) \ + HANDLER(0x20, Result, SendSyncRequestLight, INPUT(::ams::svc::Handle, session_handle)) \ + HANDLER(0x21, Result, SendSyncRequest, INPUT(::ams::svc::Handle, session_handle)) \ + HANDLER(0x22, Result, SendSyncRequestWithUserBuffer, INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPUT(::ams::svc::Handle, session_handle)) \ + HANDLER(0x23, Result, SendAsyncRequestWithUserBuffer, OUTPUT(::ams::svc::Handle, out_event_handle), INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPUT(::ams::svc::Handle, session_handle)) \ + HANDLER(0x24, Result, GetProcessId, OUTPUT(uint64_t, out_process_id), INPUT(::ams::svc::Handle, process_handle)) \ + HANDLER(0x25, Result, GetThreadId, OUTPUT(uint64_t, out_thread_id), INPUT(::ams::svc::Handle, thread_handle)) \ + HANDLER(0x26, void, Break, INPUT(::ams::svc::BreakReason, break_reason), INPUT(::ams::svc::Address, arg), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x27, Result, OutputDebugString, INPTR(char, debug_str), INPUT(::ams::svc::Size, len)) \ + HANDLER(0x28, void, ReturnFromException, INPUT(::ams::Result, result)) \ + HANDLER(0x29, Result, GetInfo, OUTPUT(uint64_t, out), INPUT(::ams::svc::InfoType, info_type), INPUT(::ams::svc::Handle, handle), INPUT(uint64_t, info_subtype)) \ + HANDLER(0x2A, void, FlushEntireDataCache) \ + HANDLER(0x2B, Result, FlushDataCache, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x2C, Result, MapPhysicalMemory, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x2D, Result, UnmapPhysicalMemory, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x2E, Result, GetDebugFutureThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(uint64_t, thread_id), INPUT(::ams::svc::Handle, debug_handle), INPUT(int64_t, ns)) \ + HANDLER(0x2F, Result, GetLastThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(::ams::svc::Address, out_tls_address), OUTPUT(uint32_t, out_flags)) \ + HANDLER(0x30, Result, GetResourceLimitLimitValue, OUTPUT(int64_t, out_limit_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \ + HANDLER(0x31, Result, GetResourceLimitCurrentValue, OUTPUT(int64_t, out_current_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \ + HANDLER(0x32, Result, SetThreadActivity, INPUT(::ams::svc::Handle, thread_handle), INPUT(::ams::svc::ThreadActivity, thread_activity)) \ + HANDLER(0x33, Result, GetThreadContext3, OUTPTR(::ams::svc::ThreadContext, out_context), INPUT(::ams::svc::Handle, thread_handle)) \ + HANDLER(0x34, Result, WaitForAddress, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::ArbitrationType, arb_type), INPUT(int32_t, value), INPUT(int64_t, timeout_ns)) \ + HANDLER(0x35, Result, SignalToAddress, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::SignalType, signal_type), INPUT(int32_t, value), INPUT(int32_t, count)) \ + HANDLER(0x36, void, SynchronizePreemptionState) \ + HANDLER(0x37, Result, GetResourceLimitPeakValue, OUTPUT(int64_t, out_peak_value), INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which)) \ + \ + HANDLER(0x39, Result, CreateIoPool, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::IoPoolType, which)) \ + HANDLER(0x3A, Result, CreateIoRegion, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Handle, io_pool), INPUT(::ams::svc::PhysicalAddress, physical_address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryMapping, mapping), INPUT(::ams::svc::MemoryPermission, perm)) \ + \ + HANDLER(0x3C, void, KernelDebug, INPUT(::ams::svc::KernelDebugType, kern_debug_type), INPUT(uint64_t, arg0), INPUT(uint64_t, arg1), INPUT(uint64_t, arg2)) \ + HANDLER(0x3D, void, ChangeKernelTraceState, INPUT(::ams::svc::KernelTraceState, kern_trace_state)) \ + \ + HANDLER(0x40, Result, CreateSession, OUTPUT(::ams::svc::Handle, out_server_session_handle), OUTPUT(::ams::svc::Handle, out_client_session_handle), INPUT(bool, is_light), INPUT(::ams::svc::Address, name)) \ + HANDLER(0x41, Result, AcceptSession, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Handle, port)) \ + HANDLER(0x42, Result, ReplyAndReceiveLight, INPUT(::ams::svc::Handle, handle)) \ + HANDLER(0x43, Result, ReplyAndReceive, OUTPUT(int32_t, out_index), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(::ams::svc::Handle, reply_target), INPUT(int64_t, timeout_ns)) \ + HANDLER(0x44, Result, ReplyAndReceiveWithUserBuffer, OUTPUT(int32_t, out_index), INPUT(::ams::svc::Address, message_buffer), INPUT(::ams::svc::Size, message_buffer_size), INPTR(::ams::svc::Handle, handles), INPUT(int32_t, num_handles), INPUT(::ams::svc::Handle, reply_target), INPUT(int64_t, timeout_ns)) \ + HANDLER(0x45, Result, CreateEvent, OUTPUT(::ams::svc::Handle, out_write_handle), OUTPUT(::ams::svc::Handle, out_read_handle)) \ + HANDLER(0x46, Result, MapIoRegion, INPUT(::ams::svc::Handle, io_region), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, perm)) \ + HANDLER(0x47, Result, UnmapIoRegion, INPUT(::ams::svc::Handle, io_region), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x48, Result, MapPhysicalMemoryUnsafe, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x49, Result, UnmapPhysicalMemoryUnsafe, INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x4A, Result, SetUnsafeLimit, INPUT(::ams::svc::Size, limit)) \ + HANDLER(0x4B, Result, CreateCodeMemory, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x4C, Result, ControlCodeMemory, INPUT(::ams::svc::Handle, code_memory_handle), INPUT(::ams::svc::CodeMemoryOperation, operation), INPUT(uint64_t, address), INPUT(uint64_t, size), INPUT(::ams::svc::MemoryPermission, perm)) \ + HANDLER(0x4D, void, SleepSystem) \ + HANDLER(0x4E, Result, ReadWriteRegister, OUTPUT(uint32_t, out_value), INPUT(::ams::svc::PhysicalAddress, address), INPUT(uint32_t, mask), INPUT(uint32_t, value)) \ + HANDLER(0x4F, Result, SetProcessActivity, INPUT(::ams::svc::Handle, process_handle), INPUT(::ams::svc::ProcessActivity, process_activity)) \ + HANDLER(0x50, Result, CreateSharedMemory, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, owner_perm), INPUT(::ams::svc::MemoryPermission, remote_perm)) \ + HANDLER(0x51, Result, MapTransferMemory, INPUT(::ams::svc::Handle, trmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size), INPUT(::ams::svc::MemoryPermission, owner_perm)) \ + HANDLER(0x52, Result, UnmapTransferMemory, INPUT(::ams::svc::Handle, trmem_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x53, Result, CreateInterruptEvent, OUTPUT(::ams::svc::Handle, out_read_handle), INPUT(int32_t, interrupt_id), INPUT(::ams::svc::InterruptType, interrupt_type)) \ + HANDLER(0x54, Result, QueryPhysicalAddress, OUTPUT(::ams::svc::NAMESPACE::PhysicalMemoryInfo, out_info), INPUT(::ams::svc::Address, address)) \ + HANDLER(0x55, Result, QueryIoMapping, OUTPUT(::ams::svc::Address, out_address), OUTPUT(::ams::svc::Size, out_size), INPUT(::ams::svc::PhysicalAddress, physical_address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x56, Result, CreateDeviceAddressSpace, OUTPUT(::ams::svc::Handle, out_handle), INPUT(uint64_t, das_address), INPUT(uint64_t, das_size)) \ + HANDLER(0x57, Result, AttachDeviceAddressSpace, INPUT(::ams::svc::DeviceName, device_name), INPUT(::ams::svc::Handle, das_handle)) \ + HANDLER(0x58, Result, DetachDeviceAddressSpace, INPUT(::ams::svc::DeviceName, device_name), INPUT(::ams::svc::Handle, das_handle)) \ + HANDLER(0x59, Result, MapDeviceAddressSpaceByForce, INPUT(::ams::svc::Handle, das_handle), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, process_address), INPUT(::ams::svc::Size, size), INPUT(uint64_t, device_address), INPUT(::ams::svc::MemoryPermission, device_perm)) \ + HANDLER(0x5A, Result, MapDeviceAddressSpaceAligned, INPUT(::ams::svc::Handle, das_handle), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, process_address), INPUT(::ams::svc::Size, size), INPUT(uint64_t, device_address), INPUT(::ams::svc::MemoryPermission, device_perm)) \ + HANDLER(0x5C, Result, UnmapDeviceAddressSpace, INPUT(::ams::svc::Handle, das_handle), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, process_address), INPUT(::ams::svc::Size, size), INPUT(uint64_t, device_address)) \ + HANDLER(0x5D, Result, InvalidateProcessDataCache, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size)) \ + HANDLER(0x5E, Result, StoreProcessDataCache, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size)) \ + HANDLER(0x5F, Result, FlushProcessDataCache, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size)) \ + HANDLER(0x60, Result, DebugActiveProcess, OUTPUT(::ams::svc::Handle, out_handle), INPUT(uint64_t, process_id)) \ + HANDLER(0x61, Result, BreakDebugProcess, INPUT(::ams::svc::Handle, debug_handle)) \ + HANDLER(0x62, Result, TerminateDebugProcess, INPUT(::ams::svc::Handle, debug_handle)) \ + HANDLER(0x63, Result, GetDebugEvent, OUTPTR(::ams::svc::NAMESPACE::DebugEventInfo, out_info), INPUT(::ams::svc::Handle, debug_handle)) \ + HANDLER(0x64, Result, ContinueDebugEvent, INPUT(::ams::svc::Handle, debug_handle), INPUT(uint32_t, flags), INPTR(uint64_t, thread_ids), INPUT(int32_t, num_thread_ids)) \ + HANDLER(0x65, Result, GetProcessList, OUTPUT(int32_t, out_num_processes), OUTPTR(uint64_t, out_process_ids), INPUT(int32_t, max_out_count)) \ + HANDLER(0x66, Result, GetThreadList, OUTPUT(int32_t, out_num_threads), OUTPTR(uint64_t, out_thread_ids), INPUT(int32_t, max_out_count), INPUT(::ams::svc::Handle, debug_handle)) \ + HANDLER(0x67, Result, GetDebugThreadContext, OUTPTR(::ams::svc::ThreadContext, out_context), INPUT(::ams::svc::Handle, debug_handle), INPUT(uint64_t, thread_id), INPUT(uint32_t, context_flags)) \ + HANDLER(0x68, Result, SetDebugThreadContext, INPUT(::ams::svc::Handle, debug_handle), INPUT(uint64_t, thread_id), INPTR(::ams::svc::ThreadContext, context), INPUT(uint32_t, context_flags)) \ + HANDLER(0x69, Result, QueryDebugProcessMemory, OUTPTR(::ams::svc::NAMESPACE::MemoryInfo, out_memory_info), OUTPUT(::ams::svc::PageInfo, out_page_info), INPUT(::ams::svc::Handle, process_handle), INPUT(::ams::svc::Address, address)) \ + HANDLER(0x6A, Result, ReadDebugProcessMemory, INPUT(::ams::svc::Address, buffer), INPUT(::ams::svc::Handle, debug_handle), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x6B, Result, WriteDebugProcessMemory, INPUT(::ams::svc::Handle, debug_handle), INPUT(::ams::svc::Address, buffer), INPUT(::ams::svc::Address, address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x6C, Result, SetHardwareBreakPoint, INPUT(::ams::svc::HardwareBreakPointRegisterName, name), INPUT(uint64_t, flags), INPUT(uint64_t, value)) \ + HANDLER(0x6D, Result, GetDebugThreadParam, OUTPUT(uint64_t, out_64), OUTPUT(uint32_t, out_32), INPUT(::ams::svc::Handle, debug_handle), INPUT(uint64_t, thread_id), INPUT(::ams::svc::DebugThreadParam, param)) \ + \ + HANDLER(0x6F, Result, GetSystemInfo, OUTPUT(uint64_t, out), INPUT(::ams::svc::SystemInfoType, info_type), INPUT(::ams::svc::Handle, handle), INPUT(uint64_t, info_subtype)) \ + HANDLER(0x70, Result, CreatePort, OUTPUT(::ams::svc::Handle, out_server_handle), OUTPUT(::ams::svc::Handle, out_client_handle), INPUT(int32_t, max_sessions), INPUT(bool, is_light), INPUT(::ams::svc::Address, name)) \ + HANDLER(0x71, Result, ManageNamedPort, OUTPUT(::ams::svc::Handle, out_server_handle), INPTR(char, name), INPUT(int32_t, max_sessions)) \ + HANDLER(0x72, Result, ConnectToPort, OUTPUT(::ams::svc::Handle, out_handle), INPUT(::ams::svc::Handle, port)) \ + HANDLER(0x73, Result, SetProcessMemoryPermission, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address), INPUT(uint64_t, size), INPUT(::ams::svc::MemoryPermission, perm)) \ + HANDLER(0x74, Result, MapProcessMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, src_address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x75, Result, UnmapProcessMemory, INPUT(::ams::svc::Address, dst_address), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, src_address), INPUT(::ams::svc::Size, size)) \ + HANDLER(0x76, Result, QueryProcessMemory, OUTPTR(::ams::svc::NAMESPACE::MemoryInfo, out_memory_info), OUTPUT(::ams::svc::PageInfo, out_page_info), INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, address)) \ + HANDLER(0x77, Result, MapProcessCodeMemory, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, dst_address), INPUT(uint64_t, src_address), INPUT(uint64_t, size)) \ + HANDLER(0x78, Result, UnmapProcessCodeMemory, INPUT(::ams::svc::Handle, process_handle), INPUT(uint64_t, dst_address), INPUT(uint64_t, src_address), INPUT(uint64_t, size)) \ + HANDLER(0x79, Result, CreateProcess, OUTPUT(::ams::svc::Handle, out_handle), INPTR(::ams::svc::NAMESPACE::CreateProcessParameter, parameters), INPTR(uint32_t, caps), INPUT(int32_t, num_caps)) \ + HANDLER(0x7A, Result, StartProcess, INPUT(::ams::svc::Handle, process_handle), INPUT(int32_t, priority), INPUT(int32_t, core_id), INPUT(uint64_t, main_thread_stack_size)) \ + HANDLER(0x7B, Result, TerminateProcess, INPUT(::ams::svc::Handle, process_handle)) \ + HANDLER(0x7C, Result, GetProcessInfo, OUTPUT(int64_t, out_info), INPUT(::ams::svc::Handle, process_handle), INPUT(::ams::svc::ProcessInfoType, info_type)) \ + HANDLER(0x7D, Result, CreateResourceLimit, OUTPUT(::ams::svc::Handle, out_handle)) \ + HANDLER(0x7E, Result, SetResourceLimitLimitValue, INPUT(::ams::svc::Handle, resource_limit_handle), INPUT(::ams::svc::LimitableResource, which), INPUT(int64_t, limit_value)) \ + HANDLER(0x7F, void, CallSecureMonitor, OUTPUT(::ams::svc::NAMESPACE::SecureMonitorArguments, args)) \ + \ + HANDLER(0x2E, Result, LegacyGetFutureThreadInfo, OUTPUT(::ams::svc::NAMESPACE::LastThreadContext, out_context), OUTPUT(::ams::svc::Address, out_tls_address), OUTPUT(uint32_t, out_flags), INPUT(int64_t, ns)) \ + HANDLER(0x55, Result, LegacyQueryIoMapping, OUTPUT(::ams::svc::Address, out_address), INPUT(::ams::svc::PhysicalAddress, physical_address), INPUT(::ams::svc::Size, size)) \ HANDLER(0x64, Result, LegacyContinueDebugEvent, INPUT(::ams::svc::Handle, debug_handle), INPUT(uint32_t, flags), INPUT(uint64_t, thread_id)) #define AMS_SVC_FOREACH_USER_DEFINITION(HANDLER, NAMESPACE) AMS_SVC_FOREACH_DEFINITION_IMPL(HANDLER, NAMESPACE, AMS_SVC_USER_INPUT_HANDLER, AMS_SVC_USER_OUTPUT_HANDLER, AMS_SVC_USER_INPTR_HANDLER, AMS_SVC_USER_OUTPTR_HANDLER) diff --git a/libraries/libvapours/include/vapours/svc/svc_select_io_pool_type.hpp b/libraries/libvapours/include/vapours/svc/svc_select_io_pool_type.hpp new file mode 100644 index 000000000..8fab8d184 --- /dev/null +++ b/libraries/libvapours/include/vapours/svc/svc_select_io_pool_type.hpp @@ -0,0 +1,43 @@ +/* + * 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_BOARD_NINTENDO_NX) + + #include + namespace ams::svc { + + using IoPoolType = ::ams::svc::board::nintendo::nx::IoPoolType; + using enum ::ams::svc::board::nintendo::nx::IoPoolType; + + } + +#else + + #define AMS_SVC_IO_POOL_NOT_SUPPORTED + + namespace ams::svc { + + enum IoPoolType : u32 { + /* Not supported. */ + IoPoolType_Count = 0, + }; + + } + +#endif diff --git a/libraries/libvapours/include/vapours/svc/svc_types.hpp b/libraries/libvapours/include/vapours/svc/svc_types.hpp index 40f36cbfa..9d281e028 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types.hpp @@ -23,3 +23,4 @@ #include #include #include +#include diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 4ed4a6b71..adbfd476e 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -117,6 +117,12 @@ namespace ams::svc { MemoryAttribute_Uncached = (1 << 3), }; + enum MemoryMapping : u32 { + MemoryMapping_IoRegister = 0, + MemoryMapping_Uncached = 1, + MemoryMapping_Memory = 2, + }; + constexpr inline size_t HeapSizeAlignment = 2_MB; struct PageInfo {