sme: Add SVE/SME testcases

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 these SME tests are currently unsupported when gdb is
connected to a remote target.  That's because the RSP doesn't support
communicating changes in vector lenghts mid-execution, so gdb will always
get wrong state from the remote target.

Co-Authored-By: Ezra Sitorus <ezra.sitorus@arm.com>
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
This commit is contained in:
Luis Machado 2022-10-10 13:31:44 +01:00
parent 69bfb2b6d0
commit 16582a51c6
45 changed files with 3778 additions and 0 deletions

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: FPSIMD
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (0 ~ 24) out of 125 tests.
set id_start 0
set id_end 24
source $srcdir/$subdir/aarch64-sme-core.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: SVE
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (25 ~ 49) out of 125 tests.
set id_start 25
set id_end 49
source $srcdir/$subdir/aarch64-sme-core.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: SSVE
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (50 ~ 74) out of 125 tests.
set id_start 50
set id_end 74
source $srcdir/$subdir/aarch64-sme-core.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: ZA only
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (75 ~ 99) out of 125 tests.
set id_start 75
set id_end 99
source $srcdir/$subdir/aarch64-sme-core.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: ZA + SSVE
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (100 ~ 124) out of 125 tests.
set id_start 100
set id_end 124
source $srcdir/$subdir/aarch64-sme-core.exp.tcl

View file

@ -0,0 +1,372 @@
/* 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 <http://www.gnu.org/licenses/>. */
/* 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 <stdio.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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_tpidr2 ()
{
__asm __volatile ("mov x0, #0xffffffffffffffff");
/* Write x0 to tpidr2. */
__asm __volatile (".word 0xd51bd0a0");
}
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)\n", 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)\n", res);
return -1;
}
res = get_vl_size ();
if (res != new_vl)
{
printf ("Unexpected VL value (%d)\n", 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)\n", res);
return -1;
}
res = get_svl_size ();
if (res != new_svl)
{
printf ("Unexpected SVL value (%d)\n", 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 || set_svl_size (svl) == -1)
return -1;
enable_states (state);
/* Also set the TPIDR2 register so we can test dumping its contents
to a core file. */
initialize_tpidr2 ();
char *p = 0x0;
*p = 0xff; /* crash point */
}
else
{
printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
return -1;
}
return 0;
}

View file

@ -0,0 +1,184 @@
# 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 <http://www.gnu.org/licenses/>.
#
# 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-scalable.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" " = 0xffffffffffffffff" \
"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
# 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"]
# 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]
set skip_unsupported 0
if {![aarch64_supports_sve_vl $vl]
|| ![aarch64_supports_sme_svl $svl]} {
# We have a vector length or streaming vector length that
# is not supported by this target. Skip to the next iteration
# since it is no use running tests for an unsupported vector
# length.
if {![aarch64_supports_sve_vl $vl]} {
verbose -log "SVE vector length $vl not supported."
} elseif {![aarch64_supports_sme_svl $svl]} {
verbose -log "SME streaming vector length $svl not supported."
}
verbose -log "Skipping test."
set skip_unsupported 1
}
with_test_prefix "state=${state} vl=${vl} svl=${svl}" {
# If the SVE or SME vector length is not supported, just skip
# these next tests.
if {$skip_unsupported} {
untested "unsupported configuration on target"
continue
}
if ![runto_main] {
untested "could not run to main"
return -1
}
# Check if we are talking to a remote target. If so, bail out,
# as right now remote targets can't communicate vector length (vl
# or svl) changes to gdb via the RSP. When this restriction is
# lifted, we can remove this guard.
if {[gdb_is_target_remote]} {
unsupported "aarch64 sve/sme tests not supported for remote targets"
return -1
}
generate_sme_core_files ${executable} ${binfile} $id $state $vl $svl
}
}
}
require is_aarch64_target
require allow_aarch64_sve_tests
require allow_aarch64_sme_tests
test_sme_core_file $id_start $id_end

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 16
# SVL: 16, 32, 64, 128
# This set covers 4 (0 ~ 3) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 0
set id_end 3
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 16
# SVL: 256
# This set covers 1 (4) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 4
set id_end 4
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 32
# SVL: 16, 32, 64, 128
# This set covers 4 (5 ~ 8) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 5
set id_end 8
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 32
# SVL: 256
# This set covers 1 (9) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 9
set id_end 9
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 64
# SVL: 16, 32, 64, 128
# This set covers 4 (10 ~ 13) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 10
set id_end 13
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 64
# SVL: 256
# This set covers 1 (14) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 14
set id_end 14
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 128
# SVL: 16, 32, 64, 128
# This set covers 4 (15 ~ 18) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 15
set id_end 18
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 128
# SVL: 256
# This set covers 1 (19) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 19
set id_end 19
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 256
# SVL: 16, 32, 64, 128
# This set covers 4 (20 ~ 23) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 20
set id_end 23
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 256
# SVL: 256
# This set covers 1 (24) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 24
set id_end 24
source $srcdir/$subdir/aarch64-sme-regs-available.exp.tcl

