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.
This commit is contained in:
Philipp Rudo
2017-03-16 10:50:29 +01:00
committed by Andreas Arnez
parent d67d2e9762
commit 3626824cea
6 changed files with 548 additions and 5 deletions

View File

@@ -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 \

View File

@@ -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
;;

390
gdb/s390-lk-tdep.c Normal file
View File

@@ -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 ();
}

36
gdb/s390-lk-tdep.h Normal file
View File

@@ -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 */

View File

@@ -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,7 +3385,13 @@ 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. */
/* 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;

View File

@@ -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 */