public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
From: Luis Machado <luis.machado@linaro.org>
To: Zied Guermazi <zied.guermazi@trande.de>, gdb-patches@sourceware.org
Subject: Re: [PATCH v3 4/7] start/stop btrace with coresight etm and collect etm buffer on linux os
Date: Thu, 1 Apr 2021 09:16:24 -0300	[thread overview]
Message-ID: <39782042-9993-d86c-4251-389fba89e1c0@linaro.org> (raw)
In-Reply-To: <20210331025234.518688-5-zied.guermazi@trande.de>

On 3/30/21 11:52 PM, Zied Guermazi wrote:
> 
> This patch implement the lower layer for starting ad stopping
> ARM CoreSight tracing on linux targets for arm and aarch64
> 
> gdb/ChangeLog
> 
> 	* nat/linux-btrace.h (btrace_tinfo_etm): New.
> 	(btrace_target_info): add etm.
> 	* nat/linux-btrace.c (linux_enable_bts): get page size from sysconf.
> 	(linux_enable_pt): get page size from sysconf.
> 	(perf_event_etm_event_type): New.
> 	(perf_event_etm_event_sink): New.
> 	(linux_enable_etm): New.
> 	(linux_enable_btrace): add enabling etm traces.
> 	(linux_disable_bts): get page size from sysconf.
> 	(linux_disable_pt): get page size from sysconf.
> 	(linux_disable_etm): New.
> 	(linux_disable_btrace): add disabling etm traces.
> 	(get_cpu_count): New.
> 	(cs_etm_is_etmv4): New.
> 	(cs_etm_get_register): New.
> 	(coresight_get_trace_id): New.
> 	(fill_etm_trace_params): New.
> 	(linux_fill_btrace_etm_config): New.
> 	(linux_read_etm): New.
> 	(linux_read_btrace): add reading etm traces.
> 	* arm-linux-nat.c (arm_linux_nat_target::enable_btrace): New.
> 	(arm_linux_nat_target::disable_btrace): New.
> 	(arm_linux_nat_target::teardown_btrace): New.
> 	(arm_linux_nat_target::read_btrace): New.
> 	(arm_linux_nat_target::btrace_conf): New.
> 	* aarch64-linux-nat.c (aarch64_linux_nat_target::enable_btrace): New.
> 	(aarch64_linux_nat_target::disable_btrace): New.
> 	(aarch64_linux_nat_target::teardown_btrace): New.
> 	(aarch64_linux_nat_target::read_btrace): New.
> 	(aarch64_linux_nat_target::btrace_conf): New.
> 
> ---
>   gdb/ChangeLog           |  34 ++++
>   gdb/aarch64-linux-nat.c |  68 +++++++
>   gdb/arm-linux-nat.c     |  68 +++++++
>   gdb/nat/linux-btrace.c  | 400 ++++++++++++++++++++++++++++++++++++++--
>   gdb/nat/linux-btrace.h  |  19 ++
>   5 files changed, 577 insertions(+), 12 deletions(-)
> 
> diff --git a/gdb/ChangeLog b/gdb/ChangeLog
> index 4453a3e8185..d22ec8b5976 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,37 @@
> +2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
> +
> +	* nat/linux-btrace.h (btrace_tinfo_etm): New.
> +	(btrace_target_info): add etm.
> +	* nat/linux-btrace.c (perf_event_read_available): New.
> +	(linux_enable_bts): get page size from sysconf.
> +	(linux_enable_pt): get page size from sysconf.
> +	(perf_event_etm_event_type): New.
> +	(perf_event_etm_event_sink): New.
> +	(linux_enable_etm): New.
> +	(linux_enable_btrace): add enabling etm traces.
> +	(linux_disable_bts): get page size from sysconf.
> +	(linux_disable_pt): get page size from sysconf.
> +	(linux_disable_etm): New.
> +	(linux_disable_btrace): add disabling etm traces.
> +	(get_cpu_count): New.
> +	(cs_etm_is_etmv4): New.
> +	(cs_etm_get_register): New.
> +	(coresight_get_trace_id): New.
> +	(fill_etm_trace_params): New.
> +	(linux_fill_btrace_etm_config): New.
> +	(linux_read_etm): New.
> +	(linux_read_btrace): add reading etm traces.
> +	* arm-linux-nat.c (arm_linux_nat_target::enable_btrace): New.
> +	(arm_linux_nat_target::disable_btrace): New.
> +	(arm_linux_nat_target::teardown_btrace): New.
> +	(arm_linux_nat_target::read_btrace): New.
> +	(arm_linux_nat_target::btrace_conf): New.
> +	* aarch64-linux-nat.c (aarch64_linux_nat_target::enable_btrace): New.
> +	(aarch64_linux_nat_target::disable_btrace): New.
> +	(aarch64_linux_nat_target::teardown_btrace): New.
> +	(aarch64_linux_nat_target::read_btrace): New.
> +	(aarch64_linux_nat_target::btrace_conf): New.
> +
>   2021-02-25  Zied Guermazi  <zied.guermazi@trande.de>
>   
>   	* btrace.c (ftrace_remove_last_insn): New.
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index 0cae91b569c..f459fdf6f0e 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -35,6 +35,7 @@
>   #include "nat/aarch64-linux.h"
>   #include "nat/aarch64-linux-hw-point.h"
>   #include "nat/aarch64-sve-linux-ptrace.h"
> +#include "nat/linux-btrace.h"
>   
>   #include "elf/external.h"
>   #include "elf/common.h"
> @@ -84,6 +85,17 @@ class aarch64_linux_nat_target final : public linux_nat_target
>     /* Override the GNU/Linux post attach hook.  */
>     void post_attach (int pid) override;
>   
> +  /* Override branch tracing.  */
> +  struct btrace_target_info *enable_btrace (ptid_t ptid,
> +				const struct btrace_config *conf) override;
> +  void disable_btrace (struct btrace_target_info *tinfo) override;
> +  void teardown_btrace (struct btrace_target_info *tinfo) override;
> +  enum btrace_error read_btrace (struct btrace_data *data,
> +				  struct btrace_target_info *btinfo,
> +				  enum btrace_read_type type) override;
> +  const struct btrace_config *btrace_conf (const struct btrace_target_info *)
> +				override;
> +
>     /* These three defer to common nat/ code.  */
>     void low_new_thread (struct lwp_info *lp) override
>     { aarch64_linux_new_thread (lp); }
> @@ -632,6 +644,62 @@ aarch64_linux_nat_target::post_attach (int pid)
>     linux_nat_target::post_attach (pid);
>   }
>   
> +/* Enable branch tracing.  */
> +
> +struct btrace_target_info *
> +aarch64_linux_nat_target::enable_btrace (ptid_t ptid,
> +					  const struct btrace_config *conf)
> +{
> +  struct btrace_target_info *tinfo = nullptr;
> +  try
> +    {
> +      tinfo = linux_enable_btrace (ptid, conf);
> +    }
> +  catch (const gdb_exception_error &exception)
> +    {
> +      error (_("Could not enable branch tracing for %s: %s"),
> +	     target_pid_to_str (ptid).c_str (), exception.what ());
> +    }
> +
> +  return tinfo;
> +}
> +
> +/* Disable branch tracing.  */
> +
> +void
> +aarch64_linux_nat_target::disable_btrace (struct btrace_target_info *tinfo)
> +{
> +  enum btrace_error errcode = linux_disable_btrace (tinfo);
> +
> +  if (errcode != BTRACE_ERR_NONE)
> +    error (_("Could not disable branch tracing."));
> +}
> +
> +/* Teardown branch tracing.  */
> +
> +void
> +aarch64_linux_nat_target::teardown_btrace (struct btrace_target_info *tinfo)
> +{
> +  /* Ignore errors.  */
> +  linux_disable_btrace (tinfo);
> +}
> +
> +enum btrace_error
> +aarch64_linux_nat_target::read_btrace (struct btrace_data *data,
> +				       struct btrace_target_info *btinfo,
> +				       enum btrace_read_type type)
> +{
> +  return linux_read_btrace (data, btinfo, type);
> +}
> +
> +/* See to_btrace_conf in target.h.  */
> +
> +const struct btrace_config *
> +aarch64_linux_nat_target::btrace_conf (const struct btrace_target_info *btinfo)
> +{
> +  return linux_btrace_conf (btinfo);
> +}
> +
>   /* Implement the "read_description" target_ops method.  */
>   
>   const struct target_desc *
> diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
> index 662dade0a12..8a8d4b65776 100644
> --- a/gdb/arm-linux-nat.c
> +++ b/gdb/arm-linux-nat.c
> @@ -39,6 +39,7 @@
>   #include <sys/procfs.h>
>   
>   #include "nat/linux-ptrace.h"
> +#include "nat/linux-btrace.h"
>   #include "linux-tdep.h"
>   
>   /* Prototypes for supply_gregset etc.  */
> @@ -95,6 +96,17 @@ class arm_linux_nat_target final : public linux_nat_target
>   
>     const struct target_desc *read_description () override;
>   
> +  /* Override branch tracing.  */
> +  struct btrace_target_info *enable_btrace (ptid_t ptid,
> +				const struct btrace_config *conf) override;
> +  void disable_btrace (struct btrace_target_info *tinfo) override;
> +  void teardown_btrace (struct btrace_target_info *tinfo) override;
> +  enum btrace_error read_btrace (struct btrace_data *data,
> +				  struct btrace_target_info *btinfo,
> +				  enum btrace_read_type type) override;
> +  const struct btrace_config *btrace_conf (const struct btrace_target_info *)
> +				override;
> +
>     /* Override linux_nat_target low methods.  */
>   
>     /* Handle thread creation and exit.  */
> @@ -1190,6 +1202,62 @@ arm_linux_nat_target::watchpoint_addr_within_range (CORE_ADDR addr,
>     return start <= addr && start + length - 1 >= addr;
>   }
>   
> +/* Enable branch tracing.  */
> +
> +struct btrace_target_info *
> +arm_linux_nat_target::enable_btrace (ptid_t ptid,
> +				     const struct btrace_config *conf)
> +{
> +  struct btrace_target_info *tinfo = nullptr;
> +  try
> +    {
> +      tinfo = linux_enable_btrace (ptid, conf);
> +    }
> +  catch (const gdb_exception_error &exception)
> +    {
> +      error (_("Could not enable branch tracing for %s: %s"),
> +	     target_pid_to_str (ptid).c_str (), exception.what ());
> +    }
> +
> +  return tinfo;
> +}
> +
> +/* Disable branch tracing.  */
> +
> +void
> +arm_linux_nat_target::disable_btrace (struct btrace_target_info *tinfo)
> +{
> +  enum btrace_error errcode = linux_disable_btrace (tinfo);
> +
> +  if (errcode != BTRACE_ERR_NONE)
> +    error (_("Could not disable branch tracing."));

Is this error due to not being able to disable branch tracing or not 
having an active tracing session to disable? If the latter, you may want 
to rephrase the error message.

> +}
> +
> +/* Teardown branch tracing.  */
> +
> +void
> +arm_linux_nat_target::teardown_btrace (struct btrace_target_info *tinfo)
> +{
> +  /* Ignore errors.  */
> +  linux_disable_btrace (tinfo);
> +}
> +
> +enum btrace_error
> +arm_linux_nat_target::read_btrace (struct btrace_data *data,
> +				   struct btrace_target_info *btinfo,
> +				   enum btrace_read_type type)
> +{
> +  return linux_read_btrace (data, btinfo, type);
> +}
> +
> +/* See to_btrace_conf in target.h.  */
> +
> +const struct btrace_config *
> +arm_linux_nat_target::btrace_conf (const struct btrace_target_info *btinfo)
> +{
> +  return linux_btrace_conf (btinfo);
> +}
> +
>   /* Handle thread creation.  We need to copy the breakpoints and watchpoints
>      in the parent thread to the child thread.  */
>   void
> diff --git a/gdb/nat/linux-btrace.c b/gdb/nat/linux-btrace.c
> index 324f7ef0407..11e2dd96397 100644
> --- a/gdb/nat/linux-btrace.c
> +++ b/gdb/nat/linux-btrace.c
> @@ -32,6 +32,10 @@
>   
>   #include <sys/syscall.h>
>   
> +#if defined (HAVE_LIBOPENCSD_C_API)
> +#  include <opencsd/ocsd_if_types.h>
> +#endif
> +
>   #if HAVE_LINUX_PERF_EVENT_H && defined(SYS_perf_event_open)
>   #include <unistd.h>
>   #include <sys/mman.h>
> @@ -483,10 +487,11 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
>     scoped_fd fd (syscall (SYS_perf_event_open, &bts->attr, pid, -1, -1, 0));
>     if (fd.get () < 0)
>       diagnose_perf_event_open_fail ();
> +  long page_size = sysconf (_SC_PAGESIZE);
>   
>     /* Convert the requested size in bytes to pages (rounding up).  */
> -  pages = ((size_t) conf->size / PAGE_SIZE
> -	   + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
> +  pages = ((size_t) conf->size / page_size
> +	   + ((conf->size % page_size) == 0 ? 0 : 1));
>     /* We need at least one page.  */
>     if (pages == 0)
>       pages = 1;
> @@ -505,17 +510,17 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
>         size_t length;
>         __u64 data_size;
>   
> -      data_size = (__u64) pages * PAGE_SIZE;
> +      data_size = (__u64) pages * page_size;
>   
>         /* Don't ask for more than we can represent in the configuration.  */
>         if ((__u64) UINT_MAX < data_size)
>   	continue;
>   
>         size = (size_t) data_size;
> -      length = size + PAGE_SIZE;
> +      length = size + page_size;
>   
>         /* Check for overflows.  */
> -      if ((__u64) length != data_size + PAGE_SIZE)
> +      if ((__u64) length != data_size + page_size)
>   	continue;
>   
>         errno = 0;
> @@ -530,7 +535,7 @@ linux_enable_bts (ptid_t ptid, const struct btrace_config_bts *conf)
>   
>     struct perf_event_mmap_page *header = (struct perf_event_mmap_page *)
>       data.get ();
> -  data_offset = PAGE_SIZE;
> +  data_offset = page_size;
>   
>   #if defined (PERF_ATTR_SIZE_VER5)
>     if (offsetof (struct perf_event_mmap_page, data_size) <= header->size)
> @@ -613,7 +618,8 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
>       diagnose_perf_event_open_fail ();
>   
>     /* Allocate the configuration page. */
> -  scoped_mmap data (nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
> +  long page_size = sysconf (_SC_PAGESIZE);
> +  scoped_mmap data (nullptr, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
>   		    fd.get (), 0);
>     if (data.get () == MAP_FAILED)
>       error (_("Failed to map trace user page: %s."), safe_strerror (errno));
> @@ -624,8 +630,8 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
>     header->aux_offset = header->data_offset + header->data_size;
>   
>     /* Convert the requested size in bytes to pages (rounding up).  */
> -  pages = ((size_t) conf->size / PAGE_SIZE
> -	   + ((conf->size % PAGE_SIZE) == 0 ? 0 : 1));
> +  pages = ((size_t) conf->size / page_size
> +	   + ((conf->size % page_size) == 0 ? 0 : 1));
>     /* We need at least one page.  */
>     if (pages == 0)
>       pages = 1;
> @@ -644,7 +650,7 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
>         size_t length;
>         __u64 data_size;
>   
> -      data_size = (__u64) pages * PAGE_SIZE;
> +      data_size = (__u64) pages * page_size;
>   
>         /* Don't ask for more than we can represent in the configuration.  */
>         if ((__u64) UINT_MAX < data_size)
> @@ -689,6 +695,154 @@ linux_enable_pt (ptid_t ptid, const struct btrace_config_pt *conf)
>   
>   #endif /* !defined (PERF_ATTR_SIZE_VER5) */
>   
> +/* Determine the etm event type.  */
> +
> +static int
> +perf_event_etm_event_type ()
> +{
> +  static const char filename[] = "/sys/bus/event_source/devices/cs_etm/type";
> +
> +  errno = 0;
> +  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
> +  if (file.get () == nullptr)
> +    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
> +
> +  int type, found = fscanf (file.get (), "%d", &type);
> +  if (found != 1)
> +    error (_("Failed to read the ETM event type from %s."), filename);
> +
> +  return type;
> +}
> +
> +/* Get the sink hash to use in the event attributes.  */
> +
> +static unsigned int
> +perf_event_etm_event_sink (const struct btrace_config_etm *conf)
> +{
> +  char filename[PATH_MAX];
> +
> +  sprintf (filename, "/sys/bus/event_source/devices/cs_etm/sinks/%s",
> +	   conf->sink);

Instead of hardcoding the filename buffer size, you could use 
string_printf or snprintf here.

> +  errno = 0;
> +  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
> +  if (file.get () == nullptr)
> +    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
> +
> +  unsigned int sink;
> +  int  found = fscanf (file.get (), "0x%x", &sink);
> +  if (found != 1)
> +    error (_("Failed to read the ETM sink from %s."), filename);
> +
> +  return sink;
> +}
> +
> +/* Enable arm CoreSight ETM tracing.  */
> +

arm -> ARM

> +static struct btrace_target_info *
> +linux_enable_etm (ptid_t ptid, const struct btrace_config_etm *conf)
> +{
> +  struct btrace_tinfo_etm *etm;
> +  size_t pages;
> +  int pid, pg;
> +
> +  pid = ptid.lwp ();
> +  if (pid == 0)
> +    pid = ptid.pid ();
> +
> +  gdb::unique_xmalloc_ptr<btrace_target_info> tinfo
> +    (XCNEW (btrace_target_info));
> +  tinfo->ptid = ptid;
> +
> +  tinfo->conf.format = BTRACE_FORMAT_ETM;
> +  etm = &tinfo->variant.etm;
> +
> +  etm->attr.type = perf_event_etm_event_type ();
> +  etm->attr.size = sizeof (etm->attr);
> +
> +  etm->attr.sample_type = PERF_SAMPLE_CPU;
> +  etm->attr.read_format = PERF_FORMAT_ID;
> +  etm->attr.sample_id_all = 1;
> +  etm->attr.enable_on_exec = 1;
> +  etm->attr.exclude_kernel = 1;
> +  etm->attr.exclude_hv = 1;
> +  etm->attr.exclude_idle = 1;
> +  if (conf->sink != nullptr)
> +    {
> +      if (strcmp (conf->sink, "default")!=0)
> +	etm->attr.config2 = perf_event_etm_event_sink (conf);
> +    }
> +
> +  errno = 0;
> +  scoped_fd fd (syscall (SYS_perf_event_open, &etm->attr, pid, -1, -1, 0));
> +  if (fd.get () < 0)
> +    diagnose_perf_event_open_fail ();
> +
> +  /* Allocate the configuration page.  */
> +  long page_size = sysconf (_SC_PAGESIZE);
> +  scoped_mmap data (nullptr, page_size, PROT_READ | PROT_WRITE, MAP_SHARED,
> +		    fd.get (), 0);
> +  if (data.get () == MAP_FAILED)
> +    error (_("Failed to map trace user page: %s."), safe_strerror (errno));
> +
> +  struct perf_event_mmap_page *header = (struct perf_event_mmap_page *)
> +    data.get ();
> +
> +  header->aux_offset = header->data_offset + header->data_size;
> +  /* Convert the requested size in bytes to pages (rounding up).  */
> +  pages = ((size_t) conf->size / page_size
> +	   + ((conf->size % page_size) == 0 ? 0 : 1));
> +  /* We need at least one page.  */
> +  if (pages == 0)
> +    pages = 1;
> +
> +  /* The buffer size can be requested in powers of two pages.  Adjust PAGES
> +     to the next power of two.  */
> +  for (pg = 0; pages != ((size_t) 1 << pg); ++pg)
> +    if ((pages & ((size_t) 1 << pg)) != 0)
> +      pages += ((size_t) 1 << pg);
> +
> +  /* We try to allocate the requested size.
> +     If that fails, try to get as much as we can.  */
> +  scoped_mmap aux;
> +  for (; pages > 0; pages >>= 1)
> +    {
> +      size_t length;
> +      __u64 data_size;
> +      data_size = (__u64) pages * page_size;
> +
> +      /* Don't ask for more than we can represent in the configuration.  */
> +      if ((__u64) UINT_MAX < data_size)
> +	continue;
> +
> +      length = (size_t) data_size;
> +
> +      /* Check for overflows.  */
> +      if ((__u64) length != data_size)
> +	continue;
> +
> +      header->aux_size = data_size;
> +
> +      errno = 0;
> +      aux.reset (nullptr, length, PROT_READ, MAP_SHARED, fd.get (),
> +		 header->aux_offset);
> +      if (aux.get () != MAP_FAILED)
> +	break;
> +    }
> +  if (pages == 0)
> +    error (_("Failed to map trace buffer: %s."), safe_strerror (errno));
> +
> +  etm->etm.size = aux.size ();
> +  etm->etm.mem = (const uint8_t *) aux.release ();
> +  etm->etm.data_head = &header->aux_head;
> +  etm->etm.last_head = header->aux_tail;
> +  etm->header = (struct perf_event_mmap_page *) data.release ();
> +  gdb_assert (etm->header == header);
> +  etm->file = fd.release ();
> +
> +  tinfo->conf.etm.size = (unsigned int) etm->etm.size;
> +  return tinfo.release ();
> +}
> +
>   /* See linux-btrace.h.  */
>   
>   struct btrace_target_info *
> @@ -707,6 +861,10 @@ linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
>   
>       case BTRACE_FORMAT_PT:
>         return linux_enable_pt (ptid, &conf->pt);
> +
> +    case BTRACE_FORMAT_ETM:
> +      return linux_enable_etm (ptid, &conf->etm);
> +
>       }
>   }
>   
> @@ -715,7 +873,8 @@ linux_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
>   static enum btrace_error
>   linux_disable_bts (struct btrace_tinfo_bts *tinfo)
>   {
> -  munmap((void *) tinfo->header, tinfo->bts.size + PAGE_SIZE);
> +  long page_size = sysconf (_SC_PAGESIZE);
> +  munmap((void *) tinfo->header, tinfo->bts.size + page_size);
>     close (tinfo->file);
>   
>     return BTRACE_ERR_NONE;
> @@ -726,8 +885,22 @@ linux_disable_bts (struct btrace_tinfo_bts *tinfo)
>   static enum btrace_error
>   linux_disable_pt (struct btrace_tinfo_pt *tinfo)
>   {
> +  long page_size = sysconf (_SC_PAGESIZE);
>     munmap((void *) tinfo->pt.mem, tinfo->pt.size);
> -  munmap((void *) tinfo->header, PAGE_SIZE);
> +  munmap((void *) tinfo->header, page_size);
> +  close (tinfo->file);
> +
> +  return BTRACE_ERR_NONE;
> +}
> +
> +/* Disable arm CoreSight ETM tracing.  */
> +

arm -> ARM

> +static enum btrace_error
> +linux_disable_etm (struct btrace_tinfo_etm *tinfo)
> +{
> +  long page_size = sysconf (_SC_PAGESIZE);
> +  munmap ((void *) tinfo->etm.mem, tinfo->etm.size);
> +  munmap ((void *) tinfo->header, page_size);
>     close (tinfo->file);
>   
>     return BTRACE_ERR_NONE;
> @@ -753,6 +926,10 @@ linux_disable_btrace (struct btrace_target_info *tinfo)
>       case BTRACE_FORMAT_PT:
>         errcode = linux_disable_pt (&tinfo->variant.pt);
>         break;
> +
> +    case BTRACE_FORMAT_ETM:
> +      errcode = linux_disable_etm (&tinfo->variant.etm);
> +      break;
>       }
>   
>     if (errcode == BTRACE_ERR_NONE)
> @@ -898,6 +1075,197 @@ linux_read_pt (struct btrace_data_pt *btrace,
>     internal_error (__FILE__, __LINE__, _("Unknown btrace read type."));
>   }
>   
> +/* Return the number of CPUs that are present.  */
> +
> +static int
> +get_cpu_count (void)
> +{
> +  static const char filename[] = "/sys/devices/system/cpu/present";
> +
> +  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
> +  if (file.get () == nullptr)
> +    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
> +
> +  int length;
> +
> +  fseek (file.get (), 0, SEEK_END);
> +  length = ftell (file.get ());
> +  fseek (file.get (), 0, SEEK_SET);
> +
> +  char * buffer;

Spurious space between * and buffer.
> +
> +  buffer = (char*) xmalloc (length+1);

space between char and *.

> +
> +  length = fread (buffer, 1, length, file.get ());
> +  buffer[length]='\0';

Space between buffer[length] and =, and between = and '\0'.

> +  while (--length)
> +    {
> +      if ((buffer[length] == ',') || (buffer[length] == '-'))
> +	{
> +	  length++;
> +	  break;
> +	}
> +    }
> +
> +  int cpu_count;
> +
> +  if (sscanf (&buffer[length], "%d", &cpu_count) < 1)
> +    error (_("Failed to get cpu count in %s: %s."),
> +	     buffer, safe_strerror (errno));
> +
> +  cpu_count ++;
> +  return (cpu_count);
> +}
> +
> +/* Check if the ETM is an etmv4.  */
> +
> +static bool
> +cs_etm_is_etmv4 (int cpu)
> +{
> +  char filename[PATH_MAX];
> +  sprintf (filename,
> +	  "/sys/bus/event_source/devices/cs_etm/cpu%d/trcidr/trcidr0",
> +	  cpu);

Same suggestion about not relying on a fixed-size buffer and using 
string_printf or snprintf.

> +  errno = 0;
> +  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
> +  if (file.get () == nullptr)
> +    return false;
> +
> +  return true;
> +}
> +
> +/* Get etm configuration register from sys filesystem.  */
> +
> +static uint32_t
> +cs_etm_get_register (int cpu, const char *path)
> +{
> +  char filename[PATH_MAX];
> +
> +  /* Get coresight register from sysfs.  */
> +  sprintf (filename,
> +	  "/sys/bus/event_source/devices/cs_etm/cpu%d/%s",
> +	  cpu, path);

Same here.

> +  errno = 0;
> +  gdb_file_up file = gdb_fopen_cloexec (filename, "r");
> +  if (file.get () == nullptr)
> +    error (_("Failed to open %s: %s."), filename, safe_strerror (errno));
> +
> +  uint32_t val = 0;
> +
> +  int  found = fscanf (file.get (), "0x%x", &val);
> +  if (found != 1)
> +    error (_("Failed to read coresight register from %s."), filename);
> +  return val;
> +}
> +
> +#define CORESIGHT_ETM_PMU_SEED  0x10
> +
> +/* Calculate trace_id for this cpu
> +   to be kept aligned with coresight-pmu.h.  */
> +
> +static inline int
> +coresight_get_trace_id (int cpu)
> +{
> +  return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
> +}
> +
> +

Spurious newline.

> +/* PTMs ETMIDR[11:8] set to b0011.  */
> +#define ETMIDR_PTM_VERSION 0x00000300
> +
> +/* Collect and fill etm trace parameter.  */
> +
> +static void
> +fill_etm_trace_params (struct cs_etm_trace_params *etm_trace_params, int cpu)
> +{
> +  if (cs_etm_is_etmv4 (cpu) == true)
> +    {
> +      etm_trace_params->arch_ver = ARCH_V8;
> +      etm_trace_params->core_profile = profile_CortexA;
> +      etm_trace_params->protocol = OCSD_PROTOCOL_ETMV4I;
> +      /* This is the parameter passed in etm->attr.config in the call to
> +	 perf_event_open remapped according to linux/coresight-pmu.h.  */

Is the indentation of the second line of this comment block off?

> +      etm_trace_params->etmv4.reg_configr = 0;
> +      etm_trace_params->etmv4.reg_idr0
> +	 = cs_etm_get_register (cpu, "trcidr/trcidr0");
> +      etm_trace_params->etmv4.reg_idr1
> +	 = cs_etm_get_register (cpu, "trcidr/trcidr1");
> +      etm_trace_params->etmv4.reg_idr2
> +	 = cs_etm_get_register (cpu, "trcidr/trcidr2");
> +      etm_trace_params->etmv4.reg_idr8
> +	 = cs_etm_get_register (cpu, "trcidr/trcidr8");
> +      etm_trace_params->etmv4.reg_traceidr = coresight_get_trace_id (cpu);
> +    }
> +  else
> +    {
> +      etm_trace_params->arch_ver = ARCH_V7;
> +      etm_trace_params->core_profile = profile_CortexA;
> +      etm_trace_params->protocol
> +	= (etm_trace_params->etmv3.reg_idr & ETMIDR_PTM_VERSION)
> +	  == ETMIDR_PTM_VERSION ? OCSD_PROTOCOL_PTM : OCSD_PROTOCOL_ETMV3;
> +      etm_trace_params->etmv3.reg_ccer
> +	 = cs_etm_get_register (cpu, "mgmt/etmccer");
> +      etm_trace_params->etmv3.reg_ctrl
> +	 = cs_etm_get_register (cpu, "mgmt/etmcr");
> +      etm_trace_params->etmv3.reg_idr
> +	 = cs_etm_get_register (cpu, "mgmt/etmidr");
> +      etm_trace_params->etmv3.reg_trc_id
> +	 = cs_etm_get_register (cpu, "traceid");
> +    }
> +}
> +
> +static void
> +linux_fill_btrace_etm_config (struct btrace_target_info *tinfo,
> +			       struct btrace_data_etm_config *conf)
> +{
> +
> +  cs_etm_trace_params etm_trace_params;
> +  conf->num_cpu = get_cpu_count ();
> +  conf->etm_trace_params = new std::vector<cs_etm_trace_params>;
> +  for (int i = 0; i < conf->num_cpu; i++)
> +    {
> +      fill_etm_trace_params (&etm_trace_params,i);
> +      conf->etm_trace_params->push_back (etm_trace_params);
> +    }
> +
> +  conf->etm_decoder_params.formatted = 1;
> +  conf->etm_decoder_params.fsyncs = 0;
> +  conf->etm_decoder_params.hsyncs = 0;
> +  conf->etm_decoder_params.frame_aligned = 0;
> +  conf->etm_decoder_params.reset_on_4x_sync = 1;
> +}
> +
> +static enum btrace_error
> +linux_read_etm (struct btrace_data_etm *btrace,
> +		struct btrace_target_info *tinfo,
> +		enum btrace_read_type type)
> +{
> +  struct perf_event_buffer *etm;
> +  etm = &tinfo->variant.etm.etm;
> +
> +  linux_fill_btrace_etm_config (tinfo, &btrace->config);
> +
> +  switch (type)
> +    {
> +    case BTRACE_READ_DELTA:
> +      /* We don't support delta reads.  The data head (i.e. aux_head) wraps
> +	 around to stay inside the aux buffer.  */

Indentation of the second line of the comment block off?

> +      return BTRACE_ERR_NOT_SUPPORTED;
> +
> +    case BTRACE_READ_NEW:
> +      if (!perf_event_new_data (etm))
> +	return BTRACE_ERR_NONE;
> +
> +      /* Fall through.  */
> +    case BTRACE_READ_ALL:
> +      perf_event_read_all (etm, &(btrace->data),&(btrace->size));
> +      return BTRACE_ERR_NONE;
> +    }
> +
> +  internal_error (__FILE__, __LINE__, _("Unkown btrace read type."));
> +}
> +
> +
>   /* See linux-btrace.h.  */
>   
>   enum btrace_error
> @@ -924,6 +1292,14 @@ linux_read_btrace (struct btrace_data *btrace,
>         btrace->variant.pt.size = 0;
>   
>         return linux_read_pt (&btrace->variant.pt, tinfo, type);
> +
> +    case BTRACE_FORMAT_ETM:
> +      /* We read btrace in arm CoreSight ETM Trace format.  */

arm -> ARM

> +      btrace->format = BTRACE_FORMAT_ETM;
> +      btrace->variant.etm.data = NULL;
> +      btrace->variant.etm.size = 0;
> +
> +      return linux_read_etm (&btrace->variant.etm, tinfo, type);
>       }
>   
>     internal_error (__FILE__, __LINE__, _("Unkown branch trace format."));
> diff --git a/gdb/nat/linux-btrace.h b/gdb/nat/linux-btrace.h
> index 607182da144..3038d2f45a0 100644
> --- a/gdb/nat/linux-btrace.h
> +++ b/gdb/nat/linux-btrace.h
> @@ -78,6 +78,22 @@ struct btrace_tinfo_pt
>     /* The trace perf event buffer.  */
>     struct perf_event_buffer pt;
>   };
> +
> +/* Branch trace target information for ARM CoreSight ETM Trace.  */
> +struct btrace_tinfo_etm
> +{
> +  /* The Linux perf_event configuration for collecting the branch trace.  */
> +  struct perf_event_attr attr;
> +
> +  /* The perf event file.  */
> +  int file;
> +
> +  /* The perf event configuration page.  */
> +  volatile struct perf_event_mmap_page *header;

I'm not too familiar with the interface, but does this need to be 
volatile? Is this something changing this in the background?

> +
> +  /* The trace perf event buffer.  */
> +  struct perf_event_buffer etm;
> +};
>   #endif /* HAVE_LINUX_PERF_EVENT_H */
>   
>   /* Branch trace target information per thread.  */
> @@ -98,6 +114,9 @@ struct btrace_target_info
>   
>       /* CONF.FORMAT == BTRACE_FORMAT_PT.  */
>       struct btrace_tinfo_pt pt;
> +
> +    /* CONF.FORMAT == BTRACE_FORMAT_ETM.  */
> +    struct btrace_tinfo_etm etm;
>     } variant;
>   #endif /* HAVE_LINUX_PERF_EVENT_H */
>   };
> 

