early-access version 3103
This commit is contained in:
parent
881a47bdc4
commit
4876ef3fba
21 changed files with 564 additions and 138 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3102.
|
This is the source code for early-access 3103.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -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…
Reference in a new issue