mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 06:46:40 +08:00 
			
		
		
		
	Merge pull request #9183 from liamwhite/svc-refresh
kernel/svc_types: refresh
This commit is contained in:
		
						commit
						ea41c53ab1
					
				| @ -149,7 +149,7 @@ public: | ||||
|             context->AddDomainObject(std::move(iface)); | ||||
|         } else { | ||||
|             kernel.CurrentProcess()->GetResourceLimit()->Reserve( | ||||
|                 Kernel::LimitableResource::Sessions, 1); | ||||
|                 Kernel::LimitableResource::SessionCountMax, 1); | ||||
| 
 | ||||
|             auto* session = Kernel::KSession::Create(kernel); | ||||
|             session->Initialize(nullptr, iface->GetServiceName()); | ||||
|  | ||||
| @ -265,7 +265,8 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) { | ||||
|     const size_t slab_size = num_pages * PageSize; | ||||
| 
 | ||||
|     // Reserve memory from the system resource limit.
 | ||||
|     ASSERT(kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemory, slab_size)); | ||||
|     ASSERT( | ||||
|         kernel.GetSystemResourceLimit()->Reserve(LimitableResource::PhysicalMemoryMax, slab_size)); | ||||
| 
 | ||||
|     // Allocate memory for the slab.
 | ||||
|     constexpr auto AllocateOption = KMemoryManager::EncodeOption( | ||||
|  | ||||
| @ -61,7 +61,7 @@ bool KClientPort::IsSignaled() const { | ||||
| Result KClientPort::CreateSession(KClientSession** out) { | ||||
|     // Reserve a new session from the resource limit.
 | ||||
|     KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), | ||||
|                                                    LimitableResource::Sessions); | ||||
|                                                    LimitableResource::SessionCountMax); | ||||
|     R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|     // Update the session counts.
 | ||||
|  | ||||
| @ -50,7 +50,7 @@ Result KEvent::Clear() { | ||||
| void KEvent::PostDestroy(uintptr_t arg) { | ||||
|     // Release the event count resource the owner process holds.
 | ||||
|     KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||||
|     owner->GetResourceLimit()->Release(LimitableResource::Events, 1); | ||||
|     owner->GetResourceLimit()->Release(LimitableResource::EventCountMax, 1); | ||||
|     owner->Close(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -216,13 +216,15 @@ struct KMemoryInfo { | ||||
| 
 | ||||
|     constexpr Svc::MemoryInfo GetSvcMemoryInfo() const { | ||||
|         return { | ||||
|             .addr = m_address, | ||||
|             .base_address = m_address, | ||||
|             .size = m_size, | ||||
|             .state = static_cast<Svc::MemoryState>(m_state & KMemoryState::Mask), | ||||
|             .attr = static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask), | ||||
|             .perm = static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask), | ||||
|             .ipc_refcount = m_ipc_lock_count, | ||||
|             .device_refcount = m_device_use_count, | ||||
|             .attribute = | ||||
|                 static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask), | ||||
|             .permission = | ||||
|                 static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask), | ||||
|             .ipc_count = m_ipc_lock_count, | ||||
|             .device_count = m_device_use_count, | ||||
|             .padding = {}, | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @ -920,8 +920,8 @@ Result KPageTable::SetupForIpcServer(VAddr* out_addr, size_t size, VAddr src_add | ||||
| 
 | ||||
|     // Reserve space for any partial pages we allocate.
 | ||||
|     const size_t unmapped_size = aligned_src_size - mapping_src_size; | ||||
|     KScopedResourceReservation memory_reservation(m_resource_limit, | ||||
|                                                   LimitableResource::PhysicalMemory, unmapped_size); | ||||
|     KScopedResourceReservation memory_reservation( | ||||
|         m_resource_limit, LimitableResource::PhysicalMemoryMax, unmapped_size); | ||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|     // Ensure that we manage page references correctly.
 | ||||
| @ -1227,7 +1227,7 @@ Result KPageTable::CleanupForIpcServer(VAddr address, size_t size, KMemoryState | ||||
|     const VAddr mapping_start = Common::AlignUp((address), PageSize); | ||||
|     const VAddr mapping_end = Common::AlignDown((address) + size, PageSize); | ||||
|     const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; | ||||
|     m_resource_limit->Release(LimitableResource::PhysicalMemory, aligned_size - mapping_size); | ||||
|     m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, aligned_size - mapping_size); | ||||
| 
 | ||||
|     R_SUCCEED(); | ||||
| } | ||||
| @ -1568,7 +1568,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { | ||||
|         { | ||||
|             // Reserve the memory from the process resource limit.
 | ||||
|             KScopedResourceReservation memory_reservation( | ||||
|                 m_resource_limit, LimitableResource::PhysicalMemory, size - mapped_size); | ||||
|                 m_resource_limit, LimitableResource::PhysicalMemoryMax, size - mapped_size); | ||||
|             R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|             // Allocate pages for the new memory.
 | ||||
| @ -1908,7 +1908,7 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) { | ||||
| 
 | ||||
|     // Release the memory resource.
 | ||||
|     m_mapped_physical_memory_size -= mapped_size; | ||||
|     m_resource_limit->Release(LimitableResource::PhysicalMemory, mapped_size); | ||||
|     m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, mapped_size); | ||||
| 
 | ||||
|     // Update memory blocks.
 | ||||
|     m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, | ||||
| @ -2492,7 +2492,7 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) { | ||||
|                           OperationType::Unmap)); | ||||
| 
 | ||||