View file

@ -0,0 +1,178 @@
/* 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 <http://www.gnu.org/licenses/>. */
/* Exercise various cases of reading/writing ZA contents for AArch64's
Scalable Matrix Extension. */
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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)\n", 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)\n", 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)\n", res);
return -1;
}
res = get_vl_size ();
if (res != new_vl)
{
printf ("Unexpected VL value (%d)\n", 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)\n", res);
return -1;
}
res = get_svl_size ();
if (res != new_svl)
{
printf ("Unexpected SVL value (%d)\n", 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 || set_svl_size (svl) == -1)
continue;
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);
if (set_vl_size (vl) == -1 || set_svl_size (svl) == -1)
continue;
disable_za ();
dummy (); /* stop 2 */
}
}
else
{
printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
return -1;
}
return 0;
}

View file

@ -0,0 +1,245 @@
# 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 <http://www.gnu.org/licenses/>.
# Exercise reading/writing ZA registers when there is ZA state.
load_lib aarch64-scalable.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
}
# Check if we are talking to a remote target. If so, bail out, as right now
# remote targets can't communicate vector length (vl or svl) changes to gdb
# via the RSP. When this restriction is lifted, we can remove this guard.
if {[gdb_is_target_remote]} {
unsupported "aarch64 sve/sme tests not supported for remote targets"
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 skip_unsupported 0
if {![aarch64_supports_sve_vl $vl]
|| ![aarch64_supports_sme_svl $svl]} {
# We have a vector length or streaming vector length that
# is not supported by this target. Skip to the next iteration
# since it is no use running tests for an unsupported vector
# length.
if {![aarch64_supports_sve_vl $vl]} {
verbose -log "SVE vector length $vl not supported."
} elseif {![aarch64_supports_sme_svl $svl]} {
verbose -log "SME streaming vector length $svl not supported."
}
verbose -log "Skipping test."
set skip_unsupported 1
}
set mode "prctl"
with_test_prefix "$mode, vl=${vl} svl=${svl}" {
# If the SVE or SME vector length is not supported, just skip
# these next tests.
if {$skip_unsupported} {
untested "unsupported configuration on target"
continue
}
# 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]
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 skip_unsupported 0
if {![aarch64_supports_sve_vl $vl]
|| ![aarch64_supports_sme_svl $svl]} {
# We have a vector length or streaming vector length that
# is not supported by this target. Skip to the next iteration
# since it is no use running tests for an unsupported vector
# length.
if {![aarch64_supports_sve_vl $vl]} {
verbose -log "SVE vector length $vl not supported."
} elseif {![aarch64_supports_sme_svl $svl]} {
verbose -log "SME streaming vector length $svl not supported."
}
verbose -log "Skipping test."
set skip_unsupported 1
}
set mode "gdb"
with_test_prefix "$mode, vl=${vl} svl=${svl}" {
# If the SVE or SME vector length is not supported, just skip
# these next tests.
if {$skip_unsupported} {
untested "unsupported configuration on target"
continue
}
# Run the program until we stop at the point where gdb should
# adjust the SVE and SME vector lengths.
gdb_continue_to_breakpoint $non_prctl_breakpoint
# 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
require allow_aarch64_sve_tests
require allow_aarch64_sme_tests
test_sme_registers_available $id_start $id_end

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: FPSIMD
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (0 ~ 24) out of 125 tests.
set id_start 0
set id_end 24
source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: SVE
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (25 ~ 49) out of 125 tests.
set id_start 25
set id_end 49
source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: SSVE
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (50 ~ 74) out of 125 tests.
set id_start 50
set id_end 74
source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: ZA only
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (75 ~ 99) out of 125 tests.
set id_start 75
set id_end 99
source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl

View file

@ -0,0 +1,23 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# state: ZA + SSVE
# VL: 16, 32, 64, 128, 256
# SVL: 16, 32, 64, 128, 256
# This set covers 25 (100 ~ 124) out of 125 tests.
set id_start 100
set id_end 124
source $srcdir/$subdir/aarch64-sme-regs-sigframe.exp.tcl

View file

@ -0,0 +1,366 @@
/* 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 <http://www.gnu.org/licenses/>. */
/* Exercise AArch64's Scalable Vector/Matrix Extension signal frame handling
for GDB. */
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#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)\n", 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)\n", 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)\n", res);
return -1;
}
res = get_vl_size ();
if (res != new_vl)
{
printf ("Unexpected VL value (%d)\n", 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)\n", res);
return -1;
}
res = get_svl_size ();
if (res != new_svl)
{
printf ("Unexpected SVL value (%d)\n", 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 || set_svl_size (svl) == -1)
continue;
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;
}

View file

@ -0,0 +1,179 @@
# 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 <http://www.gnu.org/licenses/>.
# Exercise restoring SME/TPIDR2 state from a signal frame.
load_lib aarch64-scalable.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
}
# Check if we are talking to a remote target. If so, bail out, as right now
# remote targets can't communicate vector length (vl or svl) changes to gdb
# via the RSP. When this restriction is lifted, we can remove this guard.
if {[gdb_is_target_remote]} {
unsupported "aarch64 sve/sme tests not supported for remote targets"
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]
set skip_unsupported 0
if {![aarch64_supports_sve_vl $vl]
|| ![aarch64_supports_sme_svl $svl]} {
# We have a vector length or streaming vector length that
# is not supported by this target. Skip to the next iteration
# since it is no use running tests for an unsupported vector
# length.
if {![aarch64_supports_sve_vl $vl]} {
verbose -log "SVE vector length $vl not supported."
} elseif {![aarch64_supports_sme_svl $svl]} {
verbose -log "SME streaming vector length $svl not supported."
}
verbose -log "Skipping test."
set skip_unsupported 1
}
with_test_prefix "state=${state} vl=${vl} svl=${svl}" {
# If the SVE or SME vector length is not supported, just skip
# these next tests.
if {$skip_unsupported} {
untested "unsupported configuration on target"
continue
}
# 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
require allow_aarch64_sve_tests
require allow_aarch64_sme_tests
test_sme_registers_sigframe $id_start $id_end

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 16
# SVL: 16, 32, 64, 128
# This set covers 4 (0 ~ 3) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 0
set id_end 3
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 16
# SVL: 256
# This set covers 1 (4) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 4
set id_end 4
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 32
# SVL: 16, 32, 64, 128
# This set covers 4 (5 ~ 8) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 5
set id_end 8
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 32
# SVL: 256
# This set covers 1 (9) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 9
set id_end 9
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 64
# SVL: 16, 32, 64, 128
# This set covers 4 (10 ~ 13) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 10
set id_end 13
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 64
# SVL: 256
# This set covers 1 (14) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 14
set id_end 14
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 128
# SVL: 16, 32, 64, 128
# This set covers 4 (15 ~ 18) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 15
set id_end 18
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 128
# SVL: 256
# This set covers 1 (19) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 19
set id_end 19
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 256
# SVL: 16, 32, 64, 128
# This set covers 4 (20 ~ 23) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 20
set id_end 23
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,26 @@
# 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 <http://www.gnu.org/licenses/>. */
# Exercise tests with the following parameters:
# VL: 256
# SVL: 256
# This set covers 1 (24) out of 25 tests.
#
# These tests are split this way for parallelization and for performance
# reasons.
#
set id_start 24
set id_end 24
source $srcdir/$subdir/aarch64-sme-regs-unavailable.exp.tcl

View file

@ -0,0 +1,152 @@
/* 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 <http://www.gnu.org/licenses/>. */
/* Exercise various cases of ZA contents not being available for AArch64's
Scalable Matrix Extension. */
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <unistd.h>
#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)\n", 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)\n", 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)\n", res);
return -1;
}
res = get_vl_size ();
if (res != new_vl)
{
printf ("Unexpected VL value (%d)\n", 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)\n", res);
return -1;
}
res = get_svl_size ();
if (res != new_svl)
{
printf ("Unexpected SVL value (%d)\n", 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 || set_svl_size (svl) == -1)
continue;
dummy (); /* stop 1 */
}
dummy (); /* stop 2 */
}
else
{
printf ("SKIP: no HWCAP_SVE or HWCAP2_SME on this system\n");
return -1;
}
return 0;
}

