1b96e6615SThomas Richter // SPDX-License-Identifier: GPL-2.0 2b96e6615SThomas Richter /* 3b96e6615SThomas Richter * Copyright IBM Corp. 2018 4b96e6615SThomas Richter * Auxtrace support for s390 CPU-Measurement Sampling Facility 5b96e6615SThomas Richter * 6b96e6615SThomas Richter * Author(s): Thomas Richter <tmricht@linux.ibm.com> 733d9e183SThomas Richter * 833d9e183SThomas Richter * Auxiliary traces are collected during 'perf record' using rbd000 event. 933d9e183SThomas Richter * Several PERF_RECORD_XXX are generated during recording: 1033d9e183SThomas Richter * 1133d9e183SThomas Richter * PERF_RECORD_AUX: 1233d9e183SThomas Richter * Records that new data landed in the AUX buffer part. 1333d9e183SThomas Richter * PERF_RECORD_AUXTRACE: 1433d9e183SThomas Richter * Defines auxtrace data. Followed by the actual data. The contents of 1533d9e183SThomas Richter * the auxtrace data is dependent on the event and the CPU. 1633d9e183SThomas Richter * This record is generated by perf record command. For details 1733d9e183SThomas Richter * see Documentation/perf.data-file-format.txt. 1833d9e183SThomas Richter * PERF_RECORD_AUXTRACE_INFO: 1933d9e183SThomas Richter * Defines a table of contains for PERF_RECORD_AUXTRACE records. This 20180ca71cSThomas Richter * record is generated during 'perf record' command. Each record contains 21180ca71cSThomas Richter * up to 256 entries describing offset and size of the AUXTRACE data in the 2233d9e183SThomas Richter * perf.data file. 2333d9e183SThomas Richter * PERF_RECORD_AUXTRACE_ERROR: 2433d9e183SThomas Richter * Indicates an error during AUXTRACE collection such as buffer overflow. 2533d9e183SThomas Richter * PERF_RECORD_FINISHED_ROUND: 2633d9e183SThomas Richter * Perf events are not necessarily in time stamp order, as they can be 2733d9e183SThomas Richter * collected in parallel on different CPUs. If the events should be 2833d9e183SThomas Richter * processed in time order they need to be sorted first. 2933d9e183SThomas Richter * Perf report guarantees that there is no reordering over a 3033d9e183SThomas Richter * PERF_RECORD_FINISHED_ROUND boundary event. All perf records with a 3133d9e183SThomas Richter * time stamp lower than this record are processed (and displayed) before 3233d9e183SThomas Richter * the succeeding perf record are processed. 3333d9e183SThomas Richter * 3433d9e183SThomas Richter * These records are evaluated during perf report command. 3533d9e183SThomas Richter * 3633d9e183SThomas Richter * 1. PERF_RECORD_AUXTRACE_INFO is used to set up the infrastructure for 3733d9e183SThomas Richter * auxiliary trace data processing. See s390_cpumsf_process_auxtrace_info() 3833d9e183SThomas Richter * below. 3933d9e183SThomas Richter * Auxiliary trace data is collected per CPU. To merge the data into the report 4033d9e183SThomas Richter * an auxtrace_queue is created for each CPU. It is assumed that the auxtrace 4133d9e183SThomas Richter * data is in ascending order. 4233d9e183SThomas Richter * 4333d9e183SThomas Richter * Each queue has a double linked list of auxtrace_buffers. This list contains 4433d9e183SThomas Richter * the offset and size of a CPU's auxtrace data. During auxtrace processing 4533d9e183SThomas Richter * the data portion is mmap()'ed. 4633d9e183SThomas Richter * 4733d9e183SThomas Richter * To sort the queues in chronological order, all queue access is controlled 4833d9e183SThomas Richter * by the auxtrace_heap. This is basicly a stack, each stack element has two 4933d9e183SThomas Richter * entries, the queue number and a time stamp. However the stack is sorted by 5033d9e183SThomas Richter * the time stamps. The highest time stamp is at the bottom the lowest 5133d9e183SThomas Richter * (nearest) time stamp is at the top. That sort order is maintained at all 5233d9e183SThomas Richter * times! 5333d9e183SThomas Richter * 5433d9e183SThomas Richter * After the auxtrace infrastructure has been setup, the auxtrace queues are 5533d9e183SThomas Richter * filled with data (offset/size pairs) and the auxtrace_heap is populated. 5633d9e183SThomas Richter * 5733d9e183SThomas Richter * 2. PERF_RECORD_XXX processing triggers access to the auxtrace_queues. 5833d9e183SThomas Richter * Each record is handled by s390_cpumsf_process_event(). The time stamp of 5933d9e183SThomas Richter * the perf record is compared with the time stamp located on the auxtrace_heap 6033d9e183SThomas Richter * top element. If that time stamp is lower than the time stamp from the 6133d9e183SThomas Richter * record sample, the auxtrace queues will be processed. As auxtrace queues 6233d9e183SThomas Richter * control many auxtrace_buffers and each buffer can be quite large, the 6333d9e183SThomas Richter * auxtrace buffer might be processed only partially. In this case the 6433d9e183SThomas Richter * position in the auxtrace_buffer of that queue is remembered and the time 6533d9e183SThomas Richter * stamp of the last processed entry of the auxtrace_buffer replaces the 6633d9e183SThomas Richter * current auxtrace_heap top. 6733d9e183SThomas Richter * 6833d9e183SThomas Richter * 3. Auxtrace_queues might run of out data and are feeded by the 6933d9e183SThomas Richter * PERF_RECORD_AUXTRACE handling, see s390_cpumsf_process_auxtrace_event(). 7033d9e183SThomas Richter * 7133d9e183SThomas Richter * Event Generation 7233d9e183SThomas Richter * Each sampling-data entry in the auxilary trace data generates a perf sample. 7333d9e183SThomas Richter * This sample is filled 7433d9e183SThomas Richter * with data from the auxtrace such as PID/TID, instruction address, CPU state, 7533d9e183SThomas Richter * etc. This sample is processed with perf_session__deliver_synth_event() to 7633d9e183SThomas Richter * be included into the GUI. 7733d9e183SThomas Richter * 7833d9e183SThomas Richter * 4. PERF_RECORD_FINISHED_ROUND event is used to process all the remaining 7933d9e183SThomas Richter * auxiliary traces entries until the time stamp of this record is reached 8033d9e183SThomas Richter * auxtrace_heap top. This is triggered by ordered_event->deliver(). 8133d9e183SThomas Richter * 8233d9e183SThomas Richter * 8333d9e183SThomas Richter * Perf event processing. 8433d9e183SThomas Richter * Event processing of PERF_RECORD_XXX entries relies on time stamp entries. 8533d9e183SThomas Richter * This is the function call sequence: 8633d9e183SThomas Richter * 8733d9e183SThomas Richter * __cmd_report() 8833d9e183SThomas Richter * | 8933d9e183SThomas Richter * perf_session__process_events() 9033d9e183SThomas Richter * | 9133d9e183SThomas Richter * __perf_session__process_events() 9233d9e183SThomas Richter * | 9333d9e183SThomas Richter * perf_session__process_event() 9433d9e183SThomas Richter * | This functions splits the PERF_RECORD_XXX records. 9533d9e183SThomas Richter * | - Those generated by perf record command (type number equal or higher 9633d9e183SThomas Richter * | than PERF_RECORD_USER_TYPE_START) are handled by 9733d9e183SThomas Richter * | perf_session__process_user_event(see below) 9833d9e183SThomas Richter * | - Those generated by the kernel are handled by 992a6599cdSArnaldo Carvalho de Melo * | evlist__parse_sample_timestamp() 10033d9e183SThomas Richter * | 1012a6599cdSArnaldo Carvalho de Melo * evlist__parse_sample_timestamp() 10233d9e183SThomas Richter * | Extract time stamp from sample data. 10333d9e183SThomas Richter * | 10433d9e183SThomas Richter * perf_session__queue_event() 10533d9e183SThomas Richter * | If timestamp is positive the sample is entered into an ordered_event 10633d9e183SThomas Richter * | list, sort order is the timestamp. The event processing is deferred until 10733d9e183SThomas Richter * | later (see perf_session__process_user_event()). 10833d9e183SThomas Richter * | Other timestamps (0 or -1) are handled immediately by 10933d9e183SThomas Richter * | perf_session__deliver_event(). These are events generated at start up 11033d9e183SThomas Richter * | of command perf record. They create PERF_RECORD_COMM and PERF_RECORD_MMAP* 11133d9e183SThomas Richter * | records. They are needed to create a list of running processes and its 11233d9e183SThomas Richter * | memory mappings and layout. They are needed at the beginning to enable 11333d9e183SThomas Richter * | command perf report to create process trees and memory mappings. 11433d9e183SThomas Richter * | 11533d9e183SThomas Richter * perf_session__deliver_event() 11633d9e183SThomas Richter * | Delivers a PERF_RECORD_XXX entry for handling. 11733d9e183SThomas Richter * | 11833d9e183SThomas Richter * auxtrace__process_event() 11933d9e183SThomas Richter * | The timestamp of the PERF_RECORD_XXX entry is taken to correlate with 12033d9e183SThomas Richter * | time stamps from the auxiliary trace buffers. This enables 12133d9e183SThomas Richter * | synchronization between auxiliary trace data and the events on the 12233d9e183SThomas Richter * | perf.data file. 12333d9e183SThomas Richter * | 12433d9e183SThomas Richter * machine__deliver_event() 12533d9e183SThomas Richter * | Handles the PERF_RECORD_XXX event. This depends on the record type. 12633d9e183SThomas Richter * It might update the process tree, update a process memory map or enter 12733d9e183SThomas Richter * a sample with IP and call back chain data into GUI data pool. 12833d9e183SThomas Richter * 12933d9e183SThomas Richter * 13033d9e183SThomas Richter * Deferred processing determined by perf_session__process_user_event() is 13133d9e183SThomas Richter * finally processed when a PERF_RECORD_FINISHED_ROUND is encountered. These 13233d9e183SThomas Richter * are generated during command perf record. 13333d9e183SThomas Richter * The timestamp of PERF_RECORD_FINISHED_ROUND event is taken to process all 13433d9e183SThomas Richter * PERF_RECORD_XXX entries stored in the ordered_event list. This list was 13533d9e183SThomas Richter * built up while reading the perf.data file. 13633d9e183SThomas Richter * Each event is now processed by calling perf_session__deliver_event(). 13733d9e183SThomas Richter * This enables time synchronization between the data in the perf.data file and 13833d9e183SThomas Richter * the data in the auxiliary trace buffers. 139b96e6615SThomas Richter */ 140b96e6615SThomas Richter 141b96e6615SThomas Richter #include <endian.h> 142b96e6615SThomas Richter #include <errno.h> 143b96e6615SThomas Richter #include <byteswap.h> 144b96e6615SThomas Richter #include <inttypes.h> 145b96e6615SThomas Richter #include <linux/kernel.h> 146b96e6615SThomas Richter #include <linux/types.h> 147b96e6615SThomas Richter #include <linux/bitops.h> 148b96e6615SThomas Richter #include <linux/log2.h> 1497f7c536fSArnaldo Carvalho de Melo #include <linux/zalloc.h> 150b96e6615SThomas Richter 151766e0618SThomas Richter #include <sys/stat.h> 152766e0618SThomas Richter #include <sys/types.h> 153766e0618SThomas Richter 154b96e6615SThomas Richter #include "color.h" 155b96e6615SThomas Richter #include "evsel.h" 156b96e6615SThomas Richter #include "evlist.h" 157b96e6615SThomas Richter #include "machine.h" 158b96e6615SThomas Richter #include "session.h" 1594a3cec84SArnaldo Carvalho de Melo #include "tool.h" 160b96e6615SThomas Richter #include "debug.h" 161b96e6615SThomas Richter #include "auxtrace.h" 162b96e6615SThomas Richter #include "s390-cpumsf.h" 1632b1444f2SThomas Richter #include "s390-cpumsf-kernel.h" 1648dabe9c4SThomas Richter #include "s390-cpumcf-kernel.h" 165766e0618SThomas Richter #include "config.h" 166b96e6615SThomas Richter 167b96e6615SThomas Richter struct s390_cpumsf { 168b96e6615SThomas Richter struct auxtrace auxtrace; 169b96e6615SThomas Richter struct auxtrace_queues queues; 170b96e6615SThomas Richter struct auxtrace_heap heap; 171b96e6615SThomas Richter struct perf_session *session; 172b96e6615SThomas Richter struct machine *machine; 173b96e6615SThomas Richter u32 auxtrace_type; 174b96e6615SThomas Richter u32 pmu_type; 1752b1444f2SThomas Richter u16 machine_type; 17633d9e183SThomas Richter bool data_queued; 177766e0618SThomas Richter bool use_logfile; 178766e0618SThomas Richter char *logdir; 17933d9e183SThomas Richter }; 18033d9e183SThomas Richter 18133d9e183SThomas Richter struct s390_cpumsf_queue { 18233d9e183SThomas Richter struct s390_cpumsf *sf; 18333d9e183SThomas Richter unsigned int queue_nr; 18433d9e183SThomas Richter struct auxtrace_buffer *buffer; 18533d9e183SThomas Richter int cpu; 186766e0618SThomas Richter FILE *logfile; 1878dabe9c4SThomas Richter FILE *logfile_ctr; 188b96e6615SThomas Richter }; 189b96e6615SThomas Richter 1908dabe9c4SThomas Richter /* Check if the raw data should be dumped to file. If this is the case and 1918dabe9c4SThomas Richter * the file to dump to has not been opened for writing, do so. 1928dabe9c4SThomas Richter * 1938dabe9c4SThomas Richter * Return 0 on success and greater zero on error so processing continues. 1948dabe9c4SThomas Richter */ 1958dabe9c4SThomas Richter static int s390_cpumcf_dumpctr(struct s390_cpumsf *sf, 1968dabe9c4SThomas Richter struct perf_sample *sample) 1978dabe9c4SThomas Richter { 1988dabe9c4SThomas Richter struct s390_cpumsf_queue *sfq; 1998dabe9c4SThomas Richter struct auxtrace_queue *q; 2008dabe9c4SThomas Richter int rc = 0; 2018dabe9c4SThomas Richter 2028dabe9c4SThomas Richter if (!sf->use_logfile || sf->queues.nr_queues <= sample->cpu) 2038dabe9c4SThomas Richter return rc; 2048dabe9c4SThomas Richter 2058dabe9c4SThomas Richter q = &sf->queues.queue_array[sample->cpu]; 2068dabe9c4SThomas Richter sfq = q->priv; 2078dabe9c4SThomas Richter if (!sfq) /* Queue not yet allocated */ 2088dabe9c4SThomas Richter return rc; 2098dabe9c4SThomas Richter 2108dabe9c4SThomas Richter if (!sfq->logfile_ctr) { 2118dabe9c4SThomas Richter char *name; 2128dabe9c4SThomas Richter 2138dabe9c4SThomas Richter rc = (sf->logdir) 2148dabe9c4SThomas Richter ? asprintf(&name, "%s/aux.ctr.%02x", 2158dabe9c4SThomas Richter sf->logdir, sample->cpu) 2168dabe9c4SThomas Richter : asprintf(&name, "aux.ctr.%02x", sample->cpu); 2178dabe9c4SThomas Richter if (rc > 0) 2188dabe9c4SThomas Richter sfq->logfile_ctr = fopen(name, "w"); 2198dabe9c4SThomas Richter if (sfq->logfile_ctr == NULL) { 2208dabe9c4SThomas Richter pr_err("Failed to open counter set log file %s, " 2218dabe9c4SThomas Richter "continue...\n", name); 2228dabe9c4SThomas Richter rc = 1; 2238dabe9c4SThomas Richter } 2248dabe9c4SThomas Richter free(name); 2258dabe9c4SThomas Richter } 2268dabe9c4SThomas Richter 2278dabe9c4SThomas Richter if (sfq->logfile_ctr) { 2288dabe9c4SThomas Richter /* See comment above for -4 */ 2298dabe9c4SThomas Richter size_t n = fwrite(sample->raw_data, sample->raw_size - 4, 1, 2308dabe9c4SThomas Richter sfq->logfile_ctr); 2318dabe9c4SThomas Richter if (n != 1) { 2328dabe9c4SThomas Richter pr_err("Failed to write counter set data\n"); 2338dabe9c4SThomas Richter rc = 1; 2348dabe9c4SThomas Richter } 2358dabe9c4SThomas Richter } 2368dabe9c4SThomas Richter return rc; 2378dabe9c4SThomas Richter } 2388dabe9c4SThomas Richter 239180ca71cSThomas Richter /* Display s390 CPU measurement facility basic-sampling data entry 240180ca71cSThomas Richter * Data written on s390 in big endian byte order and contains bit 241180ca71cSThomas Richter * fields across byte boundaries. 242180ca71cSThomas Richter */ 2432b1444f2SThomas Richter static bool s390_cpumsf_basic_show(const char *color, size_t pos, 244180ca71cSThomas Richter struct hws_basic_entry *basicp) 2452b1444f2SThomas Richter { 246180ca71cSThomas Richter struct hws_basic_entry *basic = basicp; 247180ca71cSThomas Richter #if __BYTE_ORDER == __LITTLE_ENDIAN 248180ca71cSThomas Richter struct hws_basic_entry local; 249180ca71cSThomas Richter unsigned long long word = be64toh(*(unsigned long long *)basicp); 250180ca71cSThomas Richter 251180ca71cSThomas Richter memset(&local, 0, sizeof(local)); 252180ca71cSThomas Richter local.def = be16toh(basicp->def); 253180ca71cSThomas Richter local.prim_asn = word & 0xffff; 254180ca71cSThomas Richter local.CL = word >> 30 & 0x3; 255180ca71cSThomas Richter local.I = word >> 32 & 0x1; 256180ca71cSThomas Richter local.AS = word >> 33 & 0x3; 257180ca71cSThomas Richter local.P = word >> 35 & 0x1; 258180ca71cSThomas Richter local.W = word >> 36 & 0x1; 259180ca71cSThomas Richter local.T = word >> 37 & 0x1; 260180ca71cSThomas Richter local.U = word >> 40 & 0xf; 261180ca71cSThomas Richter local.ia = be64toh(basicp->ia); 262180ca71cSThomas Richter local.gpp = be64toh(basicp->gpp); 263180ca71cSThomas Richter local.hpp = be64toh(basicp->hpp); 264180ca71cSThomas Richter basic = &local; 265180ca71cSThomas Richter #endif 2662b1444f2SThomas Richter if (basic->def != 1) { 2672b1444f2SThomas Richter pr_err("Invalid AUX trace basic entry [%#08zx]\n", pos); 2682b1444f2SThomas Richter return false; 2692b1444f2SThomas Richter } 2702b1444f2SThomas Richter color_fprintf(stdout, color, " [%#08zx] Basic Def:%04x Inst:%#04x" 2712b1444f2SThomas Richter " %c%c%c%c AS:%d ASN:%#04x IA:%#018llx\n" 2722b1444f2SThomas Richter "\t\tCL:%d HPP:%#018llx GPP:%#018llx\n", 2732b1444f2SThomas Richter pos, basic->def, basic->U, 2742b1444f2SThomas Richter basic->T ? 'T' : ' ', 2752b1444f2SThomas Richter basic->W ? 'W' : ' ', 2762b1444f2SThomas Richter basic->P ? 'P' : ' ', 2772b1444f2SThomas Richter basic->I ? 'I' : ' ', 2782b1444f2SThomas Richter basic->AS, basic->prim_asn, basic->ia, basic->CL, 2792b1444f2SThomas Richter basic->hpp, basic->gpp); 2802b1444f2SThomas Richter return true; 2812b1444f2SThomas Richter } 2822b1444f2SThomas Richter 283180ca71cSThomas Richter /* Display s390 CPU measurement facility diagnostic-sampling data entry. 284180ca71cSThomas Richter * Data written on s390 in big endian byte order and contains bit 285180ca71cSThomas Richter * fields across byte boundaries. 286180ca71cSThomas Richter */ 2872b1444f2SThomas Richter static bool s390_cpumsf_diag_show(const char *color, size_t pos, 288180ca71cSThomas Richter struct hws_diag_entry *diagp) 2892b1444f2SThomas Richter { 290180ca71cSThomas Richter struct hws_diag_entry *diag = diagp; 291180ca71cSThomas Richter #if __BYTE_ORDER == __LITTLE_ENDIAN 292180ca71cSThomas Richter struct hws_diag_entry local; 293180ca71cSThomas Richter unsigned long long word = be64toh(*(unsigned long long *)diagp); 294180ca71cSThomas Richter 295180ca71cSThomas Richter local.def = be16toh(diagp->def); 296180ca71cSThomas Richter local.I = word >> 32 & 0x1; 297180ca71cSThomas Richter diag = &local; 298180ca71cSThomas Richter #endif 2992b1444f2SThomas Richter if (diag->def < S390_CPUMSF_DIAG_DEF_FIRST) { 3002b1444f2SThomas Richter pr_err("Invalid AUX trace diagnostic entry [%#08zx]\n", pos); 3012b1444f2SThomas Richter return false; 3022b1444f2SThomas Richter } 3032b1444f2SThomas Richter color_fprintf(stdout, color, " [%#08zx] Diag Def:%04x %c\n", 3042b1444f2SThomas Richter pos, diag->def, diag->I ? 'I' : ' '); 3052b1444f2SThomas Richter return true; 3062b1444f2SThomas Richter } 3072b1444f2SThomas Richter 3082b1444f2SThomas Richter /* Return TOD timestamp contained in an trailer entry */ 309180ca71cSThomas Richter static unsigned long long trailer_timestamp(struct hws_trailer_entry *te, 310180ca71cSThomas Richter int idx) 3112b1444f2SThomas Richter { 3122b1444f2SThomas Richter /* te->t set: TOD in STCKE format, bytes 8-15 3132b1444f2SThomas Richter * to->t not set: TOD in STCK format, bytes 0-7 3142b1444f2SThomas Richter */ 3152b1444f2SThomas Richter unsigned long long ts; 3162b1444f2SThomas Richter 317180ca71cSThomas Richter memcpy(&ts, &te->timestamp[idx], sizeof(ts)); 318180ca71cSThomas Richter return be64toh(ts); 3192b1444f2SThomas Richter } 3202b1444f2SThomas Richter 3212b1444f2SThomas Richter /* Display s390 CPU measurement facility trailer entry */ 3222b1444f2SThomas Richter static bool s390_cpumsf_trailer_show(const char *color, size_t pos, 3232b1444f2SThomas Richter struct hws_trailer_entry *te) 3242b1444f2SThomas Richter { 325180ca71cSThomas Richter #if __BYTE_ORDER == __LITTLE_ENDIAN 326180ca71cSThomas Richter struct hws_trailer_entry local; 327180ca71cSThomas Richter const unsigned long long flags = be64toh(te->flags); 328180ca71cSThomas Richter 329180ca71cSThomas Richter memset(&local, 0, sizeof(local)); 330180ca71cSThomas Richter local.f = flags >> 63 & 0x1; 331180ca71cSThomas Richter local.a = flags >> 62 & 0x1; 332180ca71cSThomas Richter local.t = flags >> 61 & 0x1; 333180ca71cSThomas Richter local.bsdes = be16toh((flags >> 16 & 0xffff)); 334180ca71cSThomas Richter local.dsdes = be16toh((flags & 0xffff)); 335180ca71cSThomas Richter memcpy(&local.timestamp, te->timestamp, sizeof(te->timestamp)); 336180ca71cSThomas Richter local.overflow = be64toh(te->overflow); 337180ca71cSThomas Richter local.clock_base = be64toh(te->progusage[0]) >> 63 & 1; 338180ca71cSThomas Richter local.progusage2 = be64toh(te->progusage2); 339180ca71cSThomas Richter te = &local; 340180ca71cSThomas Richter #endif 3412b1444f2SThomas Richter if (te->bsdes != sizeof(struct hws_basic_entry)) { 3422b1444f2SThomas Richter pr_err("Invalid AUX trace trailer entry [%#08zx]\n", pos); 3432b1444f2SThomas Richter return false; 3442b1444f2SThomas Richter } 3452b1444f2SThomas Richter color_fprintf(stdout, color, " [%#08zx] Trailer %c%c%c bsdes:%d" 3462b1444f2SThomas Richter " dsdes:%d Overflow:%lld Time:%#llx\n" 347180ca71cSThomas Richter "\t\tC:%d TOD:%#lx\n", 3482b1444f2SThomas Richter pos, 3492b1444f2SThomas Richter te->f ? 'F' : ' ', 3502b1444f2SThomas Richter te->a ? 'A' : ' ', 3512b1444f2SThomas Richter te->t ? 'T' : ' ', 3522b1444f2SThomas Richter te->bsdes, te->dsdes, te->overflow, 353180ca71cSThomas Richter trailer_timestamp(te, te->clock_base), 354180ca71cSThomas Richter te->clock_base, te->progusage2); 3552b1444f2SThomas Richter return true; 3562b1444f2SThomas Richter } 3572b1444f2SThomas Richter 3582b1444f2SThomas Richter /* Test a sample data block. It must be 4KB or a multiple thereof in size and 3592b1444f2SThomas Richter * 4KB page aligned. Each sample data page has a trailer entry at the 3602b1444f2SThomas Richter * end which contains the sample entry data sizes. 3612b1444f2SThomas Richter * 3622b1444f2SThomas Richter * Return true if the sample data block passes the checks and set the 3632b1444f2SThomas Richter * basic set entry size and diagnostic set entry size. 3642b1444f2SThomas Richter * 3652b1444f2SThomas Richter * Return false on failure. 3662b1444f2SThomas Richter * 3672b1444f2SThomas Richter * Note: Old hardware does not set the basic or diagnostic entry sizes 3682b1444f2SThomas Richter * in the trailer entry. Use the type number instead. 3692b1444f2SThomas Richter */ 3702b1444f2SThomas Richter static bool s390_cpumsf_validate(int machine_type, 3712b1444f2SThomas Richter unsigned char *buf, size_t len, 3722b1444f2SThomas Richter unsigned short *bsdes, 3732b1444f2SThomas Richter unsigned short *dsdes) 3742b1444f2SThomas Richter { 3752b1444f2SThomas Richter struct hws_basic_entry *basic = (struct hws_basic_entry *)buf; 3762b1444f2SThomas Richter struct hws_trailer_entry *te; 3772b1444f2SThomas Richter 3782b1444f2SThomas Richter *dsdes = *bsdes = 0; 3792b1444f2SThomas Richter if (len & (S390_CPUMSF_PAGESZ - 1)) /* Illegal size */ 3802b1444f2SThomas Richter return false; 381180ca71cSThomas Richter if (be16toh(basic->def) != 1) /* No basic set entry, must be first */ 3822b1444f2SThomas Richter return false; 3832b1444f2SThomas Richter /* Check for trailer entry at end of SDB */ 3842b1444f2SThomas Richter te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ 3852b1444f2SThomas Richter - sizeof(*te)); 386180ca71cSThomas Richter *bsdes = be16toh(te->bsdes); 387180ca71cSThomas Richter *dsdes = be16toh(te->dsdes); 3882b1444f2SThomas Richter if (!te->bsdes && !te->dsdes) { 3892b1444f2SThomas Richter /* Very old hardware, use CPUID */ 3902b1444f2SThomas Richter switch (machine_type) { 3912b1444f2SThomas Richter case 2097: 3922b1444f2SThomas Richter case 2098: 3932b1444f2SThomas Richter *dsdes = 64; 3942b1444f2SThomas Richter *bsdes = 32; 3952b1444f2SThomas Richter break; 3962b1444f2SThomas Richter case 2817: 3972b1444f2SThomas Richter case 2818: 3982b1444f2SThomas Richter *dsdes = 74; 3992b1444f2SThomas Richter *bsdes = 32; 4002b1444f2SThomas Richter break; 4012b1444f2SThomas Richter case 2827: 4022b1444f2SThomas Richter case 2828: 4032b1444f2SThomas Richter *dsdes = 85; 4042b1444f2SThomas Richter *bsdes = 32; 4052b1444f2SThomas Richter break; 4062187d87eSThomas Richter case 2964: 4072187d87eSThomas Richter case 2965: 4082187d87eSThomas Richter *dsdes = 112; 4092187d87eSThomas Richter *bsdes = 32; 4102187d87eSThomas Richter break; 4112b1444f2SThomas Richter default: 4122b1444f2SThomas Richter /* Illegal trailer entry */ 4132b1444f2SThomas Richter return false; 4142b1444f2SThomas Richter } 4152b1444f2SThomas Richter } 4162b1444f2SThomas Richter return true; 4172b1444f2SThomas Richter } 4182b1444f2SThomas Richter 4192b1444f2SThomas Richter /* Return true if there is room for another entry */ 4202b1444f2SThomas Richter static bool s390_cpumsf_reached_trailer(size_t entry_sz, size_t pos) 4212b1444f2SThomas Richter { 4222b1444f2SThomas Richter size_t payload = S390_CPUMSF_PAGESZ - sizeof(struct hws_trailer_entry); 4232b1444f2SThomas Richter 4242b1444f2SThomas Richter if (payload - (pos & (S390_CPUMSF_PAGESZ - 1)) < entry_sz) 4252b1444f2SThomas Richter return false; 4262b1444f2SThomas Richter return true; 4272b1444f2SThomas Richter } 4282b1444f2SThomas Richter 4292b1444f2SThomas Richter /* Dump an auxiliary buffer. These buffers are multiple of 4302b1444f2SThomas Richter * 4KB SDB pages. 4312b1444f2SThomas Richter */ 4322b1444f2SThomas Richter static void s390_cpumsf_dump(struct s390_cpumsf *sf, 4332b1444f2SThomas Richter unsigned char *buf, size_t len) 4342b1444f2SThomas Richter { 4352b1444f2SThomas Richter const char *color = PERF_COLOR_BLUE; 4362b1444f2SThomas Richter struct hws_basic_entry *basic; 4372b1444f2SThomas Richter struct hws_diag_entry *diag; 4382b1444f2SThomas Richter unsigned short bsdes, dsdes; 43933d9e183SThomas Richter size_t pos = 0; 4402b1444f2SThomas Richter 4412b1444f2SThomas Richter color_fprintf(stdout, color, 4422b1444f2SThomas Richter ". ... s390 AUX data: size %zu bytes\n", 4432b1444f2SThomas Richter len); 4442b1444f2SThomas Richter 4452b1444f2SThomas Richter if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes, 4462b1444f2SThomas Richter &dsdes)) { 4472b1444f2SThomas Richter pr_err("Invalid AUX trace data block size:%zu" 4482b1444f2SThomas Richter " (type:%d bsdes:%hd dsdes:%hd)\n", 4492b1444f2SThomas Richter len, sf->machine_type, bsdes, dsdes); 4502b1444f2SThomas Richter return; 4512b1444f2SThomas Richter } 4522b1444f2SThomas Richter 4532b1444f2SThomas Richter /* s390 kernel always returns 4KB blocks fully occupied, 4542b1444f2SThomas Richter * no partially filled SDBs. 4552b1444f2SThomas Richter */ 4562b1444f2SThomas Richter while (pos < len) { 4572b1444f2SThomas Richter /* Handle Basic entry */ 4582b1444f2SThomas Richter basic = (struct hws_basic_entry *)(buf + pos); 4592b1444f2SThomas Richter if (s390_cpumsf_basic_show(color, pos, basic)) 4602b1444f2SThomas Richter pos += bsdes; 4612b1444f2SThomas Richter else 4622b1444f2SThomas Richter return; 4632b1444f2SThomas Richter 4642b1444f2SThomas Richter /* Handle Diagnostic entry */ 4652b1444f2SThomas Richter diag = (struct hws_diag_entry *)(buf + pos); 4662b1444f2SThomas Richter if (s390_cpumsf_diag_show(color, pos, diag)) 4672b1444f2SThomas Richter pos += dsdes; 4682b1444f2SThomas Richter else 4692b1444f2SThomas Richter return; 4702b1444f2SThomas Richter 4712b1444f2SThomas Richter /* Check for trailer entry */ 4722b1444f2SThomas Richter if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) { 4732b1444f2SThomas Richter /* Show trailer entry */ 4742b1444f2SThomas Richter struct hws_trailer_entry te; 4752b1444f2SThomas Richter 4762b1444f2SThomas Richter pos = (pos + S390_CPUMSF_PAGESZ) 4772b1444f2SThomas Richter & ~(S390_CPUMSF_PAGESZ - 1); 4782b1444f2SThomas Richter pos -= sizeof(te); 4792b1444f2SThomas Richter memcpy(&te, buf + pos, sizeof(te)); 4802b1444f2SThomas Richter /* Set descriptor sizes in case of old hardware 4812b1444f2SThomas Richter * where these values are not set. 4822b1444f2SThomas Richter */ 4832b1444f2SThomas Richter te.bsdes = bsdes; 4842b1444f2SThomas Richter te.dsdes = dsdes; 4852b1444f2SThomas Richter if (s390_cpumsf_trailer_show(color, pos, &te)) 4862b1444f2SThomas Richter pos += sizeof(te); 4872b1444f2SThomas Richter else 4882b1444f2SThomas Richter return; 4892b1444f2SThomas Richter } 4902b1444f2SThomas Richter } 4912b1444f2SThomas Richter } 4922b1444f2SThomas Richter 4932b1444f2SThomas Richter static void s390_cpumsf_dump_event(struct s390_cpumsf *sf, unsigned char *buf, 4942b1444f2SThomas Richter size_t len) 4952b1444f2SThomas Richter { 4962b1444f2SThomas Richter printf(".\n"); 4972b1444f2SThomas Richter s390_cpumsf_dump(sf, buf, len); 4982b1444f2SThomas Richter } 4992b1444f2SThomas Richter 50033d9e183SThomas Richter #define S390_LPP_PID_MASK 0xffffffff 50133d9e183SThomas Richter 50233d9e183SThomas Richter static bool s390_cpumsf_make_event(size_t pos, 50333d9e183SThomas Richter struct hws_basic_entry *basic, 50433d9e183SThomas Richter struct s390_cpumsf_queue *sfq) 505b96e6615SThomas Richter { 50633d9e183SThomas Richter struct perf_sample sample = { 50733d9e183SThomas Richter .ip = basic->ia, 50833d9e183SThomas Richter .pid = basic->hpp & S390_LPP_PID_MASK, 50933d9e183SThomas Richter .tid = basic->hpp & S390_LPP_PID_MASK, 51033d9e183SThomas Richter .cpumode = PERF_RECORD_MISC_CPUMODE_UNKNOWN, 51133d9e183SThomas Richter .cpu = sfq->cpu, 51233d9e183SThomas Richter .period = 1 51333d9e183SThomas Richter }; 51433d9e183SThomas Richter union perf_event event; 51533d9e183SThomas Richter 51633d9e183SThomas Richter memset(&event, 0, sizeof(event)); 51733d9e183SThomas Richter if (basic->CL == 1) /* Native LPAR mode */ 51833d9e183SThomas Richter sample.cpumode = basic->P ? PERF_RECORD_MISC_USER 51933d9e183SThomas Richter : PERF_RECORD_MISC_KERNEL; 52033d9e183SThomas Richter else if (basic->CL == 2) /* Guest kernel/user space */ 52133d9e183SThomas Richter sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER 52233d9e183SThomas Richter : PERF_RECORD_MISC_GUEST_KERNEL; 52333d9e183SThomas Richter else if (basic->gpp || basic->prim_asn != 0xffff) 52433d9e183SThomas Richter /* Use heuristics on old hardware */ 52533d9e183SThomas Richter sample.cpumode = basic->P ? PERF_RECORD_MISC_GUEST_USER 52633d9e183SThomas Richter : PERF_RECORD_MISC_GUEST_KERNEL; 52733d9e183SThomas Richter else 52833d9e183SThomas Richter sample.cpumode = basic->P ? PERF_RECORD_MISC_USER 52933d9e183SThomas Richter : PERF_RECORD_MISC_KERNEL; 53033d9e183SThomas Richter 53133d9e183SThomas Richter event.sample.header.type = PERF_RECORD_SAMPLE; 53233d9e183SThomas Richter event.sample.header.misc = sample.cpumode; 53333d9e183SThomas Richter event.sample.header.size = sizeof(struct perf_event_header); 53433d9e183SThomas Richter 53533d9e183SThomas Richter pr_debug4("%s pos:%#zx ip:%#" PRIx64 " P:%d CL:%d pid:%d.%d cpumode:%d cpu:%d\n", 53633d9e183SThomas Richter __func__, pos, sample.ip, basic->P, basic->CL, sample.pid, 53733d9e183SThomas Richter sample.tid, sample.cpumode, sample.cpu); 53833d9e183SThomas Richter if (perf_session__deliver_synth_event(sfq->sf->session, &event, 53933d9e183SThomas Richter &sample)) { 54033d9e183SThomas Richter pr_err("s390 Auxiliary Trace: failed to deliver event\n"); 54133d9e183SThomas Richter return false; 54233d9e183SThomas Richter } 54333d9e183SThomas Richter return true; 54433d9e183SThomas Richter } 54533d9e183SThomas Richter 54633d9e183SThomas Richter static unsigned long long get_trailer_time(const unsigned char *buf) 54733d9e183SThomas Richter { 54833d9e183SThomas Richter struct hws_trailer_entry *te; 549180ca71cSThomas Richter unsigned long long aux_time, progusage2; 550180ca71cSThomas Richter bool clock_base; 55133d9e183SThomas Richter 55233d9e183SThomas Richter te = (struct hws_trailer_entry *)(buf + S390_CPUMSF_PAGESZ 55333d9e183SThomas Richter - sizeof(*te)); 55433d9e183SThomas Richter 555180ca71cSThomas Richter #if __BYTE_ORDER == __LITTLE_ENDIAN 556180ca71cSThomas Richter clock_base = be64toh(te->progusage[0]) >> 63 & 0x1; 557180ca71cSThomas Richter progusage2 = be64toh(te->progusage[1]); 558180ca71cSThomas Richter #else 559180ca71cSThomas Richter clock_base = te->clock_base; 560180ca71cSThomas Richter progusage2 = te->progusage2; 561180ca71cSThomas Richter #endif 562180ca71cSThomas Richter if (!clock_base) /* TOD_CLOCK_BASE value missing */ 56333d9e183SThomas Richter return 0; 56433d9e183SThomas Richter 56533d9e183SThomas Richter /* Correct calculation to convert time stamp in trailer entry to 56633d9e183SThomas Richter * nano seconds (taken from arch/s390 function tod_to_ns()). 56733d9e183SThomas Richter * TOD_CLOCK_BASE is stored in trailer entry member progusage2. 56833d9e183SThomas Richter */ 569180ca71cSThomas Richter aux_time = trailer_timestamp(te, clock_base) - progusage2; 57033d9e183SThomas Richter aux_time = (aux_time >> 9) * 125 + (((aux_time & 0x1ff) * 125) >> 9); 57133d9e183SThomas Richter return aux_time; 57233d9e183SThomas Richter } 57333d9e183SThomas Richter 57433d9e183SThomas Richter /* Process the data samples of a single queue. The first parameter is a 57533d9e183SThomas Richter * pointer to the queue, the second parameter is the time stamp. This 57633d9e183SThomas Richter * is the time stamp: 57733d9e183SThomas Richter * - of the event that triggered this processing. 57833d9e183SThomas Richter * - or the time stamp when the last proccesing of this queue stopped. 57933d9e183SThomas Richter * In this case it stopped at a 4KB page boundary and record the 58033d9e183SThomas Richter * position on where to continue processing on the next invocation 58133d9e183SThomas Richter * (see buffer->use_data and buffer->use_size). 58233d9e183SThomas Richter * 58333d9e183SThomas Richter * When this function returns the second parameter is updated to 58433d9e183SThomas Richter * reflect the time stamp of the last processed auxiliary data entry 58533d9e183SThomas Richter * (taken from the trailer entry of that page). The caller uses this 58633d9e183SThomas Richter * returned time stamp to record the last processed entry in this 58733d9e183SThomas Richter * queue. 58833d9e183SThomas Richter * 58933d9e183SThomas Richter * The function returns: 59033d9e183SThomas Richter * 0: Processing successful. The second parameter returns the 59133d9e183SThomas Richter * time stamp from the trailer entry until which position 59233d9e183SThomas Richter * processing took place. Subsequent calls resume from this 59333d9e183SThomas Richter * position. 59433d9e183SThomas Richter * <0: An error occurred during processing. The second parameter 59533d9e183SThomas Richter * returns the maximum time stamp. 59633d9e183SThomas Richter * >0: Done on this queue. The second parameter returns the 59733d9e183SThomas Richter * maximum time stamp. 59833d9e183SThomas Richter */ 59933d9e183SThomas Richter static int s390_cpumsf_samples(struct s390_cpumsf_queue *sfq, u64 *ts) 60033d9e183SThomas Richter { 60133d9e183SThomas Richter struct s390_cpumsf *sf = sfq->sf; 60233d9e183SThomas Richter unsigned char *buf = sfq->buffer->use_data; 60333d9e183SThomas Richter size_t len = sfq->buffer->use_size; 60433d9e183SThomas Richter struct hws_basic_entry *basic; 60533d9e183SThomas Richter unsigned short bsdes, dsdes; 60633d9e183SThomas Richter size_t pos = 0; 60733d9e183SThomas Richter int err = 1; 60833d9e183SThomas Richter u64 aux_ts; 60933d9e183SThomas Richter 61033d9e183SThomas Richter if (!s390_cpumsf_validate(sf->machine_type, buf, len, &bsdes, 61133d9e183SThomas Richter &dsdes)) { 61233d9e183SThomas Richter *ts = ~0ULL; 61333d9e183SThomas Richter return -1; 61433d9e183SThomas Richter } 61533d9e183SThomas Richter 61633d9e183SThomas Richter /* Get trailer entry time stamp and check if entries in 61733d9e183SThomas Richter * this auxiliary page are ready for processing. If the 61833d9e183SThomas Richter * time stamp of the first entry is too high, whole buffer 61933d9e183SThomas Richter * can be skipped. In this case return time stamp. 62033d9e183SThomas Richter */ 62133d9e183SThomas Richter aux_ts = get_trailer_time(buf); 62233d9e183SThomas Richter if (!aux_ts) { 62333d9e183SThomas Richter pr_err("[%#08" PRIx64 "] Invalid AUX trailer entry TOD clock base\n", 624866053bbSArnaldo Carvalho de Melo (s64)sfq->buffer->data_offset); 62533d9e183SThomas Richter aux_ts = ~0ULL; 62633d9e183SThomas Richter goto out; 62733d9e183SThomas Richter } 62833d9e183SThomas Richter if (aux_ts > *ts) { 62933d9e183SThomas Richter *ts = aux_ts; 630b96e6615SThomas Richter return 0; 631b96e6615SThomas Richter } 632b96e6615SThomas Richter 63333d9e183SThomas Richter while (pos < len) { 63433d9e183SThomas Richter /* Handle Basic entry */ 63533d9e183SThomas Richter basic = (struct hws_basic_entry *)(buf + pos); 63633d9e183SThomas Richter if (s390_cpumsf_make_event(pos, basic, sfq)) 63733d9e183SThomas Richter pos += bsdes; 63833d9e183SThomas Richter else { 63933d9e183SThomas Richter err = -EBADF; 64033d9e183SThomas Richter goto out; 64133d9e183SThomas Richter } 64233d9e183SThomas Richter 64333d9e183SThomas Richter pos += dsdes; /* Skip diagnositic entry */ 64433d9e183SThomas Richter 64533d9e183SThomas Richter /* Check for trailer entry */ 64633d9e183SThomas Richter if (!s390_cpumsf_reached_trailer(bsdes + dsdes, pos)) { 64733d9e183SThomas Richter pos = (pos + S390_CPUMSF_PAGESZ) 64833d9e183SThomas Richter & ~(S390_CPUMSF_PAGESZ - 1); 64933d9e183SThomas Richter /* Check existence of next page */ 65033d9e183SThomas Richter if (pos >= len) 65133d9e183SThomas Richter break; 65233d9e183SThomas Richter aux_ts = get_trailer_time(buf + pos); 65333d9e183SThomas Richter if (!aux_ts) { 65433d9e183SThomas Richter aux_ts = ~0ULL; 65533d9e183SThomas Richter goto out; 65633d9e183SThomas Richter } 65733d9e183SThomas Richter if (aux_ts > *ts) { 65833d9e183SThomas Richter *ts = aux_ts; 65933d9e183SThomas Richter sfq->buffer->use_data += pos; 66033d9e183SThomas Richter sfq->buffer->use_size -= pos; 66133d9e183SThomas Richter return 0; 66233d9e183SThomas Richter } 66333d9e183SThomas Richter } 66433d9e183SThomas Richter } 66533d9e183SThomas Richter out: 66633d9e183SThomas Richter *ts = aux_ts; 66733d9e183SThomas Richter sfq->buffer->use_size = 0; 66833d9e183SThomas Richter sfq->buffer->use_data = NULL; 66933d9e183SThomas Richter return err; /* Buffer completely scanned or error */ 67033d9e183SThomas Richter } 67133d9e183SThomas Richter 67233d9e183SThomas Richter /* Run the s390 auxiliary trace decoder. 67333d9e183SThomas Richter * Select the queue buffer to operate on, the caller already selected 67433d9e183SThomas Richter * the proper queue, depending on second parameter 'ts'. 67533d9e183SThomas Richter * This is the time stamp until which the auxiliary entries should 67633d9e183SThomas Richter * be processed. This value is updated by called functions and 67733d9e183SThomas Richter * returned to the caller. 67833d9e183SThomas Richter * 67933d9e183SThomas Richter * Resume processing in the current buffer. If there is no buffer 68033d9e183SThomas Richter * get a new buffer from the queue and setup start position for 68133d9e183SThomas Richter * processing. 68233d9e183SThomas Richter * When a buffer is completely processed remove it from the queue 68333d9e183SThomas Richter * before returning. 68433d9e183SThomas Richter * 68533d9e183SThomas Richter * This function returns 68633d9e183SThomas Richter * 1: When the queue is empty. Second parameter will be set to 68733d9e183SThomas Richter * maximum time stamp. 68833d9e183SThomas Richter * 0: Normal processing done. 68933d9e183SThomas Richter * <0: Error during queue buffer setup. This causes the caller 69033d9e183SThomas Richter * to stop processing completely. 69133d9e183SThomas Richter */ 69233d9e183SThomas Richter static int s390_cpumsf_run_decoder(struct s390_cpumsf_queue *sfq, 69333d9e183SThomas Richter u64 *ts) 69433d9e183SThomas Richter { 69533d9e183SThomas Richter 69633d9e183SThomas Richter struct auxtrace_buffer *buffer; 69733d9e183SThomas Richter struct auxtrace_queue *queue; 69833d9e183SThomas Richter int err; 69933d9e183SThomas Richter 70033d9e183SThomas Richter queue = &sfq->sf->queues.queue_array[sfq->queue_nr]; 70133d9e183SThomas Richter 70233d9e183SThomas Richter /* Get buffer and last position in buffer to resume 70333d9e183SThomas Richter * decoding the auxiliary entries. One buffer might be large 70433d9e183SThomas Richter * and decoding might stop in between. This depends on the time 70533d9e183SThomas Richter * stamp of the trailer entry in each page of the auxiliary 70633d9e183SThomas Richter * data and the time stamp of the event triggering the decoding. 70733d9e183SThomas Richter */ 70833d9e183SThomas Richter if (sfq->buffer == NULL) { 70933d9e183SThomas Richter sfq->buffer = buffer = auxtrace_buffer__next(queue, 71033d9e183SThomas Richter sfq->buffer); 71133d9e183SThomas Richter if (!buffer) { 71233d9e183SThomas Richter *ts = ~0ULL; 71333d9e183SThomas Richter return 1; /* Processing done on this queue */ 71433d9e183SThomas Richter } 71533d9e183SThomas Richter /* Start with a new buffer on this queue */ 71633d9e183SThomas Richter if (buffer->data) { 71733d9e183SThomas Richter buffer->use_size = buffer->size; 71833d9e183SThomas Richter buffer->use_data = buffer->data; 71933d9e183SThomas Richter } 720766e0618SThomas Richter if (sfq->logfile) { /* Write into log file */ 721766e0618SThomas Richter size_t rc = fwrite(buffer->data, buffer->size, 1, 722766e0618SThomas Richter sfq->logfile); 723766e0618SThomas Richter if (rc != 1) 724766e0618SThomas Richter pr_err("Failed to write auxiliary data\n"); 725766e0618SThomas Richter } 72633d9e183SThomas Richter } else 72733d9e183SThomas Richter buffer = sfq->buffer; 72833d9e183SThomas Richter 72933d9e183SThomas Richter if (!buffer->data) { 73033d9e183SThomas Richter int fd = perf_data__fd(sfq->sf->session->data); 73133d9e183SThomas Richter 73233d9e183SThomas Richter buffer->data = auxtrace_buffer__get_data(buffer, fd); 73333d9e183SThomas Richter if (!buffer->data) 73433d9e183SThomas Richter return -ENOMEM; 73533d9e183SThomas Richter buffer->use_size = buffer->size; 73633d9e183SThomas Richter buffer->use_data = buffer->data; 737766e0618SThomas Richter 738766e0618SThomas Richter if (sfq->logfile) { /* Write into log file */ 739766e0618SThomas Richter size_t rc = fwrite(buffer->data, buffer->size, 1, 740766e0618SThomas Richter sfq->logfile); 741766e0618SThomas Richter if (rc != 1) 742766e0618SThomas Richter pr_err("Failed to write auxiliary data\n"); 743766e0618SThomas Richter } 74433d9e183SThomas Richter } 74533d9e183SThomas Richter pr_debug4("%s queue_nr:%d buffer:%" PRId64 " offset:%#" PRIx64 " size:%#zx rest:%#zx\n", 74633d9e183SThomas Richter __func__, sfq->queue_nr, buffer->buffer_nr, buffer->offset, 74733d9e183SThomas Richter buffer->size, buffer->use_size); 74833d9e183SThomas Richter err = s390_cpumsf_samples(sfq, ts); 74933d9e183SThomas Richter 75033d9e183SThomas Richter /* If non-zero, there is either an error (err < 0) or the buffer is 75133d9e183SThomas Richter * completely done (err > 0). The error is unrecoverable, usually 75233d9e183SThomas Richter * some descriptors could not be read successfully, so continue with 75333d9e183SThomas Richter * the next buffer. 75433d9e183SThomas Richter * In both cases the parameter 'ts' has been updated. 75533d9e183SThomas Richter */ 75633d9e183SThomas Richter if (err) { 75733d9e183SThomas Richter sfq->buffer = NULL; 758e56fbc9dSArnaldo Carvalho de Melo list_del_init(&buffer->list); 75933d9e183SThomas Richter auxtrace_buffer__free(buffer); 76033d9e183SThomas Richter if (err > 0) /* Buffer done, no error */ 76133d9e183SThomas Richter err = 0; 76233d9e183SThomas Richter } 76333d9e183SThomas Richter return err; 76433d9e183SThomas Richter } 76533d9e183SThomas Richter 76633d9e183SThomas Richter static struct s390_cpumsf_queue * 76733d9e183SThomas Richter s390_cpumsf_alloc_queue(struct s390_cpumsf *sf, unsigned int queue_nr) 76833d9e183SThomas Richter { 76933d9e183SThomas Richter struct s390_cpumsf_queue *sfq; 77033d9e183SThomas Richter 77133d9e183SThomas Richter sfq = zalloc(sizeof(struct s390_cpumsf_queue)); 77233d9e183SThomas Richter if (sfq == NULL) 77333d9e183SThomas Richter return NULL; 77433d9e183SThomas Richter 77533d9e183SThomas Richter sfq->sf = sf; 77633d9e183SThomas Richter sfq->queue_nr = queue_nr; 77733d9e183SThomas Richter sfq->cpu = -1; 778766e0618SThomas Richter if (sf->use_logfile) { 779766e0618SThomas Richter char *name; 780766e0618SThomas Richter int rc; 781766e0618SThomas Richter 782766e0618SThomas Richter rc = (sf->logdir) 783766e0618SThomas Richter ? asprintf(&name, "%s/aux.smp.%02x", 784766e0618SThomas Richter sf->logdir, queue_nr) 785766e0618SThomas Richter : asprintf(&name, "aux.smp.%02x", queue_nr); 786766e0618SThomas Richter if (rc > 0) 787766e0618SThomas Richter sfq->logfile = fopen(name, "w"); 788766e0618SThomas Richter if (sfq->logfile == NULL) { 789766e0618SThomas Richter pr_err("Failed to open auxiliary log file %s," 790766e0618SThomas Richter "continue...\n", name); 791766e0618SThomas Richter sf->use_logfile = false; 792766e0618SThomas Richter } 793766e0618SThomas Richter free(name); 794766e0618SThomas Richter } 79533d9e183SThomas Richter return sfq; 79633d9e183SThomas Richter } 79733d9e183SThomas Richter 79833d9e183SThomas Richter static int s390_cpumsf_setup_queue(struct s390_cpumsf *sf, 79933d9e183SThomas Richter struct auxtrace_queue *queue, 80033d9e183SThomas Richter unsigned int queue_nr, u64 ts) 80133d9e183SThomas Richter { 80233d9e183SThomas Richter struct s390_cpumsf_queue *sfq = queue->priv; 80333d9e183SThomas Richter 80433d9e183SThomas Richter if (list_empty(&queue->head)) 80533d9e183SThomas Richter return 0; 80633d9e183SThomas Richter 80733d9e183SThomas Richter if (sfq == NULL) { 80833d9e183SThomas Richter sfq = s390_cpumsf_alloc_queue(sf, queue_nr); 80933d9e183SThomas Richter if (!sfq) 81033d9e183SThomas Richter return -ENOMEM; 81133d9e183SThomas Richter queue->priv = sfq; 81233d9e183SThomas Richter 81333d9e183SThomas Richter if (queue->cpu != -1) 81433d9e183SThomas Richter sfq->cpu = queue->cpu; 81533d9e183SThomas Richter } 81633d9e183SThomas Richter return auxtrace_heap__add(&sf->heap, queue_nr, ts); 81733d9e183SThomas Richter } 81833d9e183SThomas Richter 81933d9e183SThomas Richter static int s390_cpumsf_setup_queues(struct s390_cpumsf *sf, u64 ts) 82033d9e183SThomas Richter { 82133d9e183SThomas Richter unsigned int i; 82233d9e183SThomas Richter int ret = 0; 82333d9e183SThomas Richter 82433d9e183SThomas Richter for (i = 0; i < sf->queues.nr_queues; i++) { 82533d9e183SThomas Richter ret = s390_cpumsf_setup_queue(sf, &sf->queues.queue_array[i], 82633d9e183SThomas Richter i, ts); 82733d9e183SThomas Richter if (ret) 82833d9e183SThomas Richter break; 82933d9e183SThomas Richter } 83033d9e183SThomas Richter return ret; 83133d9e183SThomas Richter } 83233d9e183SThomas Richter 83333d9e183SThomas Richter static int s390_cpumsf_update_queues(struct s390_cpumsf *sf, u64 ts) 83433d9e183SThomas Richter { 83533d9e183SThomas Richter if (!sf->queues.new_data) 83633d9e183SThomas Richter return 0; 83733d9e183SThomas Richter 83833d9e183SThomas Richter sf->queues.new_data = false; 83933d9e183SThomas Richter return s390_cpumsf_setup_queues(sf, ts); 84033d9e183SThomas Richter } 84133d9e183SThomas Richter 84233d9e183SThomas Richter static int s390_cpumsf_process_queues(struct s390_cpumsf *sf, u64 timestamp) 84333d9e183SThomas Richter { 84433d9e183SThomas Richter unsigned int queue_nr; 84533d9e183SThomas Richter u64 ts; 84633d9e183SThomas Richter int ret; 84733d9e183SThomas Richter 84833d9e183SThomas Richter while (1) { 84933d9e183SThomas Richter struct auxtrace_queue *queue; 85033d9e183SThomas Richter struct s390_cpumsf_queue *sfq; 85133d9e183SThomas Richter 85233d9e183SThomas Richter if (!sf->heap.heap_cnt) 85333d9e183SThomas Richter return 0; 85433d9e183SThomas Richter 85533d9e183SThomas Richter if (sf->heap.heap_array[0].ordinal >= timestamp) 85633d9e183SThomas Richter return 0; 85733d9e183SThomas Richter 85833d9e183SThomas Richter queue_nr = sf->heap.heap_array[0].queue_nr; 85933d9e183SThomas Richter queue = &sf->queues.queue_array[queue_nr]; 86033d9e183SThomas Richter sfq = queue->priv; 86133d9e183SThomas Richter 86233d9e183SThomas Richter auxtrace_heap__pop(&sf->heap); 86333d9e183SThomas Richter if (sf->heap.heap_cnt) { 86433d9e183SThomas Richter ts = sf->heap.heap_array[0].ordinal + 1; 86533d9e183SThomas Richter if (ts > timestamp) 86633d9e183SThomas Richter ts = timestamp; 86733d9e183SThomas Richter } else { 86833d9e183SThomas Richter ts = timestamp; 86933d9e183SThomas Richter } 87033d9e183SThomas Richter 87133d9e183SThomas Richter ret = s390_cpumsf_run_decoder(sfq, &ts); 87233d9e183SThomas Richter if (ret < 0) { 87333d9e183SThomas Richter auxtrace_heap__add(&sf->heap, queue_nr, ts); 87433d9e183SThomas Richter return ret; 87533d9e183SThomas Richter } 87633d9e183SThomas Richter if (!ret) { 87733d9e183SThomas Richter ret = auxtrace_heap__add(&sf->heap, queue_nr, ts); 87833d9e183SThomas Richter if (ret < 0) 87933d9e183SThomas Richter return ret; 88033d9e183SThomas Richter } 88133d9e183SThomas Richter } 88233d9e183SThomas Richter return 0; 88333d9e183SThomas Richter } 88433d9e183SThomas Richter 88533d9e183SThomas Richter static int s390_cpumsf_synth_error(struct s390_cpumsf *sf, int code, int cpu, 88616bd4321SAdrian Hunter pid_t pid, pid_t tid, u64 ip, u64 timestamp) 88733d9e183SThomas Richter { 88833d9e183SThomas Richter char msg[MAX_AUXTRACE_ERROR_MSG]; 88933d9e183SThomas Richter union perf_event event; 89033d9e183SThomas Richter int err; 89133d9e183SThomas Richter 89233d9e183SThomas Richter strncpy(msg, "Lost Auxiliary Trace Buffer", sizeof(msg) - 1); 89333d9e183SThomas Richter auxtrace_synth_error(&event.auxtrace_error, PERF_AUXTRACE_ERROR_ITRACE, 89416bd4321SAdrian Hunter code, cpu, pid, tid, ip, msg, timestamp); 89533d9e183SThomas Richter 89633d9e183SThomas Richter err = perf_session__deliver_synth_event(sf->session, &event, NULL); 89733d9e183SThomas Richter if (err) 89833d9e183SThomas Richter pr_err("s390 Auxiliary Trace: failed to deliver error event," 89933d9e183SThomas Richter "error %d\n", err); 90033d9e183SThomas Richter return err; 90133d9e183SThomas Richter } 90233d9e183SThomas Richter 90333d9e183SThomas Richter static int s390_cpumsf_lost(struct s390_cpumsf *sf, struct perf_sample *sample) 90433d9e183SThomas Richter { 90533d9e183SThomas Richter return s390_cpumsf_synth_error(sf, 1, sample->cpu, 90616bd4321SAdrian Hunter sample->pid, sample->tid, 0, 90716bd4321SAdrian Hunter sample->time); 90833d9e183SThomas Richter } 90933d9e183SThomas Richter 91033d9e183SThomas Richter static int 9118dabe9c4SThomas Richter s390_cpumsf_process_event(struct perf_session *session, 91233d9e183SThomas Richter union perf_event *event, 91333d9e183SThomas Richter struct perf_sample *sample, 91433d9e183SThomas Richter struct perf_tool *tool) 91533d9e183SThomas Richter { 91633d9e183SThomas Richter struct s390_cpumsf *sf = container_of(session->auxtrace, 91733d9e183SThomas Richter struct s390_cpumsf, 91833d9e183SThomas Richter auxtrace); 91933d9e183SThomas Richter u64 timestamp = sample->time; 92032dcd021SJiri Olsa struct evsel *ev_bc000; 9218dabe9c4SThomas Richter 92233d9e183SThomas Richter int err = 0; 92333d9e183SThomas Richter 92433d9e183SThomas Richter if (dump_trace) 92533d9e183SThomas Richter return 0; 92633d9e183SThomas Richter 92733d9e183SThomas Richter if (!tool->ordered_events) { 92833d9e183SThomas Richter pr_err("s390 Auxiliary Trace requires ordered events\n"); 92933d9e183SThomas Richter return -EINVAL; 93033d9e183SThomas Richter } 93133d9e183SThomas Richter 9328dabe9c4SThomas Richter if (event->header.type == PERF_RECORD_SAMPLE && 9338dabe9c4SThomas Richter sample->raw_size) { 9348dabe9c4SThomas Richter /* Handle event with raw data */ 935*3ccf8a7bSArnaldo Carvalho de Melo ev_bc000 = evlist__event2evsel(session->evlist, event); 9368dabe9c4SThomas Richter if (ev_bc000 && 9371fc632ceSJiri Olsa ev_bc000->core.attr.config == PERF_EVENT_CPUM_CF_DIAG) 9388dabe9c4SThomas Richter err = s390_cpumcf_dumpctr(sf, sample); 9398dabe9c4SThomas Richter return err; 9408dabe9c4SThomas Richter } 9418dabe9c4SThomas Richter 94233d9e183SThomas Richter if (event->header.type == PERF_RECORD_AUX && 94333d9e183SThomas Richter event->aux.flags & PERF_AUX_FLAG_TRUNCATED) 94433d9e183SThomas Richter return s390_cpumsf_lost(sf, sample); 94533d9e183SThomas Richter 94633d9e183SThomas Richter if (timestamp) { 94733d9e183SThomas Richter err = s390_cpumsf_update_queues(sf, timestamp); 94833d9e183SThomas Richter if (!err) 94933d9e183SThomas Richter err = s390_cpumsf_process_queues(sf, timestamp); 95033d9e183SThomas Richter } 95133d9e183SThomas Richter return err; 95233d9e183SThomas Richter } 95333d9e183SThomas Richter 95433d9e183SThomas Richter struct s390_cpumsf_synth { 95533d9e183SThomas Richter struct perf_tool cpumsf_tool; 95633d9e183SThomas Richter struct perf_session *session; 95733d9e183SThomas Richter }; 95833d9e183SThomas Richter 959b96e6615SThomas Richter static int 9602b1444f2SThomas Richter s390_cpumsf_process_auxtrace_event(struct perf_session *session, 961b96e6615SThomas Richter union perf_event *event __maybe_unused, 962b96e6615SThomas Richter struct perf_tool *tool __maybe_unused) 963b96e6615SThomas Richter { 9642b1444f2SThomas Richter struct s390_cpumsf *sf = container_of(session->auxtrace, 9652b1444f2SThomas Richter struct s390_cpumsf, 9662b1444f2SThomas Richter auxtrace); 9672b1444f2SThomas Richter 9682b1444f2SThomas Richter int fd = perf_data__fd(session->data); 9692b1444f2SThomas Richter struct auxtrace_buffer *buffer; 9702b1444f2SThomas Richter off_t data_offset; 9712b1444f2SThomas Richter int err; 9722b1444f2SThomas Richter 97333d9e183SThomas Richter if (sf->data_queued) 97433d9e183SThomas Richter return 0; 97533d9e183SThomas Richter 9762b1444f2SThomas Richter if (perf_data__is_pipe(session->data)) { 9772b1444f2SThomas Richter data_offset = 0; 9782b1444f2SThomas Richter } else { 9792b1444f2SThomas Richter data_offset = lseek(fd, 0, SEEK_CUR); 9802b1444f2SThomas Richter if (data_offset == -1) 9812b1444f2SThomas Richter return -errno; 9822b1444f2SThomas Richter } 9832b1444f2SThomas Richter 9842b1444f2SThomas Richter err = auxtrace_queues__add_event(&sf->queues, session, event, 9852b1444f2SThomas Richter data_offset, &buffer); 9862b1444f2SThomas Richter if (err) 9872b1444f2SThomas Richter return err; 9882b1444f2SThomas Richter 9892b1444f2SThomas Richter /* Dump here after copying piped trace out of the pipe */ 9902b1444f2SThomas Richter if (dump_trace) { 9912b1444f2SThomas Richter if (auxtrace_buffer__get_data(buffer, fd)) { 9922b1444f2SThomas Richter s390_cpumsf_dump_event(sf, buffer->data, 9932b1444f2SThomas Richter buffer->size); 9942b1444f2SThomas Richter auxtrace_buffer__put_data(buffer); 9952b1444f2SThomas Richter } 9962b1444f2SThomas Richter } 997b96e6615SThomas Richter return 0; 998b96e6615SThomas Richter } 999b96e6615SThomas Richter 100033d9e183SThomas Richter static void s390_cpumsf_free_events(struct perf_session *session __maybe_unused) 100133d9e183SThomas Richter { 100233d9e183SThomas Richter } 100333d9e183SThomas Richter 1004b96e6615SThomas Richter static int s390_cpumsf_flush(struct perf_session *session __maybe_unused, 1005b96e6615SThomas Richter struct perf_tool *tool __maybe_unused) 1006b96e6615SThomas Richter { 1007b96e6615SThomas Richter return 0; 1008b96e6615SThomas Richter } 1009b96e6615SThomas Richter 101033d9e183SThomas Richter static void s390_cpumsf_free_queues(struct perf_session *session) 1011b96e6615SThomas Richter { 1012b96e6615SThomas Richter struct s390_cpumsf *sf = container_of(session->auxtrace, 1013b96e6615SThomas Richter struct s390_cpumsf, 1014b96e6615SThomas Richter auxtrace); 1015b96e6615SThomas Richter struct auxtrace_queues *queues = &sf->queues; 1016b96e6615SThomas Richter unsigned int i; 1017b96e6615SThomas Richter 1018766e0618SThomas Richter for (i = 0; i < queues->nr_queues; i++) { 1019766e0618SThomas Richter struct s390_cpumsf_queue *sfq = (struct s390_cpumsf_queue *) 1020766e0618SThomas Richter queues->queue_array[i].priv; 1021766e0618SThomas Richter 10228dabe9c4SThomas Richter if (sfq != NULL) { 10238dabe9c4SThomas Richter if (sfq->logfile) { 1024766e0618SThomas Richter fclose(sfq->logfile); 1025766e0618SThomas Richter sfq->logfile = NULL; 1026766e0618SThomas Richter } 10278dabe9c4SThomas Richter if (sfq->logfile_ctr) { 10288dabe9c4SThomas Richter fclose(sfq->logfile_ctr); 10298dabe9c4SThomas Richter sfq->logfile_ctr = NULL; 10308dabe9c4SThomas Richter } 10318dabe9c4SThomas Richter } 1032b96e6615SThomas Richter zfree(&queues->queue_array[i].priv); 1033766e0618SThomas Richter } 1034b96e6615SThomas Richter auxtrace_queues__free(queues); 1035b96e6615SThomas Richter } 1036b96e6615SThomas Richter 1037b96e6615SThomas Richter static void s390_cpumsf_free(struct perf_session *session) 1038b96e6615SThomas Richter { 1039b96e6615SThomas Richter struct s390_cpumsf *sf = container_of(session->auxtrace, 1040b96e6615SThomas Richter struct s390_cpumsf, 1041b96e6615SThomas Richter auxtrace); 1042b96e6615SThomas Richter 1043b96e6615SThomas Richter auxtrace_heap__free(&sf->heap); 104433d9e183SThomas Richter s390_cpumsf_free_queues(session); 1045b96e6615SThomas Richter session->auxtrace = NULL; 1046d8f9da24SArnaldo Carvalho de Melo zfree(&sf->logdir); 1047b96e6615SThomas Richter free(sf); 1048b96e6615SThomas Richter } 1049b96e6615SThomas Richter 1050113fcb46SAdrian Hunter static bool 1051113fcb46SAdrian Hunter s390_cpumsf_evsel_is_auxtrace(struct perf_session *session __maybe_unused, 1052113fcb46SAdrian Hunter struct evsel *evsel) 1053113fcb46SAdrian Hunter { 1054113fcb46SAdrian Hunter return evsel->core.attr.type == PERF_TYPE_RAW && 1055113fcb46SAdrian Hunter evsel->core.attr.config == PERF_EVENT_CPUM_SF_DIAG; 1056113fcb46SAdrian Hunter } 1057113fcb46SAdrian Hunter 10582b1444f2SThomas Richter static int s390_cpumsf_get_type(const char *cpuid) 10592b1444f2SThomas Richter { 10602b1444f2SThomas Richter int ret, family = 0; 10612b1444f2SThomas Richter 10622b1444f2SThomas Richter ret = sscanf(cpuid, "%*[^,],%u", &family); 10632b1444f2SThomas Richter return (ret == 1) ? family : 0; 10642b1444f2SThomas Richter } 10652b1444f2SThomas Richter 106633d9e183SThomas Richter /* Check itrace options set on perf report command. 106733d9e183SThomas Richter * Return true, if none are set or all options specified can be 1068766e0618SThomas Richter * handled on s390 (currently only option 'd' for logging. 106933d9e183SThomas Richter * Return false otherwise. 107033d9e183SThomas Richter */ 107133d9e183SThomas Richter static bool check_auxtrace_itrace(struct itrace_synth_opts *itops) 107233d9e183SThomas Richter { 1073766e0618SThomas Richter bool ison = false; 1074766e0618SThomas Richter 107533d9e183SThomas Richter if (!itops || !itops->set) 107633d9e183SThomas Richter return true; 1077766e0618SThomas Richter ison = itops->inject || itops->instructions || itops->branches || 1078766e0618SThomas Richter itops->transactions || itops->ptwrites || 1079766e0618SThomas Richter itops->pwr_events || itops->errors || 1080766e0618SThomas Richter itops->dont_decode || itops->calls || itops->returns || 1081766e0618SThomas Richter itops->callchain || itops->thread_stack || 1082ec90e42cSAdrian Hunter itops->last_branch || itops->add_callchain || 1083ec90e42cSAdrian Hunter itops->add_last_branch; 1084766e0618SThomas Richter if (!ison) 1085766e0618SThomas Richter return true; 1086766e0618SThomas Richter pr_err("Unsupported --itrace options specified\n"); 108733d9e183SThomas Richter return false; 108833d9e183SThomas Richter } 108933d9e183SThomas Richter 1090766e0618SThomas Richter /* Check for AUXTRACE dump directory if it is needed. 1091766e0618SThomas Richter * On failure print an error message but continue. 1092766e0618SThomas Richter * Return 0 on wrong keyword in config file and 1 otherwise. 1093766e0618SThomas Richter */ 1094766e0618SThomas Richter static int s390_cpumsf__config(const char *var, const char *value, void *cb) 1095766e0618SThomas Richter { 1096766e0618SThomas Richter struct s390_cpumsf *sf = cb; 1097766e0618SThomas Richter struct stat stbuf; 1098766e0618SThomas Richter int rc; 1099766e0618SThomas Richter 1100766e0618SThomas Richter if (strcmp(var, "auxtrace.dumpdir")) 1101766e0618SThomas Richter return 0; 1102766e0618SThomas Richter sf->logdir = strdup(value); 1103766e0618SThomas Richter if (sf->logdir == NULL) { 1104766e0618SThomas Richter pr_err("Failed to find auxtrace log directory %s," 1105766e0618SThomas Richter " continue with current directory...\n", value); 1106766e0618SThomas Richter return 1; 1107766e0618SThomas Richter } 1108766e0618SThomas Richter rc = stat(sf->logdir, &stbuf); 1109766e0618SThomas Richter if (rc == -1 || !S_ISDIR(stbuf.st_mode)) { 1110766e0618SThomas Richter pr_err("Missing auxtrace log directory %s," 1111766e0618SThomas Richter " continue with current directory...\n", value); 1112d8f9da24SArnaldo Carvalho de Melo zfree(&sf->logdir); 1113766e0618SThomas Richter } 1114766e0618SThomas Richter return 1; 1115766e0618SThomas Richter } 1116766e0618SThomas Richter 1117b96e6615SThomas Richter int s390_cpumsf_process_auxtrace_info(union perf_event *event, 1118b96e6615SThomas Richter struct perf_session *session) 1119b96e6615SThomas Richter { 112072932371SJiri Olsa struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; 1121b96e6615SThomas Richter struct s390_cpumsf *sf; 1122b96e6615SThomas Richter int err; 1123b96e6615SThomas Richter 112472932371SJiri Olsa if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info)) 1125b96e6615SThomas Richter return -EINVAL; 1126b96e6615SThomas Richter 1127b96e6615SThomas Richter sf = zalloc(sizeof(struct s390_cpumsf)); 1128b96e6615SThomas Richter if (sf == NULL) 1129b96e6615SThomas Richter return -ENOMEM; 1130b96e6615SThomas Richter 113133d9e183SThomas Richter if (!check_auxtrace_itrace(session->itrace_synth_opts)) { 113233d9e183SThomas Richter err = -EINVAL; 113333d9e183SThomas Richter goto err_free; 113433d9e183SThomas Richter } 1135766e0618SThomas Richter sf->use_logfile = session->itrace_synth_opts->log; 1136766e0618SThomas Richter if (sf->use_logfile) 1137766e0618SThomas Richter perf_config(s390_cpumsf__config, sf); 113833d9e183SThomas Richter 1139b96e6615SThomas Richter err = auxtrace_queues__init(&sf->queues); 1140b96e6615SThomas Richter if (err) 1141b96e6615SThomas Richter goto err_free; 1142b96e6615SThomas Richter 1143b96e6615SThomas Richter sf->session = session; 1144b96e6615SThomas Richter sf->machine = &session->machines.host; /* No kvm support */ 1145b96e6615SThomas Richter sf->auxtrace_type = auxtrace_info->type; 1146b96e6615SThomas Richter sf->pmu_type = PERF_TYPE_RAW; 11472b1444f2SThomas Richter sf->machine_type = s390_cpumsf_get_type(session->evlist->env->cpuid); 1148b96e6615SThomas Richter 1149b96e6615SThomas Richter sf->auxtrace.process_event = s390_cpumsf_process_event; 1150b96e6615SThomas Richter sf->auxtrace.process_auxtrace_event = s390_cpumsf_process_auxtrace_event; 1151b96e6615SThomas Richter sf->auxtrace.flush_events = s390_cpumsf_flush; 1152b96e6615SThomas Richter sf->auxtrace.free_events = s390_cpumsf_free_events; 1153b96e6615SThomas Richter sf->auxtrace.free = s390_cpumsf_free; 1154113fcb46SAdrian Hunter sf->auxtrace.evsel_is_auxtrace = s390_cpumsf_evsel_is_auxtrace; 1155b96e6615SThomas Richter session->auxtrace = &sf->auxtrace; 1156b96e6615SThomas Richter 115733d9e183SThomas Richter if (dump_trace) 1158b96e6615SThomas Richter return 0; 1159b96e6615SThomas Richter 116033d9e183SThomas Richter err = auxtrace_queues__process_index(&sf->queues, session); 116133d9e183SThomas Richter if (err) 116233d9e183SThomas Richter goto err_free_queues; 116333d9e183SThomas Richter 116433d9e183SThomas Richter if (sf->queues.populated) 116533d9e183SThomas Richter sf->data_queued = true; 116633d9e183SThomas Richter 116733d9e183SThomas Richter return 0; 116833d9e183SThomas Richter 116933d9e183SThomas Richter err_free_queues: 117033d9e183SThomas Richter auxtrace_queues__free(&sf->queues); 117133d9e183SThomas Richter session->auxtrace = NULL; 1172b96e6615SThomas Richter err_free: 1173d8f9da24SArnaldo Carvalho de Melo zfree(&sf->logdir); 1174b96e6615SThomas Richter free(sf); 1175b96e6615SThomas Richter return err; 1176b96e6615SThomas Richter } 1177