From patchwork Sat Feb 1 00:06:36 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Maciej W. Rozycki" X-Patchwork-Id: 37635 Received: (qmail 32997 invoked by alias); 1 Feb 2020 00:06:42 -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 32987 invoked by uid 89); 1 Feb 2020 00:06:41 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-7.6 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3 autolearn=ham version=3.3.1 spammy= X-HELO: esa3.hgst.iphmx.com Received: from esa3.hgst.iphmx.com (HELO esa3.hgst.iphmx.com) (216.71.153.141) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 01 Feb 2020 00:06:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=wdc.com; i=@wdc.com; q=dns/txt; s=dkim.wdc.com; t=1580515600; x=1612051600; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-id:content-transfer-encoding: mime-version; bh=cVAYwaSM3NqyygqWYhm+DScijfuwjB4wzCJWQJ7HZj8=; b=D5Vmtoz2oH/LooGpJlpj0+rv4HAigbFbfAObuECWFDiIrlggqCSUH7qa 7agqOKxk+E63qLvZ1agyXOASPmU957n0/2TRf+PmXP7gU7vVRUsMMb7hR tL1bpsxP02YBB9XnRUUj6wZNIHq4Zm6JJqN64tVNbNP8pLrh0AQoO/wgv F97RoTyTj7UYZ/OunGwcEb4xWqA1tSHlQ1+SaDT6EzJNfPbDE6Fo13lvG 5CHNqIqtDf+w431qlH2pobfPfllPRQHdKlOdoJGEmb5zr2l8XlrlkVqZI pukHgEVvZNO6fBlrVWxkl0HmQREGhPBA3i5Pe8/lYze6JlafucB5lRDSi g==; IronPort-SDR: 35oXKgAxlNc649PO0vPaSGxkLYD40lq48mP9cus3Aj5DhFyaLtvxd1GRhytGaPPj4AUQs0E09T GwESykQkLdOmZLfwBeSI/NYa/KDFfRMeUOF6hZfH0c4jh2DEXfXtgUIUNQjCBPU2k+7uUZsMav 8iUTUHk/Kn9VE+HZXWavgiFKEvbGg7dbGRLOwreUNwNXx16b1pf60xAzkjOnLfwwHVf2nFZ1M6 zamXmnu++7VFuzDQvfiTzEr0RX/Qm+w1tvQHBhuAQZICQ9U0hEJbwCrtp2tU/tv7m96HO1G5S4 JGI= Received: from mail-dm6nam12lp2172.outbound.protection.outlook.com (HELO NAM12-DM6-obe.outbound.protection.outlook.com) ([104.47.59.172]) by ob1.hgst.iphmx.com with ESMTP; 01 Feb 2020 08:06:38 +0800 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=ApHYBSFI84t7ZMX3qDWbqCmMmkREj4lVYiwMGiLfYLjWT9pE3oE99FYBTpS1WeU5QMUXajKUaw183XMlowEEvQBdi2pW615F53pclBRit3vJRNvvqVfgC7KZazIEY4ZYu5cuGGS6pe5+qzt8aiKLaXkSL5EbhzkuondNH77LiZrZdvsNQk2Ya1oLYAcaf5gcvxWsD4UQjg/nuaSCfJ6zEImS1dHiy9w+PlyYOTAfcMVfKUCraB+QGya1MpcOvrj9S+zQ/VEYIut5Lv0Ji4MQbJiN89oskTeXQDM9RJyegWRb8rnwmvPEUoPPspyGqSVOqDWdgD2N79AWZOfNTiJfOw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=RJCKlhr43ByCxAof3L/66lk/UcOiRbkW3BDM1Ju2w0Q=; b=CFpdMbaVJhs2ocXxqf91MWrZIZ5KJV/P4hWnR1PHC+YdCbs9NelC+N9usVufyTFHhsVuPWuyd8sAq2Pl0E0ta+q6DJjJbO75at7tdD03MHiFiXCO77ZYSxFvd4n8Mi6xWm5aMAPMFmoJhJI/n0wEnmbjT/Rj8kC66J4qy12CPTCsWd3z5H5dG1AU/DYx5E0mPX/sJ81X1JMb4CXq9D4t13xF6VOBfStqHge79pY1FllxPpmYfpAoHf6zL3Xts4KdgswEMo/FnP5Jlm79FJZmI1x+YupiyPsgosu8+D0ovhM5fuDU0PoJ7AboRVE+jYYfOFt/HQ8yhXqUD1RJyHHeqA== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=wdc.com; dmarc=pass action=none header.from=wdc.com; dkim=pass header.d=wdc.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sharedspace.onmicrosoft.com; s=selector2-sharedspace-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=RJCKlhr43ByCxAof3L/66lk/UcOiRbkW3BDM1Ju2w0Q=; b=BYad8/yVH9onztcr0/dUgONs6ii/WBdsw3Cueb+XW4ypXkjEF/EBZzJnej1mMatJtFCPGpDoePzxjhCWGE01FX64n/VwqsaJszIhlXufgRqplbGKv2E/gPj24CpcizW/y93zpdBryoGn7JeXffZkOn+hzCHwGeDD5zWt6qH2sFY= Received: from BY5PR04MB6980.namprd04.prod.outlook.com (10.186.134.11) by BY5PR04MB6581.namprd04.prod.outlook.com (52.135.41.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.2686.29; Sat, 1 Feb 2020 00:06:36 +0000 Received: from BY5PR04MB6980.namprd04.prod.outlook.com ([fe80::d068:7819:b5cf:353]) by BY5PR04MB6980.namprd04.prod.outlook.com ([fe80::d068:7819:b5cf:353%5]) with mapi id 15.20.2686.028; Sat, 1 Feb 2020 00:06:36 +0000 From: "Maciej W. Rozycki" To: "gdb-patches@sourceware.org" CC: Jim Wilson , Andrew Burgess , Palmer Dabbelt , Tom Tromey , "guoren@kernel.org" , "lifang_xia@c-sky.com" , "yunhai_shang@c-sky.com" , "jiangshuai_li@c-sky.com" Subject: [PATCH v4 1/3] RISC-V/Linux/native: Determine FLEN dynamically Date: Sat, 1 Feb 2020 00:06:36 +0000 Message-ID: References: In-Reply-To: authentication-results: spf=none (sender IP is ) smtp.mailfrom=macro@wdc.com; x-ms-exchange-transport-forked: True wdcipoutbound: EOP-TRUE x-ms-oob-tlc-oobclassifiers: OLM:9508; x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-messagedata: w02jrEJr9Uiv6jkFQKeu3+rtB6OHnxsIyTtEV7eNeVHWK4fqkBNJfaPwCcERUr76y8XdTrusZldFBDdRARcuQlBwRdfMRq7LE/gAEnCAn8Rsqo2l5i0vF1/lHWubC2TqGg1eIK+vTFpZbRJwK+aLFg== Content-ID: <26B447E953DD6B4F9EECE72D0AC34D56@namprd04.prod.outlook.com> MIME-Version: 1.0 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: fS/lQLaVSxQnwJVXU1Y+EMc1hCl5ixt6ijZNAoNJMAsjYfsy9V3u0gQ9zUXvIbwl Fix RISC-V native Linux support to handle a 64-bit FPU (FLEN == 64) with both RV32 and RV64 systems, which is a part of the current Linux ABI for hard-float systems, rather than assuming that (FLEN == XLEN) in target description determination and that (FLEN == 64) in register access. We can do better however and not rely on any particular value of FLEN and probe for it dynamically, by observing that the PTRACE_GETREGSET ptrace(2) call will only accept an exact regset size, and that will reflect FLEN. Therefore iterate over the call in target description determination with a geometrically increasing regset size until a match is marked by a successful ptrace(2) call completion or we run beyond the maximum size we can support. Update register accessors accordingly, using FLEN determined to size the buffer used for NT_PRSTATUS requests and then to exchange data with the regcache. Also handle a glibc bug where ELF_NFPREG is defined in terms of NFPREG, however NFPREG is nowhere defined. gdb/ * riscv-linux-nat.c [!NFPREG] (NFPREG): New macro. (supply_fpregset_regnum, fill_fpregset): Handle regset buffer offsets according to FLEN determined. (riscv_linux_nat_target::read_description): Determine FLEN dynamically. (riscv_linux_nat_target::fetch_registers): Size regset buffer according to FLEN determined. (riscv_linux_nat_target::store_registers): Likewise. --- No changes from v3. Changes from v2: - Avoid an ambiguous FGR reference in `riscv_linux_nat_target::read_description'. - Advance through the buffer accessed in `supply_fpregset_regnum' and `fill_fpregset' so as to avoid doing a variable multiplication in a loop; also precalculate the buffer offset for single register accesses to avoid excessive line wrapping and improve code readability. - Move the `i' variable declaration to the beginning of `fill_fpregset', for consistency with `supply_fpregset_regnum' (since the loop is being rewritten anyway). Changes from v1: - Also set the size of the regset buffer dynamically in `riscv_linux_nat_target::fetch_registers' and `riscv_linux_nat_target::store_registers', and update `fill_fpregset' and `supply_fpregset_regnum' accordingly. --- gdb/riscv-linux-nat.c | 110 ++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 84 insertions(+), 26 deletions(-) gdb-riscv-linux-nat-flen.diff Index: binutils-gdb/gdb/riscv-linux-nat.c =================================================================== --- binutils-gdb.orig/gdb/riscv-linux-nat.c +++ binutils-gdb/gdb/riscv-linux-nat.c @@ -28,6 +28,11 @@ #include +/* Work around glibc header breakage causing ELF_NFPREG not to be usable. */ +#ifndef NFPREG +# define NFPREG 33 +#endif + /* RISC-V Linux native additions to the default linux support. */ class riscv_linux_nat_target final : public linux_nat_target @@ -88,21 +93,35 @@ static void supply_fpregset_regnum (struct regcache *regcache, const prfpregset_t *fpregs, int regnum) { + int flen = register_size (regcache->arch (), RISCV_FIRST_FP_REGNUM); + union + { + const prfpregset_t *fpregs; + const gdb_byte *buf; + } + fpbuf = { .fpregs = fpregs }; int i; if (regnum == -1) { /* We only support the FP registers and FCSR here. */ - for (i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++) - regcache->raw_supply (i, &fpregs->__d.__f[i - RISCV_FIRST_FP_REGNUM]); + for (i = RISCV_FIRST_FP_REGNUM; + i <= RISCV_LAST_FP_REGNUM; + i++, fpbuf.buf += flen) + regcache->raw_supply (i, fpbuf.buf); - regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); } else if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) - regcache->raw_supply (regnum, - &fpregs->__d.__f[regnum - RISCV_FIRST_FP_REGNUM]); + { + fpbuf.buf += flen * (regnum - RISCV_FIRST_FP_REGNUM); + regcache->raw_supply (regnum, fpbuf.buf); + } else if (regnum == RISCV_CSR_FCSR_REGNUM) - regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + { + fpbuf.buf += flen * (RISCV_LAST_FP_REGNUM - RISCV_FIRST_FP_REGNUM + 1); + regcache->raw_supply (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); + } } /* Copy all floating point registers from regset FPREGS into REGCACHE. */ @@ -145,19 +164,35 @@ void fill_fpregset (const struct regcache *regcache, prfpregset_t *fpregs, int regnum) { + int flen = register_size (regcache->arch (), RISCV_FIRST_FP_REGNUM); + union + { + prfpregset_t *fpregs; + gdb_byte *buf; + } + fpbuf = { .fpregs = fpregs }; + int i; + if (regnum == -1) { /* We only support the FP registers and FCSR here. */ - for (int i = RISCV_FIRST_FP_REGNUM; i <= RISCV_LAST_FP_REGNUM; i++) - regcache->raw_collect (i, &fpregs->__d.__f[i - RISCV_FIRST_FP_REGNUM]); + for (i = RISCV_FIRST_FP_REGNUM; + i <= RISCV_LAST_FP_REGNUM; + i++, fpbuf.buf += flen) + regcache->raw_collect (i, fpbuf.buf); - regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); } else if (regnum >= RISCV_FIRST_FP_REGNUM && regnum <= RISCV_LAST_FP_REGNUM) - regcache->raw_collect (regnum, - &fpregs->__d.__f[regnum - RISCV_FIRST_FP_REGNUM]); + { + fpbuf.buf += flen * (regnum - RISCV_FIRST_FP_REGNUM); + regcache->raw_collect (regnum, fpbuf.buf); + } else if (regnum == RISCV_CSR_FCSR_REGNUM) - regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, &fpregs->__d.__fcsr); + { + fpbuf.buf += flen * (RISCV_LAST_FP_REGNUM - RISCV_FIRST_FP_REGNUM + 1); + regcache->raw_collect (RISCV_CSR_FCSR_REGNUM, fpbuf.buf); + } } /* Return a target description for the current target. */ @@ -166,8 +201,8 @@ const struct target_desc * riscv_linux_nat_target::read_description () { struct riscv_gdbarch_features features; - struct iovec iov; elf_fpregset_t regs; + int flen; int tid; /* Figuring out xlen is easy. */ @@ -175,19 +210,40 @@ riscv_linux_nat_target::read_description tid = inferior_ptid.lwp (); - iov.iov_base = ®s; - iov.iov_len = sizeof (regs); + /* Start with no f-registers. */ + features.flen = 0; - /* Can we fetch the f-registers? */ - if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, - (PTRACE_TYPE_ARG3) &iov) == -1) - features.flen = 0; /* No f-registers. */ - else + /* How much worth of f-registers can we fetch if any? */ + for (flen = sizeof (regs.__f.__f[0]); ; flen *= 2) { - /* TODO: We need a way to figure out the actual length of the - f-registers. We could have 64-bit x-registers, with 32-bit - f-registers. For now, just assumed xlen and flen match. */ - features.flen = features.xlen; + size_t regset_size; + struct iovec iov; + + /* Regsets have a uniform slot size, so we count FSCR like + an FP data register. */ + regset_size = ELF_NFPREG * flen; + if (regset_size > sizeof (regs)) + break; + + iov.iov_base = ®s; + iov.iov_len = regset_size; + if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, + (PTRACE_TYPE_ARG3) &iov) == -1) + { + switch (errno) + { + case EINVAL: + continue; + case EIO: + break; + default: + perror_with_name (_("Couldn't get registers")); + break; + } + } + else + features.flen = flen; + break; } return riscv_create_target_description (features); @@ -228,7 +284,8 @@ riscv_linux_nat_target::fetch_registers elf_fpregset_t regs; iov.iov_base = ®s; - iov.iov_len = sizeof (regs); + iov.iov_len = ELF_NFPREG * register_size (regcache->arch (), + RISCV_FIRST_FP_REGNUM); if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1) @@ -289,7 +346,8 @@ riscv_linux_nat_target::store_registers elf_fpregset_t regs; iov.iov_base = ®s; - iov.iov_len = sizeof (regs); + iov.iov_len = ELF_NFPREG * register_size (regcache->arch (), + RISCV_FIRST_FP_REGNUM); if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, (PTRACE_TYPE_ARG3) &iov) == -1)