Blame SOURCES/gdb-rhbz1187581-power8-regs-not-in-8.2-12of15.patch

190f2a
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
190f2a
From: Keith Seitz <keiths@redhat.com>
190f2a
Date: Fri, 11 Jan 2019 17:02:17 -0500
190f2a
Subject: gdb-rhbz1187581-power8-regs-not-in-8.2-12of15.patch
190f2a
190f2a
;; [PowerPC] Add support for EBB and PMU registers
190f2a
;; Edjunior Barbosa Machado and Pedro Franco de Carvalho, RH BZ 1187581m
190f2a
190f2a
[PowerPC] Add support for EBB and PMU registers
190f2a
190f2a
This patch adds support for registers of the Event Based Branching and
190f2a
Performance Monitoring Units for the powerpc linux native and core
190f2a
file targets, and for the powerpc linux server stub.
190f2a
190f2a
All three EBB registers are accessible.  Only a subset of the PMU
190f2a
registers can be accessed through ptrace.  Because of this, the PMU
190f2a
registers are enumerated individually in gdbarch_tdep, as opposed to
190f2a
having a single "have_pmu" flag.  This is intended to make it easier
190f2a
to add additional PMU registers in the future, since checking a
190f2a
"have_pmu" flag elsewhere in the code would no longer be correct.  The
190f2a
tdesc feature is named org.gnu.gdb.power.linux.pmu because of this.
190f2a
190f2a
It's unclear if it makes sense to save and restore these registers
190f2a
across function calls, since some of them can be modified
190f2a
asynchronously.  They are also not tracked in record-replay mode.
190f2a
190f2a
The kernel can return ENODATA when ptrace is used to get the EBB
190f2a
registers, unless a linux performance event that uses EBB is open in
190f2a
the inferior.  For this reason, the "fill" functions in the server
190f2a
stub for the ebb register sets is not implemented.
190f2a
190f2a
Since gdbserver writes all registers in one go before resuming the
190f2a
inferior, this error would not be detected at the time the user tries
190f2a
to write to one of the registers on the client side, and gdbserver
190f2a
would print out warnings every time it resumes the inferior when no
190f2a
ebb performance event is opened, so there is currently no
190f2a
straightforward way to handle this case.  This means the ebb registers
190f2a
in the client-side regcache can become dirty when the user tries to
190f2a
write to them, until the inferior is resumed and stopped again.
190f2a
190f2a
A related issue is that 'G' packets used to write to unrelated
190f2a
registers will include bad data for the EBB registers if they are
190f2a
unavailable, since no register status information is included in the
190f2a
'G' packet.  This data won't be written to the inferior by the
190f2a
gdbserver stub because the "fill" functions are not implemented, and
190f2a
currently the gdbserver stub doesn't change the status of the
190f2a
registers in its own regcache in response to 'G' packets.
190f2a
190f2a
Another limitation for the ebb registers is that traceframes don't
190f2a
record if registers are available or not, so if these registers are
190f2a
collected when a tracepoint is hit and the inferior has no ebb event
190f2a
opened, the user will see zero values for all of them, instead of the
190f2a
usual <unavailable>.
190f2a
190f2a
Because these registers are often unavailable, trying to store them
190f2a
with target_store_registers with -1 for the regno argument (all
190f2a
registers) would almost always fail, so they are ignored in this case.
190f2a
190f2a
gdb/ChangeLog:
190f2a
2018-10-26  Edjunior Barbosa Machado  <emachado@linux.vnet.ibm.com>
190f2a
        Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
190f2a
190f2a
    * arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_EBBREGSET)
190f2a
    (PPC_LINUX_SIZEOF_PMUREGSET): Declare.
190f2a
    * nat/ppc-linux.h (PPC_FEATURE2_EBB, NT_PPC_EBB, NT_PPC_PMU):
190f2a
    Define if not already defined.
190f2a
    * features/rs6000/power-ebb.xml: New file.
190f2a
    * features/rs6000/power-linux-pmu.xml: New file.
190f2a
    * features/rs6000/powerpc-isa207-vsx32l.xml: Include ebb and pmu
190f2a
    features.
190f2a
    * features/rs6000/powerpc-isa207-vsx64l.xml: Likewise.
190f2a
    * features/rs6000/powerpc-isa207-vsx32l.c: Re-generate.
190f2a
    * features/rs6000/powerpc-isa207-vsx64l.c: Re-generate.
190f2a
    * regformats/rs6000/powerpc-isa207-vsx32l.dat: Re-generate.
190f2a
    * regformats/rs6000/powerpc-isa207-vsx64l.dat: Re-generate.
190f2a
    * ppc-linux-nat.c (fetch_register, fetch_ppc_registers): Call
190f2a
    fetch_regset with ebb and pmu regsets.
190f2a
    (store_register, store_ppc_registers): Call store_regset with ebb
190f2a
    and pmu regsets.
190f2a
    (ppc_linux_nat_target::read_description): Set isa207 field in the
190f2a
    features struct if ebb and pmu are avaiable.
190f2a
    * ppc-linux-tdep.c (ppc32_regmap_ebb, ppc32_regmap_pmu)
190f2a
    (ppc32_linux_ebbregset, ppc32_linux_pmuregset): New globals.
190f2a
    (ppc_linux_iterate_over_regset_sections): Call back with the ebb
190f2a
    and pmu regsets.
190f2a
    (ppc_linux_core_read_description): Check if the pmu section is
190f2a
    present and set isa207 in the features struct.
190f2a
    * ppc-linux-tdep.h (ppc32_linux_ebbregset)
190f2a
    (ppc32_linux_pmuregset): Declare.
