general: properly support multiple memory instances

This commit is contained in:
Liam 2023-12-17 20:46:41 -05:00
parent cae675343c
commit 31bf57a310
17 changed files with 102 additions and 102 deletions

View File

@ -166,6 +166,10 @@ u32 ProgramMetadata::GetSystemResourceSize() const {
return npdm_header.system_resource_size; return npdm_header.system_resource_size;
} }
PoolPartition ProgramMetadata::GetPoolPartition() const {
return acid_header.pool_partition;
}
const ProgramMetadata::KernelCapabilityDescriptors& ProgramMetadata::GetKernelCapabilities() const { const ProgramMetadata::KernelCapabilityDescriptors& ProgramMetadata::GetKernelCapabilities() const {
return aci_kernel_capabilities; return aci_kernel_capabilities;
} }
@ -201,7 +205,7 @@ void ProgramMetadata::Print() const {
// Begin ACID printing (potential perms, signed) // Begin ACID printing (potential perms, signed)
LOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data()); LOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", acid_header.flags); LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", acid_header.flags);
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO"); LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.production_flag ? "YES" : "NO");
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min); LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max); LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions); LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);

View File

@ -34,6 +34,13 @@ enum class ProgramFilePermission : u64 {
Everything = 1ULL << 63, Everything = 1ULL << 63,
}; };
enum class PoolPartition : u32 {
Application = 0,
Applet = 1,
System = 2,
SystemNonSecure = 3,
};
/** /**
* Helper which implements an interface to parse Program Description Metadata (NPDM) * Helper which implements an interface to parse Program Description Metadata (NPDM)
* Data can either be loaded from a file path or with data and an offset into it. * Data can either be loaded from a file path or with data and an offset into it.
@ -72,6 +79,7 @@ public:
u64 GetTitleID() const; u64 GetTitleID() const;
u64 GetFilesystemPermissions() const; u64 GetFilesystemPermissions() const;
u32 GetSystemResourceSize() const; u32 GetSystemResourceSize() const;
PoolPartition GetPoolPartition() const;
const KernelCapabilityDescriptors& GetKernelCapabilities() const; const KernelCapabilityDescriptors& GetKernelCapabilities() const;
const std::array<u8, 0x10>& GetName() const { const std::array<u8, 0x10>& GetName() const {
return npdm_header.application_name; return npdm_header.application_name;
@ -116,8 +124,9 @@ private:
union { union {
u32 flags; u32 flags;
BitField<0, 1, u32> is_retail; BitField<0, 1, u32> production_flag;
BitField<1, 31, u32> flags_unk; BitField<1, 1, u32> unqualified_approval;
BitField<2, 4, PoolPartition> pool_partition;
}; };
u64_le title_id_min; u64_le title_id_min;
u64_le title_id_max; u64_le title_id_max;

View File

@ -58,9 +58,8 @@ Result KClientPort::CreateSession(KClientSession** out) {
KSession* session{}; KSession* session{};
// Reserve a new session from the resource limit. // Reserve a new session from the resource limit.
//! FIXME: we are reserving this from the wrong resource limit!
KScopedResourceReservation session_reservation( KScopedResourceReservation session_reservation(
m_kernel.ApplicationProcess()->GetResourceLimit(), LimitableResource::SessionCountMax); GetCurrentProcessPointer(m_kernel)->GetResourceLimit(), LimitableResource::SessionCountMax);
R_UNLESS(session_reservation.Succeeded(), ResultLimitReached); R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);
// Allocate a session normally. // Allocate a session normally.

View File

@ -30,7 +30,7 @@ public:
public: public:
explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {} explicit KHandleTable(KernelCore& kernel) : m_kernel(kernel) {}
Result Initialize(s32 size) { Result Initialize(KProcess* owner, s32 size) {
// Check that the table size is valid. // Check that the table size is valid.
R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory); R_UNLESS(size <= static_cast<s32>(MaxTableSize), ResultOutOfMemory);
@ -44,6 +44,7 @@ public:
m_next_linear_id = MinLinearId; m_next_linear_id = MinLinearId;
m_count = 0; m_count = 0;
m_free_head_index = -1; m_free_head_index = -1;
m_owner = owner;
// Free all entries. // Free all entries.
for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) { for (s32 i = 0; i < static_cast<s32>(m_table_size); ++i) {
@ -90,8 +91,8 @@ public:
// Handle pseudo-handles. // Handle pseudo-handles.
if constexpr (std::derived_from<KProcess, T>) { if constexpr (std::derived_from<KProcess, T>) {
if (handle == Svc::PseudoHandle::CurrentProcess) { if (handle == Svc::PseudoHandle::CurrentProcess) {
//! FIXME: this is the wrong process! // TODO: this should be the current process
auto* const cur_process = m_kernel.ApplicationProcess(); auto* const cur_process = m_owner;
ASSERT(cur_process != nullptr); ASSERT(cur_process != nullptr);
return cur_process; return cur_process;
} }
@ -301,6 +302,7 @@ private:
private: private:
KernelCore& m_kernel; KernelCore& m_kernel;
KProcess* m_owner{};
std::array<EntryInfo, MaxTableSize> m_entry_infos{}; std::array<EntryInfo, MaxTableSize> m_entry_infos{};
std::array<KAutoObject*, MaxTableSize> m_objects{}; std::array<KAutoObject*, MaxTableSize> m_objects{};
mutable KSpinLock m_lock; mutable KSpinLock m_lock;

View File

@ -306,12 +306,16 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params, const KPa
False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool,
params.code_address, params.code_num_pages * PageSize, params.code_address, params.code_num_pages * PageSize,
m_system_resource, res_limit, this->GetMemory(), 0)); m_system_resource, res_limit, m_memory, 0));
} }
ON_RESULT_FAILURE_2 { ON_RESULT_FAILURE_2 {
m_page_table.Finalize(); m_page_table.Finalize();
}; };
// Ensure our memory is initialized.
m_memory.SetCurrentPageTable(*this);
m_memory.SetGPUDirtyManagers(m_dirty_memory_managers);
// Ensure we can insert the code region. // Ensure we can insert the code region.
R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize, R_UNLESS(m_page_table.CanContain(params.code_address, params.code_num_pages * PageSize,
KMemoryState::Code), KMemoryState::Code),
@ -399,12 +403,16 @@ Result KProcess::Initialize(const Svc::CreateProcessParameter& params,
False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge); False(params.flags & Svc::CreateProcessFlag::DisableDeviceAddressSpaceMerge);
R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool, R_TRY(m_page_table.Initialize(as_type, enable_aslr, enable_das_merge, !enable_aslr, pool,
params.code_address, code_size, m_system_resource, res_limit, params.code_address, code_size, m_system_resource, res_limit,
this->GetMemory(), aslr_space_start)); m_memory, aslr_space_start));
} }
ON_RESULT_FAILURE_2 { ON_RESULT_FAILURE_2 {
m_page_table.Finalize(); m_page_table.Finalize();
}; };
// Ensure our memory is initialized.
m_memory.SetCurrentPageTable(*this);
m_memory.SetGPUDirtyManagers(m_dirty_memory_managers);
// Ensure we can insert the code region. // Ensure we can insert the code region.
R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code), R_UNLESS(m_page_table.CanContain(params.code_address, code_size, KMemoryState::Code),
ResultInvalidMemoryRegion); ResultInvalidMemoryRegion);
@ -1094,8 +1102,7 @@ void KProcess::UnpinThread(KThread* thread) {
Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids, Result KProcess::GetThreadList(s32* out_num_threads, KProcessAddress out_thread_ids,
s32 max_out_count) { s32 max_out_count) {
// TODO: use current memory reference auto& memory = this->GetMemory();
auto& memory = m_kernel.System().ApplicationMemory();
// Lock the list. // Lock the list.
KScopedLightLock lk(m_list_lock); KScopedLightLock lk(m_list_lock);
@ -1128,15 +1135,15 @@ void KProcess::Switch(KProcess* cur_process, KProcess* next_process) {}
KProcess::KProcess(KernelCore& kernel) KProcess::KProcess(KernelCore& kernel)
: KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel}, : KAutoObjectWithSlabHeapAndContainer(kernel), m_page_table{kernel}, m_state_lock{kernel},
m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()}, m_list_lock{kernel}, m_cond_var{kernel.System()}, m_address_arbiter{kernel.System()},
m_handle_table{kernel}, m_dirty_memory_managers{}, m_exclusive_monitor{}, m_handle_table{kernel}, m_dirty_memory_managers{},
m_memory{kernel.System()} {} m_exclusive_monitor{}, m_memory{kernel.System()} {}
KProcess::~KProcess() = default; KProcess::~KProcess() = default;
Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size, Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std::size_t code_size,
KProcessAddress aslr_space_start, bool is_hbl) { KProcessAddress aslr_space_start, bool is_hbl) {
// Create a resource limit for the process. // Create a resource limit for the process.
const auto physical_memory_size = const auto pool = static_cast<KMemoryManager::Pool>(metadata.GetPoolPartition());
m_kernel.MemoryManager().GetSize(Kernel::KMemoryManager::Pool::Application); const auto physical_memory_size = m_kernel.MemoryManager().GetSize(pool);
auto* res_limit = auto* res_limit =
Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size); Kernel::CreateResourceLimitForProcess(m_kernel.System(), physical_memory_size);
@ -1147,8 +1154,10 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
Svc::CreateProcessFlag flag{}; Svc::CreateProcessFlag flag{};
u64 code_address{}; u64 code_address{};
// We are an application. // Determine if we are an application.
flag |= Svc::CreateProcessFlag::IsApplication; if (pool == KMemoryManager::Pool::Application) {
flag |= Svc::CreateProcessFlag::IsApplication;
}
// If we are 64-bit, create as such. // If we are 64-bit, create as such.
if (metadata.Is64BitProgram()) { if (metadata.Is64BitProgram()) {
@ -1197,8 +1206,8 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
std::memcpy(params.name.data(), name.data(), sizeof(params.name)); std::memcpy(params.name.data(), name.data(), sizeof(params.name));
// Initialize for application process. // Initialize for application process.
R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, R_TRY(this->Initialize(params, metadata.GetKernelCapabilities(), res_limit, pool,
KMemoryManager::Pool::Application, aslr_space_start)); aslr_space_start));
// Assign remaining properties. // Assign remaining properties.
m_is_hbl = is_hbl; m_is_hbl = is_hbl;
@ -1239,9 +1248,6 @@ void KProcess::InitializeInterfaces() {
m_exclusive_monitor = m_exclusive_monitor =
Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES); Core::MakeExclusiveMonitor(this->GetMemory(), Core::Hardware::NUM_CPU_CORES);
this->GetMemory().SetCurrentPageTable(*this);
this->GetMemory().SetGPUDirtyManagers(m_dirty_memory_managers);
#ifdef HAS_NCE #ifdef HAS_NCE
if (this->Is64Bit() && Settings::IsNceEnabled()) { if (this->Is64Bit() && Settings::IsNceEnabled()) {
for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {

View File

@ -552,7 +552,7 @@ private:
Result InitializeHandleTable(s32 size) { Result InitializeHandleTable(s32 size) {
// Try to initialize the handle table. // Try to initialize the handle table.
R_TRY(m_handle_table.Initialize(size)); R_TRY(m_handle_table.Initialize(this, size));
// We succeeded, so note that we did. // We succeeded, so note that we did.
m_is_handle_table_initialized = true; m_is_handle_table_initialized = true;

View File

@ -33,8 +33,7 @@ void KSession::Initialize(KClientPort* client_port, uintptr_t name) {
m_name = name; m_name = name;
// Set our owner process. // Set our owner process.
//! FIXME: this is the wrong process! m_process = GetCurrentProcessPointer(m_kernel);
m_process = m_kernel.ApplicationProcess();
m_process->Open(); m_process->Open();
// Set our port. // Set our port.

View File

@ -1422,8 +1422,7 @@ s32 GetCurrentCoreId(KernelCore& kernel) {
} }
Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel) { Core::Memory::Memory& GetCurrentMemory(KernelCore& kernel) {
// TODO: per-process memory return GetCurrentProcess(kernel).GetMemory();
return kernel.System().ApplicationMemory();
} }
KScopedDisableDispatch::~KScopedDisableDispatch() { KScopedDisableDispatch::~KScopedDisableDispatch() {

View File

@ -68,8 +68,6 @@ struct KernelCore::Impl {
global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel); global_object_list_container = std::make_unique<KAutoObjectWithListContainer>(kernel);
global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel); global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
global_handle_table = std::make_unique<Kernel::KHandleTable>(kernel);
global_handle_table->Initialize(KHandleTable::MaxTableSize);
is_phantom_mode_for_singlecore = false; is_phantom_mode_for_singlecore = false;
@ -121,9 +119,6 @@ struct KernelCore::Impl {
next_user_process_id = KProcess::ProcessIdMin; next_user_process_id = KProcess::ProcessIdMin;
next_thread_id = 1; next_thread_id = 1;
global_handle_table->Finalize();
global_handle_table.reset();
preemption_event = nullptr; preemption_event = nullptr;
// Cleanup persistent kernel objects // Cleanup persistent kernel objects
@ -787,10 +782,6 @@ struct KernelCore::Impl {
std::shared_ptr<Core::Timing::EventType> preemption_event; std::shared_ptr<Core::Timing::EventType> preemption_event;
// This is the kernel's handle table or supervisor handle table which
// stores all the objects in place.
std::unique_ptr<KHandleTable> global_handle_table;
std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container; std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
std::unique_ptr<KObjectNameGlobalData> object_name_global_data; std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
@ -877,10 +868,6 @@ KResourceLimit* KernelCore::GetSystemResourceLimit() {
return impl->system_resource_limit; return impl->system_resource_limit;
} }
KScopedAutoObject<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
return impl->global_handle_table->GetObject<KThread>(handle);
}
void KernelCore::AppendNewProcess(KProcess* process) { void KernelCore::AppendNewProcess(KProcess* process) {
impl->process_list.push_back(process); impl->process_list.push_back(process);
} }
@ -1017,14 +1004,6 @@ u64 KernelCore::CreateNewUserProcessID() {
return impl->next_user_process_id++; return impl->next_user_process_id++;
} }
KHandleTable& KernelCore::GlobalHandleTable() {
return *impl->global_handle_table;
}
const KHandleTable& KernelCore::GlobalHandleTable() const {
return *impl->global_handle_table;
}
void KernelCore::RegisterCoreThread(std::size_t core_id) { void KernelCore::RegisterCoreThread(std::size_t core_id) {
impl->RegisterCoreThread(core_id); impl->RegisterCoreThread(core_id);
} }

View File

@ -116,9 +116,6 @@ public:
/// Retrieves a shared pointer to the system resource limit instance. /// Retrieves a shared pointer to the system resource limit instance.
KResourceLimit* GetSystemResourceLimit(); KResourceLimit* GetSystemResourceLimit();
/// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
KScopedAutoObject<KThread> RetrieveThreadFromGlobalHandleTable(Handle handle) const;
/// Adds the given shared pointer to an internal list of active processes. /// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(KProcess* process); void AppendNewProcess(KProcess* process);

View File

@ -89,7 +89,7 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F
crash_report += fmt::format(" ESR: {:016x}\n", info.esr); crash_report += fmt::format(" ESR: {:016x}\n", info.esr);
crash_report += fmt::format(" FAR: {:016x}\n", info.far); crash_report += fmt::format(" FAR: {:016x}\n", info.far);
crash_report += "\nBacktrace:\n"; crash_report += "\nBacktrace:\n";
for (size_t i = 0; i < info.backtrace_size; i++) { for (u32 i = 0; i < std::min<u32>(info.backtrace_size, 32); i++) {
crash_report += crash_report +=
fmt::format(" Backtrace[{:02d}]: {:016x}\n", i, info.backtrace[i]); fmt::format(" Backtrace[{:02d}]: {:016x}\n", i, info.backtrace[i]);
} }

View File

@ -47,7 +47,7 @@ ServerManager::~ServerManager() {
m_stopped.Wait(); m_stopped.Wait();
m_threads.clear(); m_threads.clear();
// Clean up ports. // Clean up server ports.
for (const auto& [port, handler] : m_ports) { for (const auto& [port, handler] : m_ports) {
port->Close(); port->Close();
} }
@ -97,22 +97,15 @@ Result ServerManager::RegisterNamedService(const std::string& service_name,
u32 max_sessions) { u32 max_sessions) {
ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects); ASSERT(m_sessions.size() + m_ports.size() < MaximumWaitObjects);
// Add the new server to sm:. // Add the new server to sm: and get the moved server port.
ASSERT(R_SUCCEEDED( Kernel::KServerPort* server_port{};
m_system.ServiceManager().RegisterService(service_name, max_sessions, handler_factory))); R_ASSERT(m_system.ServiceManager().RegisterService(std::addressof(server_port), service_name,
max_sessions, handler_factory));
// Get the registered port.
Kernel::KPort* port{};
ASSERT(
R_SUCCEEDED(m_system.ServiceManager().GetServicePort(std::addressof(port), service_name)));
// Open a new reference to the server port.
port->GetServerPort().Open();
// Begin tracking the server port. // Begin tracking the server port.
{ {
std::scoped_lock ll{m_list_mutex}; std::scoped_lock ll{m_list_mutex};
m_ports.emplace(std::addressof(port->GetServerPort()), std::move(handler_factory)); m_ports.emplace(server_port, std::move(handler_factory));
} }
// Signal the wakeup event. // Signal the wakeup event.

View File

@ -507,6 +507,14 @@ void SET_SYS::SetTvSettings(HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void SET_SYS::GetDebugModeFlag(HLERequestContext& ctx) {
LOG_DEBUG(Service_SET, "called");
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(0);
}
void SET_SYS::GetQuestFlag(HLERequestContext& ctx) { void SET_SYS::GetQuestFlag(HLERequestContext& ctx) {
LOG_WARNING(Service_SET, "(STUBBED) called"); LOG_WARNING(Service_SET, "(STUBBED) called");
@ -926,7 +934,7 @@ SET_SYS::SET_SYS(Core::System& system_) : ServiceFramework{system_, "set:sys"},
{59, &SET_SYS::SetNetworkSystemClockContext, "SetNetworkSystemClockContext"}, {59, &SET_SYS::SetNetworkSystemClockContext, "SetNetworkSystemClockContext"},
{60, &SET_SYS::IsUserSystemClockAutomaticCorrectionEnabled, "IsUserSystemClockAutomaticCorrectionEnabled"}, {60, &SET_SYS::IsUserSystemClockAutomaticCorrectionEnabled, "IsUserSystemClockAutomaticCorrectionEnabled"},
{61, &SET_SYS::SetUserSystemClockAutomaticCorrectionEnabled, "SetUserSystemClockAutomaticCorrectionEnabled"}, {61, &SET_SYS::SetUserSystemClockAutomaticCorrectionEnabled, "SetUserSystemClockAutomaticCorrectionEnabled"},
{62, nullptr, "GetDebugModeFlag"}, {62, &SET_SYS::GetDebugModeFlag, "GetDebugModeFlag"},
{63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"}, {63, &SET_SYS::GetPrimaryAlbumStorage, "GetPrimaryAlbumStorage"},
{64, nullptr, "SetPrimaryAlbumStorage"}, {64, nullptr, "SetPrimaryAlbumStorage"},
{65, nullptr, "GetUsb30EnableFlag"}, {65, nullptr, "GetUsb30EnableFlag"},
@ -1143,6 +1151,8 @@ void SET_SYS::StoreSettings() {
} }
void SET_SYS::StoreSettingsThreadFunc(std::stop_token stop_token) { void SET_SYS::StoreSettingsThreadFunc(std::stop_token stop_token) {
Common::SetCurrentThreadName("SettingsStore");
while (Common::StoppableTimedWait(stop_token, std::chrono::minutes(1))) { while (Common::StoppableTimedWait(stop_token, std::chrono::minutes(1))) {
std::scoped_lock l{m_save_needed_mutex}; std::scoped_lock l{m_save_needed_mutex};
if (!std::exchange(m_save_needed, false)) { if (!std::exchange(m_save_needed, false)) {

View File

@ -98,6 +98,7 @@ private:
void GetSettingsItemValue(HLERequestContext& ctx); void GetSettingsItemValue(HLERequestContext& ctx);
void GetTvSettings(HLERequestContext& ctx); void GetTvSettings(HLERequestContext& ctx);
void SetTvSettings(HLERequestContext& ctx); void SetTvSettings(HLERequestContext& ctx);
void GetDebugModeFlag(HLERequestContext& ctx);
void GetQuestFlag(HLERequestContext& ctx); void GetQuestFlag(HLERequestContext& ctx);
void GetDeviceTimeZoneLocationName(HLERequestContext& ctx); void GetDeviceTimeZoneLocationName(HLERequestContext& ctx);
void SetDeviceTimeZoneLocationName(HLERequestContext& ctx); void SetDeviceTimeZoneLocationName(HLERequestContext& ctx);

View File

@ -29,8 +29,7 @@ ServiceManager::ServiceManager(Kernel::KernelCore& kernel_) : kernel{kernel_} {
ServiceManager::~ServiceManager() { ServiceManager::~ServiceManager() {
for (auto& [name, port] : service_ports) { for (auto& [name, port] : service_ports) {
port->GetClientPort().Close(); port->Close();
port->GetServerPort().Close();
} }
if (deferral_event) { if (deferral_event) {
@ -50,8 +49,8 @@ static Result ValidateServiceName(const std::string& name) {
return ResultSuccess; return ResultSuccess;
} }
Result ServiceManager::RegisterService(std::string name, u32 max_sessions, Result ServiceManager::RegisterService(Kernel::KServerPort** out_server_port, std::string name,
SessionRequestHandlerFactory handler) { u32 max_sessions, SessionRequestHandlerFactory handler) {
R_TRY(ValidateServiceName(name)); R_TRY(ValidateServiceName(name));
std::scoped_lock lk{lock}; std::scoped_lock lk{lock};
@ -66,13 +65,17 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions,
// Register the port. // Register the port.
Kernel::KPort::Register(kernel, port); Kernel::KPort::Register(kernel, port);
service_ports.emplace(name, port); service_ports.emplace(name, std::addressof(port->GetClientPort()));
registered_services.emplace(name, handler); registered_services.emplace(name, handler);
if (deferral_event) { if (deferral_event) {
deferral_event->Signal(); deferral_event->Signal();
} }
return ResultSuccess; // Set our output.
*out_server_port = std::addressof(port->GetServerPort());
// We succeeded.
R_SUCCEED();
} }
Result ServiceManager::UnregisterService(const std::string& name) { Result ServiceManager::UnregisterService(const std::string& name) {
@ -91,7 +94,8 @@ Result ServiceManager::UnregisterService(const std::string& name) {
return ResultSuccess; return ResultSuccess;
} }
Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::string& name) { Result ServiceManager::GetServicePort(Kernel::KClientPort** out_client_port,
const std::string& name) {
R_TRY(ValidateServiceName(name)); R_TRY(ValidateServiceName(name));
std::scoped_lock lk{lock}; std::scoped_lock lk{lock};
@ -101,7 +105,7 @@ Result ServiceManager::GetServicePort(Kernel::KPort** out_port, const std::strin
return Service::SM::ResultNotRegistered; return Service::SM::ResultNotRegistered;
} }
*out_port = it->second; *out_client_port = it->second;
return ResultSuccess; return ResultSuccess;
} }
@ -172,8 +176,8 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
std::string name(PopServiceName(rp)); std::string name(PopServiceName(rp));
// Find the named port. // Find the named port.
Kernel::KPort* port{}; Kernel::KClientPort* client_port{};
auto port_result = service_manager.GetServicePort(&port, name); auto port_result = service_manager.GetServicePort(&client_port, name);
if (port_result == Service::SM::ResultInvalidServiceName) { if (port_result == Service::SM::ResultInvalidServiceName) {
LOG_ERROR(Service_SM, "Invalid service name '{}'", name); LOG_ERROR(Service_SM, "Invalid service name '{}'", name);
return Service::SM::ResultInvalidServiceName; return Service::SM::ResultInvalidServiceName;
@ -187,7 +191,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
// Create a new session. // Create a new session.
Kernel::KClientSession* session{}; Kernel::KClientSession* session{};
if (const auto result = port->GetClientPort().CreateSession(&session); result.IsError()) { if (const auto result = client_port->CreateSession(&session); result.IsError()) {
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw); LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
return result; return result;
} }
@ -221,7 +225,9 @@ void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_s
LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name, LOG_DEBUG(Service_SM, "called with name={}, max_session_count={}, is_light={}", name,
max_session_count, is_light); max_session_count, is_light);
if (const auto result = service_manager.RegisterService(name, max_session_count, nullptr); Kernel::KServerPort* server_port{};
if (const auto result = service_manager.RegisterService(std::addressof(server_port), name,
max_session_count, nullptr);
result.IsError()) { result.IsError()) {
LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", result.raw); LOG_ERROR(Service_SM, "failed to register service with error_code={:08X}", result.raw);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@ -229,13 +235,9 @@ void SM::RegisterServiceImpl(HLERequestContext& ctx, std::string name, u32 max_s
return; return;
} }
auto* port = Kernel::KPort::Create(kernel);
port->Initialize(ServerSessionCountMax, is_light, 0);
SCOPE_EXIT({ port->GetClientPort().Close(); });
IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles}; IPC::ResponseBuilder rb{ctx, 2, 0, 1, IPC::ResponseBuilder::Flags::AlwaysMoveHandles};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.PushMoveObjects(port->GetServerPort()); rb.PushMoveObjects(server_port);
} }
void SM::UnregisterService(HLERequestContext& ctx) { void SM::UnregisterService(HLERequestContext& ctx) {

View File

@ -56,10 +56,10 @@ public:
explicit ServiceManager(Kernel::KernelCore& kernel_); explicit ServiceManager(Kernel::KernelCore& kernel_);
~ServiceManager(); ~ServiceManager();
Result RegisterService(std::string name, u32 max_sessions, Result RegisterService(Kernel::KServerPort** out_server_port, std::string name,
SessionRequestHandlerFactory handler_factory); u32 max_sessions, SessionRequestHandlerFactory handler_factory);
Result UnregisterService(const std::string& name); Result UnregisterService(const std::string& name);
Result GetServicePort(Kernel::KPort** out_port, const std::string& name); Result GetServicePort(Kernel::KClientPort** out_client_port, const std::string& name);
template <Common::DerivedFrom<SessionRequestHandler> T> template <Common::DerivedFrom<SessionRequestHandler> T>
std::shared_ptr<T> GetService(const std::string& service_name) const { std::shared_ptr<T> GetService(const std::string& service_name) const {
@ -84,7 +84,7 @@ private:
/// Map of registered services, retrieved using GetServicePort. /// Map of registered services, retrieved using GetServicePort.
std::mutex lock; std::mutex lock;
std::unordered_map<std::string, SessionRequestHandlerFactory> registered_services; std::unordered_map<std::string, SessionRequestHandlerFactory> registered_services;
std::unordered_map<std::string, Kernel::KPort*> service_ports; std::unordered_map<std::string, Kernel::KClientPort*> service_ports;
/// Kernel context /// Kernel context
Kernel::KernelCore& kernel; Kernel::KernelCore& kernel;

View File

@ -45,7 +45,13 @@ struct Memory::Impl {
void SetCurrentPageTable(Kernel::KProcess& process) { void SetCurrentPageTable(Kernel::KProcess& process) {
current_page_table = &process.GetPageTable().GetImpl(); current_page_table = &process.GetPageTable().GetImpl();
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
if (std::addressof(process) == system.ApplicationProcess() &&
Settings::IsFastmemEnabled()) {
current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer();
} else {
current_page_table->fastmem_arena = nullptr;
}
} }
void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,
@ -57,7 +63,7 @@ struct Memory::Impl {
MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target, MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target,
Common::PageType::Memory); Common::PageType::Memory);
if (Settings::IsFastmemEnabled()) { if (current_page_table->fastmem_arena) {
system.DeviceMemory().buffer.Map(GetInteger(base), system.DeviceMemory().buffer.Map(GetInteger(base),
GetInteger(target) - DramMemoryMap::Base, size, perms); GetInteger(target) - DramMemoryMap::Base, size, perms);
} }
@ -69,7 +75,7 @@ struct Memory::Impl {
MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0, MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0,
Common::PageType::Unmapped); Common::PageType::Unmapped);
if (Settings::IsFastmemEnabled()) { if (current_page_table->fastmem_arena) {
system.DeviceMemory().buffer.Unmap(GetInteger(base), size); system.DeviceMemory().buffer.Unmap(GetInteger(base), size);
} }
} }
@ -79,7 +85,7 @@ struct Memory::Impl {
ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size);
ASSERT_MSG((vaddr & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", vaddr); ASSERT_MSG((vaddr & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", vaddr);
if (!Settings::IsFastmemEnabled()) { if (!current_page_table->fastmem_arena) {
return; return;
} }
@ -88,11 +94,6 @@ struct Memory::Impl {
const bool is_x = const bool is_x =
True(perms & Common::MemoryPermission::Execute) && Settings::IsNceEnabled(); True(perms & Common::MemoryPermission::Execute) && Settings::IsNceEnabled();
if (!current_page_table) {
system.DeviceMemory().buffer.Protect(vaddr, size, is_r, is_w, is_x);
return;
}
u64 protect_bytes{}; u64 protect_bytes{};
u64 protect_begin{}; u64 protect_begin{};
for (u64 addr = vaddr; addr < vaddr + size; addr += YUZU_PAGESIZE) { for (u64 addr = vaddr; addr < vaddr + size; addr += YUZU_PAGESIZE) {
@ -239,7 +240,7 @@ struct Memory::Impl {
bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped, bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped,
auto on_memory, auto on_rasterizer, auto increment) { auto on_memory, auto on_rasterizer, auto increment) {
const auto& page_table = system.ApplicationProcess()->GetPageTable().GetImpl(); const auto& page_table = *current_page_table;
std::size_t remaining_size = size; std::size_t remaining_size = size;
std::size_t page_index = addr >> YUZU_PAGEBITS; std::size_t page_index = addr >> YUZU_PAGEBITS;
std::size_t page_offset = addr & YUZU_PAGEMASK; std::size_t page_offset = addr & YUZU_PAGEMASK;
@ -484,7 +485,7 @@ struct Memory::Impl {
return; return;
} }
if (Settings::IsFastmemEnabled()) { if (current_page_table->fastmem_arena) {
system.DeviceMemory().buffer.Protect(vaddr, size, !debug, !debug); system.DeviceMemory().buffer.Protect(vaddr, size, !debug, !debug);
} }
@ -541,7 +542,7 @@ struct Memory::Impl {
return; return;
} }
if (Settings::IsFastmemEnabled()) { if (current_page_table->fastmem_arena) {
const bool is_read_enable = const bool is_read_enable =
!Settings::values.use_reactive_flushing.GetValue() || !cached; !Settings::values.use_reactive_flushing.GetValue() || !cached;
system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached); system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached);
@ -886,8 +887,7 @@ void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress
} }
bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const {
const Kernel::KProcess& process = *system.ApplicationProcess(); const auto& page_table = *impl->current_page_table;
const auto& page_table = process.GetPageTable().GetImpl();
const size_t page = vaddr >> YUZU_PAGEBITS; const size_t page = vaddr >> YUZU_PAGEBITS;
if (page >= page_table.pointers.size()) { if (page >= page_table.pointers.size()) {
return false; return false;