Skip to content

Commit b5e71ca

Browse files
Athira Rajeevmaddy-kerneldev
authored andcommitted
powerpc/perf/vpa-dtl: Handle the writing of perf record when aux wake up is needed
Handle the case when the aux buffer is going to be full and data needs to be written to the data file. perf_aux_output_begin() function checks if there is enough space depending on the values of aux_wakeup and aux_watermark which is part of "struct perf_buffer". Inorder to maintain where to write to aux buffer, add two fields to "struct vpa_pmu_buf". Field "threshold" to indicate total possible DTL entries that can be contained in aux buffer and field "full" to indicate anytime when buffer is full. In perf_aux_output_end, there is check to see if wake up is needed based on aux head value. In vpa_dtl_capture_aux(), check if there is enough space to contain the DTL data. If not, save the data for available memory and set full to true. Set head of private aux to zero when buffer is full so that next data will be copied to beginning of the buffer. The address used for copying to aux is "aux_copy_buf + buf->head". So once buffer is full, set head to zero, so that next time it will be written from start of the buffer. Signed-off-by: Athira Rajeev <atrajeev@linux.ibm.com> Tested-by: Tejas Manhas <tejas05@linux.ibm.com> Tested-by: Venkat Rao Bagalkote <venkat88@linux.ibm.com> Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com> Link: https://patch.msgid.link/20250915102947.26681-7-atrajeev@linux.ibm.com
1 parent 2de8b6d commit b5e71ca

1 file changed

Lines changed: 52 additions & 2 deletions

File tree

arch/powerpc/perf/vpa-dtl.c

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,11 @@ struct vpa_pmu_buf {
8585
u64 *base;
8686
u64 size;
8787
u64 head;
88+
u64 head_size;
8889
/* boot timebase and frequency needs to be saved only at once */
8990
int boottb_freq_saved;
91+
u64 threshold;
92+
bool full;
9093
};
9194

9295
/*
@@ -120,11 +123,31 @@ static void vpa_dtl_capture_aux(long *n_entries, struct vpa_pmu_buf *buf,
120123
{
121124
struct dtl_entry *aux_copy_buf = (struct dtl_entry *)buf->base;
122125

126+
/*
127+
* check if there is enough space to contain the
128+
* DTL data. If not, save the data for available
129+
* memory and set full to true.
130+
*/
131+
if (buf->head + *n_entries >= buf->threshold) {
132+
*n_entries = buf->threshold - buf->head;
133+
buf->full = 1;
134+
}
135+
123136
/*
124137
* Copy to AUX buffer from per-thread address
125138
*/
126139
memcpy(aux_copy_buf + buf->head, &dtl->buf[index], *n_entries * sizeof(struct dtl_entry));
127140

141+
if (buf->full) {
142+
/*
143+
* Set head of private aux to zero when buffer is full
144+
* so that next data will be copied to beginning of the
145+
* buffer
146+
*/
147+
buf->head = 0;
148+
return;
149+
}
150+
128151
buf->head += *n_entries;
129152

130153
return;
@@ -178,6 +201,7 @@ static void vpa_dtl_dump_sample_data(struct perf_event *event)
178201
struct vpa_pmu_buf *aux_buf;
179202

180203
struct vpa_dtl *dtl = &per_cpu(vpa_dtl_cpu, event->cpu);
204+
u64 size;
181205

182206
cur_idx = be64_to_cpu(lppaca_of(event->cpu).dtl_idx);
183207
last_idx = dtl->last_idx;
@@ -222,13 +246,37 @@ static void vpa_dtl_dump_sample_data(struct perf_event *event)
222246
n_req -= read_size;
223247
n_read += read_size;
224248
i = 0;
249+
if (aux_buf->full) {
250+
size = (n_read * sizeof(struct dtl_entry));
251+
if ((size + aux_buf->head_size) > aux_buf->size) {
252+
size = aux_buf->size - aux_buf->head_size;
253+
perf_aux_output_end(&vpa_ctx->handle, size);
254+
aux_buf->head = 0;
255+
aux_buf->head_size = 0;
256+
} else {
257+
aux_buf->head_size += (n_read * sizeof(struct dtl_entry));
258+
perf_aux_output_end(&vpa_ctx->handle, n_read * sizeof(struct dtl_entry));
259+
}
260+
goto out;
261+
}
225262
}
226263

227264
/* .. and now the head */
228265
vpa_dtl_capture_aux(&n_req, aux_buf, dtl, i);
229266

230-
/* Move the aux->head to indicate size of data in aux buffer */
231-
perf_aux_output_end(&vpa_ctx->handle, (n_req + n_read) * sizeof(struct dtl_entry));
267+
size = ((n_req + n_read) * sizeof(struct dtl_entry));
268+
if ((size + aux_buf->head_size) > aux_buf->size) {
269+
size = aux_buf->size - aux_buf->head_size;
270+
perf_aux_output_end(&vpa_ctx->handle, size);
271+
aux_buf->head = 0;
272+
aux_buf->head_size = 0;
273+
} else {
274+
aux_buf->head_size += ((n_req + n_read) * sizeof(struct dtl_entry));
275+
/* Move the aux->head to indicate size of data in aux buffer */
276+
perf_aux_output_end(&vpa_ctx->handle, (n_req + n_read) * sizeof(struct dtl_entry));
277+
}
278+
out:
279+
aux_buf->full = 0;
232280
}
233281

234282
/*
@@ -491,7 +539,9 @@ static void *vpa_dtl_setup_aux(struct perf_event *event, void **pages,
491539

492540
buf->size = nr_pages << PAGE_SHIFT;
493541
buf->head = 0;
542+
buf->head_size = 0;
494543
buf->boottb_freq_saved = 0;
544+
buf->threshold = ((buf->size - 32) / sizeof(struct dtl_entry));
495545
return no_free_ptr(buf);
496546
}
497547

0 commit comments

Comments
 (0)