190f2a
    * ppc-tdep.h (struct gdbarch_tdep) <ppc_mmcr0_regnum>: New field.
190f2a
    <ppc_mmcr2_regnum, ppc_siar_regnum, ppc_sdar_regnum>: New fields.
190f2a
    <ppc_sier_regnum>: New field.
190f2a
    (enum): <PPC_BESCR_REGNUM, PPC_EBBHR_REGNUM, PPC_EBBRR_REGNUM>:
190f2a
    New enum values.
190f2a
    <PPC_MMCR0_REGNUM, PPC_MMCR2_REGNUM, PPC_SIAR_REGNUM>: New enum
190f2a
    values.
190f2a
    <PPC_SDAR_REGNUM, PPC_SIER_REGNUM>: New enum values.
190f2a
    (PPC_IS_EBB_REGNUM, PPC_IS_PMU_REGNUM): Define.
190f2a
    * rs6000-tdep.c (rs6000_gdbarch_init): Look for and validate the
190f2a
    ebb and pmu features.
190f2a
190f2a
gdb/gdbserver/ChangeLog:
190f2a
2018-10-26  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
190f2a
190f2a
    * configure.srv (powerpc*-*-linux*): Add rs6000/power-ebb.xml and
190f2a
    rs6000/power-linux-pmu.xml to srv_xmlfiles.
190f2a
    * linux-ppc-low.c (ppc_store_ebbregset, ppc_fill_pmuregset)
190f2a
    (ppc_store_pmuregset): New functions.
190f2a
    (ppc_regsets): Add entries for ebb and pmu regsets.
190f2a
    (ppc_arch_setup): Set isa207 in features struct if the ebb and
190f2a
    pmu regsets are available.  Set sizes for these regsets.
190f2a
190f2a
gdb/doc/ChangeLog:
190f2a
2018-10-26  Pedro Franco de Carvalho  <pedromfc@linux.ibm.com>
190f2a
190f2a
    * gdb.texinfo (PowerPC Features): Describe new features
190f2a
    "org.gnu.gdb.power.ebb" and "org.gnu.gdb.power.linux.pmu".
190f2a
190f2a
diff --git a/gdb/arch/ppc-linux-common.h b/gdb/arch/ppc-linux-common.h
190f2a
--- a/gdb/arch/ppc-linux-common.h
190f2a
+++ b/gdb/arch/ppc-linux-common.h
190f2a
@@ -33,6 +33,8 @@ struct target_desc;
190f2a
 #define PPC_LINUX_SIZEOF_PPRREGSET 8
190f2a
 #define PPC_LINUX_SIZEOF_DSCRREGSET 8
190f2a
 #define PPC_LINUX_SIZEOF_TARREGSET 8
190f2a
+#define PPC_LINUX_SIZEOF_EBBREGSET (3*8)
190f2a
+#define PPC_LINUX_SIZEOF_PMUREGSET (5*8)
190f2a
 
190f2a
 /* Check if the hwcap auxv entry indicates that isa205 is supported.  */
190f2a
 bool ppc_linux_has_isa205 (CORE_ADDR hwcap);
190f2a
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
190f2a
--- a/gdb/doc/gdb.texinfo
190f2a
+++ b/gdb/doc/gdb.texinfo
190f2a
@@ -42564,6 +42564,15 @@ contain the 64-bit register @samp{dscr}.
190f2a
 The @samp{org.gnu.gdb.power.tar} feature is optional.  It should
190f2a
 contain the 64-bit register @samp{tar}.
190f2a
 
190f2a
+The @samp{org.gnu.gdb.power.ebb} feature is optional.  It should
190f2a
+contain registers @samp{bescr}, @samp{ebbhr} and @samp{ebbrr}, all
190f2a
+64-bit wide.
190f2a
+
190f2a
+The @samp{org.gnu.gdb.power.linux.pmu} feature is optional.  It should
190f2a
+contain registers @samp{mmcr0}, @samp{mmcr2}, @samp{siar}, @samp{sdar}
190f2a
+and @samp{sier}, all 64-bit wide.  This is the subset of the isa 2.07
190f2a
+server PMU registers provided by @sc{gnu}/Linux.
190f2a
+
190f2a
 @node S/390 and System z Features
190f2a
 @subsection S/390 and System z Features
190f2a
 @cindex target descriptions, S/390 features
190f2a
diff --git a/gdb/features/rs6000/power-ebb.xml b/gdb/features/rs6000/power-ebb.xml
190f2a
new file mode 100644
190f2a
--- /dev/null
190f2a
+++ b/gdb/features/rs6000/power-ebb.xml
190f2a
@@ -0,0 +1,14 @@
190f2a
+
190f2a
+
190f2a
+
190f2a
+     Copying and distribution of this file, with or without modification,
190f2a
+     are permitted in any medium without royalty provided the copyright
190f2a
+     notice and this notice are preserved.  -->
190f2a
+
190f2a
+
190f2a
+
190f2a
+<feature name="org.gnu.gdb.power.ebb">
190f2a
+  <reg name="bescr" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+  <reg name="ebbhr" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+  <reg name="ebbrr" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+</feature>
190f2a
diff --git a/gdb/features/rs6000/power-linux-pmu.xml b/gdb/features/rs6000/power-linux-pmu.xml
190f2a
new file mode 100644
190f2a
--- /dev/null
190f2a
+++ b/gdb/features/rs6000/power-linux-pmu.xml
190f2a
@@ -0,0 +1,17 @@
190f2a
+
190f2a
+
190f2a
+
190f2a
+     Copying and distribution of this file, with or without modification,
190f2a
+     are permitted in any medium without royalty provided the copyright
190f2a
+     notice and this notice are preserved.  -->
190f2a
+
190f2a
+
190f2a
+     provided by Linux.  -->
190f2a
+
190f2a
+<feature name="org.gnu.gdb.power.linux.pmu">
190f2a
+  <reg name="mmcr0" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+  <reg name="mmcr2" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+  <reg name="siar" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+  <reg name="sdar" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+  <reg name="sier" bitsize="64" type="uint64" save-restore="no"/>
190f2a
+</feature>
190f2a
diff --git a/gdb/features/rs6000/powerpc-isa207-vsx32l.c b/gdb/features/rs6000/powerpc-isa207-vsx32l.c
190f2a
--- a/gdb/features/rs6000/powerpc-isa207-vsx32l.c
190f2a
+++ b/gdb/features/rs6000/powerpc-isa207-vsx32l.c
190f2a
@@ -199,5 +199,17 @@ initialize_tdesc_powerpc_isa207_vsx32l (void)
190f2a
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.tar");
190f2a
   tdesc_create_reg (feature, "tar", 141, 1, NULL, 64, "uint64");
