[PATCH] drm/amdgpu: Add atomic CPU-GPU clock counter correlation

Jesse Zhang jesse.zhang at amd.com
Fri Jul 11 08:35:58 UTC 2025


This patch introduces a new IOCTL to provide tightly correlated
CPU and GPU timestamps for accurate performance measurements
and synchronization between host and device timelines.

Key improvements:
1. Adds AMDGPU_INFO_CLOCK_COUNTERS query type (0x06)
2. Implements atomic sampling of clocks with:
   - preempt_disable()
   - local IRQ disabling
   - GPU timestamp sampled first (higher latency)
   - CPU timestamps sampled immediately after
3. Provides three correlated clocks:
   - GPU clock counter (ns)
   - CPU raw monotonic time (ns)
   - System boottime (ns)
4. Includes system clock frequency (1GHz) for reference

The implementation addresses the need for precise CPU-GPU
timestamp correlation in ROCm applications, particularly for:
- Performance analysis tools
- Compute pipeline synchronization
- Graphics/compute interoperability
- Low-latency VR/AR applications

Signed-off-by: Jesse Zhang <Jesse.Zhang at amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 44 +++++++++++++++++++++++++
 include/uapi/drm/amdgpu_drm.h           | 19 +++++++++++
 2 files changed, 63 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 931c52c918c4..8412c88aada9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -595,6 +595,43 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
 	return 0;
 }
 
+/**
+ * get_cpu_gpu_counters - Atomically sample CPU and GPU clocks
+ * @adev: amdgpu device pointer
+ * @args: structure to store clock counters
+ *
+ * Samples CPU and GPU clocks as close to simultaneously as possible
+ * by disabling preemption and interrupts during the sampling.
+ * Returns 0 on success.
+ */
+static int get_cpu_gpu_counters(struct amdgpu_device *adev,
+                               struct drm_amdgpu_info_clock_counters *args)
+{
+	unsigned long flags;
+
+	/* Disable preemption and interrupts on local CPU */
+	preempt_disable();
+	local_irq_save(flags);
+
+	if (adev->gfx.funcs->get_gpu_clock_counter)
+		args->gpu_clock_counter = adev->gfx.funcs->get_gpu_clock_counter(adev);
+	else
+		args->gpu_clock_counter = 0;
+
+	/* No access to rdtsc. Using raw monotonic time */
+	args->cpu_clock_counter = ktime_get_raw_ns();
+	args->system_clock_counter = ktime_get_boottime_ns();
+
+	/* Since the counter is in nano-seconds we use 1GHz frequency */
+	args->system_clock_freq = 1000000000;
+
+	/* Restore previous state */
+	local_irq_restore(flags);
+	preempt_enable();
+
+	return 0;
+}
+
 /*
  * Userspace get information ioctl
  */
@@ -734,6 +771,13 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp)
 	case AMDGPU_INFO_TIMESTAMP:
 		ui64 = amdgpu_gfx_get_gpu_clock_counter(adev);
 		return copy_to_user(out, &ui64, min(size, 8u)) ? -EFAULT : 0;
+	case AMDGPU_INFO_CLOCK_COUNTERS: {
+		struct drm_amdgpu_info_clock_counters counters;
+
+		 memset(&counters, 0, sizeof(counters));
+		get_cpu_gpu_counters(adev, &counters);
+		return copy_to_user(out, &counters, min(size, sizeof(counters))) ? -EFAULT : 0;
+	}
 	case AMDGPU_INFO_FW_VERSION: {
 		struct drm_amdgpu_info_firmware fw_info;
 
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index bdedbaccf776..e8adbbd076ca 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -1056,6 +1056,8 @@ struct drm_amdgpu_cs_chunk_cp_gfx_shadow {
 #define AMDGPU_INFO_HW_IP_COUNT			0x03
 /* timestamp for GL_ARB_timer_query */
 #define AMDGPU_INFO_TIMESTAMP			0x05
+/* get synchronized CPU and GPU clock counters  */
+#define AMDGPU_INFO_CLOCK_COUNTERS		0x06
 /* Query the firmware version */
 #define AMDGPU_INFO_FW_VERSION			0x0e
 	/* Subquery id: Query VCE firmware version */
@@ -1598,6 +1600,23 @@ struct drm_amdgpu_info_uq_metadata {
 	};
 };
 
+/**
+ * struct drm_amdgpu_info_clock_counters - Clock counter information
+ *
+ * Used to correlate timestamps between CPU and GPU with minimal skew.
+ * All counters are in nanoseconds for consistent comparison.
+ */
+struct drm_amdgpu_info_clock_counters {
+	/* GPU clock counter in nanoseconds */
+	__u64 gpu_clock_counter;
+	/* CPU clock counter (raw monotonic) in nanoseconds */
+	__u64 cpu_clock_counter;
+	/* System boottime clock counter in nanoseconds */
+	__u64 system_clock_counter;
+	/* System clock frequency in Hz (always 1GHz) */
+	__u64 system_clock_freq;
+};
+
 /*
  * Supported GPU families
  */
-- 
2.34.1



More information about the amd-gfx mailing list