btrace, linux: Enable ptwrite packets.

Enable ptwrite in the PT config, if it is supported by the kernel.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
This commit is contained in:
Felix Willgerodt
2018-05-29 08:44:45 +02:00
parent ccc480801b
commit 77a33bb024
3 changed files with 72 additions and 0 deletions

View File

@@ -2653,6 +2653,14 @@ pt_print_packet (const struct pt_packet *packet)
case ppt_mnt:
gdb_printf (("mnt %" PRIx64 ""), packet->payload.mnt.payload);
break;
#if (LIBIPT_VERSION >= 0x200)
case ppt_ptw:
gdb_printf (("ptw %u: 0x%" PRIx64 "%s"), packet->payload.ptw.plc,
packet->payload.ptw.payload,
packet->payload.ptw.ip ? (" ip") : (""));
break;
#endif /* defined (LIBIPT_VERSION >= 0x200) */
}
}

View File

@@ -415,6 +415,59 @@ cpu_supports_bts (void)
}
}
/* Return the Intel PT config bitmask from the linux sysfs for a FEATURE.
The bits can be used in the perf_event configuration when enabling PT.
Callers of this function are expected to check the availability of the
feature first via linux_supports_pt_feature. */
static uint64_t
linux_read_pt_config_bitmask (const char *feature)
{
uint64_t config_bitmask = 0;
std::string filename
= std::string ("/sys/bus/event_source/devices/intel_pt/format/")
+ feature;
gdb_file_up file = gdb_fopen_cloexec (filename.c_str (), "r");
if (file.get () == nullptr)
error (_("Failed to determine config from %s."), filename.c_str ());
uint8_t start, end;
int found = fscanf (file.get (), "config:%hhu-%hhu", &start, &end);
if (found == 1)
end = start;
else if (found != 2)
error (_("Failed to determine config from %s."), filename.c_str ());
for (uint8_t i = start; i <= end; ++i)
config_bitmask |= (1ULL << i);
return config_bitmask;
}
/* Check whether the linux target supports the Intel PT FEATURE. */
static bool
linux_supports_pt_feature (const char *feature)
{
std::string filename
= std::string ("/sys/bus/event_source/devices/intel_pt/caps/") + feature;
gdb_file_up file = gdb_fopen_cloexec (filename.c_str (), "r");
if (file.get () == nullptr)
return false;
int status, found = fscanf (file.get (), "%d", &status);
if (found != 1)
{
warning (_("Failed to determine %s support from %s."), feature,
filename.c_str ());
return false;
}
return (status == 1);
}
/* The perf_event_open syscall failed. Try to print a helpful error
message. */
@@ -627,6 +680,12 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
tinfo->attr.exclude_hv = 1;
tinfo->attr.exclude_idle = 1;
if (conf->ptwrite && linux_supports_pt_feature ("ptwrite"))
{
tinfo->attr.config |= linux_read_pt_config_bitmask ("ptw");
tinfo->conf.pt.ptwrite = true;
}
errno = 0;
scoped_fd fd (syscall (SYS_perf_event_open, &tinfo->attr, pid, -1, -1, 0));
if (fd.get () < 0)

View File

@@ -3306,4 +3306,9 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
record_btrace_conf.bts.size = 64 * 1024;
record_btrace_conf.pt.size = 16 * 1024;
#if (LIBIPT_VERSION >= 0x200)
record_btrace_conf.pt.ptwrite = true;
#else
record_btrace_conf.pt.ptwrite = false;
#endif
}