268 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * arm_spe_decoder.c: ARM SPE support4 */5 6#ifndef _GNU_SOURCE7#define _GNU_SOURCE8#endif9#include <errno.h>10#include <inttypes.h>11#include <stdbool.h>12#include <string.h>13#include <stdint.h>14#include <stdlib.h>15#include <linux/bitops.h>16#include <linux/compiler.h>17#include <linux/zalloc.h>18 19#include "../auxtrace.h"20#include "../debug.h"21#include "../util.h"22 23#include "arm-spe-decoder.h"24 25static u64 arm_spe_calc_ip(int index, u64 payload)26{27 u64 ns, el, val;28 29 /* Instruction virtual address or Branch target address */30 if (index == SPE_ADDR_PKT_HDR_INDEX_INS ||31 index == SPE_ADDR_PKT_HDR_INDEX_BRANCH) {32 ns = SPE_ADDR_PKT_GET_NS(payload);33 el = SPE_ADDR_PKT_GET_EL(payload);34 35 /* Clean highest byte */36 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);37 38 /* Fill highest byte for EL1 or EL2 (VHE) mode */39 if (ns && (el == SPE_ADDR_PKT_EL1 || el == SPE_ADDR_PKT_EL2))40 payload |= 0xffULL << SPE_ADDR_PKT_ADDR_BYTE7_SHIFT;41 42 /* Data access virtual address */43 } else if (index == SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT) {44 45 /* Clean tags */46 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);47 48 /*49 * Armv8 ARM (ARM DDI 0487F.c), chapter "D10.2.1 Address packet"50 * defines the data virtual address payload format, the top byte51 * (bits [63:56]) is assigned as top-byte tag; so we only can52 * retrieve address value from bits [55:0].53 *54 * According to Documentation/arch/arm64/memory.rst, if detects the55 * specific pattern in bits [55:52] of payload which falls in56 * the kernel space, should fixup the top byte and this allows57 * perf tool to parse DSO symbol for data address correctly.58 *59 * For this reason, if detects the bits [55:52] is 0xf, will60 * fill 0xff into the top byte.61 */62 val = SPE_ADDR_PKT_ADDR_GET_BYTE_6(payload);63 if ((val & 0xf0ULL) == 0xf0ULL)64 payload |= 0xffULL << SPE_ADDR_PKT_ADDR_BYTE7_SHIFT;65 66 /* Data access physical address */67 } else if (index == SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS) {68 /* Clean highest byte */69 payload = SPE_ADDR_PKT_ADDR_GET_BYTES_0_6(payload);70 } else {71 static u32 seen_idx = 0;72 if (!(seen_idx & BIT(index))) {73 seen_idx |= BIT(index);74 pr_warning("ignoring unsupported address packet index: 0x%x\n", index);75 }76 }77 78 return payload;79}80 81struct arm_spe_decoder *arm_spe_decoder_new(struct arm_spe_params *params)82{83 struct arm_spe_decoder *decoder;84 85 if (!params->get_trace)86 return NULL;87 88 decoder = zalloc(sizeof(struct arm_spe_decoder));89 if (!decoder)90 return NULL;91 92 decoder->get_trace = params->get_trace;93 decoder->data = params->data;94 95 return decoder;96}97 98void arm_spe_decoder_free(struct arm_spe_decoder *decoder)99{100 free(decoder);101}102 103static int arm_spe_get_data(struct arm_spe_decoder *decoder)104{105 struct arm_spe_buffer buffer = { .buf = 0, };106 int ret;107 108 pr_debug("Getting more data\n");109 ret = decoder->get_trace(&buffer, decoder->data);110 if (ret < 0)111 return ret;112 113 decoder->buf = buffer.buf;114 decoder->len = buffer.len;115 116 if (!decoder->len)117 pr_debug("No more data\n");118 119 return decoder->len;120}121 122static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder)123{124 int ret;125 126 do {127 if (!decoder->len) {128 ret = arm_spe_get_data(decoder);129 130 /* Failed to read out trace data */131 if (ret <= 0)132 return ret;133 }134 135 ret = arm_spe_get_packet(decoder->buf, decoder->len,136 &decoder->packet);137 if (ret <= 0) {138 /* Move forward for 1 byte */139 decoder->buf += 1;140 decoder->len -= 1;141 return -EBADMSG;142 }143 144 decoder->buf += ret;145 decoder->len -= ret;146 } while (decoder->packet.type == ARM_SPE_PAD);147 148 return 1;149}150 151static int arm_spe_read_record(struct arm_spe_decoder *decoder)152{153 int err;154 int idx;155 u64 payload, ip;156 157 memset(&decoder->record, 0x0, sizeof(decoder->record));158 decoder->record.context_id = (u64)-1;159 160 while (1) {161 err = arm_spe_get_next_packet(decoder);162 if (err <= 0)163 return err;164 165 idx = decoder->packet.index;166 payload = decoder->packet.payload;167 168 switch (decoder->packet.type) {169 case ARM_SPE_TIMESTAMP:170 decoder->record.timestamp = payload;171 return 1;172 case ARM_SPE_END:173 return 1;174 case ARM_SPE_ADDRESS:175 ip = arm_spe_calc_ip(idx, payload);176 if (idx == SPE_ADDR_PKT_HDR_INDEX_INS)177 decoder->record.from_ip = ip;178 else if (idx == SPE_ADDR_PKT_HDR_INDEX_BRANCH)179 decoder->record.to_ip = ip;180 else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT)181 decoder->record.virt_addr = ip;182 else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS)183 decoder->record.phys_addr = ip;184 break;185 case ARM_SPE_COUNTER:186 if (idx == SPE_CNT_PKT_HDR_INDEX_TOTAL_LAT)187 decoder->record.latency = payload;188 break;189 case ARM_SPE_CONTEXT:190 decoder->record.context_id = payload;191 break;192 case ARM_SPE_OP_TYPE:193 switch (idx) {194 case SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC:195 decoder->record.op |= ARM_SPE_OP_LDST;196 if (payload & SPE_OP_PKT_ST)197 decoder->record.op |= ARM_SPE_OP_ST;198 else199 decoder->record.op |= ARM_SPE_OP_LD;200 if (SPE_OP_PKT_IS_LDST_SVE(payload))201 decoder->record.op |= ARM_SPE_OP_SVE_LDST;202 break;203 case SPE_OP_PKT_HDR_CLASS_OTHER:204 decoder->record.op |= ARM_SPE_OP_OTHER;205 if (SPE_OP_PKT_IS_OTHER_SVE_OP(payload))206 decoder->record.op |= ARM_SPE_OP_SVE_OTHER;207 break;208 case SPE_OP_PKT_HDR_CLASS_BR_ERET:209 decoder->record.op |= ARM_SPE_OP_BRANCH_ERET;210 break;211 default:212 pr_err("Get packet error!\n");213 return -1;214 }215 break;216 case ARM_SPE_EVENTS:217 if (payload & BIT(EV_L1D_REFILL))218 decoder->record.type |= ARM_SPE_L1D_MISS;219 220 if (payload & BIT(EV_L1D_ACCESS))221 decoder->record.type |= ARM_SPE_L1D_ACCESS;222 223 if (payload & BIT(EV_TLB_WALK))224 decoder->record.type |= ARM_SPE_TLB_MISS;225 226 if (payload & BIT(EV_TLB_ACCESS))227 decoder->record.type |= ARM_SPE_TLB_ACCESS;228 229 if (payload & BIT(EV_LLC_MISS))230 decoder->record.type |= ARM_SPE_LLC_MISS;231 232 if (payload & BIT(EV_LLC_ACCESS))233 decoder->record.type |= ARM_SPE_LLC_ACCESS;234 235 if (payload & BIT(EV_REMOTE_ACCESS))236 decoder->record.type |= ARM_SPE_REMOTE_ACCESS;237 238 if (payload & BIT(EV_MISPRED))239 decoder->record.type |= ARM_SPE_BRANCH_MISS;240 241 if (payload & BIT(EV_PARTIAL_PREDICATE))242 decoder->record.type |= ARM_SPE_SVE_PARTIAL_PRED;243 244 if (payload & BIT(EV_EMPTY_PREDICATE))245 decoder->record.type |= ARM_SPE_SVE_EMPTY_PRED;246 247 break;248 case ARM_SPE_DATA_SOURCE:249 decoder->record.source = payload;250 break;251 case ARM_SPE_BAD:252 break;253 case ARM_SPE_PAD:254 break;255 default:256 pr_err("Get packet error!\n");257 return -1;258 }259 }260 261 return 0;262}263 264int arm_spe_decode(struct arm_spe_decoder *decoder)265{266 return arm_spe_read_record(decoder);267}268