sm: reimplement using tipc instead of cmif (probably broken, untested)

This commit is contained in:
Michael Scire 2021-04-10 01:58:26 -07:00
parent 728bda9677
commit 2542f282e0
14 changed files with 83 additions and 155 deletions

View File

@ -21,7 +21,7 @@ PRECOMPILED_HEADERS := $(CURRENT_DIRECTORY)/include/stratosphere.hpp
#PRECOMPILED_HEADERS :=
DEFINES := $(ATMOSPHERE_DEFINES) -DATMOSPHERE_IS_STRATOSPHERE -D_GNU_SOURCE
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2
SETTINGS := $(ATMOSPHERE_SETTINGS) -O2 -flto
CFLAGS := $(ATMOSPHERE_CFLAGS) $(SETTINGS) $(DEFINES) $(INCLUDE)
CXXFLAGS := $(CFLAGS) $(ATMOSPHERE_CXXFLAGS)
ASFLAGS := $(ATMOSPHERE_ASFLAGS) $(SETTINGS)

View File

@ -25,4 +25,3 @@
#include <stratosphere/sm/impl/sm_user_interface.hpp>
#include <stratosphere/sm/impl/sm_manager_interface.hpp>
#include <stratosphere/sm/impl/sm_debug_monitor_interface.hpp>

View File

@ -1,27 +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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours.hpp>
#include <stratosphere/sm/sm_types.hpp>
#include <stratosphere/sf.hpp>
#define AMS_SM_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereGetRecord, (sf::Out<sm::ServiceRecord> record, sm::ServiceName service), (record, service)) \
AMS_SF_METHOD_INFO(C, H, 65001, void, AtmosphereListRecords, (const sf::OutArray<sm::ServiceRecord> &records, sf::Out<u64> out_count, u64 offset), (records, out_count, offset)) \
AMS_SF_METHOD_INFO(C, H, 65002, void, AtmosphereGetRecordSize, (sf::Out<u64> record_size), (record_size))
AMS_SF_DEFINE_INTERFACE(ams::sm::impl, IDebugMonitorInterface, AMS_SM_I_DEBUG_MONITOR_INTERFACE_INTERFACE_INFO)

View File

@ -17,13 +17,13 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/sm/sm_types.hpp>
#include <stratosphere/sf.hpp>
#include <stratosphere/tipc.hpp>
#define AMS_SM_I_MANAGER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, RegisterProcess, (os::ProcessId process_id, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac), (process_id, acid_sac, aci_sac)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, UnregisterProcess, (os::ProcessId process_id), (process_id)) \
AMS_SF_METHOD_INFO(C, H, 65000, void, AtmosphereEndInitDefers, (), ()) \
AMS_SF_METHOD_INFO(C, H, 65001, void, AtmosphereHasMitm, (sf::Out<bool> out, sm::ServiceName service), (out, service)) \
AMS_SF_METHOD_INFO(C, H, 65002, Result, AtmosphereRegisterProcess, (os::ProcessId process_id, ncm::ProgramId program_id, cfg::OverrideStatus override_status, const sf::InBuffer &acid_sac, const sf::InBuffer &aci_sac), (process_id, program_id, override_status, acid_sac, aci_sac))
#define AMS_SM_I_MANAGER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, RegisterProcess, (os::ProcessId process_id, const tipc::InBuffer acid_sac, const tipc::InBuffer aci_sac), (process_id, acid_sac, aci_sac)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, UnregisterProcess, (os::ProcessId process_id), (process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 65000, void, AtmosphereEndInitDefers, (), ()) \
AMS_TIPC_METHOD_INFO(C, H, 65001, void, AtmosphereHasMitm, (tipc::Out<bool> out, sm::ServiceName service), (out, service)) \
AMS_TIPC_METHOD_INFO(C, H, 65002, Result, AtmosphereRegisterProcess, (os::ProcessId process_id, ncm::ProgramId program_id, cfg::OverrideStatus override_status, const tipc::InBuffer acid_sac, const tipc::InBuffer aci_sac), (process_id, program_id, override_status, acid_sac, aci_sac))
AMS_SF_DEFINE_INTERFACE(ams::sm::impl, IManagerInterface, AMS_SM_I_MANAGER_INTERFACE_INTERFACE_INFO)
AMS_TIPC_DEFINE_INTERFACE(ams::sm::impl, IManagerInterface, AMS_SM_I_MANAGER_INTERFACE_INTERFACE_INFO)

