linux/tools/perf/util/arm-spe-decoder/arm-spe-decoder.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * arm_spe_decoder.c: ARM SPE support
   4 */
   5
   6#ifndef _GNU_SOURCE
   7#define _GNU_SOURCE
   8#endif
   9#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 byte
  51                 * (bits [63:56]) is assigned as top-byte tag; so we only can
  52                 * retrieve address value from bits [55:0].
  53                 *
  54                 * According to Documentation/arm64/memory.rst, if detects the
  55                 * specific pattern in bits [55:52] of payload which falls in
  56                 * the kernel space, should fixup the top byte and this allows
  57                 * perf tool to parse DSO symbol for data address correctly.
  58                 *
  59                 * For this reason, if detects the bits [55:52] is 0xf, will
  60                 * 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                pr_err("unsupported address packet index: 0x%x\n", index);
  72        }
  73
  74        return payload;
  75}
  76
  77struct arm_spe_decoder *arm_spe_decoder_new(struct arm_spe_params *params)
  78{
  79        struct arm_spe_decoder *decoder;
  80
  81        if (!params->get_trace)
  82                return NULL;
  83
  84        decoder = zalloc(sizeof(struct arm_spe_decoder));
  85        if (!decoder)
  86                return NULL;
  87
  88        decoder->get_trace = params->get_trace;
  89        decoder->data = params->data;
  90
  91        return decoder;
  92}
  93
  94void arm_spe_decoder_free(struct arm_spe_decoder *decoder)
  95{
  96        free(decoder);
  97}
  98
  99static int arm_spe_get_data(struct arm_spe_decoder *decoder)
 100{
 101        struct arm_spe_buffer buffer = { .buf = 0, };
 102        int ret;
 103
 104        pr_debug("Getting more data\n");
 105        ret = decoder->get_trace(&buffer, decoder->data);
 106        if (ret < 0)
 107                return ret;
 108
 109        decoder->buf = buffer.buf;
 110        decoder->len = buffer.len;
 111
 112        if (!decoder->len)
 113                pr_debug("No more data\n");
 114
 115        return decoder->len;
 116}
 117
 118static int arm_spe_get_next_packet(struct arm_spe_decoder *decoder)
 119{
 120        int ret;
 121
 122        do {
 123                if (!decoder->len) {
 124                        ret = arm_spe_get_data(decoder);
 125
 126                        /* Failed to read out trace data */
 127                        if (ret <= 0)
 128                                return ret;
 129                }
 130
 131                ret = arm_spe_get_packet(decoder->buf, decoder->len,
 132                                         &decoder->packet);
 133                if (ret <= 0) {
 134                        /* Move forward for 1 byte */
 135                        decoder->buf += 1;
 136                        decoder->len -= 1;
 137                        return -EBADMSG;
 138                }
 139
 140                decoder->buf += ret;
 141                decoder->len -= ret;
 142        } while (decoder->packet.type == ARM_SPE_PAD);
 143
 144        return 1;
 145}
 146
 147static int arm_spe_read_record(struct arm_spe_decoder *decoder)
 148{
 149        int err;
 150        int idx;
 151        u64 payload, ip;
 152
 153        memset(&decoder->record, 0x0, sizeof(decoder->record));
 154
 155        while (1) {
 156                err = arm_spe_get_next_packet(decoder);
 157                if (err <= 0)
 158                        return err;
 159
 160                idx = decoder->packet.index;
 161                payload = decoder->packet.payload;
 162
 163                switch (decoder->packet.type) {
 164                case ARM_SPE_TIMESTAMP:
 165                        decoder->record.timestamp = payload;
 166                        return 1;
 167                case ARM_SPE_END:
 168                        return 1;
 169                case ARM_SPE_ADDRESS:
 170                        ip = arm_spe_calc_ip(idx, payload);
 171                        if (idx == SPE_ADDR_PKT_HDR_INDEX_INS)
 172                                decoder->record.from_ip = ip;
 173                        else if (idx == SPE_ADDR_PKT_HDR_INDEX_BRANCH)
 174                                decoder->record.to_ip = ip;
 175                        else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_VIRT)
 176                                decoder->record.virt_addr = ip;
 177                        else if (idx == SPE_ADDR_PKT_HDR_INDEX_DATA_PHYS)
 178                                decoder->record.phys_addr = ip;
 179                        break;
 180                case ARM_SPE_COUNTER:
 181                        break;
 182                case ARM_SPE_CONTEXT:
 183                        break;
 184                case ARM_SPE_OP_TYPE:
 185                        if (idx == SPE_OP_PKT_HDR_CLASS_LD_ST_ATOMIC) {
 186                                if (payload & 0x1)
 187                                        decoder->record.op = ARM_SPE_ST;
 188                                else
 189                                        decoder->record.op = ARM_SPE_LD;
 190                        }
 191                        break;
 192                case ARM_SPE_EVENTS:
 193                        if (payload & BIT(EV_L1D_REFILL))
 194                                decoder->record.type |= ARM_SPE_L1D_MISS;
 195
 196                        if (payload & BIT(EV_L1D_ACCESS))
 197                                decoder->record.type |= ARM_SPE_L1D_ACCESS;
 198
 199                        if (payload & BIT(EV_TLB_WALK))
 200                                decoder->record.type |= ARM_SPE_TLB_MISS;
 201
 202                        if (payload & BIT(EV_TLB_ACCESS))
 203                                decoder->record.type |= ARM_SPE_TLB_ACCESS;
 204
 205                        if (payload & BIT(EV_LLC_MISS))
 206                                decoder->record.type |= ARM_SPE_LLC_MISS;
 207
 208                        if (payload & BIT(EV_LLC_ACCESS))
 209                                decoder->record.type |= ARM_SPE_LLC_ACCESS;
 210
 211                        if (payload & BIT(EV_REMOTE_ACCESS))
 212                                decoder->record.type |= ARM_SPE_REMOTE_ACCESS;
 213
 214                        if (payload & BIT(EV_MISPRED))
 215                                decoder->record.type |= ARM_SPE_BRANCH_MISS;
 216
 217                        break;
 218                case ARM_SPE_DATA_SOURCE:
 219                        break;
 220                case ARM_SPE_BAD:
 221                        break;
 222                case ARM_SPE_PAD:
 223                        break;
 224                default:
 225                        pr_err("Get packet error!\n");
 226                        return -1;
 227                }
 228        }
 229
 230        return 0;
 231}
 232
 233int arm_spe_decode(struct arm_spe_decoder *decoder)
 234{
 235        return arm_spe_read_record(decoder);
 236}
 237