190f2a
 
190f2a
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.ebb");
190f2a
+  tdesc_create_reg (feature, "bescr", 142, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "ebbhr", 143, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "ebbrr", 144, 0, NULL, 64, "uint64");
190f2a
+
190f2a
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux.pmu");
190f2a
+  tdesc_create_reg (feature, "mmcr0", 145, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "mmcr2", 146, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "siar", 147, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "sdar", 148, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "sier", 149, 0, NULL, 64, "uint64");
190f2a
+
190f2a
   tdesc_powerpc_isa207_vsx32l = result;
190f2a
 }
190f2a
diff --git a/gdb/features/rs6000/powerpc-isa207-vsx32l.xml b/gdb/features/rs6000/powerpc-isa207-vsx32l.xml
190f2a
--- a/gdb/features/rs6000/powerpc-isa207-vsx32l.xml
190f2a
+++ b/gdb/features/rs6000/powerpc-isa207-vsx32l.xml
190f2a
@@ -16,4 +16,6 @@
190f2a
   <xi:include href="power-ppr.xml"/>
190f2a
   <xi:include href="power-dscr.xml"/>
190f2a
   <xi:include href="power-tar.xml"/>
190f2a
+  <xi:include href="power-ebb.xml"/>
190f2a
+  <xi:include href="power-linux-pmu.xml"/>
190f2a
 </target>
190f2a
diff --git a/gdb/features/rs6000/powerpc-isa207-vsx64l.c b/gdb/features/rs6000/powerpc-isa207-vsx64l.c
190f2a
--- a/gdb/features/rs6000/powerpc-isa207-vsx64l.c
190f2a
+++ b/gdb/features/rs6000/powerpc-isa207-vsx64l.c
190f2a
@@ -199,5 +199,17 @@ initialize_tdesc_powerpc_isa207_vsx64l (void)
190f2a
   feature = tdesc_create_feature (result, "org.gnu.gdb.power.tar");
190f2a
   tdesc_create_reg (feature, "tar", 141, 1, NULL, 64, "uint64");
190f2a
 
190f2a
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.ebb");
190f2a
+  tdesc_create_reg (feature, "bescr", 142, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "ebbhr", 143, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "ebbrr", 144, 0, NULL, 64, "uint64");
190f2a
+
190f2a
+  feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux.pmu");
190f2a
+  tdesc_create_reg (feature, "mmcr0", 145, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "mmcr2", 146, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "siar", 147, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "sdar", 148, 0, NULL, 64, "uint64");
190f2a
+  tdesc_create_reg (feature, "sier", 149, 0, NULL, 64, "uint64");
190f2a
+
190f2a
   tdesc_powerpc_isa207_vsx64l = result;
190f2a
 }
190f2a
diff --git a/gdb/features/rs6000/powerpc-isa207-vsx64l.xml b/gdb/features/rs6000/powerpc-isa207-vsx64l.xml
190f2a
--- a/gdb/features/rs6000/powerpc-isa207-vsx64l.xml
190f2a
+++ b/gdb/features/rs6000/powerpc-isa207-vsx64l.xml
190f2a
@@ -16,4 +16,6 @@
190f2a
   <xi:include href="power-ppr.xml"/>
190f2a
   <xi:include href="power-dscr.xml"/>
190f2a
   <xi:include href="power-tar.xml"/>
190f2a
+  <xi:include href="power-ebb.xml"/>
190f2a
+  <xi:include href="power-linux-pmu.xml"/>
190f2a
 </target>
190f2a
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
190f2a
--- a/gdb/gdbserver/configure.srv
190f2a
+++ b/gdb/gdbserver/configure.srv
190f2a
@@ -249,6 +249,8 @@ case "${target}" in
190f2a
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-dscr.xml"
190f2a
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-ppr.xml"
190f2a
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-tar.xml"
190f2a
+			srv_xmlfiles="${srv_xmlfiles} rs6000/power-ebb.xml"
190f2a
+			srv_xmlfiles="${srv_xmlfiles} rs6000/power-linux-pmu.xml"
190f2a
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-e500l.xml"
190f2a
 			srv_xmlfiles="${srv_xmlfiles} rs6000/power-spe.xml"
190f2a
 			srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-64l.xml"
190f2a
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
190f2a
--- a/gdb/gdbserver/linux-ppc-low.c
190f2a
+++ b/gdb/gdbserver/linux-ppc-low.c
190f2a
@@ -545,6 +545,61 @@ ppc_store_tarregset (struct regcache *regcache, const void *buf)
190f2a
   supply_register_by_name (regcache, "tar", tar);
190f2a
 }
190f2a
 
