Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v6.11-rc6 190 lines 4.5 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * HiSilicon PCIe Trace and Tuning (PTT) support 4 * Copyright (c) 2022 HiSilicon Technologies Co., Ltd. 5 */ 6 7#include <byteswap.h> 8#include <endian.h> 9#include <errno.h> 10#include <inttypes.h> 11#include <linux/bitops.h> 12#include <linux/kernel.h> 13#include <linux/log2.h> 14#include <linux/types.h> 15#include <linux/zalloc.h> 16#include <stdlib.h> 17#include <unistd.h> 18 19#include "auxtrace.h" 20#include "color.h" 21#include "debug.h" 22#include "evsel.h" 23#include "hisi-ptt.h" 24#include "hisi-ptt-decoder/hisi-ptt-pkt-decoder.h" 25#include "machine.h" 26#include "session.h" 27#include "tool.h" 28#include <internal/lib.h> 29 30struct hisi_ptt { 31 struct auxtrace auxtrace; 32 u32 auxtrace_type; 33 struct perf_session *session; 34 struct machine *machine; 35 u32 pmu_type; 36}; 37 38static enum hisi_ptt_pkt_type hisi_ptt_check_packet_type(unsigned char *buf) 39{ 40 uint32_t head = *(uint32_t *)buf; 41 42 if ((HISI_PTT_8DW_CHECK_MASK & head) == HISI_PTT_IS_8DW_PKT) 43 return HISI_PTT_8DW_PKT; 44 45 return HISI_PTT_4DW_PKT; 46} 47 48static void hisi_ptt_dump(struct hisi_ptt *ptt __maybe_unused, 49 unsigned char *buf, size_t len) 50{ 51 const char *color = PERF_COLOR_BLUE; 52 enum hisi_ptt_pkt_type type; 53 size_t pos = 0; 54 int pkt_len; 55 56 type = hisi_ptt_check_packet_type(buf); 57 len = round_down(len, hisi_ptt_pkt_size[type]); 58 color_fprintf(stdout, color, ". ... HISI PTT data: size %zu bytes\n", 59 len); 60 61 while (len > 0) { 62 pkt_len = hisi_ptt_pkt_desc(buf, pos, type); 63 if (!pkt_len) 64 color_fprintf(stdout, color, " Bad packet!\n"); 65 66 pos += pkt_len; 67 len -= pkt_len; 68 } 69} 70 71static void hisi_ptt_dump_event(struct hisi_ptt *ptt, unsigned char *buf, 72 size_t len) 73{ 74 printf(".\n"); 75 76 hisi_ptt_dump(ptt, buf, len); 77} 78 79static int hisi_ptt_process_event(struct perf_session *session __maybe_unused, 80 union perf_event *event __maybe_unused, 81 struct perf_sample *sample __maybe_unused, 82 struct perf_tool *tool __maybe_unused) 83{ 84 return 0; 85} 86 87static int hisi_ptt_process_auxtrace_event(struct perf_session *session, 88 union perf_event *event, 89 struct perf_tool *tool __maybe_unused) 90{ 91 struct hisi_ptt *ptt = container_of(session->auxtrace, struct hisi_ptt, 92 auxtrace); 93 int fd = perf_data__fd(session->data); 94 int size = event->auxtrace.size; 95 void *data = malloc(size); 96 off_t data_offset; 97 int err; 98 99 if (!data) 100 return -errno; 101 102 if (perf_data__is_pipe(session->data)) { 103 data_offset = 0; 104 } else { 105 data_offset = lseek(fd, 0, SEEK_CUR); 106 if (data_offset == -1) { 107 free(data); 108 return -errno; 109 } 110 } 111 112 err = readn(fd, data, size); 113 if (err != (ssize_t)size) { 114 free(data); 115 return -errno; 116 } 117 118 if (dump_trace) 119 hisi_ptt_dump_event(ptt, data, size); 120 121 free(data); 122 return 0; 123} 124 125static int hisi_ptt_flush(struct perf_session *session __maybe_unused, 126 struct perf_tool *tool __maybe_unused) 127{ 128 return 0; 129} 130 131static void hisi_ptt_free_events(struct perf_session *session __maybe_unused) 132{ 133} 134 135static void hisi_ptt_free(struct perf_session *session) 136{ 137 struct hisi_ptt *ptt = container_of(session->auxtrace, struct hisi_ptt, 138 auxtrace); 139 140 session->auxtrace = NULL; 141 free(ptt); 142} 143 144static bool hisi_ptt_evsel_is_auxtrace(struct perf_session *session, 145 struct evsel *evsel) 146{ 147 struct hisi_ptt *ptt = container_of(session->auxtrace, struct hisi_ptt, auxtrace); 148 149 return evsel->core.attr.type == ptt->pmu_type; 150} 151 152static void hisi_ptt_print_info(__u64 type) 153{ 154 if (!dump_trace) 155 return; 156 157 fprintf(stdout, " PMU Type %" PRId64 "\n", (s64) type); 158} 159 160int hisi_ptt_process_auxtrace_info(union perf_event *event, 161 struct perf_session *session) 162{ 163 struct perf_record_auxtrace_info *auxtrace_info = &event->auxtrace_info; 164 struct hisi_ptt *ptt; 165 166 if (auxtrace_info->header.size < HISI_PTT_AUXTRACE_PRIV_SIZE + 167 sizeof(struct perf_record_auxtrace_info)) 168 return -EINVAL; 169 170 ptt = zalloc(sizeof(*ptt)); 171 if (!ptt) 172 return -ENOMEM; 173 174 ptt->session = session; 175 ptt->machine = &session->machines.host; /* No kvm support */ 176 ptt->auxtrace_type = auxtrace_info->type; 177 ptt->pmu_type = auxtrace_info->priv[0]; 178 179 ptt->auxtrace.process_event = hisi_ptt_process_event; 180 ptt->auxtrace.process_auxtrace_event = hisi_ptt_process_auxtrace_event; 181 ptt->auxtrace.flush_events = hisi_ptt_flush; 182 ptt->auxtrace.free_events = hisi_ptt_free_events; 183 ptt->auxtrace.free = hisi_ptt_free; 184 ptt->auxtrace.evsel_is_auxtrace = hisi_ptt_evsel_is_auxtrace; 185 session->auxtrace = &ptt->auxtrace; 186 187 hisi_ptt_print_info(auxtrace_info->priv[0]); 188 189 return 0; 190}