View file

@ -0,0 +1,212 @@
# 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 <http://www.gnu.org/licenses/>.
# 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-scalable.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
}
# Check if we are talking to a remote target. If so, bail out, as right now
# remote targets can't communicate vector length (vl or svl) changes to gdb
# via the RSP. When this restriction is lifted, we can remove this guard.
if {[gdb_is_target_remote]} {
unsupported "aarch64 sve/sme tests not supported for remote targets"
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 skip_unsupported 0
if {![aarch64_supports_sve_vl $vl]
|| ![aarch64_supports_sme_svl $svl]} {
# We have a vector length or streaming vector length that
# is not supported by this target. Skip to the next iteration
# since it is no use running tests for an unsupported vector
# length.
if {![aarch64_supports_sve_vl $vl]} {
verbose -log "SVE vector length $vl not supported."
} elseif {![aarch64_supports_sme_svl $svl]} {
verbose -log "SME streaming vector length $svl not supported."
}
verbose -log "Skipping test."
set skip_unsupported 1
}
with_test_prefix "prctl, vl=${vl} svl=${svl}" {
# If the SVE or SME vector length is not supported, just skip
# these next tests.
if {$skip_unsupported} {
untested "unsupported configuration on target"
continue
}
# 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]
set skip_unsupported 0
if {![aarch64_supports_sve_vl $vl]
|| ![aarch64_supports_sme_svl $svl]} {
# We have a vector length or streaming vector length that
# is not supported by this target. Skip to the next iteration
# since it is no use running tests for an unsupported vector
# length.
if {![aarch64_supports_sve_vl $vl]} {
verbose -log "SVE vector length $vl not supported."
} elseif {![aarch64_supports_sme_svl $svl]} {
verbose -log "SME streaming vector length $svl not supported."
}
verbose -log "Skipping test."
set skip_unsupported 1
}
with_test_prefix "gdb, vl=${vl} svl=${svl}" {
# If the SVE or SME vector length is not supported, just skip
# these next tests.
if {$skip_unsupported} {
untested "unsupported configuration on target"
continue
}
# 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
require allow_aarch64_sve_tests
require allow_aarch64_sme_tests
test_sme_registers_unavailable $id_start $id_end

View file

@ -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 <http://www.gnu.org/licenses/>. */
/* 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 <stdio.h>
#include <sys/auxv.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#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;
}

View file

@ -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 <http://www.gnu.org/licenses/>.
#
# Sanity check for AArch64 Scalable Vector/Matrix Extensions functionality.
load_lib aarch64-scalable.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
require allow_aarch64_sve_tests
require allow_aarch64_sme_tests
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
}
# Check if we are talking to a remote target. If so, bail out, as right now
# remote targets can't communicate vector length (vl or svl) changes to gdb
# via the RSP. When this restriction is lifted, we can remove this guard.
if {[gdb_is_target_remote]} {
unsupported "aarch64 sve/sme tests not supported for remote targets"
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

View file

@ -0,0 +1,237 @@
# 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 <http://www.gnu.org/licenses/>. */
# Support routines for aarch64 scalable extension tests
# Load generic aarch64 test dependencies.
load_lib aarch64.exp
#
# 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 <repeats 16 times>}
#
# or
#
# {BYTE_FPSIMD <repeats 16 times>, 0 <repeats ... times>}
#
# or
#
# {BYTE_SVE <repeats VL times>}
#
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 <repeats 16 times>, 0 <repeats $sve_repeat_count times>"
} else {
append data "$byte_fpsimd <repeats 16 times>"
}
} else {
append data "$byte_sve <repeats $vl times>"
}
append data $brace_close
verbose -log "sve_value_pattern pattern string is..."
verbose -log $data
return $data
}
#
# Return the SVCR value based on STATE.
# SVCR is only available when SME is available.
#
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 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 <repeats 16 times>, 0 <repeats $z_repeats times>}"]
}
} 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 (85)
# 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 (170) 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
}

