diff options
22 files changed, 738 insertions, 378 deletions
| diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h index 3bb111748..a86bec252 100644 --- a/src/core/hle/ipc_helpers.h +++ b/src/core/hle/ipc_helpers.h @@ -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()); diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp index aa2dddcc6..bda098511 100644 --- a/src/core/hle/kernel/init/init_slab_setup.cpp +++ b/src/core/hle/kernel/init/init_slab_setup.cpp @@ -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( diff --git a/src/core/hle/kernel/k_client_port.cpp b/src/core/hle/kernel/k_client_port.cpp index eaa2e094c..2ec623a58 100644 --- a/src/core/hle/kernel/k_client_port.cpp +++ b/src/core/hle/kernel/k_client_port.cpp @@ -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. diff --git a/src/core/hle/kernel/k_event.cpp b/src/core/hle/kernel/k_event.cpp index 78ca59463..27f70e5c5 100644 --- a/src/core/hle/kernel/k_event.cpp +++ b/src/core/hle/kernel/k_event.cpp @@ -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();  } diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h index 6f845d675..3b6e7baff 100644 --- a/src/core/hle/kernel/k_memory_block.h +++ b/src/core/hle/kernel/k_memory_block.h @@ -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 = {},          };      } diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp index fab55a057..5387bf5fe 100644 --- a/src/core/hle/kernel/k_page_table.cpp +++ b/src/core/hle/kernel/k_page_table.cpp @@ -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. diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 4ddeea73b..55a9c5fae 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -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);      } diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp index 010dcf99e..b9d22b414 100644 --- a/src/core/hle/kernel/k_resource_limit.cpp +++ b/src/core/hle/kernel/k_resource_limit.cpp @@ -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;  } diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h index 65c98c979..2573d1b7c 100644 --- a/src/core/hle/kernel/k_resource_limit.h +++ b/src/core/hle/kernel/k_resource_limit.h @@ -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; diff --git a/src/core/hle/kernel/k_session.cpp b/src/core/hle/kernel/k_session.cpp index 7a6534ac3..b6f6fe9d9 100644 --- a/src/core/hle/kernel/k_session.cpp +++ b/src/core/hle/kernel/k_session.cpp @@ -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();  } diff --git a/src/core/hle/kernel/k_shared_memory.cpp b/src/core/hle/kernel/k_shared_memory.cpp index a039cc591..10cd4c43d 100644 --- a/src/core/hle/kernel/k_shared_memory.cpp +++ b/src/core/hle/kernel/k_shared_memory.cpp @@ -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. diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index cc88d08f0..21207fe99 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -263,9 +263,9 @@ Result KThread::InitializeThread(KThread* thread, KThreadFunction func, uintptr_      R_SUCCEED();  } -Result KThread::InitializeDummyThread(KThread* thread) { +Result KThread::InitializeDummyThread(KThread* thread, KProcess* owner) {      // Initialize the thread. -    R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, {}, ThreadType::Dummy)); +    R_TRY(thread->Initialize({}, {}, {}, DummyThreadPriority, 3, owner, ThreadType::Dummy));      // Initialize emulation parameters.      thread->stack_parameters.disable_count = 0; @@ -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();      } diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 30aa10c9a..f38c92bff 100644 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -415,7 +415,7 @@ public:      static void PostDestroy(uintptr_t arg); -    [[nodiscard]] static Result InitializeDummyThread(KThread* thread); +    [[nodiscard]] static Result InitializeDummyThread(KThread* thread, KProcess* owner);      [[nodiscard]] static Result InitializeMainThread(Core::System& system, KThread* thread,                                                       s32 virt_core); diff --git a/src/core/hle/kernel/k_transfer_memory.cpp b/src/core/hle/kernel/k_transfer_memory.cpp index b0320eb73..9f34c2d46 100644 --- a/src/core/hle/kernel/k_transfer_memory.cpp +++ b/src/core/hle/kernel/k_transfer_memory.cpp @@ -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();  } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index abff14079..b77723503 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -91,7 +91,7 @@ struct KernelCore::Impl {                                         pt_heap_region.GetSize());          } -        RegisterHostThread(); +        RegisterHostThread(nullptr);          default_service_thread = &CreateServiceThread(kernel, "DefaultServiceThread");      } @@ -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));      } @@ -373,15 +377,18 @@ struct KernelCore::Impl {      }      // Gets the dummy KThread for the caller, allocating a new one if this is the first time -    KThread* GetHostDummyThread() { +    KThread* GetHostDummyThread(KThread* existing_thread) {          auto initialize = [this](KThread* thread) { -            ASSERT(KThread::InitializeDummyThread(thread).IsSuccess()); +            ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());              thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));              return thread;          }; -        thread_local auto raw_thread = KThread(system.Kernel()); -        thread_local auto thread = initialize(&raw_thread); +        thread_local KThread raw_thread{system.Kernel()}; +        thread_local KThread* thread = nullptr; +        if (thread == nullptr) { +            thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread; +        }          return thread;      } @@ -396,9 +403,9 @@ struct KernelCore::Impl {      }      /// Registers a new host thread by allocating a host thread ID for it -    void RegisterHostThread() { +    void RegisterHostThread(KThread* existing_thread) {          [[maybe_unused]] const auto this_id = GetHostThreadId(); -        [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(); +        [[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread);      }      [[nodiscard]] u32 GetCurrentHostThreadID() { @@ -429,7 +436,7 @@ struct KernelCore::Impl {      KThread* GetCurrentEmuThread() {          const auto thread_id = GetCurrentHostThreadID();          if (thread_id >= Core::Hardware::NUM_CPU_CORES) { -            return GetHostDummyThread(); +            return GetHostDummyThread(nullptr);          }          return current_thread; @@ -1120,8 +1127,12 @@ void KernelCore::RegisterCoreThread(std::size_t core_id) {      impl->RegisterCoreThread(core_id);  } -void KernelCore::RegisterHostThread() { -    impl->RegisterHostThread(); +void KernelCore::RegisterHostThread(KThread* existing_thread) { +    impl->RegisterHostThread(existing_thread); + +    if (existing_thread != nullptr) { +        ASSERT(GetCurrentEmuThread() == existing_thread); +    }  }  u32 KernelCore::GetCurrentHostThreadID() const { @@ -1196,16 +1207,28 @@ void KernelCore::Suspend(bool suspended) {      const bool should_suspend{exception_exited || suspended};      const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable; -    for (auto* process : GetProcessList()) { -        process->SetActivity(activity); +    std::vector<KScopedAutoObject<KThread>> process_threads; +    { +        KScopedSchedulerLock sl{*this}; + +        if (auto* process = CurrentProcess(); process != nullptr) { +            process->SetActivity(activity); + +            if (!should_suspend) { +                // Runnable now; no need to wait. +                return; +            } -        if (should_suspend) { -            // Wait for execution to stop              for (auto* thread : process->GetThreadList()) { -                thread->WaitUntilSuspended(); +                process_threads.emplace_back(thread);              }          }      } + +    // Wait for execution to stop. +    for (auto& thread : process_threads) { +        thread->WaitUntilSuspended(); +    }  }  void KernelCore::ShutdownCores() { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 29617d736..2e22fe0f6 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -240,7 +240,7 @@ public:      void RegisterCoreThread(std::size_t core_id);      /// Register the current thread as a non CPU core thread. -    void RegisterHostThread(); +    void RegisterHostThread(KThread* existing_thread = nullptr);      /// Gets the virtual memory manager for the kernel.      KMemoryManager& MemoryManager(); diff --git a/src/core/hle/kernel/service_thread.cpp b/src/core/hle/kernel/service_thread.cpp index c8fe42537..f5c2ab23f 100644 --- a/src/core/hle/kernel/service_thread.cpp +++ b/src/core/hle/kernel/service_thread.cpp @@ -36,11 +36,12 @@ public:  private:      KernelCore& kernel; -    std::jthread m_thread; +    std::jthread m_host_thread;      std::mutex m_session_mutex;      std::map<KServerSession*, std::shared_ptr<SessionRequestManager>> m_sessions;      KEvent* m_wakeup_event;      KProcess* m_process; +    KThread* m_thread;      std::atomic<bool> m_shutdown_requested;      const std::string m_service_name;  }; @@ -132,7 +133,7 @@ void ServiceThread::Impl::SessionClosed(KServerSession* server_session,  void ServiceThread::Impl::LoopProcess() {      Common::SetCurrentThreadName(m_service_name.c_str()); -    kernel.RegisterHostThread(); +    kernel.RegisterHostThread(m_thread);      while (!m_shutdown_requested.load()) {          WaitAndProcessImpl(); @@ -160,7 +161,7 @@ ServiceThread::Impl::~Impl() {      // Shut down the processing thread.      m_shutdown_requested.store(true);      m_wakeup_event->Signal(); -    m_thread.join(); +    m_host_thread.join();      // Lock mutex.      m_session_mutex.lock(); @@ -177,6 +178,9 @@ ServiceThread::Impl::~Impl() {      m_wakeup_event->GetReadableEvent().Close();      m_wakeup_event->Close(); +    // Close thread. +    m_thread->Close(); +      // Close process.      m_process->Close();  } @@ -189,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. @@ -199,11 +203,19 @@ ServiceThread::Impl::Impl(KernelCore& kernel_, const std::string& service_name)      // Commit the event reservation.      event_reservation.Commit(); -    // Register the event. -    KEvent::Register(kernel, m_wakeup_event); +    // Reserve a new thread from the process resource limit +    KScopedResourceReservation thread_reservation(m_process, LimitableResource::ThreadCountMax); +    ASSERT(thread_reservation.Succeeded()); + +    // Initialize thread. +    m_thread = KThread::Create(kernel); +    ASSERT(KThread::InitializeDummyThread(m_thread, m_process).IsSuccess()); + +    // Commit the thread reservation. +    thread_reservation.Commit();      // Start thread. -    m_thread = std::jthread([this] { LoopProcess(); }); +    m_host_thread = std::jthread([this] { LoopProcess(); });  }  ServiceThread::ServiceThread(KernelCore& kernel, const std::string& name) diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index ecac97a52..9962ad171 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -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}", -                     info1, info2); +    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 BreakType::AssertionFailed: -        LOG_CRITICAL(Debug_Emulated, -                     "Signalling debugger, Assertion failed! info1=0x{:016X}, info2=0x{:016X}", +    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::PreNROLoad: -        LOG_WARNING( -            Debug_Emulated, -            "Signalling debugger, Attempting to load an NRO at 0x{:016X} with size 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::PostNROLoad: -        LOG_WARNING(Debug_Emulated, -                    "Signalling debugger, Loaded 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::PreNROUnload: -        LOG_WARNING( -            Debug_Emulated, -            "Signalling debugger, Attempting to unload 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::PostNROUnload: -        LOG_WARNING(Debug_Emulated, -                    "Signalling debugger, Unloaded 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::CppException: +    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.");          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;      } diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h index 9b0305552..33eebcef6 100644 --- a/src/core/hle/kernel/svc_types.h +++ b/src/core/hle/kernel/svc_types.h @@ -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 diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index af133af93..42991928e 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -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 {}; diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 69e0fe808..1cf9dd1c4 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp @@ -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. diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 6acfb7b06..d88efacd7 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -401,224 +401,127 @@ void GRenderWindow::closeEvent(QCloseEvent* event) {  }  int GRenderWindow::QtKeyToSwitchKey(Qt::Key qt_key) { -    switch (qt_key) { -    case Qt::Key_A: -        return Settings::NativeKeyboard::A; -    case Qt::Key_B: -        return Settings::NativeKeyboard::B; -    case Qt::Key_C: -        return Settings::NativeKeyboard::C; -    case Qt::Key_D: -        return Settings::NativeKeyboard::D; -    case Qt::Key_E: -        return Settings::NativeKeyboard::E; -    case Qt::Key_F: -        return Settings::NativeKeyboard::F; -    case Qt::Key_G: -        return Settings::NativeKeyboard::G; -    case Qt::Key_H: -        return Settings::NativeKeyboard::H; -    case Qt::Key_I: -        return Settings::NativeKeyboard::I; -    case Qt::Key_J: -        return Settings::NativeKeyboard::J; -    case Qt::Key_K: -        return Settings::NativeKeyboard::K; -    case Qt::Key_L: -        return Settings::NativeKeyboard::L; -    case Qt::Key_M: -        return Settings::NativeKeyboard::M; -    case Qt::Key_N: -        return Settings::NativeKeyboard::N; -    case Qt::Key_O: -        return Settings::NativeKeyboard::O; -    case Qt::Key_P: -        return Settings::NativeKeyboard::P; -    case Qt::Key_Q: -        return Settings::NativeKeyboard::Q; -    case Qt::Key_R: -        return Settings::NativeKeyboard::R; -    case Qt::Key_S: -        return Settings::NativeKeyboard::S; -    case Qt::Key_T: -        return Settings::NativeKeyboard::T; -    case Qt::Key_U: -        return Settings::NativeKeyboard::U; -    case Qt::Key_V: -        return Settings::NativeKeyboard::V; -    case Qt::Key_W: -        return Settings::NativeKeyboard::W; -    case Qt::Key_X: -        return Settings::NativeKeyboard::X; -    case Qt::Key_Y: -        return Settings::NativeKeyboard::Y; -    case Qt::Key_Z: -        return Settings::NativeKeyboard::Z; -    case Qt::Key_1: -        return Settings::NativeKeyboard::N1; -    case Qt::Key_2: -        return Settings::NativeKeyboard::N2; -    case Qt::Key_3: -        return Settings::NativeKeyboard::N3; -    case Qt::Key_4: -        return Settings::NativeKeyboard::N4; -    case Qt::Key_5: -        return Settings::NativeKeyboard::N5; -    case Qt::Key_6: -        return Settings::NativeKeyboard::N6; -    case Qt::Key_7: -        return Settings::NativeKeyboard::N7; -    case Qt::Key_8: -        return Settings::NativeKeyboard::N8; -    case Qt::Key_9: -        return Settings::NativeKeyboard::N9; -    case Qt::Key_0: -        return Settings::NativeKeyboard::N0; -    case Qt::Key_Return: -        return Settings::NativeKeyboard::Return; -    case Qt::Key_Escape: -        return Settings::NativeKeyboard::Escape; -    case Qt::Key_Backspace: -        return Settings::NativeKeyboard::Backspace; -    case Qt::Key_Tab: -        return Settings::NativeKeyboard::Tab; -    case Qt::Key_Space: -        return Settings::NativeKeyboard::Space; -    case Qt::Key_Minus: -        return Settings::NativeKeyboard::Minus; -    case Qt::Key_Plus: -    case Qt::Key_questiondown: -        return Settings::NativeKeyboard::Plus; -    case Qt::Key_BracketLeft: -    case Qt::Key_BraceLeft: -        return Settings::NativeKeyboard::OpenBracket; -    case Qt::Key_BracketRight: -    case Qt::Key_BraceRight: -        return Settings::NativeKeyboard::CloseBracket; -    case Qt::Key_Bar: -        return Settings::NativeKeyboard::Pipe; -    case Qt::Key_Dead_Tilde: -        return Settings::NativeKeyboard::Tilde; -    case Qt::Key_Ntilde: -    case Qt::Key_Semicolon: -        return Settings::NativeKeyboard::Semicolon; -    case Qt::Key_Apostrophe: -        return Settings::NativeKeyboard::Quote; -    case Qt::Key_Dead_Grave: -        return Settings::NativeKeyboard::Backquote; -    case Qt::Key_Comma: -        return Settings::NativeKeyboard::Comma; -    case Qt::Key_Period: -        return Settings::NativeKeyboard::Period; -    case Qt::Key_Slash: -        return Settings::NativeKeyboard::Slash; -    case Qt::Key_CapsLock: -        return Settings::NativeKeyboard::CapsLock; -    case Qt::Key_F1: -        return Settings::NativeKeyboard::F1; -    case Qt::Key_F2: -        return Settings::NativeKeyboard::F2; -    case Qt::Key_F3: -        return Settings::NativeKeyboard::F3; -    case Qt::Key_F4: -        return Settings::NativeKeyboard::F4; -    case Qt::Key_F5: -        return Settings::NativeKeyboard::F5; -    case Qt::Key_F6: -        return Settings::NativeKeyboard::F6; -    case Qt::Key_F7: -        return Settings::NativeKeyboard::F7; -    case Qt::Key_F8: -        return Settings::NativeKeyboard::F8; -    case Qt::Key_F9: -        return Settings::NativeKeyboard::F9; -    case Qt::Key_F10: -        return Settings::NativeKeyboard::F10; -    case Qt::Key_F11: -        return Settings::NativeKeyboard::F11; -    case Qt::Key_F12: -        return Settings::NativeKeyboard::F12; -    case Qt::Key_Print: -        return Settings::NativeKeyboard::PrintScreen; -    case Qt::Key_ScrollLock: -        return Settings::NativeKeyboard::ScrollLock; -    case Qt::Key_Pause: -        return Settings::NativeKeyboard::Pause; -    case Qt::Key_Insert: -        return Settings::NativeKeyboard::Insert; -    case Qt::Key_Home: -        return Settings::NativeKeyboard::Home; -    case Qt::Key_PageUp: -        return Settings::NativeKeyboard::PageUp; -    case Qt::Key_Delete: -        return Settings::NativeKeyboard::Delete; -    case Qt::Key_End: -        return Settings::NativeKeyboard::End; -    case Qt::Key_PageDown: -        return Settings::NativeKeyboard::PageDown; -    case Qt::Key_Right: -        return Settings::NativeKeyboard::Right; -    case Qt::Key_Left: -        return Settings::NativeKeyboard::Left; -    case Qt::Key_Down: -        return Settings::NativeKeyboard::Down; -    case Qt::Key_Up: -        return Settings::NativeKeyboard::Up; -    case Qt::Key_NumLock: -        return Settings::NativeKeyboard::NumLock; -    // Numpad keys are missing here -    case Qt::Key_F13: -        return Settings::NativeKeyboard::F13; -    case Qt::Key_F14: -        return Settings::NativeKeyboard::F14; -    case Qt::Key_F15: -        return Settings::NativeKeyboard::F15; -    case Qt::Key_F16: -        return Settings::NativeKeyboard::F16; -    case Qt::Key_F17: -        return Settings::NativeKeyboard::F17; -    case Qt::Key_F18: -        return Settings::NativeKeyboard::F18; -    case Qt::Key_F19: -        return Settings::NativeKeyboard::F19; -    case Qt::Key_F20: -        return Settings::NativeKeyboard::F20; -    case Qt::Key_F21: -        return Settings::NativeKeyboard::F21; -    case Qt::Key_F22: -        return Settings::NativeKeyboard::F22; -    case Qt::Key_F23: -        return Settings::NativeKeyboard::F23; -    case Qt::Key_F24: -        return Settings::NativeKeyboard::F24; -    // case Qt::: -    //    return Settings::NativeKeyboard::KPComma; -    // case Qt::: -    //    return Settings::NativeKeyboard::Ro; -    case Qt::Key_Hiragana_Katakana: -        return Settings::NativeKeyboard::KatakanaHiragana; -    case Qt::Key_yen: -        return Settings::NativeKeyboard::Yen; -    case Qt::Key_Henkan: -        return Settings::NativeKeyboard::Henkan; -    case Qt::Key_Muhenkan: -        return Settings::NativeKeyboard::Muhenkan; -    // case Qt::: -    //    return Settings::NativeKeyboard::NumPadCommaPc98; -    case Qt::Key_Hangul: -        return Settings::NativeKeyboard::HangulEnglish; -    case Qt::Key_Hangul_Hanja: -        return Settings::NativeKeyboard::Hanja; -    case Qt::Key_Katakana: -        return Settings::NativeKeyboard::KatakanaKey; -    case Qt::Key_Hiragana: -        return Settings::NativeKeyboard::HiraganaKey; -    case Qt::Key_Zenkaku_Hankaku: -        return Settings::NativeKeyboard::ZenkakuHankaku; -    // Modifier keys are handled by the modifier property -    default: -        return Settings::NativeKeyboard::None; +    static constexpr std::array<std::pair<Qt::Key, Settings::NativeKeyboard::Keys>, 106> key_map = { +        std::pair<Qt::Key, Settings::NativeKeyboard::Keys>{Qt::Key_A, Settings::NativeKeyboard::A}, +        {Qt::Key_A, Settings::NativeKeyboard::A}, +        {Qt::Key_B, Settings::NativeKeyboard::B}, +        {Qt::Key_C, Settings::NativeKeyboard::C}, +        {Qt::Key_D, Settings::NativeKeyboard::D}, +        {Qt::Key_E, Settings::NativeKeyboard::E}, +        {Qt::Key_F, Settings::NativeKeyboard::F}, +        {Qt::Key_G, Settings::NativeKeyboard::G}, +        {Qt::Key_H, Settings::NativeKeyboard::H}, +        {Qt::Key_I, Settings::NativeKeyboard::I}, +        {Qt::Key_J, Settings::NativeKeyboard::J}, +        {Qt::Key_K, Settings::NativeKeyboard::K}, +        {Qt::Key_L, Settings::NativeKeyboard::L}, +        {Qt::Key_M, Settings::NativeKeyboard::M}, +        {Qt::Key_N, Settings::NativeKeyboard::N}, +        {Qt::Key_O, Settings::NativeKeyboard::O}, +        {Qt::Key_P, Settings::NativeKeyboard::P}, +        {Qt::Key_Q, Settings::NativeKeyboard::Q}, +        {Qt::Key_R, Settings::NativeKeyboard::R}, +        {Qt::Key_S, Settings::NativeKeyboard::S}, +        {Qt::Key_T, Settings::NativeKeyboard::T}, +        {Qt::Key_U, Settings::NativeKeyboard::U}, +        {Qt::Key_V, Settings::NativeKeyboard::V}, +        {Qt::Key_W, Settings::NativeKeyboard::W}, +        {Qt::Key_X, Settings::NativeKeyboard::X}, +        {Qt::Key_Y, Settings::NativeKeyboard::Y}, +        {Qt::Key_Z, Settings::NativeKeyboard::Z}, +        {Qt::Key_1, Settings::NativeKeyboard::N1}, +        {Qt::Key_2, Settings::NativeKeyboard::N2}, +        {Qt::Key_3, Settings::NativeKeyboard::N3}, +        {Qt::Key_4, Settings::NativeKeyboard::N4}, +        {Qt::Key_5, Settings::NativeKeyboard::N5}, +        {Qt::Key_6, Settings::NativeKeyboard::N6}, +        {Qt::Key_7, Settings::NativeKeyboard::N7}, +        {Qt::Key_8, Settings::NativeKeyboard::N8}, +        {Qt::Key_9, Settings::NativeKeyboard::N9}, +        {Qt::Key_0, Settings::NativeKeyboard::N0}, +        {Qt::Key_Return, Settings::NativeKeyboard::Return}, +        {Qt::Key_Escape, Settings::NativeKeyboard::Escape}, +        {Qt::Key_Backspace, Settings::NativeKeyboard::Backspace}, +        {Qt::Key_Tab, Settings::NativeKeyboard::Tab}, +        {Qt::Key_Space, Settings::NativeKeyboard::Space}, +        {Qt::Key_Minus, Settings::NativeKeyboard::Minus}, +        {Qt::Key_Plus, Settings::NativeKeyboard::Plus}, +        {Qt::Key_questiondown, Settings::NativeKeyboard::Plus}, +        {Qt::Key_BracketLeft, Settings::NativeKeyboard::OpenBracket}, +        {Qt::Key_BraceLeft, Settings::NativeKeyboard::OpenBracket}, +        {Qt::Key_BracketRight, Settings::NativeKeyboard::CloseBracket}, +        {Qt::Key_BraceRight, Settings::NativeKeyboard::CloseBracket}, +        {Qt::Key_Bar, Settings::NativeKeyboard::Pipe}, +        {Qt::Key_Dead_Tilde, Settings::NativeKeyboard::Tilde}, +        {Qt::Key_Ntilde, Settings::NativeKeyboard::Semicolon}, +        {Qt::Key_Semicolon, Settings::NativeKeyboard::Semicolon}, +        {Qt::Key_Apostrophe, Settings::NativeKeyboard::Quote}, +        {Qt::Key_Dead_Grave, Settings::NativeKeyboard::Backquote}, +        {Qt::Key_Comma, Settings::NativeKeyboard::Comma}, +        {Qt::Key_Period, Settings::NativeKeyboard::Period}, +        {Qt::Key_Slash, Settings::NativeKeyboard::Slash}, +        {Qt::Key_CapsLock, Settings::NativeKeyboard::CapsLockKey}, +        {Qt::Key_F1, Settings::NativeKeyboard::F1}, +        {Qt::Key_F2, Settings::NativeKeyboard::F2}, +        {Qt::Key_F3, Settings::NativeKeyboard::F3}, +        {Qt::Key_F4, Settings::NativeKeyboard::F4}, +        {Qt::Key_F5, Settings::NativeKeyboard::F5}, +        {Qt::Key_F6, Settings::NativeKeyboard::F6}, +        {Qt::Key_F7, Settings::NativeKeyboard::F7}, +        {Qt::Key_F8, Settings::NativeKeyboard::F8}, +        {Qt::Key_F9, Settings::NativeKeyboard::F9}, +        {Qt::Key_F10, Settings::NativeKeyboard::F10}, +        {Qt::Key_F11, Settings::NativeKeyboard::F11}, +        {Qt::Key_F12, Settings::NativeKeyboard::F12}, +        {Qt::Key_Print, Settings::NativeKeyboard::PrintScreen}, +        {Qt::Key_ScrollLock, Settings::NativeKeyboard::ScrollLockKey}, +        {Qt::Key_Pause, Settings::NativeKeyboard::Pause}, +        {Qt::Key_Insert, Settings::NativeKeyboard::Insert}, +        {Qt::Key_Home, Settings::NativeKeyboard::Home}, +        {Qt::Key_PageUp, Settings::NativeKeyboard::PageUp}, +        {Qt::Key_Delete, Settings::NativeKeyboard::Delete}, +        {Qt::Key_End, Settings::NativeKeyboard::End}, +        {Qt::Key_PageDown, Settings::NativeKeyboard::PageDown}, +        {Qt::Key_Right, Settings::NativeKeyboard::Right}, +        {Qt::Key_Left, Settings::NativeKeyboard::Left}, +        {Qt::Key_Down, Settings::NativeKeyboard::Down}, +        {Qt::Key_Up, Settings::NativeKeyboard::Up}, +        {Qt::Key_NumLock, Settings::NativeKeyboard::NumLockKey}, +        // Numpad keys are missing here +        {Qt::Key_F13, Settings::NativeKeyboard::F13}, +        {Qt::Key_F14, Settings::NativeKeyboard::F14}, +        {Qt::Key_F15, Settings::NativeKeyboard::F15}, +        {Qt::Key_F16, Settings::NativeKeyboard::F16}, +        {Qt::Key_F17, Settings::NativeKeyboard::F17}, +        {Qt::Key_F18, Settings::NativeKeyboard::F18}, +        {Qt::Key_F19, Settings::NativeKeyboard::F19}, +        {Qt::Key_F20, Settings::NativeKeyboard::F20}, +        {Qt::Key_F21, Settings::NativeKeyboard::F21}, +        {Qt::Key_F22, Settings::NativeKeyboard::F22}, +        {Qt::Key_F23, Settings::NativeKeyboard::F23}, +        {Qt::Key_F24, Settings::NativeKeyboard::F24}, +        // {Qt::..., Settings::NativeKeyboard::KPComma}, +        // {Qt::..., Settings::NativeKeyboard::Ro}, +        {Qt::Key_Hiragana_Katakana, Settings::NativeKeyboard::KatakanaHiragana}, +        {Qt::Key_yen, Settings::NativeKeyboard::Yen}, +        {Qt::Key_Henkan, Settings::NativeKeyboard::Henkan}, +        {Qt::Key_Muhenkan, Settings::NativeKeyboard::Muhenkan}, +        // {Qt::..., Settings::NativeKeyboard::NumPadCommaPc98}, +        {Qt::Key_Hangul, Settings::NativeKeyboard::HangulEnglish}, +        {Qt::Key_Hangul_Hanja, Settings::NativeKeyboard::Hanja}, +        {Qt::Key_Katakana, Settings::NativeKeyboard::KatakanaKey}, +        {Qt::Key_Hiragana, Settings::NativeKeyboard::HiraganaKey}, +        {Qt::Key_Zenkaku_Hankaku, Settings::NativeKeyboard::ZenkakuHankaku}, +        // Modifier keys are handled by the modifier property +    }; + +    for (const auto& [qkey, nkey] : key_map) { +        if (qt_key == qkey) { +            return nkey; +        }      } + +    return Settings::NativeKeyboard::None;  }  int GRenderWindow::QtModifierToSwitchModifier(Qt::KeyboardModifiers qt_modifiers) { | 
