summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Liam2022-06-06 12:56:01 -0400
committerGravatar Liam2022-06-16 13:18:07 -0400
commit208ed712f42cfd277405a22663197dc1c5e84cfe (patch)
tree56c1a3cbddf392d700e817cd4093564e3f096013 /src/core/hle/kernel
parentMerge pull request #8457 from liamwhite/kprocess-suspend (diff)
downloadyuzu-208ed712f42cfd277405a22663197dc1c5e84cfe.tar.gz
yuzu-208ed712f42cfd277405a22663197dc1c5e84cfe.tar.xz
yuzu-208ed712f42cfd277405a22663197dc1c5e84cfe.zip
core/debugger: memory breakpoint support
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/k_process.cpp46
-rw-r--r--src/core/hle/kernel/k_process.h30
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp1
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 cd863e715..6a73f6783 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -584,6 +584,52 @@ ResultCode KProcess::DeleteThreadLocalRegion(VAddr addr) {
584 return ResultSuccess; 584 return ResultSuccess;
585} 585}
586 586
587bool KProcess::InsertWatchpoint(Core::System& system, VAddr addr, u64 size,
588 DebugWatchpointType type) {
589 const auto watch{std::find_if(watchpoints.begin(), watchpoints.end(), [&](const auto& wp) {
590 return wp.type == DebugWatchpointType::None;
591 })};
592
593 if (watch == watchpoints.end()) {
594 return false;
595 }
596
597 watch->start_address = addr;
598 watch->end_address = addr + size;
599 watch->type = type;
600
601 for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) {
602 debug_page_refcounts[page]++;
603 system.Memory().MarkRegionDebug(page, PageSize, true);
604 }
605
606 return true;
607}
608
609bool KProcess::RemoveWatchpoint(Core::System& system, VAddr addr, u64 size,
610 DebugWatchpointType type) {
611 const auto watch{std::find_if(watchpoints.begin(), watchpoints.end(), [&](const auto& wp) {
612 return wp.start_address == addr && wp.end_address == addr + size && wp.type == type;
613 })};
614
615 if (watch == watchpoints.end()) {
616 return false;
617 }
618
619 watch->start_address = 0;
620 watch->end_address = 0;
621 watch->type = DebugWatchpointType::None;
622
623 for (VAddr page = Common::AlignDown(addr, PageSize); page < addr + size; page += PageSize) {
624 debug_page_refcounts[page]--;
625 if (!debug_page_refcounts[page]) {
626 system.Memory().MarkRegionDebug(page, PageSize, false);
627 }
628 }
629
630 return true;
631}
632
587void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { 633void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
588 const auto ReprotectSegment = [&](const CodeSet::Segment& segment, 634 const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
589 Svc::MemoryPermission permission) { 635 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
72enum class DebugWatchpointType : u8 {
73 None = 0,
74 Read = 1 << 0,
75 Write = 1 << 1,
76 ReadOrWrite = Read | Write,
77};
78DECLARE_ENUM_FLAG_OPERATORS(DebugWatchpointType);
79
80struct DebugWatchpoint {
81 VAddr start_address;
82 VAddr end_address;
83 DebugWatchpointType type;
84};
85
71class KProcess final : public KAutoObjectWithSlabHeapAndContainer<KProcess, KWorkerTask> { 86class 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
377private: 405private:
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 2d4e8637b..edd0e4eae 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();