aboutsummaryrefslogtreecommitdiff
path: root/gdb/testsuite/gdb.arch/aarch64-sve-sigunwind.c
blob: c86beaf5dda0e01020dc479c6c7122818c90640d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
/* This testcase is part of GDB, the GNU debugger.

   Copyright 2025 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 unwinding AArch64's SVE registers from a signal frame.   */

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/prctl.h>
#include <unistd.h>

static int second_vl = 0;

static void
initialize_sve_state_main ()
{
  __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.d");
  __asm __volatile ("ptrue p1.d");
  __asm __volatile ("ptrue p2.d");
  __asm __volatile ("ptrue p3.d");
  __asm __volatile ("ptrue p4.d");
  __asm __volatile ("ptrue p5.d");
  __asm __volatile ("ptrue p6.d");
  __asm __volatile ("ptrue p7.d");
  __asm __volatile ("ptrue p8.d");
  __asm __volatile ("ptrue p9.d");
  __asm __volatile ("ptrue p10.d");
  __asm __volatile ("ptrue p11.d");
  __asm __volatile ("ptrue p12.d");
  __asm __volatile ("ptrue p13.d");
  __asm __volatile ("ptrue p14.d");
  __asm __volatile ("ptrue p15.d");
  __asm __volatile ("setffr");
}

static void
initialize_sve_state_sighandler ()
{
  __asm __volatile ("dup z0.b, -2");
  __asm __volatile ("dup z1.b, -2");
  __asm __volatile ("dup z2.b, -2");
  __asm __volatile ("dup z3.b, -2");
  __asm __volatile ("dup z4.b, -2");
  __asm __volatile ("dup z5.b, -2");
  __asm __volatile ("dup z6.b, -2");
  __asm __volatile ("dup z7.b, -2");
  __asm __volatile ("dup z8.b, -2");
  __asm __volatile ("dup z9.b, -2");
  __asm __volatile ("dup z10.b, -2");
  __asm __volatile ("dup z11.b, -2");
  __asm __volatile ("dup z12.b, -2");
  __asm __volatile ("dup z13.b, -2");
  __asm __volatile ("dup z14.b, -2");
  __asm __volatile ("dup z15.b, -2");
  __asm __volatile ("dup z16.b, -2");
  __asm __volatile ("dup z17.b, -2");
  __asm __volatile ("dup z18.b, -2");
  __asm __volatile ("dup z19.b, -2");
  __asm __volatile ("dup z20.b, -2");
  __asm __volatile ("dup z21.b, -2");
  __asm __volatile ("dup z22.b, -2");
  __asm __volatile ("dup z23.b, -2");
  __asm __volatile ("dup z24.b, -2");
  __asm __volatile ("dup z25.b, -2");
  __asm __volatile ("dup z26.b, -2");
  __asm __volatile ("dup z27.b, -2");
  __asm __volatile ("dup z28.b, -2");
  __asm __volatile ("dup z29.b, -2");
  __asm __volatile ("dup z30.b, -2");
  __asm __volatile ("dup z31.b, -2");
  __asm __volatile ("pfalse p0.b");
  __asm __volatile ("pfalse p1.b");
  __asm __volatile ("pfalse p2.b");
  __asm __volatile ("pfalse p3.b");
  __asm __volatile ("pfalse p4.b");
  __asm __volatile ("pfalse p5.b");
  __asm __volatile ("pfalse p6.b");
  __asm __volatile ("pfalse p7.b");
  __asm __volatile ("pfalse p8.b");
  __asm __volatile ("pfalse p9.b");
  __asm __volatile ("pfalse p10.b");
  __asm __volatile ("pfalse p11.b");
  __asm __volatile ("pfalse p12.b");
  __asm __volatile ("pfalse p13.b");
  __asm __volatile ("pfalse p14.b");
  __asm __volatile ("pfalse p15.b");
  __asm __volatile ("setffr");
}

/* Set new value for the SVE vector length.
   Return the value that was set.  */

static int
set_vl (int vl)
{
  int rc;

  rc = prctl (PR_SVE_SET_VL, vl, 0, 0, 0);
  if (rc < 0)
    {
      perror ("FAILED to PR_SVE_SET_VL");
      exit (EXIT_FAILURE);
    }

  return rc & PR_SVE_VL_LEN_MASK;
}

static void
sighandler (int sig, siginfo_t *info, void *ucontext)
{
  /* Set vector length to the second value.  */
  second_vl = set_vl (second_vl);
  initialize_sve_state_sighandler ();
  printf ("sighandler: second_vl = %d\n", second_vl); /* Break here.  */
}

int
main (int argc, char *argv[])
{
  if (argc != 3)
    {
      fprintf (stderr, "Usage: %s <first vl> <second vl>\n", argv[0]);
      return 1;
    }

  int first_vl = atoi (argv[1]);
  second_vl = atoi (argv[2]);

  if (first_vl == 0 || second_vl == 0)
    {
      fprintf (stderr, "Invalid vector length.\n");
      return 1;
    }

  /* Set vector length to the first value.  */
  first_vl = set_vl (first_vl);

  printf ("main: first_vl = %d\n", first_vl);

  unsigned char buf[256];

  /* Use an SVE register to make the kernel start saving the SVE bank.  */
  asm volatile ("mov z0.b, #255\n\t"
		"str z0, %0"
		:
		: "m" (buf)
		: "z0", "memory");

  initialize_sve_state_main ();

  struct sigaction sigact;
  sigact.sa_sigaction = sighandler;
  sigact.sa_flags = SA_SIGINFO;
  sigaction (SIGUSR1, &sigact, NULL);

  kill (getpid (), SIGUSR1);

  return 0;
}