^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright IBM Corp. 2018
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Auxtrace support for s390 CPU-Measurement Sampling Facility
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Author(s): Thomas Richter <tmricht@linux.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Auxiliary traces are collected during 'perf record' using rbd000 event.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * Several PERF_RECORD_XXX are generated during recording:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * PERF_RECORD_AUX:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * Records that new data landed in the AUX buffer part.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) * PERF_RECORD_AUXTRACE:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Defines auxtrace data. Followed by the actual data. The contents of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * the auxtrace data is dependent on the event and the CPU.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * This record is generated by perf record command. For details
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * see Documentation/perf.data-file-format.txt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * PERF_RECORD_AUXTRACE_INFO:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * Defines a table of contains for PERF_RECORD_AUXTRACE records. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * record is generated during 'perf record' command. Each record contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) * up to 256 entries describing offset and size of the AUXTRACE data in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) * perf.data file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) * PERF_RECORD_AUXTRACE_ERROR:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) * Indicates an error during AUXTRACE collection such as buffer overflow.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) * PERF_RECORD_FINISHED_ROUND:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) * Perf events are not necessarily in time stamp order, as they can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) * collected in parallel on different CPUs. If the events should be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) * processed in time order they need to be sorted first.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) * Perf report guarantees that there is no reordering over a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * PERF_RECORD_FINISHED_ROUND boundary event. All perf records with a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * time stamp lower than this record are processed (and displayed) before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * the succeeding perf record are processed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * These records are evaluated during perf report command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) * 1. PERF_RECORD_AUXTRACE_INFO is used to set up the infrastructure for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) * auxiliary trace data processing. See s390_cpumsf_process_auxtrace_info()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) * below.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) * Auxiliary trace data is collected per CPU. To merge the data into the report
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) * an auxtrace_queue is created for each CPU. It is assumed that the auxtrace
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) * data is in ascending order.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) * Each queue has a double linked list of auxtrace_buffers. This list contains
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) * the offset and size of a CPU's auxtrace data. During auxtrace processing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) * the data portion is mmap()'ed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * To sort the queues in chronological order, all queue access is controlled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * by the auxtrace_heap. This is basicly a stack, each stack element has two
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * entries, the queue number and a time stamp. However the stack is sorted by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) * the time stamps. The highest time stamp is at the bottom the lowest
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) * (nearest) time stamp is at the top. That sort order is maintained at all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) * times!
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) * After the auxtrace infrastructure has been setup, the auxtrace queues are
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) * filled with data (offset/size pairs) and the auxtrace_heap is populated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) * 2. PERF_RECORD_XXX processing triggers access to the auxtrace_queues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) * Each record is handled by s390_cpumsf_process_event(). The time stamp of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) * the perf record is compared with the time stamp located on the auxtrace_heap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) * top element. If that time stamp is lower than the time stamp from the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) * record sample, the auxtrace queues will be processed. As auxtrace queues
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) * control many auxtrace_buffers and each buffer can be quite large, the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) * auxtrace buffer might be processed only partially. In this case the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) * position in the auxtrace_buffer of that queue is remembered and the time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) * stamp of the last processed entry of the auxtrace_buffer replaces the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) * current auxtrace_heap top.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) * 3. Auxtrace_queues might run of out data and are feeded by the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) * PERF_RECORD_AUXTRACE handling, see s390_cpumsf_process_auxtrace_event().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) * Event Generation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * Each sampling-data entry in the auxilary trace data generates a perf sample.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * This sample is filled
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * with data from the auxtrace such as PID/TID, instruction address, CPU state,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * etc. This sample is processed with perf_session__deliver_synth_event() to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * be included into the GUI.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * 4. PERF_RECORD_FINISHED_ROUND event is used to process all the remaining
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * auxiliary traces entries until the time stamp of this record is reached
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * auxtrace_heap top. This is triggered by ordered_event->deliver().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * Perf event processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * Event processing of PERF_RECORD_XXX entries relies on time stamp entries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * This is the function call sequence:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * __cmd_report()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * perf_session__process_events()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) * __perf_session__process_events()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) * perf_session__process_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * | This functions splits the PERF_RECORD_XXX records.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * | - Those generated by perf record command (type number equal or higher
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) * | than PERF_RECORD_USER_TYPE_START) are handled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * | perf_session__process_user_event(see below)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) * | - Those generated by the kernel are handled by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * | perf_evlist__parse_sample_timestamp()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) * perf_evlist__parse_sample_timestamp()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * | Extract time stamp from sample data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * perf_session__queue_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * | If timestamp is positive the sample is entered into an ordered_event
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * | list, sort order is the timestamp. The event processing is deferred until
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * | later (see perf_session__process_user_event()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * | Other timestamps (0 or -1) are handled immediately by
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * | perf_session__deliver_event(). These are events generated at start up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * | of command perf record. They create PERF_RECORD_COMM and PERF_RECORD_MMAP*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * | records. They are needed to create a list of running processes and its
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * | memory mappings and layout. They are needed at the beginning to enable
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) * | command perf report to create process trees and memory mappings.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) * perf_session__deliver_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) * | Delivers a PERF_RECORD_XXX entry for handling.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) * auxtrace__process_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) * | The timestamp of the PERF_RECORD_XXX entry is taken to correlate with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) * | time stamps from the auxiliary trace buffers. This enables
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) * | synchronization between auxiliary trace data and the events on the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) * | perf.data file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * machine__deliver_event()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) * | Handles the PERF_RECORD_XXX event. This depends on the record type.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) * It might update the process tree, update a process memory map or enter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) * a sample with IP and call back chain data into GUI data pool.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) * Deferred processing determined by perf_session__process_user_event() is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) * finally processed when a PERF_RECORD_FINISHED_ROUND is encountered. These
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * are generated during command perf record.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * The timestamp of PERF_RECORD_FINISHED_ROUND event is taken to process all
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * PERF_RECORD_XXX entries stored in the ordered_event list. This list was
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) * built up while reading the perf.data file.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * Each event is now processed by calling perf_session__deliver_event().
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * This enables time synchronization between the data in the perf.data file and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * the data in the auxiliary trace buffers.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) #include <endian.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) #include <byteswap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) #include <linux/bitops.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) #include <linux/log2.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) #include <sys/stat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) #include <sys/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) #include "color.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #include "evsel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) #include "evlist.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) #include "machine.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) #include "session.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) #include "tool.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) #include "auxtrace.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) #include "s390-cpumsf.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) #include "s390-cpumsf-kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #include "s390-cpumcf-kernel.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) #include "config.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) struct s390_cpumsf {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) struct auxtrace auxtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) struct auxtrace_queues queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) struct auxtrace_heap heap;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) struct perf_session *session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) struct machine *machine;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) u32 auxtrace_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) u32 pmu_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) u16 machine_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) bool data_queued;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) bool use_logfile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) char *logdir;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) struct s390_cpumsf_queue {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) struct s390_cpumsf *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) unsigned int queue_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) struct auxtrace_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) int cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) FILE *logfile;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) FILE *logfile_ctr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) /* Check if the raw data should be dumped to file. If this is the case and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) * the file to dump to has not been opened for writing, do so.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) * Return 0 on success and greater zero on error so processing continues.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) static int s390_cpumcf_dumpctr(struct s390_cpumsf *sf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) struct s390_cpumsf_queue *sfq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) struct auxtrace_queue *q;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) int rc = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) if (!sf->use_logfile || sf->queues.nr_queues <= sample->cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) q = &sf->queues.queue_array[sample->cpu];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) sfq = q->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) if (!sfq) /* Queue not yet allocated */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) if (!sfq->logfile_ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) rc = (sf->logdir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ? asprintf(&name, "%s/aux.ctr.%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) sf->logdir, sample->cpu)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) : asprintf(&name, "aux.ctr.%02x", sample->cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) if (rc > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) sfq->logfile_ctr = fopen(name, "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) if (sfq->logfile_ctr == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) pr_err("Failed to open counter set log file %s, "
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) "continue...\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) free(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) if (sfq->logfile_ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) /* See comment above for -4 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) size_t n = fwrite(sample->raw_data, sample->raw_size - 4, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) sfq->logfile_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) if (n != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) pr_err("Failed to write counter set data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) rc = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) return rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) /* Display s390 CPU measurement facility basic-sampling data entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) * Data written on s390 in big endian byte order and contains bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) * fields across byte boundaries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) static bool s390_cpumsf_basic_show(const char *color, size_t pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) struct hws_basic_entry *basicp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) struct hws_basic_entry *basic = basicp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) #if __BYTE_ORDER == __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) struct hws_basic_entry local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) unsigned long long word = be64toh(*(unsigned long long *)basicp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) memset(&local, 0, sizeof(local));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) local.def = be16toh(basicp->def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) local.prim_asn = word & 0xffff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) local.CL = word >> 30 & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) local.I = word >> 32 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) local.AS = word >> 33 & 0x3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) local.P = word >> 35 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) local.W = word >> 36 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) local.T = word >> 37 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) local.U = word >> 40 & 0xf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) local.ia = be64toh(basicp->ia);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) local.gpp = be64toh(basicp->gpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) local.hpp = be64toh(basicp->hpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) basic = &local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) if (basic->def != 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) pr_err("Invalid AUX trace basic entry [%#08zx]\n", pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) color_fprintf(stdout, color, " [%#08zx] Basic Def:%04x Inst:%#04x"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) " %c%c%c%c AS:%d ASN:%#04x IA:%#018llx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) "\t\tCL:%d HPP:%#018llx GPP:%#018llx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) pos, basic->def, basic->U,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) basic->T ? 'T' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) basic->W ? 'W' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) basic->P ? 'P' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) basic->I ? 'I' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) basic->AS, basic->prim_asn, basic->ia, basic->CL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) basic->hpp, basic->gpp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) /* Display s390 CPU measurement facility diagnostic-sampling data entry.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * Data written on s390 in big endian byte order and contains bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) * fields across byte boundaries.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static bool s390_cpumsf_diag_show(const char *color, size_t pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) struct hws_diag_entry *diagp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) struct hws_diag_entry *diag = diagp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) #if __BYTE_ORDER == __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) struct hws_diag_entry local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) unsigned long long word = be64toh(*(unsigned long long *)diagp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) local.def = be16toh(diagp->def);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) local.I = word >> 32 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) diag = &local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) pr_err("Invalid AUX trace diagnostic entry [%#08zx]\n", pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) color_fprintf(stdout, color, " [%#08zx] Diag Def:%04x %c\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) pos, diag->def, diag->I ? 'I' : ' ');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) /* Return TOD timestamp contained in an trailer entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) static unsigned long long trailer_timestamp(struct hws_trailer_entry *te,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) /* te->t set: TOD in STCKE format, bytes 8-15
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) * to->t not set: TOD in STCK format, bytes 0-7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) unsigned long long ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) memcpy(&ts, &te->timestamp[idx], sizeof(ts));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) return be64toh(ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) /* Display s390 CPU measurement facility trailer entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) static bool s390_cpumsf_trailer_show(const char *color, size_t pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) struct hws_trailer_entry *te)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) #if __BYTE_ORDER == __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) struct hws_trailer_entry local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) const unsigned long long flags = be64toh(te->flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) memset(&local, 0, sizeof(local));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) local.f = flags >> 63 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) local.a = flags >> 62 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) local.t = flags >> 61 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) local.bsdes = be16toh((flags >> 16 & 0xffff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) local.dsdes = be16toh((flags & 0xffff));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) memcpy(&local.timestamp, te->timestamp, sizeof(te->timestamp));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) local.overflow = be64toh(te->overflow);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) local.clock_base = be64toh(te->progusage[0]) >> 63 & 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) local.progusage2 = be64toh(te->progusage2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) te = &local;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) if (te->bsdes != sizeof(struct hws_basic_entry)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) pr_err("Invalid AUX trace trailer entry [%#08zx]\n", pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) color_fprintf(stdout, color, " [%#08zx] Trailer %c%c%c bsdes:%d"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) " dsdes:%d Overflow:%lld Time:%#llx\n"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) "\t\tC:%d TOD:%#lx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) te->f ? 'F' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) te->a ? 'A' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) te->t ? 'T' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) te->bsdes, te->dsdes, te->overflow,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) trailer_timestamp(te, te->clock_base),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) te->clock_base, te->progusage2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) /* Test a sample data block. It must be 4KB or a multiple thereof in size and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) * 4KB page aligned. Each sample data page has a trailer entry at the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) * end which contains the sample entry data sizes.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) * Return true if the sample data block passes the checks and set the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) * basic set entry size and diagnostic set entry size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) * Return false on failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) * Note: Old hardware does not set the basic or diagnostic entry sizes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) * in the trailer entry. Use the type number instead.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) static bool s390_cpumsf_validate(int machine_type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) unsigned char *buf, size_t len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) unsigned short *bsdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) unsigned short *dsdes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) struct hws_basic_entry *basic = (struct hws_basic_entry *)buf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) struct hws_trailer_entry *te;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) *dsdes = *bsdes = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) if (be16toh(basic->def) != 1) /* No basic set entry, must be first */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) /* Check for trailer entry at end of SDB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) - sizeof(*te));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) *bsdes = be16toh(te->bsdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) *dsdes = be16toh(te->dsdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) if (!te->bsdes && !te->dsdes) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) /* Very old hardware, use CPUID */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) switch (machine_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) case 2097:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) case 2098:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) *dsdes = 64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) *bsdes = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) case 2817:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) case 2818:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) *dsdes = 74;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) *bsdes = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) case 2827:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402) case 2828:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) *dsdes = 85;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) *bsdes = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) case 2964:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) case 2965:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408) *dsdes = 112;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) *bsdes = 32;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) /* Illegal trailer entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) /* Return true if there is room for another entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420) static bool s390_cpumsf_reached_trailer(size_t entry_sz, size_t pos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) /* Dump an auxiliary buffer. These buffers are multiple of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) * 4KB SDB pages.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) static void s390_cpumsf_dump(struct s390_cpumsf *sf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) unsigned char *buf, size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435) const char *color = PERF_COLOR_BLUE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) struct hws_basic_entry *basic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) struct hws_diag_entry *diag;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) unsigned short bsdes, dsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439) size_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) color_fprintf(stdout, color,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) ". ... s390 AUX data: size %zu bytes\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) &dsdes)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) pr_err("Invalid AUX trace data block size:%zu"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) " (type:%d bsdes:%hd dsdes:%hd)\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) len, sf->machine_type, bsdes, dsdes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) /* s390 kernel always returns 4KB blocks fully occupied,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) * no partially filled SDBs.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) while (pos < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) /* Handle Basic entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) basic = (struct hws_basic_entry *)(buf + pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) if (s390_cpumsf_basic_show(color, pos, basic))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) pos += bsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) /* Handle Diagnostic entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) diag = (struct hws_diag_entry *)(buf + pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) if (s390_cpumsf_diag_show(color, pos, diag))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) pos += dsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Check for trailer entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) /* Show trailer entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) struct hws_trailer_entry te;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) pos = (pos + S390_CPUMSF_PAGESZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) & ~(S390_CPUMSF_PAGESZ - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) pos -= sizeof(te);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479) memcpy(&te, buf + pos, sizeof(te));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) /* Set descriptor sizes in case of old hardware
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) * where these values are not set.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) te.bsdes = bsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) te.dsdes = dsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) if (s390_cpumsf_trailer_show(color, pos, &te))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) pos += sizeof(te);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) static void s390_cpumsf_dump_event(struct s390_cpumsf *sf, unsigned char *buf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) size_t len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) printf(".\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) s390_cpumsf_dump(sf, buf, len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) #define S390_LPP_PID_MASK 0xffffffff
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502) static bool s390_cpumsf_make_event(size_t pos,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) struct hws_basic_entry *basic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) struct s390_cpumsf_queue *sfq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) struct perf_sample sample = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507) .ip = basic->ia,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) .pid = basic->hpp & S390_LPP_PID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) .tid = basic->hpp & S390_LPP_PID_MASK,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) .cpumode = PERF_RECORD_MISC_CPUMODE_UNKNOWN,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) .cpu = sfq->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) .period = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) memset(&event, 0, sizeof(event));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) if (basic->CL == 1) /* Native LPAR mode */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519) : PERF_RECORD_MISC_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) else if (basic->CL == 2) /* Guest kernel/user space */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) : PERF_RECORD_MISC_GUEST_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) else if (basic->gpp || basic->prim_asn != 0xffff)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524) /* Use heuristics on old hardware */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) : PERF_RECORD_MISC_GUEST_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) sample.cpumode = basic->P ? PERF_RECORD_MISC_USER
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) : PERF_RECORD_MISC_KERNEL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) event.sample.header.type = PERF_RECORD_SAMPLE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) event.sample.header.misc = sample.cpumode;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) event.sample.header.size = sizeof(struct perf_event_header);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536) __func__, pos, sample.ip, basic->P, basic->CL, sample.pid,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) sample.tid, sample.cpumode, sample.cpu);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) if (perf_session__deliver_synth_event(sfq->sf->session, &event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) &sample)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) pr_err("s390 Auxiliary Trace: failed to deliver event\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) static unsigned long long get_trailer_time(const unsigned char *buf)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) struct hws_trailer_entry *te;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) unsigned long long aux_time, progusage2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) bool clock_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553) - sizeof(*te));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555) #if __BYTE_ORDER == __LITTLE_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) clock_base = be64toh(te->progusage[0]) >> 63 & 0x1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) progusage2 = be64toh(te->progusage[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) clock_base = te->clock_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) progusage2 = te->progusage2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562) if (!clock_base) /* TOD_CLOCK_BASE value missing */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) /* Correct calculation to convert time stamp in trailer entry to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) * nano seconds (taken from arch/s390 function tod_to_ns()).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) * TOD_CLOCK_BASE is stored in trailer entry member progusage2.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) aux_time = trailer_timestamp(te, clock_base) - progusage2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570) aux_time = (aux_time >> 9) * 125 + (((aux_time & 0x1ff) * 125) >> 9);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) return aux_time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) /* Process the data samples of a single queue. The first parameter is a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575) * pointer to the queue, the second parameter is the time stamp. This
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) * is the time stamp:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) * - of the event that triggered this processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) * - or the time stamp when the last proccesing of this queue stopped.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) * In this case it stopped at a 4KB page boundary and record the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) * position on where to continue processing on the next invocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) * (see buffer->use_data and buffer->use_size).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) * When this function returns the second parameter is updated to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) * reflect the time stamp of the last processed auxiliary data entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585) * (taken from the trailer entry of that page). The caller uses this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) * returned time stamp to record the last processed entry in this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) * queue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) * The function returns:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) * 0: Processing successful. The second parameter returns the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) * time stamp from the trailer entry until which position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592) * processing took place. Subsequent calls resume from this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) * position.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) * <0: An error occurred during processing. The second parameter
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) * returns the maximum time stamp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596) * >0: Done on this queue. The second parameter returns the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) * maximum time stamp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) static int s390_cpumsf_samples(struct s390_cpumsf_queue *sfq, u64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601) struct s390_cpumsf *sf = sfq->sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) unsigned char *buf = sfq->buffer->use_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) size_t len = sfq->buffer->use_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) struct hws_basic_entry *basic;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) unsigned short bsdes, dsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) size_t pos = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607) int err = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) u64 aux_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) &dsdes)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) *ts = ~0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) return -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) /* Get trailer entry time stamp and check if entries in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) * this auxiliary page are ready for processing. If the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) * time stamp of the first entry is too high, whole buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) * can be skipped. In this case return time stamp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) aux_ts = get_trailer_time(buf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) if (!aux_ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) pr_err("[%#08" PRIx64 "] Invalid AUX trailer entry TOD clock base\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) (s64)sfq->buffer->data_offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) aux_ts = ~0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) if (aux_ts > *ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) *ts = aux_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) while (pos < len) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) /* Handle Basic entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) basic = (struct hws_basic_entry *)(buf + pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) if (s390_cpumsf_make_event(pos, basic, sfq))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) pos += bsdes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) err = -EBADF;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) pos += dsdes; /* Skip diagnositic entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) /* Check for trailer entry */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646) if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) pos = (pos + S390_CPUMSF_PAGESZ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) & ~(S390_CPUMSF_PAGESZ - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) /* Check existence of next page */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) if (pos >= len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) aux_ts = get_trailer_time(buf + pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) if (!aux_ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654) aux_ts = ~0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (aux_ts > *ts) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) *ts = aux_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) sfq->buffer->use_data += pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) sfq->buffer->use_size -= pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) *ts = aux_ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) sfq->buffer->use_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668) sfq->buffer->use_data = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) return err; /* Buffer completely scanned or error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) /* Run the s390 auxiliary trace decoder.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) * Select the queue buffer to operate on, the caller already selected
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) * the proper queue, depending on second parameter 'ts'.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) * This is the time stamp until which the auxiliary entries should
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) * be processed. This value is updated by called functions and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) * returned to the caller.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679) * Resume processing in the current buffer. If there is no buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) * get a new buffer from the queue and setup start position for
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) * processing.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) * When a buffer is completely processed remove it from the queue
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) * before returning.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) * This function returns
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686) * 1: When the queue is empty. Second parameter will be set to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) * maximum time stamp.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) * 0: Normal processing done.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) * <0: Error during queue buffer setup. This causes the caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) * to stop processing completely.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) u64 *ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) struct auxtrace_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) struct auxtrace_queue *queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) queue = &sfq->sf->queues.queue_array[sfq->queue_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) /* Get buffer and last position in buffer to resume
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) * decoding the auxiliary entries. One buffer might be large
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) * and decoding might stop in between. This depends on the time
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) * stamp of the trailer entry in each page of the auxiliary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) * data and the time stamp of the event triggering the decoding.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) if (sfq->buffer == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) sfq->buffer = buffer = auxtrace_buffer__next(queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) sfq->buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711) if (!buffer) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) *ts = ~0ULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) return 1; /* Processing done on this queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) /* Start with a new buffer on this queue */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) if (buffer->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) buffer->use_size = buffer->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) buffer->use_data = buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) if (sfq->logfile) { /* Write into log file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) size_t rc = fwrite(buffer->data, buffer->size, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722) sfq->logfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) if (rc != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) pr_err("Failed to write auxiliary data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) } else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) buffer = sfq->buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (!buffer->data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) int fd = perf_data__fd(sfq->sf->session->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) buffer->data = auxtrace_buffer__get_data(buffer, fd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733) if (!buffer->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) buffer->use_size = buffer->size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) buffer->use_data = buffer->data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) if (sfq->logfile) { /* Write into log file */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) size_t rc = fwrite(buffer->data, buffer->size, 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) sfq->logfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741) if (rc != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) pr_err("Failed to write auxiliary data\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745) pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) buffer->size, buffer->use_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) err = s390_cpumsf_samples(sfq, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) /* If non-zero, there is either an error (err < 0) or the buffer is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) * completely done (err > 0). The error is unrecoverable, usually
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) * some descriptors could not be read successfully, so continue with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753) * the next buffer.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) * In both cases the parameter 'ts' has been updated.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) if (err) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) sfq->buffer = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) list_del_init(&buffer->list);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) auxtrace_buffer__free(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) if (err > 0) /* Buffer done, no error */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) static struct s390_cpumsf_queue *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) struct s390_cpumsf_queue *sfq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) sfq = zalloc(sizeof(struct s390_cpumsf_queue));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772) if (sfq == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775) sfq->sf = sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) sfq->queue_nr = queue_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) sfq->cpu = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) if (sf->use_logfile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779) char *name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) rc = (sf->logdir)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) ? asprintf(&name, "%s/aux.smp.%02x",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) sf->logdir, queue_nr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785) : asprintf(&name, "aux.smp.%02x", queue_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (rc > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) sfq->logfile = fopen(name, "w");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) if (sfq->logfile == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) pr_err("Failed to open auxiliary log file %s,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) "continue...\n", name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) sf->use_logfile = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) free(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795) return sfq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798) static int s390_cpumsf_setup_queue(struct s390_cpumsf *sf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) struct auxtrace_queue *queue,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) unsigned int queue_nr, u64 ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) struct s390_cpumsf_queue *sfq = queue->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) if (list_empty(&queue->head))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (sfq == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) sfq = s390_cpumsf_alloc_queue(sf, queue_nr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) if (!sfq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) queue->priv = sfq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) if (queue->cpu != -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814) sfq->cpu = queue->cpu;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) return auxtrace_heap__add(&sf->heap, queue_nr, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819) static int s390_cpumsf_setup_queues(struct s390_cpumsf *sf, u64 ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) for (i = 0; i < sf->queues.nr_queues; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i],
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) i, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) static int s390_cpumsf_update_queues(struct s390_cpumsf *sf, u64 ts)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) if (!sf->queues.new_data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) sf->queues.new_data = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) return s390_cpumsf_setup_queues(sf, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) static int s390_cpumsf_process_queues(struct s390_cpumsf *sf, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) unsigned int queue_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845) u64 ts;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) while (1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) struct auxtrace_queue *queue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) struct s390_cpumsf_queue *sfq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) if (!sf->heap.heap_cnt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) if (sf->heap.heap_array[0].ordinal >= timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858) queue_nr = sf->heap.heap_array[0].queue_nr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) queue = &sf->queues.queue_array[queue_nr];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) sfq = queue->priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) auxtrace_heap__pop(&sf->heap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) if (sf->heap.heap_cnt) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) ts = sf->heap.heap_array[0].ordinal + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) if (ts > timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) ts = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868) ts = timestamp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871) ret = s390_cpumsf_run_decoder(sfq, &ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) if (ret < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) auxtrace_heap__add(&sf->heap, queue_nr, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) ret = auxtrace_heap__add(&sf->heap, queue_nr, ts);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (ret < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) static int s390_cpumsf_synth_error(struct s390_cpumsf *sf, int code, int cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) pid_t pid, pid_t tid, u64 ip, u64 timestamp)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888) char msg[MAX_AUXTRACE_ERROR_MSG];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) union perf_event event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) code, cpu, pid, tid, ip, msg, timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) err = perf_session__deliver_synth_event(sf->session, &event, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898) pr_err("s390 Auxiliary Trace: failed to deliver error event,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) "error %d\n", err);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903) static int s390_cpumsf_lost(struct s390_cpumsf *sf, struct perf_sample *sample)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) return s390_cpumsf_synth_error(sf, 1, sample->cpu,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) sample->pid, sample->tid, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) sample->time);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) s390_cpumsf_process_event(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) struct perf_sample *sample,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) struct perf_tool *tool)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) struct s390_cpumsf *sf = container_of(session->auxtrace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) struct s390_cpumsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) auxtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) u64 timestamp = sample->time;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) struct evsel *ev_bc000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) int err = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) if (dump_trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) if (!tool->ordered_events) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) pr_err("s390 Auxiliary Trace requires ordered events\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) if (event->header.type == PERF_RECORD_SAMPLE &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) sample->raw_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) /* Handle event with raw data */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) ev_bc000 = perf_evlist__event2evsel(session->evlist, event);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936) if (ev_bc000 &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938) err = s390_cpumcf_dumpctr(sf, sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (event->header.type == PERF_RECORD_AUX &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) event->aux.flags & PERF_AUX_FLAG_TRUNCATED)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) return s390_cpumsf_lost(sf, sample);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) if (timestamp) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947) err = s390_cpumsf_update_queues(sf, timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) err = s390_cpumsf_process_queues(sf, timestamp);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) struct s390_cpumsf_synth {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) struct perf_tool cpumsf_tool;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) struct perf_session *session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) s390_cpumsf_process_auxtrace_event(struct perf_session *session,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) union perf_event *event __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) struct perf_tool *tool __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) struct s390_cpumsf *sf = container_of(session->auxtrace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) struct s390_cpumsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966) auxtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) int fd = perf_data__fd(session->data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) struct auxtrace_buffer *buffer;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) off_t data_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973) if (sf->data_queued)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) if (perf_data__is_pipe(session->data)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) data_offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) data_offset = lseek(fd, 0, SEEK_CUR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) if (data_offset == -1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) return -errno;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) err = auxtrace_queues__add_event(&sf->queues, session, event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) data_offset, &buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) /* Dump here after copying piped trace out of the pipe */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) if (dump_trace) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) if (auxtrace_buffer__get_data(buffer, fd)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) s390_cpumsf_dump_event(sf, buffer->data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) buffer->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) auxtrace_buffer__put_data(buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) static void s390_cpumsf_free_events(struct perf_session *session __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) static int s390_cpumsf_flush(struct perf_session *session __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) struct perf_tool *tool __maybe_unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) static void s390_cpumsf_free_queues(struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) struct s390_cpumsf *sf = container_of(session->auxtrace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) struct s390_cpumsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) auxtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) struct auxtrace_queues *queues = &sf->queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) unsigned int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) for (i = 0; i < queues->nr_queues; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) struct s390_cpumsf_queue *sfq = (struct s390_cpumsf_queue *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) queues->queue_array[i].priv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) if (sfq != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) if (sfq->logfile) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) fclose(sfq->logfile);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025) sfq->logfile = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) if (sfq->logfile_ctr) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) fclose(sfq->logfile_ctr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) sfq->logfile_ctr = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) zfree(&queues->queue_array[i].priv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) auxtrace_queues__free(queues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037) static void s390_cpumsf_free(struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) struct s390_cpumsf *sf = container_of(session->auxtrace,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) struct s390_cpumsf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) auxtrace);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) auxtrace_heap__free(&sf->heap);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) s390_cpumsf_free_queues(session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) session->auxtrace = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) zfree(&sf->logdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) free(sf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050) static bool
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) s390_cpumsf_evsel_is_auxtrace(struct perf_session *session __maybe_unused,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) struct evsel *evsel)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) return evsel->core.attr.type == PERF_TYPE_RAW &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) evsel->core.attr.config == PERF_EVENT_CPUM_SF_DIAG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) static int s390_cpumsf_get_type(const char *cpuid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) int ret, family = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062) ret = sscanf(cpuid, "%*[^,],%u", &family);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) return (ret == 1) ? family : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) /* Check itrace options set on perf report command.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) * Return true, if none are set or all options specified can be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) * handled on s390 (currently only option 'd' for logging.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069) * Return false otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) static bool check_auxtrace_itrace(struct itrace_synth_opts *itops)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) bool ison = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) if (!itops || !itops->set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) ison = itops->inject || itops->instructions || itops->branches ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) itops->transactions || itops->ptwrites ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) itops->pwr_events || itops->errors ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080) itops->dont_decode || itops->calls || itops->returns ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) itops->callchain || itops->thread_stack ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) itops->last_branch || itops->add_callchain ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) itops->add_last_branch;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) if (!ison)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) return true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) pr_err("Unsupported --itrace options specified\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) /* Check for AUXTRACE dump directory if it is needed.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) * On failure print an error message but continue.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) * Return 0 on wrong keyword in config file and 1 otherwise.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) static int s390_cpumsf__config(const char *var, const char *value, void *cb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) struct s390_cpumsf *sf = cb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) struct stat stbuf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) int rc;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) if (strcmp(var, "auxtrace.dumpdir"))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) sf->logdir = strdup(value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (sf->logdir == NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) pr_err("Failed to find auxtrace log directory %s,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105) " continue with current directory...\n", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) rc = stat(sf->logdir, &stbuf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) if (rc == -1 || !S_ISDIR(stbuf.st_mode)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) pr_err("Missing auxtrace log directory %s,"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) " continue with current directory...\n", value);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) zfree(&sf->logdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114) return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) int s390_cpumsf_process_auxtrace_info(union perf_event *event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) struct perf_session *session)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) struct s390_cpumsf *sf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) int err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) sf = zalloc(sizeof(struct s390_cpumsf));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) if (sf == NULL)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) if (!check_auxtrace_itrace(session->itrace_synth_opts)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132) err = -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135) sf->use_logfile = session->itrace_synth_opts->log;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) if (sf->use_logfile)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) perf_config(s390_cpumsf__config, sf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) err = auxtrace_queues__init(&sf->queues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1141) goto err_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1143) sf->session = session;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1144) sf->machine = &session->machines.host; /* No kvm support */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1145) sf->auxtrace_type = auxtrace_info->type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1146) sf->pmu_type = PERF_TYPE_RAW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1147) sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1149) sf->auxtrace.process_event = s390_cpumsf_process_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1150) sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1151) sf->auxtrace.flush_events = s390_cpumsf_flush;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1152) sf->auxtrace.free_events = s390_cpumsf_free_events;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1153) sf->auxtrace.free = s390_cpumsf_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1154) sf->auxtrace.evsel_is_auxtrace = s390_cpumsf_evsel_is_auxtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1155) session->auxtrace = &sf->auxtrace;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1157) if (dump_trace)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1158) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1160) err = auxtrace_queues__process_index(&sf->queues, session);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1161) if (err)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1162) goto err_free_queues;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1163)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1164) if (sf->queues.populated)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1165) sf->data_queued = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1166)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1167) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1168)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1169) err_free_queues:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1170) auxtrace_queues__free(&sf->queues);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1171) session->auxtrace = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1172) err_free:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1173) zfree(&sf->logdir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1174) free(sf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1175) return err;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1176) }