I'm addressing mostly formatting issues for now, as they tend to get in 
the way of proper code review. And I'm not too familiar with the branch 
tracing code.

  reply	other threads:[~2021-04-01 12:16 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-31  2:52 [PATCH v3 0/7] extend branch tracing to use ARM CoreSight traces Zied Guermazi
2021-03-31  2:52 ` [PATCH v3 1/7] configure gdb build system for supporting btrace on arm processors Zied Guermazi
2021-03-31  2:52 ` [PATCH v3 2/7] add btrace coresight related commands Zied Guermazi
2021-03-31  6:32   ` Eli Zaretskii
2021-03-31 18:30   ` Luis Machado
2021-03-31 20:24     ` Zied Guermazi
2021-04-01 16:11       ` Luis Machado
2021-03-31  2:52 ` [PATCH v3 3/7] start/stop btrace with coresight etm and parse etm buffer. nat independant Zied Guermazi
2021-03-31 20:23   ` Luis Machado
     [not found]     ` <a78174f9-177f-3757-6b33-d09f38f1fec8@trande.de>
2021-04-01 21:04       ` Zied Guermazi
2021-03-31  2:52 ` [PATCH v3 4/7] start/stop btrace with coresight etm and collect etm buffer on linux os Zied Guermazi
2021-04-01 12:16   ` Luis Machado [this message]
2021-04-01 21:57     ` Zied Guermazi
2021-03-31  2:52 ` [PATCH v3 5/7] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY Zied Guermazi
2021-04-01 12:18   ` Luis Machado
2021-03-31  2:52 ` [PATCH v3 6/7] add support for coresight btrace via remote protocol Zied Guermazi
2021-03-31  6:33   ` Eli Zaretskii
2021-04-01 12:45   ` Luis Machado
2021-04-01 22:58     ` Zied Guermazi
2021-03-31  2:52 ` [PATCH v3 7/7] adapt btrace testcases for arm target Zied Guermazi
2021-04-01 13:34   ` Luis Machado
2021-04-04 19:30     ` Zied Guermazi
2021-04-06 13:09       ` Luis Machado
2021-04-09 19:34         ` Zied Guermazi
2021-04-12 17:11           ` Luis Machado
2021-04-02 16:02 ` [PATCH v3 0/7] extend branch tracing to use ARM CoreSight traces Simon Marchi
2021-04-02 16:05   ` Zied Guermazi
2021-04-05  0:09     ` Simon Marchi
2021-04-05  7:38       ` Zied Guermazi
2021-04-06 16:25         ` Simon Marchi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=39782042-9993-d86c-4251-389fba89e1c0@linaro.org \
    --to=luis.machado@linaro.org \
    --cc=gdb-patches@sourceware.org \
    --cc=zied.guermazi@trande.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).