|             // Release the memory from the resource limit.
 | ||||
|             m_resource_limit->Release(LimitableResource::PhysicalMemory, num_pages * PageSize); | ||||
|             m_resource_limit->Release(LimitableResource::PhysicalMemoryMax, num_pages * PageSize); | ||||
| 
 | ||||
|             // Apply the memory block update.
 | ||||
|             m_memory_block_manager.Update(std::addressof(allocator), m_heap_region_start + size, | ||||
| @ -2522,7 +2522,7 @@ Result KPageTable::SetHeapSize(VAddr* out, size_t size) { | ||||
| 
 | ||||
|     // Reserve memory for the heap extension.
 | ||||
|     KScopedResourceReservation memory_reservation( | ||||
|         m_resource_limit, LimitableResource::PhysicalMemory, allocation_size); | ||||
|         m_resource_limit, LimitableResource::PhysicalMemoryMax, allocation_size); | ||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|     // Allocate pages for the heap extension.
 | ||||
|  | ||||
| @ -38,7 +38,7 @@ namespace { | ||||
|  */ | ||||
| void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { | ||||
|     const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); | ||||
|     ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::Threads, 1)); | ||||
|     ASSERT(owner_process.GetResourceLimit()->Reserve(LimitableResource::ThreadCountMax, 1)); | ||||
| 
 | ||||
|     KThread* thread = KThread::Create(system.Kernel()); | ||||
|     SCOPE_EXIT({ thread->Close(); }); | ||||
| @ -124,7 +124,7 @@ void KProcess::DecrementRunningThreadCount() { | ||||
| } | ||||
| 
 | ||||
| u64 KProcess::GetTotalPhysicalMemoryAvailable() { | ||||
|     const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + | ||||
|     const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemoryMax) + | ||||
|                        page_table.GetNormalMemorySize() + GetSystemResourceSize() + image_size + | ||||
|                        main_thread_stack_size}; | ||||
|     if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); | ||||
| @ -349,8 +349,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | ||||
|     // We currently do not support process-specific system resource
 | ||||
|     UNIMPLEMENTED_IF(system_resource_size != 0); | ||||
| 
 | ||||
|     KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, | ||||
|                                                   code_size + system_resource_size); | ||||
|     KScopedResourceReservation memory_reservation( | ||||
|         resource_limit, LimitableResource::PhysicalMemoryMax, code_size + system_resource_size); | ||||
|     if (!memory_reservation.Succeeded()) { | ||||
|         LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", | ||||
|                   code_size + system_resource_size); | ||||
| @ -406,8 +406,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std: | ||||
| 
 | ||||
| void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | ||||
|     AllocateMainThreadStack(stack_size); | ||||
|     resource_limit->Reserve(LimitableResource::Threads, 1); | ||||
|     resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); | ||||
|     resource_limit->Reserve(LimitableResource::ThreadCountMax, 1); | ||||
|     resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, main_thread_stack_size); | ||||
| 
 | ||||
|     const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; | ||||
|     ASSERT(!page_table.SetMaxHeapSize(heap_capacity).IsError()); | ||||
| @ -442,7 +442,7 @@ void KProcess::PrepareForTermination() { | ||||
|     plr_address = 0; | ||||
| 
 | ||||
|     if (resource_limit) { | ||||
|         resource_limit->Release(LimitableResource::PhysicalMemory, | ||||
|         resource_limit->Release(LimitableResource::PhysicalMemoryMax, | ||||
|                                 main_thread_stack_size + image_size); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -159,12 +159,13 @@ KResourceLimit* CreateResourceLimitForProcess(Core::System& system, s64 physical | ||||
|     // TODO(bunnei): These values are the system defaults, the limits for service processes are
 | ||||
|     // lower. These should use the correct limit values.
 | ||||
| 
 | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, physical_memory_size) | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, physical_memory_size) | ||||
|                .IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200).IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800).IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900).IsSuccess()); | ||||
|     ASSERT( | ||||
|         resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200).IsSuccess()); | ||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133).IsSuccess()); | ||||
| 
 | ||||
|     return resource_limit; | ||||
| } | ||||
|  | ||||
| @ -16,15 +16,8 @@ class CoreTiming; | ||||
| 
 | ||||
