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"
202 if (!sf->use_logfile || sf->queues.nr_queues <= sample->cpu) in s390_cpumcf_dumpctr()
205 q = &sf->queues.queue_array[sample->cpu]; in s390_cpumcf_dumpctr()
206 sfq = q->priv; in s390_cpumcf_dumpctr()
210 if (!sfq->logfile_ctr) { in s390_cpumcf_dumpctr()
213 rc = (sf->logdir) in s390_cpumcf_dumpctr()
215 sf->logdir, sample->cpu) in s390_cpumcf_dumpctr()
216 : asprintf(&name, "aux.ctr.%02x", sample->cpu); in s390_cpumcf_dumpctr()
218 sfq->logfile_ctr = fopen(name, "w"); in s390_cpumcf_dumpctr()
219 if (sfq->logfile_ctr == NULL) { in s390_cpumcf_dumpctr()
227 if (sfq->logfile_ctr) { in s390_cpumcf_dumpctr()
228 /* See comment above for -4 */ in s390_cpumcf_dumpctr()
229 size_t n = fwrite(sample->raw_data, sample->raw_size - 4, 1, in s390_cpumcf_dumpctr()
230 sfq->logfile_ctr); in s390_cpumcf_dumpctr()
239 /* Display s390 CPU measurement facility basic-sampling data entry
248 struct hws_basic_entry local; in s390_cpumsf_basic_show() local
251 memset(&local, 0, sizeof(local)); in s390_cpumsf_basic_show()
252 local.def = be16toh(basicp->def); in s390_cpumsf_basic_show()
253 local.prim_asn = word & 0xffff; in s390_cpumsf_basic_show()
254 local.CL = word >> 30 & 0x3; in s390_cpumsf_basic_show()
255 local.I = word >> 32 & 0x1; in s390_cpumsf_basic_show()
256 local.AS = word >> 33 & 0x3; in s390_cpumsf_basic_show()
257 local.P = word >> 35 & 0x1; in s390_cpumsf_basic_show()
258 local.W = word >> 36 & 0x1; in s390_cpumsf_basic_show()
259 local.T = word >> 37 & 0x1; in s390_cpumsf_basic_show()
260 local.U = word >> 40 & 0xf; in s390_cpumsf_basic_show()
261 local.ia = be64toh(basicp->ia); in s390_cpumsf_basic_show()
262 local.gpp = be64toh(basicp->gpp); in s390_cpumsf_basic_show()
263 local.hpp = be64toh(basicp->hpp); in s390_cpumsf_basic_show()
264 basic = &local; in s390_cpumsf_basic_show()
266 if (basic->def != 1) { in s390_cpumsf_basic_show()
273 pos, basic->def, basic->U, in s390_cpumsf_basic_show()
274 basic->T ? 'T' : ' ', in s390_cpumsf_basic_show()
275 basic->W ? 'W' : ' ', in s390_cpumsf_basic_show()
276 basic->P ? 'P' : ' ', in s390_cpumsf_basic_show()
277 basic->I ? 'I' : ' ', in s390_cpumsf_basic_show()
278 basic->AS, basic->prim_asn, basic->ia, basic->CL, in s390_cpumsf_basic_show()
279 basic->hpp, basic->gpp); in s390_cpumsf_basic_show()
283 /* Display s390 CPU measurement facility diagnostic-sampling data entry.
292 struct hws_diag_entry local; in s390_cpumsf_diag_show() local
295 local.def = be16toh(diagp->def); in s390_cpumsf_diag_show()
296 local.I = word >> 32 & 0x1; in s390_cpumsf_diag_show()
297 diag = &local; in s390_cpumsf_diag_show()
299 if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) { in s390_cpumsf_diag_show()
304 pos, diag->def, diag->I ? 'I' : ' '); in s390_cpumsf_diag_show()
312 /* te->t set: TOD in STCKE format, bytes 8-15 in trailer_timestamp()
313 * to->t not set: TOD in STCK format, bytes 0-7 in trailer_timestamp()
317 memcpy(&ts, &te->timestamp[idx], sizeof(ts)); in trailer_timestamp()
326 struct hws_trailer_entry local; in s390_cpumsf_trailer_show() local
327 const unsigned long long flags = be64toh(te->flags); in s390_cpumsf_trailer_show()
329 memset(&local, 0, sizeof(local)); in s390_cpumsf_trailer_show()
330 local.f = flags >> 63 & 0x1; in s390_cpumsf_trailer_show()
331 local.a = flags >> 62 & 0x1; in s390_cpumsf_trailer_show()
332 local.t = flags >> 61 & 0x1; in s390_cpumsf_trailer_show()
333 local.bsdes = be16toh((flags >> 16 & 0xffff)); in s390_cpumsf_trailer_show()
334 local.dsdes = be16toh((flags & 0xffff)); in s390_cpumsf_trailer_show()
335 memcpy(&local.timestamp, te->timestamp, sizeof(te->timestamp)); in s390_cpumsf_trailer_show()
336 local.overflow = be64toh(te->overflow); in s390_cpumsf_trailer_show()
337 local.clock_base = be64toh(te->progusage[0]) >> 63 & 1; in s390_cpumsf_trailer_show()
338 local.progusage2 = be64toh(te->progusage2); in s390_cpumsf_trailer_show()
339 te = &local; in s390_cpumsf_trailer_show()
341 if (te->bsdes != sizeof(struct hws_basic_entry)) { in s390_cpumsf_trailer_show()
349 te->f ? 'F' : ' ', in s390_cpumsf_trailer_show()
350 te->a ? 'A' : ' ', in s390_cpumsf_trailer_show()
351 te->t ? 'T' : ' ', in s390_cpumsf_trailer_show()
352 te->bsdes, te->dsdes, te->overflow, in s390_cpumsf_trailer_show()
353 trailer_timestamp(te, te->clock_base), in s390_cpumsf_trailer_show()
354 te->clock_base, te->progusage2); in s390_cpumsf_trailer_show()
379 if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */ in s390_cpumsf_validate()
381 if (be16toh(basic->def) != 1) /* No basic set entry, must be first */ in s390_cpumsf_validate()
385 - sizeof(*te)); in s390_cpumsf_validate()
386 *bsdes = be16toh(te->bsdes); in s390_cpumsf_validate()
387 *dsdes = be16toh(te->dsdes); in s390_cpumsf_validate()
388 if (!te->bsdes && !te->dsdes) { in s390_cpumsf_validate()
422 size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry); in s390_cpumsf_reached_trailer()
424 if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz) in s390_cpumsf_reached_trailer()
445 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes, in s390_cpumsf_dump()
449 len, sf->machine_type, bsdes, dsdes); in s390_cpumsf_dump()
477 & ~(S390_CPUMSF_PAGESZ - 1); in s390_cpumsf_dump()
478 pos -= sizeof(te); in s390_cpumsf_dump()
507 .ip = basic->ia, in s390_cpumsf_make_event()
508 .pid = basic->hpp & S390_LPP_PID_MASK, in s390_cpumsf_make_event()
509 .tid = basic->hpp & S390_LPP_PID_MASK, in s390_cpumsf_make_event()
511 .cpu = sfq->cpu, in s390_cpumsf_make_event()
517 if (basic->CL == 1) /* Native LPAR mode */ in s390_cpumsf_make_event()
518 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER in s390_cpumsf_make_event()
520 else if (basic->CL == 2) /* Guest kernel/user space */ in s390_cpumsf_make_event()
521 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER in s390_cpumsf_make_event()
523 else if (basic->gpp || basic->prim_asn != 0xffff) in s390_cpumsf_make_event()
525 sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER in s390_cpumsf_make_event()
528 sample.cpumode = basic->P ? PERF_RECORD_MISC_USER in s390_cpumsf_make_event()
535 pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n", in s390_cpumsf_make_event()
536 __func__, pos, sample.ip, basic->P, basic->CL, sample.pid, in s390_cpumsf_make_event()
538 if (perf_session__deliver_synth_event(sfq->sf->session, &event, in s390_cpumsf_make_event()
553 - sizeof(*te)); in get_trailer_time()
556 clock_base = be64toh(te->progusage[0]) >> 63 & 0x1; in get_trailer_time()
557 progusage2 = be64toh(te->progusage[1]); in get_trailer_time()
559 clock_base = te->clock_base; in get_trailer_time()
560 progusage2 = te->progusage2; in get_trailer_time()
569 aux_time = trailer_timestamp(te, clock_base) - progusage2; in get_trailer_time()
577 * - of the event that triggered this processing.
578 * - or the time stamp when the last processing of this queue stopped.
581 * (see buffer->use_data and buffer->use_size).
601 struct s390_cpumsf *sf = sfq->sf; in s390_cpumsf_samples()
602 unsigned char *buf = sfq->buffer->use_data; in s390_cpumsf_samples()
603 size_t len = sfq->buffer->use_size; in s390_cpumsf_samples()
610 if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes, in s390_cpumsf_samples()
613 return -1; in s390_cpumsf_samples()
624 (s64)sfq->buffer->data_offset); in s390_cpumsf_samples()
639 err = -EBADF; in s390_cpumsf_samples()
648 & ~(S390_CPUMSF_PAGESZ - 1); in s390_cpumsf_samples()
659 sfq->buffer->use_data += pos; in s390_cpumsf_samples()
660 sfq->buffer->use_size -= pos; in s390_cpumsf_samples()
667 sfq->buffer->use_size = 0; in s390_cpumsf_samples()
668 sfq->buffer->use_data = NULL; in s390_cpumsf_samples()
700 queue = &sfq->sf->queues.queue_array[sfq->queue_nr]; in s390_cpumsf_run_decoder()
708 if (sfq->buffer == NULL) { in s390_cpumsf_run_decoder()
709 sfq->buffer = buffer = auxtrace_buffer__next(queue, in s390_cpumsf_run_decoder()
710 sfq->buffer); in s390_cpumsf_run_decoder()
716 if (buffer->data) { in s390_cpumsf_run_decoder()
717 buffer->use_size = buffer->size; in s390_cpumsf_run_decoder()
718 buffer->use_data = buffer->data; in s390_cpumsf_run_decoder()
720 if (sfq->logfile) { /* Write into log file */ in s390_cpumsf_run_decoder()
721 size_t rc = fwrite(buffer->data, buffer->size, 1, in s390_cpumsf_run_decoder()
722 sfq->logfile); in s390_cpumsf_run_decoder()
727 buffer = sfq->buffer; in s390_cpumsf_run_decoder()
729 if (!buffer->data) { in s390_cpumsf_run_decoder()
730 int fd = perf_data__fd(sfq->sf->session->data); in s390_cpumsf_run_decoder()
732 buffer->data = auxtrace_buffer__get_data(buffer, fd); in s390_cpumsf_run_decoder()
733 if (!buffer->data) in s390_cpumsf_run_decoder()
734 return -ENOMEM; in s390_cpumsf_run_decoder()
735 buffer->use_size = buffer->size; in s390_cpumsf_run_decoder()
736 buffer->use_data = buffer->data; in s390_cpumsf_run_decoder()
738 if (sfq->logfile) { /* Write into log file */ in s390_cpumsf_run_decoder()
739 size_t rc = fwrite(buffer->data, buffer->size, 1, in s390_cpumsf_run_decoder()
740 sfq->logfile); in s390_cpumsf_run_decoder()
746 __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset, in s390_cpumsf_run_decoder()
747 buffer->size, buffer->use_size); in s390_cpumsf_run_decoder()
750 /* If non-zero, there is either an error (err < 0) or the buffer is in s390_cpumsf_run_decoder()
757 sfq->buffer = NULL; in s390_cpumsf_run_decoder()
758 list_del_init(&buffer->list); in s390_cpumsf_run_decoder()
775 sfq->sf = sf; in s390_cpumsf_alloc_queue()
776 sfq->queue_nr = queue_nr; in s390_cpumsf_alloc_queue()
777 sfq->cpu = -1; in s390_cpumsf_alloc_queue()
778 if (sf->use_logfile) { in s390_cpumsf_alloc_queue()
782 rc = (sf->logdir) in s390_cpumsf_alloc_queue()
784 sf->logdir, queue_nr) in s390_cpumsf_alloc_queue()
787 sfq->logfile = fopen(name, "w"); in s390_cpumsf_alloc_queue()
788 if (sfq->logfile == NULL) { in s390_cpumsf_alloc_queue()
791 sf->use_logfile = false; in s390_cpumsf_alloc_queue()
802 struct s390_cpumsf_queue *sfq = queue->priv; in s390_cpumsf_setup_queue()
804 if (list_empty(&queue->head)) in s390_cpumsf_setup_queue()
810 return -ENOMEM; in s390_cpumsf_setup_queue()
811 queue->priv = sfq; in s390_cpumsf_setup_queue()
813 if (queue->cpu != -1) in s390_cpumsf_setup_queue()
814 sfq->cpu = queue->cpu; in s390_cpumsf_setup_queue()
816 return auxtrace_heap__add(&sf->heap, queue_nr, ts); in s390_cpumsf_setup_queue()
824 for (i = 0; i < sf->queues.nr_queues; i++) { in s390_cpumsf_setup_queues()
825 ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i], in s390_cpumsf_setup_queues()
835 if (!sf->queues.new_data) in s390_cpumsf_update_queues()
838 sf->queues.new_data = false; in s390_cpumsf_update_queues()
852 if (!sf->heap.heap_cnt) in s390_cpumsf_process_queues()
855 if (sf->heap.heap_array[0].ordinal >= timestamp) in s390_cpumsf_process_queues()
858 queue_nr = sf->heap.heap_array[0].queue_nr; in s390_cpumsf_process_queues()
859 queue = &sf->queues.queue_array[queue_nr]; in s390_cpumsf_process_queues()
860 sfq = queue->priv; in s390_cpumsf_process_queues()
862 auxtrace_heap__pop(&sf->heap); in s390_cpumsf_process_queues()
863 if (sf->heap.heap_cnt) { in s390_cpumsf_process_queues()
864 ts = sf->heap.heap_array[0].ordinal + 1; in s390_cpumsf_process_queues()
873 auxtrace_heap__add(&sf->heap, queue_nr, ts); in s390_cpumsf_process_queues()
877 ret = auxtrace_heap__add(&sf->heap, queue_nr, ts); in s390_cpumsf_process_queues()
886 pid_t pid, pid_t tid, u64 ip, u64 timestamp) in s390_cpumsf_synth_error() argument
892 strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1); in s390_cpumsf_synth_error()
894 code, cpu, pid, tid, ip, msg, timestamp); in s390_cpumsf_synth_error()
896 err = perf_session__deliver_synth_event(sf->session, &event, NULL); in s390_cpumsf_synth_error()
905 return s390_cpumsf_synth_error(sf, 1, sample->cpu, in s390_cpumsf_lost()
906 sample->pid, sample->tid, 0, in s390_cpumsf_lost()
907 sample->time); in s390_cpumsf_lost()
916 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_process_event()
919 u64 timestamp = sample->time; in s390_cpumsf_process_event()
927 if (!tool->ordered_events) { in s390_cpumsf_process_event()
929 return -EINVAL; in s390_cpumsf_process_event()
932 if (event->header.type == PERF_RECORD_SAMPLE && in s390_cpumsf_process_event()
933 sample->raw_size) { in s390_cpumsf_process_event()
935 ev_bc000 = evlist__event2evsel(session->evlist, event); in s390_cpumsf_process_event()
937 ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG) in s390_cpumsf_process_event()
942 if (event->header.type == PERF_RECORD_AUX && in s390_cpumsf_process_event()
943 event->aux.flags & PERF_AUX_FLAG_TRUNCATED) in s390_cpumsf_process_event()
964 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_process_auxtrace_event()
968 int fd = perf_data__fd(session->data); in s390_cpumsf_process_auxtrace_event()
973 if (sf->data_queued) in s390_cpumsf_process_auxtrace_event()
976 if (perf_data__is_pipe(session->data)) { in s390_cpumsf_process_auxtrace_event()
980 if (data_offset == -1) in s390_cpumsf_process_auxtrace_event()
981 return -errno; in s390_cpumsf_process_auxtrace_event()
984 err = auxtrace_queues__add_event(&sf->queues, session, event, in s390_cpumsf_process_auxtrace_event()
992 s390_cpumsf_dump_event(sf, buffer->data, in s390_cpumsf_process_auxtrace_event()
993 buffer->size); in s390_cpumsf_process_auxtrace_event()
1012 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_free_queues()
1015 struct auxtrace_queues *queues = &sf->queues; in s390_cpumsf_free_queues()
1018 for (i = 0; i < queues->nr_queues; i++) { in s390_cpumsf_free_queues()
1020 queues->queue_array[i].priv; in s390_cpumsf_free_queues()
1023 if (sfq->logfile) { in s390_cpumsf_free_queues()
1024 fclose(sfq->logfile); in s390_cpumsf_free_queues()
1025 sfq->logfile = NULL; in s390_cpumsf_free_queues()
1027 if (sfq->logfile_ctr) { in s390_cpumsf_free_queues()
1028 fclose(sfq->logfile_ctr); in s390_cpumsf_free_queues()
1029 sfq->logfile_ctr = NULL; in s390_cpumsf_free_queues()
1032 zfree(&queues->queue_array[i].priv); in s390_cpumsf_free_queues()
1039 struct s390_cpumsf *sf = container_of(session->auxtrace, in s390_cpumsf_free()
1043 auxtrace_heap__free(&sf->heap); in s390_cpumsf_free()
1045 session->auxtrace = NULL; in s390_cpumsf_free()
1046 zfree(&sf->logdir); in s390_cpumsf_free()
1054 return evsel->core.attr.type == PERF_TYPE_RAW && in s390_cpumsf_evsel_is_auxtrace()
1055 evsel->core.attr.config == PERF_EVENT_CPUM_SF_DIAG; in s390_cpumsf_evsel_is_auxtrace()
1075 if (!itops || !itops->set) in check_auxtrace_itrace()
1077 ison = itops->inject || itops->instructions || itops->branches || in check_auxtrace_itrace()
1078 itops->transactions || itops->ptwrites || in check_auxtrace_itrace()
1079 itops->pwr_events || itops->errors || in check_auxtrace_itrace()
1080 itops->dont_decode || itops->calls || itops->returns || in check_auxtrace_itrace()
1081 itops->callchain || itops->thread_stack || in check_auxtrace_itrace()
1082 itops->last_branch || itops->add_callchain || in check_auxtrace_itrace()
1083 itops->add_last_branch; in check_auxtrace_itrace()
1086 pr_err("Unsupported --itrace options specified\n"); in check_auxtrace_itrace()
1102 sf->logdir = strdup(value); in s390_cpumsf__config()
1103 if (sf->logdir == NULL) { in s390_cpumsf__config()
1108 rc = stat(sf->logdir, &stbuf); in s390_cpumsf__config()
1109 if (rc == -1 || !S_ISDIR(stbuf.st_mode)) { in s390_cpumsf__config()
1112 zfree(&sf->logdir); in s390_cpumsf__config()
1120 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; in s390_cpumsf_process_auxtrace_info()
1124 if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info)) in s390_cpumsf_process_auxtrace_info()
1125 return -EINVAL; in s390_cpumsf_process_auxtrace_info()
1129 return -ENOMEM; in s390_cpumsf_process_auxtrace_info()
1131 if (!check_auxtrace_itrace(session->itrace_synth_opts)) { in s390_cpumsf_process_auxtrace_info()
1132 err = -EINVAL; in s390_cpumsf_process_auxtrace_info()
1135 sf->use_logfile = session->itrace_synth_opts->log; in s390_cpumsf_process_auxtrace_info()
1136 if (sf->use_logfile) in s390_cpumsf_process_auxtrace_info()
1139 err = auxtrace_queues__init(&sf->queues); in s390_cpumsf_process_auxtrace_info()
1143 sf->session = session; in s390_cpumsf_process_auxtrace_info()
1144 sf->machine = &session->machines.host; /* No kvm support */ in s390_cpumsf_process_auxtrace_info()
1145 sf->auxtrace_type = auxtrace_info->type; in s390_cpumsf_process_auxtrace_info()
1146 sf->pmu_type = PERF_TYPE_RAW; in s390_cpumsf_process_auxtrace_info()
1147 sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid); in s390_cpumsf_process_auxtrace_info()
1149 sf->auxtrace.process_event = s390_cpumsf_process_event; in s390_cpumsf_process_auxtrace_info()
1150 sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event; in s390_cpumsf_process_auxtrace_info()
1151 sf->auxtrace.flush_events = s390_cpumsf_flush; in s390_cpumsf_process_auxtrace_info()
1152 sf->auxtrace.free_events = s390_cpumsf_free_events; in s390_cpumsf_process_auxtrace_info()
1153 sf->auxtrace.free = s390_cpumsf_free; in s390_cpumsf_process_auxtrace_info()
1154 sf->auxtrace.evsel_is_auxtrace = s390_cpumsf_evsel_is_auxtrace; in s390_cpumsf_process_auxtrace_info()
1155 session->auxtrace = &sf->auxtrace; in s390_cpumsf_process_auxtrace_info()
1160 err = auxtrace_queues__process_index(&sf->queues, session); in s390_cpumsf_process_auxtrace_info()
1164 if (sf->queues.populated) in s390_cpumsf_process_auxtrace_info()
1165 sf->data_queued = true; in s390_cpumsf_process_auxtrace_info()
1170 auxtrace_queues__free(&sf->queues); in s390_cpumsf_process_auxtrace_info()
1171 session->auxtrace = NULL; in s390_cpumsf_process_auxtrace_info()
1173 zfree(&sf->logdir); in s390_cpumsf_process_auxtrace_info()