View file

@ -0,0 +1,90 @@
/* 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 <http://www.gnu.org/licenses/>. */
/* AArch64 SME feature check. This test serves as a way for the GDB testsuite
to verify that a target supports SVE at runtime, and also reports data
about the various supported SME streaming vector lengths. */
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef HWCAP2_SME
#define HWCAP2_SME (1 << 23)
#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_svl_size ()
{
int res = prctl (PR_SME_GET_VL, 0, 0, 0, 0);
if (res < 0)
return -1;
return (res & PR_SME_VL_LEN_MASK);
}
static int set_svl_size (int new_svl)
{
if (prctl (PR_SME_SET_VL, new_svl, 0, 0, 0, 0) < 0)
return -1;
if (get_svl_size () != new_svl)
return -1;
return 0;
}
static void
dummy ()
{
}
#define SVL_MIN 16
#define SVL_MAX 256
#define SVL_INCREMENT_POWER 1
int
main (int argc, char **argv)
{
/* Number of supported SME streaming vector lengths. */
size_t supported_svl_count = 0;
/* Vector containing the various supported SME streaming vector lengths. */
size_t supported_svl[5];
if (getauxval (AT_HWCAP) & HWCAP2_SME)
{
for (int svl = SVL_MIN; svl <= SVL_MAX; svl <<= SVL_INCREMENT_POWER)
{
if (set_svl_size (svl) == 0)
{
supported_svl[supported_svl_count] = svl;
supported_svl_count++;
}
}
}
return 0; /* stop here */
}

