diff options
| author | 2022-06-21 16:04:57 -0700 | |
|---|---|---|
| committer | 2022-06-21 16:04:57 -0700 | |
| commit | 737c446fc18618cf80a1243104ac8f5114c29a22 (patch) | |
| tree | 881e88bcc52e4d0639906f61a9b1a5292e36767d /src/core/hle/kernel | |
| parent | Merge pull request #8468 from liamwhite/dispatch-tracking (diff) | |
| parent | core/debugger: memory breakpoint support (diff) | |
| download | yuzu-737c446fc18618cf80a1243104ac8f5114c29a22.tar.gz yuzu-737c446fc18618cf80a1243104ac8f5114c29a22.tar.xz yuzu-737c446fc18618cf80a1243104ac8f5114c29a22.zip | |
Merge pull request #8432 from liamwhite/watchpoint
core/debugger: memory breakpoint support
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/k_process.cpp | 46 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_process.h | 30 | ||||
| -rw-r--r-- | src/core/hle/kernel/k_scheduler.cpp | 1 |
3 files changed, 77 insertions, 0 deletions
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 61a4fb464..cb84c20e3 100644 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp | |||
| @@ -579,6 +579,52 @@ ResultCode KProcess::DeleteThreadLocalRegion(VAddr addr) { | |||
| 579 | return ResultSuccess; | 579 | return ResultSuccess; |
| 580 | } | 580 | } |
| 581 | 581 | ||
| 582 | bool KProcess::InsertWatchpoint(Core::System& system, VAddr addr, u64 size, | ||
| 583 | DebugWatchpointType type) { | ||
| 584 | const auto watch{std::find_if(watchpoints.begin(), watchpoints.end(), [&](const auto& wp) { | ||
| 585 | return wp.type == DebugWatchpointType::None; | ||
| 586 | })}; | ||
| 587 | |||
| 588 | if (watch == watchpoints.end()) { | ||
| 589 | return false; | ||
| 590 | } | ||
| 591 | |||
| 592 | watch->start_address = addr; | ||
| 593 | watch->end_address = addr + size; | ||
| 594 | watch->type = type; | ||
| 595 | |||
| 596 | for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) { | ||
| 597 | debug_page_refcounts[page]++; | ||
| 598 | system.Memory().MarkRegionDebug(page, PageSize, true); | ||
| 599 | } | ||
| 600 | |||
| 601 | return true; | ||
| 602 | } | ||
| 603 | |||
| 604 | bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size, | ||
| 605 | DebugWatchpointType type) { | ||
| 606 | const auto watch{std::find_if(watchpoints.begin(), watchpoints.end(), [&](const auto& wp) { | ||
| 607 | return wp.start_address == addr && wp.end_address == addr + size && wp.type == type; | ||
| 608 | })}; | ||
| 609 | |||
| 610 | if (watch == watchpoints.end()) { | ||
| 611 | return false; | ||
| 612 | } | ||
| 613 | |||
| 614 | watch->start_address = 0; | ||
| 615 | watch->end_address = 0; | ||
| 616 | watch->type = DebugWatchpointType::None; | ||
| 617 | |||
| 618 | for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) { | ||
| 619 | debug_page_refcounts[page]--; | ||
| 620 | if (!debug_page_refcounts[page]) { | ||
| 621 | system.Memory().MarkRegionDebug(page, PageSize, false); | ||
| 622 | } | ||
| 623 | } | ||
| 624 | |||
| 625 | return true; | ||
| 626 | } | ||
| 627 | |||
| 582 | void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { | 628 | void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { |
| 583 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, | 629 | const auto ReprotectSegment = [&](const CodeSet::Segment& segment, |
| 584 | Svc::MemoryPermission permission) { | 630 | Svc::MemoryPermission permission) { |
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index e562a79b8..c2086e5ba 100644 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | 8 | #include <cstddef> |
| 9 | #include <list> | 9 | #include <list> |
| 10 | #include <map> | ||
| 10 | #include <string> | 11 | #include <string> |
| 11 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 12 | #include "core/hle/kernel/k_address_arbiter.h" | 13 | #include "core/hle/kernel/k_address_arbiter.h" |
| @@ -68,6 +69,20 @@ enum class ProcessActivity : u32 { | |||
| 68 | Paused, | 69 | Paused, |
| 69 | }; | 70 | }; |
| 70 | 71 | ||
| 72 | enum class DebugWatchpointType : u8 { | ||
| 73 | None = 0, | ||
| 74 | Read = 1 << 0, | ||
| 75 | Write = 1 << 1, | ||
| 76 | ReadOrWrite = Read | Write, | ||
| 77 | }; | ||
| 78 | DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType); | ||
| 79 | |||
| 80 | struct DebugWatchpoint { | ||
| 81 | VAddr start_address; | ||
| 82 | VAddr end_address; | ||
| 83 | DebugWatchpointType type; | ||
| 84 | }; | ||
| 85 | |||
| 71 | class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { | 86 | class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { |
| 72 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); | 87 | KERNEL_AUTOOBJECT_TRAITS(KProcess, KSynchronizationObject); |
| 73 | 88 | ||
| @@ -374,6 +389,19 @@ public: | |||
| 374 | // Frees a used TLS slot identified by the given address | 389 | // Frees a used TLS slot identified by the given address |
| 375 | ResultCode DeleteThreadLocalRegion(VAddr addr); | 390 | ResultCode DeleteThreadLocalRegion(VAddr addr); |
| 376 | 391 | ||
| 392 | /////////////////////////////////////////////////////////////////////////////////////////////// | ||
| 393 | // Debug watchpoint management | ||
| 394 | |||
| 395 | // Attempts to insert a watchpoint into a free slot. Returns false if none are available. | ||
| 396 | bool InsertWatchpoint(Core::System& system, VAddr addr, u64 size, DebugWatchpointType type); | ||
| 397 | |||
| 398 | // Attempts to remove the watchpoint specified by the given parameters. | ||
| 399 | bool RemoveWatchpoint(Core::System& system, VAddr addr, u64 size, DebugWatchpointType type); | ||
| 400 | |||
| 401 | const std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>& GetWatchpoints() const { | ||
| 402 | return watchpoints; | ||
| 403 | } | ||
| 404 | |||
| 377 | private: | 405 | private: |
| 378 | void PinThread(s32 core_id, KThread* thread) { | 406 | void PinThread(s32 core_id, KThread* thread) { |
| 379 | ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); | 407 | ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); |
| @@ -478,6 +506,8 @@ private: | |||
| 478 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> running_threads{}; | 506 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> running_threads{}; |
| 479 | std::array<u64, Core::Hardware::NUM_CPU_CORES> running_thread_idle_counts{}; | 507 | std::array<u64, Core::Hardware::NUM_CPU_CORES> running_thread_idle_counts{}; |
| 480 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> pinned_threads{}; | 508 | std::array<KThread*, Core::Hardware::NUM_CPU_CORES> pinned_threads{}; |
| 509 | std::array<DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS> watchpoints{}; | ||
| 510 | std::map<VAddr, u64> debug_page_refcounts; | ||
| 481 | 511 | ||
| 482 | KThread* exception_thread{}; | 512 | KThread* exception_thread{}; |
| 483 | 513 | ||
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 7e03b26f8..fb3b84f3d 100644 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp | |||
| @@ -710,6 +710,7 @@ void KScheduler::Reload(KThread* thread) { | |||
| 710 | Core::ARM_Interface& cpu_core = system.ArmInterface(core_id); | 710 | Core::ARM_Interface& cpu_core = system.ArmInterface(core_id); |
| 711 | cpu_core.LoadContext(thread->GetContext32()); | 711 | cpu_core.LoadContext(thread->GetContext32()); |
| 712 | cpu_core.LoadContext(thread->GetContext64()); | 712 | cpu_core.LoadContext(thread->GetContext64()); |
| 713 | cpu_core.LoadWatchpointArray(thread->GetOwnerProcess()->GetWatchpoints()); | ||
| 713 | cpu_core.SetTlsAddress(thread->GetTLSAddress()); | 714 | cpu_core.SetTlsAddress(thread->GetTLSAddress()); |
| 714 | cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0()); | 715 | cpu_core.SetTPIDR_EL0(thread->GetTPIDR_EL0()); |
| 715 | cpu_core.ClearExclusiveState(); | 716 | cpu_core.ClearExclusiveState(); |