1
0
Fork 0
mirror of https://github.com/Atmosphere-NX/Atmosphere.git synced 2024-12-18 08:22:04 +00:00

kern: add SvcExitThread, SvcSendAsyncRequestWithUserBuffer, SvcReplyAndReceiveWithUserBuffer

This commit is contained in:
Michael Scire 2020-07-10 15:31:23 -07:00
parent 1b429918de
commit d52655eaf1
3 changed files with 114 additions and 8 deletions

View file

@ -441,8 +441,8 @@ namespace ams::kern {
Result KPageTableBase::LockMemoryAndOpen(KPageGroup *out_pg, KPhysicalAddress *out_paddr, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, KMemoryPermission new_perm, u32 lock_attr) { Result KPageTableBase::LockMemoryAndOpen(KPageGroup *out_pg, KPhysicalAddress *out_paddr, KProcessAddress addr, size_t size, u32 state_mask, u32 state, u32 perm_mask, u32 perm, u32 attr_mask, u32 attr, KMemoryPermission new_perm, u32 lock_attr) {
/* Validate basic preconditions. */ /* Validate basic preconditions. */
MESOSPHERE_ASSERT((attr_mask & lock_attr) == lock_attr); MESOSPHERE_ASSERT((lock_attr & attr) == 0);
MESOSPHERE_ASSERT((attr & lock_attr) == lock_attr); MESOSPHERE_ASSERT((lock_attr & (KMemoryAttribute_IpcLocked | KMemoryAttribute_DeviceShared)) == 0);
/* Validate the lock request. */ /* Validate the lock request. */
const size_t num_pages = size / PageSize; const size_t num_pages = size / PageSize;

View file

@ -153,10 +153,111 @@ namespace ams::kern::svc {
return page_table.UnlockForIpcUserBuffer(message, buffer_size); return page_table.UnlockForIpcUserBuffer(message, buffer_size);
} }
ALWAYS_INLINE Result SendAsyncRequestWithUserBufferImpl(ams::svc::Handle *out_event_handle, uintptr_t message, size_t buffer_size, ams::svc::Handle session_handle) {
/* Get the process and handle table. */
auto &process = GetCurrentProcess();
auto &handle_table = process.GetHandleTable();
/* Reserve a new event from the process resource limit. */
KScopedResourceReservation event_reservation(std::addressof(process), ams::svc::LimitableResource_EventCountMax);
R_UNLESS(event_reservation.Succeeded(), svc::ResultLimitReached());
/* Get the client session. */
KScopedAutoObject session = GetCurrentProcess().GetHandleTable().GetObject<KClientSession>(session_handle);
R_UNLESS(session.IsNotNull(), svc::ResultInvalidHandle());
/* Get the parent, and persist a reference to it until we're done. */
KScopedAutoObject parent = session->GetParent();
MESOSPHERE_ASSERT(parent.IsNotNull());
/* Create a new event. */
KEvent *event = KEvent::Create();
R_UNLESS(event != nullptr, svc::ResultOutOfResource());
/* Initialize the event. */
event->Initialize();
/* Commit our reservation. */
event_reservation.Commit();
/* At end of scope, kill the standing references to the sub events. */
ON_SCOPE_EXIT {
event->GetReadableEvent().Close();
event->GetWritableEvent().Close();
};
/* Register the event. */
R_TRY(KEvent::Register(event));
/* Add the readable event to the handle table. */
R_TRY(handle_table.Add(out_event_handle, std::addressof(event->GetReadableEvent())));
/* Ensure that if we fail to send the request, we close the readable handle. */
auto read_guard = SCOPE_GUARD { handle_table.Remove(*out_event_handle); };
/* Send the async request. */
R_TRY(session->SendAsyncRequest(std::addressof(event->GetWritableEvent()), message, buffer_size));
/* We succeeded. */
read_guard.Cancel();
return ResultSuccess();
}
ALWAYS_INLINE Result SendAsyncRequestWithUserBuffer(ams::svc::Handle *out_event_handle, uintptr_t message, size_t buffer_size, ams::svc::Handle session_handle) {
/* Validate that the message buffer is page aligned and does not overflow. */
R_UNLESS(util::IsAligned(message, PageSize), svc::ResultInvalidAddress());
R_UNLESS(buffer_size > 0, svc::ResultInvalidSize());
R_UNLESS(util::IsAligned(buffer_size, PageSize), svc::ResultInvalidSize());
R_UNLESS(message < message + buffer_size, svc::ResultInvalidCurrentMemory());
/* Get the process page table. */
auto &page_table = GetCurrentProcess().GetPageTable();
/* Lock the mesage buffer. */
R_TRY(page_table.LockForIpcUserBuffer(nullptr, message, buffer_size));
/* Ensure that if we fail, we unlock the message buffer. */
auto unlock_guard = SCOPE_GUARD { page_table.UnlockForIpcUserBuffer(message, buffer_size); };
/* Send the request. */
MESOSPHERE_ASSERT(message != 0);
R_TRY(SendAsyncRequestWithUserBufferImpl(out_event_handle, message, buffer_size, session_handle));
/* We sent the request successfully. */
unlock_guard.Cancel();
return ResultSuccess();
}
ALWAYS_INLINE Result ReplyAndReceive(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) { ALWAYS_INLINE Result ReplyAndReceive(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
return ReplyAndReceiveImpl(out_index, 0, 0, Null<KPhysicalAddress>, handles, num_handles, reply_target, timeout_ns); return ReplyAndReceiveImpl(out_index, 0, 0, Null<KPhysicalAddress>, handles, num_handles, reply_target, timeout_ns);
} }
ALWAYS_INLINE Result ReplyAndReceiveWithUserBuffer(int32_t *out_index, uintptr_t message, size_t buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
/* Validate that the message buffer is page aligned and does not overflow. */
R_UNLESS(util::IsAligned(message, PageSize), svc::ResultInvalidAddress());
R_UNLESS(buffer_size > 0, svc::ResultInvalidSize());
R_UNLESS(util::IsAligned(buffer_size, PageSize), svc::ResultInvalidSize());
R_UNLESS(message < message + buffer_size, svc::ResultInvalidCurrentMemory());
/* Get the process page table. */
auto &page_table = GetCurrentProcess().GetPageTable();
/* Lock the mesage buffer, getting its physical address. */
KPhysicalAddress message_paddr;
R_TRY(page_table.LockForIpcUserBuffer(std::addressof(message_paddr), message, buffer_size));
/* Ensure that even if we fail, we unlock the message buffer when done. */
auto unlock_guard = SCOPE_GUARD { page_table.UnlockForIpcUserBuffer(message, buffer_size); };
/* Send the request. */
MESOSPHERE_ASSERT(message != 0);
R_TRY(ReplyAndReceiveImpl(out_index, message, buffer_size, message_paddr, handles, num_handles, reply_target, timeout_ns));
/* We sent the request successfully, so cancel our guard and check the unlock result. */
unlock_guard.Cancel();
return page_table.UnlockForIpcUserBuffer(message, buffer_size);
}
} }
/* ============================= 64 ABI ============================= */ /* ============================= 64 ABI ============================= */
@ -170,7 +271,7 @@ namespace ams::kern::svc {
} }
Result SendAsyncRequestWithUserBuffer64(ams::svc::Handle *out_event_handle, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, ams::svc::Handle session_handle) { Result SendAsyncRequestWithUserBuffer64(ams::svc::Handle *out_event_handle, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, ams::svc::Handle session_handle) {
MESOSPHERE_PANIC("Stubbed SvcSendAsyncRequestWithUserBuffer64 was called."); return SendAsyncRequestWithUserBuffer(out_event_handle, message_buffer, message_buffer_size, session_handle);
} }
Result ReplyAndReceive64(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) { Result ReplyAndReceive64(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
@ -178,7 +279,7 @@ namespace ams::kern::svc {
} }
Result ReplyAndReceiveWithUserBuffer64(int32_t *out_index, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) { Result ReplyAndReceiveWithUserBuffer64(int32_t *out_index, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
MESOSPHERE_PANIC("Stubbed SvcReplyAndReceiveWithUserBuffer64 was called."); return ReplyAndReceiveWithUserBuffer(out_index, message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
} }
/* ============================= 64From32 ABI ============================= */ /* ============================= 64From32 ABI ============================= */
@ -192,7 +293,7 @@ namespace ams::kern::svc {
} }
Result SendAsyncRequestWithUserBuffer64From32(ams::svc::Handle *out_event_handle, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, ams::svc::Handle session_handle) { Result SendAsyncRequestWithUserBuffer64From32(ams::svc::Handle *out_event_handle, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, ams::svc::Handle session_handle) {
MESOSPHERE_PANIC("Stubbed SvcSendAsyncRequestWithUserBuffer64From32 was called."); return SendAsyncRequestWithUserBuffer(out_event_handle, message_buffer, message_buffer_size, session_handle);
} }
Result ReplyAndReceive64From32(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) { Result ReplyAndReceive64From32(int32_t *out_index, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
@ -200,7 +301,7 @@ namespace ams::kern::svc {
} }
Result ReplyAndReceiveWithUserBuffer64From32(int32_t *out_index, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) { Result ReplyAndReceiveWithUserBuffer64From32(int32_t *out_index, ams::svc::Address message_buffer, ams::svc::Size message_buffer_size, KUserPointer<const ams::svc::Handle *> handles, int32_t num_handles, ams::svc::Handle reply_target, int64_t timeout_ns) {
MESOSPHERE_PANIC("Stubbed SvcReplyAndReceiveWithUserBuffer64From32 was called."); return ReplyAndReceiveWithUserBuffer(out_index, message_buffer, message_buffer_size, handles, num_handles, reply_target, timeout_ns);
} }
} }

View file

@ -81,6 +81,11 @@ namespace ams::kern::svc {
return ResultSuccess(); return ResultSuccess();
} }
void ExitThread() {
GetCurrentThread().Exit();
MESOSPHERE_PANIC("Process survived call to exit");
}
Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) { Result GetThreadPriority(int32_t *out_priority, ams::svc::Handle thread_handle) {
/* Get the thread from its handle. */ /* Get the thread from its handle. */
KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle); KScopedAutoObject thread = GetCurrentProcess().GetHandleTable().GetObject<KThread>(thread_handle);
@ -114,7 +119,7 @@ namespace ams::kern::svc {
} }
void ExitThread64() { void ExitThread64() {
MESOSPHERE_PANIC("Stubbed SvcExitThread64 was called."); return ExitThread();
} }
void SleepThread64(int64_t ns) { void SleepThread64(int64_t ns) {
@ -168,7 +173,7 @@ namespace ams::kern::svc {
} }
void ExitThread64From32() { void ExitThread64From32() {
MESOSPHERE_PANIC("Stubbed SvcExitThread64From32 was called."); return ExitThread();
} }
void SleepThread64From32(int64_t ns) { void SleepThread64From32(int64_t ns) {