View file

@ -0,0 +1,90 @@
/* 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 <http://www.gnu.org/licenses/>. */
/* AArch64 SVE feature check. This test serves as a way for the GDB testsuite
to verify that a target supports SVE at runtime, and also reports data
about the various supported SVE vector lengths. */
#include <stdio.h>
#include <sys/auxv.h>
#include <sys/prctl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#ifndef HWCAP_SVE
#define HWCAP_SVE (1 << 22)
#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
static int get_vl_size ()
{
int res = prctl (PR_SVE_GET_VL, 0, 0, 0, 0);
if (res < 0)
return -1;
return (res & PR_SVE_VL_LEN_MASK);
}
static int set_vl_size (int new_vl)
{
if (prctl (PR_SVE_SET_VL, new_vl, 0, 0, 0, 0) < 0)
return -1;
if (get_vl_size () != new_vl)
return -1;
return 0;
}
static void
dummy ()
{
}
#define VL_MIN 16
#define VL_MAX 256
#define VL_INCREMENT 16
int
main (int argc, char **argv)
{
/* Number of supported SVE vector lengths. */
size_t supported_vl_count = 0;
/* Vector containing the various supported SVE vector lengths. */
size_t supported_vl[16];
if (getauxval (AT_HWCAP) & HWCAP_SVE)
{
for (int vl = VL_MIN; vl <= VL_MAX; vl += VL_INCREMENT)
{
if (set_vl_size (vl) == 0)
{
supported_vl[supported_vl_count] = vl;
supported_vl_count++;
}
}
}
return 0; /* stop here */
}

