From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from simark.ca by simark.ca with LMTP id oLdlKczq+WS9kRIAWB0awg (envelope-from ) for ; Thu, 07 Sep 2023 11:22:52 -0400 Authentication-Results: simark.ca; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=HU6D9X/A; dkim-atps=neutral Received: by simark.ca (Postfix, from userid 112) id A62911E0C3; Thu, 7 Sep 2023 11:22:52 -0400 (EDT) Received: from server2.sourceware.org (ip-8-43-85-97.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by simark.ca (Postfix) with ESMTPS id 8B7D21E092 for ; Thu, 7 Sep 2023 11:22:50 -0400 (EDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 108F7385086B for ; Thu, 7 Sep 2023 15:22:50 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 108F7385086B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1694100170; bh=P2ZBfnwiYwZZhA+Ye5n5liGl62yApGtAVaiZ+6AA0fg=; h=To:CC:Subject:Date:In-Reply-To:References:List-Id: List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe: From:Reply-To:From; b=HU6D9X/A6GzlyfhnsOEl32bIl3oEKYYkfBYrNF5qhjQQrZRbPlCw3les7Ph+nEzvS WJShv1pfmBxN3XL1l7ZKm2vcWvlNcQoHhI45TBrA3qt5gw6Bh281NlNVXJH5Kik6cI GwrRHQV7lIcJFF0QExdotpjYUlqLy0tG1MMyLqqk= Received: from EUR04-HE1-obe.outbound.protection.outlook.com (mail-he1eur04on2042.outbound.protection.outlook.com [40.107.7.42]) by sourceware.org (Postfix) with ESMTPS id CE0A0385841D for ; Thu, 7 Sep 2023 15:20:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CE0A0385841D Received: from DU2PR04CA0238.eurprd04.prod.outlook.com (2603:10a6:10:2b1::33) by AS8PR08MB6616.eurprd08.prod.outlook.com (2603:10a6:20b:319::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.34; Thu, 7 Sep 2023 15:20:34 +0000 Received: from DBAEUR03FT036.eop-EUR03.prod.protection.outlook.com (2603:10a6:10:2b1:cafe::83) by DU2PR04CA0238.outlook.office365.com (2603:10a6:10:2b1::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.30 via Frontend Transport; Thu, 7 Sep 2023 15:20:34 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=armh.onmicrosoft.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by DBAEUR03FT036.mail.protection.outlook.com (100.127.142.193) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6768.28 via Frontend Transport; Thu, 7 Sep 2023 15:20:34 +0000 Received: ("Tessian outbound 5c548696a0e7:v175"); Thu, 07 Sep 2023 15:20:34 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 08e14713ace224e1 X-CR-MTA-TID: 64aa7808 Received: from 2f8b2c5498c1.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 43588D97-AB97-4D11-AF29-70FF9D32037E.1; Thu, 07 Sep 2023 15:20:26 +0000 Received: from EUR04-HE1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 2f8b2c5498c1.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Thu, 07 Sep 2023 15:20:26 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=kz/Qkc2SIqUvZxKoI+Uz+js3hyAhpj0GFSnzFNSHfVM4QutKD1dEo0dw0gLo0EnVi1BTROTyn1+o86+CPwPMH0scpPygVfwz6QOYoNrLfkH7FA7EHRG8+xSvdouMD8SDRppOhz6N3lFdfwYrhLghCZdu9nT49xrkluRRe2WbWnpm7GrT3Or52pVBbS4mwaXxJFH72K3P76/hSvZuxxU/batChHmKl05dMNPxp+Y7dfI6CMgAFMA5upLusM/UPq0Kqu5dexiJRNo12my3f2zgcaun71mbqpRB+c/ov2uv6q3UIfxkj3oDYNlO7GY4PsTywbko32L0wK9mojV5/T5BFQ== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=P2ZBfnwiYwZZhA+Ye5n5liGl62yApGtAVaiZ+6AA0fg=; b=JOFScNY7qFIOI5ImPAMDjog7mraKmJpNy90POSdLjIvK0gf85p2H0VL74zKWagA9AA960HdFoBtNQMis5MofH8N9Y1xCPB6Du7j1xGC36EgKLvq1Z4kdXsuba4NFmYHzCYs543bc7nLlPrm6OmWdxA1voBX0YKP+phQgRS5lqd9BX4w48E0QSNQAgbCYegP9D+FPbaBIdlotEYk0F3hfmBQMdfuugS6x2ZmACkd54Sa6/Kgs5s5LAEesag6q2N/5ytoDQ2YTJKe8AS1NdViOEHb9AQw4zIygQ3zvGuj/4Bf4nJDrT8OWKxN8OEzgtvdTfyl7fZB1nLMiGri99rzB6g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=sourceware.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=none (message not signed); arc=none Received: from AS9PR05CA0349.eurprd05.prod.outlook.com (2603:10a6:20b:490::33) by AS8PR08MB6101.eurprd08.prod.outlook.com (2603:10a6:20b:29a::7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.34; Thu, 7 Sep 2023 15:20:22 +0000 Received: from AM7EUR03FT023.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:490:cafe::b5) by AS9PR05CA0349.outlook.office365.com (2603:10a6:20b:490::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6745.38 via Frontend Transport; Thu, 7 Sep 2023 15:20:22 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; pr=C Received: from nebula.arm.com (40.67.248.234) by AM7EUR03FT023.mail.protection.outlook.com (100.127.140.73) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6768.28 via Frontend Transport; Thu, 7 Sep 2023 15:20:22 +0000 Received: from AZ-NEU-EX03.Arm.com (10.251.24.31) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.27; Thu, 7 Sep 2023 15:20:21 +0000 Received: from e129171.cambridge.arm.com (10.1.32.59) by mail.arm.com (10.251.24.31) with Microsoft SMTP Server id 15.1.2507.27 via Frontend Transport; Thu, 7 Sep 2023 15:20:21 +0000 To: CC: Subject: [PATCH v5 03/16] [gdb/gdbserver] refactor: Simplify SVE interface to read/write registers Date: Thu, 7 Sep 2023 16:20:05 +0100 Message-ID: <20230907152018.1031257-4-luis.machado@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230907152018.1031257-1-luis.machado@arm.com> References: <20230907152018.1031257-1-luis.machado@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain X-EOPAttributedMessage: 1 X-MS-TrafficTypeDiagnostic: AM7EUR03FT023:EE_|AS8PR08MB6101:EE_|DBAEUR03FT036:EE_|AS8PR08MB6616:EE_ X-MS-Office365-Filtering-Correlation-Id: a5efe7dd-f272-4df5-ce72-08dbafb5fb7c x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; X-Microsoft-Antispam-Message-Info-Original: zEucj6jnwtzwNEaDFWRuzJN0CSKm7cR9BgL5Oh4QQLalTG3Sqzcmcp/tNxB8A8hJHEkBcdIlljqu/Hs08YvSaJlATCr2HzmbbowHPLEwVSTQ5V5QPhLRFx4xhPk1SMvZpd6UBWA6QdtSr8OgEdujjzC5mtzJnVcv4CAn1FL5NIqJHD7tffV4whfxMn7UB0hFpKJCRhALBAEpC0A8nwtDMtXDOO2r2Nnko4tuE+AoC8Jv1TCbZY/1D+keN4mWSiYz6bf4qGDIidLaNDVnt/1w7jhxIk7SFUkPb4xLBSlUDXoOlS6yUTaVjcdc+mOTvW3bGm4FJGeiCY2NUOrAJvOCeuLrX47+NXgRftMNcLEG2FECaJ+j3opVJZ2A3ANyDNPp2fq/yc7tJP08RrGiIKwwqpPpiuTxmwNS3Ux792ovuU36mCy1vpxse7DhMKqym2xSWp9yBF6/nyH+SXj1HAhdna82a9g+n7dT3w2FqKtph2YKfxLdLtiSNVgvRLpHpQtpwcjO+FRgpgB4hfYIXxJayaT5Ls9X9mI2GAcFt7NjRQ+RF+dGDMUd5ZjGowhPGnxX0emg9ir3KO5K8mRKdac5jC+t6nvif0ZhIZPJWqO+4ONCEOFyNtMMv211/Tcpal/SGaeJzrogUiPZrbapCi6zkh9/Z3my2DCZzz1F1yumBMDRngDP2KZ3kmHTFCEMHCVCsyi1GQebRPq+UYIkoNjvCCCbsTek2lSJwYmcz+2iyTzFn87b+Lvzc4R1GhHiIpiwsyqKCMf8TSHSXj5CeeJrlQ== X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:nebula.arm.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230031)(4636009)(396003)(346002)(39860400002)(136003)(376002)(186009)(1800799009)(451199024)(82310400011)(46966006)(40470700004)(36840700001)(8676002)(44832011)(4326008)(8936002)(6666004)(30864003)(70206006)(6916009)(5660300002)(41300700001)(478600001)(70586007)(2906002)(316002)(426003)(336012)(1076003)(26005)(7696005)(2616005)(36860700001)(83380400001)(47076005)(356005)(82740400003)(81166007)(40480700001)(86362001)(40460700003)(36756003)(36900700001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB6101 X-MS-Exchange-Transport-CrossTenantHeadersStripped: DBAEUR03FT036.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: 54e9e3c2-d827-4c03-a199-08dbafb5f424 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: E0oz7JsUmQ5EIn1amy27GoYYZRVhTgelU4EAkQHR13HwO4dqMw9J2DqYcRYGTLhv+GW7djqAly9R9AhO8g92AbuEu2IjORfvcY1pnXbnaWCLJXMt5bpFV7TD+/YCctO2ki73Enebhl4hvSHYP1Lx9buHhcCMSnMyfCezWmgFFRAaHAsQ52XcOd5++5Hs8aAH+V75O4lba5yIzkaxvTZDtiCLYc/kZ77GMb4YJRfDLzHGKzXw+pzjdPYKhWbn/TDoi6UdifYv/rE9VODg8V/n61hJagS4jSeHsSeFuISd3xxEpCtlCF5kSCOL05BMPRKfK8BcvEPOCDkAuHzzeufSdiwa5I6N+N3bm8uFhosp4xneB3ufiOgO8/XglDDhhC2c6i7RcLhuvhzzejwznrsFeHUOiqoOT/FMCbbGPjaiB047CELhuJCGdEnXS+ZUYa3flh8E43w7L2hTHnPvb26YsvIeURA3BuWEKRSurw1aW7xAfqwu687FYr8vWWI7lRAtRIuaBGnYh8BcfEfdwP3RC/awXq9Rqs3TFKOal6Tce0ub2Mfdnyn1Sl4T3b0Ic8TAPqx6XVby/0s03IYzPpawWCyszRjZiPSReP2IirEf5JppB6hVGg1OCyHukJDwZWg25/GUgvPYk/vNZK8KsF9JSwTeB/6EHXlLToqHShP2p4vEsj4kUR6Fhlb8SVdOWxLejg7gcyEJvFTfsguUGJ8Jy1bWEclzuI4W979LM2Lqptu9WUaalLXrB6pRY/PVq2za X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230031)(4636009)(39860400002)(376002)(136003)(346002)(396003)(186009)(451199024)(1800799009)(82310400011)(46966006)(40470700004)(36840700001)(82740400003)(81166007)(6666004)(7696005)(40460700003)(36860700001)(86362001)(36756003)(47076005)(40480700001)(107886003)(26005)(336012)(1076003)(2906002)(30864003)(426003)(83380400001)(2616005)(478600001)(316002)(8936002)(70206006)(8676002)(4326008)(5660300002)(44832011)(70586007)(41300700001)(6916009); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 07 Sep 2023 15:20:34.6102 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: a5efe7dd-f272-4df5-ce72-08dbafb5fb7c X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: DBAEUR03FT036.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR08MB6616 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, UNPARSEABLE_RELAY autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Luis Machado via Gdb-patches Reply-To: Luis Machado Errors-To: gdb-patches-bounces+public-inbox=simark.ca@sourceware.org Sender: "Gdb-patches" Updates on v4: - Removed unused return value. - Fixed buffer overrun in a for loop. --- This is a patch in preparation to upcoming patches enabling SME support. It attempts to simplify the gdb/gdbserver shared interface used to read/write SVE registers. Where the current code makes use of unique_ptr, allocating a new buffer by hand and passing a buffer around, this patch makes that code use gdb::byte_vector and passes a reference to this byte vector to the functions, allowing the functions to have ready access to the size of the buffer. It also shares a bit more code between gdb and gdbserver, in particular around handling of ptrace get/set requests for SVE. I think gdbserver could be refactored to handle register reads/writes more like gdb's native layer as opposed to letting the generic linux-low layer do the ptrace calls. This is not very flexible and assumes one size for the responses. If you have something like NT_ARM_SVE, where you can have either FPSIMD or SVE contents, it doesn't work that well. I didn't want to change that interface right now as it is a bit too much work and touches all the targets, some of which I can't easily test. Hence the reason why the buffer the generic linux-now passes down to linux-aarch64-low is unused or ignored. No user-visible changes should happen as part of this refactor other than a slightly reworded warning message. While doing the refactor, I also noticed what seems to be a mistake in checking if the register cache contains active (non-zero) SVE data. For instance, the original code did something like this in aarch64_sve_regs_copy_from_reg_buf: has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i reg, sizeof (__int128_t)); "reg" is a zeroed-out buffer that we compare the Z register contents past the first 128 bits. The problem here is that raw_compare returns 1 if the contents compare the same, which means has_sve_state will be true. But if we compared the Z register contents to 0, it means we *do not* have SVE state, and therefore has_sve_state should be false. The consequence of this mistake is that we convert the initial FPSIMD-formatted data we get from ptrace for the NT_ARM_SVE register set to a SVE-formatted one. In the end, this doesn't cause user-visible differences because the values of both the Z and V registers will still be the same. But the logic is not correct. I used the opportunity to fix this, and it gets tested later on by the additional SME tests. I do plan on submitting some SVE-specific tests to make sure we have a bit more coverage in GDB's testsuite. Regression-tested on aarch64-linux Ubuntu 22.04/20.04. --- gdb/aarch64-linux-nat.c | 30 +--- gdb/nat/aarch64-scalable-linux-ptrace.c | 202 +++++++++++++++--------- gdb/nat/aarch64-scalable-linux-ptrace.h | 27 ++-- gdbserver/linux-aarch64-low.cc | 24 ++- 4 files changed, 173 insertions(+), 110 deletions(-) diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c index 9f32279c0ac..267a1ca0e79 100644 --- a/gdb/aarch64-linux-nat.c +++ b/gdb/aarch64-linux-nat.c @@ -319,9 +319,8 @@ store_fpregs_to_thread (const struct regcache *regcache) static void fetch_sveregs_from_thread (struct regcache *regcache) { - std::unique_ptr base - = aarch64_sve_get_sveregs (regcache->ptid ().lwp ()); - aarch64_sve_regs_copy_to_reg_buf (regcache, base.get ()); + /* Fetch SVE state from the thread and copy it into the register cache. */ + aarch64_sve_regs_copy_to_reg_buf (regcache->ptid ().lwp (), regcache); } /* Store to the current thread the valid sve register @@ -330,28 +329,9 @@ fetch_sveregs_from_thread (struct regcache *regcache) static void store_sveregs_to_thread (struct regcache *regcache) { - int ret; - struct iovec iovec; - int tid = regcache->ptid ().lwp (); - - /* First store vector length to the thread. This is done first to ensure the - ptrace buffers read from the kernel are the correct size. */ - if (!aarch64_sve_set_vq (tid, regcache)) - perror_with_name (_("Unable to set VG register")); - - /* Obtain a dump of SVE registers from ptrace. */ - std::unique_ptr base = aarch64_sve_get_sveregs (tid); - - /* Overwrite with regcache state. */ - aarch64_sve_regs_copy_from_reg_buf (regcache, base.get ()); - - /* Write back to the kernel. */ - iovec.iov_base = base.get (); - iovec.iov_len = ((struct user_sve_header *) base.get ())->size; - ret = ptrace (PTRACE_SETREGSET, tid, NT_ARM_SVE, &iovec); - - if (ret < 0) - perror_with_name (_("Unable to store sve registers")); + /* Fetch SVE state from the register cache and update the thread TID with + it. */ + aarch64_sve_regs_copy_from_reg_buf (regcache->ptid ().lwp (), regcache); } /* Fill GDB's register array with the pointer authentication mask values from diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.c b/gdb/nat/aarch64-scalable-linux-ptrace.c index cc43f510892..6eea9104cef 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.c +++ b/gdb/nat/aarch64-scalable-linux-ptrace.c @@ -120,28 +120,43 @@ aarch64_sve_set_vq (int tid, struct reg_buffer_common *reg_buf) /* See nat/aarch64-scalable-linux-ptrace.h. */ -std::unique_ptr -aarch64_sve_get_sveregs (int tid) +gdb::byte_vector +aarch64_fetch_sve_regset (int tid) { - struct iovec iovec; uint64_t vq = aarch64_sve_get_vq (tid); if (vq == 0) - perror_with_name (_("Unable to fetch SVE register header")); + perror_with_name (_("Unable to fetch SVE vector length")); /* A ptrace call with NT_ARM_SVE will return a header followed by either a dump of all the SVE and FP registers, or an fpsimd structure (identical to the one returned by NT_FPREGSET) if the kernel has not yet executed any SVE code. Make sure we allocate enough space for a full SVE dump. */ - iovec.iov_len = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE); - std::unique_ptr buf (new gdb_byte[iovec.iov_len]); - iovec.iov_base = buf.get (); + gdb::byte_vector sve_state (SVE_PT_SIZE (vq, SVE_PT_REGS_SVE), 0); + + struct iovec iovec; + iovec.iov_base = sve_state.data (); + iovec.iov_len = sve_state.size (); if (ptrace (PTRACE_GETREGSET, tid, NT_ARM_SVE, &iovec) < 0) perror_with_name (_("Unable to fetch SVE registers")); - return buf; + return sve_state; +} + +/* See nat/aarch64-scalable-linux-ptrace.h. */ + +void +aarch64_store_sve_regset (int tid, const gdb::byte_vector &sve_state) +{ + struct iovec iovec; + /* We need to cast from (const void *) here. */ + iovec.iov_base = (void *) sve_state.data (); + iovec.iov_len = sve_state.size (); + + if (ptrace (PTRACE_SETREGSET, tid, NT_ARM_SVE, &iovec) < 0) + perror_with_name (_("Unable to store SVE registers")); } /* If we are running in BE mode, byteswap the contents @@ -165,11 +180,13 @@ aarch64_maybe_swab128 (gdb_byte *dst, const gdb_byte *src, size_t size) /* See nat/aarch64-scalable-linux-ptrace.h. */ void -aarch64_sve_regs_copy_to_reg_buf (struct reg_buffer_common *reg_buf, - const void *buf) +aarch64_sve_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf) { - char *base = (char *) buf; - struct user_sve_header *header = (struct user_sve_header *) buf; + gdb::byte_vector sve_state = aarch64_fetch_sve_regset (tid); + + char *base = (char *) sve_state.data (); + struct user_sve_header *header + = (struct user_sve_header *) sve_state.data (); uint64_t vq = sve_vq_from_vl (header->vl); uint64_t vg = sve_vg_from_vl (header->vl); @@ -249,18 +266,33 @@ aarch64_sve_regs_copy_to_reg_buf (struct reg_buffer_common *reg_buf, reg_buf->raw_supply (AARCH64_SVE_FFR_REGNUM, reg); } + + /* At this point we have updated the register cache with the contents of + the NT_ARM_SVE register set. */ } /* See nat/aarch64-scalable-linux-ptrace.h. */ void -aarch64_sve_regs_copy_from_reg_buf (const struct reg_buffer_common *reg_buf, - void *buf) +aarch64_sve_regs_copy_from_reg_buf (int tid, + struct reg_buffer_common *reg_buf) { - struct user_sve_header *header = (struct user_sve_header *) buf; - char *base = (char *) buf; + /* First store the vector length to the thread. This is done first to + ensure the ptrace buffers read from the kernel are the correct size. */ + if (!aarch64_sve_set_vq (tid, reg_buf)) + perror_with_name (_("Unable to set VG register")); + + /* Obtain a dump of SVE registers from ptrace. */ + gdb::byte_vector sve_state = aarch64_fetch_sve_regset (tid); + + struct user_sve_header *header = (struct user_sve_header *) sve_state.data (); uint64_t vq = sve_vq_from_vl (header->vl); + gdb::byte_vector new_state (SVE_PT_SIZE (32, SVE_PT_REGS_SVE), 0); + memcpy (new_state.data (), sve_state.data (), sve_state.size ()); + header = (struct user_sve_header *) new_state.data (); + char *base = (char *) new_state.data (); + /* Sanity check the data in the header. */ if (!sve_vl_valid (header->vl) || SVE_PT_SIZE (vq, header->flags) != header->size) @@ -275,36 +307,40 @@ aarch64_sve_regs_copy_from_reg_buf (const struct reg_buffer_common *reg_buf, resulting in the initialization of SVE state written back to the kernel, which is why we try to avoid it. */ - bool has_sve_state = false; - gdb_byte *reg = (gdb_byte *) alloca (SVE_PT_SVE_ZREG_SIZE (vq)); - struct user_fpsimd_state *fpsimd - = (struct user_fpsimd_state *)(base + SVE_PT_FPSIMD_OFFSET); - - memset (reg, 0, SVE_PT_SVE_ZREG_SIZE (vq)); + /* Buffer (using the maximum size a Z register) used to look for zeroed + out sve state. */ + gdb_byte reg[256]; + memset (reg, 0, sizeof (reg)); /* Check in the reg_buf if any of the Z registers are set after the first 128 bits, or if any of the other SVE registers are set. */ - + bool has_sve_state = false; for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++) { - has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i, - reg, sizeof (__int128_t)); - if (has_sve_state) - break; + if (!reg_buf->raw_compare (AARCH64_SVE_Z0_REGNUM + i, reg, + V_REGISTER_SIZE)) + { + has_sve_state = true; + break; + } } if (!has_sve_state) for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++) { - has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_P0_REGNUM + i, - reg, 0); - if (has_sve_state) - break; + if (!reg_buf->raw_compare (AARCH64_SVE_P0_REGNUM + i, reg, 0)) + { + has_sve_state = true; + break; + } } if (!has_sve_state) - has_sve_state |= reg_buf->raw_compare (AARCH64_SVE_FFR_REGNUM, - reg, 0); + has_sve_state + = !reg_buf->raw_compare (AARCH64_SVE_FFR_REGNUM, reg, 0); + + struct user_fpsimd_state *fpsimd + = (struct user_fpsimd_state *)(base + SVE_PT_FPSIMD_OFFSET); /* If no SVE state exists, then use the existing fpsimd structure to write out state and return. */ @@ -344,50 +380,74 @@ aarch64_sve_regs_copy_from_reg_buf (const struct reg_buffer_common *reg_buf, if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM)) reg_buf->raw_collect (AARCH64_FPCR_REGNUM, &fpsimd->fpcr); - return; - } - - /* Otherwise, reformat the fpsimd structure into a full SVE set, by - expanding the V registers (working backwards so we don't splat - registers before they are copied) and using null for everything else. - Note that enough space for a full SVE dump was originally allocated - for base. */ + /* At this point we have collected all the data from the register + cache and we are ready to update the FPSIMD register content + of the thread. */ - header->flags |= SVE_PT_REGS_SVE; - header->size = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE); + /* Fall through so we can update the thread's contents with the + FPSIMD register cache values. */ + } + else + { + /* Otherwise, reformat the fpsimd structure into a full SVE set, by + expanding the V registers (working backwards so we don't splat + registers before they are copied) and using zero for everything + else. + Note that enough space for a full SVE dump was originally allocated + for base. */ + + header->flags |= SVE_PT_REGS_SVE; + header->size = SVE_PT_SIZE (vq, SVE_PT_REGS_SVE); + + memcpy (base + SVE_PT_SVE_FPSR_OFFSET (vq), &fpsimd->fpsr, + sizeof (uint32_t)); + memcpy (base + SVE_PT_SVE_FPCR_OFFSET (vq), &fpsimd->fpcr, + sizeof (uint32_t)); + + for (int i = AARCH64_SVE_Z_REGS_NUM - 1; i >= 0 ; i--) + { + memcpy (base + SVE_PT_SVE_ZREG_OFFSET (vq, i), &fpsimd->vregs[i], + sizeof (__int128_t)); + } - memcpy (base + SVE_PT_SVE_FPSR_OFFSET (vq), &fpsimd->fpsr, - sizeof (uint32_t)); - memcpy (base + SVE_PT_SVE_FPCR_OFFSET (vq), &fpsimd->fpcr, - sizeof (uint32_t)); + /* At this point we have converted the FPSIMD layout to an SVE + layout and copied the register data. - for (int i = AARCH64_SVE_Z_REGS_NUM; i >= 0 ; i--) - { - memcpy (base + SVE_PT_SVE_ZREG_OFFSET (vq, i), &fpsimd->vregs[i], - sizeof (__int128_t)); + Fall through so we can update the thread's contents with the SVE + register cache values. */ } } + else + { + /* We already have SVE state for this thread, so we just need to update + the values of the registers. */ + for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++) + if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_Z0_REGNUM + + i)) + reg_buf->raw_collect (AARCH64_SVE_Z0_REGNUM + i, + base + SVE_PT_SVE_ZREG_OFFSET (vq, i)); - /* Replace the kernel values with those from reg_buf. */ - - for (int i = 0; i < AARCH64_SVE_Z_REGS_NUM; i++) - if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_Z0_REGNUM + i)) - reg_buf->raw_collect (AARCH64_SVE_Z0_REGNUM + i, - base + SVE_PT_SVE_ZREG_OFFSET (vq, i)); - - for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++) - if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_P0_REGNUM + i)) - reg_buf->raw_collect (AARCH64_SVE_P0_REGNUM + i, - base + SVE_PT_SVE_PREG_OFFSET (vq, i)); + for (int i = 0; i < AARCH64_SVE_P_REGS_NUM; i++) + if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_P0_REGNUM + + i)) + reg_buf->raw_collect (AARCH64_SVE_P0_REGNUM + i, + base + SVE_PT_SVE_PREG_OFFSET (vq, i)); + + if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_FFR_REGNUM)) + reg_buf->raw_collect (AARCH64_SVE_FFR_REGNUM, + base + SVE_PT_SVE_FFR_OFFSET (vq)); + if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM)) + reg_buf->raw_collect (AARCH64_FPSR_REGNUM, + base + SVE_PT_SVE_FPSR_OFFSET (vq)); + if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM)) + reg_buf->raw_collect (AARCH64_FPCR_REGNUM, + base + SVE_PT_SVE_FPCR_OFFSET (vq)); + } - if (REG_VALID == reg_buf->get_register_status (AARCH64_SVE_FFR_REGNUM)) - reg_buf->raw_collect (AARCH64_SVE_FFR_REGNUM, - base + SVE_PT_SVE_FFR_OFFSET (vq)); - if (REG_VALID == reg_buf->get_register_status (AARCH64_FPSR_REGNUM)) - reg_buf->raw_collect (AARCH64_FPSR_REGNUM, - base + SVE_PT_SVE_FPSR_OFFSET (vq)); - if (REG_VALID == reg_buf->get_register_status (AARCH64_FPCR_REGNUM)) - reg_buf->raw_collect (AARCH64_FPCR_REGNUM, - base + SVE_PT_SVE_FPCR_OFFSET (vq)); + /* At this point we have collected all the data from the register cache and + we are ready to update the SVE/FPSIMD register contents of the thread. + sve_state should contain all the data in the correct format, ready to be + passed on to ptrace. */ + aarch64_store_sve_regset (tid, new_state); } diff --git a/gdb/nat/aarch64-scalable-linux-ptrace.h b/gdb/nat/aarch64-scalable-linux-ptrace.h index 2847c4e0263..167782c493d 100644 --- a/gdb/nat/aarch64-scalable-linux-ptrace.h +++ b/gdb/nat/aarch64-scalable-linux-ptrace.h @@ -52,22 +52,27 @@ uint64_t aarch64_sve_get_vq (int tid); bool aarch64_sve_set_vq (int tid, uint64_t vq); bool aarch64_sve_set_vq (int tid, struct reg_buffer_common *reg_buf); -/* Read the current SVE register set using ptrace, allocating space as - required. */ +/* Read the current SVE register set from thread TID and return its data + through a byte vector. */ -extern std::unique_ptr aarch64_sve_get_sveregs (int tid); +extern gdb::byte_vector aarch64_fetch_sve_regset (int tid); -/* Put the registers from linux structure buf into register buffer. Assumes the - vector lengths in the register buffer match the size in the kernel. */ +/* Write the SVE contents from SVE_STATE to thread TID. */ -extern void aarch64_sve_regs_copy_to_reg_buf (struct reg_buffer_common *reg_buf, - const void *buf); +extern void +aarch64_store_sve_regset (int tid, const gdb::byte_vector &sve_state); + +/* Given a thread id TID and a register buffer REG_BUF, update the register + buffer with the SVE state from thread TID. */ + +extern void +aarch64_sve_regs_copy_to_reg_buf (int tid, struct reg_buffer_common *reg_buf); -/* Put the registers from register buffer into linux structure buf. Assumes the - vector lengths in the register buffer match the size in the kernel. */ +/* Given a thread id TID and a register buffer REG_BUF containing SVE + register data, write the SVE data to thread TID. */ extern void -aarch64_sve_regs_copy_from_reg_buf (const struct reg_buffer_common *reg_buf, - void *buf); +aarch64_sve_regs_copy_from_reg_buf (int tid, + struct reg_buffer_common *reg_buf); #endif /* NAT_AARCH64_SCALABLE_LINUX_PTRACE_H */ diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc index 8b22f1979d6..7c633c212f3 100644 --- a/gdbserver/linux-aarch64-low.cc +++ b/gdbserver/linux-aarch64-low.cc @@ -719,9 +719,18 @@ aarch64_target::low_new_fork (process_info *parent, /* Wrapper for aarch64_sve_regs_copy_to_reg_buf. */ static void -aarch64_sve_regs_copy_to_regcache (struct regcache *regcache, const void *buf) +aarch64_sve_regs_copy_to_regcache (struct regcache *regcache, + ATTRIBUTE_UNUSED const void *buf) { - return aarch64_sve_regs_copy_to_reg_buf (regcache, buf); + /* BUF is unused here since we collect the data straight from a ptrace + request in aarch64_sve_regs_copy_to_reg_buf, therefore bypassing + gdbserver's own call to ptrace. */ + + int tid = lwpid_of (current_thread); + + /* Update the register cache. aarch64_sve_regs_copy_to_reg_buf handles + fetching the NT_ARM_SVE state from thread TID. */ + aarch64_sve_regs_copy_to_reg_buf (tid, regcache); } /* Wrapper for aarch64_sve_regs_copy_from_reg_buf. */ @@ -729,7 +738,16 @@ aarch64_sve_regs_copy_to_regcache (struct regcache *regcache, const void *buf) static void aarch64_sve_regs_copy_from_regcache (struct regcache *regcache, void *buf) { - return aarch64_sve_regs_copy_from_reg_buf (regcache, buf); + int tid = lwpid_of (current_thread); + + /* Update the thread SVE state. aarch64_sve_regs_copy_from_reg_buf + handles writing the SVE/FPSIMD state back to thread TID. */ + aarch64_sve_regs_copy_from_reg_buf (tid, regcache); + + /* We need to return the expected data in BUF, so copy whatever the kernel + already has to BUF. */ + gdb::byte_vector sve_state = aarch64_fetch_sve_regset (tid); + memcpy (buf, sve_state.data (), sve_state.size ()); } /* Array containing all the possible register sets for AArch64/Linux. During -- 2.25.1