From 07e836b932854450d5b1d187afc671365a2ec5cd Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Fri, 29 Nov 2024 04:35:07 +0900 Subject: [PATCH] asahi: Fix agx_gpu_time_to_ns & implement DRM_ASAHI_GET_TIME agx_gpu_time_to_ns() was broken since it was overflowing the u64 timestamp after just ~10 minutes. Fix that by automatically computing a reduced conversion fraction, and add support for DRM_ASAHI_GET_TIME where supported (replacing the CPU timer hack). Signed-off-by: Asahi Lina Part-of: --- src/asahi/lib/agx_device.c | 33 +++++++++++++++++++++++++++++++++ src/asahi/lib/agx_device.h | 7 ++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/asahi/lib/agx_device.c b/src/asahi/lib/agx_device.c index 56d3d868c5d..2c6fc500de6 100644 --- a/src/asahi/lib/agx_device.c +++ b/src/asahi/lib/agx_device.c @@ -394,6 +394,27 @@ const agx_device_ops_t agx_device_drm_ops = { .submit = agx_submit, }; +static uint64_t +gcd(uint64_t n, uint64_t m) +{ + while (n != 0) { + uint64_t remainder = m % n; + m = n; + n = remainder; + } + + return m; +} + +static void +agx_init_timestamps(struct agx_device *dev) +{ + uint64_t ts_gcd = gcd(dev->params.timer_frequency_hz, NSEC_PER_SEC); + + dev->timestamp_to_ns.num = NSEC_PER_SEC / ts_gcd; + dev->timestamp_to_ns.den = dev->params.timer_frequency_hz / ts_gcd; +} + bool agx_open_device(void *memctx, struct agx_device *dev) { @@ -534,6 +555,8 @@ agx_open_device(void *memctx, struct agx_device *dev) dev->agxdecode = agxdecode_new_context(dev->shader_base); + agx_init_timestamps(dev); + util_sparse_array_init(&dev->bo_map, sizeof(struct agx_bo), 512); pthread_mutex_init(&dev->bo_map_lock, NULL); @@ -745,6 +768,16 @@ agx_debug_fault(struct agx_device *dev, uint64_t addr) uint64_t agx_get_gpu_timestamp(struct agx_device *dev) { + if (dev->params.feat_compat & DRM_ASAHI_FEAT_GETTIME) { + struct drm_asahi_get_time get_time = {.flags = 0, .extensions = 0}; + + int ret = asahi_simple_ioctl(dev, DRM_IOCTL_ASAHI_GET_TIME, &get_time); + if (ret) { + fprintf(stderr, "DRM_IOCTL_ASAHI_GET_TIME failed: %m\n"); + } else { + return get_time.gpu_timestamp; + } + } #if DETECT_ARCH_AARCH64 uint64_t ret; __asm__ volatile("mrs \t%0, cntvct_el0" : "=r"(ret)); diff --git a/src/asahi/lib/agx_device.h b/src/asahi/lib/agx_device.h index 3f0d762530d..a9eb5972161 100644 --- a/src/asahi/lib/agx_device.h +++ b/src/asahi/lib/agx_device.h @@ -156,6 +156,11 @@ struct agx_device { /* Simplified device selection */ enum agx_chip chip; + + struct { + uint64_t num; + uint64_t den; + } timestamp_to_ns; }; static inline bool @@ -200,7 +205,7 @@ uint64_t agx_get_gpu_timestamp(struct agx_device *dev); static inline uint64_t agx_gpu_time_to_ns(struct agx_device *dev, uint64_t gpu_time) { - return (gpu_time * NSEC_PER_SEC) / dev->params.timer_frequency_hz; + return (gpu_time * dev->timestamp_to_ns.num) / dev->timestamp_to_ns.den; } void agx_get_device_uuid(const struct agx_device *dev, void *uuid);