This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFC v3 8/8] Add S390 support for linux-kernel target


After implementing the new linux-kernel target and preparing s390-tdep.
It is now time to get everything to work.  Thus implement the hooks
required by the linux-kernel target and enable s390's privileged
registers.

gdb/ChangeLog:

	* s390-lk-tdep.h: New file.
	* s390-lk-tdep.c: New file.
	* Makefile.in (ALL_TARGET_OBS): Add s390-lk-tdep.o.
	(HFILES_NO_SRCDIR): Add s390-lk-tdep.h.
	(ALLDEPFILES): Add s390-lk-tdep.c.
	* configure.tgt (s390*-*-linux*): Add s390-lk-tdep.o.
	* s390-tdep.h: Define macros for address translation.
	* s390-tdep.c (s390-lk-tdep.h): New include.
	(s390_iterate_over_regset_sections): Enable privileged registers.
	(s390_core_read_description): Enable privileged registers.
	(s390_gdbarch_init): : Enable privileged registers and adjust.
---
 gdb/Makefile.in    |   3 +
 gdb/configure.tgt  |   5 +-
 gdb/s390-lk-tdep.c | 390 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/s390-lk-tdep.h |  36 +++++
 gdb/s390-tdep.c    |  57 +++++++-
 gdb/s390-tdep.h    |  62 +++++++++
 6 files changed, 548 insertions(+), 5 deletions(-)
 create mode 100644 gdb/s390-lk-tdep.c
 create mode 100644 gdb/s390-lk-tdep.h

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 2933b08..d6ea773 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -863,6 +863,7 @@ ALL_TARGET_OBS = \
 	rs6000-tdep.o \
 	rx-tdep.o \
 	s390-linux-tdep.o \
+	s390-lk-tdep.o \
 	s390-tdep.o \
 	score-tdep.o \
 	sh-linux-tdep.o \
@@ -1421,6 +1422,7 @@ HFILES_NO_SRCDIR = \
 	rs6000-aix-tdep.h \
 	rs6000-tdep.h \
 	s390-linux-tdep.h \
+	s390-lk-tdep.h \
 	s390-tdep.h \
 	score-tdep.h \
 	selftest-arch.h \
@@ -2620,6 +2622,7 @@ ALLDEPFILES = \
 	rx-tdep.c \
 	s390-linux-nat.c \
 	s390-linux-tdep.c \
+	s390-lk-tdep.c \
 	s390-tdep.c \
 	score-tdep.c \
 	ser-go32.c \
diff --git a/gdb/configure.tgt b/gdb/configure.tgt
index a6dc662..c89e9ee 100644
--- a/gdb/configure.tgt
+++ b/gdb/configure.tgt
@@ -482,8 +482,9 @@ powerpc*-*-*)
 
 s390*-*-linux*)
 	# Target: S390 running Linux
-	gdb_target_obs="s390-tdep.o s390-linux-tdep.o solib-svr4.o \
-			linux-tdep.o linux-record.o ${lk_target_obs}"
+	gdb_target_obs="s390-tdep.o s390-linux-tdep.o s390-lk-tdep.o \
+			solib-svr4.o linux-tdep.o linux-record.o \
+			${lk_target_obs}"
 	build_gdbserver=yes
 	;;
 
