summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar bunnei2022-06-21 16:04:57 -0700
committerGravatar GitHub2022-06-21 16:04:57 -0700
commit737c446fc18618cf80a1243104ac8f5114c29a22 (patch)
tree881e88bcc52e4d0639906f61a9b1a5292e36767d /src/core/hle/kernel
parentMerge pull request #8468 from liamwhite/dispatch-tracking (diff)
parentcore/debugger: memory breakpoint support (diff)
downloadyuzu-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.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 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
582bool 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
604bool 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
582void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { 628void 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
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 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();