| namespace Kernel { | ||||
| class KernelCore; | ||||
| enum class LimitableResource : u32 { | ||||
|     PhysicalMemory = 0, | ||||
|     Threads = 1, | ||||
|     Events = 2, | ||||
|     TransferMemory = 3, | ||||
|     Sessions = 4, | ||||
| 
 | ||||
|     Count, | ||||
| }; | ||||
| using LimitableResource = Svc::LimitableResource; | ||||
| 
 | ||||
| constexpr bool IsValidResourceType(LimitableResource type) { | ||||
|     return type < LimitableResource::Count; | ||||
|  | ||||
| @ -76,7 +76,7 @@ void KSession::OnClientClosed() { | ||||
| void KSession::PostDestroy(uintptr_t arg) { | ||||
|     // Release the session count resource the owner process holds.
 | ||||
|     KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||||
|     owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); | ||||
|     owner->GetResourceLimit()->Release(LimitableResource::SessionCountMax, 1); | ||||
|     owner->Close(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -14,7 +14,7 @@ namespace Kernel { | ||||
| KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | ||||
| 
 | ||||
| KSharedMemory::~KSharedMemory() { | ||||
|     kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); | ||||
|     kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, size); | ||||
| } | ||||
| 
 | ||||
| Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, | ||||
| @ -35,7 +35,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o | ||||
|     KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); | ||||
| 
 | ||||
|     // Reserve memory for ourselves.
 | ||||
|     KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory, | ||||
|     KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemoryMax, | ||||
|                                                   size_); | ||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
| @ -57,7 +57,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o | ||||
| 
 | ||||
| void KSharedMemory::Finalize() { | ||||
|     // Release the memory reservation.
 | ||||
|     resource_limit->Release(LimitableResource::PhysicalMemory, size); | ||||
|     resource_limit->Release(LimitableResource::PhysicalMemoryMax, size); | ||||
|     resource_limit->Close(); | ||||
| 
 | ||||
|     // Perform inherited finalization.
 | ||||
|  | ||||
| @ -303,7 +303,7 @@ void KThread::PostDestroy(uintptr_t arg) { | ||||
|     const bool resource_limit_release_hint = (arg & 1); | ||||
|     const s64 hint_value = (resource_limit_release_hint ? 0 : 1); | ||||
|     if (owner != nullptr) { | ||||
|         owner->GetResourceLimit()->Release(LimitableResource::Threads, 1, hint_value); | ||||
|         owner->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1, hint_value); | ||||
|         owner->Close(); | ||||
|     } | ||||
| } | ||||
| @ -1054,7 +1054,7 @@ void KThread::Exit() { | ||||
| 
 | ||||
|     // Release the thread resource hint, running thread count from parent.
 | ||||
|     if (parent != nullptr) { | ||||
|         parent->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 0, 1); | ||||
|         parent->GetResourceLimit()->Release(Kernel::LimitableResource::ThreadCountMax, 0, 1); | ||||
|         resource_limit_release_hint = true; | ||||
|         parent->DecrementRunningThreadCount(); | ||||
|     } | ||||
|  | ||||
| @ -37,7 +37,7 @@ void KTransferMemory::Finalize() { | ||||
| 
 | ||||
| void KTransferMemory::PostDestroy(uintptr_t arg) { | ||||
|     KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||||
|     owner->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); | ||||
|     owner->GetResourceLimit()->Release(LimitableResource::TransferMemoryCountMax, 1); | ||||
|     owner->Close(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -229,18 +229,22 @@ struct KernelCore::Impl { | ||||
|         const auto kernel_size{sizes.second}; | ||||
| 
 | ||||
|         // If setting the default system values fails, then something seriously wrong has occurred.
 | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size) | ||||
|         ASSERT( | ||||
|             system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemoryMax, total_size) | ||||
|                 .IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800) | ||||
|                    .IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900) | ||||
|                    .IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); | ||||
|         system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200) | ||||
|                    .IsSuccess()); | ||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133) | ||||
|                    .IsSuccess()); | ||||
|         system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, kernel_size); | ||||
| 
 | ||||
|         // Reserve secure applet memory, introduced in firmware 5.0.0
 | ||||
|         constexpr u64 secure_applet_memory_size{4_MiB}; | ||||
|         ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory, | ||||
|         ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, | ||||
|                                               secure_applet_memory_size)); | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -193,7 +193,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | ||||
|                          KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()); | ||||
| 
 | ||||
|     // Reserve a new event from the process resource limit
 | ||||
|     KScopedResourceReservation event_reservation(m_process, LimitableResource::Events); | ||||
|     KScopedResourceReservation event_reservation(m_process, LimitableResource::EventCountMax); | ||||
|     ASSERT(event_reservation.Succeeded()); | ||||
| 
 | ||||
|     // Initialize event.
 | ||||
| @ -204,7 +204,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | ||||
|     event_reservation.Commit(); | ||||
| 
 | ||||
|     // Reserve a new thread from the process resource limit
 | ||||
|     KScopedResourceReservation thread_reservation(m_process, LimitableResource::Threads); | ||||
|     KScopedResourceReservation thread_reservation(m_process, LimitableResource::ThreadCountMax); | ||||
|     ASSERT(thread_reservation.Succeeded()); | ||||
| 
 | ||||
|     // Initialize thread.
 | ||||
|  | ||||
| @ -267,7 +267,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | ||||
| 
 | ||||
|     // Reserve a new session from the process resource limit.
 | ||||
|     // FIXME: LimitableResource_SessionCountMax
 | ||||
|     KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); | ||||
|     KScopedResourceReservation session_reservation(&process, LimitableResource::SessionCountMax); | ||||
|     if (session_reservation.Succeeded()) { | ||||
|         session = T::Create(system.Kernel()); | ||||
|     } else { | ||||
| @ -298,7 +298,7 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien | ||||
| 
 | ||||
|         // We successfully allocated a session, so add the object we allocated to the resource
 | ||||
|         // limit.
 | ||||
|         // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1);
 | ||||
|         // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1);
 | ||||
|     } | ||||
| 
 | ||||
|     // Check that we successfully created a session.
 | ||||
| @ -656,27 +656,12 @@ static Result ArbitrateUnlock32(Core::System& system, u32 address) { | ||||
|     return ArbitrateUnlock(system, address); | ||||
| } | ||||
| 
 | ||||
| enum class BreakType : u32 { | ||||
|     Panic = 0, | ||||
|     AssertionFailed = 1, | ||||
|     PreNROLoad = 3, | ||||
|     PostNROLoad = 4, | ||||
|     PreNROUnload = 5, | ||||
|     PostNROUnload = 6, | ||||
|     CppException = 7, | ||||
| }; | ||||
| 
 | ||||
