Lines Matching +full:local +full:- +full:pid
1 // SPDX-License-Identifier: GPL-2.0
4 * Auxtrace support for s390 CPU-Measurement Sampling Facility
17 * see Documentation/perf.data-file-format.txt.
72 * Each sampling-data entry in the auxiliary trace data generates a perf sample.
74 * with data from the auxtrace such as PID/TID, instruction address, CPU state,
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
108 * | Other timestamps (0 or -1) are handled immediately by
162 #include "s390-cpumsf.h"
163 #include "s390-cpumsf-kernel.h"
164 #include "s390-cpumcf-kernel.h"
203 if (!sf->use_logfile || sf->queues.nr_queues <= sample->cpu) in s390_cpumcf_dumpctr()
206 q = &sf->queues.queue_array[sample->cpu]; in s390_cpumcf_dumpctr()
207 sfq = q->priv; in s390_cpumcf_dumpctr()
211 if (!sfq->logfile_ctr) { in s390_cpumcf_dumpctr()
214 rc = (sf->logdir) in s390_cpumcf_dumpctr()
216 sf->logdir, sample->cpu) in s390_cpumcf_dumpctr()
217 : asprintf(&name, "aux.ctr.%02x", sample->cpu); in s390_cpumcf_dumpctr()
219 sfq->logfile_ctr = fopen(name, "w"); in s390_cpumcf_dumpctr()
220 if (sfq->logfile_ctr == NULL) { in s390_cpumcf_dumpctr()
228 if (sfq->logfile_ctr) { in s390_cpumcf_dumpctr()
229 /* See comment above for -4 */ in s390_cpumcf_dumpctr()
230 size_t n = fwrite(sample->raw_data, sample->raw_size - 4, 1, in s390_cpumcf_dumpctr()
231 sfq->logfile_ctr); in s390_cpumcf_dumpctr()
240 /* Display s390 CPU measurement facility basic-sampling data entry
249 struct hws_basic_entry local; in s390_cpumsf_basic_show() local
252 memset(&local, 0, sizeof(local)); in s390_cpumsf_basic_show()
253 local.def = be16toh(basicp->def); in s390_cpumsf_basic_show()
254 local.prim_asn = word & 0xffff; in s390_cpumsf_basic_show()
255 local.CL = word >> 30 & 0x3; in s390_cpumsf_basic_show()
256 local.I = word >> 32 & 0x1; in s390_cpumsf_basic_show()
257 local.AS = word >> 33 & 0x3; in s390_cpumsf_basic_show()
258 local.P = word >> 35 & 0x1; in s390_cpumsf_basic_show()
259 local.W = word >> 36 & 0x1; in s390_cpumsf_basic_show()
260 local.T = word >> 37 & 0x1; in s390_cpumsf_basic_show()
261 local.U = word >> 40 & 0xf; in s390_cpumsf_basic_show()
262 local.ia = be64toh(basicp->ia); in s390_cpumsf_basic_show()
263 local.gpp = be64toh(basicp->gpp); in s390_cpumsf_basic_show()
264 local.hpp = be64toh(basicp->hpp); in s390_cpumsf_basic_show()
265 basic = &local; in s390_cpumsf_basic_show()
267 if (basic->def != 1) { in s390_cpumsf_basic_show()
274 pos, basic->def, basic->U, in s390_cpumsf_basic_show()
275 basic->T ? 'T' : ' ', in s390_cpumsf_basic_show()
276 basic->W ? 'W' : ' ', in s390_cpumsf_basic_show()
277 basic->P ? 'P' : ' ', in s390_cpumsf_basic_show()
278 basic->I ? 'I' : ' ', in s390_cpumsf_basic_show()
279 basic->AS, basic->prim_asn, basic->ia, basic->CL, in s390_cpumsf_basic_show()
280 basic->hpp, basic->gpp); in s390_cpumsf_basic_show()
284 /* Display s390 CPU measurement facility diagnostic-sampling data entry.
293 struct hws_diag_entry local; in s390_cpumsf_diag_show() local
296 local.def = be16toh(diagp->def); in s390_cpumsf_diag_show()
297 local.I = word >> 32 & 0x1; in s390_cpumsf_diag_show()
298 diag = &local; in s390_cpumsf_diag_show()
300 if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) { in s390_cpumsf_diag_show()
305 pos, diag->def, diag->I ? 'I' : ' '); in s390_cpumsf_diag_show()
313 /* te->t set: TOD in STCKE format, bytes 8-15 in trailer_timestamp()
314 * to->t not set: TOD in STCK format, bytes 0-7 in trailer_timestamp()
318 memcpy(&ts, &te->timestamp[idx], sizeof(ts)); in trailer_timestamp()
327 struct hws_trailer_entry local; in s390_cpumsf_trailer_show() local
328 const unsigned long long flags = be64toh(te->flags); in s390_cpumsf_trailer_show()
330 memset(&local, 0, sizeof(local)); in s390_cpumsf_trailer_show()
331 local.f = flags >> 63 & 0x1; in s390_cpumsf_trailer_show()
332 local.a = flags >> 62 & 0x1; in s390_cpumsf_trailer_show()
333 local.t = flags >> 61 & 0x1; in s390_cpumsf_trailer_show()
334 local.bsdes = be16toh((flags >> 16 & 0xffff)); in s390_cpumsf_trailer_show()
335 local.dsdes = be16toh((flags & 0xffff)); in s390_cpumsf_trailer_show()
336 memcpy(&local.timestamp, te->timestamp, sizeof(te->timestamp)); in s390_cpumsf_trailer_show()
337 local.overflow = be64toh(te->overflow); in s390_cpumsf_trailer_show()
338 local.clock_base = be64toh(te->progusage[0]) >> 63 & 1; in s390_cpumsf_trailer_show()
339 local.progusage2 = be64toh(te->progusage2); in s390_cpumsf_trailer_show()
340 te = &local; in s390_cpumsf_trailer_show()
342 if (te->bsdes != sizeof(struct hws_basic_entry)) { in s390_cpumsf_trailer_show()
350 te->f ? 'F' : ' ', in s390_cpumsf_trailer_show()
351 te->a ? 'A' : ' ', in s390_cpumsf_trailer_show()
352 te->t ? 'T' : ' ', in s390_cpumsf_trailer_show()
353 te->bsdes, te->dsdes, te->overflow, in s390_cpumsf_trailer_show()
354 trailer_timestamp(te, te->clock_base), in s390_cpumsf_trailer_show()
355 te->clock_base, te->progusage2); in s390_cpumsf_trailer_show()
380 if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */ in s390_cpumsf_validate()
382 if (be16toh(basic->def) != 1) /* No basic set entry, must be first */ in s390_cpumsf_validate()
386 - sizeof(*te)); in s390_cpumsf_validate()
387 *bsdes = be16toh(te->bsdes); in s390_cpumsf_validate()
388 *dsdes = be16toh(te->dsdes); in s390_cpumsf_validate()
389 if (!te->bsdes && !te->dsdes) { in s390_cpumsf_validate()
423 size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry); in s390_cpumsf_reached_trailer()
425 if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz) in s390_cpumsf_reached_trailer()
446 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes, in s390_cpumsf_dump()
450 len, sf->machine_type, bsdes, dsdes); in s390_cpumsf_dump()
478 & ~(S390_CPUMSF_PAGESZ - 1); in s390_cpumsf_dump()
479 pos -= sizeof(te); in s390_cpumsf_dump()
508 .ip = basic->ia, in s390_cpumsf_make_event()
509 .pid = basic->hpp & S390_LPP_PID_MASK, in s390_cpumsf_make_event()
510 .tid = basic->hpp & S390_LPP_PID_MASK, in s390_cpumsf_make_event()
512 .cpu = sfq->cpu, in s390_cpumsf_make_event()
518 if (basic->CL == 1) /* Native LPAR mode */ in s390_cpumsf_make_event()
519 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER in s390_cpumsf_make_event()
521 else if (basic->CL == 2) /* Guest kernel/user space */ in s390_cpumsf_make_event()
522 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER in s390_cpumsf_make_event()
524 else if (basic->gpp || basic->prim_asn != 0xffff) in s390_cpumsf_make_event()
526 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER in s390_cpumsf_make_event()
529 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER in s390_cpumsf_make_event()
536 pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n", in s390_cpumsf_make_event()
537 __func__, pos, sample.ip, basic->P, basic->CL, sample.pid, in s390_cpumsf_make_event()
539 if (perf_session__deliver_synth_event(sfq->sf->session, &event, in s390_cpumsf_make_event()
554 - sizeof(*te)); in get_trailer_time()
557 clock_base = be64toh(te->progusage[0]) >> 63 & 0x1; in get_trailer_time()
558 progusage2 = be64toh(te->progusage[1]); in get_trailer_time()
560 clock_base = te->clock_base; in get_trailer_time()
561 progusage2 = te->progusage2; in get_trailer_time()
570 aux_time = trailer_timestamp(te, clock_base) - progusage2; in get_trailer_time()
578 * - of the event that triggered this processing.
579 * - or the time stamp when the last processing of this queue stopped.
582 * (see buffer->use_data and buffer->use_size).
602 struct s390_cpumsf *sf = sfq->sf; in s390_cpumsf_samples()
603 unsigned char *buf = sfq->buffer->use_data; in s390_cpumsf_samples()
604 size_t len = sfq->buffer->use_size; in s390_cpumsf_samples()
611 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes, in s390_cpumsf_samples()
614 return -1; in s390_cpumsf_samples()
625 (s64)sfq->buffer->data_offset); in s390_cpumsf_samples()
640 err = -EBADF; in s390_cpumsf_samples()
649 & ~(S390_CPUMSF_PAGESZ - 1); in s390_cpumsf_samples()
660 sfq->buffer->use_data += pos; in s390_cpumsf_samples()
661 sfq->buffer->use_size -= pos; in s390_cpumsf_samples()
668 sfq->buffer->use_size = 0; in s390_cpumsf_samples()
669 sfq->buffer->use_data = NULL; in s390_cpumsf_samples()
701 queue = &sfq->sf->queues.queue_array[sfq->queue_nr]; in s390_cpumsf_run_decoder()
709 if (sfq->buffer == NULL) { in s390_cpumsf_run_decoder()
710 sfq->buffer = buffer = auxtrace_buffer__next(queue, in s390_cpumsf_run_decoder()
711 sfq->buffer); in s390_cpumsf_run_decoder()
717 if (buffer->data) { in s390_cpumsf_run_decoder()
718 buffer->use_size = buffer->size; in s390_cpumsf_run_decoder()
719 buffer->use_data = buffer->data; in s390_cpumsf_run_decoder()
721 if (sfq->logfile) { /* Write into log file */ in s390_cpumsf_run_decoder()
722 size_t rc = fwrite(buffer->data, buffer->size, 1, in s390_cpumsf_run_decoder()
723 sfq->logfile); in s390_cpumsf_run_decoder()
728 buffer = sfq->buffer; in s390_cpumsf_run_decoder()
730 if (!buffer->data) { in s390_cpumsf_run_decoder()
731 int fd = perf_data__fd(sfq->sf->session->data); in s390_cpumsf_run_decoder()
733 buffer->data = auxtrace_buffer__get_data(buffer, fd); in s390_cpumsf_run_decoder()
734 if (!buffer->data) in s390_cpumsf_run_decoder()
735 return -ENOMEM; in s390_cpumsf_run_decoder()
736 buffer->use_size = buffer->size; in s390_cpumsf_run_decoder()
737 buffer->use_data = buffer->data; in s390_cpumsf_run_decoder()
739 if (sfq->logfile) { /* Write into log file */ in s390_cpumsf_run_decoder()
740 size_t rc = fwrite(buffer->data, buffer->size, 1, in s390_cpumsf_run_decoder()
741 sfq->logfile); in s390_cpumsf_run_decoder()
747 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset, in s390_cpumsf_run_decoder()
748 buffer->size, buffer->use_size); in s390_cpumsf_run_decoder()
751 /* If non-zero, there is either an error (err < 0) or the buffer is in s390_cpumsf_run_decoder()
758 sfq->buffer = NULL; in s390_cpumsf_run_decoder()
759 list_del_init(&buffer->list); in s390_cpumsf_run_decoder()
776 sfq->sf = sf; in s390_cpumsf_alloc_queue()
777 sfq->queue_nr = queue_nr; in s390_cpumsf_alloc_queue()
778 sfq->cpu = -1; in s390_cpumsf_alloc_queue()
779 if (sf->use_logfile) { in s390_cpumsf_alloc_queue()
783 rc = (sf->logdir) in s390_cpumsf_alloc_queue()
785 sf->logdir, queue_nr) in s390_cpumsf_alloc_queue()
788 sfq->logfile = fopen(name, "w"); in s390_cpumsf_alloc_queue()
789 if (sfq->logfile == NULL) { in s390_cpumsf_alloc_queue()
792 sf->use_logfile = false; in s390_cpumsf_alloc_queue()
803 struct s390_cpumsf_queue *sfq = queue->priv; in s390_cpumsf_setup_queue()
805 if (list_empty(&queue->head)) in s390_cpumsf_setup_queue()
811 return -ENOMEM; in s390_cpumsf_setup_queue()
812 queue->priv = sfq; in s390_cpumsf_setup_queue()
814 if (queue->cpu != -1) in s390_cpumsf_setup_queue()
815 sfq->cpu = queue->cpu; in s390_cpumsf_setup_queue()
817 return auxtrace_heap__add(&sf->heap, queue_nr, ts); in s390_cpumsf_setup_queue()
825 for (i = 0; i < sf->queues.nr_queues; i++) { in s390_cpumsf_setup_queues()
826 ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i], in s390_cpumsf_setup_queues()
836 if (!sf->queues.new_data) in s390_cpumsf_update_queues()
839 sf->queues.new_data = false; in s390_cpumsf_update_queues()
853 if (!sf->heap.heap_cnt) in s390_cpumsf_process_queues()
856 if (sf->heap.heap_array[0].ordinal >= timestamp) in s390_cpumsf_process_queues()
859 queue_nr = sf->heap.heap_array[0].queue_nr; in s390_cpumsf_process_queues()
860 queue = &sf->queues.queue_array[queue_nr]; in s390_cpumsf_process_queues()
861 sfq = queue->priv; in s390_cpumsf_process_queues()
863 auxtrace_heap__pop(&sf->heap); in s390_cpumsf_process_queues()
864 if (sf->heap.heap_cnt) { in s390_cpumsf_process_queues()
865 ts = sf->heap.heap_array[0].ordinal + 1; in s390_cpumsf_process_queues()
874 auxtrace_heap__add(&sf->heap, queue_nr, ts); in s390_cpumsf_process_queues()
878 ret = auxtrace_heap__add(&sf->heap, queue_nr, ts); in s390_cpumsf_process_queues()
887 pid_t pid, pid_t tid, u64 ip, u64 timestamp) in s390_cpumsf_synth_error() argument
893 strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1); in s390_cpumsf_synth_error()
895 code, cpu, pid, tid, ip, msg, timestamp); in s390_cpumsf_synth_error()
897 err = perf_session__deliver_synth_event(sf->session, &event, NULL); in s390_cpumsf_synth_error()
906 return s390_cpumsf_synth_error(sf, 1, sample->cpu, in s390_cpumsf_lost()
907 sample->pid, sample->tid, 0, in s390_cpumsf_lost()
908 sample->time); in s390_cpumsf_lost()
917 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_process_event()
920 u64 timestamp = sample->time; in s390_cpumsf_process_event()
928 if (!tool->ordered_events) { in s390_cpumsf_process_event()
930 return -EINVAL; in s390_cpumsf_process_event()
933 if (event->header.type == PERF_RECORD_SAMPLE && in s390_cpumsf_process_event()
934 sample->raw_size) { in s390_cpumsf_process_event()
936 ev_bc000 = evlist__event2evsel(session->evlist, event); in s390_cpumsf_process_event()
938 ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG) in s390_cpumsf_process_event()
943 if (event->header.type == PERF_RECORD_AUX && in s390_cpumsf_process_event()
944 event->aux.flags & PERF_AUX_FLAG_TRUNCATED) in s390_cpumsf_process_event()
965 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_process_auxtrace_event()
969 int fd = perf_data__fd(session->data); in s390_cpumsf_process_auxtrace_event()
974 if (sf->data_queued) in s390_cpumsf_process_auxtrace_event()
977 if (perf_data__is_pipe(session->data)) { in s390_cpumsf_process_auxtrace_event()
981 if (data_offset == -1) in s390_cpumsf_process_auxtrace_event()
982 return -errno; in s390_cpumsf_process_auxtrace_event()
985 err = auxtrace_queues__add_event(&sf->queues, session, event, in s390_cpumsf_process_auxtrace_event()
993 s390_cpumsf_dump_event(sf, buffer->data, in s390_cpumsf_process_auxtrace_event()
994 buffer->size); in s390_cpumsf_process_auxtrace_event()
1013 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_free_queues()
1016 struct auxtrace_queues *queues = &sf->queues; in s390_cpumsf_free_queues()
1019 for (i = 0; i < queues->nr_queues; i++) { in s390_cpumsf_free_queues()
1021 queues->queue_array[i].priv; in s390_cpumsf_free_queues()
1024 if (sfq->logfile) { in s390_cpumsf_free_queues()
1025 fclose(sfq->logfile); in s390_cpumsf_free_queues()
1026 sfq->logfile = NULL; in s390_cpumsf_free_queues()
1028 if (sfq->logfile_ctr) { in s390_cpumsf_free_queues()
1029 fclose(sfq->logfile_ctr); in s390_cpumsf_free_queues()
1030 sfq->logfile_ctr = NULL; in s390_cpumsf_free_queues()
1033 zfree(&queues->queue_array[i].priv); in s390_cpumsf_free_queues()
1040 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_free()
1044 auxtrace_heap__free(&sf->heap); in s390_cpumsf_free()
1046 session->auxtrace = NULL; in s390_cpumsf_free()
1047 zfree(&sf->logdir); in s390_cpumsf_free()
1055 return evsel->core.attr.type == PERF_TYPE_RAW && in s390_cpumsf_evsel_is_auxtrace()
1056 evsel->core.attr.config == PERF_EVENT_CPUM_SF_DIAG; in s390_cpumsf_evsel_is_auxtrace()
1076 if (!itops || !itops->set) in check_auxtrace_itrace()
1078 ison = itops->inject || itops->instructions || itops->branches || in check_auxtrace_itrace()
1079 itops->transactions || itops->ptwrites || in check_auxtrace_itrace()
1080 itops->pwr_events || itops->errors || in check_auxtrace_itrace()
1081 itops->dont_decode || itops->calls || itops->returns || in check_auxtrace_itrace()
1082 itops->callchain || itops->thread_stack || in check_auxtrace_itrace()
1083 itops->last_branch || itops->add_callchain || in check_auxtrace_itrace()
1084 itops->add_last_branch; in check_auxtrace_itrace()
1087 pr_err("Unsupported --itrace options specified\n"); in check_auxtrace_itrace()
1103 sf->logdir = strdup(value); in s390_cpumsf__config()
1104 if (sf->logdir == NULL) { in s390_cpumsf__config()
1109 rc = stat(sf->logdir, &stbuf); in s390_cpumsf__config()
1110 if (rc == -1 || !S_ISDIR(stbuf.st_mode)) { in s390_cpumsf__config()
1113 zfree(&sf->logdir); in s390_cpumsf__config()
1121 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; in s390_cpumsf_process_auxtrace_info()
1125 if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info)) in s390_cpumsf_process_auxtrace_info()
1126 return -EINVAL; in s390_cpumsf_process_auxtrace_info()
1130 return -ENOMEM; in s390_cpumsf_process_auxtrace_info()
1132 if (!check_auxtrace_itrace(session->itrace_synth_opts)) { in s390_cpumsf_process_auxtrace_info()
1133 err = -EINVAL; in s390_cpumsf_process_auxtrace_info()
1136 sf->use_logfile = session->itrace_synth_opts->log; in s390_cpumsf_process_auxtrace_info()
1137 if (sf->use_logfile) in s390_cpumsf_process_auxtrace_info()
1140 err = auxtrace_queues__init(&sf->queues); in s390_cpumsf_process_auxtrace_info()
1144 sf->session = session; in s390_cpumsf_process_auxtrace_info()
1145 sf->machine = &session->machines.host; /* No kvm support */ in s390_cpumsf_process_auxtrace_info()
1146 sf->auxtrace_type = auxtrace_info->type; in s390_cpumsf_process_auxtrace_info()
1147 sf->pmu_type = PERF_TYPE_RAW; in s390_cpumsf_process_auxtrace_info()
1148 sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid); in s390_cpumsf_process_auxtrace_info()
1150 sf->auxtrace.process_event = s390_cpumsf_process_event; in s390_cpumsf_process_auxtrace_info()
1151 sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event; in s390_cpumsf_process_auxtrace_info()
1152 sf->auxtrace.flush_events = s390_cpumsf_flush; in s390_cpumsf_process_auxtrace_info()
1153 sf->auxtrace.free_events = s390_cpumsf_free_events; in s390_cpumsf_process_auxtrace_info()
1154 sf->auxtrace.free = s390_cpumsf_free; in s390_cpumsf_process_auxtrace_info()
1155 sf->auxtrace.evsel_is_auxtrace = s390_cpumsf_evsel_is_auxtrace; in s390_cpumsf_process_auxtrace_info()
1156 session->auxtrace = &sf->auxtrace; in s390_cpumsf_process_auxtrace_info()
1161 err = auxtrace_queues__process_index(&sf->queues, session); in s390_cpumsf_process_auxtrace_info()
1165 if (sf->queues.populated) in s390_cpumsf_process_auxtrace_info()
1166 sf->data_queued = true; in s390_cpumsf_process_auxtrace_info()
1171 auxtrace_queues__free(&sf->queues); in s390_cpumsf_process_auxtrace_info()
1172 session->auxtrace = NULL; in s390_cpumsf_process_auxtrace_info()
1174 zfree(&sf->logdir); in s390_cpumsf_process_auxtrace_info()