Lines Matching +full:convert +full:- +full:sample +full:- +full:format
1 // SPDX-License-Identifier: GPL-2.0
4 * Auxtrace support for s390 CPU-Measurement Sampling Facility
17 * see Documentation/perf.data-file-format.txt.
61 * record sample, the auxtrace queues will be processed. As auxtrace queues
72 * Each sampling-data entry in the auxiliary trace data generates a perf sample.
73 * This sample is filled
75 * etc. This sample is processed with perf_session__deliver_synth_event() to
80 * auxtrace_heap top. This is triggered by ordered_event->deliver().
95 * | - Those generated by perf record command (type number equal or higher
98 * | - Those generated by the kernel are handled by
102 * | Extract time stamp from sample data.
105 * | If timestamp is positive the sample is entered into an ordered_event
108 * | Other timestamps (0 or -1) are handled immediately by
127 * a sample with IP and call back chain data into GUI data pool.
162 #include "s390-cpumsf.h"
163 #include "s390-cpumsf-kernel.h"
164 #include "s390-cpumcf-kernel.h"
166 #include "util/sample.h"
197 struct perf_sample *sample)
203 if (!sf->use_logfile || sf->queues.nr_queues <= sample->cpu)
206 q = &sf->queues.queue_array[sample->cpu];
207 sfq = q->priv;
211 if (!sfq->logfile_ctr) {
214 rc = (sf->logdir)
216 sf->logdir, sample->cpu)
217 : asprintf(&name, "aux.ctr.%02x", sample->cpu);
219 sfq->logfile_ctr = fopen(name, "w");
220 if (sfq->logfile_ctr == NULL) {
228 if (sfq->logfile_ctr) {
229 /* See comment above for -4 */
230 size_t n = fwrite(sample->raw_data, sample->raw_size - 4, 1,
231 sfq->logfile_ctr);
240 /* Display s390 CPU measurement facility basic-sampling data entry
253 local.def = be16toh(basicp->def);
262 local.ia = be64toh(basicp->ia);
263 local.gpp = be64toh(basicp->gpp);
264 local.hpp = be64toh(basicp->hpp);
267 if (basic->def != 1) {
274 pos, basic->def, basic->U,
275 basic->T ? 'T' : ' ',
276 basic->W ? 'W' : ' ',
277 basic->P ? 'P' : ' ',
278 basic->I ? 'I' : ' ',
279 basic->AS, basic->prim_asn, basic->ia, basic->CL,
280 basic->hpp, basic->gpp);
284 /* Display s390 CPU measurement facility diagnostic-sampling data entry.
296 local.def = be16toh(diagp->def);
300 if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) {
305 pos, diag->def, diag->I ? 'I' : ' ');
313 /* te->t set: TOD in STCKE format, bytes 8-15
314 * to->t not set: TOD in STCK format, bytes 0-7
318 memcpy(&ts, &te->timestamp[idx], sizeof(ts));
328 const unsigned long long flags = be64toh(te->flags);
336 memcpy(&local.timestamp, te->timestamp, sizeof(te->timestamp));
337 local.overflow = be64toh(te->overflow);
338 local.clock_base = be64toh(te->progusage[0]) >> 63 & 1;
339 local.progusage2 = be64toh(te->progusage2);
342 if (te->bsdes != sizeof(struct hws_basic_entry)) {
350 te->f ? 'F' : ' ',
351 te->a ? 'A' : ' ',
352 te->t ? 'T' : ' ',
353 te->bsdes, te->dsdes, te->overflow,
354 trailer_timestamp(te, te->clock_base),
355 te->clock_base, te->progusage2);
359 /* Test a sample data block. It must be 4KB or a multiple thereof in size and
360 * 4KB page aligned. Each sample data page has a trailer entry at the
361 * end which contains the sample entry data sizes.
363 * Return true if the sample data block passes the checks and set the
380 if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */
382 if (be16toh(basic->def) != 1) /* No basic set entry, must be first */
386 - sizeof(*te));
387 *bsdes = be16toh(te->bsdes);
388 *dsdes = be16toh(te->dsdes);
389 if (!te->bsdes && !te->dsdes) {
423 size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry);
425 if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz)
446 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
450 len, sf->machine_type, bsdes, dsdes);
478 & ~(S390_CPUMSF_PAGESZ - 1);
479 pos -= sizeof(te);
507 struct perf_sample sample = {
508 .ip = basic->ia,
509 .pid = basic->hpp & S390_LPP_PID_MASK,
510 .tid = basic->hpp & S390_LPP_PID_MASK,
512 .cpu = sfq->cpu,
519 if (basic->CL == 1) /* Native LPAR mode */
520 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
522 else if (basic->CL == 2) /* Guest kernel/user space */
523 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
525 else if (basic->gpp || basic->prim_asn != 0xffff)
527 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
530 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
533 event.sample.header.type = PERF_RECORD_SAMPLE;
534 event.sample.header.misc = sample.cpumode;
535 event.sample.header.size = sizeof(struct perf_event_header);
538 __func__, pos, sample.ip, basic->P, basic->CL, sample.pid,
539 sample.tid, sample.cpumode, sample.cpu);
540 ret = perf_session__deliver_synth_event(sfq->sf->session, &event, &sample);
541 perf_sample__exit(&sample);
556 - sizeof(*te));
559 clock_base = be64toh(te->progusage[0]) >> 63 & 0x1;
560 progusage2 = be64toh(te->progusage[1]);
562 clock_base = te->clock_base;
563 progusage2 = te->progusage2;
568 /* Correct calculation to convert time stamp in trailer entry to
572 aux_time = trailer_timestamp(te, clock_base) - progusage2;
580 * - of the event that triggered this processing.
581 * - or the time stamp when the last processing of this queue stopped.
584 * (see buffer->use_data and buffer->use_size).
604 struct s390_cpumsf *sf = sfq->sf;
605 unsigned char *buf = sfq->buffer->use_data;
606 size_t len = sfq->buffer->use_size;
613 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
616 return -1;
627 (s64)sfq->buffer->data_offset);
642 err = -EBADF;
651 & ~(S390_CPUMSF_PAGESZ - 1);
662 sfq->buffer->use_data += pos;
663 sfq->buffer->use_size -= pos;
670 sfq->buffer->use_size = 0;
671 sfq->buffer->use_data = NULL;
703 queue = &sfq->sf->queues.queue_array[sfq->queue_nr];
711 if (sfq->buffer == NULL) {
712 sfq->buffer = buffer = auxtrace_buffer__next(queue,
713 sfq->buffer);
719 if (buffer->data) {
720 buffer->use_size = buffer->size;
721 buffer->use_data = buffer->data;
723 if (sfq->logfile) { /* Write into log file */
724 size_t rc = fwrite(buffer->data, buffer->size, 1,
725 sfq->logfile);
730 buffer = sfq->buffer;
732 if (!buffer->data) {
733 int fd = perf_data__fd(sfq->sf->session->data);
735 buffer->data = auxtrace_buffer__get_data(buffer, fd);
736 if (!buffer->data)
737 return -ENOMEM;
738 buffer->use_size = buffer->size;
739 buffer->use_data = buffer->data;
741 if (sfq->logfile) { /* Write into log file */
742 size_t rc = fwrite(buffer->data, buffer->size, 1,
743 sfq->logfile);
749 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
750 buffer->size, buffer->use_size);
753 /* If non-zero, there is either an error (err < 0) or the buffer is
760 sfq->buffer = NULL;
761 list_del_init(&buffer->list);
778 sfq->sf = sf;
779 sfq->queue_nr = queue_nr;
780 sfq->cpu = -1;
781 if (sf->use_logfile) {
785 rc = (sf->logdir)
787 sf->logdir, queue_nr)
790 sfq->logfile = fopen(name, "w");
791 if (sfq->logfile == NULL) {
794 sf->use_logfile = false;
805 struct s390_cpumsf_queue *sfq = queue->priv;
807 if (list_empty(&queue->head))
813 return -ENOMEM;
814 queue->priv = sfq;
816 if (queue->cpu != -1)
817 sfq->cpu = queue->cpu;
819 return auxtrace_heap__add(&sf->heap, queue_nr, ts);
827 for (i = 0; i < sf->queues.nr_queues; i++) {
828 ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i],
838 if (!sf->queues.new_data)
841 sf->queues.new_data = false;
855 if (!sf->heap.heap_cnt)
858 if (sf->heap.heap_array[0].ordinal >= timestamp)
861 queue_nr = sf->heap.heap_array[0].queue_nr;
862 queue = &sf->queues.queue_array[queue_nr];
863 sfq = queue->priv;
865 auxtrace_heap__pop(&sf->heap);
866 if (sf->heap.heap_cnt) {
867 ts = sf->heap.heap_array[0].ordinal + 1;
876 auxtrace_heap__add(&sf->heap, queue_nr, ts);
880 ret = auxtrace_heap__add(&sf->heap, queue_nr, ts);
895 strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1);
899 err = perf_session__deliver_synth_event(sf->session, &event, NULL);
906 static int s390_cpumsf_lost(struct s390_cpumsf *sf, struct perf_sample *sample)
908 return s390_cpumsf_synth_error(sf, 1, sample->cpu,
909 sample->pid, sample->tid, 0,
910 sample->time);
916 struct perf_sample *sample,
919 struct s390_cpumsf *sf = container_of(session->auxtrace,
922 u64 timestamp = sample->time;
930 if (!tool->ordered_events) {
932 return -EINVAL;
935 if (event->header.type == PERF_RECORD_SAMPLE &&
936 sample->raw_size) {
938 ev_bc000 = evlist__event2evsel(session->evlist, event);
940 ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG)
941 err = s390_cpumcf_dumpctr(sf, sample);
945 if (event->header.type == PERF_RECORD_AUX &&
946 event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
947 return s390_cpumsf_lost(sf, sample);
962 struct s390_cpumsf *sf = container_of(session->auxtrace,
966 int fd = perf_data__fd(session->data);
971 if (sf->data_queued)
974 if (perf_data__is_pipe(session->data)) {
978 if (data_offset == -1)
979 return -errno;
982 err = auxtrace_queues__add_event(&sf->queues, session, event,
990 s390_cpumsf_dump_event(sf, buffer->data,
991 buffer->size);
1010 struct s390_cpumsf *sf = container_of(session->auxtrace,
1013 struct auxtrace_queues *queues = &sf->queues;
1016 for (i = 0; i < queues->nr_queues; i++) {
1018 queues->queue_array[i].priv;
1021 if (sfq->logfile) {
1022 fclose(sfq->logfile);
1023 sfq->logfile = NULL;
1025 if (sfq->logfile_ctr) {
1026 fclose(sfq->logfile_ctr);
1027 sfq->logfile_ctr = NULL;
1030 zfree(&queues->queue_array[i].priv);
1037 struct s390_cpumsf *sf = container_of(session->auxtrace,
1041 auxtrace_heap__free(&sf->heap);
1043 session->auxtrace = NULL;
1044 zfree(&sf->logdir);
1052 return evsel->core.attr.type == PERF_TYPE_RAW &&
1053 evsel->core.attr.config == PERF_EVENT_CPUM_SF_DIAG;
1073 if (!itops || !itops->set)
1075 ison = itops->inject || itops->instructions || itops->branches ||
1076 itops->transactions || itops->ptwrites ||
1077 itops->pwr_events || itops->errors ||
1078 itops->dont_decode || itops->calls || itops->returns ||
1079 itops->callchain || itops->thread_stack ||
1080 itops->last_branch || itops->add_callchain ||
1081 itops->add_last_branch;
1084 pr_err("Unsupported --itrace options specified\n");
1100 sf->logdir = strdup(value);
1101 if (sf->logdir == NULL) {
1106 rc = stat(sf->logdir, &stbuf);
1107 if (rc == -1 || !S_ISDIR(stbuf.st_mode)) {
1110 zfree(&sf->logdir);
1118 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
1122 if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info))
1123 return -EINVAL;
1127 return -ENOMEM;
1129 if (!check_auxtrace_itrace(session->itrace_synth_opts)) {
1130 err = -EINVAL;
1133 sf->use_logfile = session->itrace_synth_opts->log;
1134 if (sf->use_logfile)
1137 err = auxtrace_queues__init(&sf->queues);
1141 sf->session = session;
1142 sf->machine = &session->machines.host; /* No kvm support */
1143 sf->auxtrace_type = auxtrace_info->type;
1144 sf->pmu_type = PERF_TYPE_RAW;
1145 sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid);
1147 sf->auxtrace.process_event = s390_cpumsf_process_event;
1148 sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event;
1149 sf->auxtrace.flush_events = s390_cpumsf_flush;
1150 sf->auxtrace.free_events = s390_cpumsf_free_events;
1151 sf->auxtrace.free = s390_cpumsf_free;
1152 sf->auxtrace.evsel_is_auxtrace = s390_cpumsf_evsel_is_auxtrace;
1153 session->auxtrace = &sf->auxtrace;
1158 err = auxtrace_queues__process_index(&sf->queues, session);
1162 if (sf->queues.populated)
1163 sf->data_queued = true;
1168 auxtrace_queues__free(&sf->queues);
1169 session->auxtrace = NULL;
1171 zfree(&sf->logdir);