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