1c4bbd4ecSAthira Rajeev // SPDX-License-Identifier: GPL-2.0 2c4bbd4ecSAthira Rajeev /* 3c4bbd4ecSAthira Rajeev * VPA DTL PMU support 4c4bbd4ecSAthira Rajeev */ 5c4bbd4ecSAthira Rajeev 671feffa9SAthira Rajeev #include <linux/string.h> 7c4bbd4ecSAthira Rajeev #include <inttypes.h> 8c4bbd4ecSAthira Rajeev #include "color.h" 9c4bbd4ecSAthira Rajeev #include "evlist.h" 10c4bbd4ecSAthira Rajeev #include "session.h" 11c4bbd4ecSAthira Rajeev #include "auxtrace.h" 12c4bbd4ecSAthira Rajeev #include "data.h" 13c4bbd4ecSAthira Rajeev #include "machine.h" 14c4bbd4ecSAthira Rajeev #include "debug.h" 15c4bbd4ecSAthira Rajeev #include "powerpc-vpadtl.h" 16cd1c3b73SAthira Rajeev #include "sample.h" 17cd1c3b73SAthira Rajeev #include "tool.h" 18c4bbd4ecSAthira Rajeev 19c4bbd4ecSAthira Rajeev /* 20c4bbd4ecSAthira Rajeev * Structure to save the auxtrace queue 21c4bbd4ecSAthira Rajeev */ 22c4bbd4ecSAthira Rajeev struct powerpc_vpadtl { 23c4bbd4ecSAthira Rajeev struct auxtrace auxtrace; 24c4bbd4ecSAthira Rajeev struct auxtrace_queues queues; 25c4bbd4ecSAthira Rajeev struct auxtrace_heap heap; 26c4bbd4ecSAthira Rajeev u32 auxtrace_type; 27c4bbd4ecSAthira Rajeev struct perf_session *session; 28c4bbd4ecSAthira Rajeev struct machine *machine; 29c4bbd4ecSAthira Rajeev u32 pmu_type; 3071feffa9SAthira Rajeev u64 sample_id; 31c4bbd4ecSAthira Rajeev }; 32c4bbd4ecSAthira Rajeev 33c4bbd4ecSAthira Rajeev struct boottb_freq { 34c4bbd4ecSAthira Rajeev u64 boot_tb; 35c4bbd4ecSAthira Rajeev u64 tb_freq; 36c4bbd4ecSAthira Rajeev u64 timebase; 37c4bbd4ecSAthira Rajeev u64 padded[3]; 38c4bbd4ecSAthira Rajeev }; 39c4bbd4ecSAthira Rajeev 40c4bbd4ecSAthira Rajeev struct powerpc_vpadtl_queue { 41c4bbd4ecSAthira Rajeev struct powerpc_vpadtl *vpa; 42c4bbd4ecSAthira Rajeev unsigned int queue_nr; 43c4bbd4ecSAthira Rajeev struct auxtrace_buffer *buffer; 44c4bbd4ecSAthira Rajeev struct thread *thread; 45c4bbd4ecSAthira Rajeev bool on_heap; 46cd1c3b73SAthira Rajeev struct powerpc_vpadtl_entry *dtl; 47cd1c3b73SAthira Rajeev u64 timestamp; 48cd1c3b73SAthira Rajeev unsigned long pkt_len; 49cd1c3b73SAthira Rajeev unsigned long buf_len; 50cd1c3b73SAthira Rajeev u64 boot_tb; 51cd1c3b73SAthira Rajeev u64 tb_freq; 52cd1c3b73SAthira Rajeev unsigned int tb_buffer; 53cd1c3b73SAthira Rajeev unsigned int size; 54c4bbd4ecSAthira Rajeev bool done; 55c4bbd4ecSAthira Rajeev pid_t pid; 56c4bbd4ecSAthira Rajeev pid_t tid; 57c4bbd4ecSAthira Rajeev int cpu; 58c4bbd4ecSAthira Rajeev }; 59c4bbd4ecSAthira Rajeev 60c4bbd4ecSAthira Rajeev const char *dispatch_reasons[11] = { 61c4bbd4ecSAthira Rajeev "external_interrupt", 62c4bbd4ecSAthira Rajeev "firmware_internal_event", 63c4bbd4ecSAthira Rajeev "H_PROD", 64c4bbd4ecSAthira Rajeev "decrementer_interrupt", 65c4bbd4ecSAthira Rajeev "system_reset", 66c4bbd4ecSAthira Rajeev "firmware_internal_event", 67c4bbd4ecSAthira Rajeev "conferred_cycles", 68c4bbd4ecSAthira Rajeev "time_slice", 69c4bbd4ecSAthira Rajeev "virtual_memory_page_fault", 70c4bbd4ecSAthira Rajeev "expropriated_adjunct", 71c4bbd4ecSAthira Rajeev "priv_doorbell"}; 72c4bbd4ecSAthira Rajeev 73c4bbd4ecSAthira Rajeev const char *preempt_reasons[10] = { 74c4bbd4ecSAthira Rajeev "unused", 75c4bbd4ecSAthira Rajeev "firmware_internal_event", 76c4bbd4ecSAthira Rajeev "H_CEDE", 77c4bbd4ecSAthira Rajeev "H_CONFER", 78c4bbd4ecSAthira Rajeev "time_slice", 79c4bbd4ecSAthira Rajeev "migration_hibernation_page_fault", 80c4bbd4ecSAthira Rajeev "virtual_memory_page_fault", 81c4bbd4ecSAthira Rajeev "H_CONFER_ADJUNCT", 82c4bbd4ecSAthira Rajeev "hcall_adjunct", 83c4bbd4ecSAthira Rajeev "HDEC_adjunct"}; 84c4bbd4ecSAthira Rajeev 85c4bbd4ecSAthira Rajeev #define dtl_entry_size sizeof(struct powerpc_vpadtl_entry) 86c4bbd4ecSAthira Rajeev 87c4bbd4ecSAthira Rajeev /* 88c4bbd4ecSAthira Rajeev * Function to dump the dispatch trace data when perf report 89c4bbd4ecSAthira Rajeev * is invoked with -D 90c4bbd4ecSAthira Rajeev */ 91c4bbd4ecSAthira Rajeev static void powerpc_vpadtl_dump(struct powerpc_vpadtl *vpa __maybe_unused, 92c4bbd4ecSAthira Rajeev unsigned char *buf, size_t len) 93c4bbd4ecSAthira Rajeev { 94c4bbd4ecSAthira Rajeev struct powerpc_vpadtl_entry *dtl; 95c4bbd4ecSAthira Rajeev int pkt_len, pos = 0; 96c4bbd4ecSAthira Rajeev const char *color = PERF_COLOR_BLUE; 97c4bbd4ecSAthira Rajeev 98c4bbd4ecSAthira Rajeev color_fprintf(stdout, color, 99c4bbd4ecSAthira Rajeev ". ... VPA DTL PMU data: size %zu bytes, entries is %zu\n", 100c4bbd4ecSAthira Rajeev len, len/dtl_entry_size); 101c4bbd4ecSAthira Rajeev 102c4bbd4ecSAthira Rajeev if (len % dtl_entry_size) 103c4bbd4ecSAthira Rajeev len = len - (len % dtl_entry_size); 104c4bbd4ecSAthira Rajeev 105c4bbd4ecSAthira Rajeev while (len) { 106c4bbd4ecSAthira Rajeev pkt_len = dtl_entry_size; 107c4bbd4ecSAthira Rajeev printf("."); 108c4bbd4ecSAthira Rajeev color_fprintf(stdout, color, " %08x: ", pos); 109c4bbd4ecSAthira Rajeev dtl = (struct powerpc_vpadtl_entry *)buf; 110c4bbd4ecSAthira Rajeev if (dtl->timebase != 0) { 111c4bbd4ecSAthira Rajeev printf("dispatch_reason:%s, preempt_reason:%s, " 112c4bbd4ecSAthira Rajeev "enqueue_to_dispatch_time:%d, ready_to_enqueue_time:%d, " 113c4bbd4ecSAthira Rajeev "waiting_to_ready_time:%d\n", 114c4bbd4ecSAthira Rajeev dispatch_reasons[dtl->dispatch_reason], 115c4bbd4ecSAthira Rajeev preempt_reasons[dtl->preempt_reason], 116c4bbd4ecSAthira Rajeev be32_to_cpu(dtl->enqueue_to_dispatch_time), 117c4bbd4ecSAthira Rajeev be32_to_cpu(dtl->ready_to_enqueue_time), 118c4bbd4ecSAthira Rajeev be32_to_cpu(dtl->waiting_to_ready_time)); 119c4bbd4ecSAthira Rajeev } else { 120c4bbd4ecSAthira Rajeev struct boottb_freq *boot_tb = (struct boottb_freq *)buf; 121c4bbd4ecSAthira Rajeev 122c4bbd4ecSAthira Rajeev printf("boot_tb: %" PRIu64 ", tb_freq: %" PRIu64 "\n", 123c4bbd4ecSAthira Rajeev boot_tb->boot_tb, boot_tb->tb_freq); 124c4bbd4ecSAthira Rajeev } 125c4bbd4ecSAthira Rajeev 126c4bbd4ecSAthira Rajeev pos += pkt_len; 127c4bbd4ecSAthira Rajeev buf += pkt_len; 128c4bbd4ecSAthira Rajeev len -= pkt_len; 129c4bbd4ecSAthira Rajeev } 130c4bbd4ecSAthira Rajeev } 131c4bbd4ecSAthira Rajeev 132cd1c3b73SAthira Rajeev static unsigned long long powerpc_vpadtl_timestamp(struct powerpc_vpadtl_queue *vpaq) 133cd1c3b73SAthira Rajeev { 134cd1c3b73SAthira Rajeev struct powerpc_vpadtl_entry *record = vpaq->dtl; 135cd1c3b73SAthira Rajeev unsigned long long timestamp = 0; 136cd1c3b73SAthira Rajeev unsigned long long boot_tb; 137cd1c3b73SAthira Rajeev unsigned long long diff; 138cd1c3b73SAthira Rajeev double result, div; 139cd1c3b73SAthira Rajeev double boot_freq; 140cd1c3b73SAthira Rajeev /* 141cd1c3b73SAthira Rajeev * Formula used to get timestamp that can be co-related with 142cd1c3b73SAthira Rajeev * other perf events: 143cd1c3b73SAthira Rajeev * ((timbase from DTL entry - boot time) / frequency) * 1000000000 144cd1c3b73SAthira Rajeev */ 145cd1c3b73SAthira Rajeev if (record->timebase) { 146cd1c3b73SAthira Rajeev boot_tb = vpaq->boot_tb; 147cd1c3b73SAthira Rajeev boot_freq = vpaq->tb_freq; 148cd1c3b73SAthira Rajeev diff = be64_to_cpu(record->timebase) - boot_tb; 149cd1c3b73SAthira Rajeev div = diff / boot_freq; 150cd1c3b73SAthira Rajeev result = div; 151cd1c3b73SAthira Rajeev result = result * 1000000000; 152cd1c3b73SAthira Rajeev timestamp = result; 153cd1c3b73SAthira Rajeev } 154cd1c3b73SAthira Rajeev 155cd1c3b73SAthira Rajeev return timestamp; 156cd1c3b73SAthira Rajeev } 157cd1c3b73SAthira Rajeev 158c4bbd4ecSAthira Rajeev static struct powerpc_vpadtl *session_to_vpa(struct perf_session *session) 159c4bbd4ecSAthira Rajeev { 160c4bbd4ecSAthira Rajeev return container_of(session->auxtrace, struct powerpc_vpadtl, auxtrace); 161c4bbd4ecSAthira Rajeev } 162c4bbd4ecSAthira Rajeev 163c4bbd4ecSAthira Rajeev static void powerpc_vpadtl_dump_event(struct powerpc_vpadtl *vpa, unsigned char *buf, 164c4bbd4ecSAthira Rajeev size_t len) 165c4bbd4ecSAthira Rajeev { 166c4bbd4ecSAthira Rajeev printf(".\n"); 167c4bbd4ecSAthira Rajeev powerpc_vpadtl_dump(vpa, buf, len); 168c4bbd4ecSAthira Rajeev } 169c4bbd4ecSAthira Rajeev 170*8644834aSAthira Rajeev /* 171*8644834aSAthira Rajeev * Generate perf sample for each entry in the dispatch trace log. 172*8644834aSAthira Rajeev * - sample ip is picked from srr0 field of powerpc_vpadtl_entry 173*8644834aSAthira Rajeev * - sample cpu is logical cpu. 174*8644834aSAthira Rajeev * - cpumode is set to PERF_RECORD_MISC_KERNEL 175*8644834aSAthira Rajeev * - Additionally save the details in raw_data of sample. This 176*8644834aSAthira Rajeev * is to print the relevant fields in perf_sample__fprintf_synth() 177*8644834aSAthira Rajeev * when called from builtin-script 178*8644834aSAthira Rajeev */ 179*8644834aSAthira Rajeev static int powerpc_vpadtl_sample(struct powerpc_vpadtl_entry *record, 180*8644834aSAthira Rajeev struct powerpc_vpadtl *vpa, u64 save, int cpu) 181*8644834aSAthira Rajeev { 182*8644834aSAthira Rajeev struct perf_sample sample; 183*8644834aSAthira Rajeev union perf_event event; 184*8644834aSAthira Rajeev 185*8644834aSAthira Rajeev sample.ip = be64_to_cpu(record->srr0); 186*8644834aSAthira Rajeev sample.period = 1; 187*8644834aSAthira Rajeev sample.cpu = cpu; 188*8644834aSAthira Rajeev sample.id = vpa->sample_id; 189*8644834aSAthira Rajeev sample.callchain = NULL; 190*8644834aSAthira Rajeev sample.branch_stack = NULL; 191*8644834aSAthira Rajeev memset(&event, 0, sizeof(event)); 192*8644834aSAthira Rajeev sample.cpumode = PERF_RECORD_MISC_KERNEL; 193*8644834aSAthira Rajeev sample.time = save; 194*8644834aSAthira Rajeev sample.raw_data = record; 195*8644834aSAthira Rajeev sample.raw_size = sizeof(record); 196*8644834aSAthira Rajeev event.sample.header.type = PERF_RECORD_SAMPLE; 197*8644834aSAthira Rajeev event.sample.header.misc = sample.cpumode; 198*8644834aSAthira Rajeev event.sample.header.size = sizeof(struct perf_event_header); 199*8644834aSAthira Rajeev 200*8644834aSAthira Rajeev if (perf_session__deliver_synth_event(vpa->session, &event, &sample)) { 201*8644834aSAthira Rajeev pr_debug("Failed to create sample for dtl entry\n"); 202*8644834aSAthira Rajeev return -1; 203*8644834aSAthira Rajeev } 204*8644834aSAthira Rajeev 205*8644834aSAthira Rajeev return 0; 206*8644834aSAthira Rajeev } 207*8644834aSAthira Rajeev 208cd1c3b73SAthira Rajeev static int powerpc_vpadtl_get_buffer(struct powerpc_vpadtl_queue *vpaq) 209c4bbd4ecSAthira Rajeev { 210cd1c3b73SAthira Rajeev struct auxtrace_buffer *buffer = vpaq->buffer; 211cd1c3b73SAthira Rajeev struct auxtrace_queues *queues = &vpaq->vpa->queues; 212cd1c3b73SAthira Rajeev struct auxtrace_queue *queue; 213cd1c3b73SAthira Rajeev 214cd1c3b73SAthira Rajeev queue = &queues->queue_array[vpaq->queue_nr]; 215cd1c3b73SAthira Rajeev buffer = auxtrace_buffer__next(queue, buffer); 216cd1c3b73SAthira Rajeev 217cd1c3b73SAthira Rajeev if (!buffer) 218c4bbd4ecSAthira Rajeev return 0; 219cd1c3b73SAthira Rajeev 220cd1c3b73SAthira Rajeev vpaq->buffer = buffer; 221cd1c3b73SAthira Rajeev vpaq->size = buffer->size; 222cd1c3b73SAthira Rajeev 223cd1c3b73SAthira Rajeev /* If the aux_buffer doesn't have data associated, try to load it */ 224cd1c3b73SAthira Rajeev if (!buffer->data) { 225cd1c3b73SAthira Rajeev /* get the file desc associated with the perf data file */ 226cd1c3b73SAthira Rajeev int fd = perf_data__fd(vpaq->vpa->session->data); 227cd1c3b73SAthira Rajeev 228cd1c3b73SAthira Rajeev buffer->data = auxtrace_buffer__get_data(buffer, fd); 229cd1c3b73SAthira Rajeev if (!buffer->data) 230cd1c3b73SAthira Rajeev return -ENOMEM; 231cd1c3b73SAthira Rajeev } 232cd1c3b73SAthira Rajeev 233cd1c3b73SAthira Rajeev vpaq->buf_len = buffer->size; 234cd1c3b73SAthira Rajeev 235cd1c3b73SAthira Rajeev if (buffer->size % dtl_entry_size) 236cd1c3b73SAthira Rajeev vpaq->buf_len = buffer->size - (buffer->size % dtl_entry_size); 237cd1c3b73SAthira Rajeev 238cd1c3b73SAthira Rajeev if (vpaq->tb_buffer != buffer->buffer_nr) { 239cd1c3b73SAthira Rajeev vpaq->pkt_len = 0; 240cd1c3b73SAthira Rajeev vpaq->tb_buffer = 0; 241cd1c3b73SAthira Rajeev } 242cd1c3b73SAthira Rajeev 243cd1c3b73SAthira Rajeev return 1; 244cd1c3b73SAthira Rajeev } 245cd1c3b73SAthira Rajeev 246cd1c3b73SAthira Rajeev /* 247cd1c3b73SAthira Rajeev * The first entry in the queue for VPA DTL PMU has the boot timebase, 248cd1c3b73SAthira Rajeev * frequency details which are needed to get timestamp which is required to 249cd1c3b73SAthira Rajeev * correlate with other events. Save the boot_tb and tb_freq as part of 250cd1c3b73SAthira Rajeev * powerpc_vpadtl_queue. The very next entry is the actual trace data to 251cd1c3b73SAthira Rajeev * be returned. 252cd1c3b73SAthira Rajeev */ 253cd1c3b73SAthira Rajeev static int powerpc_vpadtl_decode(struct powerpc_vpadtl_queue *vpaq) 254cd1c3b73SAthira Rajeev { 255cd1c3b73SAthira Rajeev int ret; 256cd1c3b73SAthira Rajeev char *buf; 257cd1c3b73SAthira Rajeev struct boottb_freq *boottb; 258cd1c3b73SAthira Rajeev 259cd1c3b73SAthira Rajeev ret = powerpc_vpadtl_get_buffer(vpaq); 260cd1c3b73SAthira Rajeev if (ret <= 0) 261cd1c3b73SAthira Rajeev return ret; 262cd1c3b73SAthira Rajeev 263cd1c3b73SAthira Rajeev boottb = (struct boottb_freq *)vpaq->buffer->data; 264cd1c3b73SAthira Rajeev if (boottb->timebase == 0) { 265cd1c3b73SAthira Rajeev vpaq->boot_tb = boottb->boot_tb; 266cd1c3b73SAthira Rajeev vpaq->tb_freq = boottb->tb_freq; 267cd1c3b73SAthira Rajeev vpaq->pkt_len += dtl_entry_size; 268cd1c3b73SAthira Rajeev } 269cd1c3b73SAthira Rajeev 270cd1c3b73SAthira Rajeev buf = vpaq->buffer->data; 271cd1c3b73SAthira Rajeev buf += vpaq->pkt_len; 272cd1c3b73SAthira Rajeev vpaq->dtl = (struct powerpc_vpadtl_entry *)buf; 273cd1c3b73SAthira Rajeev 274cd1c3b73SAthira Rajeev vpaq->tb_buffer = vpaq->buffer->buffer_nr; 275cd1c3b73SAthira Rajeev vpaq->buffer = NULL; 276cd1c3b73SAthira Rajeev vpaq->buf_len = 0; 277cd1c3b73SAthira Rajeev 278cd1c3b73SAthira Rajeev return 1; 279cd1c3b73SAthira Rajeev } 280cd1c3b73SAthira Rajeev 281*8644834aSAthira Rajeev static int powerpc_vpadtl_decode_all(struct powerpc_vpadtl_queue *vpaq) 282*8644834aSAthira Rajeev { 283*8644834aSAthira Rajeev int ret; 284*8644834aSAthira Rajeev unsigned char *buf; 285*8644834aSAthira Rajeev 286*8644834aSAthira Rajeev if (!vpaq->buf_len || vpaq->pkt_len == vpaq->size) { 287*8644834aSAthira Rajeev ret = powerpc_vpadtl_get_buffer(vpaq); 288*8644834aSAthira Rajeev if (ret <= 0) 289*8644834aSAthira Rajeev return ret; 290*8644834aSAthira Rajeev } 291*8644834aSAthira Rajeev 292*8644834aSAthira Rajeev if (vpaq->buffer) { 293*8644834aSAthira Rajeev buf = vpaq->buffer->data; 294*8644834aSAthira Rajeev buf += vpaq->pkt_len; 295*8644834aSAthira Rajeev vpaq->dtl = (struct powerpc_vpadtl_entry *)buf; 296*8644834aSAthira Rajeev if ((long long)be64_to_cpu(vpaq->dtl->timebase) <= 0) { 297*8644834aSAthira Rajeev if (vpaq->pkt_len != dtl_entry_size && vpaq->buf_len) { 298*8644834aSAthira Rajeev vpaq->pkt_len += dtl_entry_size; 299*8644834aSAthira Rajeev vpaq->buf_len -= dtl_entry_size; 300*8644834aSAthira Rajeev } 301*8644834aSAthira Rajeev return -1; 302*8644834aSAthira Rajeev } 303*8644834aSAthira Rajeev vpaq->pkt_len += dtl_entry_size; 304*8644834aSAthira Rajeev vpaq->buf_len -= dtl_entry_size; 305*8644834aSAthira Rajeev } else { 306*8644834aSAthira Rajeev return 0; 307*8644834aSAthira Rajeev } 308*8644834aSAthira Rajeev 309*8644834aSAthira Rajeev return 1; 310*8644834aSAthira Rajeev } 311*8644834aSAthira Rajeev 312*8644834aSAthira Rajeev static int powerpc_vpadtl_run_decoder(struct powerpc_vpadtl_queue *vpaq, u64 *timestamp) 313*8644834aSAthira Rajeev { 314*8644834aSAthira Rajeev struct powerpc_vpadtl *vpa = vpaq->vpa; 315*8644834aSAthira Rajeev struct powerpc_vpadtl_entry *record; 316*8644834aSAthira Rajeev int ret; 317*8644834aSAthira Rajeev unsigned long long vpaq_timestamp; 318*8644834aSAthira Rajeev 319*8644834aSAthira Rajeev while (1) { 320*8644834aSAthira Rajeev ret = powerpc_vpadtl_decode_all(vpaq); 321*8644834aSAthira Rajeev if (!ret) { 322*8644834aSAthira Rajeev pr_debug("All data in the queue has been processed.\n"); 323*8644834aSAthira Rajeev return 1; 324*8644834aSAthira Rajeev } 325*8644834aSAthira Rajeev 326*8644834aSAthira Rajeev /* 327*8644834aSAthira Rajeev * Error is detected when decoding VPA PMU trace. Continue to 328*8644834aSAthira Rajeev * the next trace data and find out more dtl entries. 329*8644834aSAthira Rajeev */ 330*8644834aSAthira Rajeev if (ret < 0) 331*8644834aSAthira Rajeev continue; 332*8644834aSAthira Rajeev 333*8644834aSAthira Rajeev record = vpaq->dtl; 334*8644834aSAthira Rajeev 335*8644834aSAthira Rajeev vpaq_timestamp = powerpc_vpadtl_timestamp(vpaq); 336*8644834aSAthira Rajeev 337*8644834aSAthira Rajeev /* Update timestamp for the last record */ 338*8644834aSAthira Rajeev if (vpaq_timestamp > vpaq->timestamp) 339*8644834aSAthira Rajeev vpaq->timestamp = vpaq_timestamp; 340*8644834aSAthira Rajeev 341*8644834aSAthira Rajeev /* 342*8644834aSAthira Rajeev * If the timestamp of the queue is later than timestamp of the 343*8644834aSAthira Rajeev * coming perf event, bail out so can allow the perf event to 344*8644834aSAthira Rajeev * be processed ahead. 345*8644834aSAthira Rajeev */ 346*8644834aSAthira Rajeev if (vpaq->timestamp >= *timestamp) { 347*8644834aSAthira Rajeev *timestamp = vpaq->timestamp; 348*8644834aSAthira Rajeev vpaq->pkt_len -= dtl_entry_size; 349*8644834aSAthira Rajeev vpaq->buf_len += dtl_entry_size; 350*8644834aSAthira Rajeev return 0; 351*8644834aSAthira Rajeev } 352*8644834aSAthira Rajeev 353*8644834aSAthira Rajeev ret = powerpc_vpadtl_sample(record, vpa, vpaq_timestamp, vpaq->cpu); 354*8644834aSAthira Rajeev if (ret) 355*8644834aSAthira Rajeev continue; 356*8644834aSAthira Rajeev } 357*8644834aSAthira Rajeev return 0; 358*8644834aSAthira Rajeev } 359*8644834aSAthira Rajeev 360*8644834aSAthira Rajeev /* 361*8644834aSAthira Rajeev * For each of the PERF_RECORD_XX record, compare the timestamp 362*8644834aSAthira Rajeev * of perf record with timestamp of top element in the auxtrace heap. 363*8644834aSAthira Rajeev * Process the auxtrace queue if the timestamp of element from heap is 364*8644834aSAthira Rajeev * lower than timestamp from entry in perf record. 365*8644834aSAthira Rajeev * 366*8644834aSAthira Rajeev * Update the timestamp of the auxtrace heap with the timestamp 367*8644834aSAthira Rajeev * of last processed entry from the auxtrace buffer. 368*8644834aSAthira Rajeev */ 369*8644834aSAthira Rajeev static int powerpc_vpadtl_process_queues(struct powerpc_vpadtl *vpa, u64 timestamp) 370*8644834aSAthira Rajeev { 371*8644834aSAthira Rajeev unsigned int queue_nr; 372*8644834aSAthira Rajeev u64 ts; 373*8644834aSAthira Rajeev int ret; 374*8644834aSAthira Rajeev 375*8644834aSAthira Rajeev while (1) { 376*8644834aSAthira Rajeev struct auxtrace_queue *queue; 377*8644834aSAthira Rajeev struct powerpc_vpadtl_queue *vpaq; 378*8644834aSAthira Rajeev 379*8644834aSAthira Rajeev if (!vpa->heap.heap_cnt) 380*8644834aSAthira Rajeev return 0; 381*8644834aSAthira Rajeev 382*8644834aSAthira Rajeev if (vpa->heap.heap_array[0].ordinal >= timestamp) 383*8644834aSAthira Rajeev return 0; 384*8644834aSAthira Rajeev 385*8644834aSAthira Rajeev queue_nr = vpa->heap.heap_array[0].queue_nr; 386*8644834aSAthira Rajeev queue = &vpa->queues.queue_array[queue_nr]; 387*8644834aSAthira Rajeev vpaq = queue->priv; 388*8644834aSAthira Rajeev 389*8644834aSAthira Rajeev auxtrace_heap__pop(&vpa->heap); 390*8644834aSAthira Rajeev 391*8644834aSAthira Rajeev if (vpa->heap.heap_cnt) { 392*8644834aSAthira Rajeev ts = vpa->heap.heap_array[0].ordinal + 1; 393*8644834aSAthira Rajeev if (ts > timestamp) 394*8644834aSAthira Rajeev ts = timestamp; 395*8644834aSAthira Rajeev } else { 396*8644834aSAthira Rajeev ts = timestamp; 397*8644834aSAthira Rajeev } 398*8644834aSAthira Rajeev 399*8644834aSAthira Rajeev ret = powerpc_vpadtl_run_decoder(vpaq, &ts); 400*8644834aSAthira Rajeev if (ret < 0) { 401*8644834aSAthira Rajeev auxtrace_heap__add(&vpa->heap, queue_nr, ts); 402*8644834aSAthira Rajeev return ret; 403*8644834aSAthira Rajeev } 404*8644834aSAthira Rajeev 405*8644834aSAthira Rajeev if (!ret) { 406*8644834aSAthira Rajeev ret = auxtrace_heap__add(&vpa->heap, queue_nr, ts); 407*8644834aSAthira Rajeev if (ret < 0) 408*8644834aSAthira Rajeev return ret; 409*8644834aSAthira Rajeev } else { 410*8644834aSAthira Rajeev vpaq->on_heap = false; 411*8644834aSAthira Rajeev } 412*8644834aSAthira Rajeev } 413*8644834aSAthira Rajeev return 0; 414*8644834aSAthira Rajeev } 415*8644834aSAthira Rajeev 416cd1c3b73SAthira Rajeev static struct powerpc_vpadtl_queue *powerpc_vpadtl__alloc_queue(struct powerpc_vpadtl *vpa, 417cd1c3b73SAthira Rajeev unsigned int queue_nr) 418cd1c3b73SAthira Rajeev { 419cd1c3b73SAthira Rajeev struct powerpc_vpadtl_queue *vpaq; 420cd1c3b73SAthira Rajeev 421cd1c3b73SAthira Rajeev vpaq = zalloc(sizeof(*vpaq)); 422cd1c3b73SAthira Rajeev if (!vpaq) 423cd1c3b73SAthira Rajeev return NULL; 424cd1c3b73SAthira Rajeev 425cd1c3b73SAthira Rajeev vpaq->vpa = vpa; 426cd1c3b73SAthira Rajeev vpaq->queue_nr = queue_nr; 427cd1c3b73SAthira Rajeev 428cd1c3b73SAthira Rajeev return vpaq; 429cd1c3b73SAthira Rajeev } 430cd1c3b73SAthira Rajeev 431cd1c3b73SAthira Rajeev /* 432cd1c3b73SAthira Rajeev * When the Dispatch Trace Log data is collected along with other events 433cd1c3b73SAthira Rajeev * like sched tracepoint events, it needs to be correlated and present 434cd1c3b73SAthira Rajeev * interleaved along with these events. Perf events can be collected 435cd1c3b73SAthira Rajeev * parallely across the CPUs. 436cd1c3b73SAthira Rajeev * 437cd1c3b73SAthira Rajeev * An auxtrace_queue is created for each CPU. Data within each queue is in 438cd1c3b73SAthira Rajeev * increasing order of timestamp. Allocate and setup auxtrace queues here. 439cd1c3b73SAthira Rajeev * All auxtrace queues is maintained in auxtrace heap in the increasing order 440cd1c3b73SAthira Rajeev * of timestamp. So always the lowest timestamp (entries to be processed first) 441cd1c3b73SAthira Rajeev * is on top of the heap. 442cd1c3b73SAthira Rajeev * 443cd1c3b73SAthira Rajeev * To add to auxtrace heap, fetch the timestamp from first DTL entry 444cd1c3b73SAthira Rajeev * for each of the queue. 445cd1c3b73SAthira Rajeev */ 446cd1c3b73SAthira Rajeev static int powerpc_vpadtl__setup_queue(struct powerpc_vpadtl *vpa, 447cd1c3b73SAthira Rajeev struct auxtrace_queue *queue, 448cd1c3b73SAthira Rajeev unsigned int queue_nr) 449cd1c3b73SAthira Rajeev { 450cd1c3b73SAthira Rajeev struct powerpc_vpadtl_queue *vpaq = queue->priv; 451cd1c3b73SAthira Rajeev 452cd1c3b73SAthira Rajeev if (list_empty(&queue->head) || vpaq) 453cd1c3b73SAthira Rajeev return 0; 454cd1c3b73SAthira Rajeev 455cd1c3b73SAthira Rajeev vpaq = powerpc_vpadtl__alloc_queue(vpa, queue_nr); 456cd1c3b73SAthira Rajeev if (!vpaq) 457cd1c3b73SAthira Rajeev return -ENOMEM; 458cd1c3b73SAthira Rajeev 459cd1c3b73SAthira Rajeev queue->priv = vpaq; 460cd1c3b73SAthira Rajeev 461cd1c3b73SAthira Rajeev if (queue->cpu != -1) 462cd1c3b73SAthira Rajeev vpaq->cpu = queue->cpu; 463cd1c3b73SAthira Rajeev 464cd1c3b73SAthira Rajeev if (!vpaq->on_heap) { 465cd1c3b73SAthira Rajeev int ret; 466cd1c3b73SAthira Rajeev retry: 467cd1c3b73SAthira Rajeev ret = powerpc_vpadtl_decode(vpaq); 468cd1c3b73SAthira Rajeev if (!ret) 469cd1c3b73SAthira Rajeev return 0; 470cd1c3b73SAthira Rajeev 471cd1c3b73SAthira Rajeev if (ret < 0) 472cd1c3b73SAthira Rajeev goto retry; 473cd1c3b73SAthira Rajeev 474cd1c3b73SAthira Rajeev vpaq->timestamp = powerpc_vpadtl_timestamp(vpaq); 475cd1c3b73SAthira Rajeev 476cd1c3b73SAthira Rajeev ret = auxtrace_heap__add(&vpa->heap, queue_nr, vpaq->timestamp); 477cd1c3b73SAthira Rajeev if (ret) 478cd1c3b73SAthira Rajeev return ret; 479cd1c3b73SAthira Rajeev vpaq->on_heap = true; 480cd1c3b73SAthira Rajeev } 481cd1c3b73SAthira Rajeev 482cd1c3b73SAthira Rajeev return 0; 483cd1c3b73SAthira Rajeev } 484cd1c3b73SAthira Rajeev 485cd1c3b73SAthira Rajeev static int powerpc_vpadtl__setup_queues(struct powerpc_vpadtl *vpa) 486cd1c3b73SAthira Rajeev { 487cd1c3b73SAthira Rajeev unsigned int i; 488cd1c3b73SAthira Rajeev int ret; 489cd1c3b73SAthira Rajeev 490cd1c3b73SAthira Rajeev for (i = 0; i < vpa->queues.nr_queues; i++) { 491cd1c3b73SAthira Rajeev ret = powerpc_vpadtl__setup_queue(vpa, &vpa->queues.queue_array[i], i); 492cd1c3b73SAthira Rajeev if (ret) 493cd1c3b73SAthira Rajeev return ret; 494cd1c3b73SAthira Rajeev } 495cd1c3b73SAthira Rajeev 496cd1c3b73SAthira Rajeev return 0; 497cd1c3b73SAthira Rajeev } 498cd1c3b73SAthira Rajeev 499cd1c3b73SAthira Rajeev static int powerpc_vpadtl__update_queues(struct powerpc_vpadtl *vpa) 500cd1c3b73SAthira Rajeev { 501cd1c3b73SAthira Rajeev if (vpa->queues.new_data) { 502cd1c3b73SAthira Rajeev vpa->queues.new_data = false; 503cd1c3b73SAthira Rajeev return powerpc_vpadtl__setup_queues(vpa); 504cd1c3b73SAthira Rajeev } 505cd1c3b73SAthira Rajeev 506cd1c3b73SAthira Rajeev return 0; 507cd1c3b73SAthira Rajeev } 508cd1c3b73SAthira Rajeev 509cd1c3b73SAthira Rajeev static int powerpc_vpadtl_process_event(struct perf_session *session, 510cd1c3b73SAthira Rajeev union perf_event *event __maybe_unused, 511cd1c3b73SAthira Rajeev struct perf_sample *sample, 512cd1c3b73SAthira Rajeev const struct perf_tool *tool) 513cd1c3b73SAthira Rajeev { 514cd1c3b73SAthira Rajeev struct powerpc_vpadtl *vpa = session_to_vpa(session); 515cd1c3b73SAthira Rajeev int err = 0; 516cd1c3b73SAthira Rajeev 517cd1c3b73SAthira Rajeev if (dump_trace) 518cd1c3b73SAthira Rajeev return 0; 519cd1c3b73SAthira Rajeev 520cd1c3b73SAthira Rajeev if (!tool->ordered_events) { 521cd1c3b73SAthira Rajeev pr_err("VPA requires ordered events\n"); 522cd1c3b73SAthira Rajeev return -EINVAL; 523cd1c3b73SAthira Rajeev } 524cd1c3b73SAthira Rajeev 525cd1c3b73SAthira Rajeev if (sample->time) { 526cd1c3b73SAthira Rajeev err = powerpc_vpadtl__update_queues(vpa); 527cd1c3b73SAthira Rajeev if (err) 528cd1c3b73SAthira Rajeev return err; 529*8644834aSAthira Rajeev 530*8644834aSAthira Rajeev err = powerpc_vpadtl_process_queues(vpa, sample->time); 531cd1c3b73SAthira Rajeev } 532cd1c3b73SAthira Rajeev 533cd1c3b73SAthira Rajeev return err; 534c4bbd4ecSAthira Rajeev } 535c4bbd4ecSAthira Rajeev 536c4bbd4ecSAthira Rajeev /* 537c4bbd4ecSAthira Rajeev * Process PERF_RECORD_AUXTRACE records 538c4bbd4ecSAthira Rajeev */ 539c4bbd4ecSAthira Rajeev static int powerpc_vpadtl_process_auxtrace_event(struct perf_session *session, 540c4bbd4ecSAthira Rajeev union perf_event *event, 541c4bbd4ecSAthira Rajeev const struct perf_tool *tool __maybe_unused) 542c4bbd4ecSAthira Rajeev { 543c4bbd4ecSAthira Rajeev struct powerpc_vpadtl *vpa = session_to_vpa(session); 544c4bbd4ecSAthira Rajeev struct auxtrace_buffer *buffer; 545c4bbd4ecSAthira Rajeev int fd = perf_data__fd(session->data); 546c4bbd4ecSAthira Rajeev off_t data_offset; 547c4bbd4ecSAthira Rajeev int err; 548c4bbd4ecSAthira Rajeev 549c4bbd4ecSAthira Rajeev if (!dump_trace) 550c4bbd4ecSAthira Rajeev return 0; 551c4bbd4ecSAthira Rajeev 552c4bbd4ecSAthira Rajeev if (perf_data__is_pipe(session->data)) { 553c4bbd4ecSAthira Rajeev data_offset = 0; 554c4bbd4ecSAthira Rajeev } else { 555c4bbd4ecSAthira Rajeev data_offset = lseek(fd, 0, SEEK_CUR); 556c4bbd4ecSAthira Rajeev if (data_offset == -1) 557c4bbd4ecSAthira Rajeev return -errno; 558c4bbd4ecSAthira Rajeev } 559c4bbd4ecSAthira Rajeev 560c4bbd4ecSAthira Rajeev err = auxtrace_queues__add_event(&vpa->queues, session, event, 561c4bbd4ecSAthira Rajeev data_offset, &buffer); 562c4bbd4ecSAthira Rajeev 563c4bbd4ecSAthira Rajeev if (err) 564c4bbd4ecSAthira Rajeev return err; 565c4bbd4ecSAthira Rajeev 566c4bbd4ecSAthira Rajeev /* Dump here now we have copied a piped trace out of the pipe */ 567c4bbd4ecSAthira Rajeev if (auxtrace_buffer__get_data(buffer, fd)) { 568c4bbd4ecSAthira Rajeev powerpc_vpadtl_dump_event(vpa, buffer->data, buffer->size); 569c4bbd4ecSAthira Rajeev auxtrace_buffer__put_data(buffer); 570c4bbd4ecSAthira Rajeev } 571c4bbd4ecSAthira Rajeev 572c4bbd4ecSAthira Rajeev return 0; 573c4bbd4ecSAthira Rajeev } 574c4bbd4ecSAthira Rajeev 575c4bbd4ecSAthira Rajeev static int powerpc_vpadtl_flush(struct perf_session *session __maybe_unused, 576c4bbd4ecSAthira Rajeev const struct perf_tool *tool __maybe_unused) 577c4bbd4ecSAthira Rajeev { 578c4bbd4ecSAthira Rajeev return 0; 579c4bbd4ecSAthira Rajeev } 580c4bbd4ecSAthira Rajeev 581c4bbd4ecSAthira Rajeev static void powerpc_vpadtl_free_events(struct perf_session *session) 582c4bbd4ecSAthira Rajeev { 583c4bbd4ecSAthira Rajeev struct powerpc_vpadtl *vpa = session_to_vpa(session); 584c4bbd4ecSAthira Rajeev struct auxtrace_queues *queues = &vpa->queues; 585c4bbd4ecSAthira Rajeev 586c4bbd4ecSAthira Rajeev for (unsigned int i = 0; i < queues->nr_queues; i++) 587c4bbd4ecSAthira Rajeev zfree(&queues->queue_array[i].priv); 588c4bbd4ecSAthira Rajeev 589c4bbd4ecSAthira Rajeev auxtrace_queues__free(queues); 590c4bbd4ecSAthira Rajeev } 591c4bbd4ecSAthira Rajeev 592c4bbd4ecSAthira Rajeev static void powerpc_vpadtl_free(struct perf_session *session) 593c4bbd4ecSAthira Rajeev { 594c4bbd4ecSAthira Rajeev struct powerpc_vpadtl *vpa = session_to_vpa(session); 595c4bbd4ecSAthira Rajeev 596c4bbd4ecSAthira Rajeev auxtrace_heap__free(&vpa->heap); 597c4bbd4ecSAthira Rajeev powerpc_vpadtl_free_events(session); 598c4bbd4ecSAthira Rajeev session->auxtrace = NULL; 599c4bbd4ecSAthira Rajeev free(vpa); 600c4bbd4ecSAthira Rajeev } 601c4bbd4ecSAthira Rajeev 602c4bbd4ecSAthira Rajeev static const char * const powerpc_vpadtl_info_fmts[] = { 603c4bbd4ecSAthira Rajeev [POWERPC_VPADTL_TYPE] = " PMU Type %"PRId64"\n", 604c4bbd4ecSAthira Rajeev }; 605c4bbd4ecSAthira Rajeev 606c4bbd4ecSAthira Rajeev static void powerpc_vpadtl_print_info(__u64 *arr) 607c4bbd4ecSAthira Rajeev { 608c4bbd4ecSAthira Rajeev if (!dump_trace) 609c4bbd4ecSAthira Rajeev return; 610c4bbd4ecSAthira Rajeev 611c4bbd4ecSAthira Rajeev fprintf(stdout, powerpc_vpadtl_info_fmts[POWERPC_VPADTL_TYPE], arr[POWERPC_VPADTL_TYPE]); 612c4bbd4ecSAthira Rajeev } 613c4bbd4ecSAthira Rajeev 61471feffa9SAthira Rajeev static void set_event_name(struct evlist *evlist, u64 id, 61571feffa9SAthira Rajeev const char *name) 61671feffa9SAthira Rajeev { 61771feffa9SAthira Rajeev struct evsel *evsel; 61871feffa9SAthira Rajeev 61971feffa9SAthira Rajeev evlist__for_each_entry(evlist, evsel) { 62071feffa9SAthira Rajeev if (evsel->core.id && evsel->core.id[0] == id) { 62171feffa9SAthira Rajeev if (evsel->name) 62271feffa9SAthira Rajeev zfree(&evsel->name); 62371feffa9SAthira Rajeev evsel->name = strdup(name); 62471feffa9SAthira Rajeev break; 62571feffa9SAthira Rajeev } 62671feffa9SAthira Rajeev } 62771feffa9SAthira Rajeev } 62871feffa9SAthira Rajeev 62971feffa9SAthira Rajeev static int 63071feffa9SAthira Rajeev powerpc_vpadtl_synth_events(struct powerpc_vpadtl *vpa, struct perf_session *session) 63171feffa9SAthira Rajeev { 63271feffa9SAthira Rajeev struct evlist *evlist = session->evlist; 63371feffa9SAthira Rajeev struct evsel *evsel; 63471feffa9SAthira Rajeev struct perf_event_attr attr; 63571feffa9SAthira Rajeev bool found = false; 63671feffa9SAthira Rajeev u64 id; 63771feffa9SAthira Rajeev int err; 63871feffa9SAthira Rajeev 63971feffa9SAthira Rajeev evlist__for_each_entry(evlist, evsel) { 64071feffa9SAthira Rajeev if (strstarts(evsel->name, "vpa_dtl")) { 64171feffa9SAthira Rajeev found = true; 64271feffa9SAthira Rajeev break; 64371feffa9SAthira Rajeev } 64471feffa9SAthira Rajeev } 64571feffa9SAthira Rajeev 64671feffa9SAthira Rajeev if (!found) { 64771feffa9SAthira Rajeev pr_debug("No selected events with VPA trace data\n"); 64871feffa9SAthira Rajeev return 0; 64971feffa9SAthira Rajeev } 65071feffa9SAthira Rajeev 65171feffa9SAthira Rajeev memset(&attr, 0, sizeof(struct perf_event_attr)); 65271feffa9SAthira Rajeev attr.size = sizeof(struct perf_event_attr); 65371feffa9SAthira Rajeev attr.sample_type = evsel->core.attr.sample_type; 65471feffa9SAthira Rajeev attr.sample_id_all = evsel->core.attr.sample_id_all; 65571feffa9SAthira Rajeev attr.type = PERF_TYPE_SYNTH; 65671feffa9SAthira Rajeev attr.config = PERF_SYNTH_POWERPC_VPA_DTL; 65771feffa9SAthira Rajeev 65871feffa9SAthira Rajeev /* create new id val to be a fixed offset from evsel id */ 65971feffa9SAthira Rajeev id = evsel->core.id[0] + 1000000000; 66071feffa9SAthira Rajeev if (!id) 66171feffa9SAthira Rajeev id = 1; 66271feffa9SAthira Rajeev 66371feffa9SAthira Rajeev err = perf_session__deliver_synth_attr_event(session, &attr, id); 66471feffa9SAthira Rajeev if (err) 66571feffa9SAthira Rajeev return err; 66671feffa9SAthira Rajeev 66771feffa9SAthira Rajeev vpa->sample_id = id; 66871feffa9SAthira Rajeev set_event_name(evlist, id, "vpa-dtl"); 66971feffa9SAthira Rajeev 67071feffa9SAthira Rajeev return 0; 67171feffa9SAthira Rajeev } 67271feffa9SAthira Rajeev 673c4bbd4ecSAthira Rajeev /* 674c4bbd4ecSAthira Rajeev * Process the PERF_RECORD_AUXTRACE_INFO records and setup 675c4bbd4ecSAthira Rajeev * the infrastructure to process auxtrace events. PERF_RECORD_AUXTRACE_INFO 676c4bbd4ecSAthira Rajeev * is processed first since it is of type perf_user_event_type. 677c4bbd4ecSAthira Rajeev * Initialise the aux buffer queues using auxtrace_queues__init(). 678c4bbd4ecSAthira Rajeev * auxtrace_queue is created for each CPU. 679c4bbd4ecSAthira Rajeev */ 680c4bbd4ecSAthira Rajeev int powerpc_vpadtl_process_auxtrace_info(union perf_event *event, 681c4bbd4ecSAthira Rajeev struct perf_session *session) 682c4bbd4ecSAthira Rajeev { 683c4bbd4ecSAthira Rajeev struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; 684c4bbd4ecSAthira Rajeev size_t min_sz = sizeof(u64) * POWERPC_VPADTL_TYPE; 685c4bbd4ecSAthira Rajeev struct powerpc_vpadtl *vpa; 686c4bbd4ecSAthira Rajeev int err; 687c4bbd4ecSAthira Rajeev 688c4bbd4ecSAthira Rajeev if (auxtrace_info->header.size < sizeof(struct perf_record_auxtrace_info) + 689c4bbd4ecSAthira Rajeev min_sz) 690c4bbd4ecSAthira Rajeev return -EINVAL; 691c4bbd4ecSAthira Rajeev 692c4bbd4ecSAthira Rajeev vpa = zalloc(sizeof(struct powerpc_vpadtl)); 693c4bbd4ecSAthira Rajeev if (!vpa) 694c4bbd4ecSAthira Rajeev return -ENOMEM; 695c4bbd4ecSAthira Rajeev 696c4bbd4ecSAthira Rajeev err = auxtrace_queues__init(&vpa->queues); 697c4bbd4ecSAthira Rajeev if (err) 698c4bbd4ecSAthira Rajeev goto err_free; 699c4bbd4ecSAthira Rajeev 700c4bbd4ecSAthira Rajeev vpa->session = session; 701c4bbd4ecSAthira Rajeev vpa->machine = &session->machines.host; /* No kvm support */ 702c4bbd4ecSAthira Rajeev vpa->auxtrace_type = auxtrace_info->type; 703c4bbd4ecSAthira Rajeev vpa->pmu_type = auxtrace_info->priv[POWERPC_VPADTL_TYPE]; 704c4bbd4ecSAthira Rajeev 705c4bbd4ecSAthira Rajeev vpa->auxtrace.process_event = powerpc_vpadtl_process_event; 706c4bbd4ecSAthira Rajeev vpa->auxtrace.process_auxtrace_event = powerpc_vpadtl_process_auxtrace_event; 707c4bbd4ecSAthira Rajeev vpa->auxtrace.flush_events = powerpc_vpadtl_flush; 708c4bbd4ecSAthira Rajeev vpa->auxtrace.free_events = powerpc_vpadtl_free_events; 709c4bbd4ecSAthira Rajeev vpa->auxtrace.free = powerpc_vpadtl_free; 710c4bbd4ecSAthira Rajeev session->auxtrace = &vpa->auxtrace; 711c4bbd4ecSAthira Rajeev 712c4bbd4ecSAthira Rajeev powerpc_vpadtl_print_info(&auxtrace_info->priv[0]); 713c4bbd4ecSAthira Rajeev 71471feffa9SAthira Rajeev if (dump_trace) 715c4bbd4ecSAthira Rajeev return 0; 716c4bbd4ecSAthira Rajeev 71771feffa9SAthira Rajeev err = powerpc_vpadtl_synth_events(vpa, session); 71871feffa9SAthira Rajeev if (err) 71971feffa9SAthira Rajeev goto err_free_queues; 72071feffa9SAthira Rajeev 72171feffa9SAthira Rajeev err = auxtrace_queues__process_index(&vpa->queues, session); 72271feffa9SAthira Rajeev if (err) 72371feffa9SAthira Rajeev goto err_free_queues; 72471feffa9SAthira Rajeev 72571feffa9SAthira Rajeev return 0; 72671feffa9SAthira Rajeev 72771feffa9SAthira Rajeev err_free_queues: 72871feffa9SAthira Rajeev auxtrace_queues__free(&vpa->queues); 72971feffa9SAthira Rajeev session->auxtrace = NULL; 73071feffa9SAthira Rajeev 731c4bbd4ecSAthira Rajeev err_free: 732c4bbd4ecSAthira Rajeev free(vpa); 733c4bbd4ecSAthira Rajeev return err; 734c4bbd4ecSAthira Rajeev } 735