190f2a
+/* Event-Based Branching regset store function.  Unless the inferior
190f2a
+   has a perf event open, ptrace can return in error when reading and
190f2a
+   writing to the regset, with ENODATA.  For reading, the registers
190f2a
+   will correctly show as unavailable.  For writing, gdbserver
190f2a
+   currently only caches any register writes from P and G packets and
190f2a
+   the stub always tries to write all the regsets when resuming the
190f2a
+   inferior, which would result in frequent warnings.  For this
190f2a
+   reason, we don't define a fill function.  This also means that the
190f2a
+   client-side regcache will be dirty if the user tries to write to
190f2a
+   the EBB registers.  G packets that the client sends to write to
190f2a
+   unrelated registers will also include data for EBB registers, even
190f2a
+   if they are unavailable.  */
190f2a
+
190f2a
+static void
190f2a
+ppc_store_ebbregset (struct regcache *regcache, const void *buf)
190f2a
+{
190f2a
+  const char *regset = (const char *) buf;
190f2a
+
190f2a
+  /* The order in the kernel regset is: EBBRR, EBBHR, BESCR.  In the
190f2a
+     .dat file is BESCR, EBBHR, EBBRR.  */
190f2a
+  supply_register_by_name (regcache, "ebbrr", &regset[0]);
190f2a
+  supply_register_by_name (regcache, "ebbhr", &regset[8]);
190f2a
+  supply_register_by_name (regcache, "bescr", &regset[16]);
190f2a
+}
190f2a
+
190f2a
+/* Performance Monitoring Unit regset fill function.  */
190f2a
+
190f2a
+static void
190f2a
+ppc_fill_pmuregset (struct regcache *regcache, void *buf)
190f2a
+{
190f2a
+  char *regset = (char *) buf;
190f2a
+
190f2a
+  /* The order in the kernel regset is SIAR, SDAR, SIER, MMCR2, MMCR0.
190f2a
+     In the .dat file is MMCR0, MMCR2, SIAR, SDAR, SIER.  */
190f2a
+  collect_register_by_name (regcache, "siar", &regset[0]);
190f2a
+  collect_register_by_name (regcache, "sdar", &regset[8]);
190f2a
+  collect_register_by_name (regcache, "sier", &regset[16]);
190f2a
+  collect_register_by_name (regcache, "mmcr2", &regset[24]);
190f2a
+  collect_register_by_name (regcache, "mmcr0", &regset[32]);
190f2a
+}
190f2a
+
190f2a
+/* Performance Monitoring Unit regset store function.  */
190f2a
+
190f2a
+static void
190f2a
+ppc_store_pmuregset (struct regcache *regcache, const void *buf)
190f2a
+{
190f2a
+  const char *regset = (const char *) buf;
190f2a
+
190f2a
+  supply_register_by_name (regcache, "siar", &regset[0]);
190f2a
+  supply_register_by_name (regcache, "sdar", &regset[8]);
190f2a
+  supply_register_by_name (regcache, "sier", &regset[16]);
190f2a
+  supply_register_by_name (regcache, "mmcr2", &regset[24]);
190f2a
+  supply_register_by_name (regcache, "mmcr0", &regset[32]);
190f2a
+}
190f2a
+
190f2a
 static void
190f2a
 ppc_fill_vsxregset (struct regcache *regcache, void *buf)
190f2a
 {
190f2a
@@ -654,6 +709,10 @@ static struct regset_info ppc_regsets[] = {
190f2a
      fetch them every time, but still fall back to PTRACE_PEEKUSER for the
190f2a
      general registers.  Some kernels support these, but not the newer
190f2a
      PPC_PTRACE_GETREGS.  */
190f2a
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_EBB, 0, EXTENDED_REGS,
190f2a
+    NULL, ppc_store_ebbregset },
190f2a
+  { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_PMU, 0, EXTENDED_REGS,
190f2a
+    ppc_fill_pmuregset, ppc_store_pmuregset },
190f2a
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_TAR, 0, EXTENDED_REGS,
190f2a
     ppc_fill_tarregset, ppc_store_tarregset },
190f2a
   { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PPC_PPR, 0, EXTENDED_REGS,
190f2a
@@ -734,8 +793,13 @@ ppc_arch_setup (void)
190f2a
       features.ppr_dscr = true;
190f2a
       if ((ppc_hwcap2 & PPC_FEATURE2_ARCH_2_07)
190f2a
 	  && (ppc_hwcap2 & PPC_FEATURE2_TAR)
190f2a
+	  && (ppc_hwcap2 & PPC_FEATURE2_EBB)
190f2a
 	  && ppc_check_regset (tid, NT_PPC_TAR,
190f2a
-			       PPC_LINUX_SIZEOF_TARREGSET))
190f2a
+			       PPC_LINUX_SIZEOF_TARREGSET)
190f2a
+	  && ppc_check_regset (tid, NT_PPC_EBB,
190f2a
+			       PPC_LINUX_SIZEOF_EBBREGSET)
190f2a
+	  && ppc_check_regset (tid, NT_PPC_PMU,
190f2a
+			       PPC_LINUX_SIZEOF_PMUREGSET))
190f2a
 	features.isa207 = true;
190f2a
     }
190f2a
 
190f2a
@@ -798,6 +862,14 @@ ppc_arch_setup (void)
190f2a
 	    regset->size = (features.isa207 ?
190f2a
 			    PPC_LINUX_SIZEOF_TARREGSET : 0);
190f2a
 	    break;
