1 | // SPDX-License-Identifier: GPL-2.0 |
2 | #include <asm/insn.h> |
3 | #include <linux/mm.h> |
4 | |
5 | #include "perf_event.h" |
6 | |
7 | static int decode_branch_type(struct insn *insn) |
8 | { |
9 | int ext; |
10 | |
11 | if (insn_get_opcode(insn)) |
12 | return X86_BR_ABORT; |
13 | |
14 | switch (insn->opcode.bytes[0]) { |
15 | case 0xf: |
16 | switch (insn->opcode.bytes[1]) { |
17 | case 0x05: /* syscall */ |
18 | case 0x34: /* sysenter */ |
19 | return X86_BR_SYSCALL; |
20 | case 0x07: /* sysret */ |
21 | case 0x35: /* sysexit */ |
22 | return X86_BR_SYSRET; |
23 | case 0x80 ... 0x8f: /* conditional */ |
24 | return X86_BR_JCC; |
25 | } |
26 | return X86_BR_NONE; |
27 | case 0x70 ... 0x7f: /* conditional */ |
28 | return X86_BR_JCC; |
29 | case 0xc2: /* near ret */ |
30 | case 0xc3: /* near ret */ |
31 | case 0xca: /* far ret */ |
32 | case 0xcb: /* far ret */ |
33 | return X86_BR_RET; |
34 | case 0xcf: /* iret */ |
35 | return X86_BR_IRET; |
36 | case 0xcc ... 0xce: /* int */ |
37 | return X86_BR_INT; |
38 | case 0xe8: /* call near rel */ |
39 | if (insn_get_immediate(insn) || insn->immediate1.value == 0) { |
40 | /* zero length call */ |
41 | return X86_BR_ZERO_CALL; |
42 | } |
43 | fallthrough; |
44 | case 0x9a: /* call far absolute */ |
45 | return X86_BR_CALL; |
46 | case 0xe0 ... 0xe3: /* loop jmp */ |
47 | return X86_BR_JCC; |
48 | case 0xe9 ... 0xeb: /* jmp */ |
49 | return X86_BR_JMP; |
50 | case 0xff: /* call near absolute, call far absolute ind */ |
51 | if (insn_get_modrm(insn)) |
52 | return X86_BR_ABORT; |
53 | |
54 | ext = (insn->modrm.bytes[0] >> 3) & 0x7; |
55 | switch (ext) { |
56 | case 2: /* near ind call */ |
57 | case 3: /* far ind call */ |
58 | return X86_BR_IND_CALL; |
59 | case 4: |
60 | case 5: |
61 | return X86_BR_IND_JMP; |
62 | } |
63 | return X86_BR_NONE; |
64 | } |
65 | |
66 | return X86_BR_NONE; |
67 | } |
68 | |
69 | /* |
70 | * return the type of control flow change at address "from" |
71 | * instruction is not necessarily a branch (in case of interrupt). |
72 | * |
73 | * The branch type returned also includes the priv level of the |
74 | * target of the control flow change (X86_BR_USER, X86_BR_KERNEL). |
75 | * |
76 | * If a branch type is unknown OR the instruction cannot be |
77 | * decoded (e.g., text page not present), then X86_BR_NONE is |
78 | * returned. |
79 | * |
80 | * While recording branches, some processors can report the "from" |
81 | * address to be that of an instruction preceding the actual branch |
82 | * when instruction fusion occurs. If fusion is expected, attempt to |
83 | * find the type of the first branch instruction within the next |
84 | * MAX_INSN_SIZE bytes and if found, provide the offset between the |
85 | * reported "from" address and the actual branch instruction address. |
86 | */ |
87 | static int get_branch_type(unsigned long from, unsigned long to, int abort, |
88 | bool fused, int *offset) |
89 | { |
90 | struct insn insn; |
91 | void *addr; |
92 | int bytes_read, bytes_left, insn_offset; |
93 | int ret = X86_BR_NONE; |
94 | int to_plm, from_plm; |
95 | u8 buf[MAX_INSN_SIZE]; |
96 | int is64 = 0; |
97 | |
98 | /* make sure we initialize offset */ |
99 | if (offset) |
100 | *offset = 0; |
101 | |
102 | to_plm = kernel_ip(ip: to) ? X86_BR_KERNEL : X86_BR_USER; |
103 | from_plm = kernel_ip(ip: from) ? X86_BR_KERNEL : X86_BR_USER; |
104 | |
105 | /* |
106 | * maybe zero if lbr did not fill up after a reset by the time |
107 | * we get a PMU interrupt |
108 | */ |
109 | if (from == 0 || to == 0) |
110 | return X86_BR_NONE; |
111 | |
112 | if (abort) |
113 | return X86_BR_ABORT | to_plm; |
114 | |
115 | if (from_plm == X86_BR_USER) { |
116 | /* |
117 | * can happen if measuring at the user level only |
118 | * and we interrupt in a kernel thread, e.g., idle. |
119 | */ |
120 | if (!current->mm) |
121 | return X86_BR_NONE; |
122 | |
123 | /* may fail if text not present */ |
124 | bytes_left = copy_from_user_nmi(to: buf, from: (void __user *)from, |
125 | MAX_INSN_SIZE); |
126 | bytes_read = MAX_INSN_SIZE - bytes_left; |
127 | if (!bytes_read) |
128 | return X86_BR_NONE; |
129 | |
130 | addr = buf; |
131 | } else { |
132 | /* |
133 | * The LBR logs any address in the IP, even if the IP just |
134 | * faulted. This means userspace can control the from address. |
135 | * Ensure we don't blindly read any address by validating it is |
136 | * a known text address and not a vsyscall address. |
137 | */ |
138 | if (kernel_text_address(addr: from) && !in_gate_area_no_mm(addr: from)) { |
139 | addr = (void *)from; |
140 | /* |
141 | * Assume we can get the maximum possible size |
142 | * when grabbing kernel data. This is not |
143 | * _strictly_ true since we could possibly be |
144 | * executing up next to a memory hole, but |
145 | * it is very unlikely to be a problem. |
146 | */ |
147 | bytes_read = MAX_INSN_SIZE; |
148 | } else { |
149 | return X86_BR_NONE; |
150 | } |
151 | } |
152 | |
153 | /* |
154 | * decoder needs to know the ABI especially |
155 | * on 64-bit systems running 32-bit apps |
156 | */ |
157 | #ifdef CONFIG_X86_64 |
158 | is64 = kernel_ip(ip: (unsigned long)addr) || any_64bit_mode(current_pt_regs()); |
159 | #endif |
160 | insn_init(insn: &insn, kaddr: addr, buf_len: bytes_read, x86_64: is64); |
161 | ret = decode_branch_type(insn: &insn); |
162 | insn_offset = 0; |
163 | |
164 | /* Check for the possibility of branch fusion */ |
165 | while (fused && ret == X86_BR_NONE) { |
166 | /* Check for decoding errors */ |
167 | if (insn_get_length(insn: &insn) || !insn.length) |
168 | break; |
169 | |
170 | insn_offset += insn.length; |
171 | bytes_read -= insn.length; |
172 | if (bytes_read < 0) |
173 | break; |
174 | |
175 | insn_init(insn: &insn, kaddr: addr + insn_offset, buf_len: bytes_read, x86_64: is64); |
176 | ret = decode_branch_type(insn: &insn); |
177 | } |
178 | |
179 | if (offset) |
180 | *offset = insn_offset; |
181 | |
182 | /* |
183 | * interrupts, traps, faults (and thus ring transition) may |
184 | * occur on any instructions. Thus, to classify them correctly, |
185 | * we need to first look at the from and to priv levels. If they |
186 | * are different and to is in the kernel, then it indicates |
187 | * a ring transition. If the from instruction is not a ring |
188 | * transition instr (syscall, systenter, int), then it means |
189 | * it was a irq, trap or fault. |
190 | * |
191 | * we have no way of detecting kernel to kernel faults. |
192 | */ |
193 | if (from_plm == X86_BR_USER && to_plm == X86_BR_KERNEL |
194 | && ret != X86_BR_SYSCALL && ret != X86_BR_INT) |
195 | ret = X86_BR_IRQ; |
196 | |
197 | /* |
198 | * branch priv level determined by target as |
199 | * is done by HW when LBR_SELECT is implemented |
200 | */ |
201 | if (ret != X86_BR_NONE) |
202 | ret |= to_plm; |
203 | |
204 | return ret; |
205 | } |
206 | |
207 | int branch_type(unsigned long from, unsigned long to, int abort) |
208 | { |
209 | return get_branch_type(from, to, abort, fused: false, NULL); |
210 | } |
211 | |
212 | int branch_type_fused(unsigned long from, unsigned long to, int abort, |
213 | int *offset) |
214 | { |
215 | return get_branch_type(from, to, abort, fused: true, offset); |
216 | } |
217 | |
218 | #define X86_BR_TYPE_MAP_MAX 16 |
219 | |
220 | static int branch_map[X86_BR_TYPE_MAP_MAX] = { |
221 | PERF_BR_CALL, /* X86_BR_CALL */ |
222 | PERF_BR_RET, /* X86_BR_RET */ |
223 | PERF_BR_SYSCALL, /* X86_BR_SYSCALL */ |
224 | PERF_BR_SYSRET, /* X86_BR_SYSRET */ |
225 | PERF_BR_UNKNOWN, /* X86_BR_INT */ |
226 | PERF_BR_ERET, /* X86_BR_IRET */ |
227 | PERF_BR_COND, /* X86_BR_JCC */ |
228 | PERF_BR_UNCOND, /* X86_BR_JMP */ |
229 | PERF_BR_IRQ, /* X86_BR_IRQ */ |
230 | PERF_BR_IND_CALL, /* X86_BR_IND_CALL */ |
231 | PERF_BR_UNKNOWN, /* X86_BR_ABORT */ |
232 | PERF_BR_UNKNOWN, /* X86_BR_IN_TX */ |
233 | PERF_BR_NO_TX, /* X86_BR_NO_TX */ |
234 | PERF_BR_CALL, /* X86_BR_ZERO_CALL */ |
235 | PERF_BR_UNKNOWN, /* X86_BR_CALL_STACK */ |
236 | PERF_BR_IND, /* X86_BR_IND_JMP */ |
237 | }; |
238 | |
239 | int common_branch_type(int type) |
240 | { |
241 | int i; |
242 | |
243 | type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */ |
244 | |
245 | if (type) { |
246 | i = __ffs(type); |
247 | if (i < X86_BR_TYPE_MAP_MAX) |
248 | return branch_map[i]; |
249 | } |
250 | |
251 | return PERF_BR_UNKNOWN; |
252 | } |
253 | |