diff --git a/externals/catch b/externals/catch index d2a130f243..cd76f5730c 160000 --- a/externals/catch +++ b/externals/catch @@ -1 +1 @@ -Subproject commit d2a130f2433aeaca070e3e4d6298a80049d21cfc +Subproject commit cd76f5730c9a3afa19f3b9c83608d9c7ab325a19 diff --git a/externals/xbyak b/externals/xbyak index 71b75f653f..2794cde79e 160000 --- a/externals/xbyak +++ b/externals/xbyak @@ -1 +1 @@ -Subproject commit 71b75f653f3858403eb33d48f6346eef34b837fe +Subproject commit 2794cde79eb71e86490061cac9622ad0067b8d15 diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index ceb3f76835..73a83f2ef3 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -10,6 +10,7 @@ #include "core/arm/dynarmic/arm_dynarmic.h" #include "core/core.h" #include "core/core_timing.h" +#include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/svc.h" #include "core/memory.h" diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp index 4c11f35a49..6bc3494601 100644 --- a/src/core/arm/unicorn/arm_unicorn.cpp +++ b/src/core/arm/unicorn/arm_unicorn.cpp @@ -203,7 +203,7 @@ void ARM_Unicorn::ExecuteInstructions(int num_instructions) { } Kernel::Thread* thread = Kernel::GetCurrentThread(); SaveContext(thread->context); - if (last_bkpt_hit || (num_instructions == 1)) { + if (last_bkpt_hit || GDBStub::GetCpuStepFlag()) { last_bkpt_hit = false; GDBStub::Break(); GDBStub::SendTrap(thread, 5); diff --git a/src/core/core.cpp b/src/core/core.cpp index e01c45cddc..4ac22e44f6 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -62,7 +62,6 @@ System::ResultStatus System::RunLoop(bool tight_loop) { // execute. Otherwise, get out of the loop function. if (GDBStub::GetCpuHaltFlag()) { if (GDBStub::GetCpuStepFlag()) { - GDBStub::SetCpuStepFlag(false); tight_loop = false; } else { return ResultStatus::Success; @@ -78,6 +77,11 @@ System::ResultStatus System::RunLoop(bool tight_loop) { } } + if (GDBStub::IsServerEnabled()) { + GDBStub::SetCpuStepFlag(false); + GDBStub::SetInstCacheValidity(true); + } + return status; } diff --git a/src/core/core.h b/src/core/core.h index a3be88aa8a..677665caec 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -82,6 +82,17 @@ public: */ ResultStatus SingleStep(); + /** + * Invalidate the CPU instruction caches + * This function should only be used by GDBStub which is supposed to keep things + * synch'ed to its internal instruction cache validity flag. + */ + void InvalidateCpuInstructionCaches() { + for (auto& cpu : cpu_cores) { + cpu->ArmInterface().ClearInstructionCache(); + } + } + /// Shutdown the emulated system. void Shutdown(); diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 884e64e994..3daff2dc32 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -160,6 +160,7 @@ u16 gdbstub_port = 24689; bool halt_loop = true; bool step_loop = false; bool send_trap = false; +bool inst_cache_valid = true; // If set to false, the server will never be started and no // gdbstub-related functions will be executed. @@ -173,6 +174,7 @@ struct Breakpoint { bool active; VAddr addr; u64 len; + u8 inst[4]; }; using BreakpointMap = std::map; @@ -453,6 +455,8 @@ static void RemoveBreakpoint(BreakpointType type, VAddr addr) { LOG_DEBUG(Debug_GDBStub, "gdb: removed a breakpoint: {:016X} bytes at {:016X} of type {}", bp->second.len, bp->second.addr, static_cast(type)); + Memory::WriteBlock(bp->second.addr, bp->second.inst, 4); + GDBStub::SetInstCacheValidity(false); p.erase(addr); } @@ -937,6 +941,7 @@ static void WriteMemory() { GdbHexToMem(data.data(), len_pos + 1, len); Memory::WriteBlock(addr, data.data(), len); + GDBStub::SetInstCacheValidity(false); SendReply("OK"); } @@ -956,6 +961,7 @@ static void Step() { step_loop = true; halt_loop = true; send_trap = true; + GDBStub::SetInstCacheValidity(false); } /// Tell the CPU if we hit a memory breakpoint. @@ -972,6 +978,7 @@ static void Continue() { memory_break = false; step_loop = false; halt_loop = false; + GDBStub::SetInstCacheValidity(false); } /** @@ -988,6 +995,10 @@ static bool CommitBreakpoint(BreakpointType type, VAddr addr, u64 len) { breakpoint.active = true; breakpoint.addr = addr; breakpoint.len = len; + Memory::ReadBlock(addr, breakpoint.inst, 4); + static const u8 btrap[] = {0xd4, 0x20, 0x7d, 0x00}; + Memory::WriteBlock(addr, btrap, 4); + GDBStub::SetInstCacheValidity(false); p.insert({addr, breakpoint}); LOG_DEBUG(Debug_GDBStub, "gdb: added {} breakpoint: {:016X} bytes at {:016X}", @@ -1305,4 +1316,15 @@ void SendTrap(Kernel::Thread* thread, int trap) { send_trap = false; } } + +void SetInstCacheValidity(bool is_valid) { + inst_cache_valid = is_valid; + if (!inst_cache_valid) { + Core::System::GetInstance().InvalidateCpuInstructionCaches(); + } +} + +bool GetInstCacheValidity() { + return inst_cache_valid; +} }; // namespace GDBStub diff --git a/src/core/gdbstub/gdbstub.h b/src/core/gdbstub/gdbstub.h index 5a36524b2e..ca58392f84 100644 --- a/src/core/gdbstub/gdbstub.h +++ b/src/core/gdbstub/gdbstub.h @@ -104,4 +104,10 @@ void SetCpuStepFlag(bool is_step); * @param trap Trap no. */ void SendTrap(Kernel::Thread* thread, int trap); + +/// Set instruction cache validity. +void SetInstCacheValidity(bool is_valid); + +/// Get instruction cache validity. +bool GetInstCacheValidity(); } // namespace GDBStub diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index e17d637e43..aa37aa0442 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -296,6 +296,10 @@ void RegisterFileSystems() { auto sdcard = std::make_unique(std::move(sd_directory)); sdmc_factory = std::move(sdcard); + + auto romfs = + std::make_unique(Core::System::GetInstance().GetAppLoader()); + romfs_factory = std::move(romfs); } void InstallInterfaces(SM::ServiceManager& service_manager) { diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 993f1e65a2..a1157ce6a7 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -551,7 +551,7 @@ private: } else if (transaction == TransactionId::CancelBuffer) { LOG_CRITICAL(Service_VI, "(STUBBED) called, transaction=CancelBuffer"); } else { - ASSERT_MSG(false, "Unimplemented"); + UNIMPLEMENTED(); } IPC::ResponseBuilder rb{ctx, 2}; diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index 118e91cf1b..5ae7276bd2 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui @@ -22,13 +22,6 @@ GDB - - - - The GDB Stub only works correctly when the CPU JIT is off. - - -