From patchwork Thu Jan 12 11:32:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Rudo X-Patchwork-Id: 18875 Received: (qmail 110147 invoked by alias); 12 Jan 2017 11:32:38 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 110077 invoked by uid 89); 12 Jan 2017 11:32:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.9 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=10806, 1080, 6, UD:regcache.h, regcache.h X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 12 Jan 2017 11:32:34 +0000 Received: from pps.filterd (m0098421.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id v0CBUMLA109431 for ; Thu, 12 Jan 2017 06:32:32 -0500 Received: from e06smtp14.uk.ibm.com (e06smtp14.uk.ibm.com [195.75.94.110]) by mx0a-001b2d01.pphosted.com with ESMTP id 27x5h6g6p3-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 12 Jan 2017 06:32:32 -0500 Received: from localhost by e06smtp14.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 12 Jan 2017 11:32:30 -0000 Received: from d06dlp03.portsmouth.uk.ibm.com (9.149.20.15) by e06smtp14.uk.ibm.com (192.168.101.144) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 12 Jan 2017 11:32:27 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id 6E0851B0805F; Thu, 12 Jan 2017 11:35:08 +0000 (GMT) Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v0CBWQ5v56819940; Thu, 12 Jan 2017 11:32:26 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2421952043; Thu, 12 Jan 2017 10:30:56 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTPS id E9A255203F; Thu, 12 Jan 2017 10:30:55 +0000 (GMT) From: Philipp Rudo To: gdb-patches@sourceware.org Cc: peter.griffin@linaro.org, yao.qi@arm.com, arnez@linux.vnet.ibm.com Subject: [RFC 7/7] Add S390 support for linux-kernel target Date: Thu, 12 Jan 2017 12:32:17 +0100 In-Reply-To: <20170112113217.48852-1-prudo@linux.vnet.ibm.com> References: <20170112113217.48852-1-prudo@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17011211-0016-0000-0000-0000042676A7 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17011211-0017-0000-0000-0000260F7C9F Message-Id: <20170112113217.48852-8-prudo@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-01-12_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=1 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1701120162 X-IsSubscribed: yes Implement functions for the linux-kernel target hooks. gdb/ChangeLog: * s390-linux-tdep.h: Define macros for address translation. * s390-linux-tdep.c: Include gdbthread.h and lk-low.h. (s390_gregmap_lk): New array. (s390_gregset_lk): New type. (s390_lk_get_registers, s390_lk_get_percpu_offset) (s390_lk_map_running_task_to_cpu, s390_lk_is_kvaddr) (s390_lk_read_table_entry, s390_lk_vtop, s390_lk_init_private): New function. (s390_gdbarch_init): Adjust. --- gdb/s390-linux-tdep.c | 270 ++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/s390-linux-tdep.h | 62 ++++++++++++ 2 files changed, 332 insertions(+) diff --git a/gdb/s390-linux-tdep.c b/gdb/s390-linux-tdep.c index 054c6d5..f436a74 100644 --- a/gdb/s390-linux-tdep.c +++ b/gdb/s390-linux-tdep.c @@ -29,6 +29,7 @@ #include "target.h" #include "gdbcore.h" #include "gdbcmd.h" +#include "gdbthread.h" #include "objfiles.h" #include "floatformat.h" #include "regcache.h" @@ -49,6 +50,8 @@ #include "auxv.h" #include "xml-syscall.h" +#include "lk-low.h" + #include "stap-probe.h" #include "ax.h" #include "ax-gdb.h" @@ -783,6 +786,14 @@ static const struct regcache_map_entry s390_gregmap[] = { 0 } }; +static const struct regcache_map_entry s390_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 s390_regmap_cr [] = { { 16, S390_CR0_REGNUM, 8 }, @@ -891,6 +902,12 @@ const struct regset s390_gregset = { regcache_collect_regset }; +const struct regset s390_gregset_lk = { + s390_gregmap_lk, + regcache_supply_regset, + regcache_collect_regset +}; + const struct regset s390_cr_regset = { s390_regmap_cr, regcache_supply_regset, @@ -1080,6 +1097,256 @@ s390_core_read_description (struct gdbarch *gdbarch, } } +/* Funktion 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; + size_t size; + struct cleanup *old_chain; + + regset = &s390_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)); + + buf = XCNEWVEC (gdb_byte, size); + old_chain = make_cleanup (xfree, buf); + read_memory (gprs, buf, size); + regset->supply_regset (regset, regcache, -1, buf, size); + do_cleanups (old_chain); +} + +/* 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 (int cpu) +{ + CORE_ADDR lowcore_ptr, lowcore; + int 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. */ + +int +s390_lk_map_running_task_to_cpu (struct thread_info *ti) +{ + struct regcache *regcache; + enum register_status reg_status; + CORE_ADDR lowcore; + 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_int (lowcore + LK_OFFSET (lowcore, cpu_nr)); + + return cpu; +} + +/* Funktion 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; + int table_type; + + /* 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 %#lx with empty region-first-table entry."), + vaddr); + else if ((entry & S390_LK_RFTE_TT) >> 2 != S390_LK_DAT_TT_REGION1) + warning (_("Trying to translate address %#lx with corrupt table type in region-first-table entry."), + vaddr); + else if (entry & S390_LK_RFTE_I) + warning (_("Translating address %#lx with invalid bit set at region-first-table entry."), + vaddr); + + 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 %#lx with empty region-second-table entry."), + vaddr); + else if ((entry & S390_LK_RSTE_TT) >> 2 != S390_LK_DAT_TT_REGION2) + warning (_("Trying to translate address %#lx with corrupt table type in region-second-table entry."), + vaddr); + else if (entry & S390_LK_RSTE_I) + warning (_("Translating address %#lx with invalid bit set at region-second-table entry."), + vaddr); + + 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 %#lx with empty region-third-table entry."), + vaddr); + else if ((entry & S390_LK_RTTE_TT) >> 2 != S390_LK_DAT_TT_REGION3) + warning (_("Trying to translate address %#lx with corrupt table type in region-third-table entry."), + vaddr); + else if (entry & S390_LK_RTTE_I) + warning (_("Translating address %#lx with invalid bit set at region-third-table entry."), + vaddr); + + /* 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 %#lx with empty segment-table entry."), + vaddr); + else if ((entry & S390_LK_STE_TT) >> 2 != S390_LK_DAT_TT_SEGMENT) + warning (_("Trying to translate address %#lx with corrupt table type in segment-table entry."), + vaddr); + else if (entry & S390_LK_STE_I) + warning (_("Translating address %#lx with invalid bit set at segment-table entry."), + vaddr); + + /* 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 %#lx with empty page-table entry."), + vaddr); + else if (entry & S390_LK_PTE_I) + warning (_("Translating address %#lx with invalid bit set at page-table entry."), + vaddr); + + 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. */ +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. Abort.")); + 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; +} + /* Decoding S/390 instructions. */ @@ -8220,6 +8487,9 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_process_record (gdbarch, s390_process_record); set_gdbarch_process_record_signal (gdbarch, s390_linux_record_signal); + /* Support linux kernel debugging. */ + set_gdbarch_lk_init_private (gdbarch, s390_lk_init_private); + s390_init_linux_record_tdep (&s390_linux_record_tdep, ABI_LINUX_S390); s390_init_linux_record_tdep (&s390x_linux_record_tdep, ABI_LINUX_ZSERIES); diff --git a/gdb/s390-linux-tdep.h b/gdb/s390-linux-tdep.h index fdb3c3d..8a16b0b 100644 --- a/gdb/s390-linux-tdep.h +++ b/gdb/s390-linux-tdep.h @@ -238,4 +238,66 @@ extern struct target_desc *tdesc_s390x_te_linux64; extern struct target_desc *tdesc_s390x_vx_linux64; extern struct target_desc *tdesc_s390x_tevx_linux64; +/* 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-Validy 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-Validy 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