mirror of
				https://git.suyu.dev/suyu/suyu.git
				synced 2025-10-31 14:56: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)); |             context->AddDomainObject(std::move(iface)); | ||||||
|         } else { |         } else { | ||||||
|             kernel.CurrentProcess()->GetResourceLimit()->Reserve( |             kernel.CurrentProcess()->GetResourceLimit()->Reserve( | ||||||
|                 Kernel::LimitableResource::Sessions, 1); |                 Kernel::LimitableResource::SessionCountMax, 1); | ||||||
| 
 | 
 | ||||||
|             auto* session = Kernel::KSession::Create(kernel); |             auto* session = Kernel::KSession::Create(kernel); | ||||||
|             session->Initialize(nullptr, iface->GetServiceName()); |             session->Initialize(nullptr, iface->GetServiceName()); | ||||||
|  | |||||||
| @ -265,7 +265,8 @@ void KPageBufferSlabHeap::Initialize(Core::System& system) { | |||||||
|     const size_t slab_size = num_pages * PageSize; |     const size_t slab_size = num_pages * PageSize; | ||||||
| 
 | 
 | ||||||
|     // Reserve memory from the system resource limit.
 |     // 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.
 |     // Allocate memory for the slab.
 | ||||||
|     constexpr auto AllocateOption = KMemoryManager::EncodeOption( |     constexpr auto AllocateOption = KMemoryManager::EncodeOption( | ||||||
|  | |||||||
| @ -61,7 +61,7 @@ bool KClientPort::IsSignaled() const { | |||||||
| Result KClientPort::CreateSession(KClientSession** out) { | Result KClientPort::CreateSession(KClientSession** out) { | ||||||
|     // Reserve a new session from the resource limit.
 |     // Reserve a new session from the resource limit.
 | ||||||
|     KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), |     KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(), | ||||||
|                                                    LimitableResource::Sessions); |                                                    LimitableResource::SessionCountMax); | ||||||
|     R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
|     // Update the session counts.
 |     // Update the session counts.
 | ||||||
|  | |||||||
| @ -50,7 +50,7 @@ Result KEvent::Clear() { | |||||||
| void KEvent::PostDestroy(uintptr_t arg) { | void KEvent::PostDestroy(uintptr_t arg) { | ||||||
|     // Release the event count resource the owner process holds.
 |     // Release the event count resource the owner process holds.
 | ||||||
|     KProcess* owner = reinterpret_cast<KProcess*>(arg); |     KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||||||
|     owner->GetResourceLimit()->Release(LimitableResource::Events, 1); |     owner->GetResourceLimit()->Release(LimitableResource::EventCountMax, 1); | ||||||
|     owner->Close(); |     owner->Close(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -216,13 +216,15 @@ struct KMemoryInfo { | |||||||
| 
 | 
 | ||||||
|     constexpr Svc::MemoryInfo GetSvcMemoryInfo() const { |     constexpr Svc::MemoryInfo GetSvcMemoryInfo() const { | ||||||
|         return { |         return { | ||||||
|             .addr = m_address, |             .base_address = m_address, | ||||||
|             .size = m_size, |             .size = m_size, | ||||||
|             .state = static_cast<Svc::MemoryState>(m_state & KMemoryState::Mask), |             .state = static_cast<Svc::MemoryState>(m_state & KMemoryState::Mask), | ||||||
|             .attr = static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask), |             .attribute = | ||||||
|             .perm = static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask), |                 static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask), | ||||||
|             .ipc_refcount = m_ipc_lock_count, |             .permission = | ||||||
|             .device_refcount = m_device_use_count, |                 static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask), | ||||||
|  |             .ipc_count = m_ipc_lock_count, | ||||||
|  |             .device_count = m_device_use_count, | ||||||
|             .padding = {}, |             .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.
 |     // Reserve space for any partial pages we allocate.
 | ||||||
|     const size_t unmapped_size = aligned_src_size - mapping_src_size; |     const size_t unmapped_size = aligned_src_size - mapping_src_size; | ||||||
|     KScopedResourceReservation memory_reservation(m_resource_limit, |     KScopedResourceReservation memory_reservation( | ||||||
|                                                   LimitableResource::PhysicalMemory, unmapped_size); |         m_resource_limit, LimitableResource::PhysicalMemoryMax, unmapped_size); | ||||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
|     // Ensure that we manage page references correctly.
 |     // 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_start = Common::AlignUp((address), PageSize); | ||||||
|     const VAddr mapping_end = Common::AlignDown((address) + size, PageSize); |     const VAddr mapping_end = Common::AlignDown((address) + size, PageSize); | ||||||
|     const size_t mapping_size = (mapping_start < mapping_end) ? mapping_end - mapping_start : 0; |     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(); |     R_SUCCEED(); | ||||||
| } | } | ||||||
| @ -1568,7 +1568,7 @@ Result KPageTable::MapPhysicalMemory(VAddr address, size_t size) { | |||||||
|         { |         { | ||||||
|             // Reserve the memory from the process resource limit.
 |             // Reserve the memory from the process resource limit.
 | ||||||
|             KScopedResourceReservation memory_reservation( |             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); |             R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
|             // Allocate pages for the new memory.
 |             // Allocate pages for the new memory.
 | ||||||
| @ -1908,7 +1908,7 @@ Result KPageTable::UnmapPhysicalMemory(VAddr address, size_t size) { | |||||||
| 
 | 
 | ||||||
|     // Release the memory resource.
 |     // Release the memory resource.
 | ||||||
|     m_mapped_physical_memory_size -= mapped_size; |     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.
 |     // Update memory blocks.
 | ||||||
|     m_memory_block_manager.Update(std::addressof(allocator), address, size / PageSize, |     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)); |                           OperationType::Unmap)); | ||||||
| 
 | 
 | ||||||
|             // Release the memory from the resource limit.
 |             // 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.
 |             // Apply the memory block update.
 | ||||||
|             m_memory_block_manager.Update(std::addressof(allocator), m_heap_region_start + size, |             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.
 |     // Reserve memory for the heap extension.
 | ||||||
|     KScopedResourceReservation memory_reservation( |     KScopedResourceReservation memory_reservation( | ||||||
|         m_resource_limit, LimitableResource::PhysicalMemory, allocation_size); |         m_resource_limit, LimitableResource::PhysicalMemoryMax, allocation_size); | ||||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
|     // Allocate pages for the heap extension.
 |     // Allocate pages for the heap extension.
 | ||||||
|  | |||||||
| @ -38,7 +38,7 @@ namespace { | |||||||
|  */ |  */ | ||||||
| void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { | void SetupMainThread(Core::System& system, KProcess& owner_process, u32 priority, VAddr stack_top) { | ||||||
|     const VAddr entry_point = owner_process.PageTable().GetCodeRegionStart(); |     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()); |     KThread* thread = KThread::Create(system.Kernel()); | ||||||
|     SCOPE_EXIT({ thread->Close(); }); |     SCOPE_EXIT({ thread->Close(); }); | ||||||
| @ -124,7 +124,7 @@ void KProcess::DecrementRunningThreadCount() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u64 KProcess::GetTotalPhysicalMemoryAvailable() { | 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 + |                        page_table.GetNormalMemorySize() + GetSystemResourceSize() + image_size + | ||||||
|                        main_thread_stack_size}; |                        main_thread_stack_size}; | ||||||
|     if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); |     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
 |     // We currently do not support process-specific system resource
 | ||||||
|     UNIMPLEMENTED_IF(system_resource_size != 0); |     UNIMPLEMENTED_IF(system_resource_size != 0); | ||||||
| 
 | 
 | ||||||
|     KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory, |     KScopedResourceReservation memory_reservation( | ||||||
|                                                   code_size + system_resource_size); |         resource_limit, LimitableResource::PhysicalMemoryMax, code_size + system_resource_size); | ||||||
|     if (!memory_reservation.Succeeded()) { |     if (!memory_reservation.Succeeded()) { | ||||||
|         LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", |         LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes", | ||||||
|                   code_size + system_resource_size); |                   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) { | void KProcess::Run(s32 main_thread_priority, u64 stack_size) { | ||||||
|     AllocateMainThreadStack(stack_size); |     AllocateMainThreadStack(stack_size); | ||||||
|     resource_limit->Reserve(LimitableResource::Threads, 1); |     resource_limit->Reserve(LimitableResource::ThreadCountMax, 1); | ||||||
|     resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); |     resource_limit->Reserve(LimitableResource::PhysicalMemoryMax, main_thread_stack_size); | ||||||
| 
 | 
 | ||||||
|     const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; |     const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)}; | ||||||
|     ASSERT(!page_table.SetMaxHeapSize(heap_capacity).IsError()); |     ASSERT(!page_table.SetMaxHeapSize(heap_capacity).IsError()); | ||||||
| @ -442,7 +442,7 @@ void KProcess::PrepareForTermination() { | |||||||
|     plr_address = 0; |     plr_address = 0; | ||||||
| 
 | 
 | ||||||
|     if (resource_limit) { |     if (resource_limit) { | ||||||
|         resource_limit->Release(LimitableResource::PhysicalMemory, |         resource_limit->Release(LimitableResource::PhysicalMemoryMax, | ||||||
|                                 main_thread_stack_size + image_size); |                                 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
 |     // TODO(bunnei): These values are the system defaults, the limits for service processes are
 | ||||||
|     // lower. These should use the correct limit values.
 |     // 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()); |                .IsSuccess()); | ||||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); |     ASSERT(resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800).IsSuccess()); | ||||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); |     ASSERT(resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900).IsSuccess()); | ||||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200).IsSuccess()); |     ASSERT( | ||||||
|     ASSERT(resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); |         resource_limit->SetLimitValue(LimitableResource::TransferMemoryCountMax, 200).IsSuccess()); | ||||||
|  |     ASSERT(resource_limit->SetLimitValue(LimitableResource::SessionCountMax, 1133).IsSuccess()); | ||||||
| 
 | 
 | ||||||
|     return resource_limit; |     return resource_limit; | ||||||
| } | } | ||||||
|  | |||||||
| @ -16,15 +16,8 @@ class CoreTiming; | |||||||
| 
 | 
 | ||||||
| namespace Kernel { | namespace Kernel { | ||||||
| class KernelCore; | 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) { | constexpr bool IsValidResourceType(LimitableResource type) { | ||||||
|     return type < LimitableResource::Count; |     return type < LimitableResource::Count; | ||||||
|  | |||||||
| @ -76,7 +76,7 @@ void KSession::OnClientClosed() { | |||||||
| void KSession::PostDestroy(uintptr_t arg) { | void KSession::PostDestroy(uintptr_t arg) { | ||||||
|     // Release the session count resource the owner process holds.
 |     // Release the session count resource the owner process holds.
 | ||||||
|     KProcess* owner = reinterpret_cast<KProcess*>(arg); |     KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||||||
|     owner->GetResourceLimit()->Release(LimitableResource::Sessions, 1); |     owner->GetResourceLimit()->Release(LimitableResource::SessionCountMax, 1); | ||||||
|     owner->Close(); |     owner->Close(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,7 +14,7 @@ namespace Kernel { | |||||||
| KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | KSharedMemory::KSharedMemory(KernelCore& kernel_) : KAutoObjectWithSlabHeapAndContainer{kernel_} {} | ||||||
| 
 | 
 | ||||||
| KSharedMemory::~KSharedMemory() { | KSharedMemory::~KSharedMemory() { | ||||||
|     kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemory, size); |     kernel.GetSystemResourceLimit()->Release(LimitableResource::PhysicalMemoryMax, size); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* owner_process_, | 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(); |     KResourceLimit* reslimit = kernel.GetSystemResourceLimit(); | ||||||
| 
 | 
 | ||||||
|     // Reserve memory for ourselves.
 |     // Reserve memory for ourselves.
 | ||||||
|     KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemory, |     KScopedResourceReservation memory_reservation(reslimit, LimitableResource::PhysicalMemoryMax, | ||||||
|                                                   size_); |                                                   size_); | ||||||
|     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
| @ -57,7 +57,7 @@ Result KSharedMemory::Initialize(Core::DeviceMemory& device_memory_, KProcess* o | |||||||
| 
 | 
 | ||||||
| void KSharedMemory::Finalize() { | void KSharedMemory::Finalize() { | ||||||
|     // Release the memory reservation.
 |     // Release the memory reservation.
 | ||||||
|     resource_limit->Release(LimitableResource::PhysicalMemory, size); |     resource_limit->Release(LimitableResource::PhysicalMemoryMax, size); | ||||||
|     resource_limit->Close(); |     resource_limit->Close(); | ||||||
| 
 | 
 | ||||||
|     // Perform inherited finalization.
 |     // Perform inherited finalization.
 | ||||||
|  | |||||||
| @ -303,7 +303,7 @@ void KThread::PostDestroy(uintptr_t arg) { | |||||||
|     const bool resource_limit_release_hint = (arg & 1); |     const bool resource_limit_release_hint = (arg & 1); | ||||||
|     const s64 hint_value = (resource_limit_release_hint ? 0 : 1); |     const s64 hint_value = (resource_limit_release_hint ? 0 : 1); | ||||||
|     if (owner != nullptr) { |     if (owner != nullptr) { | ||||||
|         owner->GetResourceLimit()->Release(LimitableResource::Threads, 1, hint_value); |         owner->GetResourceLimit()->Release(LimitableResource::ThreadCountMax, 1, hint_value); | ||||||
|         owner->Close(); |         owner->Close(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @ -1054,7 +1054,7 @@ void KThread::Exit() { | |||||||
| 
 | 
 | ||||||
|     // Release the thread resource hint, running thread count from parent.
 |     // Release the thread resource hint, running thread count from parent.
 | ||||||
|     if (parent != nullptr) { |     if (parent != nullptr) { | ||||||
|         parent->GetResourceLimit()->Release(Kernel::LimitableResource::Threads, 0, 1); |         parent->GetResourceLimit()->Release(Kernel::LimitableResource::ThreadCountMax, 0, 1); | ||||||
|         resource_limit_release_hint = true; |         resource_limit_release_hint = true; | ||||||
|         parent->DecrementRunningThreadCount(); |         parent->DecrementRunningThreadCount(); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -37,7 +37,7 @@ void KTransferMemory::Finalize() { | |||||||
| 
 | 
 | ||||||
| void KTransferMemory::PostDestroy(uintptr_t arg) { | void KTransferMemory::PostDestroy(uintptr_t arg) { | ||||||
|     KProcess* owner = reinterpret_cast<KProcess*>(arg); |     KProcess* owner = reinterpret_cast<KProcess*>(arg); | ||||||
|     owner->GetResourceLimit()->Release(LimitableResource::TransferMemory, 1); |     owner->GetResourceLimit()->Release(LimitableResource::TransferMemoryCountMax, 1); | ||||||
|     owner->Close(); |     owner->Close(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -229,18 +229,22 @@ struct KernelCore::Impl { | |||||||
|         const auto kernel_size{sizes.second}; |         const auto kernel_size{sizes.second}; | ||||||
| 
 | 
 | ||||||
|         // If setting the default system values fails, then something seriously wrong has occurred.
 |         // 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()); |                 .IsSuccess()); | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); |         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800) | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 900).IsSuccess()); |  | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200) |  | ||||||
|                    .IsSuccess()); |                    .IsSuccess()); | ||||||
|         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess()); |         ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900) | ||||||
|         system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); |                    .IsSuccess()); | ||||||
|  |         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
 |         // Reserve secure applet memory, introduced in firmware 5.0.0
 | ||||||
|         constexpr u64 secure_applet_memory_size{4_MiB}; |         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)); |                                               secure_applet_memory_size)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -193,7 +193,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | |||||||
|                          KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()); |                          KProcess::ProcessType::KernelInternal, kernel.GetSystemResourceLimit()); | ||||||
| 
 | 
 | ||||||
|     // Reserve a new event from the process resource limit
 |     // 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()); |     ASSERT(event_reservation.Succeeded()); | ||||||
| 
 | 
 | ||||||
|     // Initialize event.
 |     // Initialize event.
 | ||||||
| @ -204,7 +204,7 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name) | |||||||
|     event_reservation.Commit(); |     event_reservation.Commit(); | ||||||
| 
 | 
 | ||||||
|     // Reserve a new thread from the process resource limit
 |     // 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()); |     ASSERT(thread_reservation.Succeeded()); | ||||||
| 
 | 
 | ||||||
|     // Initialize thread.
 |     // 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.
 |     // Reserve a new session from the process resource limit.
 | ||||||
|     // FIXME: LimitableResource_SessionCountMax
 |     // FIXME: LimitableResource_SessionCountMax
 | ||||||
|     KScopedResourceReservation session_reservation(&process, LimitableResource::Sessions); |     KScopedResourceReservation session_reservation(&process, LimitableResource::SessionCountMax); | ||||||
|     if (session_reservation.Succeeded()) { |     if (session_reservation.Succeeded()) { | ||||||
|         session = T::Create(system.Kernel()); |         session = T::Create(system.Kernel()); | ||||||
|     } else { |     } 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
 |         // We successfully allocated a session, so add the object we allocated to the resource
 | ||||||
|         // limit.
 |         // limit.
 | ||||||
|         // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::Sessions, 1);
 |         // system.Kernel().GetSystemResourceLimit().Reserve(LimitableResource::SessionCountMax, 1);
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // Check that we successfully created a session.
 |     // Check that we successfully created a session.
 | ||||||
| @ -656,27 +656,12 @@ static Result ArbitrateUnlock32(Core::System& system, u32 address) { | |||||||
|     return ArbitrateUnlock(system, 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
 | /// Break program execution
 | ||||||
| static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) { | 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{}; |     bool has_dumped_buffer{}; | ||||||
|     std::vector<u8> debug_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; |         has_dumped_buffer = true; | ||||||
|     }; |     }; | ||||||
|     switch (break_reason.break_type) { |     switch (break_reason) { | ||||||
|     case BreakType::Panic: |     case BreakReason::Panic: | ||||||
|         LOG_CRITICAL(Debug_Emulated, "Signalling debugger, PANIC! info1=0x{:016X}, info2=0x{:016X}", |         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); |                      info1, info2); | ||||||
|         handle_debug_buffer(info1, info2); |         handle_debug_buffer(info1, info2); | ||||||
|         break; |         break; | ||||||
|     case BreakType::AssertionFailed: |     case BreakReason::User: | ||||||
|         LOG_CRITICAL(Debug_Emulated, |         LOG_WARNING(Debug_Emulated, "Userspace Break! 0x{:016X} with size 0x{:016X}", info1, info2); | ||||||
|                      "Signalling debugger, Assertion failed! info1=0x{:016X}, info2=0x{:016X}", |  | ||||||
|                      info1, info2); |  | ||||||
|         handle_debug_buffer(info1, info2); |         handle_debug_buffer(info1, info2); | ||||||
|         break; |         break; | ||||||
|     case BreakType::PreNROLoad: |     case BreakReason::PreLoadDll: | ||||||
|         LOG_WARNING( |         LOG_INFO(Debug_Emulated, | ||||||
|             Debug_Emulated, |                  "Userspace Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||||
|             "Signalling debugger, 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); |                  info2); | ||||||
|         break; |         break; | ||||||
|     case BreakType::PreNROUnload: |     case BreakReason::PostLoadDll: | ||||||
|         LOG_WARNING( |         LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||||
|             Debug_Emulated, |  | ||||||
|             "Signalling debugger, 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); |                  info2); | ||||||
|         break; |         break; | ||||||
|     case BreakType::CppException: |     case BreakReason::PreUnloadDll: | ||||||
|  |         LOG_INFO(Debug_Emulated, | ||||||
|  |                  "Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1, | ||||||
|  |                  info2); | ||||||
|  |         break; | ||||||
|  |     case BreakReason::PostUnloadDll: | ||||||
|  |         LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}", | ||||||
|  |                  info1, info2); | ||||||
|  |         break; | ||||||
|  |     case BreakReason::CppException: | ||||||
|         LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); |         LOG_CRITICAL(Debug_Emulated, "Signalling debugger. Uncaught C++ exception encountered."); | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         LOG_WARNING( |         LOG_WARNING( | ||||||
|             Debug_Emulated, |             Debug_Emulated, | ||||||
|             "Signalling debugger, Unknown break reason {}, info1=0x{:016X}, info2=0x{:016X}", |             "Signalling debugger, Unknown break reason {:#X}, info1=0x{:016X}, info2=0x{:016X}", | ||||||
|             static_cast<u32>(break_reason.break_type.Value()), info1, info2); |             reason, info1, info2); | ||||||
|         handle_debug_buffer(info1, info2); |         handle_debug_buffer(info1, info2); | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     system.GetReporter().SaveSvcBreakReport( |     system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2, | ||||||
|         static_cast<u32>(break_reason.break_type.Value()), break_reason.signal_debugger.As<bool>(), |                                             has_dumped_buffer ? std::make_optional(debug_buffer) | ||||||
|         info1, info2, has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt); |                                                               : std::nullopt); | ||||||
| 
 | 
 | ||||||
|     if (!break_reason.signal_debugger) { |     if (!notification_only) { | ||||||
|         LOG_CRITICAL( |         LOG_CRITICAL( | ||||||
|             Debug_Emulated, |             Debug_Emulated, | ||||||
|             "Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}", |             "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()}; |     auto& memory{system.Memory()}; | ||||||
|     const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()}; |     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.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 + 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 + 0x14, static_cast<u32>(memory_info.attribute)); | ||||||
|     memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.perm)); |     memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission)); | ||||||
|     memory.Write32(memory_info_address + 0x1c, memory_info.ipc_refcount); |     memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count); | ||||||
|     memory.Write32(memory_info_address + 0x20, memory_info.device_refcount); |     memory.Write32(memory_info_address + 0x20, memory_info.device_count); | ||||||
|     memory.Write32(memory_info_address + 0x24, 0); |     memory.Write32(memory_info_address + 0x24, 0); | ||||||
| 
 | 
 | ||||||
|     // Page info appears to be currently unused by the kernel and is always set to zero.
 |     // 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).
 |     // Reserve a new thread from the process resource limit (waiting up to 100ms).
 | ||||||
|     KScopedResourceReservation thread_reservation( |     KScopedResourceReservation thread_reservation( | ||||||
|         kernel.CurrentProcess(), LimitableResource::Threads, 1, |         kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1, | ||||||
|         system.CoreTiming().GetGlobalTimeNs().count() + 100000000); |         system.CoreTiming().GetGlobalTimeNs().count() + 100000000); | ||||||
|     if (!thread_reservation.Succeeded()) { |     if (!thread_reservation.Succeeded()) { | ||||||
|         LOG_ERROR(Kernel_SVC, "Could not reserve a new thread"); |         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.
 |     // Reserve a new transfer memory from the process resource limit.
 | ||||||
|     KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), |     KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(), | ||||||
|                                                  LimitableResource::TransferMemory); |                                                  LimitableResource::TransferMemoryCountMax); | ||||||
|     R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
|     // Create the transfer memory.
 |     // 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
 |     // Reserve a new event from the process resource limit
 | ||||||
|     KScopedResourceReservation event_reservation(kernel.CurrentProcess(), |     KScopedResourceReservation event_reservation(kernel.CurrentProcess(), | ||||||
|                                                  LimitableResource::Events); |                                                  LimitableResource::EventCountMax); | ||||||
|     R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); |     R_UNLESS(event_reservation.Succeeded(), ResultLimitReached); | ||||||
| 
 | 
 | ||||||
|     // Create a new event.
 |     // 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) { | 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); |     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(); |     const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | ||||||
|     KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); |     KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); | ||||||
|     if (process.IsNull()) { |     if (process.IsNull()) { | ||||||
| @ -2552,9 +2531,9 @@ static Result GetProcessInfo(Core::System& system, u64* out, Handle process_hand | |||||||
|         return ResultInvalidHandle; |         return ResultInvalidHandle; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     const auto info_type = static_cast<InfoType>(type); |     const auto info_type = static_cast<ProcessInfoType>(type); | ||||||
|     if (info_type != InfoType::Status) { |     if (info_type != ProcessInfoType::ProcessState) { | ||||||
|         LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type); |         LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type); | ||||||
|         return ResultInvalidEnumValue; |         return ResultInvalidEnumValue; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -8,6 +8,8 @@ | |||||||
| 
 | 
 | ||||||
| namespace Kernel::Svc { | namespace Kernel::Svc { | ||||||
| 
 | 
 | ||||||
|  | using Handle = u32; | ||||||
|  | 
 | ||||||
| enum class MemoryState : u32 { | enum class MemoryState : u32 { | ||||||
|     Free = 0x00, |     Free = 0x00, | ||||||
|     Io = 0x01, |     Io = 0x01, | ||||||
| @ -55,17 +57,6 @@ enum class MemoryPermission : u32 { | |||||||
| }; | }; | ||||||
| DECLARE_ENUM_FLAG_OPERATORS(MemoryPermission); | 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 { | enum class SignalType : u32 { | ||||||
|     Signal = 0, |     Signal = 0, | ||||||
|     SignalAndIncrementIfEqual = 1, |     SignalAndIncrementIfEqual = 1, | ||||||
| @ -124,7 +115,57 @@ enum class ProcessExitReason : u32 { | |||||||
| 
 | 
 | ||||||
| constexpr inline size_t ThreadLocalRegionSize = 0x200; | 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 { | enum class DebugEvent : u32 { | ||||||
|     CreateProcess = 0, |     CreateProcess = 0, | ||||||
|     CreateThread = 1, |     CreateThread = 1, | ||||||
| @ -133,6 +174,14 @@ enum class DebugEvent : u32 { | |||||||
|     Exception = 4, |     Exception = 4, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | enum class DebugThreadParam : u32 { | ||||||
|  |     Priority = 0, | ||||||
|  |     State = 1, | ||||||
|  |     IdealCore = 2, | ||||||
|  |     CurrentCore = 3, | ||||||
|  |     AffinityMask = 4, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| enum class DebugException : u32 { | enum class DebugException : u32 { | ||||||
|     UndefinedInstruction = 0, |     UndefinedInstruction = 0, | ||||||
|     InstructionAbort = 1, |     InstructionAbort = 1, | ||||||
| @ -146,4 +195,401 @@ enum class DebugException : u32 { | |||||||
|     MemorySystemError = 9, |     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
 | } // namespace Kernel::Svc
 | ||||||
|  | |||||||
| @ -31,7 +31,7 @@ ServiceContext::~ServiceContext() { | |||||||
| Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { | Kernel::KEvent* ServiceContext::CreateEvent(std::string&& name) { | ||||||
|     // Reserve a new event from the process resource limit
 |     // Reserve a new event from the process resource limit
 | ||||||
|     Kernel::KScopedResourceReservation event_reservation(process, |     Kernel::KScopedResourceReservation event_reservation(process, | ||||||
|                                                          Kernel::LimitableResource::Events); |                                                          Kernel::LimitableResource::EventCountMax); | ||||||
|     if (!event_reservation.Succeeded()) { |     if (!event_reservation.Succeeded()) { | ||||||
|         LOG_CRITICAL(Service, "Resource limit reached!"); |         LOG_CRITICAL(Service, "Resource limit reached!"); | ||||||
|         return {}; |         return {}; | ||||||
|  | |||||||
| @ -34,8 +34,8 @@ void Controller::CloneCurrentObject(Kernel::HLERequestContext& ctx) { | |||||||
|     // once this is a proper process
 |     // once this is a proper process
 | ||||||
| 
 | 
 | ||||||
|     // Reserve a new session from the process resource limit.
 |     // Reserve a new session from the process resource limit.
 | ||||||
|     Kernel::KScopedResourceReservation session_reservation(&process, |     Kernel::KScopedResourceReservation session_reservation( | ||||||
|                                                            Kernel::LimitableResource::Sessions); |         &process, Kernel::LimitableResource::SessionCountMax); | ||||||
|     ASSERT(session_reservation.Succeeded()); |     ASSERT(session_reservation.Succeeded()); | ||||||
| 
 | 
 | ||||||
|     // Create the session.
 |     // Create the session.
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user