commit 1b63490c9173f8c9770b7885def720516aa9b9f8 Author: Andreas Arnez Date: Mon Sep 25 16:02:23 2017 +0200 S390: Add guarded-storage register support to GDB Recognize targets with the new guarded-storage feature and then present the guarded-storage registers and the Linux-specific guarded-storage broadcast control block appropriately. gdb/ChangeLog: * s390-linux-nat.c (have_regset_gs): New static variable. (s390_linux_fetch_inferior_registers): Handle guarded-storage control block and guarded-storage broadcast control regsets. (s390_read_description): Detect whether the target has guarded-storage support, return appropriate tdesc. * s390-linux-tdep.c (features/s390-gs-linux64.c): New include. (features/s390x-gs-linux64.c): Likewise. (struct gdbarch_tdep) : New field. (s390_regmap_gs, s390_regmap_gsbc, s390_gs_regset) (s390_gsbc_regset): New variables. (s390_iterate_over_regset_sections): Iterate over s390_gs_regset and s390_gsbc_regset, if applicable. (s390_core_read_description): Check whether core file was from a target with guarded-storage support; include appropriate regsets. (s390_gdbarch_init): Add registers for guarded-storage support. (_initialize_s390_tdep): Initialize new target descriptions that include registers for guarded-storage support. * s390-linux-tdep.h (HWCAP_S390_GS, S390_GSD_REGNUM) (S390_GSSM_REGNUM, S390_GSEPLA_REGNUM) (S390_BC_GSD_REGNUM, S390_BC_GSSM_REGNUM): New defines. (S390_NUM_REGS): Adjust macro definition. (s390_gs_regset, s390_gsbc_regset, tdesc_s390_gs_linux64) (tdesc_s390x_gs_linux64): New declarations. ### a/gdb/ChangeLog ### b/gdb/ChangeLog ## -1,5 +1,31 @@ 2017-09-25 Andreas Arnez + * s390-linux-nat.c (have_regset_gs): New static variable. + (s390_linux_fetch_inferior_registers): Handle guarded-storage + control block and guarded-storage broadcast control regsets. + (s390_read_description): Detect whether the target has + guarded-storage support, return appropriate tdesc. + * s390-linux-tdep.c (features/s390-gs-linux64.c): New include. + (features/s390x-gs-linux64.c): Likewise. + (struct gdbarch_tdep) : New field. + (s390_regmap_gs, s390_regmap_gsbc, s390_gs_regset) + (s390_gsbc_regset): New variables. + (s390_iterate_over_regset_sections): Iterate over s390_gs_regset + and s390_gsbc_regset, if applicable. + (s390_core_read_description): Check whether core file was from a + target with guarded-storage support; include appropriate regsets. + (s390_gdbarch_init): Add registers for guarded-storage support. + (_initialize_s390_tdep): Initialize new target descriptions that + include registers for guarded-storage support. + * s390-linux-tdep.h (HWCAP_S390_GS, S390_GSD_REGNUM) + (S390_GSSM_REGNUM, S390_GSEPLA_REGNUM) + (S390_BC_GSD_REGNUM, S390_BC_GSSM_REGNUM): New defines. + (S390_NUM_REGS): Adjust macro definition. + (s390_gs_regset, s390_gsbc_regset, tdesc_s390_gs_linux64) + (tdesc_s390x_gs_linux64): New declarations. + +2017-09-25 Andreas Arnez + * features/s390-gs-linux64.xml: New file. * features/s390-gs.xml: New file. * features/s390-gsbc.xml: New file. --- a/gdb/s390-linux-nat.c +++ b/gdb/s390-linux-nat.c @@ -54,6 +54,7 @@ static int have_regset_last_break = 0; static int have_regset_system_call = 0; static int have_regset_tdb = 0; static int have_regset_vxrs = 0; +static int have_regset_gs = 0; /* Register map for 32-bit executables running under a 64-bit kernel. */ @@ -406,6 +407,18 @@ s390_linux_fetch_inferior_registers (struct target_ops *ops, fetch_regset (regcache, tid, NT_S390_VXRS_HIGH, 16 * 16, &s390_vxrs_high_regset); } + + if (have_regset_gs) + { + if (regnum == -1 || (regnum >= S390_GSD_REGNUM + && regnum <= S390_GSEPLA_REGNUM)) + fetch_regset (regcache, tid, NT_S390_GS_CB, 4 * 8, + &s390_gs_regset); + if (regnum == -1 || (regnum >= S390_BC_GSD_REGNUM + && regnum <= S390_BC_GSEPLA_REGNUM)) + fetch_regset (regcache, tid, NT_S390_GS_BC, 4 * 8, + &s390_gsbc_regset); + } } /* Store register REGNUM back into the child process. If REGNUM is @@ -974,8 +987,13 @@ s390_read_description (struct target_ops *ops) && check_regset (tid, NT_S390_VXRS_LOW, 16 * 8) && check_regset (tid, NT_S390_VXRS_HIGH, 16 * 16); + have_regset_gs = (hwcap & HWCAP_S390_GS) + && check_regset (tid, NT_S390_GS_CB, 4 * 8) + && check_regset (tid, NT_S390_GS_BC, 4 * 8); + if (s390_target_wordsize () == 8) - return (have_regset_vxrs ? + return (have_regset_gs ? tdesc_s390x_gs_linux64 : + have_regset_vxrs ? (have_regset_tdb ? tdesc_s390x_tevx_linux64 : tdesc_s390x_vx_linux64) : have_regset_tdb ? tdesc_s390x_te_linux64 : @@ -984,7 +1002,8 @@ s390_read_description (struct target_ops *ops) tdesc_s390x_linux64); if (hwcap & HWCAP_S390_HIGH_GPRS) - return (have_regset_vxrs ? + return (have_regset_gs ? tdesc_s390_gs_linux64 : + have_regset_vxrs ? (have_regset_tdb ? tdesc_s390_tevx_linux64 : tdesc_s390_vx_linux64) : have_regset_tdb ? tdesc_s390_te_linux64 : --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -69,12 +69,14 @@ #include "features/s390-te-linux64.c" #include "features/s390-vx-linux64.c" #include "features/s390-tevx-linux64.c" +#include "features/s390-gs-linux64.c" #include "features/s390x-linux64.c" #include "features/s390x-linux64v1.c" #include "features/s390x-linux64v2.c" #include "features/s390x-te-linux64.c" #include "features/s390x-vx-linux64.c" #include "features/s390x-tevx-linux64.c" +#include "features/s390x-gs-linux64.c" #define XML_SYSCALL_FILENAME_S390 "syscalls/s390-linux.xml" #define XML_SYSCALL_FILENAME_S390X "syscalls/s390x-linux.xml" @@ -113,6 +115,7 @@ struct gdbarch_tdep int have_linux_v1; int have_linux_v2; int have_tdb; + bool have_gs; }; @@ -834,6 +837,24 @@ static const struct regcache_map_entry s390_regmap_vxrs_high[] = { 0 } }; +static const struct regcache_map_entry s390_regmap_gs[] = + { + { 1, REGCACHE_MAP_SKIP, 8 }, + { 1, S390_GSD_REGNUM, 8 }, + { 1, S390_GSSM_REGNUM, 8 }, + { 1, S390_GSEPLA_REGNUM, 8 }, + { 0 } + }; + +static const struct regcache_map_entry s390_regmap_gsbc[] = + { + { 1, REGCACHE_MAP_SKIP, 8 }, + { 1, S390_BC_GSD_REGNUM, 8 }, + { 1, S390_BC_GSSM_REGNUM, 8 }, + { 1, S390_BC_GSEPLA_REGNUM, 8 }, + { 0 } + }; + /* Supply the TDB regset. Like regcache_supply_regset, but invalidate the TDB registers unless the TDB format field is valid. */ @@ -905,6 +926,18 @@ const struct regset s390_vxrs_high_regset = { regcache_collect_regset }; +const struct regset s390_gs_regset = { + s390_regmap_gs, + regcache_supply_regset, + regcache_collect_regset +}; + +const struct regset s390_gsbc_regset = { + s390_regmap_gsbc, + regcache_supply_regset, + regcache_collect_regset +}; + /* Iterate over supported core file register note sections. */ static void @@ -951,6 +984,23 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch, cb (".reg-s390-vxrs-high", 16 * 16, &s390_vxrs_high_regset, "s390 vector registers 16-31", cb_data); } + + /* Iterate over the guarded-storage regsets if in "read" mode, or if + their registers are available. */ + if (tdep->have_gs) + { + if (regcache == NULL + || REG_VALID == regcache_register_status (regcache, + S390_GSD_REGNUM)) + cb (".reg-s390-gs-cb", 4 * 8, &s390_gs_regset, + "s390 guarded-storage registers", cb_data); + + if (regcache == NULL + || REG_VALID == regcache_register_status (regcache, + S390_BC_GSD_REGNUM)) + cb (".reg-s390-gs-bc", 4 * 8, &s390_gsbc_regset, + "s390 guarded-storage broadcast control", cb_data); + } } static const struct target_desc * @@ -959,7 +1009,7 @@ s390_core_read_description (struct gdbarch *gdbarch, { asection *section = bfd_get_section_by_name (abfd, ".reg"); CORE_ADDR hwcap = 0; - int high_gprs, v1, v2, te, vx; + bool high_gprs, v1, v2, te, vx, gs; target_auxv_search (target, AT_HWCAP, &hwcap); if (!section) @@ -971,12 +1021,14 @@ s390_core_read_description (struct gdbarch *gdbarch, v2 = (bfd_get_section_by_name (abfd, ".reg-s390-system-call") != NULL); vx = (hwcap & HWCAP_S390_VX); te = (hwcap & HWCAP_S390_TE); + gs = (hwcap & HWCAP_S390_GS); switch (bfd_section_size (abfd, section)) { case s390_sizeof_gregset: if (high_gprs) - return (te && vx ? tdesc_s390_tevx_linux64 : + return (gs ? tdesc_s390_gs_linux64 : + te && vx ? tdesc_s390_tevx_linux64 : vx ? tdesc_s390_vx_linux64 : te ? tdesc_s390_te_linux64 : v2 ? tdesc_s390_linux64v2 : @@ -986,7 +1038,8 @@ s390_core_read_description (struct gdbarch *gdbarch, v1 ? tdesc_s390_linux32v1 : tdesc_s390_linux32); case s390x_sizeof_gregset: - return (te && vx ? tdesc_s390x_tevx_linux64 : + return (gs ? tdesc_s390x_gs_linux64 : + te && vx ? tdesc_s390x_tevx_linux64 : vx ? tdesc_s390x_vx_linux64 : te ? tdesc_s390x_te_linux64 : v2 ? tdesc_s390x_linux64v2 : @@ -7767,6 +7820,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) int have_linux_v2 = 0; int have_tdb = 0; int have_vx = 0; + int have_gs = 0; int first_pseudo_reg, last_pseudo_reg; static const char *const stap_register_prefixes[] = { "%", NULL }; static const char *const stap_register_indirection_prefixes[] = { "(", @@ -7834,6 +7888,12 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23", "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31", }; + static const char *const gs_cb[] = { + "gsd", "gssm", "gsepla", + }; + static const char *const gs_bc[] = { + "bc_gsd", "bc_gssm", "bc_gsepla", + }; const struct tdesc_feature *feature; int i, valid_p = 1; @@ -7937,6 +7997,29 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) have_vx = 1; } + /* Guarded-storage registers. */ + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.gs"); + if (feature) + { + for (i = 0; i < 3; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_GSD_REGNUM + i, + gs_cb[i]); + have_gs = 1; + } + + /* Guarded-storage broadcast control. */ + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.gsbc"); + if (feature) + { + valid_p &= have_gs; + + for (i = 0; i < 3; i++) + valid_p &= tdesc_numbered_register (feature, tdesc_data, + S390_BC_GSD_REGNUM + i, + gs_bc[i]); + } + if (!valid_p) { tdesc_data_cleanup (tdesc_data); @@ -7970,6 +8053,8 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) continue; if ((tdep->gpr_full_regnum != -1) != have_upper) continue; + if (tdep->have_gs != have_gs) + continue; if (tdesc_data != NULL) tdesc_data_cleanup (tdesc_data); return arches->gdbarch; @@ -7982,6 +8067,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->have_linux_v1 = have_linux_v1; tdep->have_linux_v2 = have_linux_v2; tdep->have_tdb = have_tdb; + tdep->have_gs = have_gs; gdbarch = gdbarch_alloc (&info, tdep); set_gdbarch_believe_pcc_promotion (gdbarch, 0); @@ -8157,10 +8243,12 @@ _initialize_s390_tdep (void) initialize_tdesc_s390_te_linux64 (); initialize_tdesc_s390_vx_linux64 (); initialize_tdesc_s390_tevx_linux64 (); + initialize_tdesc_s390_gs_linux64 (); initialize_tdesc_s390x_linux64 (); initialize_tdesc_s390x_linux64v1 (); initialize_tdesc_s390x_linux64v2 (); initialize_tdesc_s390x_te_linux64 (); initialize_tdesc_s390x_vx_linux64 (); initialize_tdesc_s390x_tevx_linux64 (); + initialize_tdesc_s390x_gs_linux64 (); } --- a/gdb/s390-linux-tdep.h +++ b/gdb/s390-linux-tdep.h @@ -33,6 +33,10 @@ #define HWCAP_S390_VX 2048 #endif +#ifndef HWCAP_S390_GS +#define HWCAP_S390_GS 16384 +#endif + /* Register information. */ /* Program Status Word. */ @@ -166,8 +170,14 @@ #define S390_V29_REGNUM 119 #define S390_V30_REGNUM 120 #define S390_V31_REGNUM 121 +#define S390_GSD_REGNUM 122 +#define S390_GSSM_REGNUM 123 +#define S390_GSEPLA_REGNUM 124 +#define S390_BC_GSD_REGNUM 125 +#define S390_BC_GSSM_REGNUM 126 +#define S390_BC_GSEPLA_REGNUM 127 /* Total. */ -#define S390_NUM_REGS 122 +#define S390_NUM_REGS 128 /* Special register usage. */ #define S390_SP_REGNUM S390_R15_REGNUM @@ -198,6 +208,8 @@ extern const struct regset s390_tdb_regset; #define s390_sizeof_tdbregset 0x100 extern const struct regset s390_vxrs_low_regset; extern const struct regset s390_vxrs_high_regset; +extern const struct regset s390_gs_regset; +extern const struct regset s390_gsbc_regset; /* GNU/Linux target descriptions. */ extern struct target_desc *tdesc_s390_linux32; @@ -209,11 +221,13 @@ extern struct target_desc *tdesc_s390_linux64v2; extern struct target_desc *tdesc_s390_te_linux64; extern struct target_desc *tdesc_s390_vx_linux64; extern struct target_desc *tdesc_s390_tevx_linux64; +extern struct target_desc *tdesc_s390_gs_linux64; extern struct target_desc *tdesc_s390x_linux64; extern struct target_desc *tdesc_s390x_linux64v1; extern struct target_desc *tdesc_s390x_linux64v2; extern struct target_desc *tdesc_s390x_te_linux64; extern struct target_desc *tdesc_s390x_vx_linux64; extern struct target_desc *tdesc_s390x_tevx_linux64; +extern struct target_desc *tdesc_s390x_gs_linux64; #endif