summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp13
-rw-r--r--src/core/hle/kernel/k_resource_limit.h12
-rw-r--r--src/core/hle/kernel/kernel.cpp44
-rw-r--r--src/core/hle/kernel/process.cpp26
-rw-r--r--src/core/hle/kernel/svc.cpp2
5 files changed, 39 insertions, 58 deletions
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index d7a4a38e6..d05b34ea3 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -2,21 +2,16 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
#include "common/assert.h"
-#include "core/core.h"
#include "core/core_timing.h"
-#include "core/core_timing_util.h"
#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
constexpr s64 DefaultTimeout = 10000000000; // 10 seconds
-KResourceLimit::KResourceLimit(KernelCore& kernel, Core::System& system)
- : Object{kernel}, lock{kernel}, cond_var{kernel}, kernel{kernel}, system(system) {}
+KResourceLimit::KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_)
+ : Object{kernel}, lock{kernel}, cond_var{kernel}, core_timing(core_timing_) {}
KResourceLimit::~KResourceLimit() = default;
s64 KResourceLimit::GetLimitValue(LimitableResource which) const {
@@ -83,7 +78,7 @@ ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
}
bool KResourceLimit::Reserve(LimitableResource which, s64 value) {
- return Reserve(which, value, system.CoreTiming().GetGlobalTimeNs().count() + DefaultTimeout);
+ return Reserve(which, value, core_timing.GetGlobalTimeNs().count() + DefaultTimeout);
}
bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
@@ -114,7 +109,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
}
if (current_hints[index] + value <= limit_values[index] &&
- (timeout < 0 || system.CoreTiming().GetGlobalTimeNs().count() < timeout)) {
+ (timeout < 0 || core_timing.GetGlobalTimeNs().count() < timeout)) {
waiter_count++;
cond_var.Wait(&lock, timeout);
waiter_count--;
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 58ae456f1..4542317d0 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -2,9 +2,6 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
-// This file references various implementation details from Atmosphere, an open-source firmware for
-// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
-
#pragma once
#include <array>
@@ -15,8 +12,8 @@
union ResultCode;
-namespace Core {
-class System;
+namespace Core::Timing {
+class CoreTiming;
}
namespace Kernel {
@@ -37,7 +34,7 @@ constexpr bool IsValidResourceType(LimitableResource type) {
class KResourceLimit final : public Object {
public:
- explicit KResourceLimit(KernelCore& kernel, Core::System& system);
+ explicit KResourceLimit(KernelCore& kernel, const Core::Timing::CoreTiming& core_timing_);
~KResourceLimit();
s64 GetLimitValue(LimitableResource which) const;
@@ -75,7 +72,6 @@ private:
mutable KLightLock lock;
s32 waiter_count{};
KLightConditionVariable cond_var;
- KernelCore& kernel;
- Core::System& system;
+ const Core::Timing::CoreTiming& core_timing;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8fd990577..5c4f45ab4 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -67,8 +67,13 @@ struct KernelCore::Impl {
is_phantom_mode_for_singlecore = false;
InitializePhysicalCores();
- InitializeSystemResourceLimit(kernel, system);
- InitializeMemoryLayout();
+
+ // Derive the initial memory layout from the emulated board
+ KMemoryLayout memory_layout;
+ DeriveInitialMemoryLayout(memory_layout);
+ InitializeMemoryLayout(memory_layout);
+ InitializeSystemResourceLimit(kernel, system.CoreTiming(), memory_layout);
+ InitializeSlabHeaps();
InitializeSchedulers();
InitializeSuspendThreads();
InitializePreemption(kernel);
@@ -137,27 +142,33 @@ struct KernelCore::Impl {
}
// Creates the default system resource limit
- void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
- system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ void InitializeSystemResourceLimit(KernelCore& kernel,
+ const Core::Timing::CoreTiming& core_timing,
+ const KMemoryLayout& memory_layout) {
+ system_resource_limit = std::make_shared<KResourceLimit>(kernel, core_timing);
+ const auto [total_size, kernel_size] = memory_layout.GetTotalAndKernelMemorySizes();
// If setting the default system values fails, then something seriously wrong has occurred.
- ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, total_size)
.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)
.IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 1133).IsSuccess());
+ system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size);
- // Derived from recent software updates. The kernel reserves 27MB
- constexpr u64 kernel_size{0x1b00000};
- if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) {
- UNREACHABLE();
- }
// Reserve secure applet memory, introduced in firmware 5.0.0
- constexpr u64 secure_applet_memory_size{0x400000};
+ constexpr u64 secure_applet_memory_size{Common::Size_4_MB};
ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
secure_applet_memory_size));
+
+ // This memory seems to be reserved on hardware, but is not reserved/used by yuzu.
+ // Likely Horizon OS reserved memory
+ // TODO(ameerj): Derive the memory rather than hardcode it.
+ constexpr u64 unknown_reserved_memory{0x2f896000};
+ ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
+ unknown_reserved_memory));
}
void InitializePreemption(KernelCore& kernel) {
@@ -531,11 +542,7 @@ struct KernelCore::Impl {
linear_region_start);
}
- void InitializeMemoryLayout() {
- // Derive the initial memory layout from the emulated board
- KMemoryLayout memory_layout;
- DeriveInitialMemoryLayout(memory_layout);
-
+ void InitializeMemoryLayout(const KMemoryLayout& memory_layout) {
const auto system_pool = memory_layout.GetKernelSystemPoolRegionPhysicalExtents();
const auto applet_pool = memory_layout.GetKernelAppletPoolRegionPhysicalExtents();
const auto application_pool = memory_layout.GetKernelApplicationPoolRegionPhysicalExtents();
@@ -578,11 +585,14 @@ struct KernelCore::Impl {
system.Kernel(), system.DeviceMemory(), nullptr, {time_phys_addr, time_size / PageSize},
KMemoryPermission::None, KMemoryPermission::Read, time_phys_addr, time_size,
"Time:SharedMemory");
+ }
+ void InitializeSlabHeaps() {
// Allocate slab heaps
user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
- constexpr u64 user_slab_heap_size{0x1ef000};
+ // TODO(ameerj): This should be derived, not hardcoded within the kernel
+ constexpr u64 user_slab_heap_size{0x3de000};
// Reserve slab heaps
ASSERT(
system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 9d5956ead..e35deb8e2 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -10,6 +10,7 @@
#include "common/alignment.h"
#include "common/assert.h"
#include "common/logging/log.h"
+#include "common/settings.h"
#include "core/core.h"
#include "core/device_memory.h"
#include "core/file_sys/program_metadata.h"
@@ -26,7 +27,6 @@
#include "core/hle/kernel/svc_results.h"
#include "core/hle/lock.h"
#include "core/memory.h"
-#include "core/settings.h"
namespace Kernel {
namespace {
@@ -120,9 +120,7 @@ std::shared_ptr<Process> Process::Create(Core::System& system, std::string name,
std::shared_ptr<Process> process = std::make_shared<Process>(system);
process->name = std::move(name);
- // TODO: This is inaccurate
- // The process should hold a reference to the kernel-wide resource limit.
- process->resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ process->resource_limit = kernel.GetSystemResourceLimit();
process->status = ProcessStatus::Created;
process->program_id = 0;
process->process_id = type == ProcessType::KernelInternal ? kernel.CreateNewKernelProcessID()
@@ -160,17 +158,13 @@ void Process::DecrementThreadCount() {
}
u64 Process::GetTotalPhysicalMemoryAvailable() const {
- // TODO: This is expected to always return the application memory pool size after accurately
- // reserving kernel resources. The current workaround uses a process-local resource limit of
- // application memory pool size, which is inaccurate.
const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size +
main_thread_stack_size};
-
+ ASSERT(capacity == kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
if (capacity < memory_usage_capacity) {
return capacity;
}
-
return memory_usage_capacity;
}
@@ -272,10 +266,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
system_resource_size = metadata.GetSystemResourceSize();
image_size = code_size;
- // Set initial resource limits
- resource_limit->SetLimitValue(
- LimitableResource::PhysicalMemory,
- kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
KScopedResourceReservation memory_reservation(resource_limit, LimitableResource::PhysicalMemory,
code_size + system_resource_size);
if (!memory_reservation.Succeeded()) {
@@ -324,16 +314,6 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
UNREACHABLE();
}
- // Set initial resource limits
- resource_limit->SetLimitValue(
- LimitableResource::PhysicalMemory,
- kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application));
-
- resource_limit->SetLimitValue(LimitableResource::Threads, 608);
- resource_limit->SetLimitValue(LimitableResource::Events, 700);
- resource_limit->SetLimitValue(LimitableResource::TransferMemory, 128);
- resource_limit->SetLimitValue(LimitableResource::Sessions, 894);
-
// Create TLS region
tls_region_address = CreateTLSRegion();
memory_reservation.Commit();
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index fcffc746d..bebb86154 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -2156,7 +2156,7 @@ static ResultCode CreateResourceLimit(Core::System& system, Handle* out_handle)
LOG_DEBUG(Kernel_SVC, "called");
auto& kernel = system.Kernel();
- auto resource_limit = std::make_shared<KResourceLimit>(kernel, system);
+ auto resource_limit = std::make_shared<KResourceLimit>(kernel, system.CoreTiming());
auto* const current_process = kernel.CurrentProcess();
ASSERT(current_process != nullptr);