| struct BreakReason { | ||||
|     union { | ||||
|         u32 raw; | ||||
|         BitField<0, 30, BreakType> break_type; | ||||
|         BitField<31, 1, u32> signal_debugger; | ||||
|     }; | ||||
| }; | ||||
| 
 | ||||
| /// Break program execution
 | ||||
| static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | ||||
|     BreakReason break_reason{reason}; | ||||
|     BreakReason break_reason = | ||||
|         static_cast<BreakReason>(reason & ~static_cast<u32>(BreakReason::NotificationOnlyFlag)); | ||||
|     bool notification_only = (reason & static_cast<u32>(BreakReason::NotificationOnlyFlag)) != 0; | ||||
| 
 | ||||
|     bool has_dumped_buffer{}; | ||||
|     std::vector<u8> debug_buffer; | ||||
| 
 | ||||
| @ -705,57 +690,56 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | ||||
|         } | ||||
|         has_dumped_buffer = true; | ||||
|     }; | ||||
|     switch (break_reason.break_type) { | ||||
|     case BreakType::Panic: | ||||
|         LOG_CRITICAL(Debug_Emulated, "Signalling debugger, PANIC! info1=0x{:016X}, info2=0x{:016X}", | ||||
|     switch (break_reason) { | ||||
|     case BreakReason::Panic: | ||||
|         LOG_CRITICAL(Debug_Emulated, "Userspace PANIC! info1=0x{:016X}, info2=0x{:016X}", info1, | ||||
|                      info2); | ||||
|         handle_debug_buffer(info1, info2); | ||||
|         break; | ||||
|     case BreakReason::Assert: | ||||
|         LOG_CRITICAL(Debug_Emulated, "Userspace Assertion failed! info1=0x{:016X}, info2=0x{:016X}", | ||||
|                      info1, info2); | ||||
|         handle_debug_buffer(info1, info2); | ||||
|         break; | ||||
|     case BreakType::AssertionFailed: | ||||
|         LOG_CRITICAL(Debug_Emulated, | ||||
|                      "Signalling debugger, Assertion failed! info1=0x{:016X}, info2=0x{:016X}", | ||||
|                      info1, info2); | ||||
|     case BreakReason::User: | ||||
|         LOG_WARNING(Debug_Emulated, "Userspace Break! 0x{:016X} with size 0x{:016X}", info1, info2); | ||||
|         handle_debug_buffer(info1, info2); | ||||
|         break; | ||||
|     case BreakType::PreNROLoad: | ||||
|         LOG_WARNING( | ||||
|             Debug_Emulated, | ||||
|             "Signalling debugger, Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", | ||||
|             info1, info2); | ||||
|     case BreakReason::PreLoadDll: | ||||
|         LOG_INFO(Debug_Emulated, | ||||
|                  "Userspace Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||
|                  info2); | ||||
|         break; | ||||
|     case BreakType::PostNROLoad: | ||||
|         LOG_WARNING(Debug_Emulated, | ||||
|                     "Signalling debugger, Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||
|                     info2); | ||||
|     case BreakReason::PostLoadDll: | ||||
|         LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||
|                  info2); | ||||
|         break; | ||||
|     case BreakType::PreNROUnload: | ||||
|         LOG_WARNING( | ||||
|             Debug_Emulated, | ||||
|             "Signalling debugger, Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", | ||||
|             info1, info2); | ||||
|     case BreakReason::PreUnloadDll: | ||||
|         LOG_INFO(Debug_Emulated, | ||||
|                  "Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||
|                  info2); | ||||
|         break; | ||||
|     case BreakType::PostNROUnload: | ||||
|         LOG_WARNING(Debug_Emulated, | ||||
|                     "Signalling debugger, Unloaded an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||
|                     info2); | ||||
|     case BreakReason::PostUnloadDll: | ||||
|         LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}", | ||||
|                  info1, info2); | ||||
|         break; | ||||
|     case BreakType::CppException: | ||||
|     case BreakReason::CppException: | ||||
|         LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); | ||||
|         break; | ||||
|     default: | ||||
|         LOG_WARNING( | ||||
|             Debug_Emulated, | ||||
|             "Signalling debugger, Unknown break reason {}, info1=0x{:016X}, info2=0x{:016X}", | ||||
|             static_cast<u32>(break_reason.break_type.Value()), info1, info2); | ||||
|             "Signalling debugger, Unknown break reason {:#X}, info1=0x{:016X}, info2=0x{:016X}", | ||||
|             reason, info1, info2); | ||||
|         handle_debug_buffer(info1, info2); | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     system.GetReporter().SaveSvcBreakReport( | ||||
|         static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger.As<bool>(), | ||||
|         info1, info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); | ||||
|     system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2, | ||||
|                                             has_dumped_buffer ? std::make_optional(debug_buffer) | ||||
|                                                               : std::nullopt); | ||||
| 
 | ||||
|     if (!break_reason.signal_debugger) { | ||||
|     if (!notification_only) { | ||||
|         LOG_CRITICAL( | ||||
|             Debug_Emulated, | ||||
|             "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", | ||||
| @ -1716,13 +1700,13 @@ static Result QueryProcessMemory(Core::System& system, VAddr memory_info_address | ||||
|     auto& memory{system.Memory()}; | ||||
|     const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; | ||||
| 
 | ||||
|     memory.Write64(memory_info_address + 0x00, memory_info.addr); | ||||
|     memory.Write64(memory_info_address + 0x00, memory_info.base_address); | ||||
|     memory.Write64(memory_info_address + 0x08, memory_info.size); | ||||
|     memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff); | ||||
|     memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attr)); | ||||
|     memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm)); | ||||
|     memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount); | ||||
|     memory.Write32(memory_info_address + 0x20, memory_info.device_refcount); | ||||
|     memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attribute)); | ||||
|     memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission)); | ||||
|     memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count); | ||||
|     memory.Write32(memory_info_address + 0x20, memory_info.device_count); | ||||
|     memory.Write32(memory_info_address + 0x24, 0); | ||||
| 
 | ||||
|     // Page info appears to be currently unused by the kernel and is always set to zero.
 | ||||
| @ -1943,7 +1927,7 @@ static Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry | ||||
| 
 | ||||
|     // Reserve a new thread from the process resource limit (waiting up to 100ms).
 | ||||
|     KScopedResourceReservation thread_reservation( | ||||
|         kernel.CurrentProcess(), LimitableResource::Threads, 1, | ||||
|         kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1, | ||||
|         system.CoreTiming().GetGlobalTimeNs().count() + 100000000); | ||||
|     if (!thread_reservation.Succeeded()) { | ||||
|         LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); | ||||
| @ -2344,7 +2328,7 @@ static Result CreateTransferMemory(Core::System& system, Handle* out, VAddr addr | ||||
| 
 | ||||
|     // Reserve a new transfer memory from the process resource limit.
 | ||||
|     KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), | ||||
|                                                  LimitableResource::TransferMemory); | ||||
|                                                  LimitableResource::TransferMemoryCountMax); | ||||
|     R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|     // Create the transfer memory.
 | ||||
| @ -2496,7 +2480,7 @@ static Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_r | ||||
| 
 | ||||
|     // Reserve a new event from the process resource limit
 | ||||
|     KScopedResourceReservation event_reservation(kernel.CurrentProcess(), | ||||
|                                                  LimitableResource::Events); | ||||
|                                                  LimitableResource::EventCountMax); | ||||
|     R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); | ||||
| 
 | ||||
|     // Create a new event.
 | ||||
| @ -2539,11 +2523,6 @@ static Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out | ||||
| static Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) { | ||||
|     LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type); | ||||
| 
 | ||||
|     // This function currently only allows retrieving a process' status.
 | ||||
|     enum class InfoType { | ||||
|         Status, | ||||
|     }; | ||||
| 
 | ||||
