diff --git a/README.md b/README.md index 49068e99b..31ab43a1f 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1722. +This is the source code for early-access 1725. ## Legal Notice diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 8fd8620fd..9fffd816f 100755 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp @@ -14,6 +14,7 @@ void PageTable::Resize(size_t address_space_width_in_bits, size_t page_size_in_b const size_t num_page_table_entries{1ULL << (address_space_width_in_bits - page_size_in_bits)}; pointers.resize(num_page_table_entries); backing_addr.resize(num_page_table_entries); + current_address_space_width_in_bits = address_space_width_in_bits; } } // namespace Common diff --git a/src/common/page_table.h b/src/common/page_table.h index 61c5552e0..e92b66b2b 100755 --- a/src/common/page_table.h +++ b/src/common/page_table.h @@ -98,6 +98,10 @@ struct PageTable { */ void Resize(size_t address_space_width_in_bits, size_t page_size_in_bits); + size_t GetAddressSpaceBits() const { + return current_address_space_width_in_bits; + } + /** * Vector of memory pointers backing each page. An entry can only be non-null if the * corresponding attribute element is of type `Memory`. @@ -105,6 +109,8 @@ struct PageTable { VirtualBuffer pointers; VirtualBuffer backing_addr; + + size_t current_address_space_width_in_bits; }; } // namespace Common diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 50dc82382..6ff241cd2 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -24,45 +24,46 @@ namespace Core { class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks { public: - explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) : parent{parent_} {} + explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) + : parent{parent_}, memory(parent.system.Memory()) {} u8 MemoryRead8(u32 vaddr) override { - return parent.system.Memory().Read8(vaddr); + return memory.Read8(vaddr); } u16 MemoryRead16(u32 vaddr) override { - return parent.system.Memory().Read16(vaddr); + return memory.Read16(vaddr); } u32 MemoryRead32(u32 vaddr) override { - return parent.system.Memory().Read32(vaddr); + return memory.Read32(vaddr); } u64 MemoryRead64(u32 vaddr) override { - return parent.system.Memory().Read64(vaddr); + return memory.Read64(vaddr); } void MemoryWrite8(u32 vaddr, u8 value) override { - parent.system.Memory().Write8(vaddr, value); + memory.Write8(vaddr, value); } void MemoryWrite16(u32 vaddr, u16 value) override { - parent.system.Memory().Write16(vaddr, value); + memory.Write16(vaddr, value); } void MemoryWrite32(u32 vaddr, u32 value) override { - parent.system.Memory().Write32(vaddr, value); + memory.Write32(vaddr, value); } void MemoryWrite64(u32 vaddr, u64 value) override { - parent.system.Memory().Write64(vaddr, value); + memory.Write64(vaddr, value); } bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override { - return parent.system.Memory().WriteExclusive8(vaddr, value, expected); + return memory.WriteExclusive8(vaddr, value, expected); } bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override { - return parent.system.Memory().WriteExclusive16(vaddr, value, expected); + return memory.WriteExclusive16(vaddr, value, expected); } bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override { - return parent.system.Memory().WriteExclusive32(vaddr, value, expected); + return memory.WriteExclusive32(vaddr, value, expected); } bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override { - return parent.system.Memory().WriteExclusive64(vaddr, value, expected); + return memory.WriteExclusive64(vaddr, value, expected); } void InterpreterFallback(u32 pc, std::size_t num_instructions) override { @@ -112,6 +113,7 @@ public: } ARM_Dynarmic_32& parent; + Core::Memory::Memory& memory; std::size_t num_interpreted_instructions{}; static constexpr u64 minimum_run_cycles = 1000U; }; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 4f5a58b38..98a6cef62 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -27,57 +27,56 @@ using Vector = Dynarmic::A64::Vector; class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks { public: - explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) : parent{parent_} {} + explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) + : parent{parent_}, memory(parent.system.Memory()) {} u8 MemoryRead8(u64 vaddr) override { - return parent.system.Memory().Read8(vaddr); + return memory.Read8(vaddr); } u16 MemoryRead16(u64 vaddr) override { - return parent.system.Memory().Read16(vaddr); + return memory.Read16(vaddr); } u32 MemoryRead32(u64 vaddr) override { - return parent.system.Memory().Read32(vaddr); + return memory.Read32(vaddr); } u64 MemoryRead64(u64 vaddr) override { - return parent.system.Memory().Read64(vaddr); + return memory.Read64(vaddr); } Vector MemoryRead128(u64 vaddr) override { - auto& memory = parent.system.Memory(); return {memory.Read64(vaddr), memory.Read64(vaddr + 8)}; } void MemoryWrite8(u64 vaddr, u8 value) override { - parent.system.Memory().Write8(vaddr, value); + memory.Write8(vaddr, value); } void MemoryWrite16(u64 vaddr, u16 value) override { - parent.system.Memory().Write16(vaddr, value); + memory.Write16(vaddr, value); } void MemoryWrite32(u64 vaddr, u32 value) override { - parent.system.Memory().Write32(vaddr, value); + memory.Write32(vaddr, value); } void MemoryWrite64(u64 vaddr, u64 value) override { - parent.system.Memory().Write64(vaddr, value); + memory.Write64(vaddr, value); } void MemoryWrite128(u64 vaddr, Vector value) override { - auto& memory = parent.system.Memory(); memory.Write64(vaddr, value[0]); memory.Write64(vaddr + 8, value[1]); } bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override { - return parent.system.Memory().WriteExclusive8(vaddr, value, expected); + return memory.WriteExclusive8(vaddr, value, expected); } bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override { - return parent.system.Memory().WriteExclusive16(vaddr, value, expected); + return memory.WriteExclusive16(vaddr, value, expected); } bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override { - return parent.system.Memory().WriteExclusive32(vaddr, value, expected); + return memory.WriteExclusive32(vaddr, value, expected); } bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override { - return parent.system.Memory().WriteExclusive64(vaddr, value, expected); + return memory.WriteExclusive64(vaddr, value, expected); } bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override { - return parent.system.Memory().WriteExclusive128(vaddr, value, expected); + return memory.WriteExclusive128(vaddr, value, expected); } void InterpreterFallback(u64 pc, std::size_t num_instructions) override { @@ -139,6 +138,7 @@ public: } ARM_Dynarmic_64& parent; + Core::Memory::Memory& memory; u64 tpidrro_el0 = 0; u64 tpidr_el0 = 0; static constexpr u64 minimum_run_cycles = 1000U; diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h index 8501156e8..f2fff3b01 100755 --- a/src/core/hle/kernel/k_client_port.h +++ b/src/core/hle/kernel/k_client_port.h @@ -22,7 +22,7 @@ class KClientPort final : public KSynchronizationObject { public: explicit KClientPort(KernelCore& kernel_); - virtual ~KClientPort() override; + ~KClientPort() override; void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_); void OnSessionFinalized(); @@ -49,8 +49,8 @@ public: bool IsServerClosed() const; // Overridden virtual functions. - virtual void Destroy() override; - virtual bool IsSignaled() const override; + void Destroy() override; + bool IsSignaled() const override; ResultCode CreateSession(KClientSession** out); diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h index 720a8c243..b11d5b4e3 100755 --- a/src/core/hle/kernel/k_client_session.h +++ b/src/core/hle/kernel/k_client_session.h @@ -34,7 +34,7 @@ class KClientSession final public: explicit KClientSession(KernelCore& kernel_); - virtual ~KClientSession(); + ~KClientSession() override; void Initialize(KSession* parent_, std::string&& name_) { // Set member variables. @@ -42,7 +42,7 @@ public: name = std::move(name_); } - virtual void Destroy() override; + void Destroy() override; static void PostDestroy([[maybe_unused]] uintptr_t arg) {} KSession* GetParent() const { diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h index 9a59ffb70..3d3ec99e2 100755 --- a/src/core/hle/kernel/k_event.h +++ b/src/core/hle/kernel/k_event.h @@ -20,23 +20,21 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer(owner); } - static void PostDestroy(uintptr_t arg); - - virtual KProcess* GetOwner() const override { + KProcess* GetOwner() const override { return owner; } @@ -48,6 +46,8 @@ public: return writable_event; } + static void PostDestroy(uintptr_t arg); + private: KReadableEvent readable_event; KWritableEvent writable_event; diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h index 960f1f3a3..4018ea2df 100755 --- a/src/core/hle/kernel/k_port.h +++ b/src/core/hle/kernel/k_port.h @@ -22,7 +22,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer; - public: explicit KServerPort(KernelCore& kernel_); - virtual ~KServerPort() override; + ~KServerPort() override; void Initialize(KPort* parent_, std::string&& name_); @@ -63,13 +60,14 @@ public: bool IsLight() const; // Overridden virtual functions. - virtual void Destroy() override; - virtual bool IsSignaled() const override; + void Destroy() override; + bool IsSignaled() const override; private: + using SessionList = boost::intrusive::list; + void CleanupSessions(); -private: SessionList session_list; SessionRequestHandlerPtr session_handler; KPort* parent{}; diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h index dd4de2904..27b757ad2 100755 --- a/src/core/hle/kernel/k_server_session.h +++ b/src/core/hle/kernel/k_server_session.h @@ -42,9 +42,9 @@ class KServerSession final : public KSynchronizationObject, public: explicit KServerSession(KernelCore& kernel_); - virtual ~KServerSession() override; + ~KServerSession() override; - virtual void Destroy() override; + void Destroy() override; void Initialize(KSession* parent_, std::string&& name_); @@ -56,7 +56,7 @@ public: return parent; } - virtual bool IsSignaled() const override; + bool IsSignaled() const override; void OnClientClosed(); diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h index a981fd1f6..4ddd080d2 100755 --- a/src/core/hle/kernel/k_session.h +++ b/src/core/hle/kernel/k_session.h @@ -18,17 +18,17 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer(process); } @@ -78,7 +78,6 @@ private: ServerClosed = 3, }; -private: void SetState(State state) { atomic_state = static_cast(state); } @@ -87,7 +86,6 @@ private: return static_cast(atomic_state.load(std::memory_order_relaxed)); } -private: KServerSession server; KClientSession client; std::atomic> atomic_state{ diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h index 553a56327..e9815f90b 100755 --- a/src/core/hle/kernel/k_shared_memory.h +++ b/src/core/hle/kernel/k_shared_memory.h @@ -68,9 +68,9 @@ public: return device_memory->GetPointer(physical_address + offset); } - virtual void Finalize() override; + void Finalize() override; - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return is_initialized; } static void PostDestroy([[maybe_unused]] uintptr_t arg) {} diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h index a41dd1220..3d4ce1fbc 100755 --- a/src/core/hle/kernel/k_synchronization_object.h +++ b/src/core/hle/kernel/k_synchronization_object.h @@ -29,7 +29,7 @@ public: KSynchronizationObject** objects, const s32 num_objects, s64 timeout); - virtual void Finalize() override; + void Finalize() override; [[nodiscard]] virtual bool IsSignaled() const = 0; @@ -37,7 +37,7 @@ public: protected: explicit KSynchronizationObject(KernelCore& kernel); - virtual ~KSynchronizationObject(); + ~KSynchronizationObject() override; virtual void OnFinalizeSynchronizationObject() {} diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index e3f08f256..3cf43d290 100755 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -168,13 +168,13 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s std::memset(static_cast(std::addressof(GetStackParameters())), 0, sizeof(StackParameters)); - // Setup the TLS, if needed. - if (type == ThreadType::User) { - tls_address = owner->CreateTLSRegion(); - } - // Set parent, if relevant. if (owner != nullptr) { + // Setup the TLS, if needed. + if (type == ThreadType::User) { + tls_address = owner->CreateTLSRegion(); + } + parent = owner; parent->Open(); parent->IncrementThreadCount(); diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h index 4abfc2b49..01eebb165 100755 --- a/src/core/hle/kernel/k_thread.h +++ b/src/core/hle/kernel/k_thread.h @@ -358,21 +358,21 @@ public: return termination_requested || GetRawState() == ThreadState::Terminated; } - [[nodiscard]] virtual u64 GetId() const override final { + [[nodiscard]] u64 GetId() const override { return this->GetThreadID(); } - [[nodiscard]] virtual bool IsInitialized() const override { + [[nodiscard]] bool IsInitialized() const override { return initialized; } - [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override { + [[nodiscard]] uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast(parent) | (resource_limit_release_hint ? 1 : 0); } - virtual void Finalize() override; + void Finalize() override; - [[nodiscard]] virtual bool IsSignaled() const override; + [[nodiscard]] bool IsSignaled() const override; static void PostDestroy(uintptr_t arg); diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h index c2d0f1eaf..31029a5c2 100755 --- a/src/core/hle/kernel/k_transfer_memory.h +++ b/src/core/hle/kernel/k_transfer_memory.h @@ -27,23 +27,23 @@ class KTransferMemory final public: explicit KTransferMemory(KernelCore& kernel_); - virtual ~KTransferMemory() override; + ~KTransferMemory() override; ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_); - virtual void Finalize() override; + void Finalize() override; - virtual bool IsInitialized() const override { + bool IsInitialized() const override { return is_initialized; } - virtual uintptr_t GetPostDestroyArgument() const override { + uintptr_t GetPostDestroyArgument() const override { return reinterpret_cast(owner); } static void PostDestroy(uintptr_t arg); - KProcess* GetOwner() const { + KProcess* GetOwner() const override { return owner; } diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h index 607b0eadb..858d982c4 100755 --- a/src/core/hle/kernel/k_writable_event.h +++ b/src/core/hle/kernel/k_writable_event.h @@ -21,7 +21,7 @@ public: explicit KWritableEvent(KernelCore& kernel_); ~KWritableEvent() override; - virtual void Destroy() override; + void Destroy() override; static void PostDestroy([[maybe_unused]] uintptr_t arg) {} diff --git a/src/core/memory.cpp b/src/core/memory.cpp index bf2ef7816..9857278f6 100755 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -591,7 +591,15 @@ struct Memory::Impl { * @returns The instance of T read from the specified virtual address. */ template - T Read(const VAddr vaddr) { + T Read(VAddr vaddr) { + // AARCH64 masks the upper 16 bit of all memory accesses + vaddr &= 0xffffffffffffLL; + + if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { + LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr); + return 0; + } + // Avoid adding any extra logic to this fast-path block const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); if (const u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { @@ -629,7 +637,16 @@ struct Memory::Impl { * is undefined. */ template - void Write(const VAddr vaddr, const T data) { + void Write(VAddr vaddr, const T data) { + // AARCH64 masks the upper 16 bit of all memory accesses + vaddr &= 0xffffffffffffLL; + + if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { + LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, + static_cast(data), vaddr); + return; + } + // Avoid adding any extra logic to this fast-path block const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { @@ -656,7 +673,16 @@ struct Memory::Impl { } template - bool WriteExclusive(const VAddr vaddr, const T data, const T expected) { + bool WriteExclusive(VAddr vaddr, const T data, const T expected) { + // AARCH64 masks the upper 16 bit of all memory accesses + vaddr &= 0xffffffffffffLL; + + if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { + LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, + static_cast(data), vaddr); + return true; + } + const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { // NOTE: Avoid adding any extra logic to this fast-path block @@ -683,7 +709,16 @@ struct Memory::Impl { return true; } - bool WriteExclusive128(const VAddr vaddr, const u128 data, const u128 expected) { + bool WriteExclusive128(VAddr vaddr, const u128 data, const u128 expected) { + // AARCH64 masks the upper 16 bit of all memory accesses + vaddr &= 0xffffffffffffLL; + + if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) { + LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8, + static_cast(data[0]), vaddr); + return true; + } + const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw(); if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) { // NOTE: Avoid adding any extra logic to this fast-path block diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 37f7b24e1..35cc561be 100755 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -104,7 +104,13 @@ void GPU::WaitFence(u32 syncpoint_id, u32 value) { } MICROPROFILE_SCOPE(GPU_wait); std::unique_lock lock{sync_mutex}; - sync_cv.wait(lock, [=, this] { return syncpoints.at(syncpoint_id).load() >= value; }); + sync_cv.wait(lock, [=, this] { + if (shutting_down.load(std::memory_order_relaxed)) { + // We're shutting down, ensure no threads continue to wait for the next syncpoint + return true; + } + return syncpoints.at(syncpoint_id).load() >= value; + }); } void GPU::IncrementSyncPoint(const u32 syncpoint_id) { @@ -523,6 +529,10 @@ void GPU::TriggerCpuInterrupt(const u32 syncpoint_id, const u32 value) const { } void GPU::ShutDown() { + // Signal that threads should no longer block on syncpoint fences + shutting_down.store(true, std::memory_order_relaxed); + sync_cv.notify_all(); + gpu_thread.ShutDown(); } diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h index 29a867863..a8e98e51b 100755 --- a/src/video_core/gpu.h +++ b/src/video_core/gpu.h @@ -389,6 +389,8 @@ private: std::unique_ptr kepler_memory; /// Shader build notifier std::unique_ptr shader_notify; + /// When true, we are about to shut down emulation session, so terminate outstanding tasks + std::atomic_bool shutting_down{}; std::array, Service::Nvidia::MaxSyncPoints> syncpoints{};