From: Zied Guermazi <zied.guermazi@trande.de>
To: gdb-patches@sourceware.org, markus.t.metzger@intel.com
Cc: Zied Guermazi <zied.guermazi@trande.de>
Subject: [PATCH v6 4/7] start/stop btrace with coresight etm and collect etm buffer on linux os
Date: Mon, 31 May 2021 23:33:04 +0200 [thread overview]
Message-ID: <20210531213307.275079-5-zied.guermazi@trande.de> (raw)
In-Reply-To: <20210531213307.275079-1-zied.guermazi@trande.de>
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/aarch64-linux-nat.c | 68 +++++++
gdb/arm-linux-nat.c | 68 +++++++
gdb/nat/linux-btrace.c | 395 ++++++++++++++++++++++++++++++++++++++--
gdb/nat/linux-btrace.h | 19 ++
4 files changed, 537 insertions(+), 13 deletions(-)
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 61224022f6a..4b629e1b3d2 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"
@@ -88,6 +89,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); }
@@ -714,6 +726,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 880ac0da044..32631b33328 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."));
+}
+
+/* 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..9ef182d774a 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];
+
+ snprintf (filename, PATH_MAX,
+ "/sys/bus/event_source/devices/cs_etm/sinks/%s", conf->sink);
+ 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. */
+
+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)
{
- munmap((void *) tinfo->pt.mem, tinfo->pt.size);
- munmap((void *) tinfo->header, PAGE_SIZE);
+ long page_size = sysconf (_SC_PAGESIZE);
+ munmap ((void *) tinfo->pt.mem, tinfo->pt.size);
+ munmap ((void *) tinfo->header, page_size);
+ close (tinfo->file);
+
+ return BTRACE_ERR_NONE;
+}
+
+/* Disable ARM CoreSight ETM tracing. */
+
+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,190 @@ 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));
+
+ fseek (file.get (), 0, SEEK_END);
+ int length = ftell (file.get ());
+ fseek (file.get (), 0, SEEK_SET);
+
+ char *buffer = (char *) xmalloc (length+1);
+
+ length = fread (buffer, 1, length, file.get ());
+ buffer[length]='\0';
+ while ((--length) != 0)
+ {
+ if ((buffer[length] == ',') || (buffer[length] == '-'))
+ {
+ length++;
+ break;
+ }
+ }
+
+ int cpu_count;
+ int found = sscanf (&buffer[length], "%d", &cpu_count);
+ if (found < 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];
+ snprintf (filename, PATH_MAX,
+ "/sys/bus/event_source/devices/cs_etm/cpu%d/trcidr/trcidr0", cpu);
+ 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. */
+ snprintf (filename, PATH_MAX,
+ "/sys/bus/event_source/devices/cs_etm/cpu%d/%s", cpu, path);
+ 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));
+}
+
+/* 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. */
+ 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->cpu_count = get_cpu_count ();
+ conf->etm_trace_params = new std::vector<cs_etm_trace_params>;
+ for (int i = 0; i < conf->cpu_count; 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. */
+ 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 +1285,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. */
+ 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;
+
+ /* 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 */
};
--
2.25.1
next prev parent reply other threads:[~2021-05-31 21:33 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-05-31 21:33 [PATCH v6 0/7] extend branch tracing to use ARM CoreSight traces Zied Guermazi
2021-05-31 21:33 ` [PATCH v6 1/7] configure gdb build system for supporting btrace on arm processors Zied Guermazi
2021-06-30 12:17 ` Luis Machado via Gdb-patches
2021-05-31 21:33 ` [PATCH v6 2/7] add btrace coresight related commands Zied Guermazi
2021-06-01 12:07 ` Eli Zaretskii via Gdb-patches
2021-06-01 15:47 ` Zied Guermazi
2021-06-30 12:26 ` Luis Machado via Gdb-patches
2021-05-31 21:33 ` [PATCH v6 3/7] start/stop btrace with coresight etm and parse etm buffer. nat independant Zied Guermazi
2021-06-22 14:59 ` Metzger, Markus T via Gdb-patches
2022-04-07 16:33 ` Zied Guermazi
2022-04-13 7:00 ` Metzger, Markus T via Gdb-patches
2022-05-10 12:58 ` Zied Guermazi
2022-05-10 13:21 ` Metzger, Markus T via Gdb-patches
2021-06-30 12:54 ` Luis Machado via Gdb-patches
2021-05-31 21:33 ` Zied Guermazi [this message]
2021-06-23 8:00 ` [PATCH v6 4/7] start/stop btrace with coresight etm and collect etm buffer on linux os Metzger, Markus T via Gdb-patches
2022-05-12 22:52 ` Zied Guermazi
2022-05-13 5:31 ` Metzger, Markus T via Gdb-patches
2022-06-12 21:02 ` Zied Guermazi
2022-06-20 12:52 ` Metzger, Markus T via Gdb-patches
2022-07-18 19:06 ` Zied Guermazi
2022-07-19 5:04 ` Metzger, Markus T via Gdb-patches
2022-07-21 22:20 ` Zied Guermazi
2022-07-25 14:33 ` Metzger, Markus T via Gdb-patches
2021-06-30 13:24 ` Luis Machado via Gdb-patches
2021-05-31 21:33 ` [PATCH v6 5/7] fix issue: gdb hangs in the command following a commad returning with TARGET_WAITKIND_NO_HISTORY Zied Guermazi
2021-06-23 8:08 ` Metzger, Markus T via Gdb-patches
2021-05-31 21:33 ` [PATCH v6 6/7] add support for coresight btrace via remote protocol Zied Guermazi
2021-06-01 12:08 ` Eli Zaretskii via Gdb-patches
2021-06-23 10:59 ` Metzger, Markus T via Gdb-patches
2021-05-31 21:33 ` [PATCH v6 7/7] adapt btrace testcases for arm target Zied Guermazi
2021-06-22 21:28 ` Lancelot SIX via Gdb-patches
2021-06-23 14:16 ` Metzger, Markus T via Gdb-patches
2022-05-13 11:08 ` Richard Earnshaw via Gdb-patches
2022-05-17 9:44 ` Zied Guermazi
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=20210531213307.275079-5-zied.guermazi@trande.de \
--to=zied.guermazi@trande.de \
--cc=gdb-patches@sourceware.org \
--cc=markus.t.metzger@intel.com \
/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