Skip to content

Commit 090306f

Browse files
committed
Convert SVE macros into c++ constants and inlines
This patch updates LLDB's in house version of SVE ptrace/sig macros by converting them into constants and inlines. They are housed under sve namespace and are used by process elf-core for reading SVE register data. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D85641
1 parent 5b797eb commit 090306f

File tree

2 files changed

+162
-136
lines changed

2 files changed

+162
-136
lines changed

lldb/source/Plugins/Process/Utility/LinuxPTraceDefines_arm64sve.h

Lines changed: 149 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -9,60 +9,57 @@
99
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
1010
#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H
1111

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-
1712
#include <stdint.h>
1813

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 {
3116

3217
/*
3318
* The SVE architecture leaves space for future expansion of the
3419
* vector length beyond its initial architectural limit of 2048 bits
3520
* (16 quadwords).
3621
*
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.
3924
*/
40-
#define SVE_VQ_BYTES 16 /* number of bytes per quadword */
4125

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;
4433

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;
4736

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+
}
5040

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;
5552

5653
/*
5754
* If the SVE registers are currently live for the thread at signal delivery,
5855
* 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.
6158
*
6259
* 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)),
6461
* 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
6663
* used except for this check.
6764
*
6865
* The same convention applies when returning from a signal: a caller
@@ -76,63 +73,75 @@ struct sve_context {
7673
* doing a sigreturn.
7774
*
7875
*
79-
* Note: for all these macros, the "vq" argument denotes the SVE
76+
* Note: for all these functions, the "vq" argument denotes the SVE
8077
* vector length in quadwords (i.e., units of 128 bits).
8178
*
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
8481
* guaranteed for a struct sve_context written by the kernel.
8582
*
8683
*
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
9087
* size in bytes:
9188
*
9289
* x type description
9390
* - ---- -----------
9491
* REGS the entire SVE context
9592
*
96-
* ZREGS __uint128_t[SVE_NUM_ZREGS][vq] all Z-registers
93+
* ZREGS __uint128_t[num_of_zregs][vq] all Z-registers
9794
* ZREG __uint128_t[vq] individual Z-register Zn
9895
*
99-
* PREGS uint16_t[SVE_NUM_PREGS][vq] all P-registers
96+
* PREGS uint16_t[num_of_pregs][vq] all P-registers
10097
* PREG uint16_t[vq] individual P-register Pn
10198
*
10299
* FFR uint16_t[vq] first-fault status register
103100
*
104101
* Additional data might be appended in the future.
105102
*/
106103

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+
}
110117

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+
}
114121

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+
}
120125

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+
}
126129

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+
}
129133

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+
}
132137

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+
}
134141

135-
/* SVE/FP/SIMD state (NT_ARM_SVE) */
142+
inline uint32_t SVESigContextSize(uint16_t vq) {
143+
return SigRegsOffset() + SigRegsSize(vq);
144+
}
136145

137146
struct user_sve_header {
138147
uint32_t size; /* total meaningful regset content in bytes */
@@ -144,61 +153,54 @@ struct user_sve_header {
144153
};
145154

146155
/* 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;
158159

159160
/*
160161
* The remainder of the SVE state follows struct user_sve_header. The
161162
* 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
163164
* of the state in bytes, including the header.
164165
*
165166
* Refer to <asm/sigcontext.h> for details of how to pass the correct
166167
* "vq" argument to these macros.
167168
*/
168169

169170
/* 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+
}
173174

174175
/*
175176
* The register data content and layout depends on the value of the
176177
* flags field.
177178
*/
178179

179180
/*
180-
* (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_FPSIMD case:
181+
* (flags & ptrace_regs_mask) == ptrace_regs_fpsimd case:
181182
*
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
183184
* 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
186187
* sizeof(struct user_fpsimd_state).
187188
*/
188189

189-
#define SVE_PT_FPSIMD_OFFSET SVE_PT_REGS_OFFSET
190+
const uint32_t ptrace_fpsimd_offset = PTraceRegsOffset();
190191

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; }
192194

193195
/*
194-
* (flags & SVE_PT_REGS_MASK) == SVE_PT_REGS_SVE case:
196+
* (flags & ptrace_regs_mask) == ptrace_regs_sve case:
195197
*
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).
198200
*
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
202204
* the size in bytes:
203205
*
204206
* x type description
@@ -215,53 +217,75 @@ struct user_sve_header {
215217
* Additional data might be appended in the future.
216218
*/
217219

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+
}
223246

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+
}
226250

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+
}
228254

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+
}
234258

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+
}
240262

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+
}
242267

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+
}
249271

250272
/*
251273
* Any future extension appended after FPCR must be aligned to the next
252274
* 128-bit boundary.
253275
*/
254276

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+
}
259281

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+
}
264287

265-
#endif // SVE_SIG_REGS_OFFSET
288+
} // namespace SVE
289+
} // namespace lldb_private
266290

267291
#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_LINUXPTRACEDEFINES_ARM64SVE_H

0 commit comments

Comments
 (0)