From patchwork Fri May 19 10:25:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luis Machado X-Patchwork-Id: 69678 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 4617438425A6 for ; Fri, 19 May 2023 10:29:07 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 4617438425A6 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1684492147; bh=hpcvx1QSuY6/aIXHjmaUDwJPR7CVY++z9EIn9y2TLUQ=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=dacwy2L9q6GRHXOZ4AW4SMS38cMWLhBCzVTHDS9V7ZU8X0vkT1KdYyrj+OfrYq7zN J1nlOPLZfERZmejflsPLnWtHAbVFRmUsMForV0K2z9exn8xpUhkQdizq7vZkHEOyp8 eZDf3rVWZg9GuMYZ+zAcXJAU+hGpixuCHKtgMzjw= X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from EUR03-AM7-obe.outbound.protection.outlook.com (mail-am7eur03on2054.outbound.protection.outlook.com [40.107.105.54]) by sourceware.org (Postfix) with ESMTPS id C69933858426 for ; Fri, 19 May 2023 10:25:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org C69933858426 Received: from AM7PR03CA0030.eurprd03.prod.outlook.com (2603:10a6:20b:130::40) by GV2PR08MB8100.eurprd08.prod.outlook.com (2603:10a6:150:7a::9) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.21; Fri, 19 May 2023 10:25:27 +0000 Received: from AM7EUR03FT058.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:130:cafe::d9) by AM7PR03CA0030.outlook.office365.com (2603:10a6:20b:130::40) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.21 via Frontend Transport; Fri, 19 May 2023 10:25:27 +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 AM7EUR03FT058.mail.protection.outlook.com (100.127.140.247) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.19 via Frontend Transport; Fri, 19 May 2023 10:25:27 +0000 Received: ("Tessian outbound 99a3040377ca:v136"); Fri, 19 May 2023 10:25:27 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 4ac29ece902337dc X-CR-MTA-TID: 64aa7808 Received: from 44f7d938c9ec.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id 3E001AFA-CB6D-4505-95A3-A2E2D9094AC4.1; Fri, 19 May 2023 10:25:21 +0000 Received: from EUR02-AM0-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id 44f7d938c9ec.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Fri, 19 May 2023 10:25:21 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=Rd4NWOV3o2rf8QYojJ/u2n8jgoAIYSlCM9784splkZ88X+5Yf0TsrbkeJtr+lQZh57ZtSuo1kaE0zenFMe+CSjb3O2rrrBNWl4vSZCruQoMa69S0mVhhTZtxd+0UuGZabEO8rVHlpJGnyym0XkDfJFABKJk2Xl5ADyWGHhA5NhhACNsK0RjY7tp84sXxSXvZ2iQWzyVl/gDqO9m0xDWB2R4rUPV70kOhL0AqNamhFKhMVWPbUocUhEBgrC8FdcZZ0QcDNnu1lDZBvh38aCV0+S+4mPttLmJtIJLjhuOugqU9MnnCIMHcmcrMWzn2LduEAmzhdm3B6y956w6xAkSV3A== 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=hpcvx1QSuY6/aIXHjmaUDwJPR7CVY++z9EIn9y2TLUQ=; b=VFSEIWA/oWO47YAeSfmlmynaPlHaVETef+6CeB+LEWxu9mYG9UkuKY1/Z9BOhg3QxE3LmBx02tIbeS9D6KvH7JHAqSpnyKFh/OijbpTTR3x5XPZF7QuCSWbaUCcG/pLYgWvXbAeaQUnt52mPVY8IGFbKAzpXGPKBtFd/wK7B5ozjynyMtUqfvxYOUlgR3fFXS/5TjfPrc/Lcwif9XEgxUqLxWeIJRwysEE7dDw95WUnIpoHBesRBE9aRx8XPHNfSF88FKMMsQgU3B5PFeAlydzK1D2VKswm/rH9phajq9Cv/yKI9mxncrHpYOiNWSiI1R0EC58B/1yDTOTRLEz5zyA== 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 AM9P192CA0006.EURP192.PROD.OUTLOOK.COM (2603:10a6:20b:21d::11) by AM7PR08MB5333.eurprd08.prod.outlook.com (2603:10a6:20b:104::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.21; Fri, 19 May 2023 10:25:17 +0000 Received: from AM7EUR03FT056.eop-EUR03.prod.protection.outlook.com (2603:10a6:20b:21d:cafe::28) by AM9P192CA0006.outlook.office365.com (2603:10a6:20b:21d::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.6411.21 via Frontend Transport; Fri, 19 May 2023 10:25:17 +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 AM7EUR03FT056.mail.protection.outlook.com (100.127.140.107) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.6411.19 via Frontend Transport; Fri, 19 May 2023 10:25:16 +0000 Received: from AZ-NEU-EX03.Arm.com (10.251.24.31) by AZ-NEU-EX03.Arm.com (10.251.24.31) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.23; Fri, 19 May 2023 10:25:13 +0000 Received: from e129171.cambridge.arm.com (10.1.37.65) by mail.arm.com (10.251.24.31) with Microsoft SMTP Server id 15.1.2507.23 via Frontend Transport; Fri, 19 May 2023 10:25:13 +0000 To: Subject: [PATCH v2 16/17] [gdb/testsuite] sme: Add SVE/SME testcases Date: Fri, 19 May 2023 11:25:07 +0100 Message-ID: <20230519102508.14020-17-luis.machado@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230519102508.14020-1-luis.machado@arm.com> References: <20230519102508.14020-1-luis.machado@arm.com> MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-TrafficTypeDiagnostic: AM7EUR03FT056:EE_|AM7PR08MB5333:EE_|AM7EUR03FT058:EE_|GV2PR08MB8100:EE_ X-MS-Office365-Filtering-Correlation-Id: d4c2c5bd-8d5d-4a3c-7646-08db58535d3c 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: +Xc5+aJaElrv9f+VYL0LdkUjA1Qw9OXxSzgRmf+Vrx9RuKUeNa+s4YxxBwQwwafVP4nFpbJ7u0eg1O22EGFyXdm230+syAi2BB+gX2Ih0VH/UR9aUoBWBrTvo1ngVtL929X4Jt4Bb43xRfTIqKIeCfCmCKnTYDAd5yVbHeRHtSJN8Oxj3iWvVfaxWuJgpYqwgcleiAar/to68QU1JDo43P+q28Ey6I+EUVtboFvIvHMExn/m3EWyaEaQ7+jmA13CqqdAsFrWQYe8stwWKyJ4lqZTRgSOfbwvZxaXCGztPnJA1SX65m32KyJUsnAQ/jN4kNPwgBj15/BaFiaurbC5qSPgVgzCszBv5rI/fPxkqjJv16Hk1gaut0a2ACA+nZclh/F/AbyZiqcfLkx0iAfXNDJK9z/mwTewc1GUD1n0BOFVhCFtLtIzqgyBGDnDqYPHEvP5YDYTYbLWZmhSMmtiDX4wteyjtnHOFQmTnVRS5EjCCOWgpPfePVzOFvYTx3qY/9tPN/HszryfCOpsSymY2/wDdGg6tx8vtkfVpwlKaEos9A3AwaHl+XO79HJpV/mR+usODarecZTS3SE89AScC2PLolLWvvUnyMjnT4FUGS5tMsOqlkmSLOnl/0WiL4qrwvo2fNcSJsuNscaerynnB0klVaQI3BiHatk0zgi2/WROf28e6189fYVnxIrg1lsQkhVnQl/C/1UADFylLU7ck6JldFzIvrMzvND049amMluzS5hywxI75bSPdhoMvCNj 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:(13230028)(4636009)(39850400004)(346002)(396003)(376002)(136003)(451199021)(46966006)(36840700001)(336012)(426003)(36860700001)(83380400001)(478600001)(26005)(1076003)(2616005)(47076005)(186003)(6666004)(7696005)(82310400005)(316002)(81166007)(8676002)(6916009)(8936002)(86362001)(36756003)(356005)(41300700001)(40480700001)(70206006)(70586007)(82740400003)(2906002)(30864003)(44832011)(5660300002)(2004002)(36900700001)(579004)(559001); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM7PR08MB5333 X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM7EUR03FT058.eop-EUR03.prod.protection.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: eea88605-3dfd-414f-a266-08db58535719 X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: 3HQERkcZOFttfdjfwpcVp3fOjuG44WsfJXyJ8wE6WpnmXrLx4LXakC90cjps70MqzTa1BjiCkBL9IyKdrCBid0ZWiNXbbMhCyxGnBhcQy94Ag2l41ck5ng+t70a/LfIn/zGGxz7QWUkje9XsosV/q19rstHUyd8XX5XkIOIN9A07ccVflHcZRARGxhCUDnYxE6Oi1geMtdr7DRSuryylwU1AePS5e/bVDYsXUq2VcwRkwevRKe3Ijd4oCCSKMovOZS2Ig93v3kh/4B5rUlY0SjTzkKkdKE1rgiHW7W81CdTz0lWl8+nfWS6/YhyPnLg36IkhnncacLNJ1tH9reM+MeDt/tpkDhUsrrmQyynxlsacQfKbexiLD9RfSuwk23btL82NoOMcHSKwdwUdaSGLN7HmBOXRANMmw1wfgoemUWDgEimjR8YTxOSoYFKqpsoatFVkL2slgwT77zRVqALVPB3Q3fNQKokLAqXnxHNO6Uqn+RagzGQwnfkj56YxykEFM7Z7c2q9ejXwigis+HoRX06Ti3ps7WxSW/tY0o/w8OOUZdAdvZ1dElmtY09VgaUTrgvhkYrwdJNRGkxp/fW/ScrzeMob6Mz9PZ0xaPi1fxIDNaIM3NroeIcIlxqXZCkZBSFBogkC0WGzJ9xP2bFx/PRyG8Px6RjzjK2mhbqTuofrQ+Ga8iSWOnB1bVWQCIe0KDx6JEo0OM2KxSI7br+DK/0/0GESbYc+eK8SEGaESsi6e+/0BXmky+DCSl05/96c 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:(13230028)(4636009)(39860400002)(346002)(396003)(136003)(376002)(451199021)(46966006)(36840700001)(40470700004)(478600001)(2906002)(40480700001)(30864003)(7696005)(6666004)(70586007)(70206006)(6916009)(316002)(41300700001)(44832011)(26005)(5660300002)(36860700001)(8936002)(8676002)(1076003)(186003)(40460700003)(81166007)(36756003)(336012)(426003)(2616005)(47076005)(83380400001)(82310400005)(86362001)(82740400003)(2004002)(559001)(579004); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 May 2023 10:25:27.1893 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: d4c2c5bd-8d5d-4a3c-7646-08db58535d3c 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: AM7EUR03FT058.eop-EUR03.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: GV2PR08MB8100 X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_NONE, KAM_SHORT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE, 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.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Luis Machado via Gdb-patches From: Luis Machado Reply-To: Luis Machado Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org Sender: "Gdb-patches" Add 5 SVE/SME tests to exercise all the new features like reading/writing registers, pseudo-registers, signal frames and core files. - Sanity check for SME: Gives a brief smoke test to make sure the most basic of features are working correctly. - ZA unavailability tests: Validates the behavior/content of the ZA register is correct when no payload is available. It also exercises changing the vector lengths. - ZA Availability tests: These tests exercise reading/writing to all the possible ZA pseudo-registers, and validates the state is correct. - Core file tests: Validates that core file reading and writing works correctly and that all state dumped/loaded is sane. This is exercised for both Linux Kernel core files and gcore core files. - Signal frame tests: Validates the correct restoration of SME/SVE/FPSIMD values across signal frames. Since some of these tests are very lengthy and take a little while to run (under QEMU at the moment), I decided to parallelize them into smaller chunks so we can throw some more CPU power at them so they run faster. I'd still like to add a few more tests to give the testsuite more coverage in the areas of SME/SVE. Hopefully in the near future that will happen. Just a reminder that most of these tests will FAIL when running against gdbserver because all of the tests change the vector length mid-execution in some way. Since gdbserver can't communicate the change of state over RSP to GDB, we will always get wrong state from gdbserver. Co-Authored-By: Ezra Sitorus --- gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp | 18 + gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp | 18 + gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp | 18 + gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp | 18 + gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp | 18 + gdb/testsuite/gdb.arch/aarch64-sme-core.c | 361 +++++++++++++++++ .../gdb.arch/aarch64-sme-core.exp.tcl | 167 ++++++++ .../gdb.arch/aarch64-sme-regs-available-0.exp | 18 + .../gdb.arch/aarch64-sme-regs-available-1.exp | 18 + .../gdb.arch/aarch64-sme-regs-available-2.exp | 18 + .../gdb.arch/aarch64-sme-regs-available-3.exp | 18 + .../gdb.arch/aarch64-sme-regs-available-4.exp | 18 + .../gdb.arch/aarch64-sme-regs-available.c | 184 +++++++++ .../aarch64-sme-regs-available.exp.tcl | 194 +++++++++ .../gdb.arch/aarch64-sme-regs-sigframe-0.exp | 18 + .../gdb.arch/aarch64-sme-regs-sigframe-1.exp | 18 + .../gdb.arch/aarch64-sme-regs-sigframe-2.exp | 18 + .../gdb.arch/aarch64-sme-regs-sigframe-3.exp | 18 + .../gdb.arch/aarch64-sme-regs-sigframe-4.exp | 18 + .../gdb.arch/aarch64-sme-regs-sigframe.c | 368 +++++++++++++++++ .../aarch64-sme-regs-sigframe.exp.tcl | 156 ++++++++ .../aarch64-sme-regs-unavailable-0.exp | 18 + .../aarch64-sme-regs-unavailable-1.exp | 18 + .../aarch64-sme-regs-unavailable-2.exp | 18 + .../aarch64-sme-regs-unavailable-3.exp | 18 + .../aarch64-sme-regs-unavailable-4.exp | 18 + .../gdb.arch/aarch64-sme-regs-unavailable.c | 154 ++++++++ .../aarch64-sme-regs-unavailable.exp.tcl | 162 ++++++++ gdb/testsuite/gdb.arch/aarch64-sme-sanity.c | 249 ++++++++++++ gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp | 72 ++++ gdb/testsuite/lib/aarch64.exp | 372 ++++++++++++++++++ gdb/testsuite/lib/gdb.exp | 63 +++ 32 files changed, 2862 insertions(+) create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-sanity.c create mode 100644 gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp create mode 100644 gdb/testsuite/lib/aarch64.exp diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp new file mode 100644 index 00000000000..c4755346bc8 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-0.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 0 +set id_end 24 +source $srcdir/$subdir/aarch64-sme-core.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp new file mode 100644 index 00000000000..6461c47d6b5 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-1.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 25 +set id_end 49 +source $srcdir/$subdir/aarch64-sme-core.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp new file mode 100644 index 00000000000..e5bf5bf2b84 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-2.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 50 +set id_end 74 +source $srcdir/$subdir/aarch64-sme-core.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp new file mode 100644 index 00000000000..1846c83a63c --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-3.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 75 +set id_end 99 +source $srcdir/$subdir/aarch64-sme-core.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp new file mode 100644 index 00000000000..45e69fa8ad5 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core-4.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 100 +set id_end 124 +source $srcdir/$subdir/aarch64-sme-core.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.c b/gdb/testsuite/gdb.arch/aarch64-sme-core.c new file mode 100644 index 00000000000..7d4284b80c8 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.c @@ -0,0 +1,361 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2023 Free Software Foundation, Inc. + + 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 . */ + +/* Exercise AArch64's Scalable Vector/Matrix Extension core file generation + for GDB. This includes reading Linux Kernel-generated core files and + writing GDB core files via the gcore command and making sure the contents + are sane. */ + +#include +#include +#include +#include +#include +#include + +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif + +#ifndef HWCAP2_SME +#define HWCAP2_SME (1 << 23) +#endif + +#ifndef PR_SVE_SET_VL +#define PR_SVE_SET_VL 50 +#define PR_SVE_GET_VL 51 +#define PR_SVE_VL_LEN_MASK 0xffff +#endif + +#ifndef PR_SME_SET_VL +#define PR_SME_SET_VL 63 +#define PR_SME_GET_VL 64 +#define PR_SME_VL_LEN_MASK 0xffff +#endif + +static void +enable_za () +{ + /* smstart za */ + __asm __volatile (".word 0xD503457F"); +} + +static void +disable_za () +{ + /* smstop za */ + __asm __volatile (".word 0xD503447F"); +} + +static void +enable_sm () +{ + /* smstart sm */ + __asm __volatile (".word 0xD503437F"); +} + +static void +disable_sm () +{ + /* smstop sm */ + __asm __volatile (".word 0xD503427F"); +} + +static void +initialize_fpsimd_state () +{ + char buffer[16]; + + for (int i = 0; i < 16; i++) + buffer[i] = 0x55; + + __asm __volatile ("mov x0, %0\n\t" \ + : : "r" (buffer)); + + __asm __volatile ("ldr q0, [x0]"); + __asm __volatile ("ldr q1, [x0]"); + __asm __volatile ("ldr q2, [x0]"); + __asm __volatile ("ldr q3, [x0]"); + __asm __volatile ("ldr q4, [x0]"); + __asm __volatile ("ldr q5, [x0]"); + __asm __volatile ("ldr q6, [x0]"); + __asm __volatile ("ldr q7, [x0]"); + __asm __volatile ("ldr q8, [x0]"); + __asm __volatile ("ldr q9, [x0]"); + __asm __volatile ("ldr q10, [x0]"); + __asm __volatile ("ldr q11, [x0]"); + __asm __volatile ("ldr q12, [x0]"); + __asm __volatile ("ldr q13, [x0]"); + __asm __volatile ("ldr q14, [x0]"); + __asm __volatile ("ldr q15, [x0]"); + __asm __volatile ("ldr q16, [x0]"); + __asm __volatile ("ldr q17, [x0]"); + __asm __volatile ("ldr q18, [x0]"); + __asm __volatile ("ldr q19, [x0]"); + __asm __volatile ("ldr q20, [x0]"); + __asm __volatile ("ldr q21, [x0]"); + __asm __volatile ("ldr q22, [x0]"); + __asm __volatile ("ldr q23, [x0]"); + __asm __volatile ("ldr q24, [x0]"); + __asm __volatile ("ldr q25, [x0]"); + __asm __volatile ("ldr q26, [x0]"); + __asm __volatile ("ldr q27, [x0]"); + __asm __volatile ("ldr q28, [x0]"); + __asm __volatile ("ldr q29, [x0]"); + __asm __volatile ("ldr q30, [x0]"); + __asm __volatile ("ldr q31, [x0]"); +} + +static void +initialize_za_state () +{ + /* zero za */ + __asm __volatile (".word 0xC00800FF"); + + char buffer[256]; + + for (int i = 0; i < 256; i++) + buffer[i] = 0xaa; + + __asm __volatile ("mov x0, %0\n\t" \ + : : "r" (buffer)); + + /* Initialize loop boundaries. */ + __asm __volatile ("mov w12, 0"); + __asm __volatile ("mov w17, 256"); + + /* loop: ldr za[w12, 0], [x0] */ + __asm __volatile ("loop: .word 0xe1000000"); + __asm __volatile ("add w12, w12, 1"); + __asm __volatile ("cmp w12, w17"); + __asm __volatile ("bne loop"); +} + +static void +initialize_sve_state () +{ + __asm __volatile ("dup z0.b, -1"); + __asm __volatile ("dup z1.b, -1"); + __asm __volatile ("dup z2.b, -1"); + __asm __volatile ("dup z3.b, -1"); + __asm __volatile ("dup z4.b, -1"); + __asm __volatile ("dup z5.b, -1"); + __asm __volatile ("dup z6.b, -1"); + __asm __volatile ("dup z7.b, -1"); + __asm __volatile ("dup z8.b, -1"); + __asm __volatile ("dup z9.b, -1"); + __asm __volatile ("dup z10.b, -1"); + __asm __volatile ("dup z11.b, -1"); + __asm __volatile ("dup z12.b, -1"); + __asm __volatile ("dup z13.b, -1"); + __asm __volatile ("dup z14.b, -1"); + __asm __volatile ("dup z15.b, -1"); + __asm __volatile ("dup z16.b, -1"); + __asm __volatile ("dup z17.b, -1"); + __asm __volatile ("dup z18.b, -1"); + __asm __volatile ("dup z19.b, -1"); + __asm __volatile ("dup z20.b, -1"); + __asm __volatile ("dup z21.b, -1"); + __asm __volatile ("dup z22.b, -1"); + __asm __volatile ("dup z23.b, -1"); + __asm __volatile ("dup z24.b, -1"); + __asm __volatile ("dup z25.b, -1"); + __asm __volatile ("dup z26.b, -1"); + __asm __volatile ("dup z27.b, -1"); + __asm __volatile ("dup z28.b, -1"); + __asm __volatile ("dup z29.b, -1"); + __asm __volatile ("dup z30.b, -1"); + __asm __volatile ("dup z31.b, -1"); + __asm __volatile ("ptrue p0.b"); + __asm __volatile ("ptrue p1.b"); + __asm __volatile ("ptrue p2.b"); + __asm __volatile ("ptrue p3.b"); + __asm __volatile ("ptrue p4.b"); + __asm __volatile ("ptrue p5.b"); + __asm __volatile ("ptrue p6.b"); + __asm __volatile ("ptrue p7.b"); + __asm __volatile ("ptrue p8.b"); + __asm __volatile ("ptrue p9.b"); + __asm __volatile ("ptrue p10.b"); + __asm __volatile ("ptrue p11.b"); + __asm __volatile ("ptrue p12.b"); + __asm __volatile ("ptrue p13.b"); + __asm __volatile ("ptrue p14.b"); + __asm __volatile ("ptrue p15.b"); + __asm __volatile ("setffr"); +} + +static int get_vl_size () +{ + int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int get_svl_size () +{ + int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int set_vl_size (int new_vl) +{ + int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_SET_VL (%d)", res); + return -1; + } + + res = get_vl_size (); + if (res != new_vl) + { + printf ("Unexpected VL value (%d)", res); + return -1; + } + + return res; +} + +static int set_svl_size (int new_svl) +{ + int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_SET_VL (%d)", res); + return -1; + } + + res = get_svl_size (); + if (res != new_svl) + { + printf ("Unexpected SVL value (%d)", res); + return -1; + } + + return res; +} + +/* Enable register states based on STATE. + + 0 - FPSIMD + 1 - SVE + 2 - SSVE + 3 - ZA + 4 - ZA and SSVE. */ + +void enable_states (int state) +{ + disable_za (); + disable_sm (); + initialize_fpsimd_state (); + + if (state == 1) + { + initialize_sve_state (); + } + else if (state == 2) + { + enable_sm (); + initialize_sve_state (); + } + else if (state == 3) + { + enable_za (); + initialize_za_state (); + } + else if (state == 4) + { + enable_za (); + enable_sm (); + initialize_sve_state (); + initialize_za_state (); + } + + return; +} + +static int +test_id_to_state (int id) +{ + return id / 25; +} + +static int +test_id_to_vl (int id) +{ + return 16 << ((id / 5) % 5); +} + +static int +test_id_to_svl (int id) +{ + return 16 << (id % 5); +} + +static void +dummy () +{ +} + +int +main (int argc, char **argv) +{ + if (argc > 2) + printf ("Incorrect number of arguments passed to test.\n"); + + if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME) + { + long test_id = 0; + + /* If we have a test id passed as argument, read it now. */ + if (argc == 2) + test_id = strtol (argv[1], NULL, 0); + + dummy (); /* stop to initialize test_id */ + + int state = test_id_to_state (test_id); + int vl = test_id_to_vl (test_id); + int svl = test_id_to_svl (test_id); + + if (set_vl_size (vl) == -1) + return -1; + if (set_svl_size (svl) == -1) + return -1; + + enable_states (state); + + char *p = 0x0; + *p = 0xff; /* crash point */ + } + else + { + printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n"); + return -1; + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl new file mode 100644 index 00000000000..1fc325d4df7 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-core.exp.tcl @@ -0,0 +1,167 @@ +# Copyright (C) 2023 Free Software Foundation, Inc. + +# 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 . +# +# Exercise core file reading/writing in the presence of SME support. +# This test exercises GDB's dumping/loading capability for Linux +# Kernel core files and for gcore core files. + +load_lib aarch64.exp + +# +# Validate that CORE_FILENAME can be read correctly and that the register +# state is sane. +# +proc check_sme_core_file { core_filename state vl svl } { + # Load the core file. + if [gdb_test "core $core_filename" \ + [multi_line \ + "Core was generated by.*\." \ + "Program terminated with signal SIGSEGV, Segmentation fault\." \ + "#0 ${::hex} in main \\(.*\\) at .*" \ + ".*p = 0xff;.* crash point .*"] \ + "load core file"] { + untested "failed to generate core file" + return -1 + } + + check_state $state $vl $svl + + # Check the value of TPIDR2 in the core file. + gdb_test "print/x \$tpidr2" " = 0x1f2f3f4f5f6f7f8f" "tpidr2 contents from core file" +} + +# +# Generate two core files for EXECUTABLE, BINFILE with a test id of ID. +# STATE is the register state, VL is the SVE vector length and SVL is the +# SME vector length. +# One of the core files is generated by the kernel and the other by the +# gcore command. +# +proc generate_sme_core_files { executable binfile id state vl svl} { + # Run the program until the point where we need to adjust the + # test id. + set init_breakpoint "stop to initialize test_id" + gdb_breakpoint [gdb_get_line_number $init_breakpoint] + gdb_continue_to_breakpoint $init_breakpoint + gdb_test_no_output "set test_id = $id" + + # Run the program until just before the crash. + set crash_breakpoint "crash point" + gdb_breakpoint [gdb_get_line_number $crash_breakpoint] + gdb_continue_to_breakpoint $crash_breakpoint + gdb_test_no_output "set print repeats 1" "adjust repeat count pre-crash" + + # Adjust the register to custom values that we will check later when + # loading the core files. + check_state $state $vl $svl + + # Modify tpidr2 so we can validate its value is properly dumped to the + # core files. + gdb_test_no_output "set \$tpidr2 = 0x1f2f3f4f5f6f7f8f" + + # Continue until a crash. + gdb_test "continue" \ + [multi_line \ + "Program received signal SIGSEGV, Segmentation fault\." \ + "${::hex} in main \\(.*\\) at .*" \ + ".*p = 0xff;.* crash point .*"] \ + "run to crash" + + # Generate the gcore core file. + set gcore_filename [standard_output_file "${executable}-${id}-${state}-${vl}-${svl}.gcore"] + set gcore_generated [gdb_gcore_cmd "$gcore_filename" "generate gcore file"] + + # Continue until the end. + gdb_test "continue" "Program terminated with signal SIGSEGV.*" \ + "program terminated with SIGSEGV" + + # Generate a native core file. + set core_filename [core_find ${binfile} {} $id] + set core_generated [expr {$core_filename != ""}] + set native_core_name "${binfile}-${id}-${state}-${vl}-${svl}.core" + remote_exec build "mv $core_filename ${native_core_name}" + set core_filename ${native_core_name} + + # At this point we have a couple core files, the gcore one generated by GDB + # and the native one generated by the Linux Kernel. Make sure GDB can read + # both correctly. + if {$gcore_generated} { + clean_restart ${binfile} + gdb_test_no_output "set print repeats 1" \ + "adjust repeat count post-crash gcore" + + with_test_prefix "gcore corefile" { + check_sme_core_file $gcore_filename $state $vl $svl + } + } else { + fail "gcore corefile not generated" + } + + if {$core_generated} { + clean_restart ${binfile} + + gdb_test_no_output "set print repeats 1" \ + "adjust repeat count post-crash native core" + + with_test_prefix "native corefile" { + check_sme_core_file $core_filename $state $vl $svl + } + } else { + untested "native corefile not generated" + } +} + +# +# Exercise core file reading (kernel-generated core files) and writing +# (gcore command) for test id's ID_START through ID_END. +# +proc test_sme_core_file { id_start id_end } { + set compile_flags {"debug" "macros" "additional_flags=-march=armv8.5-a+sve"} + standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-core.c + set executable "${::testfile}" + if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} { + return -1 + } + set binfile [standard_output_file ${executable}] + + for {set id $id_start} {$id <= $id_end} {incr id} { + set state [test_id_to_state $id] + set vl [test_id_to_vl $id] + set svl [test_id_to_svl $id] + + with_test_prefix "state=${state} vl=${vl} svl=${svl}" { + if ![runto_main] { + untested "could not run to main" + return -1 + } + + generate_sme_core_files ${executable} ${binfile} $id $state $vl $svl + } + } +} + +require is_aarch64_target + +if {![allow_aarch64_sve_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +if {![allow_aarch64_sme_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +test_sme_core_file $id_start $id_end diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp new file mode 100644 index 00000000000..b264170c56a --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-0.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 0 +set id_end 4 +source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp new file mode 100644 index 00000000000..ac48aa905bc --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-1.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 5 +set id_end 9 +source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp new file mode 100644 index 00000000000..0e8f3e311ee --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-2.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 10 +set id_end 14 +source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp new file mode 100644 index 00000000000..fabb24c5aad --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-3.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 14 +set id_end 19 +source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp new file mode 100644 index 00000000000..5abeabb74c4 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available-4.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 20 +set id_end 24 +source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c new file mode 100644 index 00000000000..bf27356908f --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.c @@ -0,0 +1,184 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2023 Free Software Foundation, Inc. + + 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 . */ + +/* Exercise various cases of reading/writing ZA contents for AArch64's + Scalable Matrix Extension. */ + +#include +#include +#include +#include +#include +#include + +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif + +#ifndef HWCAP2_SME +#define HWCAP2_SME (1 << 23) +#endif + +#ifndef PR_SVE_SET_VL +#define PR_SVE_SET_VL 50 +#define PR_SVE_GET_VL 51 +#define PR_SVE_VL_LEN_MASK 0xffff +#endif + +#ifndef PR_SME_SET_VL +#define PR_SME_SET_VL 63 +#define PR_SME_GET_VL 64 +#define PR_SME_VL_LEN_MASK 0xffff +#endif + +static void +enable_za () +{ + /* smstart za */ + __asm __volatile (".word 0xD503457F"); +} + +static void +disable_za () +{ + /* smstop za */ + __asm __volatile (".word 0xD503447F"); +} + +static int get_vl_size () +{ + int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int get_svl_size () +{ + int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int set_vl_size (int new_vl) +{ + int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_SET_VL (%d)", res); + return -1; + } + + res = get_vl_size (); + if (res != new_vl) + { + printf ("Unexpected VL value (%d)", res); + return -1; + } + + return res; +} + +static int set_svl_size (int new_svl) +{ + int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_SET_VL (%d)", res); + return -1; + } + + res = get_svl_size (); + if (res != new_svl) + { + printf ("Unexpected SVL value (%d)", res); + return -1; + } + + return res; +} + +static int +test_id_to_vl (int id) +{ + return 16 << ((id / 5) % 5); +} + +static int +test_id_to_svl (int id) +{ + return 16 << (id % 5); +} + +static void +dummy () +{ +} + +int +main (int argc, char **argv) +{ + if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME) + { + int id_start = ID_START; + int id_end = ID_END; + + for (int id = id_start; id <= id_end; id++) + { + int vl = test_id_to_vl (id); + int svl = test_id_to_svl (id); + + if (set_vl_size (vl) == -1) + return -1; + if (set_svl_size (svl) == -1) + return -1; + + enable_za (); + dummy (); /* stop 1 */ + } + + for (int id = id_start; id <= id_end; id++) + { + int vl = test_id_to_vl (id); + int svl = test_id_to_svl (id); + + /* Make sure the vl/svl is something other than what gdb is about + to set them to. */ + if (set_vl_size (vl == 16? 32 : vl) == -1) + return -1; + if (set_svl_size (svl == 16? 32 : svl) == -1) + return -1; + + disable_za (); + dummy (); /* stop 2 */ + } + } + else + { + printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n"); + return -1; + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl new file mode 100644 index 00000000000..19131819273 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-available.exp.tcl @@ -0,0 +1,194 @@ +# Copyright (C) 2023 Free Software Foundation, Inc. + +# 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 . + +# Exercise reading/writing ZA registers when there is ZA state. + +load_lib aarch64.exp + +# +# Cycle through all ZA registers and pseudo-registers and validate that their +# contents are available for vector length SVL. +# +# Make sure reading/writing to ZA registers work as expected. +# +proc check_regs { mode vl svl } { + # Check VG to make sure it is correct + set expected_vg [expr $vl / 8] + gdb_test "print \$vg" "= ${expected_vg}" + + # Check SVG to make sure it is correct + set expected_svg [expr $svl / 8] + gdb_test "print \$svg" "= ${expected_svg}" + + # If svl is adjusted by prctl, we will have ZA enabled. If gdb is + # adjusting svl, ZA will not be enabled by default. It will only be + # enabled when ZA is written to. + set za_state "= \\\[ ZA \\\]" + if {$mode == "gdb"} { + set za_state "= \\\[ \\\]" + } + + # Check SVCR. + if [gdb_test "print \$svcr" $za_state "svcr before assignments" ] { + fail "incorrect za state" + return -1 + } + + # Check the size of ZA. + set expected_za_size [expr $svl * $svl] + gdb_test "print sizeof \$za" " = $expected_za_size" + + # Check the size of Z0. + gdb_test "print sizeof \$z0" " = $vl" + + # Exercise reading/writing from/to ZA. + initialize_2d_array "\$za" 255 $svl $svl + set pattern [string_to_regexp [2d_array_value_pattern 255 $svl $svl]] + gdb_test "print \$za" " = $pattern" "read back from za" + + # Exercise reading/writing from/to the tile pseudo-registers. + set last_tile 1 + set expected_size [expr $svl * $svl] + set tile_svl $svl + set za_state "= \\\[ ZA \\\]" + foreach_with_prefix granularity {"b" "h" "s" "d" "q"} { + for {set tile 0} {$tile < $last_tile} {incr tile} { + set register_name "\$za${tile}${granularity}" + + # Test the size. + gdb_test "print sizeof ${register_name}" " = ${expected_size}" + + # Test reading/writing + initialize_2d_array $register_name 255 $tile_svl $tile_svl + + # Make sure we have ZA state. + if [gdb_test "print \$svcr" $za_state "svcr after assignment to ${register_name}" ] { + fail "incorrect za state" + return -1 + } + + set pattern [string_to_regexp [2d_array_value_pattern 255 $tile_svl $tile_svl]] + gdb_test "print $register_name" " = $pattern" "read back from $register_name" + } + set last_tile [expr $last_tile * 2] + set expected_size [expr $expected_size / 2] + set tile_svl [expr $tile_svl / 2] + } + + # Exercise reading/writing from/to the tile slice pseudo-registers. + set last_tile 1 + set last_slice $svl + set expected_size $svl + set num_elements $svl + foreach_with_prefix granularity {"b" "h" "s" "d" "q"} { + for {set tile 0} {$tile < $last_tile} {incr tile} { + for {set slice 0} {$slice < $last_slice} {incr slice} { + foreach_with_prefix direction {"h" "v"} { + set register_name "\$za${tile}${direction}${granularity}${slice}" + + # Test the size. + gdb_test "print sizeof ${register_name}" " = ${expected_size}" + + # Test reading/writing + initialize_1d_array $register_name 255 $num_elements + + # Make sure we have ZA state. + if [gdb_test "print \$svcr" $za_state "svcr after assignment of ${register_name}" ] { + fail "incorrect za state" + return -1 + } + + set pattern [string_to_regexp [1d_array_value_pattern 255 $num_elements]] + gdb_test "print $register_name" " = $pattern" "read back from $register_name" + } + } + } + set last_tile [expr $last_tile * 2] + set last_slice [expr ($last_slice / 2)] + set num_elements [expr $num_elements / 2] + } +} + +# +# Cycle through all ZA registers and pseudo-registers and validate their +# contents. +# +proc test_sme_registers_available { id_start id_end } { + + set compile_flags {"debug" "macros"} + lappend compile_flags "additional_flags=-DID_START=${id_start}" + lappend compile_flags "additional_flags=-DID_END=${id_end}" + + standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-regs-available.c + set executable "${::testfile}-${id_start}-${id_end}" + if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} { + return -1 + } + set binfile [standard_output_file ${executable}] + + if ![runto_main] { + untested "could not run to main" + return -1 + } + + gdb_test_no_output "set print repeats 1" + + set prctl_breakpoint "stop 1" + gdb_breakpoint [gdb_get_line_number $prctl_breakpoint] + + for {set id $id_start} {$id <= $id_end} {incr id} { + set vl [test_id_to_vl $id] + set svl [test_id_to_svl $id] + set mode "prctl" + with_test_prefix "$mode, vl=${vl} svl=${svl}" { + # Run the program until it has adjusted svl. + gdb_continue_to_breakpoint $prctl_breakpoint + check_regs $mode $vl $svl + } + } + + set non_prctl_breakpoint "stop 2" + gdb_breakpoint [gdb_get_line_number $non_prctl_breakpoint] + gdb_continue_to_breakpoint $non_prctl_breakpoint + + for {set id $id_start} {$id <= $id_end} {incr id} { + set vl [test_id_to_vl $id] + set svl [test_id_to_svl $id] + set mode "gdb" + with_test_prefix "$mode, vl=${vl} svl=${svl}" { + # Adjust svl via gdb. + set vg_value [expr $vl / 8] + set svg_value [expr $svl / 8] + gdb_test_no_output "set \$vg = ${vg_value}" + gdb_test_no_output "set \$svg = ${svg_value}" + + check_regs $mode $vl $svl + } + } +} + +require is_aarch64_target + +if {![allow_aarch64_sve_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +if {![allow_aarch64_sme_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +test_sme_registers_available $id_start $id_end diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp new file mode 100644 index 00000000000..00b29deed98 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-0.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 0 +set id_end 24 +source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp new file mode 100644 index 00000000000..991efce4f25 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-1.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 25 +set id_end 49 +source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp new file mode 100644 index 00000000000..5bd3cb80861 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-2.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 50 +set id_end 74 +source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp new file mode 100644 index 00000000000..6e9cf9e929b --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-3.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 75 +set id_end 99 +source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp new file mode 100644 index 00000000000..0a9a11c30a2 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe-4.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 100 +set id_end 124 +source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c new file mode 100644 index 00000000000..4d178ec01f6 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.c @@ -0,0 +1,368 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2023 Free Software Foundation, Inc. + + 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 . */ + +/* Exercise AArch64's Scalable Vector/Matrix Extension signal frame handling + for GDB. */ + +#include +#include +#include +#include +#include +#include +#include + +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif + +#ifndef HWCAP2_SME +#define HWCAP2_SME (1 << 23) +#endif + +#ifndef PR_SVE_SET_VL +#define PR_SVE_SET_VL 50 +#define PR_SVE_GET_VL 51 +#define PR_SVE_VL_LEN_MASK 0xffff +#endif + +#ifndef PR_SME_SET_VL +#define PR_SME_SET_VL 63 +#define PR_SME_GET_VL 64 +#define PR_SME_VL_LEN_MASK 0xffff +#endif + +static int count = 0; + +static void +handler (int sig) +{ + count++; /* handler */ +} + +static void +enable_za () +{ + /* smstart za */ + __asm __volatile (".word 0xD503457F"); +} + +static void +disable_za () +{ + /* smstop za */ + __asm __volatile (".word 0xD503447F"); +} + +static void +enable_sm () +{ + /* smstart sm */ + __asm __volatile (".word 0xD503437F"); +} + +static void +disable_sm () +{ + /* smstop sm */ + __asm __volatile (".word 0xD503427F"); +} + +static void +initialize_fpsimd_state () +{ + char buffer[16]; + + for (int i = 0; i < 16; i++) + buffer[i] = 0x55; + + __asm __volatile ("mov x0, %0\n\t" \ + : : "r" (buffer)); + + __asm __volatile ("ldr q0, [x0]"); + __asm __volatile ("ldr q1, [x0]"); + __asm __volatile ("ldr q2, [x0]"); + __asm __volatile ("ldr q3, [x0]"); + __asm __volatile ("ldr q4, [x0]"); + __asm __volatile ("ldr q5, [x0]"); + __asm __volatile ("ldr q6, [x0]"); + __asm __volatile ("ldr q7, [x0]"); + __asm __volatile ("ldr q8, [x0]"); + __asm __volatile ("ldr q9, [x0]"); + __asm __volatile ("ldr q10, [x0]"); + __asm __volatile ("ldr q11, [x0]"); + __asm __volatile ("ldr q12, [x0]"); + __asm __volatile ("ldr q13, [x0]"); + __asm __volatile ("ldr q14, [x0]"); + __asm __volatile ("ldr q15, [x0]"); + __asm __volatile ("ldr q16, [x0]"); + __asm __volatile ("ldr q17, [x0]"); + __asm __volatile ("ldr q18, [x0]"); + __asm __volatile ("ldr q19, [x0]"); + __asm __volatile ("ldr q20, [x0]"); + __asm __volatile ("ldr q21, [x0]"); + __asm __volatile ("ldr q22, [x0]"); + __asm __volatile ("ldr q23, [x0]"); + __asm __volatile ("ldr q24, [x0]"); + __asm __volatile ("ldr q25, [x0]"); + __asm __volatile ("ldr q26, [x0]"); + __asm __volatile ("ldr q27, [x0]"); + __asm __volatile ("ldr q28, [x0]"); + __asm __volatile ("ldr q29, [x0]"); + __asm __volatile ("ldr q30, [x0]"); + __asm __volatile ("ldr q31, [x0]"); +} + +static void +initialize_za_state () +{ + /* zero za */ + __asm __volatile (".word 0xC00800FF"); + + char buffer[256]; + + for (int i = 0; i < 256; i++) + buffer[i] = 0xaa; + + __asm __volatile ("mov x0, %0\n\t" \ + : : "r" (buffer)); + + /* Initialize loop boundaries. */ + __asm __volatile ("mov w12, 0"); + __asm __volatile ("mov w17, 256"); + + /* loop: ldr za[w12, 0], [x0] */ + __asm __volatile ("loop: .word 0xe1000000"); + __asm __volatile ("add w12, w12, 1"); + __asm __volatile ("cmp w12, w17"); + __asm __volatile ("bne loop"); +} + +static void +initialize_sve_state () +{ + __asm __volatile ("dup z0.b, -1"); + __asm __volatile ("dup z1.b, -1"); + __asm __volatile ("dup z2.b, -1"); + __asm __volatile ("dup z3.b, -1"); + __asm __volatile ("dup z4.b, -1"); + __asm __volatile ("dup z5.b, -1"); + __asm __volatile ("dup z6.b, -1"); + __asm __volatile ("dup z7.b, -1"); + __asm __volatile ("dup z8.b, -1"); + __asm __volatile ("dup z9.b, -1"); + __asm __volatile ("dup z10.b, -1"); + __asm __volatile ("dup z11.b, -1"); + __asm __volatile ("dup z12.b, -1"); + __asm __volatile ("dup z13.b, -1"); + __asm __volatile ("dup z14.b, -1"); + __asm __volatile ("dup z15.b, -1"); + __asm __volatile ("dup z16.b, -1"); + __asm __volatile ("dup z17.b, -1"); + __asm __volatile ("dup z18.b, -1"); + __asm __volatile ("dup z19.b, -1"); + __asm __volatile ("dup z20.b, -1"); + __asm __volatile ("dup z21.b, -1"); + __asm __volatile ("dup z22.b, -1"); + __asm __volatile ("dup z23.b, -1"); + __asm __volatile ("dup z24.b, -1"); + __asm __volatile ("dup z25.b, -1"); + __asm __volatile ("dup z26.b, -1"); + __asm __volatile ("dup z27.b, -1"); + __asm __volatile ("dup z28.b, -1"); + __asm __volatile ("dup z29.b, -1"); + __asm __volatile ("dup z30.b, -1"); + __asm __volatile ("dup z31.b, -1"); + __asm __volatile ("ptrue p0.b"); + __asm __volatile ("ptrue p1.b"); + __asm __volatile ("ptrue p2.b"); + __asm __volatile ("ptrue p3.b"); + __asm __volatile ("ptrue p4.b"); + __asm __volatile ("ptrue p5.b"); + __asm __volatile ("ptrue p6.b"); + __asm __volatile ("ptrue p7.b"); + __asm __volatile ("ptrue p8.b"); + __asm __volatile ("ptrue p9.b"); + __asm __volatile ("ptrue p10.b"); + __asm __volatile ("ptrue p11.b"); + __asm __volatile ("ptrue p12.b"); + __asm __volatile ("ptrue p13.b"); + __asm __volatile ("ptrue p14.b"); + __asm __volatile ("ptrue p15.b"); + __asm __volatile ("setffr"); +} + +static int get_vl_size () +{ + int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int get_svl_size () +{ + int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int set_vl_size (int new_vl) +{ + int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_SET_VL (%d)", res); + return -1; + } + + res = get_vl_size (); + if (res != new_vl) + { + printf ("Unexpected VL value (%d)", res); + return -1; + } + + return res; +} + +static int set_svl_size (int new_svl) +{ + int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_SET_VL (%d)", res); + return -1; + } + + res = get_svl_size (); + if (res != new_svl) + { + printf ("Unexpected SVL value (%d)", res); + return -1; + } + + return res; +} + +/* Enable register states based on STATE. + + 0 - FPSIMD + 1 - SVE + 2 - SSVE + 3 - ZA + 4 - ZA and SSVE. */ + +void enable_states (int state) +{ + disable_za (); + disable_sm (); + initialize_fpsimd_state (); + + if (state == 1) + { + initialize_sve_state (); + } + else if (state == 2) + { + enable_sm (); + initialize_sve_state (); + } + else if (state == 3) + { + enable_za (); + initialize_za_state (); + } + else if (state == 4) + { + enable_za (); + enable_sm (); + initialize_sve_state (); + initialize_za_state (); + } + + return; +} + +static int +test_id_to_state (int id) +{ + return (id / 25); +} + +static int +test_id_to_vl (int id) +{ + return 16 << ((id / 5) % 5); +} + +static int +test_id_to_svl (int id) +{ + return 16 << (id % 5); +} + +static void +dummy () +{ +} + +int +main (int argc, char **argv) +{ + if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME) + { + int id_start = ID_START; + int id_end = ID_END; +#ifdef SIGILL + signal (SIGILL, handler); +#endif + + int signal_count = 0; + for (int id = id_start; id <= id_end; id++) + { + int state = test_id_to_state (id); + int vl = test_id_to_vl (id); + int svl = test_id_to_svl (id); + + if (set_vl_size (vl) == -1) + return -1; + if (set_svl_size (svl) == -1) + return -1; + + signal_count++; + enable_states (state); + dummy (); /* stop before SIGILL */ + __asm __volatile (".word 0xDEADBEEF"); /* illegal instruction */ + while (signal_count != count); + } + } + else + { + printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n"); + return -1; + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl new file mode 100644 index 00000000000..4279cdc6d9b --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-sigframe.exp.tcl @@ -0,0 +1,156 @@ +# Copyright (C) 2023 Free Software Foundation, Inc. + +# 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 . + +# Exercise restoring SME/TPIDR2 state from a signal frame. + +load_lib aarch64.exp + +# +# Validate the state of registers in the signal frame for various states. +# +proc test_sme_registers_sigframe { id_start id_end } { + + set compile_flags {"debug" "macros"} + lappend compile_flags "additional_flags=-march=armv8.5-a+sve" + lappend compile_flags "additional_flags=-DID_START=${id_start}" + lappend compile_flags "additional_flags=-DID_END=${id_end}" + + standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-regs-sigframe.c + set executable "${::testfile}-${id_start}-${id_end}" + if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} { + return -1 + } + set binfile [standard_output_file ${executable}] + + if ![runto_main] { + untested "could not run to main" + return -1 + } + + set sigill_breakpoint "stop before SIGILL" + set handler_breakpoint "handler" + gdb_breakpoint [gdb_get_line_number $sigill_breakpoint] + gdb_breakpoint [gdb_get_line_number $handler_breakpoint] + + for {set id $id_start} {$id <= $id_end} {incr id} { + set state [test_id_to_state $id] + set vl [test_id_to_vl $id] + set svl [test_id_to_svl $id] + + with_test_prefix "state=${state} vl=${vl} svl=${svl}" { + + # Run the program until it has adjusted the svl. + if [gdb_continue_to_breakpoint $sigill_breakpoint] { + return -1 + } + + # Check SVG to make sure it is correct + set expected_svg [expr $svl / 8] + gdb_test "print \$svg" "= ${expected_svg}" + + # Check the size of ZA. + set expected_za_size [expr $svl * $svl] + gdb_test "print sizeof \$za" " = $expected_za_size" + + # Check the value of SVCR. + gdb_test "print \$svcr" [get_svcr_value $state] "svcr before signal" + + # Handle SME ZA initialization and state. + set byte 0 + if { $state == "za" || $state == "za_ssve" } { + set byte 170 + } + + # Set the expected ZA pattern. + set za_pattern [string_to_regexp [2d_array_value_pattern $byte $svl $svl]] + + # Handle SVE/SSVE initialization and state. + set sve_vl $svl + if { $state == "ssve" || $state == "za_ssve" } { + # SVE state comes from SSVE. + set sve_vl $svl + } else { + # SVE state comes from regular SVE. + set sve_vl $vl + } + + # Initialize the SVE state. + set sve_pattern [string_to_regexp [sve_value_pattern $state $sve_vl 85 255]] + for {set row 0} {$row < 32} {incr row} { + set register_name "\$z${row}\.b\.u" + gdb_test "print sizeof $register_name" " = $sve_vl" "size of $register_name" + gdb_test "print $register_name" $sve_pattern "read back from $register_name" + } + + # Print ZA to check its value. + gdb_test "print \$za" $za_pattern "read back from za" + + # Test TPIDR2 restore from signal frame as well. + gdb_test_no_output "set \$tpidr2=0x0102030405060708" + + # Run to the illegal instruction. + if [gdb_test "continue" "Continuing\.\r\n\r\nProgram received signal SIGILL, Illegal instruction\..*in main.*"] { + return + } + + # Skip the illegal instruction. The signal handler will be called after we continue. + gdb_test_no_output "set \$pc=\$pc+4" + # Continue to the signal handler. + if [gdb_continue_to_breakpoint $handler_breakpoint] { + return -1 + } + + # Modify TPIDR2 so it is different from its value past the signal + # frame. + gdb_test_no_output "set \$tpidr2 = 0x0" + + # Select the frame that contains "main". + gdb_test "frame 2" "#2.* main \\\(.*\\\) at.*" + + for {set row 0} {$row < 32} {incr row} { + set register_name "\$z${row}\.b\.u" + gdb_test "print sizeof $register_name" " = $sve_vl" "size of $register_name in the signal frame" + gdb_test "print $register_name" $sve_pattern "$register_name contents from signal frame" + } + + # Check the size of ZA in the signal frame. + set expected_za_size [expr $svl * $svl] + gdb_test "print sizeof \$za" " = $expected_za_size" "size of za in signal frame" + + # Check the value of SVCR in the signal frame. + gdb_test "print \$svcr" [get_svcr_value $state] "svcr from signal frame" + + # Check the value of ZA in the signal frame. + gdb_test "print \$za" $za_pattern "za contents from signal frame" + + # Check the value of TPIDR2 in the signal frame. + gdb_test "print/x \$tpidr2" " = 0x102030405060708" "tpidr2 contents from signal frame" + } + } +} + +require is_aarch64_target + +if {![allow_aarch64_sve_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +if {![allow_aarch64_sme_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +test_sme_registers_sigframe $id_start $id_end diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp new file mode 100644 index 00000000000..c758c4862be --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-0.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 0 +set id_end 3 +source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp new file mode 100644 index 00000000000..10e27174067 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-1.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 11 +set id_end 15 +source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp new file mode 100644 index 00000000000..c1e5e279231 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-2.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 16 +set id_end 19 +source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp new file mode 100644 index 00000000000..cbe84dbff9a --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-3.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 20 +set id_end 22 +source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp new file mode 100644 index 00000000000..f6f884cb910 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable-4.exp @@ -0,0 +1,18 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +set id_start 23 +set id_end 24 +source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c new file mode 100644 index 00000000000..2dd72ffd5d4 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.c @@ -0,0 +1,154 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2023 Free Software Foundation, Inc. + + 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 . */ + +/* Exercise various cases of ZA contents not being available for AArch64's + Scalable Matrix Extension. */ + +#include +#include +#include +#include +#include + +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif + +#ifndef HWCAP2_SME +#define HWCAP2_SME (1 << 23) +#endif + +#ifndef PR_SVE_SET_VL +#define PR_SVE_SET_VL 50 +#define PR_SVE_GET_VL 51 +#define PR_SVE_VL_LEN_MASK 0xffff +#endif + +#ifndef PR_SME_SET_VL +#define PR_SME_SET_VL 63 +#define PR_SME_GET_VL 64 +#define PR_SME_VL_LEN_MASK 0xffff +#endif + +static int get_vl_size () +{ + int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int get_svl_size () +{ + int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_GET_VL (%d)", res); + return -1; + } + return (res & PR_SVE_VL_LEN_MASK); +} + +static int set_vl_size (int new_vl) +{ + int res = prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SVE_SET_VL (%d)", res); + return -1; + } + + res = get_vl_size (); + if (res != new_vl) + { + printf ("Unexpected VL value (%d)", res); + return -1; + } + + return res; +} + +static int set_svl_size (int new_svl) +{ + int res = prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0); + if (res < 0) + { + printf ("FAILED to PR_SME_SET_VL (%d)", res); + return -1; + } + + res = get_svl_size (); + if (res != new_svl) + { + printf ("Unexpected SVL value (%d)", res); + return -1; + } + + return res; +} + +static int +test_id_to_vl (int id) +{ + return 16 << ((id / 5) % 5); +} + +static int +test_id_to_svl (int id) +{ + return 16 << (id % 5); +} + +static void +dummy () +{ +} + +int +main (int argc, char **argv) +{ + if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME) + { + int id_start = ID_START; + int id_end = ID_END; + + for (int id = id_start; id <= id_end; id++) + { + int vl = test_id_to_vl (id); + int svl = test_id_to_svl (id); + + if (set_vl_size (vl) == -1) + return -1; + if (set_svl_size (svl) == -1) + return -1; + + dummy (); /* stop 1 */ + } + + dummy (); /* stop 2 */ + } + else + { + printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n"); + return -1; + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl new file mode 100644 index 00000000000..d515fe07b90 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-regs-unavailable.exp.tcl @@ -0,0 +1,162 @@ +# Copyright (C) 2023 Free Software Foundation, Inc. + +# 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 . + +# Exercise the following: +# - Printing ZA registers when there is no ZA state. +# - Setting values of ZA registers when there is no ZA state. +# - Validating ZA state is activated when we write to ZA registers. + +load_lib aarch64.exp + +# +# Validate that the ZA registers have the expected state. +# +proc_with_prefix check_regs { vl svl } { + # Check VG to make sure it is correct + set expected_vg [expr $vl / 8] + gdb_test "print \$vg" "= ${expected_vg}" + + # Check SVG to make sure it is correct + set expected_svg [expr $svl / 8] + gdb_test "print \$svg" "= ${expected_svg}" + + # Make sure there is no SM or ZA state. + if [gdb_test "print \$svcr" "= \\\[ \\\]"] { + fail "incorrect ZA state" + return -1 + } + + # Check the size of ZA. + set expected_za_size [expr $svl * $svl] + gdb_test "print sizeof \$za" " = $expected_za_size" + + # Check the size of Z0. + gdb_test "print sizeof \$z0" " = $vl" + + # Set the expected ZA pattern. + set za_pattern [string_to_regexp [2d_array_value_pattern 0 $svl $svl]] + + # Check ZA. + gdb_test "print \$za" $za_pattern + + # Exercise reading/writing the tile slice pseudo-registers. + set last_tile 1 + set last_slice $svl + set elements $svl + set expected_size $svl + foreach_with_prefix granularity {"b" "h" "s" "d" "q"} { + set pattern [string_to_regexp [1d_array_value_pattern 0 $elements]] + for {set tile 0} {$tile < $last_tile} {incr tile} { + for {set slice 0} {$slice < $last_slice} {incr slice} { + foreach_with_prefix direction {"h" "v"} { + set register_name "\$za${tile}${direction}${granularity}${slice}" + # Test the size. + gdb_test "print sizeof ${register_name}" " = ${expected_size}" + gdb_test "print ${register_name}" $pattern + } + } + } + set last_tile [expr $last_tile * 2] + set last_slice [expr ($last_slice / 2)] + set elements [expr ($elements / 2)] + } + + # Exercise reading/writing the tile pseudo-registers. + set last_tile 1 + set elements $svl + set expected_size [expr $svl * $svl] + foreach_with_prefix granularity {"b" "h" "s" "d" "q"} { + set pattern [string_to_regexp [2d_array_value_pattern 0 $elements $elements]] + for {set tile 0} {$tile < $last_tile} {incr tile} { + set register_name "\$za${tile}${granularity}" + # Test the size. + gdb_test "print sizeof ${register_name}" " = ${expected_size}" + gdb_test "print ${register_name}" $pattern + } + set last_tile [expr $last_tile * 2] + set expected_size [expr $expected_size / 2] + set elements [expr ($elements / 2)] + } +} + +# +# Cycle through all ZA registers and pseudo-registers and validate that their +# contents are unavailable (zeroed out) for vector length SVL. +# +proc test_sme_registers_unavailable { id_start id_end } { + + set compile_flags {"debug" "macros"} + lappend compile_flags "additional_flags=-DID_START=${id_start}" + lappend compile_flags "additional_flags=-DID_END=${id_end}" + + standard_testfile ${::srcdir}/${::subdir}/aarch64-sme-regs-unavailable.c + set executable "${::testfile}-${id_start}-${id_end}" + if {[prepare_for_testing "failed to prepare" ${executable} ${::srcfile} ${compile_flags}]} { + return -1 + } + set binfile [standard_output_file ${executable}] + + if ![runto_main] { + untested "could not run to main" + return -1 + } + + gdb_test_no_output "set print repeats 1" + + set prctl_breakpoint "stop 1" + gdb_breakpoint [gdb_get_line_number $prctl_breakpoint] + + for {set id $id_start} {$id <= $id_end} {incr id} { + set vl [test_id_to_vl $id] + set svl [test_id_to_svl $id] + with_test_prefix "prctl, vl=${vl} svl=${svl}" { + # Run the program until it has adjusted svl. + gdb_continue_to_breakpoint $prctl_breakpoint + check_regs $vl $svl + } + } + + set non_prctl_breakpoint "stop 2" + gdb_breakpoint [gdb_get_line_number $non_prctl_breakpoint] + gdb_continue_to_breakpoint $non_prctl_breakpoint + + for {set id $id_start} {$id <= $id_end} {incr id} { + set vl [test_id_to_vl $id] + set svl [test_id_to_svl $id] + with_test_prefix "non prctl, vl=${vl} svl=${svl}" { + # Adjust vg and svg. + set vg_value [expr $vl / 8] + set svg_value [expr $svl / 8] + gdb_test_no_output "set \$vg = ${vg_value}" + gdb_test_no_output "set \$svg = ${svg_value}" + + check_regs $vl $svl + } + } +} + +require is_aarch64_target + +if {![allow_aarch64_sve_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +if {![allow_aarch64_sme_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +test_sme_registers_unavailable $id_start $id_end diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c new file mode 100644 index 00000000000..694de0626d2 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.c @@ -0,0 +1,249 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2023 Free Software Foundation, Inc. + + 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 . */ + +/* Sanity test to exercise AArch64's Scalable Vector/Matrix Extension basic + functionality. It cycles through different combinations of state and + initializes different register sets. */ + +#include +#include +#include +#include +#include + +#ifndef HWCAP_SVE +#define HWCAP_SVE (1 << 22) +#endif + +#ifndef HWCAP2_SME +#define HWCAP2_SME (1 << 23) +#endif + +static void +enable_za () +{ + /* smstart za */ + __asm __volatile (".word 0xD503457F"); +} + +static void +disable_za () +{ + /* smstop za */ + __asm __volatile (".word 0xD503447F"); +} + +static void +enable_sm () +{ + /* smstart sm */ + __asm __volatile (".word 0xD503437F"); +} + +static void +disable_sm () +{ + /* smstop sm */ + __asm __volatile (".word 0xD503427F"); +} + +static void +initialize_fpsimd_state () +{ + char buffer[16]; + + for (int i = 0; i < 16; i++) + buffer[i] = 0x55; + + __asm __volatile ("mov x0, %0\n\t" \ + : : "r" (buffer)); + + __asm __volatile ("ldr q0, [x0]"); + __asm __volatile ("ldr q1, [x0]"); + __asm __volatile ("ldr q2, [x0]"); + __asm __volatile ("ldr q3, [x0]"); + __asm __volatile ("ldr q4, [x0]"); + __asm __volatile ("ldr q5, [x0]"); + __asm __volatile ("ldr q6, [x0]"); + __asm __volatile ("ldr q7, [x0]"); + __asm __volatile ("ldr q8, [x0]"); + __asm __volatile ("ldr q9, [x0]"); + __asm __volatile ("ldr q10, [x0]"); + __asm __volatile ("ldr q11, [x0]"); + __asm __volatile ("ldr q12, [x0]"); + __asm __volatile ("ldr q13, [x0]"); + __asm __volatile ("ldr q14, [x0]"); + __asm __volatile ("ldr q15, [x0]"); + __asm __volatile ("ldr q16, [x0]"); + __asm __volatile ("ldr q17, [x0]"); + __asm __volatile ("ldr q18, [x0]"); + __asm __volatile ("ldr q19, [x0]"); + __asm __volatile ("ldr q20, [x0]"); + __asm __volatile ("ldr q21, [x0]"); + __asm __volatile ("ldr q22, [x0]"); + __asm __volatile ("ldr q23, [x0]"); + __asm __volatile ("ldr q24, [x0]"); + __asm __volatile ("ldr q25, [x0]"); + __asm __volatile ("ldr q26, [x0]"); + __asm __volatile ("ldr q27, [x0]"); + __asm __volatile ("ldr q28, [x0]"); + __asm __volatile ("ldr q29, [x0]"); + __asm __volatile ("ldr q30, [x0]"); + __asm __volatile ("ldr q31, [x0]"); +} + +static void +initialize_za_state () +{ + /* zero za */ + __asm __volatile (".word 0xC00800FF"); + + char buffer[256]; + + for (int i = 0; i < 256; i++) + buffer[i] = 0xaa; + + __asm __volatile ("mov x0, %0\n\t" \ + : : "r" (buffer)); + + /* Initialize loop boundaries. */ + __asm __volatile ("mov w12, 0"); + __asm __volatile ("mov w17, 256"); + + /* loop: ldr za[w12, 0], [x0] */ + __asm __volatile ("loop: .word 0xe1000000"); + __asm __volatile ("add w12, w12, 1"); + __asm __volatile ("cmp w12, w17"); + __asm __volatile ("bne loop"); +} + +static void +initialize_sve_state () +{ + __asm __volatile ("dup z0.b, -1"); + __asm __volatile ("dup z1.b, -1"); + __asm __volatile ("dup z2.b, -1"); + __asm __volatile ("dup z3.b, -1"); + __asm __volatile ("dup z4.b, -1"); + __asm __volatile ("dup z5.b, -1"); + __asm __volatile ("dup z6.b, -1"); + __asm __volatile ("dup z7.b, -1"); + __asm __volatile ("dup z8.b, -1"); + __asm __volatile ("dup z9.b, -1"); + __asm __volatile ("dup z10.b, -1"); + __asm __volatile ("dup z11.b, -1"); + __asm __volatile ("dup z12.b, -1"); + __asm __volatile ("dup z13.b, -1"); + __asm __volatile ("dup z14.b, -1"); + __asm __volatile ("dup z15.b, -1"); + __asm __volatile ("dup z16.b, -1"); + __asm __volatile ("dup z17.b, -1"); + __asm __volatile ("dup z18.b, -1"); + __asm __volatile ("dup z19.b, -1"); + __asm __volatile ("dup z20.b, -1"); + __asm __volatile ("dup z21.b, -1"); + __asm __volatile ("dup z22.b, -1"); + __asm __volatile ("dup z23.b, -1"); + __asm __volatile ("dup z24.b, -1"); + __asm __volatile ("dup z25.b, -1"); + __asm __volatile ("dup z26.b, -1"); + __asm __volatile ("dup z27.b, -1"); + __asm __volatile ("dup z28.b, -1"); + __asm __volatile ("dup z29.b, -1"); + __asm __volatile ("dup z30.b, -1"); + __asm __volatile ("dup z31.b, -1"); + __asm __volatile ("ptrue p0.b"); + __asm __volatile ("ptrue p1.b"); + __asm __volatile ("ptrue p2.b"); + __asm __volatile ("ptrue p3.b"); + __asm __volatile ("ptrue p4.b"); + __asm __volatile ("ptrue p5.b"); + __asm __volatile ("ptrue p6.b"); + __asm __volatile ("ptrue p7.b"); + __asm __volatile ("ptrue p8.b"); + __asm __volatile ("ptrue p9.b"); + __asm __volatile ("ptrue p10.b"); + __asm __volatile ("ptrue p11.b"); + __asm __volatile ("ptrue p12.b"); + __asm __volatile ("ptrue p13.b"); + __asm __volatile ("ptrue p14.b"); + __asm __volatile ("ptrue p15.b"); + __asm __volatile ("setffr"); +} + +/* Enable register states based on STATE. + + 0 - FPSIMD + 1 - SVE + 2 - SSVE + 3 - ZA + 4 - ZA and SSVE. */ + +void enable_states (int state) +{ + disable_za (); + disable_sm (); + initialize_fpsimd_state (); + + if (state == 1) + { + initialize_sve_state (); + } + else if (state == 2) + { + enable_sm (); + initialize_sve_state (); + } + else if (state == 3) + { + enable_za (); + initialize_za_state (); + } + else if (state == 4) + { + enable_za (); + enable_sm (); + initialize_sve_state (); + initialize_za_state (); + } + + return; +} + +void dummy () +{ +} + +int +main (int argc, char **argv) +{ + if (getauxval (AT_HWCAP) & HWCAP_SVE && getauxval (AT_HWCAP2) & HWCAP2_SME) + { + for (int state = 0; state < 5; state++) + { + enable_states (state); + dummy (); /* stop here */ + } + } + else + { + printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n"); + return -1; + } + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp new file mode 100644 index 00000000000..c96df7543e0 --- /dev/null +++ b/gdb/testsuite/gdb.arch/aarch64-sme-sanity.exp @@ -0,0 +1,72 @@ +# Copyright (C) 2023 Free Software Foundation, Inc. + +# 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 . +# +# Sanity check for AArch64 Scalable Vector/Matrix Extensions functionality. + +load_lib aarch64.exp + +# +# Run a series of basic checks for SVE/SME states. +# +proc sanity_check { vl svl } { + # Run the program until the point where we start initializing the different + # register states. + set state_breakpoint "stop here" + gdb_breakpoint [gdb_get_line_number $state_breakpoint] + + for {set id 0} {$id < 5} {incr id} { + set state [state_id_to_state_string $id] + + with_test_prefix "state=${state} vl=${vl} svl=${svl}" { + gdb_continue_to_breakpoint $state_breakpoint + check_state $state $vl $svl + } + } +} + +require is_aarch64_target + +if {![allow_aarch64_sve_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +if {![allow_aarch64_sme_tests]} { + verbose "Skipping ${gdb_test_file_name}." + return +} + +set compile_flags {"debug" "macros" "additional_flags=-march=armv8.5-a+sve"} +standard_testfile +if {[prepare_for_testing "failed to prepare" ${testfile} ${srcfile} ${compile_flags}]} { + return -1 +} + +if {![runto_main]} { + return -1 +} + +# Adjust the repeat count for the test. +gdb_test_no_output "set print repeats 1" "adjust repeat count" + +# Fetch both the vector length and the streaming vector length the target +# system is using. We do not force any vector lengths and do not change +# it mid-execution. +set vl [expr [get_valueof "" "\$vg" "0" "fetch value of vl"] * 8] +set svl [expr [get_valueof "" "\$svg" "0" "fetch value of svl"] * 8] + +# Now we are at the point where we can start checking state and moving the +# testcase forward. +sanity_check $vl $svl diff --git a/gdb/testsuite/lib/aarch64.exp b/gdb/testsuite/lib/aarch64.exp new file mode 100644 index 00000000000..076964e2028 --- /dev/null +++ b/gdb/testsuite/lib/aarch64.exp @@ -0,0 +1,372 @@ +# Copyright 2023 Free Software Foundation, Inc. + +# 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 . */ + +# Support routines for aarch64-specific tests + +# +# Return a regular expression that matches what gdb would print for a +# 1-dimension vector containing ELEMENTS elements of value BYTE. +# +# The pattern is of the form "{BYTE ". +# +proc 1d_array_value_pattern { byte elements } { + set brace_open "{" + set brace_close "}" + + append data $brace_open $byte + if {$elements > 1} { + append data " " + } + append data $brace_close + + verbose -log "1d_array_value_pattern Pattern string is..." + verbose -log $data + return $data +} + +# +# Return a regular expression that matches what gdb would print for a +# 2-dimension vector containing ROWS rows and COLUMNS columns of elements +# of value BYTE. +# +# The pattern is of the form +# "{{BYTE } }". +# +proc 2d_array_value_pattern { byte rows columns } { + set brace_open "{" + set brace_close "}" + + append data $brace_open [1d_array_value_pattern $byte $columns] + if {$rows > 1} { + append data " " + } + append data $brace_close + + verbose -log "2d_array_value_pattern Pattern string is..." + verbose -log $data + return $data +} + +# +# Return a regular expression that matches what gdb would print for a +# SVE Z register of length VL in state STATE. The Z register should be filled +# with BYTE_SVE and the FPSIMD registers should be filled with BYTE_FPSIMD. +# +# The pattern is of the form +# +# {BYTE_FPSIMD } +# +# or +# +# {BYTE_FPSIMD , 0 } +# +# or +# +# {BYTE_SVE } +# +proc sve_value_pattern { state vl byte_fpsimd byte_sve } { + set brace_open "{" + set brace_close "}" + + append data $brace_open + if { $state == "fpsimd" || $state == "za" } { + if { $vl > 16 } { + set sve_repeat_count [expr $vl - 16] + append data "$byte_fpsimd , 0 " + } else { + append data "$byte_fpsimd " + } + } else { + append data "$byte_sve " + } + append data $brace_close + + verbose -log "sve_value_pattern pattern string is..." + verbose -log $data + return $data +} + +# +# Initialize register NAME, a 1-dimension vector, with ELEMENTS elements +# by setting all elements to BYTE. ELEMENTS is limited at 256 for memory +# usage purposes. +# +# The initialization is of the form "{BYTE, BYTE, BYTE ...}". +# +proc initialize_1d_array { name byte elements } { + set brace_open "{" + set brace_close "}" + + append data $brace_open + + # Build the assignment in a single shot. + for {set element 0} {$element < $elements} {incr element} { + # Construct the initializer by appending elements to it. + append data $byte + + # If this isn't the last element, add a comma. + if {[expr $element + 1] < $elements} { + append data ", " + } + } + append data $brace_close + + verbose -log "initialization string is..." + verbose -log $data + gdb_test_no_output "set $name = $data" "write to $name" +} + +# +# Return an initializer string for a 2-dimension vector with ROWS rows and +# COLUMNS columns, initializing all elements to BYTE for register NAME. +# +# COLUMNS is limited to 256 elements for memory usage purposes. +# +# The initialization is of the form "{{BYTE, BYTE}, ..., {BYTE, BYTE}}}". +# +proc initialize_2d_array { name byte rows columns } { + set brace_open "{" + set brace_close "}" + + if {[expr $rows * $columns] <= 256} { + # Build the assignment in a single shot, as we have a maximum of 256 + # elements. + for {set row 0} {$row < $rows} {incr row} { + append data $brace_open + for {set column 0} {$column < $columns} {incr column} { + # Construct the initializer by appending elements to it. + append data $byte + + # If this isn't the last column, add a comma. + if {[expr $column + 1] < $columns} { + append data ", " + } + } + + append data $brace_close + + # If this isn't the last row, add a comma. + if {[expr $row + 1] < $rows} { + append data "," + } + } + + set data $brace_open$data + set data $data$brace_close + + verbose -log "initialization string is..." + verbose -log $data + gdb_test_no_output "set $name = $data" "write to $name" + } else { + # There are too many elements to initialize (more than 256), so we + # will do the initialization row by row. + for {set row 0} {$row < $rows} {incr row} { + initialize_1d_array "$name\[$row\]" $byte $columns + } + } +} + +# +# Return the SVCR value based STATE. +# +proc get_svcr_value { state } { + if { $state == "ssve" } { + return "= \\\[ SM \\\]" + } elseif { $state == "za" } { + return "= \\\[ ZA \\\]" + } elseif { $state == "za_ssve" } { + return "= \\\[ SM ZA \\\]" + } + + return "= \\\[ \\\]" +} + +# +# Return the state string based on STATE +# +proc state_id_to_state_string { state } { + if {$state == 0} { + return "fpsimd" + } elseif {$state == 1} { + return "sve" + } elseif {$state == 2} { + return "ssve" + } elseif {$state == 3} { + return "za" + } elseif {$state == 4} { + return "za_ssve" + } +} + +# +# Given a test ID, return the string representing the register state. +# The state is one of fpsimd, sve, ssve, za and za_ssve. +# +proc test_id_to_state { id } { + set state [expr $id / 25] + + return [state_id_to_state_string $state] +} + +# +# Given a test ID, return the associated vector length. +# +proc test_id_to_vl { id } { + return [expr 16 << (($id / 5) % 5)] +} + +# +# Given a test ID, return the associated streaming vector length. +# +proc test_id_to_svl { id } { + return [expr 16 << ($id % 5)] +} + +# +# Validate the values of the FPSIMD registers. +# +proc check_fpsimd_regs { byte state vl svl} { + set fpsimd_pattern [string_to_regexp [1d_array_value_pattern $byte 16]] + + for {set number 0} {$number < 32} {incr number} { + set register_name "\$v${number}\.b\.u" + gdb_test "print sizeof $register_name" " = 16" + gdb_test "print $register_name" $fpsimd_pattern + } +} + +# +# Validate the values of the SVE registers. +# +proc check_sve_regs { byte state vl svl } { + + # If streaming mode is enabled, the vector length is the streaming + # vector length. + set z_pattern "" + set z_size 0 + if {$state == "ssve" || $state == "za_ssve"} { + set z_pattern [string_to_regexp [1d_array_value_pattern $byte $svl]] + set z_size $svl + } else { + set z_size $vl + + if {$state == "fpsimd" || $state == "za"} { + # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers + # are zero. + if {$vl == 16} { + set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]] + } else { + set z_repeats [expr $vl - 16] + set z_pattern [string_to_regexp "{$byte , 0 }"] + } + } else { + set z_pattern [string_to_regexp [1d_array_value_pattern $byte $vl]] + } + } + set p_size [expr $z_size / 8] + + # If there is no SVE/SSVE state, the contents of the Z/P/FFR registers + # are zero. + set p_byte $byte + if {$state == "fpsimd" || $state == "za"} { + set p_byte 0 + } + set p_pattern [string_to_regexp [1d_array_value_pattern $p_byte $p_size]] + + for {set number 0} {$number < 32} {incr number} { + set register_name "\$z${number}\.b\.u" + gdb_test "print sizeof $register_name" " = $z_size" + gdb_test "print $register_name" $z_pattern + } + + for {set number 0} {$number < 16} {incr number} { + set register_name "\$p${number}" + gdb_test "print sizeof $register_name" " = $p_size" + gdb_test "print $register_name" $p_pattern + } + + gdb_test "print \$ffr" $p_pattern +} + +# +# Validate the values of the SME registers. +# +proc check_sme_regs { byte state svl } { + # ZA contents are only available when the ZA state is enabled. Otherwise + # the ZA contents are unavailable (zeroed out). + set za_pattern "" + set expected_za_size [expr $svl * $svl] + + if {$state != "za" && $state != "za_ssve"} { + set byte 0 + } + + set za_pattern [string_to_regexp [2d_array_value_pattern $byte $svl $svl]] + + gdb_test "print sizeof \$za" " = $expected_za_size" + gdb_test "print \$za" $za_pattern +} + +# +# With register STATE, vector length VL and streaming vector length SVL, +# run some register state checks to make sure the values are the expected +# ones +# +proc check_state { state vl svl } { + # The FPSIMD registers are initialized with a value of 0x55 (125) + # for each byte. + # + # The SVE registers are initialized with a value of 0xff (255) for each + # byte, including the predicate registers and FFR. + # + # The SME (ZA) register is initialized with a value of 0xaa (252) for + # each byte. + + # Check VG to make sure it is correct + set expected_vg [expr $vl / 8] + # If streaming mode is enabled, then vg is actually svg. + if {$state == "ssve" || $state == "za_ssve"} { + set expected_vg [expr $svl / 8] + } + gdb_test "print \$vg" " = ${expected_vg}" + + # Check SVG to make sure it is correct + set expected_svg [expr $svl / 8] + gdb_test "print \$svg" " = ${expected_svg}" + + # Check the value of SVCR. + gdb_test "print \$svcr" [get_svcr_value $state] + + # When we have any SVE or SSVE state, the FPSIMD registers will have + # the same values as the SVE/SSVE Z registers. + set fpsimd_byte 85 + if {$state == "sve" || $state == "ssve" || $state == "za_ssve"} { + set fpsimd_byte 255 + } + + set sve_byte 255 + if {$state == "fpsimd" || $state == "za"} { + set sve_byte 85 + } + + # Check FPSIMD registers + check_fpsimd_regs $fpsimd_byte $state $vl $svl + # Check SVE registers + check_sve_regs $sve_byte $state $vl $svl + # Check SME registers + check_sme_regs 170 $state $svl +} + + diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index 133d914aff8..7b5c641d0cc 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -4085,6 +4085,69 @@ gdb_caching_proc allow_aarch64_sve_tests {} { return $allow_sve_tests } +# Run a test on the target to see if it supports Aarch64 SME extensions. +# Return 0 if so, 1 if it does not. Note this causes a restart of GDB. + +gdb_caching_proc allow_aarch64_sme_tests {} { + global srcdir subdir gdb_prompt inferior_exited_re + + set me "allow_aarch64_sme_tests" + + if { ![is_aarch64_target]} { + return 0 + } + + set compile_flags "{additional_flags=-march=armv8-a+sme}" + + # Compile a test program containing SVE instructions. + set src { + int main() { + asm volatile ("smstart za"); + return 0; + } + } + if {![gdb_simple_compile $me $src executable $compile_flags]} { + # Try again, but with a raw hex instruction so we don't rely on + # assembler support for SME. + + set compile_flags "{additional_flags=-march=armv8-a}" + + # Compile a test program containing SVE instructions. + set src { + int main() { + asm volatile (".word 0xD503457F"); + return 0; + } + } + + if {![gdb_simple_compile $me $src executable $compile_flags]} { + return 0 + } + } + + # Compilation succeeded so now run it via gdb. + clean_restart $obj + gdb_run_cmd + gdb_expect { + -re ".*Illegal instruction.*${gdb_prompt} $" { + verbose -log "\n$me sme support not detected" + set allow_sme_tests 0 + } + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" { + verbose -log "\n$me: sme support detected" + set allow_sme_tests 1 + } + default { + warning "\n$me: default case taken" + set allow_sme_tests 0 + } + } + gdb_exit + remote_file build delete $obj + + verbose "$me: returning $allow_sme_tests" 2 + return $allow_sme_tests +} # A helper that compiles a test case to see if __int128 is supported. proc gdb_int128_helper {lang} {