/* * Copyright 2023 Advanced Micro Devices, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE.
*/
if (error_reason & (KFD_EC_MASK(EC_PROCESS_RUNTIME))) { /* * block should only happen after the debugger receives runtime * enable notice.
*/
up(&p->runtime_enable_sema);
error_reason &= ~KFD_EC_MASK(EC_PROCESS_RUNTIME);
}
if (error_reason) return kfd_send_exception_to_runtime(p, queue_id, error_reason);
if (!pdd->dev->kfd->shared_resources.enable_mes)
r = debug_map_and_unlock(pdd->dev->dqm); else
r = kfd_dbg_set_mes_debug_mode(pdd, true);
kfd_dbg_clear_dev_watch_id(pdd, watch_id);
return r;
}
int kfd_dbg_trap_set_dev_address_watch(struct kfd_process_device *pdd,
uint64_t watch_address,
uint32_t watch_address_mask,
uint32_t *watch_id,
uint32_t watch_mode)
{ int xcc_id, r = kfd_dbg_get_dev_watch_id(pdd, watch_id);
uint32_t xcc_mask = pdd->dev->xcc_mask;
if (r) return r;
if (!pdd->dev->kfd->shared_resources.enable_mes) {
r = debug_lock_and_unmap(pdd->dev->dqm); if (r) {
kfd_dbg_clear_dev_watch_id(pdd, *watch_id); return r;
}
}
target->dbg_flags = *flags;
*flags = prev_flags; for (i = 0; i < target->n_pdds; i++) { struct kfd_process_device *pdd = target->pdds[i];
if (!kfd_dbg_is_per_vmid_supported(pdd->dev)) continue;
if (!pdd->dev->kfd->shared_resources.enable_mes)
r = debug_refresh_runlist(pdd->dev->dqm); else
r = kfd_dbg_set_mes_debug_mode(pdd, true);
if (r) {
target->dbg_flags = prev_flags; break;
}
rewind_count++;
}
/* Rewind flags */ if (r) {
target->dbg_flags = prev_flags;
for (i = 0; i < rewind_count; i++) { struct kfd_process_device *pdd = target->pdds[i];
if (!kfd_dbg_is_per_vmid_supported(pdd->dev)) continue;
if (!pdd->dev->kfd->shared_resources.enable_mes)
debug_refresh_runlist(pdd->dev->dqm); else
kfd_dbg_set_mes_debug_mode(pdd, true);
}
}
return r;
}
/* kfd_dbg_trap_deactivate: * target: target process * unwind: If this is unwinding a failed kfd_dbg_trap_enable() * unwind_count: * If unwind == true, how far down the pdd list we need * to unwind * else: ignored
*/ void kfd_dbg_trap_deactivate(struct kfd_process *target, bool unwind, int unwind_count)
{ int i;
if (!unwind) {
uint32_t flags = 0; int resume_count = resume_queues(target, 0, NULL);
if (resume_count)
pr_debug("Resumed %d queues\n", resume_count);
for (i = 0; i < target->n_pdds; i++) { struct kfd_process_device *pdd = target->pdds[i];
/* If this is an unwind, and we have unwound the required * enable calls on the pdd list, we need to stop now * otherwise we may mess up another debugger session.
*/ if (unwind && i == unwind_count) break;
/* GFX off is already disabled by debug activate if not RLC restore supported. */ if (kfd_dbg_is_rlc_restore_supported(pdd->dev))
amdgpu_gfx_off_ctrl(pdd->dev->adev, false);
pdd->spi_dbg_override =
pdd->dev->kfd2kgd->disable_debug_trap(
pdd->dev->adev,
target->runtime_info.ttmp_setup,
pdd->dev->vm_info.last_vmid_kfd);
amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
if (!kfd_dbg_is_per_vmid_supported(pdd->dev) &&
release_debug_trap_vmid(pdd->dev->dqm, &pdd->qpd))
pr_err("Failed to release debug vmid on [%i]\n", pdd->dev->id);
if (!pdd->dev->kfd->shared_resources.enable_mes)
debug_refresh_runlist(pdd->dev->dqm); else
kfd_dbg_set_mes_debug_mode(pdd, !kfd_dbg_has_cwsr_workaround(pdd->dev));
}
/* Disable GFX OFF to prevent garbage read/writes to debug registers. * If RLC restore of debug registers is not supported and runtime enable * hasn't done so already on ttmp setup request, restore the trap config registers. * * If RLC restore of debug registers is not supported, keep gfx off disabled for * the debug session.
*/
amdgpu_gfx_off_ctrl(pdd->dev->adev, false); if (!(kfd_dbg_is_rlc_restore_supported(pdd->dev) ||
target->runtime_info.ttmp_setup))
pdd->dev->kfd2kgd->enable_debug_trap(pdd->dev->adev, true,
pdd->dev->vm_info.last_vmid_kfd);
if (kfd_dbg_is_rlc_restore_supported(pdd->dev))
amdgpu_gfx_off_ctrl(pdd->dev->adev, true);
/* * Setting the debug flag in the trap handler requires that the TMA has been * allocated, which occurs during CWSR initialization. * In the event that CWSR has not been initialized at this point, setting the * flag will be called again during CWSR initialization if the target process * is still debug enabled.
*/
kfd_process_set_trap_debug_flag(&pdd->qpd, true);
if (!pdd->dev->kfd->shared_resources.enable_mes)
r = debug_refresh_runlist(pdd->dev->dqm); else
r = kfd_dbg_set_mes_debug_mode(pdd, true);
if (r) {
target->runtime_info.runtime_state =
DEBUG_RUNTIME_STATE_ENABLED_ERROR; goto unwind_err;
}
}
return 0;
unwind_err: /* Enabling debug failed, we need to disable on * all GPUs so the enable is all or nothing.
*/
kfd_dbg_trap_deactivate(target, true, i); return r;
}
int kfd_dbg_trap_enable(struct kfd_process *target, uint32_t fd, void __user *runtime_info, uint32_t *runtime_size)
{ struct file *f;
uint32_t copy_size; int i, r = 0;
if (target->debug_trap_enabled) return -EALREADY;
/* Enable pre-checks */ for (i = 0; i < target->n_pdds; i++) { struct kfd_process_device *pdd = target->pdds[i];
if (!KFD_IS_SOC15(pdd->dev)) return -ENODEV;
if (pdd->qpd.num_gws && (!kfd_dbg_has_gws_support(pdd->dev) ||
kfd_dbg_has_cwsr_workaround(pdd->dev))) return -EBUSY;
}
f = fget(fd); if (!f) {
pr_err("Failed to get file for (%i)\n", fd); return -EBADF;
}
target->dbg_ev_file = f;
/* defer activation to runtime if not runtime enabled */ if (target->runtime_info.runtime_state == DEBUG_RUNTIME_STATE_ENABLED)
kfd_dbg_trap_activate(target);
/* We already hold the process reference but hold another one for the * debug session.
*/
kref_get(&target->ref);
target->debug_trap_enabled = true;
if (target->debugger_process)
atomic_inc(&target->debugger_process->debugged_process_count);
if (copy_to_user(runtime_info, (void *)&target->runtime_info, copy_size)) {
kfd_dbg_trap_deactivate(target, false, 0);
r = -EFAULT;
}
*runtime_size = sizeof(target->runtime_info);
return r;
}
staticint kfd_dbg_validate_trap_override_request(struct kfd_process *p,
uint32_t trap_override,
uint32_t trap_mask_request,
uint32_t *trap_mask_supported)
{ int i = 0;
*trap_mask_supported = 0xffffffff;
for (i = 0; i < p->n_pdds; i++) { struct kfd_process_device *pdd = p->pdds[i]; int err = pdd->dev->kfd2kgd->validate_trap_override_request(
pdd->dev->adev,
trap_override,
trap_mask_supported);
if (err) return err;
}
if (trap_mask_request & ~*trap_mask_supported) return -EACCES;
return 0;
}
int kfd_dbg_trap_set_wave_launch_override(struct kfd_process *target,
uint32_t trap_override,
uint32_t trap_mask_bits,
uint32_t trap_mask_request,
uint32_t *trap_mask_prev,
uint32_t *trap_mask_supported)
{ int r = 0, i;
r = kfd_dbg_validate_trap_override_request(target,
trap_override,
trap_mask_request,
trap_mask_supported);
if (r) return r;
for (i = 0; i < target->n_pdds; i++) { struct kfd_process_device *pdd = target->pdds[i];
/* Run over all pdd of the process */ for (i = 0; i < tmp_num_devices; i++) { struct kfd_process_device *pdd = target->pdds[i]; struct kfd_topology_device *topo_dev = kfd_topology_device_by_id(pdd->dev->id);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.