View File

@ -17,22 +17,22 @@
#pragma once
#include <vapours.hpp>
#include <stratosphere/sm/sm_types.hpp>
#include <stratosphere/sf.hpp>
#include <stratosphere/tipc.hpp>
#define AMS_SM_I_USER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_SF_METHOD_INFO(C, H, 0, Result, RegisterClient, (const sf::ClientProcessId &client_process_id), (client_process_id)) \
AMS_SF_METHOD_INFO(C, H, 1, Result, GetServiceHandle, (sf::OutMoveHandle out_h, sm::ServiceName service), (out_h, service)) \
AMS_SF_METHOD_INFO(C, H, 2, Result, RegisterService, (sf::OutMoveHandle out_h, sm::ServiceName service, u32 max_sessions, bool is_light), (out_h, service, max_sessions, is_light)) \
AMS_SF_METHOD_INFO(C, H, 3, Result, UnregisterService, (sm::ServiceName service), (service)) \
AMS_SF_METHOD_INFO(C, H, 4, Result, DetachClient, (const sf::ClientProcessId &client_process_id), (client_process_id)) \
AMS_SF_METHOD_INFO(C, H, 65000, Result, AtmosphereInstallMitm, (sf::OutMoveHandle srv_h, sf::OutMoveHandle qry_h, sm::ServiceName service), (srv_h, qry_h, service)) \
AMS_SF_METHOD_INFO(C, H, 65001, Result, AtmosphereUninstallMitm, (sm::ServiceName service), (service)) \
AMS_SF_METHOD_INFO(C, H, 65003, Result, AtmosphereAcknowledgeMitmSession, (sf::Out<sm::MitmProcessInfo> client_info, sf::OutMoveHandle fwd_h, sm::ServiceName service), (client_info, fwd_h, service)) \
AMS_SF_METHOD_INFO(C, H, 65004, Result, AtmosphereHasMitm, (sf::Out<bool> out, sm::ServiceName service), (out, service)) \
AMS_SF_METHOD_INFO(C, H, 65005, Result, AtmosphereWaitMitm, (sm::ServiceName service), (service)) \
AMS_SF_METHOD_INFO(C, H, 65006, Result, AtmosphereDeclareFutureMitm, (sm::ServiceName service), (service)) \
AMS_SF_METHOD_INFO(C, H, 65007, Result, AtmosphereClearFutureMitm, (sm::ServiceName service), (service)) \
AMS_SF_METHOD_INFO(C, H, 65100, Result, AtmosphereHasService, (sf::Out<bool> out, sm::ServiceName service), (out, service)) \
AMS_SF_METHOD_INFO(C, H, 65101, Result, AtmosphereWaitService, (sm::ServiceName service), (service))
#define AMS_SM_I_USER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, RegisterClient, (const tipc::ClientProcessId client_process_id), (client_process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, GetServiceHandle, (tipc::OutMoveHandle out_h, sm::ServiceName service), (out_h, service)) \
AMS_TIPC_METHOD_INFO(C, H, 2, Result, RegisterService, (tipc::OutMoveHandle out_h, sm::ServiceName service, u32 max_sessions, bool is_light), (out_h, service, max_sessions, is_light)) \
AMS_TIPC_METHOD_INFO(C, H, 3, Result, UnregisterService, (sm::ServiceName service), (service)) \
AMS_TIPC_METHOD_INFO(C, H, 4, Result, DetachClient, (const tipc::ClientProcessId client_process_id), (client_process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 65000, Result, AtmosphereInstallMitm, (tipc::OutMoveHandle srv_h, tipc::OutMoveHandle qry_h, sm::ServiceName service), (srv_h, qry_h, service)) \
AMS_TIPC_METHOD_INFO(C, H, 65001, Result, AtmosphereUninstallMitm, (sm::ServiceName service), (service)) \
AMS_TIPC_METHOD_INFO(C, H, 65003, Result, AtmosphereAcknowledgeMitmSession, (tipc::Out<sm::MitmProcessInfo> client_info, tipc::OutMoveHandle fwd_h, sm::ServiceName service), (client_info, fwd_h, service)) \
AMS_TIPC_METHOD_INFO(C, H, 65004, Result, AtmosphereHasMitm, (tipc::Out<bool> out, sm::ServiceName service), (out, service)) \
AMS_TIPC_METHOD_INFO(C, H, 65005, Result, AtmosphereWaitMitm, (sm::ServiceName service), (service)) \
AMS_TIPC_METHOD_INFO(C, H, 65006, Result, AtmosphereDeclareFutureMitm, (sm::ServiceName service), (service)) \
AMS_TIPC_METHOD_INFO(C, H, 65007, Result, AtmosphereClearFutureMitm, (sm::ServiceName service), (service)) \
AMS_TIPC_METHOD_INFO(C, H, 65100, Result, AtmosphereHasService, (tipc::Out<bool> out, sm::ServiceName service), (out, service)) \
AMS_TIPC_METHOD_INFO(C, H, 65101, Result, AtmosphereWaitService, (sm::ServiceName service), (service))
AMS_SF_DEFINE_INTERFACE(ams::sm::impl, IUserInterface, AMS_SM_I_USER_INTERFACE_INTERFACE_INFO)
AMS_TIPC_DEFINE_INTERFACE(ams::sm::impl, IUserInterface, AMS_SM_I_USER_INTERFACE_INTERFACE_INFO)

View File

@ -55,18 +55,6 @@ namespace ams::sm {
return !(lhs == rhs);
}
/* For Debug Monitor extensions. */
struct ServiceRecord {
ServiceName service;
os::ProcessId owner_process_id;
u64 max_sessions;
os::ProcessId mitm_process_id;
os::ProcessId mitm_waiting_ack_process_id;
bool is_light;
bool mitm_waiting_ack;
};
static_assert(sizeof(ServiceRecord) == 0x30, "ServiceRecord definition!");
/* For Mitm extensions. */
struct MitmProcessInfo {
os::ProcessId process_id;

View File

@ -280,7 +280,7 @@ namespace ams::tipc::impl {
static constexpr size_t OutDataSize = util::AlignUp(OutDataOffsets[NumOutDatas], alignof(u32));
/* Useful because reasons. */
static constexpr size_t OutDataAlign = [] {
static constexpr size_t OutDataAlign = []() -> size_t {
if constexpr (std::tuple_size<OutDatas>::value) {
return alignof(typename std::tuple_element<0, OutDatas>::type);
}

View File

@ -132,6 +132,8 @@ namespace ams::tipc {
public:
constexpr ALWAYS_INLINE InArrayImpl() : BaseType() { /* ... */ }
constexpr ALWAYS_INLINE InArrayImpl(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
constexpr ALWAYS_INLINE InArrayImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE InArrayImpl(const T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
constexpr ALWAYS_INLINE const T *GetPointer() const {
@ -163,6 +165,8 @@ namespace ams::tipc {
public:
constexpr ALWAYS_INLINE OutArrayImpl() : BaseType() { /* ... */ }
constexpr ALWAYS_INLINE OutArrayImpl(const tipc::PointerAndSize &_pas) : BaseType(_pas) { /* ... */ }
constexpr ALWAYS_INLINE OutArrayImpl(uintptr_t ptr, size_t sz) : BaseType(ptr, sz) { /* ... */ }
constexpr ALWAYS_INLINE OutArrayImpl(T *ptr, size_t num_elements) : BaseType(reinterpret_cast<uintptr_t>(ptr), num_elements * sizeof(T)) { /* ... */ }
constexpr ALWAYS_INLINE T *GetPointer() const {

View File

@ -57,7 +57,7 @@ namespace ams::tipc {
public:
constexpr ObjectManagerBase() = default;
void Initialize(os::WaitableManagerType *manager, Entry *entries, size_t max_objects) {
void InitializeImpl(os::WaitableManagerType *manager, Entry *entries, size_t max_objects) {
/* Set our waitable manager. */
m_waitable_manager = manager;
@ -179,7 +179,7 @@ namespace ams::tipc {
constexpr ObjectManager() = default;
void Initialize(os::WaitableManagerType *manager) {
this->Initialize(manager, m_entries_storage, MaxObjects);
this->InitializeImpl(manager, m_entries_storage, MaxObjects);
}
};

View File

@ -237,13 +237,15 @@ namespace ams::tipc {
--m_num_sessions;
}
void StartRegisterRetry(ResumeKey key) {
Result StartRegisterRetry(ResumeKey key) {
if constexpr (IsDeferralSupported) {
/* Acquire exclusive server manager access. */
std::scoped_lock lk(m_server_manager->GetMutex());
/* Begin the retry. */
m_deferral_manager.StartRegisterRetry(key);
return m_deferral_manager.StartRegisterRetry(key);
} else {
return ResultSuccess();
}
}
@ -329,7 +331,7 @@ namespace ams::tipc {
this->InitializeBase(id, sm, std::addressof(m_object_manager_impl));
/* Initialize our object manager. */
m_object_manager_impl->Initialize(std::addressof(this->m_waitable_manager));
m_object_manager_impl.Initialize(std::addressof(this->m_waitable_manager));
}
};
@ -430,6 +432,16 @@ namespace ams::tipc {
AMS_ABORT_UNLESS(allocated != nullptr);
return allocated;
}
void TriggerResume(ResumeKey resume_key) {
/* Acquire exclusive access to ourselves. */
std::scoped_lock lk(m_mutex);
/* Check/trigger resume on each of our ports. */
[this, resume_key]<size_t... Ix>(std::index_sequence<Ix...>) ALWAYS_INLINE_LAMBDA {
(this->TriggerResumeImpl<Ix>(resume_key), ...);
}(std::make_index_sequence<NumPorts>());
}
private:
template<size_t Ix> requires (Ix < NumPorts)
void TryAllocateObject(size_t port_index, tipc::ServiceObjectBase *&allocated) {
@ -570,6 +582,17 @@ namespace ams::tipc {
}
}
}
template<size_t Ix>
void TriggerResumeImpl(ResumeKey resume_key) {
/* Get the port manager. */
auto &port_manager = this->GetPortManager<Ix>();
/* If we should, trigger a resume. */
if (port_manager.TestResume(resume_key)) {
port_manager.TriggerResume(resume_key);
}
}
};
template<typename DeferralManagerType, typename... PortInfos>

View File

@ -1,81 +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 <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#define AMS_TEST_I_USER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, RegisterClient, (const tipc::ClientProcessId &client_process_id), (client_process_id)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, GetServiceHandle, (tipc::OutMoveHandle out_h, sm::ServiceName service), (out_h, service)) \
AMS_TIPC_METHOD_INFO(C, H, 2, Result, RegisterService, (tipc::OutMoveHandle out_h, sm::ServiceName service, u32 max_sessions, bool is_light), (out_h, service, max_sessions, is_light)) \
AMS_TIPC_METHOD_INFO(C, H, 3, Result, UnregisterService, (sm::ServiceName service), (service))
AMS_TIPC_DEFINE_INTERFACE(ams::_test::impl, IUserInterface, AMS_TEST_I_USER_INTERFACE_INTERFACE_INFO)
#define AMS_TEST_I_MANAGER_INTERFACE_INTERFACE_INFO(C, H) \
AMS_TIPC_METHOD_INFO(C, H, 0, Result, RegisterProcess, (os::ProcessId process_id, const tipc::InBuffer acid_sac, const tipc::InBuffer aci_sac), (process_id, acid_sac, aci_sac)) \
AMS_TIPC_METHOD_INFO(C, H, 1, Result, UnregisterProcess, (os::ProcessId process_id), (process_id))
AMS_TIPC_DEFINE_INTERFACE(ams::_test::impl, IManagerInterface, AMS_TEST_I_MANAGER_INTERFACE_INTERFACE_INFO)
namespace ams::_test {
class UserInterfaceFacade {
public:
Result RegisterClient(const tipc::ClientProcessId &process_id);
Result GetServiceHandle(tipc::OutMoveHandle out_h, sm::ServiceName service);
Result RegisterService(tipc::OutMoveHandle out_h, sm::ServiceName service, u32 max_sessions, bool is_light);
Result UnregisterService(sm::ServiceName service);
Result ProcessDefaultServiceCommand(const svc::ipc::MessageBuffer &message_buffer);
};
static_assert(impl::IsIUserInterface<UserInterfaceFacade>);
class ManagerInterfaceFacade {
public:
Result RegisterProcess(os::ProcessId process_id, const tipc::InBuffer acid_sac, const tipc::InBuffer aci_sac);
Result UnregisterProcess(os::ProcessId process_id);
};
static_assert(impl::IsIManagerInterface<ManagerInterfaceFacade>);
using UserInterfaceObject = ::ams::tipc::ServiceObject<impl::IUserInterface, UserInterfaceFacade>;
using ManagerInterfaceObject = ::ams::tipc::ServiceObject<impl::IManagerInterface, ManagerInterfaceFacade>;
Result TestAutomaticDispatch(UserInterfaceObject *object) {
return object->ProcessRequest();
}
Result TestManagerDispatch(ManagerInterfaceObject *object) {
return object->ProcessRequest();
}
using UserPortMeta = tipc::PortMeta<69, impl::IUserInterface, UserInterfaceFacade, tipc::SlabAllocator>;
using ManagerPortMeta = tipc::PortMeta< 1, impl::IManagerInterface, ManagerInterfaceFacade, tipc::SingletonAllocator>;
using TestServerManager = tipc::ServerManager<ManagerPortMeta, UserPortMeta>;
namespace {
TestServerManager g_test_server_manager;
}
void TestLoop() {
g_test_server_manager.LoopAuto();
}
}

View File

@ -14,8 +14,9 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stratosphere.hpp>
#include "impl/os_waitable_object_list.hpp"
#include "impl/os_timeout_helper.hpp"
#include "impl/os_waitable_object_list.hpp"
#include "impl/os_waitable_holder_impl.hpp"
namespace ams::os {
@ -399,4 +400,20 @@ namespace ams::os {
return true;
}
void InitializeWaitableHolder(WaitableHolderType *waitable_holder, MessageQueueType *mq, MessageQueueWaitType type) {
AMS_ASSERT(mq->state == MessageQueueType::State_Initialized);
switch (type) {
case MessageQueueWaitType::ForNotFull:
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_mq_for_not_full_storage, mq);
break;
case MessageQueueWaitType::ForNotEmpty:
util::ConstructAt(GetReference(waitable_holder->impl_storage).holder_of_mq_for_not_empty_storage, mq);
break;
AMS_UNREACHABLE_DEFAULT_CASE();
}
waitable_holder->user_data = 0;
}
}

View File

@ -19,7 +19,8 @@
namespace ams::settings::impl {
Result GetProductModel(s32 *out) {
return ::setsysGetProductModel(out);
static_assert(sizeof(*out) == sizeof(::SetSysProductModel));
return ::setsysGetProductModel(reinterpret_cast<::SetSysProductModel *>(out));
}
}

View File

@ -386,6 +386,10 @@ namespace ams::svc::ipc {
constexpr ALWAYS_INLINE MessageBuffer(u32 *b, size_t sz) : buffer(b), size(sz) { /* ... */ }
constexpr explicit ALWAYS_INLINE MessageBuffer(u32 *b) : buffer(b), size(sizeof(::ams::svc::ThreadLocalRegion::message_buffer)) { /* ... */ }
constexpr ALWAYS_INLINE void *GetBufferForDebug() const {
return this->buffer;
}
constexpr ALWAYS_INLINE size_t GetBufferSize() const {
return this->size;
}