@@ -2129,6 +2129,7 @@ struct i915_perf_stream {
spinlock_t samples_lock;
u32 last_ctx_id;
+ u64 last_pid;
};
/**
@@ -2261,6 +2262,12 @@ struct i915_perf_cs_sample {
* @ctx_id: Context ID associated with this perf sample
*/
u32 ctx_id;
+
+ /**
+ * @pid: PID of the process in context of which the workload was
+ * submitted, pertaining to this perf sample
+ */
+ u64 pid;
};
struct intel_cdclk_state {
@@ -198,6 +198,7 @@ struct drm_i915_gem_request {
u32 *pre_oa_offset;
u32 *post_oa_offset;
+ u64 pid;
};
extern const struct dma_fence_ops i915_fence_ops;
@@ -282,6 +282,7 @@
#define OA_EXPONENT_MAX 31
#define INVALID_CTX_ID 0xffffffff
+#define INVALID_PID 0xffffffff
/* On Gen8+ automatically triggered OA reports include a 'reason' field... */
#define OAREPORT_REASON_MASK 0x3f
@@ -294,6 +295,7 @@
struct i915_perf_sample_data {
u64 source;
u64 ctx_id;
+ u64 pid;
const u8 *report;
};
@@ -349,6 +351,7 @@ struct i915_perf_sample_data {
#define SAMPLE_OA_REPORT (1<<0)
#define SAMPLE_OA_SOURCE (1<<1)
#define SAMPLE_CTX_ID (1<<2)
+#define SAMPLE_PID (1<<3)
/**
* struct perf_open_properties - for validated properties given to open a stream
@@ -512,6 +515,9 @@ static void i915_perf_stream_emit_sample_capture(
DRM_ERROR("Emit of OA capture commands failed\n");
}
+ if (stream->sample_flags & SAMPLE_PID)
+ request->pid = current->pid;
+
reservation_object_lock(resv, NULL);
if (reservation_object_reserve_shared(resv) == 0)
reservation_object_add_shared_fence(resv, &request->fence);
@@ -626,6 +632,7 @@ static void i915_perf_stream_patch_request(struct i915_perf_stream *stream,
sample->request = i915_gem_request_get(request);
sample->id = sample_id;
sample->ctx_id = request->ctx->hw_id;
+ sample->pid = request->pid;
if (stream->sample_flags &
(SAMPLE_OA_REPORT | SAMPLE_OA_SOURCE))
i915_perf_stream_patch_sample_oa(stream, request,
@@ -943,6 +950,12 @@ static int append_perf_sample(struct i915_perf_stream *stream,
buf += 8;
}
+ if (sample_flags & SAMPLE_PID) {
+ if (copy_to_user(buf, &data->pid, 8))
+ return -EFAULT;
+ buf += 8;
+ }
+
if (sample_flags & SAMPLE_OA_REPORT) {
if (copy_to_user(buf, data->report, report_size))
return -EFAULT;
@@ -980,6 +993,9 @@ static int append_oa_buffer_sample(struct i915_perf_stream *stream,
data.ctx_id = dev_priv->perf.oa.ops.get_ctx_id(stream, report);
}
+ if (sample_flags & SAMPLE_PID)
+ data.pid = stream->last_pid;
+
if (sample_flags & SAMPLE_OA_REPORT)
data.report = report;
@@ -1588,6 +1604,14 @@ static int append_cs_buffer_sample(struct i915_perf_stream *stream,
stream->last_ctx_id = INVALID_CTX_ID;
}
+ if (sample_flags & SAMPLE_PID) {
+ data.pid = node->pid;
+ if (node->id == PRE_REQUEST_SAMPLE_ID)
+ stream->last_pid = node->pid;
+ else
+ stream->last_pid = INVALID_PID;
+ }
+
return append_perf_sample(stream, buf, count, offset, &data);
}
@@ -2820,6 +2844,7 @@ static int i915_perf_stream_init(struct i915_perf_stream *stream,
bool require_oa_unit = props->sample_flags & (SAMPLE_OA_REPORT |
SAMPLE_OA_SOURCE);
bool cs_sample_data = props->sample_flags & SAMPLE_OA_REPORT;
+ bool require_cs_mode = props->sample_flags & SAMPLE_PID;
struct i915_perf_stream *curr_stream;
struct intel_engine_cs *engine = NULL;
int ret;
@@ -2970,6 +2995,20 @@ static int i915_perf_stream_init(struct i915_perf_stream *stream,
stream->sample_flags |= SAMPLE_CTX_ID;
stream->sample_size += 8;
stream->last_ctx_id = INVALID_CTX_ID;
+
+ /*
+ * NB: it's meaningful to request SAMPLE_CTX_ID with just CS
+ * mode or periodic OA mode sampling but we don't allow
+ * SAMPLE_CTX_ID without either mode
+ */
+ if (!require_oa_unit)
+ require_cs_mode = true;
+ }
+
+ if (require_cs_mode && !props->cs_mode) {
+ DRM_ERROR("PID sampling requires a ring to be specified");
+ ret = -EINVAL;
+ goto err_enable;
}
if (props->cs_mode) {
@@ -2981,13 +3020,25 @@ static int i915_perf_stream_init(struct i915_perf_stream *stream,
goto err_enable;
}
- if (!(props->sample_flags & SAMPLE_CTX_ID)) {
+ /*
+ * The only time we should allow enabling CS mode if it's not
+ * strictly required, is if SAMPLE_CTX_ID has been requested
+ * as it's usable with periodic OA or CS sampling.
+ */
+ if (!require_cs_mode &&
+ !(props->sample_flags & SAMPLE_CTX_ID)) {
DRM_ERROR("Stream engine given without requesting any "
"CS specific property\n");
ret = -EINVAL;
goto err_enable;
}
+ if (props->sample_flags & SAMPLE_PID) {
+ stream->sample_flags |= SAMPLE_PID;
+ stream->sample_size += 8;
+ stream->last_pid = INVALID_PID;
+ }
+
idx = srcu_read_lock(&dev_priv->perf.oa.srcu);
curr_stream = srcu_dereference(
dev_priv->perf.oa.exclusive_stream,
@@ -3708,6 +3759,9 @@ static int read_properties_unlocked(struct drm_i915_private *dev_priv,
case DRM_I915_PERF_PROP_SAMPLE_CTX_ID:
props->sample_flags |= SAMPLE_CTX_ID;
break;
+ case DRM_I915_PERF_PROP_SAMPLE_PID:
+ props->sample_flags |= SAMPLE_PID;
+ break;
case DRM_I915_PERF_PROP_MAX:
MISSING_CASE(id);
return -EINVAL;
@@ -1439,6 +1439,12 @@ enum drm_i915_perf_property_id {
*/
DRM_I915_PERF_PROP_SAMPLE_CTX_ID,
+ /**
+ * The value of this property set to 1 requests inclusion of pid in the
+ * perf sample data.
+ */
+ DRM_I915_PERF_PROP_SAMPLE_PID,
+
DRM_I915_PERF_PROP_MAX /* non-ABI */
};
@@ -1506,6 +1512,7 @@ enum drm_i915_perf_record_type {
*
* { u64 source; } && DRM_I915_PERF_PROP_SAMPLE_OA_SOURCE
* { u64 ctx_id; } && DRM_I915_PERF_PROP_SAMPLE_CTX_ID
+ * { u64 pid; } && DRM_I915_PERF_PROP_SAMPLE_PID
* { u32 oa_report[]; } && DRM_I915_PERF_PROP_SAMPLE_OA
* };
*/