@@ -1671,6 +1671,73 @@ void intel_engine_apply_whitelist(struct intel_engine_cs *engine)
i915_mmio_reg_offset(RING_NOPID(base)));
}
+struct i915_oa_wl {
+ i915_reg_t reg;
+ u32 flags;
+} gen9_oa_regs[] = {
+ { OAREPORTTRIG2, RING_FORCE_TO_NONPRIV_ACCESS_RW },
+ { OAREPORTTRIG6, RING_FORCE_TO_NONPRIV_ACCESS_RW },
+}, gen12_oa_regs[] = {
+ { GEN12_OAG_OAREPORTTRIG2, RING_FORCE_TO_NONPRIV_ACCESS_RW },
+ { GEN12_OAG_OAREPORTTRIG6, RING_FORCE_TO_NONPRIV_ACCESS_RW },
+};
+
+static void whitelist_delete_perf_counters(struct i915_wa_list *wal,
+ struct i915_oa_wl *regs,
+ int count)
+{
+ while (count--) {
+ _wa_remove(wal, regs->reg);
+ regs++;
+ }
+
+ wa_init_finish(wal);
+}
+
+static void whitelist_build_perf_counters(struct i915_wa_list *wal,
+ struct i915_oa_wl *regs,
+ int count)
+{
+ while (count--) {
+ whitelist_reg_ext(wal, regs->reg, regs->flags);
+ regs++;
+ }
+}
+
+void intel_engine_apply_oa_whitelist(struct intel_engine_cs *engine)
+{
+ struct i915_wa_list *w = &engine->whitelist;
+ struct drm_i915_private *i915 = engine->i915;
+
+ if (IS_GEN(i915, 12))
+ whitelist_build_perf_counters(w, gen12_oa_regs,
+ ARRAY_SIZE(gen12_oa_regs));
+ else if (INTEL_GEN(i915) > 8)
+ whitelist_build_perf_counters(w, gen9_oa_regs,
+ ARRAY_SIZE(gen9_oa_regs));
+ else
+ return;
+
+ intel_engine_apply_whitelist(engine);
+}
+
+void intel_engine_remove_oa_whitelist(struct intel_engine_cs *engine)
+{
+ struct i915_wa_list *w = &engine->whitelist;
+ struct drm_i915_private *i915 = engine->i915;
+
+ if (IS_GEN(i915, 12))
+ whitelist_delete_perf_counters(w, gen12_oa_regs,
+ ARRAY_SIZE(gen12_oa_regs));
+ else if (INTEL_GEN(i915) > 8)
+ whitelist_delete_perf_counters(w, gen9_oa_regs,
+ ARRAY_SIZE(gen9_oa_regs));
+ else
+ return;
+
+ intel_engine_apply_whitelist(engine);
+}
+
static void
rcs_engine_wa_init(struct intel_engine_cs *engine, struct i915_wa_list *wal)
{
@@ -32,6 +32,9 @@ bool intel_gt_verify_workarounds(struct intel_gt *gt, const char *from);
void intel_engine_init_whitelist(struct intel_engine_cs *engine);
void intel_engine_apply_whitelist(struct intel_engine_cs *engine);
+void intel_engine_apply_oa_whitelist(struct intel_engine_cs *engine);
+void intel_engine_remove_oa_whitelist(struct intel_engine_cs *engine);
+
void intel_engine_init_workarounds(struct intel_engine_cs *engine);
void intel_engine_apply_workarounds(struct intel_engine_cs *engine);
int intel_engine_verify_workarounds(struct intel_engine_cs *engine,
@@ -201,6 +201,7 @@
#include "gt/intel_gt.h"
#include "gt/intel_lrc_reg.h"
#include "gt/intel_ring.h"
+#include "gt/intel_workarounds.h"
#include "i915_drv.h"
#include "i915_perf.h"
@@ -1353,6 +1354,9 @@ static void i915_oa_stream_destroy(struct i915_perf_stream *stream)
BUG_ON(stream != perf->exclusive_stream);
+ if (stream->oa_whitelisted)
+ intel_engine_remove_oa_whitelist(stream->engine);
+
/*
* Unset exclusive_stream first, it will be checked while disabling
* the metric set on gen8+.
@@ -1448,7 +1452,8 @@ static void gen8_init_oa_buffer(struct i915_perf_stream *stream)
* bit."
*/
intel_uncore_write(uncore, GEN8_OABUFFER, gtt_offset |
- OABUFFER_SIZE_16M | GEN8_OABUFFER_MEM_SELECT_GGTT);
+ OABUFFER_SIZE_16M | GEN8_OABUFFER_MEM_SELECT_GGTT |
+ GEN7_OABUFFER_EDGE_TRIGGER);
intel_uncore_write(uncore, GEN8_OATAILPTR, gtt_offset & GEN8_OATAILPTR_MASK);
/* Mark that we need updated tail pointers to read from... */
@@ -1501,7 +1506,8 @@ static void gen12_init_oa_buffer(struct i915_perf_stream *stream)
* bit."
*/
intel_uncore_write(uncore, GEN12_OAG_OABUFFER, gtt_offset |
- OABUFFER_SIZE_16M | GEN8_OABUFFER_MEM_SELECT_GGTT);
+ OABUFFER_SIZE_16M | GEN8_OABUFFER_MEM_SELECT_GGTT |
+ GEN7_OABUFFER_EDGE_TRIGGER);
intel_uncore_write(uncore, GEN12_OAG_OATAILPTR,
gtt_offset & GEN12_OAG_OATAILPTR_MASK);
@@ -3474,6 +3480,22 @@ i915_perf_open_ioctl_locked(struct i915_perf *perf,
if (!(param->flags & I915_PERF_FLAG_DISABLED))
i915_perf_enable_locked(stream);
+ /*
+ * OA whitelist allows non-privileged access to some OA counters for
+ * triggering reports into the OA buffer. This is only allowed if
+ * perf_stream_paranoid is set to 0 by the sysadmin.
+ *
+ * We want to make sure this is almost the last thing we do before
+ * returning the stream fd. If we do end up checking for errors in code
+ * that follows this, we MUST call intel_engine_remove_oa_whitelist in
+ * the error handling path to remove the whitelisted registers.
+ */
+ if (!i915_perf_stream_paranoid &&
+ props->sample_flags & SAMPLE_OA_REPORT) {
+ intel_engine_apply_oa_whitelist(stream->engine);
+ stream->oa_whitelisted = true;
+ }
+
/* Take a reference on the driver that will be kept with stream_fd
* until its release.
*/
@@ -4445,8 +4467,13 @@ int i915_perf_ioctl_version(void)
*
* 5: Add DRM_I915_PERF_PROP_POLL_OA_PERIOD parameter that controls the
* interval for the hrtimer used to check for OA data.
+ *
+ * 6: Whitelist OATRIGGER registers to allow user to trigger reports
+ * into the OA buffer. This applies only to gen8+. The feature can
+ * only be accessed if perf_stream_paranoid is set to 0 by privileged
+ * user.
*/
- return 5;
+ return 6;
}
#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
@@ -311,6 +311,11 @@ struct i915_perf_stream {
* buffer should be checked for available data.
*/
u64 poll_oa_period;
+
+ /**
+ * @oa_whitelisted: Indicates that the oa registers are whitelisted.
+ */
+ bool oa_whitelisted;
};
/**