9
9
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
10
10
#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
11
11
12
- // LinuxPTraceDefines_arm64sve.h defines essential macros for manipulating
13
- // AArch64 SVE core dump registers. Add guard for aarch64/Linux hosts where
14
- // newer versions of ptrace.h or sigcontext.h might already define SVE macros.
15
- #ifndef SVE_SIG_REGS_OFFSET
16
-
17
12
#include < stdint.h>
18
13
19
- struct aarch64_context {
20
- uint16_t magic;
21
- uint16_t size;
22
- };
23
-
24
- #define SVE_MAGIC 0x53564501
25
-
26
- struct sve_context {
27
- struct aarch64_context head;
28
- uint16_t vl;
29
- uint16_t reserved[3 ];
30
- };
14
+ namespace lldb_private {
15
+ namespace sve {
31
16
32
17
/*
33
18
* The SVE architecture leaves space for future expansion of the
34
19
* vector length beyond its initial architectural limit of 2048 bits
35
20
* (16 quadwords).
36
21
*
37
- * See linux /Documentation/arm64/sve.txt for a description of the VL/VQ
38
- * terminology.
22
+ * See <Linux kernel source tree> /Documentation/arm64/sve.rst for a description
23
+ * of the vl/vq terminology.
39
24
*/
40
- #define SVE_VQ_BYTES 16 /* number of bytes per quadword */
41
25
42
- #define SVE_VQ_MIN 1
43
- #define SVE_VQ_MAX 512
26
+ const uint16_t vq_bytes = 16 ; /* number of bytes per quadword */
27
+
28
+ const uint16_t vq_min = 1 ;
29
+ const uint16_t vq_max = 512 ;
30
+
31
+ const uint16_t vl_min = vq_min * vq_bytes;
32
+ const uint16_t vl_max = vq_max * vq_bytes;
44
33
45
- # define SVE_VL_MIN (SVE_VQ_MIN * SVE_VQ_BYTES)
46
- # define SVE_VL_MAX (SVE_VQ_MAX * SVE_VQ_BYTES)
34
+ const uint16_t num_of_zregs = 32 ;
35
+ const uint16_t num_of_pregs = 16 ;
47
36
48
- #define SVE_NUM_ZREGS 32
49
- #define SVE_NUM_PREGS 16
37
+ inline uint16_t vl_valid (uint16_t vl) {
38
+ return (vl % vq_bytes == 0 && vl >= vl_min && vl <= vl_max);
39
+ }
50
40
51
- #define sve_vl_valid (vl ) \
52
- ((vl) % SVE_VQ_BYTES == 0 && (vl) >= SVE_VL_MIN && (vl) <= SVE_VL_MAX)
53
- #define sve_vq_from_vl (vl ) ((vl) / SVE_VQ_BYTES)
54
- #define sve_vl_from_vq (vq ) ((vq)*SVE_VQ_BYTES)
41
+ inline uint16_t vq_from_vl (uint16_t vl) { return vl / vq_bytes; }
42
+ inline uint16_t vl_from_vq (uint16_t vq) { return vq * vq_bytes; }
43
+
44
+ /* A new signal frame record sve_context encodes the SVE Registers on signal
45
+ * delivery. sve_context struct definition may be included in asm/sigcontext.h.
46
+ * We define sve_context_size which will be used by LLDB sve helper functions.
47
+ * More information on sve_context can be found in Linux kernel source tree at
48
+ * Documentation/arm64/sve.rst.
49
+ */
50
+
51
+ const uint16_t sve_context_size = 16 ;
55
52
56
53
/*
57
54
* If the SVE registers are currently live for the thread at signal delivery,
58
55
* sve_context.head.size >=
59
- * SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl (sve_context.vl))
60
- * and the register data may be accessed using the SVE_SIG_ *() macros .
56
+ * SigContextSize(vq_from_vl (sve_context.vl))
57
+ * and the register data may be accessed using the Sig *() functions .
61
58
*
62
59
* If sve_context.head.size <
63
- * SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl (sve_context.vl)),
60
+ * SigContextSize(vq_from_vl (sve_context.vl)),
64
61
* the SVE registers were not live for the thread and no register data
65
- * is included: in this case, the SVE_SIG_ *() macros should not be
62
+ * is included: in this case, the Sig *() functions should not be
66
63
* used except for this check.
67
64
*
68
65
* The same convention applies when returning from a signal: a caller
@@ -76,63 +73,75 @@ struct sve_context {
76
73
* doing a sigreturn.
77
74
*
78
75
*
79
- * Note: for all these macros , the "vq" argument denotes the SVE
76
+ * Note: for all these functions , the "vq" argument denotes the SVE
80
77
* vector length in quadwords (i.e., units of 128 bits).
81
78
*
82
- * The correct way to obtain vq is to use sve_vq_from_vl (vl). The
83
- * result is valid if and only if sve_vl_valid (vl) is true. This is
79
+ * The correct way to obtain vq is to use vq_from_vl (vl). The
80
+ * result is valid if and only if vl_valid (vl) is true. This is
84
81
* guaranteed for a struct sve_context written by the kernel.
85
82
*
86
83
*
87
- * Additional macros describe the contents and layout of the payload.
88
- * For each, SVE_SIG_x_OFFSET (args) is the start offset relative to
89
- * the start of struct sve_context, and SVE_SIG_x_SIZE (args) is the
84
+ * Additional functions describe the contents and layout of the payload.
85
+ * For each, Sig*Offset (args) is the start offset relative to
86
+ * the start of struct sve_context, and Sig*Size (args) is the
90
87
* size in bytes:
91
88
*
92
89
* x type description
93
90
* - ---- -----------
94
91
* REGS the entire SVE context
95
92
*
96
- * ZREGS __uint128_t[SVE_NUM_ZREGS ][vq] all Z-registers
93
+ * ZREGS __uint128_t[num_of_zregs ][vq] all Z-registers
97
94
* ZREG __uint128_t[vq] individual Z-register Zn
98
95
*
99
- * PREGS uint16_t[SVE_NUM_PREGS ][vq] all P-registers
96
+ * PREGS uint16_t[num_of_pregs ][vq] all P-registers
100
97
* PREG uint16_t[vq] individual P-register Pn
101
98
*
102
99
* FFR uint16_t[vq] first-fault status register
103
100
*
104
101
* Additional data might be appended in the future.
105
102
*/
106
103
107
- #define SVE_SIG_ZREG_SIZE (vq ) ((uint32_t )(vq)*SVE_VQ_BYTES)
108
- #define SVE_SIG_PREG_SIZE (vq ) ((uint32_t )(vq) * (SVE_VQ_BYTES / 8 ))
109
- #define SVE_SIG_FFR_SIZE (vq ) SVE_SIG_PREG_SIZE(vq)
104
+ inline uint16_t SigZRegSize (uint16_t vq) { return vq * vq_bytes; }
105
+ inline uint16_t SigPRegSize (uint16_t vq) { return vq * vq_bytes / 8 ; }
106
+ inline uint16_t SigFFRSize (uint16_t vq) { return SigPRegSize (vq); }
107
+
108
+ inline uint32_t SigRegsOffset () {
109
+ return (sve_context_size + vq_bytes - 1 ) / vq_bytes * vq_bytes;
110
+ }
111
+
112
+ inline uint32_t SigZRegsOffset () { return SigRegsOffset (); }
113
+
114
+ inline uint32_t SigZRegOffset (uint16_t vq, uint16_t n) {
115
+ return SigRegsOffset () + SigZRegSize (vq) * n;
116
+ }
110
117
111
- # define SVE_SIG_REGS_OFFSET \
112
- (( sizeof ( struct sve_context ) + (SVE_VQ_BYTES - 1 )) / SVE_VQ_BYTES * \
113
- SVE_VQ_BYTES)
118
+ inline uint32_t SigZRegsSize ( uint16_t vq) {
119
+ return SigZRegOffset (vq, num_of_zregs) - SigRegsOffset ();
120
+ }
114
121
115
- #define SVE_SIG_ZREGS_OFFSET SVE_SIG_REGS_OFFSET
116
- #define SVE_SIG_ZREG_OFFSET (vq, n ) \
117
- (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREG_SIZE(vq) * (n))
118
- #define SVE_SIG_ZREGS_SIZE (vq ) \
119
- (SVE_SIG_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_SIG_ZREGS_OFFSET)
122
+ inline uint32_t SigPRegsOffset (uint16_t vq) {
123
+ return SigRegsOffset () + SigZRegsSize (vq);
124
+ }
120
125
121
- #define SVE_SIG_PREGS_OFFSET (vq ) (SVE_SIG_ZREGS_OFFSET + SVE_SIG_ZREGS_SIZE(vq))
122
- #define SVE_SIG_PREG_OFFSET (vq, n ) \
123
- (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREG_SIZE(vq) * (n))
124
- #define SVE_SIG_PREGS_SIZE (vq ) \
125
- (SVE_SIG_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_SIG_PREGS_OFFSET(vq))
126
+ inline uint32_t SigPRegOffset (uint16_t vq, uint16_t n) {
127
+ return SigPRegsOffset (vq) + SigPRegSize (vq) * n;
128
+ }
126
129
127
- #define SVE_SIG_FFR_OFFSET (vq ) \
128
- (SVE_SIG_PREGS_OFFSET(vq) + SVE_SIG_PREGS_SIZE(vq))
130
+ inline uint32_t SigpRegsSize (uint16_t vq) {
131
+ return SigPRegOffset (vq, num_of_pregs) - SigPRegsOffset (vq);
132
+ }
129
133
130
- #define SVE_SIG_REGS_SIZE (vq ) \
131
- (SVE_SIG_FFR_OFFSET(vq) + SVE_SIG_FFR_SIZE(vq) - SVE_SIG_REGS_OFFSET)
134
+ inline uint32_t SigFFROffset (uint16_t vq) {
135
+ return SigPRegsOffset (vq) + SigpRegsSize (vq);
136
+ }
132
137
133
- #define SVE_SIG_CONTEXT_SIZE (vq ) (SVE_SIG_REGS_OFFSET + SVE_SIG_REGS_SIZE(vq))
138
+ inline uint32_t SigRegsSize (uint16_t vq) {
139
+ return SigFFROffset (vq) + SigFFRSize (vq) - SigRegsOffset ();
140
+ }
134
141
135
- /* SVE/FP/SIMD state (NT_ARM_SVE) */
142
+ inline uint32_t SVESigContextSize (uint16_t vq) {
143
+ return SigRegsOffset () + SigRegsSize (vq);
144
+ }
136
145
137
146
struct user_sve_header {
138
147
uint32_t size; /* total meaningful regset content in bytes */
@@ -144,61 +153,54 @@ struct user_sve_header {
144
153
};
145
154
146
155
/* Definitions for user_sve_header.flags: */
147
- #define SVE_PT_REGS_MASK (1 << 0 )
148
-
149
- #define SVE_PT_REGS_FPSIMD 0
150
- #define SVE_PT_REGS_SVE SVE_PT_REGS_MASK
151
-
152
- /*
153
- * Common SVE_PT_* flags:
154
- * These must be kept in sync with prctl interface in <linux/ptrace.h>
155
- */
156
- #define SVE_PT_VL_INHERIT (PR_SVE_VL_INHERIT >> 16 )
157
- #define SVE_PT_VL_ONEXEC (PR_SVE_SET_VL_ONEXEC >> 16 )
156
+ const uint16_t ptrace_regs_mask = 1 << 0 ;
157
+ const uint16_t ptrace_regs_fpsimd = 0 ;
158
+ const uint16_t ptrace_regs_sve = ptrace_regs_mask;
158
159
159
160
/*
160
161
* The remainder of the SVE state follows struct user_sve_header. The
161
162
* total size of the SVE state (including header) depends on the
162
- * metadata in the header: SVE_PT_SIZE (vq, flags) gives the total size
163
+ * metadata in the header: PTraceSize (vq, flags) gives the total size
163
164
* of the state in bytes, including the header.
164
165
*
165
166
* Refer to <asm/sigcontext.h> for details of how to pass the correct
166
167
* "vq" argument to these macros.
167
168
*/
168
169
169
170
/* Offset from the start of struct user_sve_header to the register data */
170
- # define SVE_PT_REGS_OFFSET \
171
- (( sizeof (struct sve_context ) + (SVE_VQ_BYTES - 1 )) / SVE_VQ_BYTES * \
172
- SVE_VQ_BYTES)
171
+ inline uint16_t PTraceRegsOffset () {
172
+ return ( sizeof (struct user_sve_header ) + vq_bytes - 1 ) / vq_bytes * vq_bytes;
173
+ }
173
174
174
175
/*
175
176
* The register data content and layout depends on the value of the
176
177
* flags field.
177
178
*/
178
179
179
180
/*
180
- * (flags & SVE_PT_REGS_MASK ) == SVE_PT_REGS_FPSIMD case:
181
+ * (flags & ptrace_regs_mask ) == ptrace_regs_fpsimd case:
181
182
*
182
- * The payload starts at offset SVE_PT_FPSIMD_OFFSET , and is of type
183
+ * The payload starts at offset PTraceFPSIMDOffset , and is of type
183
184
* struct user_fpsimd_state. Additional data might be appended in the
184
- * future: use SVE_PT_FPSIMD_SIZE (vq, flags) to compute the total size.
185
- * SVE_PT_FPSIMD_SIZE (vq, flags) will never be less than
185
+ * future: use PTraceFPSIMDSize (vq, flags) to compute the total size.
186
+ * PTraceFPSIMDSize (vq, flags) will never be less than
186
187
* sizeof(struct user_fpsimd_state).
187
188
*/
188
189
189
- # define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET
190
+ const uint32_t ptrace_fpsimd_offset = PTraceRegsOffset();
190
191
191
- #define SVE_PT_FPSIMD_SIZE (vq, flags ) (sizeof (struct user_fpsimd_state ))
192
+ /* Return size of struct user_fpsimd_state from asm/ptrace.h */
193
+ inline uint32_t PTraceFPSIMDSize (uint16_t vq, uint16_t flags) { return 528 ; }
192
194
193
195
/*
194
- * (flags & SVE_PT_REGS_MASK ) == SVE_PT_REGS_SVE case:
196
+ * (flags & ptrace_regs_mask ) == ptrace_regs_sve case:
195
197
*
196
- * The payload starts at offset SVE_PT_SVE_OFFSET , and is of size
197
- * SVE_PT_SVE_SIZE (vq, flags).
198
+ * The payload starts at offset PTraceSVEOffset , and is of size
199
+ * PTraceSVESize (vq, flags).
198
200
*
199
- * Additional macros describe the contents and layout of the payload.
200
- * For each, SVE_PT_SVE_x_OFFSET (args) is the start offset relative to
201
- * the start of struct user_sve_header, and SVE_PT_SVE_x_SIZE (args) is
201
+ * Additional functions describe the contents and layout of the payload.
202
+ * For each, PTrace*X*Offset (args) is the start offset relative to
203
+ * the start of struct user_sve_header, and PTrace*X*Size (args) is
202
204
* the size in bytes:
203
205
*
204
206
* x type description
@@ -215,53 +217,75 @@ struct user_sve_header {
215
217
* Additional data might be appended in the future.
216
218
*/
217
219
218
- #define SVE_PT_SVE_ZREG_SIZE (vq ) SVE_SIG_ZREG_SIZE(vq)
219
- #define SVE_PT_SVE_PREG_SIZE (vq ) SVE_SIG_PREG_SIZE(vq)
220
- #define SVE_PT_SVE_FFR_SIZE (vq ) SVE_SIG_FFR_SIZE(vq)
221
- #define SVE_PT_SVE_FPSR_SIZE sizeof (uint32_t )
222
- #define SVE_PT_SVE_FPCR_SIZE sizeof (uint32_t )
220
+ inline uint32_t PTraceZRegSize (uint16_t vq) { return SigZRegSize (vq); }
221
+
222
+ inline uint32_t PTracePRegSize (uint16_t vq) { return SigPRegSize (vq); }
223
+
224
+ inline uint32_t PTraceFFRSize (uint16_t vq) { return SigFFRSize (vq); }
225
+
226
+ const uint32_t fpsr_size = sizeof (uint32_t );
227
+ const uint32_t fpcr_size = sizeof (uint32_t );
228
+
229
+ inline uint32_t SigToPTrace (uint32_t offset) {
230
+ return offset - SigRegsOffset () + PTraceRegsOffset ();
231
+ }
232
+
233
+ const uint32_t ptrace_sve_offset = PTraceRegsOffset();
234
+
235
+ inline uint32_t PTraceZRegsOffset (uint16_t vq) {
236
+ return SigToPTrace (SigZRegsOffset ());
237
+ }
238
+
239
+ inline uint32_t PTraceZRegOffset (uint16_t vq, uint16_t n) {
240
+ return SigToPTrace (SigZRegOffset (vq, n));
241
+ }
242
+
243
+ inline uint32_t PTraceZRegsSize (uint16_t vq) {
244
+ return PTraceZRegOffset (vq, num_of_zregs) - SigToPTrace (SigRegsOffset ());
245
+ }
223
246
224
- #define __SVE_SIG_TO_PT (offset ) \
225
- ((offset)-SVE_SIG_REGS_OFFSET + SVE_PT_REGS_OFFSET)
247
+ inline uint32_t PTracePRegsOffset (uint16_t vq) {
248
+ return SigToPTrace (SigPRegsOffset (vq));
249
+ }
226
250
227
- #define SVE_PT_SVE_OFFSET SVE_PT_REGS_OFFSET
251
+ inline uint32_t PTracePRegOffset (uint16_t vq, uint16_t n) {
252
+ return SigToPTrace (SigPRegOffset (vq, n));
253
+ }
228
254
229
- #define SVE_PT_SVE_ZREGS_OFFSET __SVE_SIG_TO_PT (SVE_SIG_ZREGS_OFFSET)
230
- #define SVE_PT_SVE_ZREG_OFFSET (vq, n ) \
231
- __SVE_SIG_TO_PT (SVE_SIG_ZREG_OFFSET(vq, n))
232
- #define SVE_PT_SVE_ZREGS_SIZE (vq ) \
233
- (SVE_PT_SVE_ZREG_OFFSET(vq, SVE_NUM_ZREGS) - SVE_PT_SVE_ZREGS_OFFSET)
255
+ inline uint32_t PTracePRegsSize (uint16_t vq) {
256
+ return PTracePRegOffset (vq, num_of_pregs) - PTracePRegsOffset (vq);
257
+ }
234
258
235
- #define SVE_PT_SVE_PREGS_OFFSET (vq ) __SVE_SIG_TO_PT(SVE_SIG_PREGS_OFFSET(vq))
236
- #define SVE_PT_SVE_PREG_OFFSET (vq, n ) \
237
- __SVE_SIG_TO_PT (SVE_SIG_PREG_OFFSET(vq, n))
238
- #define SVE_PT_SVE_PREGS_SIZE (vq ) \
239
- (SVE_PT_SVE_PREG_OFFSET(vq, SVE_NUM_PREGS) - SVE_PT_SVE_PREGS_OFFSET(vq))
259
+ inline uint32_t PTraceFFROffset (uint16_t vq) {
260
+ return SigToPTrace (SigFFROffset (vq));
261
+ }
240
262
241
- #define SVE_PT_SVE_FFR_OFFSET (vq ) __SVE_SIG_TO_PT(SVE_SIG_FFR_OFFSET(vq))
263
+ inline uint32_t PTraceFPSROffset (uint16_t vq) {
264
+ return (PTraceFFROffset (vq) + PTraceFFRSize (vq) + (vq_bytes - 1 )) / vq_bytes *
265
+ vq_bytes;
266
+ }
242
267
243
- #define SVE_PT_SVE_FPSR_OFFSET (vq ) \
244
- ((SVE_PT_SVE_FFR_OFFSET(vq) + SVE_PT_SVE_FFR_SIZE(vq) + \
245
- (SVE_VQ_BYTES - 1 )) / \
246
- SVE_VQ_BYTES * SVE_VQ_BYTES)
247
- #define SVE_PT_SVE_FPCR_OFFSET (vq ) \
248
- (SVE_PT_SVE_FPSR_OFFSET(vq) + SVE_PT_SVE_FPSR_SIZE)
268
+ inline uint32_t PTraceFPCROffset (uint16_t vq) {
269
+ return PTraceFPSROffset (vq) + fpsr_size;
270
+ }
249
271
250
272
/*
251
273
* Any future extension appended after FPCR must be aligned to the next
252
274
* 128-bit boundary.
253
275
*/
254
276
255
- # define SVE_PT_SVE_SIZE ( vq, flags ) \
256
- ((SVE_PT_SVE_FPCR_OFFSET( vq) + SVE_PT_SVE_FPCR_SIZE - SVE_PT_SVE_OFFSET + \
257
- (SVE_VQ_BYTES - 1 )) / \
258
- SVE_VQ_BYTES * SVE_VQ_BYTES)
277
+ inline uint32_t PTraceSVESize ( uint16_t vq, uint16_t flags) {
278
+ return ( PTraceFPCROffset ( vq) + fpcr_size - ptrace_sve_offset + vq_bytes - 1 ) /
279
+ vq_bytes * vq_bytes;
280
+ }
259
281
260
- #define SVE_PT_SIZE (vq, flags ) \
261
- (((flags)&SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE \
262
- ? SVE_PT_SVE_OFFSET + SVE_PT_SVE_SIZE(vq, flags) \
263
- : SVE_PT_FPSIMD_OFFSET + SVE_PT_FPSIMD_SIZE(vq, flags))
282
+ inline uint32_t PTraceSize (uint16_t vq, uint16_t flags) {
283
+ return (flags & ptrace_regs_mask) == ptrace_regs_sve
284
+ ? ptrace_sve_offset + PTraceSVESize (vq, flags)
285
+ : ptrace_fpsimd_offset + PTraceFPSIMDSize (vq, flags);
286
+ }
264
287
265
- #endif // SVE_SIG_REGS_OFFSET
288
+ } // namespace SVE
289
+ } // namespace lldb_private
266
290
267
291
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
0 commit comments