diff --git a/src/core/core.cpp b/src/core/core.cpp
index ff07210792..d808c04178 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -150,7 +150,8 @@ struct System::Impl {
         }
 
         telemetry_session->AddInitialInfo(*app_loader);
-        auto main_process = Kernel::Process::Create(system, "main");
+        auto main_process =
+            Kernel::Process::Create(system, "main", Kernel::Process::ProcessType::Userland);
         const auto [load_result, load_parameters] = app_loader->Load(*main_process);
         if (load_result != Loader::ResultStatus::Success) {
             LOG_CRITICAL(Core, "Failed to load ROM (Error {})!", static_cast<int>(load_result));
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 757e5f21f3..799e5e0d85 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -99,7 +99,8 @@ struct KernelCore::Impl {
 
     void Shutdown() {
         next_object_id = 0;
-        next_process_id = Process::ProcessIDMin;
+        next_kernel_process_id = Process::InitialKIPIDMin;
+        next_user_process_id = Process::ProcessIDMin;
         next_thread_id = 1;
 
         process_list.clear();
@@ -132,7 +133,8 @@ struct KernelCore::Impl {
     }
 
     std::atomic<u32> next_object_id{0};
-    std::atomic<u64> next_process_id{Process::ProcessIDMin};
+    std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
+    std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
     std::atomic<u64> next_thread_id{1};
 
     // Lists all processes that exist in the current session.
@@ -226,8 +228,12 @@ u64 KernelCore::CreateNewThreadID() {
     return impl->next_thread_id++;
 }
 
-u64 KernelCore::CreateNewProcessID() {
-    return impl->next_process_id++;
+u64 KernelCore::CreateNewKernelProcessID() {
+    return impl->next_kernel_process_id++;
+}
+
+u64 KernelCore::CreateNewUserProcessID() {
+    return impl->next_user_process_id++;
 }
 
 Core::Timing::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 6b87385993..0cc44ee765 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -96,7 +96,10 @@ private:
     u32 CreateNewObjectID();
 
     /// Creates a new process ID, incrementing the internal process ID counter;
-    u64 CreateNewProcessID();
+    u64 CreateNewKernelProcessID();
+
+    /// Creates a new process ID, incrementing the internal process ID counter;
+    u64 CreateNewUserProcessID();
 
     /// Creates a new thread ID, incrementing the internal thread ID counter.
     u64 CreateNewThreadID();
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 2b81a8d4ff..7cfc513a1c 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -48,7 +48,8 @@ void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) {
 }
 } // Anonymous namespace
 
-SharedPtr<Process> Process::Create(Core::System& system, std::string name) {
+SharedPtr<Process> Process::Create(Core::System& system, std::string name,
+                                   Process::ProcessType type) {
     auto& kernel = system.Kernel();
 
     SharedPtr<Process> process(new Process(system));
@@ -56,7 +57,8 @@ SharedPtr<Process> Process::Create(Core::System& system, std::string name) {
     process->resource_limit = kernel.GetSystemResourceLimit();
     process->status = ProcessStatus::Created;
     process->program_id = 0;
-    process->process_id = kernel.CreateNewProcessID();
+    process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
+                                                              : kernel.CreateNewUserProcessID();
     process->capabilities.InitializeForMetadatalessProcess();
 
     std::mt19937 rng(Settings::values.rng_seed.value_or(0));
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 29e016983e..248fd38405 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -73,9 +73,15 @@ public:
         ProcessIDMax = 0xFFFFFFFFFFFFFFFF,
     };
 
+    // Used to determine how process IDs are assigned.
+    enum class ProcessType {
+        KernelInternal,
+        Userland,
+    };
+
     static constexpr std::size_t RANDOM_ENTROPY_SIZE = 4;
 
-    static SharedPtr<Process> Create(Core::System& system, std::string name);
+    static SharedPtr<Process> Create(Core::System& system, std::string name, ProcessType type);
 
     std::string GetTypeName() const override {
         return "Process";
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp
index 58af41f6e3..ac7ae3e520 100644
--- a/src/tests/core/arm/arm_test_common.cpp
+++ b/src/tests/core/arm/arm_test_common.cpp
@@ -16,7 +16,8 @@ namespace ArmTests {
 TestEnvironment::TestEnvironment(bool mutable_memory_)
     : mutable_memory(mutable_memory_),
       test_memory(std::make_shared<TestMemory>(this)), kernel{Core::System::GetInstance()} {
-    auto process = Kernel::Process::Create(Core::System::GetInstance(), "");
+    auto process = Kernel::Process::Create(Core::System::GetInstance(), "",
+                                           Kernel::Process::ProcessType::Userland);
     page_table = &process->VMManager().page_table;
 
     std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr);