gdb: clean up x86 cpuid implementations
[deliverable/binutils-gdb.git] / gdb / common / linux-btrace.c
1 /* Linux-dependent part of branch trace support for GDB, and GDBserver.
2
3 Copyright (C) 2013 Free Software Foundation, Inc.
4
5 Contributed by Intel Corp. <markus.t.metzger@intel.com>
6
7 This file is part of GDB.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21
22 #ifdef GDBSERVER
23 #include "server.h"
24 #else
25 #include "defs.h"
26 #endif
27
28 #include "linux-btrace.h"
29 #include "common-utils.h"
30 #include "gdb_assert.h"
31 #include "regcache.h"
32 #include "gdbthread.h"
33 #include "gdb_wait.h"
34 #include "i386-cpuid.h"
35
36 #if HAVE_LINUX_PERF_EVENT_H
37
38 #include <errno.h>
39 #include <string.h>
40 #include <stdint.h>
41 #include <unistd.h>
42 #include <sys/syscall.h>
43 #include <sys/mman.h>
44 #include <sys/user.h>
45 #include <sys/ptrace.h>
46 #include <sys/types.h>
47 #include <signal.h>
48
49 /* A branch trace record in perf_event. */
50 struct perf_event_bts
51 {
52 /* The linear address of the branch source. */
53 uint64_t from;
54
55 /* The linear address of the branch destination. */
56 uint64_t to;
57 };
58
59 /* A perf_event branch trace sample. */
60 struct perf_event_sample
61 {
62 /* The perf_event sample header. */
63 struct perf_event_header header;
64
65 /* The perf_event branch tracing payload. */
66 struct perf_event_bts bts;
67 };
68
69 /* Get the perf_event header. */
70
71 static inline volatile struct perf_event_mmap_page *
72 perf_event_header (struct btrace_target_info* tinfo)
73 {
74 return tinfo->buffer;
75 }
76
77 /* Get the size of the perf_event mmap buffer. */
78
79 static inline size_t
80 perf_event_mmap_size (const struct btrace_target_info *tinfo)
81 {
82 /* The branch trace buffer is preceded by a configuration page. */
83 return (tinfo->size + 1) * PAGE_SIZE;
84 }
85
86 /* Get the size of the perf_event buffer. */
87
88 static inline size_t
89 perf_event_buffer_size (struct btrace_target_info* tinfo)
90 {
91 return tinfo->size * PAGE_SIZE;
92 }
93
94 /* Get the start address of the perf_event buffer. */
95
96 static inline const uint8_t *
97 perf_event_buffer_begin (struct btrace_target_info* tinfo)
98 {
99 return ((const uint8_t *) tinfo->buffer) + PAGE_SIZE;
100 }
101
102 /* Get the end address of the perf_event buffer. */
103
104 static inline const uint8_t *
105 perf_event_buffer_end (struct btrace_target_info* tinfo)
106 {
107 return perf_event_buffer_begin (tinfo) + perf_event_buffer_size (tinfo);
108 }
109
110 /* Check whether an address is in the kernel. */
111
112 static inline int
113 perf_event_is_kernel_addr (const struct btrace_target_info *tinfo,
114 uint64_t addr)
115 {
116 uint64_t mask;
117
118 /* If we don't know the size of a pointer, we can't check. Let's assume it's
119 not a kernel address in this case. */
120 if (tinfo->ptr_bits == 0)
121 return 0;
122
123 /* A bit mask for the most significant bit in an address. */
124 mask = (uint64_t) 1 << (tinfo->ptr_bits - 1);
125
126 /* Check whether the most significant bit in the address is set. */
127 return (addr & mask) != 0;
128 }
129
130 /* Check whether a perf event record should be skipped. */
131
132 static inline int
133 perf_event_skip_record (const struct btrace_target_info *tinfo,
134 const struct perf_event_bts *bts)
135 {
136 /* The hardware may report branches from kernel into user space. Branches
137 from user into kernel space will be suppressed. We filter the former to
138 provide a consistent branch trace excluding kernel. */
139 return perf_event_is_kernel_addr (tinfo, bts->from);
140 }
141
142 /* Perform a few consistency checks on a perf event sample record. This is
143 meant to catch cases when we get out of sync with the perf event stream. */
144
145 static inline int
146 perf_event_sample_ok (const struct perf_event_sample *sample)
147 {
148 if (sample->header.type != PERF_RECORD_SAMPLE)
149 return 0;
150
151 if (sample->header.size != sizeof (*sample))
152 return 0;
153
154 return 1;
155 }
156
157 /* Branch trace is collected in a circular buffer [begin; end) as pairs of from
158 and to addresses (plus a header).
159
160 Start points into that buffer at the next sample position.
161 We read the collected samples backwards from start.
162
163 While reading the samples, we convert the information into a list of blocks.
164 For two adjacent samples s1 and s2, we form a block b such that b.begin =
165 s1.to and b.end = s2.from.
166
167 In case the buffer overflows during sampling, one sample may have its lower
168 part at the end and its upper part at the beginning of the buffer. */
169
170 static VEC (btrace_block_s) *
171 perf_event_read_bts (struct btrace_target_info* tinfo, const uint8_t *begin,
172 const uint8_t *end, const uint8_t *start)
173 {
174 VEC (btrace_block_s) *btrace = NULL;
175 struct perf_event_sample sample;
176 size_t read = 0, size = (end - begin);
177 struct btrace_block block = { 0, 0 };
178 struct regcache *regcache;
179
180 gdb_assert (begin <= start);
181 gdb_assert (start <= end);
182
183 /* The first block ends at the current pc. */
184 #ifdef GDBSERVER
185 regcache = get_thread_regcache (find_thread_ptid (tinfo->ptid), 1);
186 #else
187 regcache = get_thread_regcache (tinfo->ptid);
188 #endif
189 block.end = regcache_read_pc (regcache);
190
191 /* The buffer may contain a partial record as its last entry (i.e. when the
192 buffer size is not a multiple of the sample size). */
193 read = sizeof (sample) - 1;
194
195 for (; read < size; read += sizeof (sample))
196 {
197 const struct perf_event_sample *psample;
198
199 /* Find the next perf_event sample in a backwards traversal. */
200 start -= sizeof (sample);
201
202 /* If we're still inside the buffer, we're done. */
203 if (begin <= start)
204 psample = (const struct perf_event_sample *) start;
205 else
206 {
207 int missing;
208
209 /* We're to the left of the ring buffer, we will wrap around and
210 reappear at the very right of the ring buffer. */
211
212 missing = (begin - start);
213 start = (end - missing);
214
215 /* If the entire sample is missing, we're done. */
216 if (missing == sizeof (sample))
217 psample = (const struct perf_event_sample *) start;
218 else
219 {
220 uint8_t *stack;
221
222 /* The sample wrapped around. The lower part is at the end and
223 the upper part is at the beginning of the buffer. */
224 stack = (uint8_t *) &sample;
225
226 /* Copy the two parts so we have a contiguous sample. */
227 memcpy (stack, start, missing);
228 memcpy (stack + missing, begin, sizeof (sample) - missing);
229
230 psample = &sample;
231 }
232 }
233
234 if (!perf_event_sample_ok (psample))
235 {
236 warning (_("Branch trace may be incomplete."));
237 break;
238 }
239
240 if (perf_event_skip_record (tinfo, &psample->bts))
241 continue;
242
243 /* We found a valid sample, so we can complete the current block. */
244 block.begin = psample->bts.to;
245
246 VEC_safe_push (btrace_block_s, btrace, &block);
247
248 /* Start the next block. */
249 block.end = psample->bts.from;
250 }
251
252 return btrace;
253 }
254
255 /* Check whether the kernel supports branch tracing. */
256
257 static int
258 kernel_supports_btrace (void)
259 {
260 struct perf_event_attr attr;
261 pid_t child, pid;
262 int status, file;
263
264 errno = 0;
265 child = fork ();
266 switch (child)
267 {
268 case -1:
269 warning (_("test branch tracing: cannot fork: %s."), strerror (errno));
270 return 0;
271
272 case 0:
273 status = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
274 if (status != 0)
275 {
276 warning (_("test branch tracing: cannot PTRACE_TRACEME: %s."),
277 strerror (errno));
278 _exit (1);
279 }
280
281 status = raise (SIGTRAP);
282 if (status != 0)
283 {
284 warning (_("test branch tracing: cannot raise SIGTRAP: %s."),
285 strerror (errno));
286 _exit (1);
287 }
288
289 _exit (1);
290
291 default:
292 pid = waitpid (child, &status, 0);
293 if (pid != child)
294 {
295 warning (_("test branch tracing: bad pid %ld, error: %s."),
296 (long) pid, strerror (errno));
297 return 0;
298 }
299
300 if (!WIFSTOPPED (status))
301 {
302 warning (_("test branch tracing: expected stop. status: %d."),
303 status);
304 return 0;
305 }
306
307 memset (&attr, 0, sizeof (attr));
308
309 attr.type = PERF_TYPE_HARDWARE;
310 attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
311 attr.sample_period = 1;
312 attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
313 attr.exclude_kernel = 1;
314 attr.exclude_hv = 1;
315 attr.exclude_idle = 1;
316
317 file = syscall (SYS_perf_event_open, &attr, child, -1, -1, 0);
318 if (file >= 0)
319 close (file);
320
321 kill (child, SIGKILL);
322 ptrace (PTRACE_KILL, child, NULL, NULL);
323
324 pid = waitpid (child, &status, 0);
325 if (pid != child)
326 {
327 warning (_("test branch tracing: bad pid %ld, error: %s."),
328 (long) pid, strerror (errno));
329 if (!WIFSIGNALED (status))
330 warning (_("test branch tracing: expected killed. status: %d."),
331 status);
332 }
333
334 return (file >= 0);
335 }
336 }
337
338 /* Check whether an Intel cpu supports branch tracing. */
339
340 static int
341 intel_supports_btrace (void)
342 {
343 unsigned int cpuid, model, family;
344
345 if (!i386_cpuid (1, &cpuid, NULL, NULL, NULL))
346 return 0;
347
348 family = (cpuid >> 8) & 0xf;
349 model = (cpuid >> 4) & 0xf;
350
351 switch (family)
352 {
353 case 0x6:
354 model += (cpuid >> 12) & 0xf0;
355
356 switch (model)
357 {
358 case 0x1a: /* Nehalem */
359 case 0x1f:
360 case 0x1e:
361 case 0x2e:
362 case 0x25: /* Westmere */
363 case 0x2c:
364 case 0x2f:
365 case 0x2a: /* Sandy Bridge */
366 case 0x2d:
367 case 0x3a: /* Ivy Bridge */
368
369 /* AAJ122: LBR, BTM, or BTS records may have incorrect branch
370 "from" information afer an EIST transition, T-states, C1E, or
371 Adaptive Thermal Throttling. */
372 return 0;
373 }
374 }
375
376 return 1;
377 }
378
379 /* Check whether the cpu supports branch tracing. */
380
381 static int
382 cpu_supports_btrace (void)
383 {
384 unsigned int ebx, ecx, edx;
385 char vendor[13];
386
387 if (!i386_cpuid (0, NULL, &ebx, &ecx, &edx))
388 return 0;
389
390 memcpy (&vendor[0], &ebx, 4);
391 memcpy (&vendor[4], &ecx, 4);
392 memcpy (&vendor[8], &edx, 4);
393 vendor[12] = '\0';
394
395 if (strcmp (vendor, "GenuineIntel") == 0)
396 return intel_supports_btrace ();
397
398 /* Don't know about others. Let's assume they do. */
399 return 1;
400 }
401
402 /* See linux-btrace.h. */
403
404 int
405 linux_supports_btrace (void)
406 {
407 static int cached;
408
409 if (cached == 0)
410 {
411 if (!kernel_supports_btrace ())
412 cached = -1;
413 else if (!cpu_supports_btrace ())
414 cached = -1;
415 else
416 cached = 1;
417 }
418
419 return cached > 0;
420 }
421
422 /* See linux-btrace.h. */
423
424 struct btrace_target_info *
425 linux_enable_btrace (ptid_t ptid)
426 {
427 struct btrace_target_info *tinfo;
428 int pid;
429
430 tinfo = xzalloc (sizeof (*tinfo));
431 tinfo->ptid = ptid;
432
433 tinfo->attr.size = sizeof (tinfo->attr);
434 tinfo->attr.type = PERF_TYPE_HARDWARE;
435 tinfo->attr.config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS;
436 tinfo->attr.sample_period = 1;
437
438 /* We sample from and to address. */
439 tinfo->attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_ADDR;
440
441 tinfo->attr.exclude_kernel = 1;
442 tinfo->attr.exclude_hv = 1;
443 tinfo->attr.exclude_idle = 1;
444
445 tinfo->ptr_bits = 0;
446
447 pid = ptid_get_lwp (ptid);
448 if (pid == 0)
449 pid = ptid_get_pid (ptid);
450
451 errno = 0;
452 tinfo->file = syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0);
453 if (tinfo->file < 0)
454 goto err;
455
456 /* We hard-code the trace buffer size.
457 At some later time, we should make this configurable. */
458 tinfo->size = 1;
459 tinfo->buffer = mmap (NULL, perf_event_mmap_size (tinfo),
460 PROT_READ, MAP_SHARED, tinfo->file, 0);
461 if (tinfo->buffer == MAP_FAILED)
462 goto err_file;
463
464 return tinfo;
465
466 err_file:
467 close (tinfo->file);
468
469 err:
470 xfree (tinfo);
471 return NULL;
472 }
473
474 /* See linux-btrace.h. */
475
476 int
477 linux_disable_btrace (struct btrace_target_info *tinfo)
478 {
479 int errcode;
480
481 errno = 0;
482 errcode = munmap (tinfo->buffer, perf_event_mmap_size (tinfo));
483 if (errcode != 0)
484 return errno;
485
486 close (tinfo->file);
487 xfree (tinfo);
488
489 return 0;
490 }
491
492 /* Check whether the branch trace has changed. */
493
494 static int
495 linux_btrace_has_changed (struct btrace_target_info *tinfo)
496 {
497 volatile struct perf_event_mmap_page *header = perf_event_header (tinfo);
498
499 return header->data_head != tinfo->data_head;
500 }
501
502 /* See linux-btrace.h. */
503
504 VEC (btrace_block_s) *
505 linux_read_btrace (struct btrace_target_info *tinfo,
506 enum btrace_read_type type)
507 {
508 VEC (btrace_block_s) *btrace = NULL;
509 volatile struct perf_event_mmap_page *header;
510 const uint8_t *begin, *end, *start;
511 unsigned long data_head, retries = 5;
512 size_t buffer_size;
513
514 if (type == btrace_read_new && !linux_btrace_has_changed (tinfo))
515 return NULL;
516
517 header = perf_event_header (tinfo);
518 buffer_size = perf_event_buffer_size (tinfo);
519
520 /* We may need to retry reading the trace. See below. */
521 while (retries--)
522 {
523 data_head = header->data_head;
524
525 /* If there's new trace, let's read it. */
526 if (data_head != tinfo->data_head)
527 {
528 /* Data_head keeps growing; the buffer itself is circular. */
529 begin = perf_event_buffer_begin (tinfo);
530 start = begin + data_head % buffer_size;
531
532 if (data_head <= buffer_size)
533 end = start;
534 else
535 end = perf_event_buffer_end (tinfo);
536
537 btrace = perf_event_read_bts (tinfo, begin, end, start);
538 }
539
540 /* The stopping thread notifies its ptracer before it is scheduled out.
541 On multi-core systems, the debugger might therefore run while the
542 kernel might be writing the last branch trace records.
543
544 Let's check whether the data head moved while we read the trace. */
545 if (data_head == header->data_head)
546 break;
547 }
548
549 tinfo->data_head = data_head;
550
551 return btrace;
552 }
553
554 #else /* !HAVE_LINUX_PERF_EVENT_H */
555
556 /* See linux-btrace.h. */
557
558 int
559 linux_supports_btrace (void)
560 {
561 return 0;
562 }
563
564 /* See linux-btrace.h. */
565
566 struct btrace_target_info *
567 linux_enable_btrace (ptid_t ptid)
568 {
569 return NULL;
570 }
571
572 /* See linux-btrace.h. */
573
574 int
575 linux_disable_btrace (struct btrace_target_info *tinfo)
576 {
577 return ENOSYS;
578 }
579
580 /* See linux-btrace.h. */
581
582 VEC (btrace_block_s) *
583 linux_read_btrace (struct btrace_target_info *tinfo,
584 enum btrace_read_type type)
585 {
586 return NULL;
587 }
588
589 #endif /* !HAVE_LINUX_PERF_EVENT_H */
This page took 0.054146 seconds and 5 git commands to generate.