190f2a
+	  case NT_PPC_EBB:
190f2a
+	    regset->size = (features.isa207 ?
190f2a
+			    PPC_LINUX_SIZEOF_EBBREGSET : 0);
190f2a
+	    break;
190f2a
+	  case NT_PPC_PMU:
190f2a
+	    regset->size = (features.isa207 ?
190f2a
+			    PPC_LINUX_SIZEOF_PMUREGSET : 0);
190f2a
+	    break;
190f2a
 	  default:
190f2a
 	    break;
190f2a
 	  }
190f2a
diff --git a/gdb/nat/ppc-linux.h b/gdb/nat/ppc-linux.h
190f2a
--- a/gdb/nat/ppc-linux.h
190f2a
+++ b/gdb/nat/ppc-linux.h
190f2a
@@ -60,6 +60,9 @@
190f2a
 #ifndef PPC_FEATURE2_TAR
190f2a
 #define PPC_FEATURE2_TAR 0x04000000
190f2a
 #endif
190f2a
+#ifndef PPC_FEATURE2_EBB
190f2a
+#define PPC_FEATURE2_EBB 0x10000000
190f2a
+#endif
190f2a
 
190f2a
 /* Glibc's headers don't define PTRACE_GETVRREGS so we cannot use a
190f2a
    configure time check.  Some older glibc's (for instance 2.2.1)
190f2a
@@ -106,6 +109,16 @@
190f2a
 #define NT_PPC_DSCR 0x105
190f2a
 #endif
190f2a
 
190f2a
+/* Event Based Branch Registers.  */
190f2a
+#ifndef NT_PPC_EBB
190f2a
+#define NT_PPC_EBB 0x106
190f2a
+#endif
190f2a
+
190f2a
+/* Performance Monitor Registers.  */
190f2a
+#ifndef NT_PPC_PMU
190f2a
+#define NT_PPC_PMU 0x107
190f2a
+#endif
190f2a
+
190f2a
 /* Return the wordsize of the target, either 4 or 8 bytes.  */
190f2a
 int ppc_linux_target_wordsize (int tid);
190f2a
 
190f2a
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
190f2a
--- a/gdb/ppc-linux-nat.c
190f2a
+++ b/gdb/ppc-linux-nat.c
190f2a
@@ -667,6 +667,24 @@ fetch_register (struct regcache *regcache, int tid, int regno)
190f2a
 		    &ppc32_linux_tarregset);
190f2a
       return;
190f2a
     }
190f2a
+  else if (PPC_IS_EBB_REGNUM (regno))
190f2a
+    {
190f2a
+      gdb_assert (tdep->have_ebb);
190f2a
+
190f2a
+      fetch_regset (regcache, tid, NT_PPC_EBB,
190f2a
+		    PPC_LINUX_SIZEOF_EBBREGSET,
190f2a
+		    &ppc32_linux_ebbregset);
190f2a
+      return;
190f2a
+    }
190f2a
+  else if (PPC_IS_PMU_REGNUM (regno))
190f2a
+    {
190f2a
+      gdb_assert (tdep->ppc_mmcr0_regnum != -1);
190f2a
+
190f2a
+      fetch_regset (regcache, tid, NT_PPC_PMU,
190f2a
+		    PPC_LINUX_SIZEOF_PMUREGSET,
190f2a
+		    &ppc32_linux_pmuregset);
190f2a
+      return;
190f2a
+    }
190f2a
 
190f2a
   if (regaddr == -1)
190f2a
     {
190f2a
@@ -875,6 +893,14 @@ fetch_ppc_registers (struct regcache *regcache, int tid)
190f2a
     fetch_regset (regcache, tid, NT_PPC_TAR,
190f2a
 		  PPC_LINUX_SIZEOF_TARREGSET,
190f2a
 		  &ppc32_linux_tarregset);
190f2a
+  if (tdep->have_ebb)
190f2a
+    fetch_regset (regcache, tid, NT_PPC_EBB,
190f2a
+		  PPC_LINUX_SIZEOF_EBBREGSET,
190f2a
+		  &ppc32_linux_ebbregset);
190f2a
+  if (tdep->ppc_mmcr0_regnum != -1)
190f2a
+    fetch_regset (regcache, tid, NT_PPC_PMU,
190f2a
+		  PPC_LINUX_SIZEOF_PMUREGSET,
190f2a
+		  &ppc32_linux_pmuregset);
190f2a
 }
190f2a
 
190f2a
 /* Fetch registers from the child process.  Fetch all registers if
190f2a
@@ -1082,6 +1108,24 @@ store_register (const struct regcache *regcache, int tid, int regno)
190f2a
 		    &ppc32_linux_tarregset);
190f2a
       return;
190f2a
     }
190f2a
+  else if (PPC_IS_EBB_REGNUM (regno))
190f2a
+    {
190f2a
+      gdb_assert (tdep->have_ebb);
190f2a
+
190f2a
+      store_regset (regcache, tid, regno, NT_PPC_EBB,
190f2a
+		    PPC_LINUX_SIZEOF_EBBREGSET,
190f2a
+		    &ppc32_linux_ebbregset);
190f2a
+      return;
190f2a
+    }
190f2a
+  else if (PPC_IS_PMU_REGNUM (regno))
190f2a
+    {
190f2a
+      gdb_assert (tdep->ppc_mmcr0_regnum != -1);
190f2a
+
190f2a
+      store_regset (regcache, tid, regno, NT_PPC_PMU,
190f2a
+		    PPC_LINUX_SIZEOF_PMUREGSET,
190f2a
+		    &ppc32_linux_pmuregset);
190f2a
+      return;
190f2a
+    }
190f2a
 
190f2a
   if (regaddr == -1)
190f2a
     return;
190f2a
@@ -1308,6 +1352,15 @@ store_ppc_registers (const struct regcache *regcache, int tid)
190f2a
     store_regset (regcache, tid, -1, NT_PPC_TAR,
190f2a
 		  PPC_LINUX_SIZEOF_TARREGSET,
190f2a
 		  &ppc32_linux_tarregset);
190f2a
+
190f2a
+  if (tdep->ppc_mmcr0_regnum != -1)
190f2a
+    store_regset (regcache, tid, -1, NT_PPC_PMU,
190f2a
+		  PPC_LINUX_SIZEOF_PMUREGSET,
190f2a
+		  &ppc32_linux_pmuregset);
190f2a
+
190f2a
+  /* Because the EBB registers can be unavailable, attempts to store
190f2a
+     them here would cause this function to fail most of the time, so
190f2a
+     we ignore them.  */
190f2a
 }