|     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | ||||
|     KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); | ||||
|     if (process.IsNull()) { | ||||
| @ -2552,9 +2531,9 @@ static Result GetProcessInfo(Core::System& system, u64* out, Handle process_hand | ||||
|         return ResultInvalidHandle; | ||||
|     } | ||||
| 
 | ||||
|     const auto info_type = static_cast<InfoType>(type); | ||||
|     if (info_type != InfoType::Status) { | ||||
|         LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type); | ||||
|     const auto info_type = static_cast<ProcessInfoType>(type); | ||||
|     if (info_type != ProcessInfoType::ProcessState) { | ||||
|         LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type); | ||||
|         return ResultInvalidEnumValue; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -8,6 +8,8 @@ | ||||
| 
 | ||||
| namespace Kernel::Svc { | ||||
| 
 | ||||
| using Handle = u32; | ||||
| 
 | ||||
| enum class MemoryState : u32 { | ||||
|     Free = 0x00, | ||||
|     Io = 0x01, | ||||
| @ -55,17 +57,6 @@ enum class MemoryPermission : u32 { | ||||
| }; | ||||
| DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); | ||||
| 
 | ||||
| struct MemoryInfo { | ||||
|     u64 addr{}; | ||||
|     u64 size{}; | ||||
|     MemoryState state{}; | ||||
|     MemoryAttribute attr{}; | ||||
|     MemoryPermission perm{}; | ||||
|     u32 ipc_refcount{}; | ||||
|     u32 device_refcount{}; | ||||
|     u32 padding{}; | ||||
| }; | ||||
| 
 | ||||
| enum class SignalType : u32 { | ||||
|     Signal = 0, | ||||
|     SignalAndIncrementIfEqual = 1, | ||||
| @ -124,7 +115,57 @@ enum class ProcessExitReason : u32 { | ||||
| 
 | ||||
| constexpr inline size_t ThreadLocalRegionSize = 0x200; | ||||
| 
 | ||||
| // Debug types.
 | ||||
| struct PageInfo { | ||||
|     u32 flags; | ||||
| }; | ||||
| 
 | ||||
| // Info Types.
 | ||||
| enum class InfoType : u32 { | ||||
|     CoreMask = 0, | ||||
|     PriorityMask = 1, | ||||
|     AliasRegionAddress = 2, | ||||
|     AliasRegionSize = 3, | ||||
|     HeapRegionAddress = 4, | ||||
|     HeapRegionSize = 5, | ||||
|     TotalMemorySize = 6, | ||||
|     UsedMemorySize = 7, | ||||
|     DebuggerAttached = 8, | ||||
|     ResourceLimit = 9, | ||||
|     IdleTickCount = 10, | ||||
|     RandomEntropy = 11, | ||||
|     AslrRegionAddress = 12, | ||||
|     AslrRegionSize = 13, | ||||
|     StackRegionAddress = 14, | ||||
|     StackRegionSize = 15, | ||||
|     SystemResourceSizeTotal = 16, | ||||
|     SystemResourceSizeUsed = 17, | ||||
|     ProgramId = 18, | ||||
|     InitialProcessIdRange = 19, | ||||
|     UserExceptionContextAddress = 20, | ||||
|     TotalNonSystemMemorySize = 21, | ||||
|     UsedNonSystemMemorySize = 22, | ||||
|     IsApplication = 23, | ||||
|     FreeThreadCount = 24, | ||||
|     ThreadTickCount = 25, | ||||
|     IsSvcPermitted = 26, | ||||
| 
 | ||||
|     MesosphereMeta = 65000, | ||||
|     MesosphereCurrentProcess = 65001, | ||||
| }; | ||||
| 
 | ||||
| enum class BreakReason : u32 { | ||||
|     Panic = 0, | ||||
|     Assert = 1, | ||||
|     User = 2, | ||||
|     PreLoadDll = 3, | ||||
|     PostLoadDll = 4, | ||||
|     PreUnloadDll = 5, | ||||
|     PostUnloadDll = 6, | ||||
|     CppException = 7, | ||||
| 
 | ||||
|     NotificationOnlyFlag = 0x80000000, | ||||
| }; | ||||
| 
 | ||||
| enum class DebugEvent : u32 { | ||||
|     CreateProcess = 0, | ||||
|     CreateThread = 1, | ||||
| @ -133,6 +174,14 @@ enum class DebugEvent : u32 { | ||||
|     Exception = 4, | ||||
| }; | ||||
| 
 | ||||
| enum class DebugThreadParam : u32 { | ||||
|     Priority = 0, | ||||
|     State = 1, | ||||
|     IdealCore = 2, | ||||
|     CurrentCore = 3, | ||||
|     AffinityMask = 4, | ||||
| }; | ||||
| 
 | ||||
| enum class DebugException : u32 { | ||||
|     UndefinedInstruction = 0, | ||||
|     InstructionAbort = 1, | ||||
| @ -146,4 +195,401 @@ enum class DebugException : u32 { | ||||
|     MemorySystemError = 9, | ||||
| }; | ||||
| 
 | ||||
| enum class DebugEventFlag : u32 { | ||||
|     Stopped = (1u << 0), | ||||
| }; | ||||
| 
 | ||||
| enum class BreakPointType : u32 { | ||||
|     HardwareInstruction = 0, | ||||
|     HardwareData = 1, | ||||
| }; | ||||
| 
 | ||||
| enum class HardwareBreakPointRegisterName : u32 { | ||||
|     I0 = 0, | ||||
|     I1 = 1, | ||||
|     I2 = 2, | ||||
|     I3 = 3, | ||||
|     I4 = 4, | ||||
|     I5 = 5, | ||||
|     I6 = 6, | ||||
|     I7 = 7, | ||||
|     I8 = 8, | ||||
|     I9 = 9, | ||||
|     I10 = 10, | ||||
|     I11 = 11, | ||||
|     I12 = 12, | ||||
|     I13 = 13, | ||||
|     I14 = 14, | ||||
|     I15 = 15, | ||||
|     D0 = 16, | ||||
|     D1 = 17, | ||||
|     D2 = 18, | ||||
|     D3 = 19, | ||||
|     D4 = 20, | ||||
|     D5 = 21, | ||||
|     D6 = 22, | ||||
|     D7 = 23, | ||||
|     D8 = 24, | ||||
|     D9 = 25, | ||||
|     D10 = 26, | ||||
|     D11 = 27, | ||||
|     D12 = 28, | ||||
|     D13 = 29, | ||||
|     D14 = 30, | ||||
|     D15 = 31, | ||||
| }; | ||||
| 
 | ||||
| namespace lp64 { | ||||
| struct LastThreadContext { | ||||
|     u64 fp; | ||||
|     u64 sp; | ||||
|     u64 lr; | ||||
|     u64 pc; | ||||
| }; | ||||
| 
 | ||||
| struct PhysicalMemoryInfo { | ||||
|     PAddr physical_address; | ||||
|     u64 virtual_address; | ||||
|     u64 size; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoCreateProcess { | ||||
|     u64 program_id; | ||||
|     u64 process_id; | ||||
|     std::array<char, 0xC> name; | ||||
|     u32 flags; | ||||
|     u64 user_exception_context_address; // 5.0.0+
 | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoCreateThread { | ||||
|     u64 thread_id; | ||||
|     u64 tls_address; | ||||
|     // Removed in 11.0.0 u64 entrypoint;
 | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoExitProcess { | ||||
|     ProcessExitReason reason; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoExitThread { | ||||
|     ThreadExitReason reason; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoUndefinedInstructionException { | ||||
|     u32 insn; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoDataAbortException { | ||||
|     u64 address; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoAlignmentFaultException { | ||||
|     u64 address; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoBreakPointException { | ||||
|     BreakPointType type; | ||||
|     u64 address; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoUserBreakException { | ||||
|     BreakReason break_reason; | ||||
|     u64 address; | ||||
|     u64 size; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoDebuggerBreakException { | ||||
|     std::array<u64, 4> active_thread_ids; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoUndefinedSystemCallException { | ||||
|     u32 id; | ||||
| }; | ||||
| 
 | ||||
| union DebugInfoSpecificException { | ||||
|     DebugInfoUndefinedInstructionException undefined_instruction; | ||||
|     DebugInfoDataAbortException data_abort; | ||||
|     DebugInfoAlignmentFaultException alignment_fault; | ||||
|     DebugInfoBreakPointException break_point; | ||||
|     DebugInfoUserBreakException user_break; | ||||
|     DebugInfoDebuggerBreakException debugger_break; | ||||
|     DebugInfoUndefinedSystemCallException undefined_system_call; | ||||
|     u64 raw; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoException { | ||||
|     DebugException type; | ||||
|     u64 address; | ||||
|     DebugInfoSpecificException specific; | ||||
| }; | ||||
| 
 | ||||
| union DebugInfo { | ||||
|     DebugInfoCreateProcess create_process; | ||||
|     DebugInfoCreateThread create_thread; | ||||
|     DebugInfoExitProcess exit_process; | ||||
|     DebugInfoExitThread exit_thread; | ||||
|     DebugInfoException exception; | ||||
| }; | ||||
| 
 | ||||
| struct DebugEventInfo { | ||||
|     DebugEvent type; | ||||
|     u32 flags; | ||||
|     u64 thread_id; | ||||
|     DebugInfo info; | ||||
| }; | ||||
| static_assert(sizeof(DebugEventInfo) >= 0x40); | ||||
| 
 | ||||
| struct SecureMonitorArguments { | ||||
|     std::array<u64, 8> r; | ||||
| }; | ||||
| static_assert(sizeof(SecureMonitorArguments) == 0x40); | ||||
| } // namespace lp64
 | ||||
| 
 | ||||
| namespace ilp32 { | ||||
| struct LastThreadContext { | ||||
|     u32 fp; | ||||
|     u32 sp; | ||||
|     u32 lr; | ||||
|     u32 pc; | ||||
| }; | ||||
| 
 | ||||
| struct PhysicalMemoryInfo { | ||||
|     PAddr physical_address; | ||||
|     u32 virtual_address; | ||||
|     u32 size; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoCreateProcess { | ||||
|     u64 program_id; | ||||
|     u64 process_id; | ||||
|     std::array<char, 0xC> name; | ||||
|     u32 flags; | ||||
|     u32 user_exception_context_address; // 5.0.0+
 | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoCreateThread { | ||||
|     u64 thread_id; | ||||
|     u32 tls_address; | ||||
|     // Removed in 11.0.0 u32 entrypoint;
 | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoExitProcess { | ||||
|     ProcessExitReason reason; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoExitThread { | ||||
|     ThreadExitReason reason; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoUndefinedInstructionException { | ||||
|     u32 insn; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoDataAbortException { | ||||
|     u32 address; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoAlignmentFaultException { | ||||
|     u32 address; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoBreakPointException { | ||||
|     BreakPointType type; | ||||
|     u32 address; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoUserBreakException { | ||||
|     BreakReason break_reason; | ||||
|     u32 address; | ||||
|     u32 size; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoDebuggerBreakException { | ||||
|     std::array<u64, 4> active_thread_ids; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoUndefinedSystemCallException { | ||||
|     u32 id; | ||||
| }; | ||||
| 
 | ||||
| union DebugInfoSpecificException { | ||||
|     DebugInfoUndefinedInstructionException undefined_instruction; | ||||
|     DebugInfoDataAbortException data_abort; | ||||
|     DebugInfoAlignmentFaultException alignment_fault; | ||||
|     DebugInfoBreakPointException break_point; | ||||
|     DebugInfoUserBreakException user_break; | ||||
|     DebugInfoDebuggerBreakException debugger_break; | ||||
|     DebugInfoUndefinedSystemCallException undefined_system_call; | ||||
|     u64 raw; | ||||
| }; | ||||
| 
 | ||||
| struct DebugInfoException { | ||||
|     DebugException type; | ||||
|     u32 address; | ||||
|     DebugInfoSpecificException specific; | ||||
| }; | ||||
| 
 | ||||
| union DebugInfo { | ||||
|     DebugInfoCreateProcess create_process; | ||||
|     DebugInfoCreateThread create_thread; | ||||
|     DebugInfoExitProcess exit_process; | ||||
|     DebugInfoExitThread exit_thread; | ||||
|     DebugInfoException exception; | ||||
| }; | ||||
| 
 | ||||
| struct DebugEventInfo { | ||||
|     DebugEvent type; | ||||
|     u32 flags; | ||||
|     u64 thread_id; | ||||
|     DebugInfo info; | ||||
| }; | ||||
| 
 | ||||
| struct SecureMonitorArguments { | ||||
|     std::array<u32, 8> r; | ||||
| }; | ||||
| static_assert(sizeof(SecureMonitorArguments) == 0x20); | ||||
| } // namespace ilp32
 | ||||
| 
 | ||||
| struct ThreadContext { | ||||
|     std::array<u64, 29> r; | ||||
|     u64 fp; | ||||
|     u64 lr; | ||||
|     u64 sp; | ||||
|     u64 pc; | ||||
|     u32 pstate; | ||||
|     u32 padding; | ||||
|     std::array<u128, 32> v; | ||||
|     u32 fpcr; | ||||
|     u32 fpsr; | ||||
|     u64 tpidr; | ||||
| }; | ||||
| static_assert(sizeof(ThreadContext) == 0x320); | ||||
| 
 | ||||
| struct MemoryInfo { | ||||
|     u64 base_address; | ||||
|     u64 size; | ||||
|     MemoryState state; | ||||
|     MemoryAttribute attribute; | ||||
|     MemoryPermission permission; | ||||
|     u32 ipc_count; | ||||
|     u32 device_count; | ||||
|     u32 padding; | ||||
| }; | ||||
| 
 | ||||
| enum class LimitableResource : u32 { | ||||
|     PhysicalMemoryMax = 0, | ||||
|     ThreadCountMax = 1, | ||||
|     EventCountMax = 2, | ||||
|     TransferMemoryCountMax = 3, | ||||
|     SessionCountMax = 4, | ||||
|     Count, | ||||
| }; | ||||
| 
 | ||||
| enum class IoPoolType : u32 { | ||||
|     // Not supported.
 | ||||
|     Count = 0, | ||||
| }; | ||||
| 
 | ||||
| enum class MemoryMapping : u32 { | ||||
|     IoRegister = 0, | ||||
|     Uncached = 1, | ||||
|     Memory = 2, | ||||
| }; | ||||
| 
 | ||||
| enum class KernelDebugType : u32 { | ||||
|     Thread = 0, | ||||
|     ThreadCallStack = 1, | ||||
|     KernelObject = 2, | ||||
|     Handle_ = 3, | ||||
|     Memory = 4, | ||||
|     PageTable = 5, | ||||
|     CpuUtilization = 6, | ||||
|     Process = 7, | ||||
|     SuspendProcess = 8, | ||||
|     ResumeProcess = 9, | ||||
|     Port = 10, | ||||
| }; | ||||
| 
 | ||||
| enum class KernelTraceState : u32 { | ||||
|     Disabled = 0, | ||||
|     Enabled = 1, | ||||
| }; | ||||
| 
 | ||||
| enum class CodeMemoryOperation : u32 { | ||||
|     Map = 0, | ||||
|     MapToOwner = 1, | ||||
|     Unmap = 2, | ||||
|     UnmapFromOwner = 3, | ||||
| }; | ||||
| 
 | ||||
| enum class InterruptType : u32 { | ||||
|     Edge = 0, | ||||
|     Level = 1, | ||||
| }; | ||||
| 
 | ||||
| enum class DeviceName { | ||||
|     Afi = 0, | ||||
|     Avpc = 1, | ||||
|     Dc = 2, | ||||
|     Dcb = 3, | ||||
|     Hc = 4, | ||||
|     Hda = 5, | ||||
|     Isp2 = 6, | ||||
|     MsencNvenc = 7, | ||||
|     Nv = 8, | ||||
|     Nv2 = 9, | ||||
|     Ppcs = 10, | ||||
|     Sata = 11, | ||||
|     Vi = 12, | ||||
|     Vic = 13, | ||||
|     XusbHost = 14, | ||||
|     XusbDev = 15, | ||||
|     Tsec = 16, | ||||
|     Ppcs1 = 17, | ||||
|     Dc1 = 18, | ||||
|     Sdmmc1a = 19, | ||||
|     Sdmmc2a = 20, | ||||
|     Sdmmc3a = 21, | ||||
|     Sdmmc4a = 22, | ||||
|     Isp2b = 23, | ||||
|     Gpu = 24, | ||||
|     Gpub = 25, | ||||
|     Ppcs2 = 26, | ||||
|     Nvdec = 27, | ||||
|     Ape = 28, | ||||
|     Se = 29, | ||||
|     Nvjpg = 30, | ||||
|     Hc1 = 31, | ||||
|     Se1 = 32, | ||||
|     Axiap = 33, | ||||
|     Etr = 34, | ||||
|     Tsecb = 35, | ||||
|     Tsec1 = 36, | ||||
|     Tsecb1 = 37, | ||||
|     Nvdec1 = 38, | ||||
|     Count, | ||||
| }; | ||||
| 
 | ||||
| enum class SystemInfoType : u32 { | ||||
|     TotalPhysicalMemorySize = 0, | ||||
|     UsedPhysicalMemorySize = 1, | ||||
|     InitialProcessIdRange = 2, | ||||
| }; | ||||
| 
 | ||||
| enum class ProcessInfoType : u32 { | ||||
|     ProcessState = 0, | ||||
| }; | ||||
| 
 | ||||
| struct CreateProcessParameter { | ||||
|     std::array<char, 12> name; | ||||
|     u32 version; | ||||
|     u64 program_id; | ||||
|     u64 code_address; | ||||
|     s32 code_num_pages; | ||||
|     u32 flags; | ||||
|     Handle reslimit; | ||||
|     s32 system_resource_num_pages; | ||||
| }; | ||||
| static_assert(sizeof(CreateProcessParameter) == 0x30); | ||||
| 
 | ||||
| } // namespace Kernel::Svc
 | ||||
|  | ||||
| @ -31,7 +31,7 @@ ServiceContext::~ServiceContext() { | ||||
| Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { | ||||
|     // Reserve a new event from the process resource limit
 | ||||
|     Kernel::KScopedResourceReservation event_reservation(process, | ||||
|                                                          Kernel::LimitableResource::Events); | ||||
|                                                          Kernel::LimitableResource::EventCountMax); | ||||
|     if (!event_reservation.Succeeded()) { | ||||
|         LOG_CRITICAL(Service, "Resource limit reached!"); | ||||
|         return {}; | ||||
|  | ||||
| @ -34,8 +34,8 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | ||||
|     // once this is a proper process
 | ||||
| 
 | ||||
|     // Reserve a new session from the process resource limit.
 | ||||
|     Kernel::KScopedResourceReservation session_reservation(&process, | ||||
|                                                            Kernel::LimitableResource::Sessions); | ||||
|     Kernel::KScopedResourceReservation session_reservation( | ||||
|         &process, Kernel::LimitableResource::SessionCountMax); | ||||
|     ASSERT(session_reservation.Succeeded()); | ||||
| 
 | ||||
|     // Create the session.
 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user