Commit dbc9a5fb authored by Umesh Nerlige Ramappa's avatar Umesh Nerlige Ramappa

drm/i915/perf: Parse 64bit report header formats correctly

Now that OA formats come in flavor of 64 bit reports, the report header
has 64 bit report-id, timestamp, context-id and gpu-ticks fields. When
filtering these reports, use the right width for these fields.

Note that upper dword of context id is reserved, so squash lower dword
only.

v2: (Ashutosh)
- Drop inline
- Update comment with dword definitions - report id and timestamp
Signed-off-by: default avatarUmesh Nerlige Ramappa <umesh.nerlige.ramappa@intel.com>
Reviewed-by: default avatarAshutosh Dixit <ashutosh.dixit@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230323225901.3743681-7-umesh.nerlige.ramappa@intel.com
parent 772a5803
...@@ -441,6 +441,67 @@ static u32 gen7_oa_hw_tail_read(struct i915_perf_stream *stream) ...@@ -441,6 +441,67 @@ static u32 gen7_oa_hw_tail_read(struct i915_perf_stream *stream)
return oastatus1 & GEN7_OASTATUS1_TAIL_MASK; return oastatus1 & GEN7_OASTATUS1_TAIL_MASK;
} }
#define oa_report_header_64bit(__s) \
((__s)->oa_buffer.format->header == HDR_64_BIT)
static u64 oa_report_id(struct i915_perf_stream *stream, void *report)
{
return oa_report_header_64bit(stream) ? *(u64 *)report : *(u32 *)report;
}
static u64 oa_report_reason(struct i915_perf_stream *stream, void *report)
{
return (oa_report_id(stream, report) >> OAREPORT_REASON_SHIFT) &
(GRAPHICS_VER(stream->perf->i915) == 12 ?
OAREPORT_REASON_MASK_EXTENDED :
OAREPORT_REASON_MASK);
}
static void oa_report_id_clear(struct i915_perf_stream *stream, u32 *report)
{
if (oa_report_header_64bit(stream))
*(u64 *)report = 0;
else
*report = 0;
}
static bool oa_report_ctx_invalid(struct i915_perf_stream *stream, void *report)
{
return !(oa_report_id(stream, report) &
stream->perf->gen8_valid_ctx_bit) &&
GRAPHICS_VER(stream->perf->i915) <= 11;
}
static u64 oa_timestamp(struct i915_perf_stream *stream, void *report)
{
return oa_report_header_64bit(stream) ?
*((u64 *)report + 1) :
*((u32 *)report + 1);
}
static void oa_timestamp_clear(struct i915_perf_stream *stream, u32 *report)
{
if (oa_report_header_64bit(stream))
*(u64 *)&report[2] = 0;
else
report[1] = 0;
}
static u32 oa_context_id(struct i915_perf_stream *stream, u32 *report)
{
u32 ctx_id = oa_report_header_64bit(stream) ? report[4] : report[2];
return ctx_id & stream->specific_ctx_id_mask;
}
static void oa_context_id_squash(struct i915_perf_stream *stream, u32 *report)
{
if (oa_report_header_64bit(stream))
report[4] = INVALID_CTX_ID;
else
report[2] = INVALID_CTX_ID;
}
/** /**
* oa_buffer_check_unlocked - check for data and update tail ptr state * oa_buffer_check_unlocked - check for data and update tail ptr state
* @stream: i915 stream instance * @stream: i915 stream instance
...@@ -509,21 +570,22 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream) ...@@ -509,21 +570,22 @@ static bool oa_buffer_check_unlocked(struct i915_perf_stream *stream)
hw_tail -= gtt_offset; hw_tail -= gtt_offset;
tail = hw_tail; tail = hw_tail;
/* Walk the stream backward until we find a report with dword 0 /* Walk the stream backward until we find a report with report
* & 1 not at 0. Since the circular buffer pointers progress by * id and timestmap not at 0. Since the circular buffer pointers
* increments of 64 bytes and that reports can be up to 256 * progress by increments of 64 bytes and that reports can be up
* bytes long, we can't tell whether a report has fully landed * to 256 bytes long, we can't tell whether a report has fully
* in memory before the first 2 dwords of the following report * landed in memory before the report id and timestamp of the
* have effectively landed. * following report have effectively landed.
* *
* This is assuming that the writes of the OA unit land in * This is assuming that the writes of the OA unit land in
* memory in the order they were written to. * memory in the order they were written to.
* If not : (╯°□°)╯︵ ┻━┻ * If not : (╯°□°)╯︵ ┻━┻
*/ */
while (OA_TAKEN(tail, aged_tail) >= report_size) { while (OA_TAKEN(tail, aged_tail) >= report_size) {
u32 *report32 = (void *)(stream->oa_buffer.vaddr + tail); void *report = stream->oa_buffer.vaddr + tail;
if (report32[0] != 0 || report32[1] != 0) if (oa_report_id(stream, report) ||
oa_timestamp(stream, report))
break; break;
tail = (tail - report_size) & (OA_BUFFER_SIZE - 1); tail = (tail - report_size) & (OA_BUFFER_SIZE - 1);
...@@ -702,7 +764,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, ...@@ -702,7 +764,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
u8 *report = oa_buf_base + head; u8 *report = oa_buf_base + head;
u32 *report32 = (void *)report; u32 *report32 = (void *)report;
u32 ctx_id; u32 ctx_id;
u32 reason; u64 reason;
/* /*
* All the report sizes factor neatly into the buffer * All the report sizes factor neatly into the buffer
...@@ -725,16 +787,12 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, ...@@ -725,16 +787,12 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
* triggered this specific report (mostly timer * triggered this specific report (mostly timer
* triggered or e.g. due to a context switch). * triggered or e.g. due to a context switch).
* *
* This field is never expected to be zero so we can * In MMIO triggered reports, some platforms do not set the
* check that the report isn't invalid before copying * reason bit in this field and it is valid to have a reason
* it to userspace... * field of zero.
*/ */
reason = ((report32[0] >> OAREPORT_REASON_SHIFT) & reason = oa_report_reason(stream, report);
(GRAPHICS_VER(stream->perf->i915) == 12 ? ctx_id = oa_context_id(stream, report32);
OAREPORT_REASON_MASK_EXTENDED :
OAREPORT_REASON_MASK));
ctx_id = report32[2] & stream->specific_ctx_id_mask;
/* /*
* Squash whatever is in the CTX_ID field if it's marked as * Squash whatever is in the CTX_ID field if it's marked as
...@@ -744,9 +802,10 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, ...@@ -744,9 +802,10 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
* Note: that we don't clear the valid_ctx_bit so userspace can * Note: that we don't clear the valid_ctx_bit so userspace can
* understand that the ID has been squashed by the kernel. * understand that the ID has been squashed by the kernel.
*/ */
if (!(report32[0] & stream->perf->gen8_valid_ctx_bit) && if (oa_report_ctx_invalid(stream, report)) {
GRAPHICS_VER(stream->perf->i915) <= 11) ctx_id = INVALID_CTX_ID;
ctx_id = report32[2] = INVALID_CTX_ID; oa_context_id_squash(stream, report32);
}
/* /*
* NB: For Gen 8 the OA unit no longer supports clock gating * NB: For Gen 8 the OA unit no longer supports clock gating
...@@ -790,7 +849,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, ...@@ -790,7 +849,7 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
*/ */
if (stream->ctx && if (stream->ctx &&
stream->specific_ctx_id != ctx_id) { stream->specific_ctx_id != ctx_id) {
report32[2] = INVALID_CTX_ID; oa_context_id_squash(stream, report32);
} }
ret = append_oa_sample(stream, buf, count, offset, ret = append_oa_sample(stream, buf, count, offset,
...@@ -802,11 +861,11 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream, ...@@ -802,11 +861,11 @@ static int gen8_append_oa_reports(struct i915_perf_stream *stream,
} }
/* /*
* Clear out the first 2 dword as a mean to detect unlanded * Clear out the report id and timestamp as a means to detect unlanded
* reports. * reports.
*/ */
report32[0] = 0; oa_report_id_clear(stream, report32);
report32[1] = 0; oa_timestamp_clear(stream, report32);
} }
if (start_offset != *offset) { if (start_offset != *offset) {
......
...@@ -38,9 +38,15 @@ enum { ...@@ -38,9 +38,15 @@ enum {
PERF_GROUP_INVALID = U32_MAX, PERF_GROUP_INVALID = U32_MAX,
}; };
enum report_header {
HDR_32_BIT = 0,
HDR_64_BIT,
};
struct i915_oa_format { struct i915_oa_format {
u32 format; u32 format;
int size; int size;
enum report_header header;
}; };
struct i915_oa_reg { struct i915_oa_reg {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment