diff options
Diffstat (limited to 'src')
33 files changed, 311 insertions, 171 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h index c6691a8e1..45e94e625 100644 --- a/src/core/arm/arm_interface.h +++ b/src/core/arm/arm_interface.h @@ -44,13 +44,6 @@ public: /// Step CPU by one instruction virtual void Step() = 0; - /// Maps a backing memory region for the CPU - virtual void MapBackingMemory(VAddr address, std::size_t size, u8* memory, - Kernel::VMAPermission perms) = 0; - - /// Unmaps a region of memory that was previously mapped using MapBackingMemory - virtual void UnmapMemory(VAddr address, std::size_t size) = 0; - /// Clear all instruction cache virtual void ClearInstructionCache() = 0; diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 44307fa19..f1506b372 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -177,15 +177,6 @@ ARM_Dynarmic::ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, ARM_Dynarmic::~ARM_Dynarmic() = default; -void ARM_Dynarmic::MapBackingMemory(u64 address, std::size_t size, u8* memory, - Kernel::VMAPermission perms) { - inner_unicorn.MapBackingMemory(address, size, memory, perms); -} - -void ARM_Dynarmic::UnmapMemory(u64 address, std::size_t size) { - inner_unicorn.UnmapMemory(address, size); -} - void ARM_Dynarmic::SetPC(u64 pc) { jit->SetPC(pc); } diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index b701e97a3..504d46c68 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -23,9 +23,6 @@ public: ARM_Dynarmic(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); ~ARM_Dynarmic() override; - void MapBackingMemory(VAddr address, std::size_t size, u8* memory, - Kernel::VMAPermission perms) override; - void UnmapMemory(u64 address, std::size_t size) override; void SetPC(u64 pc) override; u64 GetPC() const override; u64 GetReg(int index) const override; diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 4e07fe8b5..b0ee7821a 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp @@ -76,15 +76,6 @@ ARM_Unicorn::~ARM_Unicorn() { CHECKED(uc_close(uc)); } -void ARM_Unicorn::MapBackingMemory(VAddr address, std::size_t size, u8* memory, - Kernel::VMAPermission perms) { - CHECKED(uc_mem_map_ptr(uc, address, size, static_cast<u32>(perms), memory)); -} - -void ARM_Unicorn::UnmapMemory(VAddr address, std::size_t size) { - CHECKED(uc_mem_unmap(uc, address, size)); -} - void ARM_Unicorn::SetPC(u64 pc) { CHECKED(uc_reg_write(uc, UC_ARM64_REG_PC, &pc)); } diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h index 34e974b4d..fe2ffd70c 100644 --- a/src/core/arm/unicorn/arm_unicorn.h +++ b/src/core/arm/unicorn/arm_unicorn.h @@ -18,9 +18,6 @@ public: explicit ARM_Unicorn(System& system); ~ARM_Unicorn() override; - void MapBackingMemory(VAddr address, std::size_t size, u8* memory, - Kernel::VMAPermission perms) override; - void UnmapMemory(VAddr address, std::size_t size) override; void SetPC(u64 pc) override; u64 GetPC() const override; u64 GetReg(int index) const override; diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 99b7d387d..21c410e34 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -53,16 +53,12 @@ bool CpuBarrier::Rendezvous() { Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, std::size_t core_index) : cpu_barrier{cpu_barrier}, core_timing{system.CoreTiming()}, core_index{core_index} { - if (Settings::values.cpu_jit_enabled) { #ifdef ARCHITECTURE_x86_64 - arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index); + arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index); #else - arm_interface = std::make_unique<ARM_Unicorn>(system); - LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); + arm_interface = std::make_unique<ARM_Unicorn>(system); + LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif - } else { - arm_interface = std::make_unique<ARM_Unicorn>(system); - } scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface); } @@ -70,15 +66,12 @@ Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_ba Cpu::~Cpu() = default; std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(std::size_t num_cores) { - if (Settings::values.cpu_jit_enabled) { #ifdef ARCHITECTURE_x86_64 - return std::make_unique<DynarmicExclusiveMonitor>(num_cores); + return std::make_unique<DynarmicExclusiveMonitor>(num_cores); #else - return nullptr; // TODO(merry): Passthrough exclusive monitor + // TODO(merry): Passthrough exclusive monitor + return nullptr; #endif - } else { - return nullptr; // TODO(merry): Passthrough exclusive monitor - } } void Cpu::RunLoop(bool tight_loop) { diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 332573a95..58374f829 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -318,7 +318,14 @@ static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_ad return result; } - return vm_manager.UnmapRange(dst_addr, size); + const auto unmap_res = vm_manager.UnmapRange(dst_addr, size); + + // Reprotect the source mapping on success + if (unmap_res.IsSuccess()) { + ASSERT(vm_manager.ReprotectRange(src_addr, size, VMAPermission::ReadWrite).IsSuccess()); + } + + return unmap_res; } /// Connect to an OS service given the port name, returns the handle to the port to out diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 501544090..7bc925a5f 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp @@ -8,7 +8,6 @@ #include "common/assert.h" #include "common/logging/log.h" #include "common/memory_hook.h" -#include "core/arm/arm_interface.h" #include "core/core.h" #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/errors.h" @@ -109,15 +108,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target, VirtualMemoryArea& final_vma = vma_handle->second; ASSERT(final_vma.size == size); - system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset, - VMAPermission::ReadWriteExecute); - system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset, - VMAPermission::ReadWriteExecute); - system.ArmInterface(2).MapBackingMemory(target, size, block->data() + offset, - VMAPermission::ReadWriteExecute); - system.ArmInterface(3).MapBackingMemory(target, size, block->data() + offset, - VMAPermission::ReadWriteExecute); - final_vma.type = VMAType::AllocatedMemoryBlock; final_vma.permissions = VMAPermission::ReadWrite; final_vma.state = state; @@ -137,11 +127,6 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me VirtualMemoryArea& final_vma = vma_handle->second; ASSERT(final_vma.size == size); - system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); - system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); - system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); - system.ArmInterface(3).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); - final_vma.type = VMAType::BackingMemory; final_vma.permissions = VMAPermission::ReadWrite; final_vma.state = state; @@ -230,11 +215,6 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) { ASSERT(FindVMA(target)->second.size >= size); - system.ArmInterface(0).UnmapMemory(target, size); - system.ArmInterface(1).UnmapMemory(target, size); - system.ArmInterface(2).UnmapMemory(target, size); - system.ArmInterface(3).UnmapMemory(target, size); - return RESULT_SUCCESS; } diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 9fdcf2965..a192a1f5f 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -266,8 +266,8 @@ ISelfController::ISelfController(std::shared_ptr<NVFlinger::NVFlinger> nvflinger {65, nullptr, "ReportUserIsActive"}, {66, nullptr, "GetCurrentIlluminance"}, {67, nullptr, "IsIlluminanceAvailable"}, - {68, nullptr, "SetAutoSleepDisabled"}, - {69, nullptr, "IsAutoSleepDisabled"}, + {68, &ISelfController::SetAutoSleepDisabled, "SetAutoSleepDisabled"}, + {69, &ISelfController::IsAutoSleepDisabled, "IsAutoSleepDisabled"}, {70, nullptr, "ReportMultimediaError"}, {71, nullptr, "GetCurrentIlluminanceEx"}, {80, nullptr, "SetWirelessPriorityMode"}, @@ -454,6 +454,34 @@ void ISelfController::GetIdleTimeDetectionExtension(Kernel::HLERequestContext& c rb.Push<u32>(idle_time_detection_extension); } +void ISelfController::SetAutoSleepDisabled(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + is_auto_sleep_disabled = rp.Pop<bool>(); + + // On the system itself, if the previous state of is_auto_sleep_disabled + // differed from the current value passed in, it'd signify the internal + // window manager to update (and also increment some statistics like update counts) + // + // It'd also indicate this change to an idle handling context. + // + // However, given we're emulating this behavior, most of this can be ignored + // and it's sufficient to simply set the member variable for querying via + // IsAutoSleepDisabled(). + + LOG_DEBUG(Service_AM, "called. is_auto_sleep_disabled={}", is_auto_sleep_disabled); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); +} + +void ISelfController::IsAutoSleepDisabled(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called."); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + rb.Push(is_auto_sleep_disabled); +} + void ISelfController::GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called."); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 14b010164..6cb582483 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -133,6 +133,8 @@ private: void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); void GetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); + void SetAutoSleepDisabled(Kernel::HLERequestContext& ctx); + void IsAutoSleepDisabled(Kernel::HLERequestContext& ctx); void GetAccumulatedSuspendedTickValue(Kernel::HLERequestContext& ctx); void GetAccumulatedSuspendedTickChangedEvent(Kernel::HLERequestContext& ctx); @@ -142,6 +144,7 @@ private: u32 idle_time_detection_extension = 0; u64 num_fatal_sections_entered = 0; + bool is_auto_sleep_disabled = false; }; class ICommonStateGetter final : public ServiceFramework<ICommonStateGetter> { diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index dec541f2e..d1ec12ef9 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp @@ -22,7 +22,7 @@ public: {0, nullptr, "GetCompletionEvent"}, {1, nullptr, "Cancel"}, {10100, nullptr, "GetFriendListIds"}, - {10101, nullptr, "GetFriendList"}, + {10101, &IFriendService::GetFriendList, "GetFriendList"}, {10102, nullptr, "UpdateFriendInfo"}, {10110, nullptr, "GetFriendProfileImage"}, {10200, nullptr, "SendFriendRequestForApplication"}, @@ -99,6 +99,23 @@ public: } private: + enum class PresenceFilter : u32 { + None = 0, + Online = 1, + OnlinePlay = 2, + OnlineOrOnlinePlay = 3, + }; + + struct SizedFriendFilter { + PresenceFilter presence; + u8 is_favorite; + u8 same_app; + u8 same_app_played; + u8 arbitary_app_played; + u64 group_id; + }; + static_assert(sizeof(SizedFriendFilter) == 0x10, "SizedFriendFilter is an invalid size"); + void DeclareCloseOnlinePlaySession(Kernel::HLERequestContext& ctx) { // Stub used by Splatoon 2 LOG_WARNING(Service_ACC, "(STUBBED) called"); @@ -112,6 +129,22 @@ private: IPC::ResponseBuilder rb{ctx, 2}; rb.Push(RESULT_SUCCESS); } + + void GetFriendList(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto friend_offset = rp.Pop<u32>(); + const auto uuid = rp.PopRaw<Common::UUID>(); + [[maybe_unused]] const auto filter = rp.PopRaw<SizedFriendFilter>(); + const auto pid = rp.Pop<u64>(); + LOG_WARNING(Service_ACC, "(STUBBED) called, offset={}, uuid={}, pid={}", friend_offset, + uuid.Format(), pid); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(RESULT_SUCCESS); + + rb.Push<u32>(0); // Friend count + // TODO(ogniK): Return a buffer of u64s which are the "NetworkServiceAccountId" + } }; class INotificationService final : public ServiceFramework<INotificationService> { diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp index b839303ac..8ddad8682 100644 --- a/src/core/hle/service/ldr/ldr.cpp +++ b/src/core/hle/service/ldr/ldr.cpp @@ -345,14 +345,16 @@ public: vm_manager .MirrorMemory(*map_address, nro_address, nro_size, Kernel::MemoryState::ModuleCode) .IsSuccess()); - ASSERT(vm_manager.UnmapRange(nro_address, nro_size).IsSuccess()); + ASSERT(vm_manager.ReprotectRange(nro_address, nro_size, Kernel::VMAPermission::None) + .IsSuccess()); if (bss_size > 0) { ASSERT(vm_manager .MirrorMemory(*map_address + nro_size, bss_address, bss_size, Kernel::MemoryState::ModuleCode) .IsSuccess()); - ASSERT(vm_manager.UnmapRange(bss_address, bss_size).IsSuccess()); + ASSERT(vm_manager.ReprotectRange(bss_address, bss_size, Kernel::VMAPermission::None) + .IsSuccess()); } vm_manager.ReprotectRange(*map_address, header.text_size, @@ -364,7 +366,8 @@ public: Core::System::GetInstance().InvalidateCpuInstructionCaches(); - nro.insert_or_assign(*map_address, NROInfo{hash, nro_size + bss_size}); + nro.insert_or_assign(*map_address, + NROInfo{hash, nro_address, nro_size, bss_address, bss_size}); IPC::ResponseBuilder rb{ctx, 4}; rb.Push(RESULT_SUCCESS); @@ -409,9 +412,23 @@ public: } auto& vm_manager = Core::CurrentProcess()->VMManager(); - const auto& nro_size = iter->second.size; + const auto& nro_info = iter->second; - ASSERT(vm_manager.UnmapRange(nro_address, nro_size).IsSuccess()); + // Unmap the mirrored memory + ASSERT( + vm_manager.UnmapRange(nro_address, nro_info.nro_size + nro_info.bss_size).IsSuccess()); + + // Reprotect the source memory + ASSERT(vm_manager + .ReprotectRange(nro_info.nro_address, nro_info.nro_size, + Kernel::VMAPermission::ReadWrite) + .IsSuccess()); + if (nro_info.bss_size > 0) { + ASSERT(vm_manager + .ReprotectRange(nro_info.bss_address, nro_info.bss_size, + Kernel::VMAPermission::ReadWrite) + .IsSuccess()); + } Core::System::GetInstance().InvalidateCpuInstructionCaches(); @@ -473,7 +490,10 @@ private: struct NROInfo { SHA256Hash hash; - u64 size; + VAddr nro_address; + u64 nro_size; + VAddr bss_address; + u64 bss_size; }; bool initialized = false; diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index ce84e25ed..0b3923ad9 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -48,7 +48,7 @@ public: {19, nullptr, "Export"}, {20, nullptr, "IsBrokenDatabaseWithClearFlag"}, {21, &IDatabaseService::GetIndex, "GetIndex"}, - {22, nullptr, "SetInterfaceVersion"}, + {22, &IDatabaseService::SetInterfaceVersion, "SetInterfaceVersion"}, {23, nullptr, "Convert"}, }; // clang-format on @@ -350,8 +350,22 @@ private: rb.Push(index); } + void SetInterfaceVersion(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + current_interface_version = rp.PopRaw<u32>(); + + LOG_DEBUG(Service_Mii, "called, interface_version={:08X}", current_interface_version); + + UNIMPLEMENTED_IF(current_interface_version != 1); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + MiiManager db; + u32 current_interface_version = 0; + // Last read offsets of Get functions std::array<u32, 4> offsets{}; }; diff --git a/src/core/hle/service/pm/pm.cpp b/src/core/hle/service/pm/pm.cpp index ebcc41a43..fe6b5f798 100644 --- a/src/core/hle/service/pm/pm.cpp +++ b/src/core/hle/service/pm/pm.cpp @@ -3,11 +3,44 @@ // Refer to the license.txt file included. #include "core/hle/ipc_helpers.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/process.h" #include "core/hle/service/pm/pm.h" #include "core/hle/service/service.h" namespace Service::PM { +namespace { + +constexpr ResultCode ERROR_PROCESS_NOT_FOUND{ErrorModule::PM, 1}; + +constexpr u64 NO_PROCESS_FOUND_PID{0}; + +std::optional<Kernel::SharedPtr<Kernel::Process>> SearchProcessList( + const std::vector<Kernel::SharedPtr<Kernel::Process>>& process_list, + std::function<bool(const Kernel::SharedPtr<Kernel::Process>&)> predicate) { + const auto iter = std::find_if(process_list.begin(), process_list.end(), predicate); + + if (iter == process_list.end()) { + return std::nullopt; + } + + return *iter; +} + +void GetApplicationPidGeneric(Kernel::HLERequestContext& ctx, + const std::vector<Kernel::SharedPtr<Kernel::Process>>& process_list) { + const auto process = SearchProcessList(process_list, [](const auto& process) { + return process->GetProcessID() == Kernel::Process::ProcessIDMin; + }); + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push(process.has_value() ? (*process)->GetProcessID() : NO_PROCESS_FOUND_PID); +} + +} // Anonymous namespace + class BootMode final : public ServiceFramework<BootMode> { public: explicit BootMode() : ServiceFramework{"pm:bm"} { @@ -41,14 +74,15 @@ private: class DebugMonitor final : public ServiceFramework<DebugMonitor> { public: - explicit DebugMonitor() : ServiceFramework{"pm:dmnt"} { + explicit DebugMonitor(const Kernel::KernelCore& kernel) + : ServiceFramework{"pm:dmnt"}, kernel(kernel) { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "GetDebugProcesses"}, {1, nullptr, "StartDebugProcess"}, - {2, nullptr, "GetTitlePid"}, + {2, &DebugMonitor::GetTitlePid, "GetTitlePid"}, {3, nullptr, "EnableDebugForTitleId"}, - {4, nullptr, "GetApplicationPid"}, + {4, &DebugMonitor::GetApplicationPid, "GetApplicationPid"}, {5, nullptr, "EnableDebugForApplication"}, {6, nullptr, "DisableDebug"}, }; @@ -56,21 +90,77 @@ public: RegisterHandlers(functions); } + +private: + void GetTitlePid(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto title_id = rp.PopRaw<u64>(); + + LOG_DEBUG(Service_PM, "called, title_id={:016X}", title_id); + + const auto process = + SearchProcessList(kernel.GetProcessList(), [title_id](const auto& process) { + return process->GetTitleID() == title_id; + }); + + if (!process.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_PROCESS_NOT_FOUND); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push((*process)->GetProcessID()); + } + + void GetApplicationPid(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PM, "called"); + GetApplicationPidGeneric(ctx, kernel.GetProcessList()); + } + + const Kernel::KernelCore& kernel; }; class Info final : public ServiceFramework<Info> { public: - explicit Info() : ServiceFramework{"pm:info"} { + explicit Info(const std::vector<Kernel::SharedPtr<Kernel::Process>>& process_list) + : ServiceFramework{"pm:info"}, process_list(process_list) { static const FunctionInfo functions[] = { - {0, nullptr, "GetTitleId"}, + {0, &Info::GetTitleId, "GetTitleId"}, }; RegisterHandlers(functions); } + +private: + void GetTitleId(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto process_id = rp.PopRaw<u64>(); + + LOG_DEBUG(Service_PM, "called, process_id={:016X}", process_id); + + const auto process = SearchProcessList(process_list, [process_id](const auto& process) { + return process->GetProcessID() == process_id; + }); + + if (!process.has_value()) { + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ERROR_PROCESS_NOT_FOUND); + return; + } + + IPC::ResponseBuilder rb{ctx, 4}; + rb.Push(RESULT_SUCCESS); + rb.Push((*process)->GetTitleID()); + } + + const std::vector<Kernel::SharedPtr<Kernel::Process>>& process_list; }; class Shell final : public ServiceFramework<Shell> { public: - explicit Shell() : ServiceFramework{"pm:shell"} { + explicit Shell(const Kernel::KernelCore& kernel) + : ServiceFramework{"pm:shell"}, kernel(kernel) { // clang-format off static const FunctionInfo functions[] = { {0, nullptr, "LaunchProcess"}, @@ -79,21 +169,31 @@ public: {3, nullptr, "GetProcessEventWaiter"}, {4, nullptr, "GetProcessEventType"}, {5, nullptr, "NotifyBootFinished"}, - {6, nullptr, "GetApplicationPid"}, + {6, &Shell::GetApplicationPid, "GetApplicationPid"}, {7, nullptr, "BoostSystemMemoryResourceLimit"}, {8, nullptr, "EnableAdditionalSystemThreads"}, + {9, nullptr, "GetUnimplementedEventHandle"}, }; // clang-format on RegisterHandlers(functions); } + +private: + void GetApplicationPid(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_PM, "called"); + GetApplicationPidGeneric(ctx, kernel.GetProcessList()); + } + + const Kernel::KernelCore& kernel; }; -void InstallInterfaces(SM::ServiceManager& sm) { - std::make_shared<BootMode>()->InstallAsService(sm); - std::make_shared<DebugMonitor>()->InstallAsService(sm); - std::make_shared<Info>()->InstallAsService(sm); - std::make_shared<Shell>()->InstallAsService(sm); +void InstallInterfaces(Core::System& system) { + std::make_shared<BootMode>()->InstallAsService(system.ServiceManager()); + std::make_shared<DebugMonitor>(system.Kernel())->InstallAsService(system.ServiceManager()); + std::make_shared<Info>(system.Kernel().GetProcessList()) + ->InstallAsService(system.ServiceManager()); + std::make_shared<Shell>(system.Kernel())->InstallAsService(system.ServiceManager()); } } // namespace Service::PM diff --git a/src/core/hle/service/pm/pm.h b/src/core/hle/service/pm/pm.h index cc8d3f215..852e7050c 100644 --- a/src/core/hle/service/pm/pm.h +++ b/src/core/hle/service/pm/pm.h @@ -4,8 +4,8 @@ #pragma once -namespace Service::SM { -class ServiceManager; +namespace Core { +class System; } namespace Service::PM { @@ -16,6 +16,6 @@ enum class SystemBootMode { }; /// Registers all PM services with the specified service manager. -void InstallInterfaces(SM::ServiceManager& service_manager); +void InstallInterfaces(Core::System& system); } // namespace Service::PM diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp index 952c03e27..7eefd733f 100644 --- a/src/core/hle/service/service.cpp +++ b/src/core/hle/service/service.cpp @@ -241,7 +241,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system) { PCTL::InstallInterfaces(*sm); PCV::InstallInterfaces(*sm); PlayReport::InstallInterfaces(*sm); - PM::InstallInterfaces(*sm); + PM::InstallInterfaces(system); PSC::InstallInterfaces(*sm); PSM::InstallInterfaces(*sm); Set::InstallInterfaces(*sm); diff --git a/src/core/settings.cpp b/src/core/settings.cpp index 63aa59690..0dd1632ac 100644 --- a/src/core/settings.cpp +++ b/src/core/settings.cpp @@ -85,7 +85,6 @@ void LogSettings() { LogSetting("System_RngSeed", Settings::values.rng_seed.value_or(0)); LogSetting("System_CurrentUser", Settings::values.current_user); LogSetting("System_LanguageIndex", Settings::values.language_index); - LogSetting("Core_CpuJitEnabled", Settings::values.cpu_jit_enabled); LogSetting("Core_UseMultiCore", Settings::values.use_multi_core); LogSetting("Renderer_UseResolutionFactor", Settings::values.resolution_factor); LogSetting("Renderer_UseFrameLimit", Settings::values.use_frame_limit); diff --git a/src/core/settings.h b/src/core/settings.h index acf18d653..6638ce8f9 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -378,7 +378,6 @@ struct Values { std::atomic_bool is_device_reload_pending{true}; // Core - bool cpu_jit_enabled; bool use_multi_core; // Data Storage diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 98f49042a..793d102d3 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp @@ -168,7 +168,6 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader) { AddField(Telemetry::FieldType::UserConfig, "Audio_SinkId", Settings::values.sink_id); AddField(Telemetry::FieldType::UserConfig, "Audio_EnableAudioStretching", Settings::values.enable_audio_stretching); - AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.cpu_jit_enabled); AddField(Telemetry::FieldType::UserConfig, "Core_UseMultiCore", Settings::values.use_multi_core); AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor", diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index bf67e3a70..d238c1257 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h @@ -98,17 +98,19 @@ private: /** * Configures the color and depth framebuffer states. - * @param must_reconfigure If true, tells the framebuffer to skip the cache and reconfigure - * again. Used by the texture cache to solve texception conflicts - * @param use_color_fb If true, configure color framebuffers. - * @param using_depth_fb If true, configure the depth/stencil framebuffer. - * @param preserve_contents If true, tries to preserve data from a previously used framebuffer. + * + * @param current_state The current OpenGL state. + * @param using_color_fb If true, configure color framebuffers. + * @param using_depth_fb If true, configure the depth/stencil framebuffer. + * @param preserve_contents If true, tries to preserve data from a previously used + * framebuffer. * @param single_color_target Specifies if a single color buffer target should be used. + * * @returns If depth (first) or stencil (second) are being stored in the bound zeta texture - * (requires using_depth_fb to be true) + * (requires using_depth_fb to be true) */ std::pair<bool, bool> ConfigureFramebuffers( - OpenGLState& current_state, bool use_color_fb = true, bool using_depth_fb = true, + OpenGLState& current_state, bool using_color_fb = true, bool using_depth_fb = true, bool preserve_contents = true, std::optional<std::size_t> single_color_target = {}); /// Configures the current constbuffers to use for the draw command. diff --git a/src/video_core/renderer_opengl/gl_sampler_cache.h b/src/video_core/renderer_opengl/gl_sampler_cache.h index defbc2d81..34ee37f00 100644 --- a/src/video_core/renderer_opengl/gl_sampler_cache.h +++ b/src/video_core/renderer_opengl/gl_sampler_cache.h @@ -17,9 +17,9 @@ public: ~SamplerCacheOpenGL(); protected: - OGLSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const; + OGLSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const override; - GLuint ToSamplerType(const OGLSampler& sampler) const; + GLuint ToSamplerType(const OGLSampler& sampler) const override; }; } // namespace OpenGL diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 02a9f5ecb..d2e9f4031 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp @@ -109,8 +109,8 @@ void VKBufferCache::Reserve(std::size_t max_size) { } } -VKExecutionContext VKBufferCache::Send(VKExecutionContext exctx) { - return stream_buffer->Send(exctx, buffer_offset - buffer_offset_base); +void VKBufferCache::Send() { + stream_buffer->Send(buffer_offset - buffer_offset_base); } void VKBufferCache::AlignBuffer(std::size_t alignment) { diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 3edf460df..49f13bcdc 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h @@ -77,7 +77,7 @@ public: void Reserve(std::size_t max_size); /// Ensures that the set data is sent to the device. - [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx); + void Send(); /// Returns the buffer cache handle. vk::Buffer GetBuffer() const { diff --git a/src/video_core/renderer_vulkan/vk_sampler_cache.h b/src/video_core/renderer_vulkan/vk_sampler_cache.h index 771b05c73..1f73b716b 100644 --- a/src/video_core/renderer_vulkan/vk_sampler_cache.h +++ b/src/video_core/renderer_vulkan/vk_sampler_cache.h @@ -4,9 +4,6 @@ #pragma once -#include <unordered_map> - -#include "common/common_types.h" #include "video_core/renderer_vulkan/declarations.h" #include "video_core/sampler_cache.h" #include "video_core/textures/texture.h" @@ -21,9 +18,9 @@ public: ~VKSamplerCache(); protected: - UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const; + UniqueSampler CreateSampler(const Tegra::Texture::TSCEntry& tsc) const override; - vk::Sampler ToSamplerType(const UniqueSampler& sampler) const; + vk::Sampler ToSamplerType(const UniqueSampler& sampler) const override; private: const VKDevice& device; diff --git a/src/video_core/renderer_vulkan/vk_scheduler.cpp b/src/video_core/renderer_vulkan/vk_scheduler.cpp index f1fea1871..0f8116458 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.cpp +++ b/src/video_core/renderer_vulkan/vk_scheduler.cpp @@ -19,23 +19,19 @@ VKScheduler::VKScheduler(const VKDevice& device, VKResourceManager& resource_man VKScheduler::~VKScheduler() = default; -VKExecutionContext VKScheduler::GetExecutionContext() const { - return VKExecutionContext(current_fence, current_cmdbuf); -} - -VKExecutionContext VKScheduler::Flush(vk::Semaphore semaphore) { +void VKScheduler::Flush(bool release_fence, vk::Semaphore semaphore) { SubmitExecution(semaphore); - current_fence->Release(); + if (release_fence) + current_fence->Release(); AllocateNewContext(); - return GetExecutionContext(); } -VKExecutionContext VKScheduler::Finish(vk::Semaphore semaphore) { +void VKScheduler::Finish(bool release_fence, vk::Semaphore semaphore) { SubmitExecution(semaphore); current_fence->Wait(); - current_fence->Release(); + if (release_fence) + current_fence->Release(); AllocateNewContext(); - return GetExecutionContext(); } void VKScheduler::SubmitExecution(vk::Semaphore semaphore) { diff --git a/src/video_core/renderer_vulkan/vk_scheduler.h b/src/video_core/renderer_vulkan/vk_scheduler.h index cfaf5376f..0e5b49c7f 100644 --- a/src/video_core/renderer_vulkan/vk_scheduler.h +++ b/src/video_core/renderer_vulkan/vk_scheduler.h @@ -10,10 +10,43 @@ namespace Vulkan { class VKDevice; -class VKExecutionContext; class VKFence; class VKResourceManager; +class VKFenceView { +public: + VKFenceView() = default; + VKFenceView(VKFence* const& fence) : fence{fence} {} + + VKFence* operator->() const noexcept { + return fence; + } + + operator VKFence&() const noexcept { + return *fence; + } + +private: + VKFence* const& fence; +}; + +class VKCommandBufferView { +public: + VKCommandBufferView() = default; + VKCommandBufferView(const vk::CommandBuffer& cmdbuf) : cmdbuf{cmdbuf} {} + + const vk::CommandBuffer* operator->() const noexcept { + return &cmdbuf; + } + + operator vk::CommandBuffer() const noexcept { + return cmdbuf; + } + +private: + const vk::CommandBuffer& cmdbuf; +}; + /// The scheduler abstracts command buffer and fence management with an interface that's able to do /// OpenGL-like operations on Vulkan command buffers. class VKScheduler { @@ -21,16 +54,21 @@ public: explicit VKScheduler(const VKDevice& device, VKResourceManager& resource_manager); ~VKScheduler(); - /// Gets the current execution context. - [[nodiscard]] VKExecutionContext GetExecutionContext() const; + /// Gets a reference to the current fence. + VKFenceView GetFence() const { + return current_fence; + } + + /// Gets a reference to the current command buffer. + VKCommandBufferView GetCommandBuffer() const { + return current_cmdbuf; + } - /// Sends the current execution context to the GPU. It invalidates the current execution context - /// and returns a new one. - VKExecutionContext Flush(vk::Semaphore semaphore = nullptr); + /// Sends the current execution context to the GPU. + void Flush(bool release_fence = true, vk::Semaphore semaphore = nullptr); - /// Sends the current execution context to the GPU and waits for it to complete. It invalidates - /// the current execution context and returns a new one. - VKExecutionContext Finish(vk::Semaphore semaphore = nullptr); + /// Sends the current execution context to the GPU and waits for it to complete. + void Finish(bool release_fence = true, vk::Semaphore semaphore = nullptr); private: void SubmitExecution(vk::Semaphore semaphore); @@ -44,26 +82,4 @@ private: VKFence* next_fence = nullptr; }; -class VKExecutionContext { - friend class VKScheduler; - -public: - VKExecutionContext() = default; - - VKFence& GetFence() const { - return *fence; - } - - vk::CommandBuffer GetCommandBuffer() const { - return cmdbuf; - } - -private: - explicit VKExecutionContext(VKFence* fence, vk::CommandBuffer cmdbuf) - : fence{fence}, cmdbuf{cmdbuf} {} - - VKFence* fence{}; - vk::CommandBuffer cmdbuf; -}; - } // namespace Vulkan diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp index 58ffa42f2..62f1427f5 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp @@ -46,12 +46,12 @@ std::tuple<u8*, u64, bool> VKStreamBuffer::Reserve(u64 size) { return {mapped_pointer + offset, offset, invalidation_mark.has_value()}; } -VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) { +void VKStreamBuffer::Send(u64 size) { ASSERT_MSG(size <= mapped_size, "Reserved size is too small"); if (invalidation_mark) { // TODO(Rodrigo): Find a better way to invalidate than waiting for all watches to finish. - exctx = scheduler.Flush(); + scheduler.Flush(); std::for_each(watches.begin(), watches.begin() + *invalidation_mark, [&](auto& resource) { resource->Wait(); }); invalidation_mark = std::nullopt; @@ -62,11 +62,9 @@ VKExecutionContext VKStreamBuffer::Send(VKExecutionContext exctx, u64 size) { ReserveWatches(WATCHES_RESERVE_CHUNK); } // Add a watch for this allocation. - watches[used_watches++]->Watch(exctx.GetFence()); + watches[used_watches++]->Watch(scheduler.GetFence()); offset += size; - - return exctx; } void VKStreamBuffer::CreateBuffers(VKMemoryManager& memory_manager, vk::BufferUsageFlags usage) { diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h index 69d036ccd..842e54162 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.h +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.h @@ -37,7 +37,7 @@ public: std::tuple<u8*, u64, bool> Reserve(u64 size); /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. - [[nodiscard]] VKExecutionContext Send(VKExecutionContext exctx, u64 size); + void Send(u64 size); vk::Buffer GetBuffer() const { return *buffer; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 73978ff5b..b7f3fdf75 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -436,8 +436,6 @@ void Config::ReadControlValues() { void Config::ReadCoreValues() { qt_config->beginGroup(QStringLiteral("Core")); - Settings::values.cpu_jit_enabled = - ReadSetting(QStringLiteral("cpu_jit_enabled"), true).toBool(); Settings::values.use_multi_core = ReadSetting(QStringLiteral("use_multi_core"), false).toBool(); qt_config->endGroup(); @@ -831,7 +829,6 @@ void Config::SaveControlValues() { void Config::SaveCoreValues() { qt_config->beginGroup(QStringLiteral("Core")); - WriteSetting(QStringLiteral("cpu_jit_enabled"), Settings::values.cpu_jit_enabled, true); WriteSetting(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, false); qt_config->endGroup(); diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 30b22341b..067d58d80 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -340,7 +340,6 @@ void Config::ReadValues() { } // Core - Settings::values.cpu_jit_enabled = sdl2_config->GetBoolean("Core", "cpu_jit_enabled", true); Settings::values.use_multi_core = sdl2_config->GetBoolean("Core", "use_multi_core", false); // Renderer diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 4f1add434..0cfc111a6 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -76,10 +76,6 @@ motion_device= touch_device= [Core] -# Whether to use the Just-In-Time (JIT) compiler for CPU emulation -# 0: Interpreter (slow), 1 (default): JIT (fast) -cpu_jit_enabled = - # Whether to use multi-core for CPU emulation # 0 (default): Disabled, 1: Enabled use_multi_core= diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp index b96b7d279..9a11dc6c3 100644 --- a/src/yuzu_tester/config.cpp +++ b/src/yuzu_tester/config.cpp @@ -114,7 +114,6 @@ void Config::ReadValues() { } // Core - Settings::values.cpu_jit_enabled = sdl2_config->GetBoolean("Core", "cpu_jit_enabled", true); Settings::values.use_multi_core = sdl2_config->GetBoolean("Core", "use_multi_core", false); // Renderer diff --git a/src/yuzu_tester/default_ini.h b/src/yuzu_tester/default_ini.h index 0f880d8c7..9a3e86d68 100644 --- a/src/yuzu_tester/default_ini.h +++ b/src/yuzu_tester/default_ini.h @@ -8,10 +8,6 @@ namespace DefaultINI { const char* sdl2_config_file = R"( [Core] -# Whether to use the Just-In-Time (JIT) compiler for CPU emulation -# 0: Interpreter (slow), 1 (default): JIT (fast) -cpu_jit_enabled = - # Whether to use multi-core for CPU emulation # 0 (default): Disabled, 1: Enabled use_multi_core= |