View file

@ -0,0 +1,153 @@
# 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 <http://www.gnu.org/licenses/>. */
# 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 <repeats ELEMENTS times>".
#
proc 1d_array_value_pattern { byte elements } {
set brace_open "{"
set brace_close "}"
append data $brace_open $byte
if {$elements > 1} {
append data " <repeats $elements times>"
}
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 <repeats COLUMNS times>} <repeats ROWS times>}".
#
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 " <repeats $rows times>"
}
append data $brace_close
verbose -log "2d_array_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
}
}
}
#
# 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
}
}

View file

@ -4152,10 +4152,259 @@ gdb_caching_proc allow_aarch64_sve_tests {} {
gdb_exit
remote_file build delete $obj
# While testing for SVE support, also discover all the supported vector
# length values.
aarch64_initialize_sve_information
verbose "$me: returning $allow_sve_tests" 2
return $allow_sve_tests
}
# Assuming SVE is supported by the target, run some checks to determine all
# the supported vector length values and return an array containing all of those
# values. Since this is a gdb_caching_proc, this proc will only be executed
# once.
#
# To check if a particular SVE vector length is supported, the following code
# can be used. For instance, for vl == 16:
#
# if {[aarch64_supports_sve_vl 16]} {
# verbose -log "SVE vector length 16 is supported."
# }
#
# This procedure should NEVER be called by hand, as it reinitializes the GDB
# session and will derail a test. This should be called automatically as part
# of the SVE support test routine allow_aarch64_sve_tests. Users should
# restrict themselves to calling the helper proc aarch64_supports_sve_vl.
gdb_caching_proc aarch64_initialize_sve_information { } {
global srcdir
set src "${srcdir}/lib/aarch64-test-sve.c"
set test_exec [standard_temp_file "aarch64-test-sve.x"]
set compile_flags "{additional_flags=-march=armv8-a+sve}"
array set supported_vl {}
# Compile the SVE vector length test.
set result [gdb_compile $src $test_exec executable [list debug ${compile_flags} nowarnings]]
if {$result != ""} {
verbose -log "Failed to compile SVE information gathering test."
return [array get supported_vl]
}
clean_restart $test_exec
if {![runto_main]} {
return [array get supported_vl]
}
set stop_breakpoint "stop here"
gdb_breakpoint [gdb_get_line_number $stop_breakpoint $src]
gdb_continue_to_breakpoint $stop_breakpoint
# Go through the data and extract the supported SVE vector lengths.
set vl_count [get_valueof "" "supported_vl_count" "0" \
"fetch value of supported_vl_count"]
verbose -log "Found $vl_count supported SVE vector length values"
for {set vl_index 0} {$vl_index < $vl_count} {incr vl_index} {
set test_vl [get_valueof "" "supported_vl\[$vl_index\]" "0" \
"fetch value of supported_vl\[$vl_index\]"]
# Mark this vector length as supported.
if {$test_vl != 0} {
verbose -log "Found supported SVE vector length $test_vl"
set supported_vl($test_vl) 1
}
}
gdb_exit
verbose -log "Cleaning up"
remote_file build delete $test_exec
verbose -log "Done gathering information about AArch64 SVE vector lengths."
# Return the array containing all of the supported SVE vl values.
return [array get supported_vl]
}
#
# Return 1 if the target supports SVE vl LENGTH
# Return 0 otherwise.
#
proc aarch64_supports_sve_vl { length } {
# Fetch the cached array of supported SVE vl values.
array set supported_vl [aarch64_initialize_sve_information]
# Do we have the global values cached?
if {![info exists supported_vl($length)]} {
verbose -log "Target does not support SVE vl $length"
return 0
}
# The target supports SVE vl LENGTH.
return 1
}
# 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 SME 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 SME 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
# While testing for SME support, also discover all the supported vector
# length values.
aarch64_initialize_sme_information
verbose "$me: returning $allow_sme_tests" 2
return $allow_sme_tests
}
# Assuming SME is supported by the target, run some checks to determine all
# the supported streaming vector length values and return an array containing
# all of those values. Since this is a gdb_caching_proc, this proc will only
# be executed once.
#
# To check if a particular SME streaming vector length is supported, the
# following code can be used. For instance, for svl == 32:
#
# if {[aarch64_supports_sme_svl 32]} {
# verbose -log "SME streaming vector length 32 is supported."
# }
#
# This procedure should NEVER be called by hand, as it reinitializes the GDB
# session and will derail a test. This should be called automatically as part
# of the SME support test routine allow_aarch64_sme_tests. Users should
# restrict themselves to calling the helper proc aarch64_supports_sme_svl.
gdb_caching_proc aarch64_initialize_sme_information { } {
global srcdir
set src "${srcdir}/lib/aarch64-test-sme.c"
set test_exec [standard_temp_file "aarch64-test-sme.x"]
set compile_flags "{additional_flags=-march=armv8-a+sme}"
array set supported_svl {}
# Compile the SME vector length test.
set result [gdb_compile $src $test_exec executable [list debug ${compile_flags} nowarnings]]
if {$result != ""} {
verbose -log "Failed to compile SME information gathering test."
return [array get supported_svl]
}
clean_restart $test_exec
if {![runto_main]} {
return [array get supported_svl]
}
set stop_breakpoint "stop here"
gdb_breakpoint [gdb_get_line_number $stop_breakpoint $src]
gdb_continue_to_breakpoint $stop_breakpoint
# Go through the data and extract the supported SME vector lengths.
set svl_count [get_valueof "" "supported_svl_count" "0" \
"fetch value of supported_svl_count"]
verbose -log "Found $svl_count supported SME vector length values"
for {set svl_index 0} {$svl_index < $svl_count} {incr svl_index} {
set test_svl [get_valueof "" "supported_svl\[$svl_index\]" "0" \
"fetch value of supported_svl\[$svl_index\]"]
# Mark this streaming vector length as supported.
if {$test_svl != 0} {
verbose -log "Found supported SME vector length $test_svl"
set supported_svl($test_svl) 1
}
}
gdb_exit
verbose -log "Cleaning up"
remote_file build delete $test_exec
verbose -log "Done gathering information about AArch64 SME vector lengths."
# Return the array containing all of the supported SME svl values.
return [array get supported_svl]
}
#
# Return 1 if the target supports SME svl LENGTH
# Return 0 otherwise.
#
proc aarch64_supports_sme_svl { length } {
# Fetch the cached array of supported SME svl values.
array set supported_svl [aarch64_initialize_sme_information]
# Do we have the global values cached?
if {![info exists supported_svl($length)]} {
verbose -log "Target does not support SME svl $length"
return 0
}
# The target supports SME svl LENGTH.
return 1
}
# A helper that compiles a test case to see if __int128 is supported.
proc gdb_int128_helper {lang} {