]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
btrace, linux: Enable ptwrite packets.
authorFelix Willgerodt <felix.willgerodt@intel.com>
Tue, 29 May 2018 06:44:45 +0000 (08:44 +0200)
committerFelix Willgerodt <felix.willgerodt@intel.com>
Wed, 14 Aug 2024 09:20:56 +0000 (11:20 +0200)
Enable ptwrite in the PT config, if it is supported by the kernel.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
gdb/btrace.c
gdb/nat/linux-btrace.c
gdb/record-btrace.c

index 224341b6b2d820d6b04ee1051a718989dade6f52..d6188c84ad49d1af70077b2591218f37fb4389af 100644 (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)  */
     }
 }
 
index 5715168d2f0887da2321694b5a8f3e21e74c4ad7..59e8ae6bef60611437f2f4bef1db180e2f074e8a 100644 (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)
index 8b1c9e1e4c84f01ed452e530cf58e0b3c650d288..997f442af5506c41b10da71ca3888091184fcfa4 100644 (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
 }