yuzu-emu
/
yuzu-mainline
Archived
1
0
Fork 0

Merge pull request #9183 from liamwhite/svc-refresh

kernel/svc_types: refresh
This commit is contained in:
bunnei 2022-11-10 11:03:54 -08:00 committed by GitHub
commit ea41c53ab1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 562 additions and 136 deletions

View File

@ -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());

View File

@ -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(

View File

@ -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.

View File

@ -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();
} }

View File

@ -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 = {},
}; };
} }

View File

@ -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.

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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;

View File

@ -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();
} }

View File

@ -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.

View File

@ -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();
} }

View File

@ -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();
} }

View File

@ -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());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::ThreadCountMax, 800)
.IsSuccess()); .IsSuccess());
ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess()); ASSERT(system_resource_limit->SetLimitValue(LimitableResource::EventCountMax, 900)
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::TransferMemoryCountMax, 200)
system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size); .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));
} }

View File

@ -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.

View File

@ -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}", info2);
info1, info2);
break; break;
case BreakType::PostNROLoad: case BreakReason::PostLoadDll:
LOG_WARNING(Debug_Emulated, LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1,
"Signalling debugger, Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1, info2);
info2);
break; break;
case BreakType::PreNROUnload: case BreakReason::PreUnloadDll:
LOG_WARNING( LOG_INFO(Debug_Emulated,
Debug_Emulated, "Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1,
"Signalling debugger, Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info2);
info1, info2);
break; break;
case BreakType::PostNROUnload: case BreakReason::PostUnloadDll:
LOG_WARNING(Debug_Emulated, LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}",
"Signalling debugger, Unloaded an NRO at 0x{:016X} with size 0x{:016X}", info1, info1, info2);
info2);
break; break;
case BreakType::CppException: 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;
} }

View File

@ -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

View File

@ -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 {};

View File

@ -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.