Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/tools/perf/arch/arm64/util/perf_regs.c
26292 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <errno.h>
3
#include <regex.h>
4
#include <string.h>
5
#include <sys/auxv.h>
6
#include <linux/kernel.h>
7
#include <linux/zalloc.h>
8
9
#include "perf_regs.h"
10
#include "../../../perf-sys.h"
11
#include "../../../util/debug.h"
12
#include "../../../util/event.h"
13
#include "../../../util/perf_regs.h"
14
15
#ifndef HWCAP_SVE
16
#define HWCAP_SVE (1 << 22)
17
#endif
18
19
static const struct sample_reg sample_reg_masks[] = {
20
SMPL_REG(x0, PERF_REG_ARM64_X0),
21
SMPL_REG(x1, PERF_REG_ARM64_X1),
22
SMPL_REG(x2, PERF_REG_ARM64_X2),
23
SMPL_REG(x3, PERF_REG_ARM64_X3),
24
SMPL_REG(x4, PERF_REG_ARM64_X4),
25
SMPL_REG(x5, PERF_REG_ARM64_X5),
26
SMPL_REG(x6, PERF_REG_ARM64_X6),
27
SMPL_REG(x7, PERF_REG_ARM64_X7),
28
SMPL_REG(x8, PERF_REG_ARM64_X8),
29
SMPL_REG(x9, PERF_REG_ARM64_X9),
30
SMPL_REG(x10, PERF_REG_ARM64_X10),
31
SMPL_REG(x11, PERF_REG_ARM64_X11),
32
SMPL_REG(x12, PERF_REG_ARM64_X12),
33
SMPL_REG(x13, PERF_REG_ARM64_X13),
34
SMPL_REG(x14, PERF_REG_ARM64_X14),
35
SMPL_REG(x15, PERF_REG_ARM64_X15),
36
SMPL_REG(x16, PERF_REG_ARM64_X16),
37
SMPL_REG(x17, PERF_REG_ARM64_X17),
38
SMPL_REG(x18, PERF_REG_ARM64_X18),
39
SMPL_REG(x19, PERF_REG_ARM64_X19),
40
SMPL_REG(x20, PERF_REG_ARM64_X20),
41
SMPL_REG(x21, PERF_REG_ARM64_X21),
42
SMPL_REG(x22, PERF_REG_ARM64_X22),
43
SMPL_REG(x23, PERF_REG_ARM64_X23),
44
SMPL_REG(x24, PERF_REG_ARM64_X24),
45
SMPL_REG(x25, PERF_REG_ARM64_X25),
46
SMPL_REG(x26, PERF_REG_ARM64_X26),
47
SMPL_REG(x27, PERF_REG_ARM64_X27),
48
SMPL_REG(x28, PERF_REG_ARM64_X28),
49
SMPL_REG(x29, PERF_REG_ARM64_X29),
50
SMPL_REG(lr, PERF_REG_ARM64_LR),
51
SMPL_REG(sp, PERF_REG_ARM64_SP),
52
SMPL_REG(pc, PERF_REG_ARM64_PC),
53
SMPL_REG(vg, PERF_REG_ARM64_VG),
54
SMPL_REG_END
55
};
56
57
/* %xNUM */
58
#define SDT_OP_REGEX1 "^(x[1-2]?[0-9]|3[0-1])$"
59
60
/* [sp], [sp, NUM] */
61
#define SDT_OP_REGEX2 "^\\[sp(, )?([0-9]+)?\\]$"
62
63
static regex_t sdt_op_regex1, sdt_op_regex2;
64
65
static int sdt_init_op_regex(void)
66
{
67
static int initialized;
68
int ret = 0;
69
70
if (initialized)
71
return 0;
72
73
ret = regcomp(&sdt_op_regex1, SDT_OP_REGEX1, REG_EXTENDED);
74
if (ret)
75
goto error;
76
77
ret = regcomp(&sdt_op_regex2, SDT_OP_REGEX2, REG_EXTENDED);
78
if (ret)
79
goto free_regex1;
80
81
initialized = 1;
82
return 0;
83
84
free_regex1:
85
regfree(&sdt_op_regex1);
86
error:
87
pr_debug4("Regex compilation error.\n");
88
return ret;
89
}
90
91
/*
92
* SDT marker arguments on Arm64 uses %xREG or [sp, NUM], currently
93
* support these two formats.
94
*/
95
int arch_sdt_arg_parse_op(char *old_op, char **new_op)
96
{
97
int ret, new_len;
98
regmatch_t rm[5];
99
100
ret = sdt_init_op_regex();
101
if (ret < 0)
102
return ret;
103
104
if (!regexec(&sdt_op_regex1, old_op, 3, rm, 0)) {
105
/* Extract xNUM */
106
new_len = 2; /* % NULL */
107
new_len += (int)(rm[1].rm_eo - rm[1].rm_so);
108
109
*new_op = zalloc(new_len);
110
if (!*new_op)
111
return -ENOMEM;
112
113
scnprintf(*new_op, new_len, "%%%.*s",
114
(int)(rm[1].rm_eo - rm[1].rm_so), old_op + rm[1].rm_so);
115
} else if (!regexec(&sdt_op_regex2, old_op, 5, rm, 0)) {
116
/* [sp], [sp, NUM] or [sp,NUM] */
117
new_len = 7; /* + ( % s p ) NULL */
118
119
/* If the argument is [sp], need to fill offset '0' */
120
if (rm[2].rm_so == -1)
121
new_len += 1;
122
else
123
new_len += (int)(rm[2].rm_eo - rm[2].rm_so);
124
125
*new_op = zalloc(new_len);
126
if (!*new_op)
127
return -ENOMEM;
128
129
if (rm[2].rm_so == -1)
130
scnprintf(*new_op, new_len, "+0(%%sp)");
131
else
132
scnprintf(*new_op, new_len, "+%.*s(%%sp)",
133
(int)(rm[2].rm_eo - rm[2].rm_so),
134
old_op + rm[2].rm_so);
135
} else {
136
pr_debug4("Skipping unsupported SDT argument: %s\n", old_op);
137
return SDT_ARG_SKIP;
138
}
139
140
return SDT_ARG_VALID;
141
}
142
143
uint64_t arch__intr_reg_mask(void)
144
{
145
return PERF_REGS_MASK;
146
}
147
148
uint64_t arch__user_reg_mask(void)
149
{
150
struct perf_event_attr attr = {
151
.type = PERF_TYPE_HARDWARE,
152
.config = PERF_COUNT_HW_CPU_CYCLES,
153
.sample_type = PERF_SAMPLE_REGS_USER,
154
.disabled = 1,
155
.exclude_kernel = 1,
156
.sample_period = 1,
157
.sample_regs_user = PERF_REGS_MASK
158
};
159
int fd;
160
161
if (getauxval(AT_HWCAP) & HWCAP_SVE)
162
attr.sample_regs_user |= SMPL_REG_MASK(PERF_REG_ARM64_VG);
163
164
/*
165
* Check if the pmu supports perf extended regs, before
166
* returning the register mask to sample.
167
*/
168
if (attr.sample_regs_user != PERF_REGS_MASK) {
169
event_attr_init(&attr);
170
fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
171
if (fd != -1) {
172
close(fd);
173
return attr.sample_regs_user;
174
}
175
}
176
return PERF_REGS_MASK;
177
}
178
179
const struct sample_reg *arch__sample_reg_masks(void)
180
{
181
return sample_reg_masks;
182
}
183
184