190f2a
 
190f2a
 /* Fetch the AT_HWCAP entry from the aux vector.  */
190f2a
@@ -2439,7 +2492,10 @@ ppc_linux_nat_target::read_description ()
190f2a
       features.ppr_dscr = true;
190f2a
       if ((hwcap2 & PPC_FEATURE2_ARCH_2_07)
190f2a
 	  && (hwcap2 & PPC_FEATURE2_TAR)
190f2a
-	  && check_regset (tid, NT_PPC_TAR, PPC_LINUX_SIZEOF_TARREGSET))
190f2a
+	  && (hwcap2 & PPC_FEATURE2_EBB)
190f2a
+	  && check_regset (tid, NT_PPC_TAR, PPC_LINUX_SIZEOF_TARREGSET)
190f2a
+	  && check_regset (tid, NT_PPC_EBB, PPC_LINUX_SIZEOF_EBBREGSET)
190f2a
+	  && check_regset (tid, NT_PPC_PMU, PPC_LINUX_SIZEOF_PMUREGSET))
190f2a
 	features.isa207 = true;
190f2a
     }
190f2a
 
190f2a
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
190f2a
--- a/gdb/ppc-linux-tdep.c
190f2a
+++ b/gdb/ppc-linux-tdep.c
190f2a
@@ -599,6 +599,44 @@ const struct regset ppc32_linux_tarregset = {
190f2a
   regcache_collect_regset
190f2a
 };
190f2a
 
190f2a
+/* Event-Based Branching regmap.  */
190f2a
+
190f2a
+static const struct regcache_map_entry ppc32_regmap_ebb[] =
190f2a
+  {
190f2a
+      { 1, PPC_EBBRR_REGNUM, 8 },
190f2a
+      { 1, PPC_EBBHR_REGNUM, 8 },
190f2a
+      { 1, PPC_BESCR_REGNUM, 8 },
190f2a
+      { 0 }
190f2a
+  };
190f2a
+
190f2a
+/* Event-Based Branching regset.  */
190f2a
+
190f2a
+const struct regset ppc32_linux_ebbregset = {
190f2a
+  ppc32_regmap_ebb,
190f2a
+  regcache_supply_regset,
190f2a
+  regcache_collect_regset
190f2a
+};
190f2a
+
190f2a
+/* Performance Monitoring Unit regmap.  */
190f2a
+
190f2a
+static const struct regcache_map_entry ppc32_regmap_pmu[] =
190f2a
+  {
190f2a
+      { 1, PPC_SIAR_REGNUM, 8 },
190f2a
+      { 1, PPC_SDAR_REGNUM, 8 },
190f2a
+      { 1, PPC_SIER_REGNUM, 8 },
190f2a
+      { 1, PPC_MMCR2_REGNUM, 8 },
190f2a
+      { 1, PPC_MMCR0_REGNUM, 8 },
190f2a
+      { 0 }
190f2a
+  };
190f2a
+
190f2a
+/* Performance Monitoring Unit regset.  */
190f2a
+
190f2a
+const struct regset ppc32_linux_pmuregset = {
190f2a
+  ppc32_regmap_pmu,
190f2a
+  regcache_supply_regset,
190f2a
+  regcache_collect_regset
190f2a
+};
190f2a
+
190f2a
 const struct regset *
190f2a
 ppc_linux_gregset (int wordsize)
190f2a
 {
190f2a
@@ -674,6 +712,22 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
190f2a
     cb (".reg-ppc-tar", PPC_LINUX_SIZEOF_TARREGSET,
190f2a
 	PPC_LINUX_SIZEOF_TARREGSET,
190f2a
 	&ppc32_linux_tarregset, "Target Address Register", cb_data);
190f2a
+
190f2a
+  /* EBB registers are unavailable when ptrace returns ENODATA.  Check
190f2a
+     availability when generating a core file (regcache != NULL).  */
190f2a
+  if (tdep->have_ebb)
190f2a
+    if (regcache == NULL
190f2a
+	|| REG_VALID == regcache->get_register_status (PPC_BESCR_REGNUM))
190f2a
+      cb (".reg-ppc-ebb", PPC_LINUX_SIZEOF_EBBREGSET,
190f2a
+	  PPC_LINUX_SIZEOF_EBBREGSET,
190f2a
+	  &ppc32_linux_ebbregset, "Event-based Branching Registers",
190f2a
+	  cb_data);
190f2a
+
190f2a
+  if (tdep->ppc_mmcr0_regnum != -1)
190f2a
+    cb (".reg-ppc-pmu", PPC_LINUX_SIZEOF_PMUREGSET,
190f2a
+	PPC_LINUX_SIZEOF_PMUREGSET,
190f2a
+	&ppc32_linux_pmuregset, "Performance Monitor Registers",
190f2a
+	cb_data);
190f2a
 }
190f2a
 
190f2a
 static void
190f2a
@@ -1089,6 +1143,7 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
190f2a
   asection *ppr = bfd_get_section_by_name (abfd, ".reg-ppc-ppr");
