summaryrefslogtreecommitdiff
path: root/gdb/ppc-linux-tdep.c
diff options
context:
space:
mode:
authorEdjunior Barbosa Machado <emachado@linux.vnet.ibm.com>2018-10-26 09:37:55 -0300
committerPedro Franco de Carvalho <pedromfc@linux.ibm.com>2018-10-26 10:23:01 -0300
commit8d619c01db64c533df3ffc706b694f293347f0d8 (patch)
treeec5d3f9d27708105e80c8e5f1b7aa426c2929a75 /gdb/ppc-linux-tdep.c
parent81ab84fd6cdaab121988e0c424f8cdc0ae472e14 (diff)
downloadbinutils-gdb-8d619c01db64c533df3ffc706b694f293347f0d8.tar.gz
[PowerPC] Add support for HTM registers
This patch adds support for Hardware Transactional Memory registers for the powerpc linux native and core file targets, and for the pwoerpc linux server stub. These registers include both the HTM special-purpose registers (TFHAR, TEXASR and TFIAR) as well as the set of registers that are checkpointed (saved) when a transaction is initiated, which the processor restores in the event of a transaction failure. The set of checkpointed general-purpose registers is returned by the linux kernel in the same format as the regular general-purpose registers, defined in struct pt_regs. However, the architecture specifies that only some of the registers present in pt_regs are checkpointed (GPRs 0-31, CR, XER, LR and CTR). The kernel fills the slots for MSR and NIP with other info. The other fields usually don't have meaningful values. GDB doesn't define registers that are not checkpointed in the architecture, but when generating a core file, GDB fills the slot for the checkpointed MSR with the regular MSR. These are usually similar, although some bits might be different, and in some cases the checkpointed MSR will have a value of 0 in a kernel-generated core-file. The checkpointed NIP is filled with TFHAR by GDB in the core-file, which is what the kernel does. The other fields are set to 0 by GDB. Core files generated by the kernel have a note section for checkpointed GPRs with the same size for both 32-bit and 64-bit threads, and the values for the registers of a 32-bit thread are squeezed in the first half, with no useful data in the second half. GDB generates a smaller note section for 32-bit threads, but can read both sizes. The checkpointed XER is required to be 32-bit in the target description documentation, even though the more recent ISAs define it as 64-bit wide, since the high-order 32-bits are reserved, and because in Linux there is no way to get a 64-bit checkpointed XER for 32-bit threads. If this changes in the future, the target description feature requirement can be relaxed to allow for a 64-bit checkpointed XER. Access to the checkpointed CR (condition register) can be confusing. The architecture only specifies that CR fields 1 to 7 (the 24 least significant bits) are checkpointed, but the kernel provides all 8 fields (32 bits). The value of field 0 is not masked by ptrace, so it will sometimes show the result of some kernel operation, probably treclaim., which sets this field. The checkpointed registers are marked not to be saved and restored. Inferior function calls during an active transaction don't work well, and it's unclear what should be done in this case. TEXASR and TFIAR can be altered asynchronously, during transaction failure recording, so they are also not saved and restored. For consistency neither is TFHAR. Record and replay also doesn't work well when transactions are involved. This patch doesn't address this, so the values of the HTM SPRs will sometimes be innacurate when the record/relay target is enabled. For instance, executing a "tbegin." alters TFHAR and TEXASR, but these changes are not currently recorded. Because the checkpointed registers are only available when a transaction is active (or suspended), ptrace can return ENODATA when gdb tries to read these registers and the inferior is not in a transactional state. The registers are set to the unavailable state when this happens. When gbd tries to write to one of these registers, and it is unavailable, an error is raised. The "fill" functions for checkpointed register sets in the server stub are not implemented for the same reason as for the EBB register set, since ptrace can also return ENODATA for checkpointed regsets. The same issues with 'G' packets apply here. Just like for the EBB registers, tracepoints will not mark the checkpointed registers as unavailable if the inferior was not in a transaction, so their content will also show 0 instead of <unavailable> when inspecting trace data. The new tests record the values of the regular registers before stepping the inferior through a "tbegin." instruction to start a transaction, then the checkpointed registers are checked against the recorded pre-transactional values. New values are written to the checkpointed registers and recorded, the inferior continues until the transaction aborts (which is usually immediately when it is resumed), and the regular registers are checked against the recorded values, because the abort should have reverted the registers to these values. Like for the EBB registers, target_store_registers will ignore the checkpointed registers when called with -1 as the regno argument (store all registers in one go). gdb/ChangeLog: 2018-10-26 Edjunior Barbosa Machado <emachado@linux.vnet.ibm.com> Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * arch/ppc-linux-tdesc.h (tdesc_powerpc_isa207_htm_vsx32l) (tdesc_powerpc_isa207_htm_vsx64l): Declare. * arch/ppc-linux-common.h (PPC_LINUX_SIZEOF_TM_SPRREGSET) (PPC32_LINUX_SIZEOF_CGPRREGSET, PPC64_LINUX_SIZEOF_CGPRREGSET) (PPC_LINUX_SIZEOF_CFPRREGSET, PPC_LINUX_SIZEOF_CVMXREGSET) (PPC_LINUX_SIZEOF_CVSXREGSET, PPC_LINUX_SIZEOF_CPPRREGSET) (PPC_LINUX_SIZEOF_CDSCRREGSET, PPC_LINUX_SIZEOF_CTARREGSET): Define. (struct ppc_linux_features) <htm>: New field. (ppc_linux_no_features): Add initializer for htm field. * arch/ppc-linux-common.c (ppc_linux_match_description): Return new tdescs. * nat/ppc-linux.h (PPC_FEATURE2_HTM, NT_PPC_TM_CGPR) (NT_PPC_TM_CFPR, NT_PPC_TM_CVMX, NT_PPC_TM_CVSX) (NT_PPC_TM_SPR, NT_PPC_TM_CTAR, NT_PPC_TM_CPPR, NT_PPC_TM_CDSCR): Define if not already defined. * features/Makefile (WHICH): Add rs6000/powerpc-isa207-htm-vsx32l and rs6000/powerpc-isa207-htm-vsx64l. (XMLTOC): Add rs6000/powerpc-isa207-htm-vsx32l.xml and rs6000/powerpc-isa207-htm-vsx64l.xml. * features/rs6000/power-htm-spr.xml: New file. * features/rs6000/power-htm-core.xml: New file. * features/rs6000/power64-htm-core.xml: New file. * features/rs6000/power-htm-fpu.xml: New file. * features/rs6000/power-htm-altivec.xml: New file. * features/rs6000/power-htm-vsx.xml: New file. * features/rs6000/power-htm-ppr.xml: New file. * features/rs6000/power-htm-dscr.xml: New file. * features/rs6000/power-htm-tar.xml: New file. * features/rs6000/powerpc-isa207-htm-vsx32l.xml: New file. * features/rs6000/powerpc-isa207-htm-vsx64l.xml: New file. * features/rs6000/powerpc-isa207-htm-vsx32l.c: Generate. * features/rs6000/powerpc-isa207-htm-vsx64l.c: Generate. * regformats/rs6000/powerpc-isa207-htm-vsx32l.dat: Generate. * regformats/rs6000/powerpc-isa207-htm-vsx64l.dat: Generate. * ppc-linux-nat.c (fetch_register, fetch_ppc_registers): Call fetch_regset with HTM regsets. (store_register, store_ppc_registers): Call store_regset with HTM regsets. (ppc_linux_nat_target::read_description): Set htm field in the features struct if needed. * ppc-linux-tdep.c: Include features/rs6000/powerpc-isa207-htm-vsx32l.c and features/rs6000/powerpc-isa207-htm-vsx64l.c. (ppc32_regmap_tm_spr, ppc32_regmap_cgpr, ppc64_le_regmap_cgpr) (ppc64_be_regmap_cgpr, ppc32_regmap_cfpr, ppc32_le_regmap_cvmx) (ppc32_be_regmap_cvmx, ppc32_regmap_cvsx, ppc32_regmap_cppr) (ppc32_regmap_cdscr, ppc32_regmap_ctar): New globals. (ppc32_linux_tm_sprregset, ppc32_linux_cgprregset) (ppc64_be_linux_cgprregset, ppc64_le_linux_cgprregset) (ppc32_linux_cfprregset, ppc32_le_linux_cvmxregset) (ppc32_be_linux_cvmxregset, ppc32_linux_cvsxregset) (ppc32_linux_cpprregset, ppc32_linux_cdscrregset) (ppc32_linux_ctarregset): New globals. (ppc_linux_cgprregset, ppc_linux_cvmxregset): New functions. (ppc_linux_collect_core_cpgrregset): New function. (ppc_linux_iterate_over_regset_sections): Call back with the htm regsets. (ppc_linux_core_read_description): Check if the tm spr section is present and set htm in the features struct. (_initialize_ppc_linux_tdep): Call initialize_tdesc_powerpc_isa207_htm_vsx32l and initialize_tdesc_powerpc_isa207_htm_vsx64l. * ppc-linux-tdep.h (ppc_linux_cgprregset, ppc_linux_cvmxregset): Declare. (ppc32_linux_tm_sprregset, ppc32_linux_cfprregset) (ppc32_linux_cvsxregset, ppc32_linux_cpprregset) (ppc32_linux_cdscrregset, ppc32_linux_ctarregset): Declare. * ppc-tdep.h (struct gdbarch_tdep) <have_htm_spr, have_htm_core>: New fields. <have_htm_fpu, have_htm_altivec, have_htm_vsx>: Likewise. <ppc_cppr_regnum, ppc_cdscr_regnum, ppc_ctar_regnum>: Likewise. <ppc_cdl0_regnum, ppc_cvsr0_regnum, ppc_cefpr0_regnum>: Likewise. (enum) <PPC_TFHAR_REGNUM, PPC_TEXASR_REGNUM, PPC_TFIAR_REGNUM>: New enum fields. <PPC_CR0_REGNUM, PPC_CCR_REGNUM, PPC_CXER_REGNUM>: Likewise. <PPC_CLR_REGNUM, PPC_CCTR_REGNUM, PPC_CF0_REGNUM>: Likewise. <PPC_CFPSCR_REGNUM, PPC_CVR0_REGNUM, PPC_CVSCR_REGNUM>: Likewise. <PPC_CVRSAVE_REGNUM, PPC_CVSR0_UPPER_REGNUM>: Likewise. <PPC_CPPR_REGNUM, PPC_CDSCR_REGNUM>: Likewise. <PPC_CTAR_REGNUM>: Likewise. (PPC_IS_TMSPR_REGNUM, PPC_IS_CKPTGP_REGNUM, PPC_IS_CKPTFP_REGNUM) (PPC_IS_CKPTVMX_REGNUM, PPC_IS_CKPTVSX_REGNUM): Define. * rs6000-tdep.c (IS_CDFP_PSEUDOREG, IS_CVSX_PSEUDOREG) (IS_CEFP_PSEUDOREG): Define. (rs6000_register_name): Hide the upper halves of checkpointed VSX registers. Return names for the checkpointed DFP, VSX, and EFP pseudo registers. (rs6000_pseudo_register_type): Remove initial assert and raise an internal error in the else clause instead. Return types for the checkpointed DFP, VSX, and EFP pseudo registers. (dfp_pseudo_register_read, dfp_pseudo_register_write): Handle checkpointed DFP pseudo registers. (vsx_pseudo_register_read, vsx_pseudo_register_write): Handle checkpointed VSX pseudo registers. (efp_pseudo_register_read, efp_pseudo_register_write): Rename from efpr_pseudo_register_read and efpr_pseudo_register_write. Handle checkpointed EFP pseudo registers. (rs6000_pseudo_register_read, rs6000_pseudo_register_write): Handle checkpointed DFP, VSX, and EFP registers. (dfp_ax_pseudo_register_collect, vsx_ax_pseudo_register_collect) (efp_ax_pseudo_register_collect): New functions. (rs6000_ax_pseudo_register_collect): Move DFP, VSX and EFP pseudo register logic to new functions. Handle checkpointed DFP, VSX, and EFP pseudo registers. (rs6000_gdbarch_init): Look for and validate the htm features. Include checkpointed DFP, VSX and EFP pseudo-registers. * NEWS: Mention access to PPR, DSCR, TAR, EBB/PMU registers and HTM registers. gdb/gdbserver/ChangeLog: 2018-10-26 Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * configure.srv (ipa_ppc_linux_regobj): Add powerpc-isa207-htm-vsx32l-ipa.o and powerpc-isa207-htm-vsx64l-ipa.o. (powerpc*-*-linux*): Add powerpc-isa207-htm-vsx32l.o and powerpc-isa207-htm-vsx64l.o to srv_regobj. Add rs6000/power-htm-spr.xml, rs6000/power-htm-core.xml, rs6000/power64-htm-core.xml, rs6000/power-htm-fpu.xml, rs6000/power-htm-altivec.xml, rs6000/power-htm-vsx.xml, rs6000/power-htm-ppr.xml, rs6000/power-htm-dscr.xml, rs6000/power-htm-tar.xml, rs6000/powerpc-isa207-htm-vsx32l.xml, and rs6000/powerpc-isa207-htm-vsx64l.xml to srv_xmlfiles. * linux-ppc-tdesc-init.h (enum ppc_linux_tdesc) <PPC_TDESC_ISA207_HTM_VSX>: New enum value. (init_registers_powerpc_isa207_htm_vsx32l) (init_registers_powerpc_isa207_htm_vsx64l): Declare. * linux-ppc-low.c (ppc_fill_tm_sprregset, ppc_store_tm_sprregset) (ppc_store_tm_cgprregset, ppc_store_tm_cfprregset) (ppc_store_tm_cvrregset, ppc_store_tm_cvsxregset) (ppc_store_tm_cpprregset, ppc_store_tm_cdscrregset) (ppc_store_tm_ctarregset): New functions. (ppc_regsets): Add entries for HTM regsets. (ppc_arch_setup): Set htm in features struct when needed. Set sizes for the HTM regsets. (ppc_get_ipa_tdesc_idx): Return PPC_TDESC_ISA207_HTM_VSX. (initialize_low_arch): Call init_registers_powerpc_isa207_htm_vsx32l and init_registers_powerpc_isa207_htm_vsx64l. * linux-ppc-ipa.c (get_ipa_tdesc): Handle PPC_TDESC_ISA207_HTM_VSX. (initialize_low_tracepoint): Call init_registers_powerpc_isa207_htm_vsx32l and init_registers_powerpc_isa207_htm_vsx64l. gdb/testsuite/ChangeLog: 2018-10-26 Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * gdb.arch/powerpc-htm-regs.c: New file. * gdb.arch/powerpc-htm-regs.exp: New file. gdb/doc/ChangeLog: 2018-10-26 Pedro Franco de Carvalho <pedromfc@linux.ibm.com> * gdb.texinfo (PowerPC Features): Describe new features "org.gnu.gdb.power.htm.spr", "org.gnu.gdb.power.htm.core", "org.gnu.gdb.power.htm.fpu", "org.gnu.gdb.power.htm.altivec", "org.gnu.gdb.power.htm.vsx", "org.gnu.gdb.power.htm.ppr", "org.gnu.gdb.power.htm.dscr", "org.gnu.gdb.power.htm.tar".
Diffstat (limited to 'gdb/ppc-linux-tdep.c')
-rw-r--r--gdb/ppc-linux-tdep.c441
1 files changed, 440 insertions, 1 deletions
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 337ba67ed01..ed44cbe5552 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -73,6 +73,7 @@
#include "features/rs6000/powerpc-isa205-vsx32l.c"
#include "features/rs6000/powerpc-isa205-ppr-dscr-vsx32l.c"
#include "features/rs6000/powerpc-isa207-vsx32l.c"
+#include "features/rs6000/powerpc-isa207-htm-vsx32l.c"
#include "features/rs6000/powerpc-64l.c"
#include "features/rs6000/powerpc-altivec64l.c"
#include "features/rs6000/powerpc-cell64l.c"
@@ -82,6 +83,7 @@
#include "features/rs6000/powerpc-isa205-vsx64l.c"
#include "features/rs6000/powerpc-isa205-ppr-dscr-vsx64l.c"
#include "features/rs6000/powerpc-isa207-vsx64l.c"
+#include "features/rs6000/powerpc-isa207-htm-vsx64l.c"
#include "features/rs6000/powerpc-e500l.c"
/* Shared library operations for PowerPC-Linux. */
@@ -637,6 +639,239 @@ const struct regset ppc32_linux_pmuregset = {
regcache_collect_regset
};
+/* Hardware Transactional Memory special-purpose register regmap. */
+
+static const struct regcache_map_entry ppc32_regmap_tm_spr[] =
+ {
+ { 1, PPC_TFHAR_REGNUM, 8 },
+ { 1, PPC_TEXASR_REGNUM, 8 },
+ { 1, PPC_TFIAR_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Hardware Transactional Memory special-purpose register regset. */
+
+const struct regset ppc32_linux_tm_sprregset = {
+ ppc32_regmap_tm_spr,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Regmaps for the Hardware Transactional Memory checkpointed
+ general-purpose regsets for 32-bit, 64-bit big-endian, and 64-bit
+ little endian targets. The ptrace and core file buffers for 64-bit
+ targets use 8-byte fields for the 4-byte registers, and the
+ position of the register in the fields depends on the endianess.
+ The 32-bit regmap is the same for both endian types because the
+ fields are all 4-byte long.
+
+ The layout of checkpointed GPR regset is the same as a regular
+ struct pt_regs, but we skip all registers that are not actually
+ checkpointed by the processor (e.g. msr, nip), except when
+ generating a core file. The 64-bit regset is 48 * 8 bytes long.
+ In some 64-bit kernels, the regset for a 32-bit inferior has the
+ same length, but all the registers are squeezed in the first half
+ (48 * 4 bytes). The pt_regs struct calls the regular cr ccr, but
+ we use ccr for "checkpointed condition register". Note that CR
+ (condition register) field 0 is not checkpointed, but the kernel
+ returns all 4 bytes. The skipped registers should not be touched
+ when writing the regset to the inferior (with
+ PTRACE_SETREGSET). */
+
+static const struct regcache_map_entry ppc32_regmap_cgpr[] =
+ {
+ { 32, PPC_CR0_REGNUM, 4 },
+ { 3, REGCACHE_MAP_SKIP, 4 }, /* nip, msr, orig_gpr3. */
+ { 1, PPC_CCTR_REGNUM, 4 },
+ { 1, PPC_CLR_REGNUM, 4 },
+ { 1, PPC_CXER_REGNUM, 4 },
+ { 1, PPC_CCR_REGNUM, 4 },
+ { 9, REGCACHE_MAP_SKIP, 4 }, /* All the rest. */
+ { 0 }
+ };
+
+static const struct regcache_map_entry ppc64_le_regmap_cgpr[] =
+ {
+ { 32, PPC_CR0_REGNUM, 8 },
+ { 3, REGCACHE_MAP_SKIP, 8 },
+ { 1, PPC_CCTR_REGNUM, 8 },
+ { 1, PPC_CLR_REGNUM, 8 },
+ { 1, PPC_CXER_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4 }, /* CXER padding. */
+ { 1, PPC_CCR_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4}, /* CCR padding. */
+ { 9, REGCACHE_MAP_SKIP, 8},
+ { 0 }
+ };
+
+static const struct regcache_map_entry ppc64_be_regmap_cgpr[] =
+ {
+ { 32, PPC_CR0_REGNUM, 8 },
+ { 3, REGCACHE_MAP_SKIP, 8 },
+ { 1, PPC_CCTR_REGNUM, 8 },
+ { 1, PPC_CLR_REGNUM, 8 },
+ { 1, REGCACHE_MAP_SKIP, 4}, /* CXER padding. */
+ { 1, PPC_CXER_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 4}, /* CCR padding. */
+ { 1, PPC_CCR_REGNUM, 4 },
+ { 9, REGCACHE_MAP_SKIP, 8},
+ { 0 }
+ };
+
+/* Regsets for the Hardware Transactional Memory checkpointed
+ general-purpose registers for 32-bit, 64-bit big-endian, and 64-bit
+ little endian targets.
+
+ Some 64-bit kernels generate a checkpointed gpr note section with
+ 48*8 bytes for a 32-bit thread, of which only 48*4 are actually
+ used, so we set the variable size flag in the corresponding regset
+ to accept this case. */
+
+static const struct regset ppc32_linux_cgprregset = {
+ ppc32_regmap_cgpr,
+ regcache_supply_regset,
+ regcache_collect_regset,
+ REGSET_VARIABLE_SIZE
+};
+
+static const struct regset ppc64_be_linux_cgprregset = {
+ ppc64_be_regmap_cgpr,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+static const struct regset ppc64_le_linux_cgprregset = {
+ ppc64_le_regmap_cgpr,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Hardware Transactional Memory checkpointed floating-point regmap. */
+
+static const struct regcache_map_entry ppc32_regmap_cfpr[] =
+ {
+ { 32, PPC_CF0_REGNUM, 8 },
+ { 1, PPC_CFPSCR_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Hardware Transactional Memory checkpointed floating-point regset. */
+
+const struct regset ppc32_linux_cfprregset = {
+ ppc32_regmap_cfpr,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Regmaps for the Hardware Transactional Memory checkpointed vector
+ regsets, for big and little endian targets. The position of the
+ 4-byte VSCR in its 16-byte field depends on the endianess. */
+
+static const struct regcache_map_entry ppc32_le_regmap_cvmx[] =
+ {
+ { 32, PPC_CVR0_REGNUM, 16 },
+ { 1, PPC_CVSCR_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 12 },
+ { 1, PPC_CVRSAVE_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 12 },
+ { 0 }
+ };
+
+static const struct regcache_map_entry ppc32_be_regmap_cvmx[] =
+ {
+ { 32, PPC_CVR0_REGNUM, 16 },
+ { 1, REGCACHE_MAP_SKIP, 12 },
+ { 1, PPC_CVSCR_REGNUM, 4 },
+ { 1, PPC_CVRSAVE_REGNUM, 4 },
+ { 1, REGCACHE_MAP_SKIP, 12},
+ { 0 }
+ };
+
+/* Hardware Transactional Memory checkpointed vector regsets, for little
+ and big endian targets. */
+
+static const struct regset ppc32_le_linux_cvmxregset = {
+ ppc32_le_regmap_cvmx,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+static const struct regset ppc32_be_linux_cvmxregset = {
+ ppc32_be_regmap_cvmx,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Hardware Transactional Memory checkpointed vector-scalar regmap. */
+
+static const struct regcache_map_entry ppc32_regmap_cvsx[] =
+ {
+ { 32, PPC_CVSR0_UPPER_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Hardware Transactional Memory checkpointed vector-scalar regset. */
+
+const struct regset ppc32_linux_cvsxregset = {
+ ppc32_regmap_cvsx,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Hardware Transactional Memory checkpointed Program Priority Register
+ regmap. */
+
+static const struct regcache_map_entry ppc32_regmap_cppr[] =
+ {
+ { 1, PPC_CPPR_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Hardware Transactional Memory checkpointed Program Priority Register
+ regset. */
+
+const struct regset ppc32_linux_cpprregset = {
+ ppc32_regmap_cppr,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Hardware Transactional Memory checkpointed Data Stream Control
+ Register regmap. */
+
+static const struct regcache_map_entry ppc32_regmap_cdscr[] =
+ {
+ { 1, PPC_CDSCR_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Hardware Transactional Memory checkpointed Data Stream Control
+ Register regset. */
+
+const struct regset ppc32_linux_cdscrregset = {
+ ppc32_regmap_cdscr,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
+/* Hardware Transactional Memory checkpointed Target Address Register
+ regmap. */
+
+static const struct regcache_map_entry ppc32_regmap_ctar[] =
+ {
+ { 1, PPC_CTAR_REGNUM, 8 },
+ { 0 }
+ };
+
+/* Hardware Transactional Memory checkpointed Target Address Register
+ regset. */
+
+const struct regset ppc32_linux_ctarregset = {
+ ppc32_regmap_ctar,
+ regcache_supply_regset,
+ regcache_collect_regset
+};
+
const struct regset *
ppc_linux_gregset (int wordsize)
{
@@ -664,6 +899,88 @@ ppc_linux_vsxregset (void)
return &ppc32_linux_vsxregset;
}
+const struct regset *
+ppc_linux_cgprregset (struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (tdep->wordsize == 4)
+ {
+ return &ppc32_linux_cgprregset;
+ }
+ else
+ {
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ return &ppc64_be_linux_cgprregset;
+ else
+ return &ppc64_le_linux_cgprregset;
+ }
+}
+
+const struct regset *
+ppc_linux_cvmxregset (struct gdbarch *gdbarch)
+{
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+ return &ppc32_be_linux_cvmxregset;
+ else
+ return &ppc32_le_linux_cvmxregset;
+}
+
+/* Collect function used to generate the core note for the
+ checkpointed GPR regset. Here, we don't want to skip the
+ "checkpointed" NIP and MSR, so that the note section we generate is
+ similar to the one generated by the kernel. To avoid having to
+ define additional registers in GDB which are not actually
+ checkpointed in the architecture, we copy TFHAR to the checkpointed
+ NIP slot, which is what the kernel does, and copy the regular MSR
+ to the checkpointed MSR slot, which will have a similar value in
+ most cases. */
+
+static void
+ppc_linux_collect_core_cpgrregset (const struct regset *regset,
+ const struct regcache *regcache,
+ int regnum, void *buf, size_t len)
+{
+ struct gdbarch *gdbarch = regcache->arch ();
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ const struct regset *cgprregset = ppc_linux_cgprregset (gdbarch);
+
+ /* We collect the checkpointed GPRs already defined in the regular
+ regmap, then overlay TFHAR/MSR on the checkpointed NIP/MSR
+ slots. */
+ cgprregset->collect_regset (cgprregset, regcache, regnum, buf, len);
+
+ /* Check that we are collecting all the registers, which should be
+ the case when generating a core file. */
+ if (regnum != -1)
+ return;
+
+ /* PT_NIP and PT_MSR are 32 and 33 for powerpc. Don't redefine
+ these symbols since this file can run on clients in other
+ architectures where they can already be defined to other
+ values. */
+ int pt_offset = 32;
+
+ /* Check that our buffer is long enough to hold two slots at
+ pt_offset * wordsize, one for NIP and one for MSR. */
+ gdb_assert ((pt_offset + 2) * tdep->wordsize <= len);
+
+ /* TFHAR is 8 bytes wide, but the NIP slot for a 32-bit thread is
+ 4-bytes long. We use raw_collect_integer which handles
+ differences in the sizes for the source and destination buffers
+ for both endian modes. */
+ (regcache->raw_collect_integer
+ (PPC_TFHAR_REGNUM, ((gdb_byte *) buf) + pt_offset * tdep->wordsize,
+ tdep->wordsize, false));
+
+ pt_offset = 33;
+
+ (regcache->raw_collect_integer
+ (PPC_MSR_REGNUM, ((gdb_byte *) buf) + pt_offset * tdep->wordsize,
+ tdep->wordsize, false));
+}
+
/* Iterate over supported core file register note sections. */
static void
@@ -728,6 +1045,121 @@ ppc_linux_iterate_over_regset_sections (struct gdbarch *gdbarch,
PPC_LINUX_SIZEOF_PMUREGSET,
&ppc32_linux_pmuregset, "Performance Monitor Registers",
cb_data);
+
+ if (tdep->have_htm_spr)
+ cb (".reg-ppc-tm-spr", PPC_LINUX_SIZEOF_TM_SPRREGSET,
+ PPC_LINUX_SIZEOF_TM_SPRREGSET,
+ &ppc32_linux_tm_sprregset,
+ "Hardware Transactional Memory Special Purpose Registers",
+ cb_data);
+
+ /* Checkpointed registers can be unavailable, don't call back if
+ we are generating a core file. */
+
+ if (tdep->have_htm_core)
+ {
+ /* Only generate the checkpointed GPR core note if we also have
+ access to the HTM SPRs, because we need TFHAR to fill the
+ "checkpointed" NIP slot. We can read a core file without it
+ since GDB is not aware of this NIP as a visible register. */
+ if (regcache == NULL ||
+ (REG_VALID == regcache->get_register_status (PPC_CR0_REGNUM)
+ && tdep->have_htm_spr))
+ {
+ int cgpr_size = (tdep->wordsize == 4?
+ PPC32_LINUX_SIZEOF_CGPRREGSET
+ : PPC64_LINUX_SIZEOF_CGPRREGSET);
+
+ const struct regset *cgprregset =
+ ppc_linux_cgprregset (gdbarch);
+
+ if (regcache != NULL)
+ {
+ struct regset core_cgprregset = *cgprregset;
+
+ core_cgprregset.collect_regset
+ = ppc_linux_collect_core_cpgrregset;
+
+ cb (".reg-ppc-tm-cgpr",
+ cgpr_size, cgpr_size,
+ &core_cgprregset,
+ "Checkpointed General Purpose Registers", cb_data);
+ }
+ else
+ {
+ cb (".reg-ppc-tm-cgpr",
+ cgpr_size, cgpr_size,
+ cgprregset,
+ "Checkpointed General Purpose Registers", cb_data);
+ }
+ }
+ }
+
+ if (tdep->have_htm_fpu)
+ {
+ if (regcache == NULL ||
+ REG_VALID == regcache->get_register_status (PPC_CF0_REGNUM))
+ cb (".reg-ppc-tm-cfpr", PPC_LINUX_SIZEOF_CFPRREGSET,
+ PPC_LINUX_SIZEOF_CFPRREGSET,
+ &ppc32_linux_cfprregset,
+ "Checkpointed Floating Point Registers", cb_data);
+ }
+
+ if (tdep->have_htm_altivec)
+ {
+ if (regcache == NULL ||
+ REG_VALID == regcache->get_register_status (PPC_CVR0_REGNUM))
+ {
+ const struct regset *cvmxregset =
+ ppc_linux_cvmxregset (gdbarch);
+
+ cb (".reg-ppc-tm-cvmx", PPC_LINUX_SIZEOF_CVMXREGSET,
+ PPC_LINUX_SIZEOF_CVMXREGSET,
+ cvmxregset,
+ "Checkpointed Altivec (VMX) Registers", cb_data);
+ }
+ }
+
+ if (tdep->have_htm_vsx)
+ {
+ if (regcache == NULL ||
+ (REG_VALID
+ == regcache->get_register_status (PPC_CVSR0_UPPER_REGNUM)))
+ cb (".reg-ppc-tm-cvsx", PPC_LINUX_SIZEOF_CVSXREGSET,
+ PPC_LINUX_SIZEOF_CVSXREGSET,
+ &ppc32_linux_cvsxregset,
+ "Checkpointed VSX Registers", cb_data);
+ }
+
+ if (tdep->ppc_cppr_regnum != -1)
+ {
+ if (regcache == NULL ||
+ REG_VALID == regcache->get_register_status (PPC_CPPR_REGNUM))
+ cb (".reg-ppc-tm-cppr", PPC_LINUX_SIZEOF_CPPRREGSET,
+ PPC_LINUX_SIZEOF_CPPRREGSET,
+ &ppc32_linux_cpprregset,
+ "Checkpointed Priority Program Register", cb_data);
+ }
+
+ if (tdep->ppc_cdscr_regnum != -1)
+ {
+ if (regcache == NULL ||
+ REG_VALID == regcache->get_register_status (PPC_CDSCR_REGNUM))
+ cb (".reg-ppc-tm-cdscr", PPC_LINUX_SIZEOF_CDSCRREGSET,
+ PPC_LINUX_SIZEOF_CDSCRREGSET,
+ &ppc32_linux_cdscrregset,
+ "Checkpointed Data Stream Control Register", cb_data);
+ }
+
+ if (tdep->ppc_ctar_regnum)
+ {
+ if ( regcache == NULL ||
+ REG_VALID == regcache->get_register_status (PPC_CTAR_REGNUM))
+ cb (".reg-ppc-tm-ctar", PPC_LINUX_SIZEOF_CTARREGSET,
+ PPC_LINUX_SIZEOF_CTARREGSET,
+ &ppc32_linux_ctarregset,
+ "Checkpointed Target Address Register", cb_data);
+ }
}
static void
@@ -1143,6 +1575,7 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
asection *dscr = bfd_get_section_by_name (abfd, ".reg-ppc-dscr");
asection *tar = bfd_get_section_by_name (abfd, ".reg-ppc-tar");
asection *pmu = bfd_get_section_by_name (abfd, ".reg-ppc-pmu");
+ asection *htmspr = bfd_get_section_by_name (abfd, ".reg-ppc-tm-spr");
if (! section)
return NULL;
@@ -1184,7 +1617,11 @@ ppc_linux_core_read_description (struct gdbarch *gdbarch,
been unavailable when the core file was created. They will
be in the tdep but will show as unavailable. */
if (tar && pmu)
- features.isa207 = true;
+ {
+ features.isa207 = true;
+ if (htmspr)
+ features.htm = true;
+ }
}
return ppc_linux_match_description (features);
@@ -2062,6 +2499,7 @@ _initialize_ppc_linux_tdep (void)
initialize_tdesc_powerpc_isa205_vsx32l ();
initialize_tdesc_powerpc_isa205_ppr_dscr_vsx32l ();
initialize_tdesc_powerpc_isa207_vsx32l ();
+ initialize_tdesc_powerpc_isa207_htm_vsx32l ();
initialize_tdesc_powerpc_64l ();
initialize_tdesc_powerpc_altivec64l ();
initialize_tdesc_powerpc_cell64l ();
@@ -2071,5 +2509,6 @@ _initialize_ppc_linux_tdep (void)
initialize_tdesc_powerpc_isa205_vsx64l ();
initialize_tdesc_powerpc_isa205_ppr_dscr_vsx64l ();
initialize_tdesc_powerpc_isa207_vsx64l ();
+ initialize_tdesc_powerpc_isa207_htm_vsx64l ();
initialize_tdesc_powerpc_e500l ();
}