diff options
-rw-r--r-- | gdb/Makefile.in | 2 | ||||
-rw-r--r-- | gdb/s390-lk-tdep.c | 390 | ||||
-rw-r--r-- | gdb/s390-lk-tdep.h | 36 | ||||
-rw-r--r-- | gdb/s390-tdep.c | 58 | ||||
-rw-r--r-- | gdb/s390-tdep.h | 62 |
5 files changed, 544 insertions, 4 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 073cda4..74cf650 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -848,6 +848,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 \ @@ -2603,6 +2604,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/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 df248a6..31f6267 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); @@ -3336,9 +3381,14 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_stap_register_indirection_suffixes (gdbarch, stap_register_indirection_suffixes); - - /* 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 664cb9f..9448713 100644 --- a/gdb/s390-tdep.h +++ b/gdb/s390-tdep.h @@ -316,4 +316,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 */ |