190f2a
   asection *dscr = bfd_get_section_by_name (abfd, ".reg-ppc-dscr");
190f2a
   asection *tar = bfd_get_section_by_name (abfd, ".reg-ppc-tar");
190f2a
+  asection *pmu = bfd_get_section_by_name (abfd, ".reg-ppc-pmu");
190f2a
 
190f2a
   if (! section)
190f2a
     return NULL;
190f2a
@@ -1124,7 +1179,12 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
190f2a
   if (ppr && dscr)
190f2a
     {
190f2a
       features.ppr_dscr = true;
190f2a
-      if (tar)
190f2a
+
190f2a
+      /* We don't require the EBB note section to be present in the
190f2a
+	 core file to select isa207 because these registers could have
190f2a
+	 been unavailable when the core file was created.  They will
190f2a
+	 be in the tdep but will show as unavailable.  */
190f2a
+      if (tar && pmu)
190f2a
 	features.isa207 = true;
190f2a
     }
190f2a
 
190f2a
diff --git a/gdb/ppc-linux-tdep.h b/gdb/ppc-linux-tdep.h
190f2a
--- a/gdb/ppc-linux-tdep.h
190f2a
+++ b/gdb/ppc-linux-tdep.h
190f2a
@@ -48,5 +48,7 @@ int ppc_linux_trap_reg_p (struct gdbarch *gdbarch);
190f2a
 extern const struct regset ppc32_linux_pprregset;
190f2a
 extern const struct regset ppc32_linux_dscrregset;
190f2a
 extern const struct regset ppc32_linux_tarregset;
190f2a
+extern const struct regset ppc32_linux_ebbregset;
190f2a
+extern const struct regset ppc32_linux_pmuregset;
190f2a
 
190f2a
 #endif /* PPC_LINUX_TDEP_H */
190f2a
diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h
190f2a
--- a/gdb/ppc-tdep.h
190f2a
+++ b/gdb/ppc-tdep.h
190f2a
@@ -265,6 +265,15 @@ struct gdbarch_tdep
190f2a
     /* Decimal 128 registers.  */
190f2a
     int ppc_dl0_regnum;		/* First Decimal128 argument register pair.  */
190f2a
 
190f2a
+    int have_ebb;
190f2a
+
190f2a
+    /* PMU registers.  */
190f2a
+    int ppc_mmcr0_regnum;
190f2a
+    int ppc_mmcr2_regnum;
190f2a
+    int ppc_siar_regnum;
190f2a
+    int ppc_sdar_regnum;
190f2a
+    int ppc_sier_regnum;
190f2a
+
190f2a
     /* Offset to ABI specific location where link register is saved.  */
190f2a
     int lr_frame_offset;	
190f2a
 
190f2a
@@ -321,12 +330,31 @@ enum {
190f2a
   PPC_PPR_REGNUM = 172,
190f2a
   PPC_DSCR_REGNUM = 173,
190f2a
   PPC_TAR_REGNUM = 174,
190f2a
+
190f2a
+  /* EBB registers.  */
190f2a
+  PPC_BESCR_REGNUM = 175,
190f2a
+  PPC_EBBHR_REGNUM = 176,
190f2a
+  PPC_EBBRR_REGNUM = 177,
190f2a
+
190f2a
+  /* PMU registers.  */
190f2a
+  PPC_MMCR0_REGNUM = 178,
190f2a
+  PPC_MMCR2_REGNUM = 179,
190f2a
+  PPC_SIAR_REGNUM = 180,
190f2a
+  PPC_SDAR_REGNUM = 181,
190f2a
+  PPC_SIER_REGNUM = 182,
190f2a
+
190f2a
   PPC_NUM_REGS
190f2a
 };
190f2a
 
190f2a
 /* Big enough to hold the size of the largest register in bytes.  */
190f2a
 #define PPC_MAX_REGISTER_SIZE	64
190f2a
 
190f2a
+#define PPC_IS_EBB_REGNUM(i) \
190f2a
+	((i) >= PPC_BESCR_REGNUM && (i) <= PPC_EBBRR_REGNUM)
190f2a
+
190f2a
+#define PPC_IS_PMU_REGNUM(i) \
190f2a
+	((i) >= PPC_MMCR0_REGNUM && (i) <= PPC_SIER_REGNUM)
190f2a
+
190f2a
 /* An instruction to match.  */
190f2a
 
190f2a
 struct ppc_insn_pattern
190f2a
diff --git a/gdb/regformats/rs6000/powerpc-isa207-vsx32l.dat b/gdb/regformats/rs6000/powerpc-isa207-vsx32l.dat
190f2a
--- a/gdb/regformats/rs6000/powerpc-isa207-vsx32l.dat
190f2a
+++ b/gdb/regformats/rs6000/powerpc-isa207-vsx32l.dat
190f2a
@@ -145,3 +145,11 @@ expedite:r1,pc
190f2a
 64:ppr
190f2a
 64:dscr
190f2a
 64:tar
190f2a
+64:bescr
190f2a
+64:ebbhr
190f2a
+64:ebbrr
190f2a
+64:mmcr0
190f2a
+64:mmcr2
190f2a
+64:siar
190f2a
+64:sdar
190f2a
+64:sier
190f2a
diff --git a/gdb/regformats/rs6000/powerpc-isa207-vsx64l.dat b/gdb/regformats/rs6000/powerpc-isa207-vsx64l.dat
190f2a
--- a/gdb/regformats/rs6000/powerpc-isa207-vsx64l.dat
190f2a
+++ b/gdb/regformats/rs6000/powerpc-isa207-vsx64l.dat
190f2a
@@ -145,3 +145,11 @@ expedite:r1,pc
190f2a
 64:ppr
