diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/CMakeLists.txt | 14 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 66 | ||||
| -rw-r--r-- | src/core/hle/service/acc/acc.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/bcat/backend/boxcat.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/service/filesystem/filesystem.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/service/mii/manager.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nifm/nifm.cpp | 12 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/buffer_queue.cpp | 14 | ||||
| -rw-r--r-- | src/core/hle/service/nvflinger/buffer_queue.h | 1 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 52 |
12 files changed, 155 insertions, 54 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index f910e438f..9dc320f53 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,9 +1,3 @@ -if (YUZU_ENABLE_BOXCAT) - set(BCAT_BOXCAT_ADDITIONAL_SOURCES hle/service/bcat/backend/boxcat.cpp hle/service/bcat/backend/boxcat.h) -else() - set(BCAT_BOXCAT_ADDITIONAL_SOURCES) -endif() - add_library(core STATIC arm/arm_interface.h arm/arm_interface.cpp @@ -303,7 +297,6 @@ add_library(core STATIC hle/service/audio/hwopus.h hle/service/bcat/backend/backend.cpp hle/service/bcat/backend/backend.h - ${BCAT_BOXCAT_ADDITIONAL_SOURCES} hle/service/bcat/bcat.cpp hle/service/bcat/bcat.h hle/service/bcat/module.cpp @@ -608,6 +601,13 @@ add_library(core STATIC tools/freezer.h ) +if (YUZU_ENABLE_BOXCAT) + target_sources(core PRIVATE + hle/service/bcat/backend/boxcat.cpp + hle/service/bcat/backend/boxcat.h + ) +endif() + if (MSVC) target_compile_options(core PRIVATE # 'expression' : signed/unsigned mismatch diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index c04b23eff..ed30854ee 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -7,7 +7,6 @@ #include <bitset> #include <functional> #include <memory> -#include <mutex> #include <thread> #include <unordered_map> #include <utility> @@ -107,7 +106,11 @@ struct KernelCore::Impl { cores.clear(); exclusive_monitor.reset(); - host_thread_ids.clear(); + + num_host_threads = 0; + std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(), + std::thread::id{}); + std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0); } void InitializePhysicalCores() { @@ -177,54 +180,56 @@ struct KernelCore::Impl { void MakeCurrentProcess(Process* process) { current_process = process; - if (process == nullptr) { return; } - - u32 core_id = GetCurrentHostThreadID(); + const u32 core_id = GetCurrentHostThreadID(); if (core_id < Core::Hardware::NUM_CPU_CORES) { system.Memory().SetCurrentPageTable(*process, core_id); } } void RegisterCoreThread(std::size_t core_id) { - std::unique_lock lock{register_thread_mutex}; + const std::thread::id this_id = std::this_thread::get_id(); if (!is_multicore) { - single_core_thread_id = std::this_thread::get_id(); + single_core_thread_id = this_id; } - const std::thread::id this_id = std::this_thread::get_id(); - const auto it = host_thread_ids.find(this_id); + const auto end = register_host_thread_keys.begin() + num_host_threads; + const auto it = std::find(register_host_thread_keys.begin(), end, this_id); ASSERT(core_id < Core::Hardware::NUM_CPU_CORES); - ASSERT(it == host_thread_ids.end()); + ASSERT(it == end); ASSERT(!registered_core_threads[core_id]); - host_thread_ids[this_id] = static_cast<u32>(core_id); + InsertHostThread(static_cast<u32>(core_id)); registered_core_threads.set(core_id); } void RegisterHostThread() { - std::unique_lock lock{register_thread_mutex}; const std::thread::id this_id = std::this_thread::get_id(); - const auto it = host_thread_ids.find(this_id); - if (it != host_thread_ids.end()) { - return; + const auto end = register_host_thread_keys.begin() + num_host_threads; + const auto it = std::find(register_host_thread_keys.begin(), end, this_id); + if (it == end) { + InsertHostThread(registered_thread_ids++); } - host_thread_ids[this_id] = registered_thread_ids++; } - u32 GetCurrentHostThreadID() const { + void InsertHostThread(u32 value) { + const size_t index = num_host_threads++; + ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads"); + register_host_thread_values[index] = value; + register_host_thread_keys[index] = std::this_thread::get_id(); + } + + [[nodiscard]] u32 GetCurrentHostThreadID() const { const std::thread::id this_id = std::this_thread::get_id(); - if (!is_multicore) { - if (single_core_thread_id == this_id) { - return static_cast<u32>(system.GetCpuManager().CurrentCore()); - } + if (!is_multicore && single_core_thread_id == this_id) { + return static_cast<u32>(system.GetCpuManager().CurrentCore()); } - std::unique_lock lock{register_thread_mutex}; - const auto it = host_thread_ids.find(this_id); - if (it == host_thread_ids.end()) { + const auto end = register_host_thread_keys.begin() + num_host_threads; + const auto it = std::find(register_host_thread_keys.begin(), end, this_id); + if (it == end) { return Core::INVALID_HOST_THREAD_ID; } - return it->second; + return register_host_thread_values[std::distance(register_host_thread_keys.begin(), it)]; } Core::EmuThreadHandle GetCurrentEmuThreadID() const { @@ -322,10 +327,15 @@ struct KernelCore::Impl { std::vector<Kernel::PhysicalCore> cores; // 0-3 IDs represent core threads, >3 represent others - std::unordered_map<std::thread::id, u32> host_thread_ids; - u32 registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; + std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES}; std::bitset<Core::Hardware::NUM_CPU_CORES> registered_core_threads; - mutable std::mutex register_thread_mutex; + + // Number of host threads is a relatively high number to avoid overflowing + static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64; + std::atomic<size_t> num_host_threads{0}; + std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS> + register_host_thread_keys{}; + std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{}; // Kernel memory management std::unique_ptr<Memory::MemoryManager> memory_manager; diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 6b1613510..2850dd805 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -496,7 +496,7 @@ public: {3, nullptr, "LoadIdTokenCache"}, {130, nullptr, "GetNintendoAccountUserResourceCacheForApplication"}, {150, nullptr, "CreateAuthorizationRequest"}, - {160, nullptr, "StoreOpenContext"}, + {160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"}, {170, nullptr, "LoadNetworkServiceLicenseKindAsync"}, }; // clang-format on @@ -520,6 +520,12 @@ private: rb.PushRaw<u64>(user_id.GetNintendoID()); } + void StoreOpenContext(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + Common::UUID user_id; }; diff --git a/src/core/hle/service/bcat/backend/boxcat.cpp b/src/core/hle/service/bcat/backend/boxcat.cpp index bd7ea75c2..e6cadf491 100644 --- a/src/core/hle/service/bcat/backend/boxcat.cpp +++ b/src/core/hle/service/bcat/backend/boxcat.cpp @@ -463,6 +463,16 @@ Boxcat::StatusResult Boxcat::GetStatus(std::optional<std::string>& global, {std::string("Boxcat-Client-Type"), std::string(BOXCAT_CLIENT_TYPE)}, }; + if (!client.is_valid()) { + LOG_ERROR(Service_BCAT, "Client is invalid, going offline!"); + return StatusResult::Offline; + } + + if (!client.is_socket_open()) { + LOG_ERROR(Service_BCAT, "Failed to open socket, going offline!"); + return StatusResult::Offline; + } + const auto response = client.Get(BOXCAT_PATHNAME_EVENTS, headers); if (response == nullptr) return StatusResult::Offline; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 54a5fb84b..3cdef4888 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -79,7 +79,7 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons } auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); - if (dir->GetFile(Common::FS::GetFilename(path)) == nullptr) { + if (dir == nullptr || dir->GetFile(Common::FS::GetFilename(path)) == nullptr) { return FileSys::ERROR_PATH_NOT_FOUND; } if (!dir->DeleteFile(Common::FS::GetFilename(path))) { @@ -93,8 +93,9 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { std::string path(Common::FS::SanitizePath(path_)); auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); - if (dir == nullptr && Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) + if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) { dir = backing; + } auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path)); if (new_dir == nullptr) { // TODO(DarkLordZach): Find a better error code for this diff --git a/src/core/hle/service/mii/manager.cpp b/src/core/hle/service/mii/manager.cpp index 5930765bc..1b75c2ebe 100644 --- a/src/core/hle/service/mii/manager.cpp +++ b/src/core/hle/service/mii/manager.cpp @@ -131,7 +131,7 @@ template <typename T> T GetRandomValue(T min, T max) { std::random_device device; std::mt19937 gen(device()); - std::uniform_int_distribution<u64> distribution(0, static_cast<u64>(max)); + std::uniform_int_distribution<u64> distribution(static_cast<u64>(min), static_cast<u64>(max)); return static_cast<T>(distribution(gen)); } diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index 2e9d95195..db7ec6d0e 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp @@ -62,7 +62,7 @@ public: {18, nullptr, "SetRequirementByRevision"}, {19, nullptr, "GetRequirement"}, {20, nullptr, "GetRevision"}, - {21, nullptr, "GetAppletInfo"}, + {21, &IRequest::GetAppletInfo, "GetAppletInfo"}, {22, nullptr, "GetAdditionalInfo"}, {23, nullptr, "SetKeptInSleep"}, {24, nullptr, "RegisterSocketDescriptor"}, @@ -125,6 +125,16 @@ private: rb.Push(RESULT_SUCCESS); } + void GetAppletInfo(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_NIFM, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 8}; + rb.Push(RESULT_SUCCESS); + rb.Push<u32>(0); + rb.Push<u32>(0); + rb.Push<u32>(0); + } + Kernel::EventPair event1, event2; }; diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp index 85e921ceb..3a5bebff3 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -46,6 +46,8 @@ u32 nvhost_as_gpu::ioctl(Ioctl command, const std::vector<u8>& input, const std: return GetVARegions(input, output); case IoctlCommand::IocUnmapBufferCommand: return UnmapBuffer(input, output); + case IoctlCommand::IocFreeSpaceCommand: + return FreeSpace(input, output); default: break; } @@ -91,6 +93,20 @@ u32 nvhost_as_gpu::AllocateSpace(const std::vector<u8>& input, std::vector<u8>& return result; } +u32 nvhost_as_gpu::FreeSpace(const std::vector<u8>& input, std::vector<u8>& output) { + IoctlFreeSpace params{}; + std::memcpy(¶ms, input.data(), input.size()); + + LOG_DEBUG(Service_NVDRV, "called, offset={:X}, pages={:X}, page_size={:X}", params.offset, + params.pages, params.page_size); + + system.GPU().MemoryManager().Unmap(params.offset, + static_cast<std::size_t>(params.pages) * params.page_size); + + std::memcpy(output.data(), ¶ms, output.size()); + return NvErrCodes::Success; +} + u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output) { const auto num_entries = input.size() / sizeof(IoctlRemapEntry); diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h index 9a0cdff0c..fcdb40d93 100644 --- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -82,6 +82,7 @@ private: IocBindChannelCommand = 0x40044101, IocGetVaRegionsCommand = 0xC0404108, IocUnmapBufferCommand = 0xC0084105, + IocFreeSpaceCommand = 0xC0104103, }; struct IoctlInitalizeEx { @@ -107,6 +108,13 @@ private: }; static_assert(sizeof(IoctlAllocSpace) == 24, "IoctlInitalizeEx is incorrect size"); + struct IoctlFreeSpace { + u64_le offset; + u32_le pages; + u32_le page_size; + }; + static_assert(sizeof(IoctlFreeSpace) == 16, "IoctlFreeSpace is incorrect size"); + struct IoctlRemapEntry { u16_le flags; u16_le kind; @@ -162,6 +170,7 @@ private: u32 Remap(const std::vector<u8>& input, std::vector<u8>& output); u32 MapBufferEx(const std::vector<u8>& input, std::vector<u8>& output); u32 UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& output); + u32 FreeSpace(const std::vector<u8>& input, std::vector<u8>& output); u32 BindChannel(const std::vector<u8>& input, std::vector<u8>& output); u32 GetVARegions(const std::vector<u8>& input, std::vector<u8>& output); diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp index 637b310d7..4f1e210b1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue.cpp @@ -99,6 +99,20 @@ void BufferQueue::QueueBuffer(u32 slot, BufferTransformFlags transform, queue_sequence.push_back(slot); } +void BufferQueue::CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence) { + const auto itr = std::find_if(queue.begin(), queue.end(), + [slot](const Buffer& buffer) { return buffer.slot == slot; }); + ASSERT(itr != queue.end()); + ASSERT(itr->status != Buffer::Status::Free); + itr->status = Buffer::Status::Free; + itr->multi_fence = multi_fence; + itr->swap_interval = 0; + + free_buffers.push_back(slot); + + buffer_wait_event.writable->Signal(); +} + std::optional<std::reference_wrapper<const BufferQueue::Buffer>> BufferQueue::AcquireBuffer() { auto itr = queue.end(); // Iterate to find a queued buffer matching the requested slot. diff --git a/src/core/hle/service/nvflinger/buffer_queue.h b/src/core/hle/service/nvflinger/buffer_queue.h index 8a837e5aa..e7517c7e1 100644 --- a/src/core/hle/service/nvflinger/buffer_queue.h +++ b/src/core/hle/service/nvflinger/buffer_queue.h @@ -95,6 +95,7 @@ public: void QueueBuffer(u32 slot, BufferTransformFlags transform, const Common::Rectangle<int>& crop_rect, u32 swap_interval, Service::Nvidia::MultiFence& multi_fence); + void CancelBuffer(u32 slot, const Service::Nvidia::MultiFence& multi_fence); std::optional<std::reference_wrapper<const Buffer>> AcquireBuffer(); void ReleaseBuffer(u32 slot); void Disconnect(); diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index d380c60fb..5b0e371fe 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -215,10 +215,9 @@ public: explicit IGBPConnectRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPConnectRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -279,10 +278,9 @@ public: : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPSetPreallocatedBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); buffer = Read<NVFlinger::IGBPBuffer>(); } @@ -306,15 +304,40 @@ protected: } }; +class IGBPCancelBufferRequestParcel : public Parcel { +public: + explicit IGBPCancelBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { + Deserialize(); + } + + void DeserializeData() override { + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); + data = Read<Data>(); + } + + struct Data { + u32_le slot; + Service::Nvidia::MultiFence multi_fence; + }; + + Data data; +}; + +class IGBPCancelBufferResponseParcel : public Parcel { +protected: + void SerializeData() override { + Write<u32>(0); // Success + } +}; + class IGBPDequeueBufferRequestParcel : public Parcel { public: explicit IGBPDequeueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPDequeueBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -333,7 +356,6 @@ class IGBPDequeueBufferResponseParcel : public Parcel { public: explicit IGBPDequeueBufferResponseParcel(u32 slot, Service::Nvidia::MultiFence& multi_fence) : slot(slot), multi_fence(multi_fence) {} - ~IGBPDequeueBufferResponseParcel() override = default; protected: void SerializeData() override { @@ -352,10 +374,9 @@ public: explicit IGBPRequestBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPRequestBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); slot = Read<u32_le>(); } @@ -384,10 +405,9 @@ public: explicit IGBPQueueBufferRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPQueueBufferRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); data = Read<Data>(); } @@ -447,10 +467,9 @@ public: explicit IGBPQueryRequestParcel(std::vector<u8> buffer) : Parcel(std::move(buffer)) { Deserialize(); } - ~IGBPQueryRequestParcel() override = default; void DeserializeData() override { - std::u16string token = ReadInterfaceToken(); + [[maybe_unused]] const std::u16string token = ReadInterfaceToken(); type = Read<u32_le>(); } @@ -596,7 +615,12 @@ private: break; } case TransactionId::CancelBuffer: { - LOG_CRITICAL(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); + IGBPCancelBufferRequestParcel request{ctx.ReadBuffer()}; + + buffer_queue.CancelBuffer(request.data.slot, request.data.multi_fence); + + IGBPCancelBufferResponseParcel response{}; + ctx.WriteBuffer(response.Serialize()); break; } case TransactionId::Disconnect: { |