diff --git a/gdb/s390-lk-tdep.c b/gdb/s390-lk-tdep.c
new file mode 100644
index 0000000..7ff71b8
--- /dev/null
+++ b/gdb/s390-lk-tdep.c
@@ -0,0 +1,390 @@
+/* Target-dependent code for linux-kernel target on S390.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "defs.h"
+
+#include "gdbarch.h"
+#include "gdbcore.h"
+#include "gdbthread.h"
+#include "lk-low.h"
+#include "osabi.h"
+#include "regcache.h"
+#include "regset.h"
+#include "s390-tdep.h"
+#include "s390-lk-tdep.h"
+
+#include "features/s390x-cr-linux64.c"
+#include "features/s390x-vxcr-linux64.c"
+
+/* Register maps and sets.  */
+
+static const struct regcache_map_entry s390x_gregmap_lk[] =
+  {
+    { 10, S390_R6_REGNUM }, /* r0-r5 volatile */
+    { -2, REGCACHE_MAP_SKIP, 8 },
+    { 1, S390_PSWA_REGNUM }, /* Use r14 for PSWA.  */
+    { 0 }
+  };
+
+static const struct regcache_map_entry s390x_regmap_cr [] =
+  {
+    { 16, S390_CR0_REGNUM, 8 },
+    { 0 }
+  };
+
+static const struct regcache_map_entry s390x_regmap_timer [] =
+  {
+    { 1, S390_TIMER_REGNUM, 8 },
+    { 0 }
+  };
+
+static const struct regcache_map_entry s390x_regmap_todcmp [] =
+  {
+    { 1, S390_TODCMP_REGNUM, 8 },
+    { 0 }
+  };
+
+static const struct regcache_map_entry s390x_regmap_todpreg [] =
+  {
+    { 1, S390_TODPREG_REGNUM, 4 },
+    { 0 }
+  };
+
+static const struct regcache_map_entry s390x_regmap_prefix [] =
+  {
+    { 1, S390_PREFIX_REGNUM, 4 },
+    { 0 }
+  };
+
+const struct regset s390x_gregset_lk = {
+  s390x_gregmap_lk,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+const struct regset s390x_cr_regset = {
+  s390x_regmap_cr,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+const struct regset s390x_timer_regset = {
+  s390x_regmap_timer,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+const struct regset s390x_todcmp_regset = {
+  s390x_regmap_todcmp,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+const struct regset s390x_todpreg_regset = {
+  s390x_regmap_todpreg,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+const struct regset s390x_prefix_regset = {
+  s390x_regmap_prefix,
+  regcache_supply_regset,
+  regcache_collect_regset
+};
+
+/* Function for Linux kernel target get_registers hook.  Supplies gprs for
+   task TASK to REGCACHE.  Uses r14 (back jump address) as current pswa.  */
+
+void
+s390_lk_get_registers (CORE_ADDR task, struct target_ops *target,
+		       struct regcache *regcache, int regnum)
+{
+  const struct regset *regset;
+  CORE_ADDR ksp, gprs, pswa;
+  gdb_byte buf[80]; /* 80 = 10 (#registers saved) * 8 (64 bit width) */
+  size_t size;
+
+  regset = &s390x_gregset_lk;
+
+  ksp = lk_read_addr (task + LK_OFFSET (task_struct, thread)
+		      + LK_OFFSET (thread_struct, ksp));
+  gprs = ksp + LK_OFFSET (stack_frame, gprs);
+  size = FIELD_SIZE (LK_FIELD (stack_frame, gprs));
+  gdb_assert (size <= sizeof (buf));
+
+  read_memory (gprs, buf, size);
+  regset->supply_regset (regset, regcache, -1, buf, size);
+}
+
+/* Function for Linux kernel target get_percpu_offset hook.  Returns the
+   percpu_offset from lowcore for cpu CPU.  */
+
+CORE_ADDR
+s390_lk_get_percpu_offset (unsigned int cpu)
+{
+  CORE_ADDR lowcore_ptr, lowcore;
+  size_t ptr_len = lk_builtin_type_size (unsigned_long);
+
+  lowcore_ptr = LK_ADDR (lowcore_ptr) + (ptr_len * cpu);
+  lowcore = lk_read_addr (lowcore_ptr);
+
+  return lk_read_addr (lowcore + LK_OFFSET (lowcore, percpu_offset));
+}
+
+/* Function for Linux kernel target map_running_task_to_cpu hook.  */
+
+unsigned int
+s390_lk_map_running_task_to_cpu (struct thread_info *ti)
+{
+  struct regcache *regcache;
+  enum register_status reg_status;
+  CORE_ADDR lowcore;
+  unsigned int cpu;
+
+  regcache = get_thread_regcache (ti->ptid);
+  reg_status = regcache_raw_read_unsigned (regcache, S390_PREFIX_REGNUM,
+					   (ULONGEST *) &lowcore);
+  if (reg_status != REG_VALID)
+    error (_("Could not find prefix register for thread with pid %d, lwp %li."),
+	   ti->ptid.pid, ti->ptid.lwp);
+
+  cpu = lk_read_uint (lowcore + LK_OFFSET (lowcore, cpu_nr));
+
+  return cpu;
+}
+
+/* Function for Linux kernel target is_kvaddr hook.  */
+
+int
+s390_lk_is_kvaddr (CORE_ADDR addr)
+{
+  return addr >= LK_ADDR (high_memory);
+}
+
+/* Read table entry from TABLE at offset OFFSET.  Helper for s390_lk_vtop.  */
+
+static inline ULONGEST
+s390_lk_read_table_entry (CORE_ADDR table, ULONGEST offset)
+{
+  return lk_read_ulong (table + offset * lk_builtin_type_size (unsigned_long));
+}
+
+/* Function for Linux kernel target vtop hook.  Assume 64 bit addresses.  */
+
+CORE_ADDR
+s390_lk_vtop (CORE_ADDR table, CORE_ADDR vaddr)
+{
+  ULONGEST entry, offset;
+  CORE_ADDR paddr;
+  unsigned int table_type;
+  size_t addr_size = lk_builtin_type_size (unsigned_long);
+
+  /* Read first entry in table to get its type.  As the Table-Type bits are
+     the same in every table assume Region1-Table.  */
+  entry = s390_lk_read_table_entry (table, 0);
+  table_type = (entry & S390_LK_RFTE_TT) >> 2;
+
+  switch (table_type)
+    {
+      case S390_LK_DAT_TT_REGION1:
+	{
+	  offset = (vaddr & S390_LK_VADDR_RFX) >> 53;
+	  entry = s390_lk_read_table_entry (table, offset);
+
+	  /* Do sanity checks.  */
+	  if (!entry)
+	    warning (_("Trying to translate address 0x%s with empty "\
+		       "region-first-table entry."),
+		   phex (vaddr, addr_size));
+	  else if ((entry & S390_LK_RFTE_TT) >> 2 != S390_LK_DAT_TT_REGION1)
+	    warning (_("Trying to translate address 0x%s with corrupt "\
+		       "table type in region-first-table entry."),
+		     phex (vaddr, addr_size));
+	  else if (entry & S390_LK_RFTE_I)
+	    warning (_("Translating address 0x%s with invalid bit set at "\
+		       "region-first-table entry."),
+		     phex (vaddr, addr_size));
+
+	  table = entry & S390_LK_RFTE_O;
+	}
+	/* fall through */
+      case S390_LK_DAT_TT_REGION2:
+	{
+	  offset = (vaddr & S390_LK_VADDR_RSX) >> 42;
+	  entry = s390_lk_read_table_entry (table, offset);
+
+	  /* Do sanity checks.  */
+	  if (!entry)
+	    warning (_("Trying to translate address 0x%s with empty "\
+		       "region-second-table entry."),
+		   phex (vaddr, addr_size));
+	  else if ((entry & S390_LK_RSTE_TT) >> 2 != S390_LK_DAT_TT_REGION2)
+	    warning (_("Trying to translate address 0x%s with corrupt "\
+		       "table type in region-second-table entry."),
+		     phex (vaddr, addr_size));
+	  else if (entry & S390_LK_RSTE_I)
+	    warning (_("Translating address 0x%s with invalid bit set at "\
+		       "region-second-table entry."),
+		     phex (vaddr, addr_size));
+
+	  table = entry & S390_LK_RSTE_O;
+	}
+	/* fall through */
+      case S390_LK_DAT_TT_REGION3:
+	{
+	  offset = (vaddr & S390_LK_VADDR_RTX) >> 31;
+	  entry = s390_lk_read_table_entry (table, offset);
+
+	  /* Do sanity checks.  */
+	  if (!entry)
+	    warning (_("Trying to translate address 0x%s with empty "\
+		       "region-third-table entry."),
+		   phex (vaddr, addr_size));
+	  else if ((entry & S390_LK_RTTE_TT) >> 2 != S390_LK_DAT_TT_REGION3)
+	    warning (_("Trying to translate address 0x%s with corrupt "\
+		       "table type in region-third-table entry."),
+		     phex (vaddr, addr_size));
+	  else if (entry & S390_LK_RTTE_I)
+	    warning (_("Translating address 0x%s with invalid bit set at "\
+		       "region-third-table entry."),
+		     phex (vaddr, addr_size));
+
+	  /* Check for huge page.  */
+	  if (entry & S390_LK_RTTE_FC)
+	    {
+	      paddr = ((entry & S390_LK_RTTE_RFAA)
+		       + (vaddr & ~S390_LK_RTTE_RFAA));
+	      return paddr;
+	    }
+
+	  table = entry & S390_LK_RTTE_O;
+	}
+	/* fall through */
+      case S390_LK_DAT_TT_SEGMENT:
+	{
+	  offset = (vaddr & S390_LK_VADDR_SX) >> 20;
+	  entry = s390_lk_read_table_entry (table, offset);
+
+	  /* Do sanity checks.  */
+	  if (!entry)
+	    warning (_("Trying to translate address 0x%s with empty "\
+		       "segment-table entry."),
+		   phex (vaddr, addr_size));
+	  else if ((entry & S390_LK_STE_TT) >> 2 != S390_LK_DAT_TT_SEGMENT)
+	    warning (_("Trying to translate address 0x%s with corrupt "\
+		       "table type in segment-table entry."),
+		     phex (vaddr, addr_size));
+	  else if (entry & S390_LK_STE_I)
+	    warning (_("Translating address 0x%s with invalid bit set at "\
+		       "segment-table entry."),
+		     phex (vaddr, addr_size));
+
+	  /* Check for large page.  */
+	  if (entry & S390_LK_STE_FC)
+	    {
+	      paddr = ((entry & S390_LK_STE_SFAA)
+		       + (vaddr & ~S390_LK_STE_SFAA));
+	      return paddr;
+	    }
+
+	  table = entry & S390_LK_STE_O;
+	  break;
+	}
+    } /* switch (table_type) */
+
+  offset = (vaddr & S390_LK_VADDR_PX) >> 12;
+  entry = s390_lk_read_table_entry (table, offset);
+
+  /* Do sanity checks.  */
+  if (!entry)
+    warning (_("Trying to translate address 0x%s with empty page-table "\
+	       "entry."),
+	     phex (vaddr, addr_size));
+  else if (entry & S390_LK_PTE_I)
+    warning (_("Translating address 0x%s with invalid bit set at page-table "\
+	       "entry."),
+	     phex (vaddr, addr_size));
+
+  paddr = ((entry & S390_LK_PTE_PFAA) + (vaddr & ~S390_LK_PTE_PFAA));
+
+  return paddr;
+}
+
+/* Function for Linux kernel target get_module_text_offset hook.  */
+
+CORE_ADDR
+s390_lk_get_module_text_offset (CORE_ADDR mod)
+{
+  CORE_ADDR offset, mod_arch;
+
+  mod_arch = mod + LK_OFFSET (module, arch);
+  offset = lk_read_ulong (mod_arch + LK_OFFSET (mod_arch_specific, got_size));
+  offset += lk_read_ulong (mod_arch + LK_OFFSET (mod_arch_specific, plt_size));
+
+  return offset;
+}
+
+/* Initialize s390 dependent private data for linux kernel target.  */
+
+static void
+s390_lk_init_private (struct gdbarch *gdbarch)
+{
+  LK_DECLARE_FIELD (stack_frame, gprs);
+
+  LK_DECLARE_FIELD (thread_struct, ksp);
+
+  LK_DECLARE_STRUCT_ALIAS (_lowcore, lowcore); /* linux -4.4 */
+  LK_DECLARE_STRUCT_ALIAS (lowcore, lowcore); /* linux 4.5+ */
+  if (LK_STRUCT (lowcore) == NULL)
+    error (_("Could not find struct lowcore.  Aborting."));
+  LK_DECLARE_FIELD (lowcore, percpu_offset);
+  LK_DECLARE_FIELD (lowcore, current_pid);
+  LK_DECLARE_FIELD (lowcore, cpu_nr);
+
+  LK_DECLARE_FIELD (mod_arch_specific, got_size);
+  LK_DECLARE_FIELD (mod_arch_specific, plt_size);
+
+  LK_DECLARE_ADDR (lowcore_ptr);
+  LK_DECLARE_ADDR (high_memory);
+
+  LK_HOOK->get_registers = s390_lk_get_registers;
+  LK_HOOK->is_kvaddr = s390_lk_is_kvaddr;
+  LK_HOOK->vtop = s390_lk_vtop;
+  LK_HOOK->get_percpu_offset = s390_lk_get_percpu_offset;
+  LK_HOOK->map_running_task_to_cpu = s390_lk_map_running_task_to_cpu;
+  LK_HOOK->get_module_text_offset = s390_lk_get_module_text_offset;
+}
+
+/* Initialize Linux kernel specific gdbarch hooks.  */
+
+void
+s390_gdbarch_lk_init (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  /* Support linux kernel debugging.  */
+  set_gdbarch_lk_init_private (gdbarch, s390_lk_init_private);
+}
+
+extern initialize_file_ftype _initialize_s390_lk_tdep; /* -Wmissing-prototypes */
+
+void
+_initialize_s390_lk_tdep (void)
+{
+  /* Initialize the Linux kernel target descriptions.  */
+  initialize_tdesc_s390x_cr_linux64 ();
+  initialize_tdesc_s390x_vxcr_linux64 ();
+}
diff --git a/gdb/s390-lk-tdep.h b/gdb/s390-lk-tdep.h
new file mode 100644
index 0000000..68bfc96
--- /dev/null
+++ b/gdb/s390-lk-tdep.h
@@ -0,0 +1,36 @@
+/* Target-dependent code for linux-kernel target on S390.
+   Copyright (C) 2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef S390_LK_TDEP_H
+#define S390_LK_TDEP_H
+
+extern void s390_gdbarch_lk_init (struct gdbarch_info info,
+				  struct gdbarch *gdbarch);
+
+/* Core file privileged register sets, defined in s390-lk-tdep.c.  */
+extern const struct regset s390x_gregset_lk;
+extern const struct regset s390x_cr_regset;
+extern const struct regset s390x_timer_regset;
+extern const struct regset s390x_todcmp_regset;
+extern const struct regset s390x_todpreg_regset;
+extern const struct regset s390x_prefix_regset;
+
+extern struct target_desc *tdesc_s390x_cr_linux64;
+extern struct target_desc *tdesc_s390x_vxcr_linux64;
+
+#endif /* S390_LK_TDEP_H */
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index 78757fa..f4ebda8 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -40,6 +40,7 @@
 #include "reggroups.h"
 #include "regset.h"
 #include "s390-linux-tdep.h"
+#include "s390-lk-tdep.h"
 #include "s390-tdep.h"
 #include "target-descriptions.h"
 #include "trad-frame.h"
@@ -1032,7 +1033,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;
+  int high_gprs, v1, v2, te, vx, cr;
 
   target_auxv_search (target, AT_HWCAP, &hwcap);
   if (!section)
@@ -1044,6 +1045,7 @@ 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);
+  cr = (bfd_get_section_by_name (abfd, ".reg-s390-ctrs") != NULL);
 
   switch (bfd_section_size (abfd, section))
     {
@@ -1060,6 +1062,8 @@ s390_core_read_description (struct gdbarch *gdbarch,
 
     case s390x_sizeof_gregset:
       return (te && vx ? tdesc_s390x_tevx_linux64 :
+	      vx && cr ? tdesc_s390x_vxcr_linux64 :
+	      cr ? tdesc_s390x_cr_linux64 :
 	      vx ? tdesc_s390x_vx_linux64 :
 	      te ? tdesc_s390x_te_linux64 :
 	      v2 ? tdesc_s390x_linux64v2 :
@@ -1116,6 +1120,22 @@ 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);
     }
+
+  /* Privileged registers for kernel debugging.  */
+  if (bfd_get_section_by_name (core_bfd, ".reg-s390-timer"))
+    cb (".reg-s390-timer", 8, &s390x_timer_regset, "s390 timer", cb_data);
+  if (bfd_get_section_by_name (core_bfd, ".reg-s390-todcmp"))
+    cb (".reg-s390-todcmp", 8, &s390x_todcmp_regset,
+	"s390 clock comperator", cb_data);
+  if (bfd_get_section_by_name (core_bfd, ".reg-s390-todpreg"))
+    cb (".reg-s390-todpreg", 4, &s390x_todpreg_regset,
+	"s390 TOD programable register", cb_data);
+  if (bfd_get_section_by_name (core_bfd, ".reg-s390-ctrs"))
+    cb (".reg-s390-ctrs", 16 * 8, &s390x_cr_regset,
+	"s390 control registers", cb_data);
+  if (bfd_get_section_by_name (core_bfd, ".reg-s390-prefix"))
+    cb (".reg-s390-prefix", 4, &s390x_prefix_regset,
+	"s390 prefix area", cb_data);
 }
 
 
@@ -2986,6 +3006,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_privileged = 0;
   int first_pseudo_reg, last_pseudo_reg;
   static const char *const stap_register_prefixes[] = { "%", NULL };
   static const char *const stap_register_indirection_prefixes[] = { "(",
@@ -3160,6 +3181,30 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 	  have_vx = 1;
 	}
 
+      /* Control registers.  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.cr");
+      if (feature)
+	{
+	  for (i = 0; i < 16; i++)
+	    valid_p &= tdesc_numbered_register (feature, tdesc_data,
+						S390_CR0_REGNUM + i, cr[i]);
+	}
+
+      /* Privileged registers.  */
+      feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.privileged");
+      if (feature)
+	{
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      S390_TIMER_REGNUM, "timer");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      S390_TODCMP_REGNUM, "todcmp");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      S390_TODPREG_REGNUM, "todpreg");
+	  valid_p &= tdesc_numbered_register (feature, tdesc_data,
+					      S390_PREFIX_REGNUM, "prefix");
+	  have_privileged = 1;
+	}
+
       if (!valid_p)
 	{
 	  tdesc_data_cleanup (tdesc_data);
@@ -3340,8 +3385,14 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_valid_disassembler_options (gdbarch,
 					  disassembler_options_s390 ());
 
-  /* Note that GNU/Linux is the only OS supported on this platform.  */
-  s390_gdbarch_linux_init (info, gdbarch);
+  /* Note that GNU/Linux is the only OS supported on this platform.
+     Nevertheless we need to distinguish between a kernel- and user-space
+     gdbarch.  GDBs osabi support is not sufficient for our case as for both
+     cases the ELF bits are for Linux.  Thus fallback to this method.  */
+  if (have_privileged)
+    s390_gdbarch_lk_init (info, gdbarch);
+  else
+    s390_gdbarch_linux_init (info, gdbarch);
 
   return gdbarch;
 }
diff --git a/gdb/s390-tdep.h b/gdb/s390-tdep.h
index 8d0da72..0df8a27 100644
--- a/gdb/s390-tdep.h
+++ b/gdb/s390-tdep.h
@@ -319,4 +319,66 @@ enum
 #define S390_IS_TDBREGSET_REGNUM(i)				\
   ((i) >= S390_TDB_DWORD0_REGNUM && (i) <= S390_TDB_R15_REGNUM)
 
+/* Definitions for address translation.  */
+/* DAT Table types.  */
+#define S390_LK_DAT_TT_REGION1  3
+#define S390_LK_DAT_TT_REGION2  2
+#define S390_LK_DAT_TT_REGION3  1
+#define S390_LK_DAT_TT_SEGMENT  0
+
+/* Region-First-Table */
+#define S390_LK_RFTE_TL  0x3ULL		/* Table-Length */
+#define S390_LK_RFTE_TT  0xcULL		/* Table-Type */
+#define S390_LK_RFTE_I   0x20ULL	/* Region-Invalid Bit */
+#define S390_LK_RFTE_TF  0xc0ULL	/* Table Offset */
+#define S390_LK_RFTE_P   0x200ULL	/* DAT-Protection Bit */
+#define S390_LK_RFTE_O  ~0xfffULL	/* Region-Second-Table Origin */
+
+/* Region-Second-Table flags.  */
+#define S390_LK_RSTE_TL  0x3ULL		/* Table-Length */
+#define S390_LK_RSTE_TT  0xcULL		/* Table-Type */
+#define S390_LK_RSTE_I   0x20ULL	/* Region-Invalid Bit */
+#define S390_LK_RSTE_TF  0xc0ULL	/* Table Offset */
+#define S390_LK_RSTE_P   0x200ULL	/* DAT-Protection Bit */
+#define S390_LK_RSTE_O  ~0xfffULL	/* Region-Third-Table Origin */
+
+/* Region-Third-Table flags.  */
+#define S390_LK_RTTE_TL    0x3ULL	/* Table-Length */
+#define S390_LK_RTTE_TT    0xcULL	/* Table-Type */
+#define S390_LK_RTTE_CR    0x10ULL	/* Common-Region Bit */
+#define S390_LK_RTTE_I     0x20ULL	/* Region-Invalid Bit */
+#define S390_LK_RTTE_TF    0xc0ULL	/* Table Offset */
+#define S390_LK_RTTE_P     0x200ULL	/* DAT-Protection Bit */
+#define S390_LK_RTTE_FC    0x400ULL	/* Format-Control Bit */
+#define S390_LK_RTTE_F     0x800ULL	/* Fetch-Protection Bit */
+#define S390_LK_RTTE_ACC   0xf000ULL	/* Access-Control Bits */
+#define S390_LK_RTTE_AV    0x10000ULL	/* ACCF-Validity Control */
+#define S390_LK_RTTE_O    ~0xfffULL	/* Segment-Table Origin */
+#define S390_LK_RTTE_RFAA ~0x7fffffffULL /* Region-Frame Absolute Address */
+
+/* Segment-Table flags.  */
+#define S390_LK_STE_TT    0xcULL	/* Table-Type */
+#define S390_LK_STE_I     0x20ULL	/* Segment-Invalid Bit */
+#define S390_LK_STE_TF    0xc0ULL	/* Table Offset */
+#define S390_LK_STE_P     0x200ULL	/* DAT-Protection Bit */
+#define S390_LK_STE_FC    0x400ULL	/* Format-Control Bit */
+#define S390_LK_STE_F     0x800ULL	/* Fetch-Protection Bit */
+#define S390_LK_STE_ACC   0xf000ULL	/* Access-Control Bits */
+#define S390_LK_STE_AV    0x10000ULL	/* ACCF-Validity Control */
+#define S390_LK_STE_O    ~0x7ffULL	/* Page-Table Origin */
+#define S390_LK_STE_SFAA ~0xfffffULL	/* Segment-Frame Absolute Address */
+
+/* Page-Table flags.  */
+#define S390_LK_PTE_P     0x200ULL	/* DAT-Protection Bit */
+#define S390_LK_PTE_I     0x400ULL	/* Page-Invalid Bit */
+#define S390_LK_PTE_PFAA ~0xfffULL	/* Page-Frame Absolute Address */
+
+/* Virtual Address Fields.  */
+#define S390_LK_VADDR_RFX 0xffe0000000000000ULL
+#define S390_LK_VADDR_RSX 0x001ffc0000000000ULL
+#define S390_LK_VADDR_RTX 0x000003ff80000000ULL
+#define S390_LK_VADDR_SX  0x000000007ff00000ULL
+#define S390_LK_VADDR_PX  0x00000000000ff000ULL
+#define S390_LK_VADDR_BX  0x0000000000000fffULL
+
 #endif /* S390_TDEP_H */
-- 
2.8.4


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]