190f2a
 64:dscr
190f2a
 64:tar
190f2a
+64:bescr
190f2a
+64:ebbhr
190f2a
+64:ebbrr
190f2a
+64:mmcr0
190f2a
+64:mmcr2
190f2a
+64:siar
190f2a
+64:sdar
190f2a
+64:sier
190f2a
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
190f2a
--- a/gdb/rs6000-tdep.c
190f2a
+++ b/gdb/rs6000-tdep.c
190f2a
@@ -5871,7 +5871,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
190f2a
   enum powerpc_elf_abi elf_abi = POWERPC_ELF_AUTO;
190f2a
   int have_fpu = 0, have_spe = 0, have_mq = 0, have_altivec = 0;
190f2a
   int have_dfp = 0, have_vsx = 0, have_ppr = 0, have_dscr = 0;
190f2a
-  int have_tar = 0;
190f2a
+  int have_tar = 0, have_ebb = 0, have_pmu = 0;
190f2a
   int tdesc_wordsize = -1;
190f2a
   const struct target_desc *tdesc = info.target_desc;
190f2a
   struct tdesc_arch_data *tdesc_data = NULL;
190f2a
@@ -6211,6 +6211,64 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
190f2a
 	}
190f2a
       else
190f2a
 	have_tar = 0;
190f2a
+
190f2a
+      /* Event-based Branching Registers.  */
190f2a
+      feature = tdesc_find_feature (tdesc,
190f2a
+				    "org.gnu.gdb.power.ebb");
190f2a
+      if (feature != NULL)
190f2a
+	{
190f2a
+	  static const char *const ebb_regs[] = {
190f2a
+	    "bescr", "ebbhr", "ebbrr"
190f2a
+	  };
190f2a
+
190f2a
+	  valid_p = 1;
190f2a
+	  for (i = 0; i < ARRAY_SIZE (ebb_regs); i++)
190f2a
+	    valid_p &= tdesc_numbered_register (feature, tdesc_data,
190f2a
+						PPC_BESCR_REGNUM + i,
190f2a
+						ebb_regs[i]);
190f2a
+	  if (!valid_p)
190f2a
+	    {
190f2a
+	      tdesc_data_cleanup (tdesc_data);
190f2a
+	      return NULL;
190f2a
+	    }
190f2a
+	  have_ebb = 1;
190f2a
+	}
190f2a
+      else
190f2a
+	have_ebb = 0;
190f2a
+
190f2a
+      /* Subset of the ISA 2.07 Performance Monitor Registers provided
190f2a
+	 by Linux.  */
190f2a
+      feature = tdesc_find_feature (tdesc,
190f2a
+				    "org.gnu.gdb.power.linux.pmu");
190f2a
+      if (feature != NULL)
190f2a
+	{
190f2a
+	  valid_p = 1;
190f2a
+
190f2a
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
190f2a
+					      PPC_MMCR0_REGNUM,
190f2a
+					      "mmcr0");
190f2a
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
190f2a
+					      PPC_MMCR2_REGNUM,
190f2a
+					      "mmcr2");
190f2a
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
190f2a
+					      PPC_SIAR_REGNUM,
190f2a
+					      "siar");
190f2a
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
190f2a
+					      PPC_SDAR_REGNUM,
190f2a
+					      "sdar");
190f2a
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
190f2a
+					      PPC_SIER_REGNUM,
190f2a
+					      "sier");
190f2a
+
190f2a
+	  if (!valid_p)
190f2a
+	    {
190f2a
+	      tdesc_data_cleanup (tdesc_data);
190f2a
+	      return NULL;
190f2a
+	    }
190f2a
+	  have_pmu = 1;
190f2a
+	}
190f2a
+      else
190f2a
+	have_pmu = 0;
190f2a
     }
190f2a
 
190f2a
   /* If we have a 64-bit binary on a 32-bit target, complain.  Also
190f2a
@@ -6408,6 +6466,20 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
190f2a
   tdep->ppc_ppr_regnum = have_ppr ? PPC_PPR_REGNUM : -1;
190f2a
   tdep->ppc_dscr_regnum = have_dscr ? PPC_DSCR_REGNUM : -1;
190f2a
   tdep->ppc_tar_regnum = have_tar ? PPC_TAR_REGNUM : -1;
190f2a
+  tdep->have_ebb = have_ebb;
190f2a
+
190f2a
+  /* If additional pmu registers are added, care must be taken when
190f2a
+     setting new fields in the tdep below, to maintain compatibility
190f2a
+     with features that only provide some of the registers.  Currently
190f2a
+     gdb access to the pmu registers is only supported in linux, and
190f2a
+     linux only provides a subset of the pmu registers defined in the
190f2a
+     architecture.  */
190f2a
+
190f2a
+  tdep->ppc_mmcr0_regnum = have_pmu ? PPC_MMCR0_REGNUM : -1;
190f2a
+  tdep->ppc_mmcr2_regnum = have_pmu ? PPC_MMCR2_REGNUM : -1;
190f2a
+  tdep->ppc_siar_regnum = have_pmu ? PPC_SIAR_REGNUM : -1;
190f2a
+  tdep->ppc_sdar_regnum = have_pmu ? PPC_SDAR_REGNUM : -1;
190f2a
+  tdep->ppc_sier_regnum = have_pmu ? PPC_SIER_REGNUM : -1;
190f2a
 
190f2a
   set_gdbarch_pc_regnum (gdbarch, PPC_PC_REGNUM);
190f2a
   set_gdbarch_sp_regnum (gdbarch, PPC_R0_REGNUM + 1);