drm/i915/guc: Add GuC <-> kernel time stamp translation information
authorJohn Harrison <John.C.Harrison@Intel.com>
Thu, 28 Jul 2022 02:20:24 +0000 (19:20 -0700)
committerJohn Harrison <John.C.Harrison@Intel.com>
Wed, 17 Aug 2022 17:06:54 +0000 (10:06 -0700)
It is useful to be able to match GuC events to kernel events when
looking at the GuC log. That requires being able to convert GuC
timestamps to kernel time. So, when dumping error captures and/or GuC
logs, include a stamp in both time zones plus the clock frequency.

Signed-off-by: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: Alan Previn <alan.previn.teres.alexis@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220728022028.2190627-4-John.C.Harrison@Intel.com
drivers/gpu/drm/i915/gt/intel_gt_regs.h
drivers/gpu/drm/i915/gt/uc/intel_guc.c
drivers/gpu/drm/i915/gt/uc/intel_guc.h
drivers/gpu/drm/i915/gt/uc/intel_guc_log.c
drivers/gpu/drm/i915/i915_gpu_error.c
drivers/gpu/drm/i915/i915_gpu_error.h

index f64fafe28f72b278b04baa06b1b45bfbf5d1a86f..94f9ddcfb3a551638a96f152a64e905b31175e07 100644 (file)
 #define   GEN11_LSN_UNSLCVC_GAFS_HALF_CL2_MAXALLOC     (1 << 9)
 #define   GEN11_LSN_UNSLCVC_GAFS_HALF_SF_MAXALLOC      (1 << 7)
 
+#define GUCPMTIMESTAMP                         _MMIO(0xc3e8)
+
 #define __GEN9_RCS0_MOCS0                      0xc800
 #define GEN9_GFX_MOCS(i)                       _MMIO(__GEN9_RCS0_MOCS0 + (i) * 4)
 #define __GEN9_VCS0_MOCS0                      0xc900
index 2706a8c650900e661a4a178f999e9e464443d885..ab4aacc516aa407375e096dc59552b19f3af2b8d 100644 (file)
@@ -389,6 +389,25 @@ void intel_guc_write_params(struct intel_guc *guc)
        intel_uncore_forcewake_put(uncore, FORCEWAKE_GT);
 }
 
+void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p)
+{
+       struct intel_gt *gt = guc_to_gt(guc);
+       intel_wakeref_t wakeref;
+       u32 stamp = 0;
+       u64 ktime;
+
+       intel_device_info_print_runtime(RUNTIME_INFO(gt->i915), p);
+
+       with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
+               stamp = intel_uncore_read(gt->uncore, GUCPMTIMESTAMP);
+       ktime = ktime_get_boottime_ns();
+
+       drm_printf(p, "Kernel timestamp: 0x%08llX [%llu]\n", ktime, ktime);
+       drm_printf(p, "GuC timestamp: 0x%08X [%u]\n", stamp, stamp);
+       drm_printf(p, "CS timestamp frequency: %u Hz, %u ns\n",
+                  gt->clock_frequency, gt->clock_period_ns);
+}
+
 int intel_guc_init(struct intel_guc *guc)
 {
        struct intel_gt *gt = guc_to_gt(guc);
index a7acffbf15d1f2c0de316d4a9f6d3a5d869d5e3f..804133df1ac9b4ce1b51462b0ac04110f5b94a68 100644 (file)
@@ -464,4 +464,6 @@ void intel_guc_load_status(struct intel_guc *guc, struct drm_printer *p);
 
 void intel_guc_write_barrier(struct intel_guc *guc);
 
+void intel_guc_dump_time_info(struct intel_guc *guc, struct drm_printer *p);
+
 #endif
index cc8f3d153d8fd6098b220b248b4d8bfab0855d31..5654feb6f908b92363d815f9bdd757cd4978db43 100644 (file)
@@ -764,6 +764,8 @@ int intel_guc_log_dump(struct intel_guc_log *log, struct drm_printer *p,
        if (!obj)
                return 0;
 
+       intel_guc_dump_time_info(guc, p);
+
        map = i915_gem_object_pin_map_unlocked(obj, I915_MAP_WC);
        if (IS_ERR(map)) {
                DRM_DEBUG("Failed to pin object\n");
index 32e92651ef7c25b6c534462862fdf9335bfd01e2..addba75252343a40b7a12e1944a81d35c9df2619 100644 (file)
@@ -678,6 +678,7 @@ static void err_print_uc(struct drm_i915_error_state_buf *m,
 
        intel_uc_fw_dump(&error_uc->guc_fw, &p);
        intel_uc_fw_dump(&error_uc->huc_fw, &p);
+       err_printf(m, "GuC timestamp: 0x%08x\n", error_uc->timestamp);
        intel_gpu_error_print_vma(m, NULL, error_uc->guc_log);
 }
 
@@ -720,6 +721,8 @@ static void err_print_gt_global_nonguc(struct drm_i915_error_state_buf *m,
        int i;
 
        err_printf(m, "GT awake: %s\n", str_yes_no(gt->awake));
+       err_printf(m, "CS timestamp frequency: %u Hz, %d ns\n",
+                  gt->clock_frequency, gt->clock_period_ns);
        err_printf(m, "EIR: 0x%08x\n", gt->eir);
        err_printf(m, "PGTBL_ER: 0x%08x\n", gt->pgtbl_er);
 
@@ -1675,6 +1678,13 @@ gt_record_uc(struct intel_gt_coredump *gt,
         */
        error_uc->guc_fw.path = kstrdup(uc->guc.fw.path, ALLOW_FAIL);
        error_uc->huc_fw.path = kstrdup(uc->huc.fw.path, ALLOW_FAIL);
+
+       /*
+        * Save the GuC log and include a timestamp reference for converting the
+        * log times to system times (in conjunction with the error->boottime and
+        * gt->clock_frequency fields saved elsewhere).
+        */
+       error_uc->timestamp = intel_uncore_read(gt->_gt->uncore, GUCPMTIMESTAMP);
        error_uc->guc_log = create_vma_coredump(gt->_gt, uc->guc.log.vma,
                                                "GuC log buffer", compress);
 
@@ -1833,6 +1843,8 @@ static void gt_record_global_regs(struct intel_gt_coredump *gt)
 static void gt_record_info(struct intel_gt_coredump *gt)
 {
        memcpy(&gt->info, &gt->_gt->info, sizeof(struct intel_gt_info));
+       gt->clock_frequency = gt->_gt->clock_frequency;
+       gt->clock_period_ns = gt->_gt->clock_period_ns;
 }
 
 /*
index 55a143b92d10ec0fe58cf596bed5c17695aba4bf..d8a8b3d529e09ca5178079274354e1056b04f12d 100644 (file)
@@ -150,6 +150,8 @@ struct intel_gt_coredump {
        u32 gtt_cache;
        u32 aux_err; /* gen12 */
        u32 gam_done; /* gen12 */
+       u32 clock_frequency;
+       u32 clock_period_ns;
 
        /* Display related */
        u32 derrmr;
@@ -164,6 +166,7 @@ struct intel_gt_coredump {
                struct intel_uc_fw guc_fw;
                struct intel_uc_fw huc_fw;
                struct i915_vma_coredump *guc_log;
+               u32 timestamp;
                bool is_guc_capture;
        } *uc;