From 4759c2f92cedb1cc17cde146f3e123966591ab71 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Sat, 14 Mar 2020 23:13:40 -0700 Subject: [PATCH] svc: add ipc accessor boilerplate --- libraries/libvapours/include/vapours/svc.hpp | 1 + .../arch/arm64/svc_thread_local_region.hpp | 38 ++ .../vapours/svc/ipc/svc_message_buffer.hpp | 547 ++++++++++++++++++ .../include/vapours/svc/svc_common.hpp | 4 +- .../svc/svc_select_thread_local_region.hpp | 39 ++ .../include/vapours/svc/svc_types.hpp | 1 + .../include/vapours/svc/svc_types_common.hpp | 2 - 7 files changed, 628 insertions(+), 4 deletions(-) create mode 100644 libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp create mode 100644 libraries/libvapours/include/vapours/svc/ipc/svc_message_buffer.hpp create mode 100644 libraries/libvapours/include/vapours/svc/svc_select_thread_local_region.hpp diff --git a/libraries/libvapours/include/vapours/svc.hpp b/libraries/libvapours/include/vapours/svc.hpp index b26487520..2ce0d36aa 100644 --- a/libraries/libvapours/include/vapours/svc.hpp +++ b/libraries/libvapours/include/vapours/svc.hpp @@ -21,3 +21,4 @@ #include #include +#include diff --git a/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp b/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp new file mode 100644 index 000000000..c871ff4c1 --- /dev/null +++ b/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp @@ -0,0 +1,38 @@ +/* + * 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::arch::arm64 { + + constexpr inline size_t NumTlsSlots = 16; + constexpr inline size_t MessageBufferSize = 0x100; + + struct ThreadLocalRegion { + u32 message_buffer[MessageBufferSize / sizeof(u32)]; + u16 disable_count; + u16 preemption_state; + /* TODO: How should we handle libnx vs Nintendo user thread local space? */ + uintptr_t TODO[(0x200 - 0x108) / sizeof(uintptr_t)]; + }; + + ALWAYS_INLINE ThreadLocalRegion *GetThreadLocalRegion() { + ThreadLocalRegion *tlr; + __asm__ __volatile__("mrs %[tlr], tpidrro_el0" : [tlr]"=&r"(tlr) :: "memory"); + return tlr; + } + +} diff --git a/libraries/libvapours/include/vapours/svc/ipc/svc_message_buffer.hpp b/libraries/libvapours/include/vapours/svc/ipc/svc_message_buffer.hpp new file mode 100644 index 000000000..6afa9d97f --- /dev/null +++ b/libraries/libvapours/include/vapours/svc/ipc/svc_message_buffer.hpp @@ -0,0 +1,547 @@ +/* + * 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::svc::ipc { + + ALWAYS_INLINE u32 *GetMessageBuffer() { + return GetThreadLocalRegion()->message_buffer; + } + + constexpr inline size_t MessageBufferSize = sizeof(::ams::svc::ThreadLocalRegion::message_buffer); + + class MessageBuffer { + public: + class MessageHeader { + private: + /* Define fields for the first header word. */ + using Tag = util::BitPack32::Field<0, BITSIZEOF(u16), u16>; + using PointerCount = util::BitPack32::Field; + using SendCount = util::BitPack32::Field; + using ReceiveCount = util::BitPack32::Field; + using ExchangeCount = util::BitPack32::Field; + static_assert(ExchangeCount::Next == BITSIZEOF(u32)); + + /* Define fields for the second header word. */ + using RawCount = util::BitPack32::Field<0, 10, s32>; + using ReceiveListCount = util::BitPack32::Field; + using Reserved0 = util::BitPack32::Field; + using ReceiveListOffset = util::BitPack32::Field; + using HasSpecialHeader = util::BitPack32::Field; + + static constexpr inline u64 NullTag = 0; + static_assert(HasSpecialHeader::Next == BITSIZEOF(u32)); + public: + enum ReceiveListCountType { + ReceiveListCountType_None = 0, + ReceiveListCountType_ToMessageBuffer = 1, + ReceiveListCountType_ToSingleBuffer = 2, + + ReceiveListCountType_CountOffset = 2, + ReceiveListCountType_CountMax = 13, + }; + private: + util::BitPack32 header[2]; + public: + constexpr ALWAYS_INLINE MessageHeader() : header({util::BitPack32(0), util::BitPack32(0)}) { + this->header[0].Set(NullTag); + } + + constexpr ALWAYS_INLINE MessageHeader(u16 tag, bool special, s32 ptr, s32 send, s32 recv, s32 exch, s32 raw, s32 recv_list) : header({util::BitPack32(0), util::BitPack32(0)}) { + this->header[0].Set(tag); + this->header[0].Set(ptr); + this->header[0].Set(send); + this->header[0].Set(recv); + this->header[0].Set(exch); + + this->header[1].Set(raw); + this->header[1].Set(recv_list); + this->header[1].Set(special); + } + + ALWAYS_INLINE explicit MessageHeader(const MessageBuffer &buf) : header({util::BitPack32(0), util::BitPack32(0)}) { + buf.Get(0, this->header, util::size(this->header)); + } + + ALWAYS_INLINE explicit MessageHeader(const u32 *msg) : header({util::BitPack32(msg[0]), util::BitPack32(msg[1])}) { /* ... */ } + + constexpr ALWAYS_INLINE u16 GetTag() const { + return this->header[0].Get(); + } + + constexpr ALWAYS_INLINE s32 GetPointerCount() const { + return this->header[0].Get(); + } + + constexpr ALWAYS_INLINE s32 GetSendCount() const { + return this->header[0].Get(); + } + + constexpr ALWAYS_INLINE s32 GetReceiveCount() const { + return this->header[0].Get(); + } + + constexpr ALWAYS_INLINE s32 GetExchangeCount() const { + return this->header[0].Get(); + } + + constexpr ALWAYS_INLINE s32 GetMapAliasCount() const { + return this->GetSendCount() + this->GetReceiveCount() + this->GetExchangeCount(); + } + + constexpr ALWAYS_INLINE s32 GetRawCount() const { + return this->header[1].Get(); + } + + constexpr ALWAYS_INLINE s32 GetReceiveListCount() const { + return this->header[1].Get(); + } + + constexpr ALWAYS_INLINE s32 GetReceiveListOffset() const { + return this->header[1].Get(); + } + + constexpr ALWAYS_INLINE bool GetHasSpecialHeader() const { + return this->header[1].Get(); + } + + constexpr ALWAYS_INLINE void SetReceiveListCount(s32 recv_list) { + this->header[1].Set(recv_list); + } + + constexpr ALWAYS_INLINE const util::BitPack32 *GetData() const { + return this->header; + } + + static constexpr ALWAYS_INLINE size_t GetDataSize() { + return sizeof(header); + } + }; + + class SpecialHeader { + private: + /* Define fields for the header word. */ + using HasProcessId = util::BitPack32::Field<0, 1, bool>; + using CopyHandleCount = util::BitPack32::Field; + using MoveHandleCount = util::BitPack32::Field; + private: + util::BitPack32 header; + bool has_header; + public: + constexpr ALWAYS_INLINE explicit SpecialHeader(bool pid, s32 copy, s32 move) : header(0), has_header(true) { + this->header.Set(pid); + this->header.Set(copy); + this->header.Set(move); + } + + ALWAYS_INLINE explicit SpecialHeader(const MessageBuffer &buf, const MessageHeader &hdr) : header(0), has_header(hdr.GetHasSpecialHeader()) { + if (this->has_header) { + buf.Get(MessageHeader::GetDataSize() / sizeof(util::BitPack32), std::addressof(this->header), sizeof(this->header) / sizeof(util::BitPack32)); + } + } + + constexpr ALWAYS_INLINE bool GetHasProcessId() const { + return this->header.Get(); + } + + constexpr ALWAYS_INLINE bool GetCopyHandleCount() const { + return this->header.Get(); + } + + constexpr ALWAYS_INLINE bool GetMoveHandleCount() const { + return this->header.Get(); + } + + constexpr ALWAYS_INLINE const util::BitPack32 *GetHeader() const { + return std::addressof(this->header); + } + + constexpr ALWAYS_INLINE size_t GetHeaderSize() const { + if (this->has_header) { + return sizeof(this->header); + } else { + return 0; + } + } + + constexpr ALWAYS_INLINE size_t GetDataSize() const { + if (this->has_header) { + return (this->GetHasProcessId() ? sizeof(u64) : 0) + + (this->GetCopyHandleCount() * sizeof(Handle)) + + (this->GetMoveHandleCount() * sizeof(Handle)); + } else { + return 0; + } + } + }; + + class MapAliasDescriptor { + public: + enum Attribute { + Attribute_Ipc = 0, + Attribute_NonSecureIpc = 1, + Attribute_NonDeviceIpc = 3, + }; + private: + /* Define fields for the first two words. */ + using SizeLow = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + using AddressLow = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + + /* Define fields for the packed descriptor word. */ + using Attributes = util::BitPack32::Field<0, 2, Attribute>; + using AddressHigh = util::BitPack32::Field; + using Reserved = util::BitPack32::Field; + using SizeHigh = util::BitPack32::Field; + using AddressMid = util::BitPack32::Field; + + constexpr ALWAYS_INLINE u32 GetAddressMid(u64 address) { + return static_cast(address >> AddressLow::Count) & ((1u << AddressMid::Count) - 1); + } + + constexpr ALWAYS_INLINE u32 GetAddressHigh(u64 address) { + return static_cast(address >> (AddressLow::Count + AddressMid::Count)); + } + private: + util::BitPack32 data[3]; + public: + constexpr ALWAYS_INLINE MapAliasDescriptor() : data({util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}) { /* ... */ } + + ALWAYS_INLINE MapAliasDescriptor(const void *buffer, size_t _size, Attribute attr = Attribute_Ipc) : data({util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}) { + const u64 address = reinterpret_cast(buffer); + const u64 size = static_cast(_size); + this->data[0] = { static_cast(size) }; + this->data[1] = { static_cast(address) }; + + this->data[2].Set(attr); + this->data[2].Set(GetAddressMid(address)); + this->data[2].Set(static_cast(size >> SizeLow::Count)); + this->data[2].Set(GetAddressHigh(address)); + } + + ALWAYS_INLINE MapAliasDescriptor(const MessageBuffer &buf, s32 index) : data({util::BitPack32(0), util::BitPack32(0), util::BitPack32(0)}) { + buf.Get(index, this->data, util::size(this->data)); + } + + constexpr ALWAYS_INLINE uintptr_t GetAddress() const { + const u64 address = (static_cast((this->data[2].Get() << AddressMid::Count) | this->data[2].Get()) << AddressLow::Count) | this->data[1].Get(); + return address; + } + + constexpr ALWAYS_INLINE uintptr_t GetSize() const { + const u64 size = (static_cast(this->data[2].Get()) << SizeLow::Count) | this->data[0].Get(); + return size; + } + + constexpr ALWAYS_INLINE Attribute GetAttribute() const { + return this->data[2].Get(); + } + + constexpr ALWAYS_INLINE const util::BitPack32 *GetData() const { + return this->data; + } + + static constexpr ALWAYS_INLINE size_t GetDataSize() { + return sizeof(data); + } + }; + + class PointerDescriptor { + private: + /* Define fields for the packed descriptor word. */ + using Index = util::BitPack32::Field<0, 4, s32>; + using Reserved0 = util::BitPack32::Field; + using AddressHigh = util::BitPack32::Field; + using Reserved1 = util::BitPack32::Field; + using AddressMid = util::BitPack32::Field; + using Size = util::BitPack32::Field; + + /* Define fields for the second word. */ + using AddressLow = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + + constexpr ALWAYS_INLINE u32 GetAddressMid(u64 address) { + return static_cast(address >> AddressLow::Count) & ((1u << AddressMid::Count) - 1); + } + + constexpr ALWAYS_INLINE u32 GetAddressHigh(u64 address) { + return static_cast(address >> (AddressLow::Count + AddressMid::Count)); + } + private: + util::BitPack32 data[2]; + public: + constexpr ALWAYS_INLINE PointerDescriptor() : data({util::BitPack32(0), util::BitPack32(0)}) { /* ... */ } + + ALWAYS_INLINE PointerDescriptor(const void *buffer, size_t size, s32 index) : data({util::BitPack32(0), util::BitPack32(0)}) { + const u64 address = reinterpret_cast(buffer); + + this->data[0].Set(index); + this->data[0].Set(GetAddressHigh(address)); + this->data[0].Set(GetAddressMid(address)); + this->data[0].Set(size); + + this->data[1] = { static_cast(address) }; + } + + ALWAYS_INLINE PointerDescriptor(const MessageBuffer &buf, s32 index) : data({util::BitPack32(0), util::BitPack32(0)}) { + buf.Get(index, this->data, util::size(this->data)); + } + + constexpr ALWAYS_INLINE s32 GetIndex() const { + return this->data[0].Get(); + } + + constexpr ALWAYS_INLINE uintptr_t GetAddress() const { + const u64 address = (static_cast((this->data[0].Get() << AddressMid::Count) | this->data[0].Get()) << AddressLow::Count) | this->data[1].Get(); + return address; + } + + constexpr ALWAYS_INLINE size_t GetSize() const { + return this->data[0].Get(); + } + + constexpr ALWAYS_INLINE const util::BitPack32 *GetData() const { + return this->data; + } + + static constexpr ALWAYS_INLINE size_t GetDataSize() { + return sizeof(data); + } + }; + + class ReceiveListEntry { + private: + /* Define fields for the first word. */ + using AddressLow = util::BitPack32::Field<0, BITSIZEOF(u32), u32>; + + /* Define fields for the packed descriptor word. */ + using AddressHigh = util::BitPack32::Field<0, 7, u32>; + using Reserved = util::BitPack32::Field; + using Size = util::BitPack32::Field; + + constexpr ALWAYS_INLINE u32 GetAddressHigh(u64 address) { + return static_cast(address >> (AddressLow::Count)); + } + private: + util::BitPack32 data[2]; + public: + constexpr ALWAYS_INLINE ReceiveListEntry() : data({util::BitPack32(0), util::BitPack32(0)}) { /* ... */ } + + ALWAYS_INLINE ReceiveListEntry(const void *buffer, size_t size) : data({util::BitPack32(0), util::BitPack32(0)}) { + const u64 address = reinterpret_cast(buffer); + + this->data[0] = { static_cast(address) }; + + this->data[1].Set(GetAddressHigh(address)); + this->data[1].Set(size); + } + + ALWAYS_INLINE ReceiveListEntry(u32 a, u32 b) : data({util::BitPack32(a), util::BitPack32(b)}) { /* ... */ } + + constexpr ALWAYS_INLINE uintptr_t GetAddress() { + const u64 address = (static_cast(this->data[1].Get()) << AddressLow::Count) | this->data[0].Get(); + return address; + } + + constexpr ALWAYS_INLINE size_t GetSize() const { + return this->data[1].Get(); + } + + constexpr ALWAYS_INLINE const util::BitPack32 *GetData() const { + return this->data; + } + + static constexpr ALWAYS_INLINE size_t GetDataSize() { + return sizeof(data); + } + }; + private: + u32 *buffer; + size_t size; + public: + constexpr MessageBuffer(u32 *b, size_t sz) : buffer(b), size(sz) { /* ... */ } + constexpr explicit MessageBuffer(u32 *b) : buffer(b), size(sizeof(::ams::svc::ThreadLocalRegion::message_buffer)) { /* ... */ } + + constexpr ALWAYS_INLINE size_t GetBufferSize() const { + return this->size; + } + + ALWAYS_INLINE void Get(s32 index, util::BitPack32 *dst, size_t count) const { + /* Ensure that this doesn't get re-ordered. */ + __asm__ __volatile__("" ::: "memory"); + + /* Get the words. */ + static_assert(sizeof(*dst) == sizeof(*this->buffer)); + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wclass-memaccess" + __builtin_memcpy(dst, this->buffer + index, count * sizeof(*dst)); +#pragma GCC diagnostic pop + } + + ALWAYS_INLINE s32 Set(s32 index, const util::BitPack32 *src, size_t count) const { + /* Ensure that this doesn't get re-ordered. */ + __asm__ __volatile__("" ::: "memory"); + + /* Set the words. */ + __builtin_memcpy(this->buffer + index, src, count * sizeof(*src)); + + /* Ensure that this doesn't get re-ordered. */ + __asm__ __volatile__("" ::: "memory"); + + return index + count; + } + + template + ALWAYS_INLINE const T &GetRaw(s32 index) const { + return *reinterpret_cast(this->buffer + index); + } + + template + ALWAYS_INLINE s32 SetRaw(s32 index, const T &val) { + *reinterpret_cast(this->buffer + index) = val; + return index + (util::AlignUp(sizeof(val), sizeof(*this->buffer)) / sizeof(*this->buffer)); + } + + ALWAYS_INLINE void GetRawArray(s32 index, void *dst, size_t len) { + __builtin_memcpy(dst, this->buffer + index, len); + } + + ALWAYS_INLINE void SetRawArray(s32 index, const void *src, size_t len) { + __builtin_memcpy(this->buffer + index, src, len); + } + + ALWAYS_INLINE void SetNull() const { + this->Set(MessageHeader()); + } + + ALWAYS_INLINE s32 Set(const MessageHeader &hdr) const { + __builtin_memcpy(this->buffer, hdr.GetData(), hdr.GetDataSize()); + return hdr.GetDataSize() / sizeof(*this->buffer); + } + + ALWAYS_INLINE s32 Set(const SpecialHeader &spc) const { + const s32 index = MessageHeader::GetDataSize() / sizeof(*this->buffer); + __builtin_memcpy(this->buffer + index, spc.GetHeader(), spc.GetHeaderSize()); + return index + (spc.GetHeaderSize() / sizeof(*this->buffer)); + } + + ALWAYS_INLINE s32 SetHandle(s32 index, const ::ams::svc::Handle &hnd) { + static_assert(util::IsAligned(sizeof(hnd), sizeof(*this->buffer))); + __builtin_memcpy(this->buffer + index, std::addressof(hnd), sizeof(hnd)); + return index + (sizeof(hnd) / sizeof(*this->buffer)); + } + + ALWAYS_INLINE s32 SetProcessId(s32 index, const u64 pid) { + static_assert(util::IsAligned(sizeof(pid), sizeof(*this->buffer))); + __builtin_memcpy(this->buffer + index, std::addressof(pid), sizeof(pid)); + return index + (sizeof(pid) / sizeof(*this->buffer)); + } + + ALWAYS_INLINE s32 Set(s32 index, const MapAliasDescriptor &desc) { + __builtin_memcpy(this->buffer + index, desc.GetData(), desc.GetDataSize()); + return index + (desc.GetDataSize() / sizeof(*this->buffer)); + } + + ALWAYS_INLINE s32 Set(s32 index, const PointerDescriptor &desc) { + __builtin_memcpy(this->buffer + index, desc.GetData(), desc.GetDataSize()); + return index + (desc.GetDataSize() / sizeof(*this->buffer)); + } + + ALWAYS_INLINE s32 Set(s32 index, const ReceiveListEntry &desc) { + __builtin_memcpy(this->buffer + index, desc.GetData(), desc.GetDataSize()); + return index + (desc.GetDataSize() / sizeof(*this->buffer)); + } + + ALWAYS_INLINE s32 Set(s32 index, const u32 val) { + static_assert(util::IsAligned(sizeof(val), sizeof(*this->buffer))); + __builtin_memcpy(this->buffer + index, std::addressof(val), sizeof(val)); + return index + (sizeof(val) / sizeof(*this->buffer)); + } + + ALWAYS_INLINE Result GetAsyncResult() const { + MessageHeader hdr(this->buffer); + MessageHeader null{}; + R_SUCCEED_IF(AMS_UNLIKELY((__builtin_memcmp(hdr.GetData(), null.GetData(), MessageHeader::GetDataSize()) != 0))); + return this->buffer[MessageHeader::GetDataSize() / sizeof(*this->buffer)]; + } + + ALWAYS_INLINE void SetAsyncResult(Result res) const { + const s32 index = this->Set(MessageHeader()); + const auto value = res.GetValue(); + static_assert(util::IsAligned(sizeof(value), sizeof(*this->buffer))); + __builtin_memcpy(this->buffer + index, std::addressof(value), sizeof(value)); + } + + ALWAYS_INLINE u64 GetProcessId(s32 index) const { + u64 pid; + __builtin_memcpy(std::addressof(pid), this->buffer + index, sizeof(pid)); + return pid; + } + + ALWAYS_INLINE ams::svc::Handle GetHandle(s32 index) const { + static_assert(sizeof(ams::svc::Handle) == sizeof(*this->buffer)); + return ::ams::svc::Handle(this->buffer[index]); + } + + static constexpr ALWAYS_INLINE s32 GetSpecialDataIndex(const MessageHeader &hdr, const SpecialHeader &spc) { + return (MessageHeader::GetDataSize() / sizeof(util::BitPack32)) + (spc.GetHeaderSize() / sizeof(util::BitPack32)); + } + + static constexpr ALWAYS_INLINE s32 GetPointerDescriptorIndex(const MessageHeader &hdr, const SpecialHeader &spc) { + return GetSpecialDataIndex(hdr, spc) + (spc.GetDataSize() / sizeof(util::BitPack32)); + } + + static constexpr ALWAYS_INLINE s32 GetMapAliasDescriptorIndex(const MessageHeader &hdr, const SpecialHeader &spc) { + return GetPointerDescriptorIndex(hdr, spc) + (hdr.GetPointerCount() * PointerDescriptor::GetDataSize() / sizeof(util::BitPack32)); + } + + static constexpr ALWAYS_INLINE s32 GetRawDataIndex(const MessageHeader &hdr, const SpecialHeader &spc) { + return GetMapAliasDescriptorIndex(hdr, spc) + (hdr.GetMapAliasCount() * MapAliasDescriptor::GetDataSize() / sizeof(util::BitPack32)); + } + + static constexpr ALWAYS_INLINE s32 GetReceiveListIndex(const MessageHeader &hdr, const SpecialHeader &spc) { + if (const s32 recv_list_index = hdr.GetReceiveListOffset()) { + return recv_list_index; + } else { + return GetRawDataIndex(hdr, spc) + hdr.GetRawCount(); + } + } + + static constexpr ALWAYS_INLINE s32 GetMessageBufferSize(const MessageHeader &hdr, const SpecialHeader &spc) { + /* Get the size of the plain message. */ + size_t msg_size = GetReceiveListIndex(hdr, spc) * sizeof(util::BitPack32); + + /* Add the size of the receive list. */ + const auto count = hdr.GetReceiveListCount(); + switch (count) { + case MessageHeader::ReceiveListCountType_None: + break; + case MessageHeader::ReceiveListCountType_ToMessageBuffer: + break; + case MessageHeader::ReceiveListCountType_ToSingleBuffer: + msg_size += ReceiveListEntry::GetDataSize(); + break; + default: + msg_size += (count - MessageHeader::ReceiveListCountType_CountOffset) * ReceiveListEntry::GetDataSize(); + break; + } + + return msg_size; + } + }; + +} diff --git a/libraries/libvapours/include/vapours/svc/svc_common.hpp b/libraries/libvapours/include/vapours/svc/svc_common.hpp index b20680377..3e3850a0b 100644 --- a/libraries/libvapours/include/vapours/svc/svc_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_common.hpp @@ -57,7 +57,7 @@ namespace ams::svc { return handle == PseudoHandle::CurrentProcess || handle == PseudoHandle::CurrentThread; } -#ifdef ATMOSPHERE_ARCH_ARM64 +#if defined(ATMOSPHERE_ARCH_ARM64) namespace lp64 { /* ... */ } @@ -74,7 +74,7 @@ namespace ams::svc { using namespace ::ams::svc::aarch64::ilp32; #endif -#elif defined ATMOSPHERE_ARCH_ARM +#elif defined(ATMOSPHERE_ARCH_ARM) namespace ilp32 { /* ... */ } namespace aarch32 { /* ... */ } diff --git a/libraries/libvapours/include/vapours/svc/svc_select_thread_local_region.hpp b/libraries/libvapours/include/vapours/svc/svc_select_thread_local_region.hpp new file mode 100644 index 000000000..3f3393661 --- /dev/null +++ b/libraries/libvapours/include/vapours/svc/svc_select_thread_local_region.hpp @@ -0,0 +1,39 @@ +/* + * 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_ARCH_ARM64) + + #include + namespace ams::svc { + using ams::svc::arch::arm64::ThreadLocalRegion; + using ams::svc::arch::arm64::GetThreadLocalRegion; + } + +#else + + #error "Unknown architecture for svc::ThreadLocalRegion" + +#endif + +namespace ams::svc { + + constexpr inline size_t ThreadLocalRegionSize = 0x200; + static_assert(sizeof(::ams::svc::ThreadLocalRegion) == ThreadLocalRegionSize); + +} \ No newline at end of file diff --git a/libraries/libvapours/include/vapours/svc/svc_types.hpp b/libraries/libvapours/include/vapours/svc/svc_types.hpp index 9b3397431..40f36cbfa 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types.hpp @@ -17,6 +17,7 @@ #include #include +#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 5ba4d3911..df74ea0f1 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -277,8 +277,6 @@ namespace ams::svc { ThreadActivity_Paused = 1, }; - constexpr size_t ThreadLocalRegionSize = 0x200; - constexpr s32 LowestThreadPriority = 63; constexpr s32 HighestThreadPriority = 0;