#include "amdgpu.h"
 #include "amdgpu_amdkfd.h"
 #include "amdgpu_amdkfd_arcturus.h"
+#include "amdgpu_reset.h"
 #include "sdma0/sdma0_4_2_2_offset.h"
 #include "sdma0/sdma0_4_2_2_sh_mask.h"
 #include "sdma1/sdma1_4_2_2_offset.h"
 #include "amdgpu_amdkfd_gfx_v9.h"
 #include "gfxhub_v1_0.h"
 #include "mmhub_v9_4.h"
+#include "gc/gc_9_0_offset.h"
+#include "gc/gc_9_0_sh_mask.h"
 
 #define HQD_N_REGS 56
 #define DUMP_REG(addr) do {                            \
        return 0;
 }
 
+/*
+ * Helper used to suspend/resume gfx pipe for image post process work to set
+ * barrier behaviour.
+ */
+static int suspend_resume_compute_scheduler(struct amdgpu_device *adev, bool suspend)
+{
+       int i, r = 0;
+
+       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
+               struct amdgpu_ring *ring = &adev->gfx.compute_ring[i];
+
+               if (!(ring && ring->sched.thread))
+                       continue;
+
+               /* stop secheduler and drain ring. */
+               if (suspend) {
+                       drm_sched_stop(&ring->sched, NULL);
+                       r = amdgpu_fence_wait_empty(ring);
+                       if (r)
+                               goto out;
+               } else {
+                       drm_sched_start(&ring->sched, false);
+               }
+       }
+
+out:
+       /* return on resume or failure to drain rings. */
+       if (!suspend || r)
+               return r;
+
+       return amdgpu_device_ip_wait_for_idle(adev, GC_HWIP);
+}
+
+static void set_barrier_auto_waitcnt(struct amdgpu_device *adev, bool enable_waitcnt)
+{
+       uint32_t data;
+
+       WRITE_ONCE(adev->barrier_has_auto_waitcnt, enable_waitcnt);
+
+       if (!down_read_trylock(&adev->reset_domain->sem))
+               return;
+
+       amdgpu_amdkfd_suspend(adev, false);
+
+       if (suspend_resume_compute_scheduler(adev, true))
+               goto out;
+
+       data = RREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CONFIG));
+       data = REG_SET_FIELD(data, SQ_CONFIG, DISABLE_BARRIER_WAITCNT,
+                                               !enable_waitcnt);
+       WREG32(SOC15_REG_OFFSET(GC, 0, mmSQ_CONFIG), data);
+
+out:
+       suspend_resume_compute_scheduler(adev, false);
+
+       amdgpu_amdkfd_resume(adev, false);
+
+       up_read(&adev->reset_domain->sem);
+}
+
+/*
+ * restore_dbg_registers is ignored here but is a general interface requirement
+ * for devices that support GFXOFF and where the RLC save/restore list
+ * does not support hw registers for debugging i.e. the driver has to manually
+ * initialize the debug mode registers after it has disabled GFX off during the
+ * debug session.
+ */
+static uint32_t kgd_arcturus_enable_debug_trap(struct amdgpu_device *adev,
+                               bool restore_dbg_registers,
+                               uint32_t vmid)
+{
+       mutex_lock(&adev->grbm_idx_mutex);
+
+       kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+       set_barrier_auto_waitcnt(adev, true);
+
+       WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+       kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+       mutex_unlock(&adev->grbm_idx_mutex);
+
+       return 0;
+}
+
+/*
+ * keep_trap_enabled is ignored here but is a general interface requirement
+ * for devices that support multi-process debugging where the performance
+ * overhead from trap temporary setup needs to be bypassed when the debug
+ * session has ended.
+ */
+static uint32_t kgd_arcturus_disable_debug_trap(struct amdgpu_device *adev,
+                                       bool keep_trap_enabled,
+                                       uint32_t vmid)
+{
+
+       mutex_lock(&adev->grbm_idx_mutex);
+
+       kgd_gfx_v9_set_wave_launch_stall(adev, vmid, true);
+
+       set_barrier_auto_waitcnt(adev, false);
+
+       WREG32(SOC15_REG_OFFSET(GC, 0, mmSPI_GDBG_TRAP_MASK), 0);
+
+       kgd_gfx_v9_set_wave_launch_stall(adev, vmid, false);
+
+       mutex_unlock(&adev->grbm_idx_mutex);
+
+       return 0;
+}
 const struct kfd2kgd_calls arcturus_kfd2kgd = {
        .program_sh_mem_settings = kgd_gfx_v9_program_sh_mem_settings,
        .set_pasid_vmid_mapping = kgd_gfx_v9_set_pasid_vmid_mapping,
                                kgd_gfx_v9_get_atc_vmid_pasid_mapping_info,
        .set_vm_context_page_table_base =
                                kgd_gfx_v9_set_vm_context_page_table_base,
+       .enable_debug_trap = kgd_arcturus_enable_debug_trap,
+       .disable_debug_trap = kgd_arcturus_disable_debug_trap,
        .get_cu_occupancy = kgd_gfx_v9_get_cu_occupancy,
        .program_trap_handler_settings = kgd_gfx_v9_program_trap_handler_settings
 };