ATLAS Offline Software
Loading...
Searching...
No Matches
arm_helpers.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3*/
10
11
12#if defined(__aarch64__) && defined(__linux)
13
14
15#include "arm_helpers.h"
16#include "CxxUtils/SealDebug.h"
17#include <iterator>
18#include <unistd.h>
19#include <stdio.h>
20#include <asm/sigcontext.h>
21
22namespace {
23
24
25// ESR decoding logic adapted from the linux kernel ---
26// arch/arm64/kernel/traps.c
27// arch/arm64/mm/fault.c
28// arch/arm64/include/asm/esr.h
29
30static constexpr uint32_t ESR_ELx_EC_SHIFT = 26;
31static constexpr uint32_t ESR_ELx_EC_MASK = 0x3Ful << ESR_ELx_EC_SHIFT;
32inline uint32_t ESR_ELx_EC (uint32_t esr) {
33 return (esr & ESR_ELx_EC_MASK) >> ESR_ELx_EC_SHIFT;
34}
35
36static constexpr uint32_t ESR_ELx_IL_SHIFT = 25;
37static constexpr uint32_t ESR_ELx_IL = 1ul << ESR_ELx_IL_SHIFT;
38static constexpr uint32_t ESR_ELx_ISS_MASK = ESR_ELx_IL - 1;
39
40// Shared ISS field definitions for Data/Instruction aborts.
41static constexpr uint32_t ESR_ELx_SET_SHIFT = 11;
42static constexpr uint32_t ESR_ELx_SET_MASK = 3ul << ESR_ELx_SET_SHIFT;
43static constexpr uint32_t ESR_ELx_FnV_SHIFT = 10;
44static constexpr uint32_t ESR_ELx_FnV = 1ul << ESR_ELx_FnV_SHIFT;
45static constexpr uint32_t ESR_ELx_EA_SHIFT = 9;
46static constexpr uint32_t ESR_ELx_EA = 1ul << ESR_ELx_EA_SHIFT;
47static constexpr uint32_t ESR_ELx_S1PTW_SHIFT = 7;
48static constexpr uint32_t ESR_ELx_S1PTW = 1ul << ESR_ELx_S1PTW_SHIFT;
49
50// ISS field definitions for Data Aborts.
51static constexpr uint32_t ESR_ELx_ISV_SHIFT = 24;
52static constexpr uint32_t ESR_ELx_ISV = 1ul << ESR_ELx_ISV_SHIFT;
53static constexpr uint32_t ESR_ELx_SAS_SHIFT = 22;
54static constexpr uint32_t ESR_ELx_SAS = 3ul << ESR_ELx_SAS_SHIFT;
55static constexpr uint32_t ESR_ELx_SSE_SHIFT = 21;
56static constexpr uint32_t ESR_ELx_SSE = 1ul << ESR_ELx_SSE_SHIFT;
57static constexpr uint32_t ESR_ELx_SRT_SHIFT = 16;
58static constexpr uint32_t ESR_ELx_SRT_MASK = 0x1Ful << ESR_ELx_SRT_SHIFT;
59static constexpr uint32_t ESR_ELx_SF_SHIFT = 15;
60static constexpr uint32_t ESR_ELx_SF = 1u << ESR_ELx_SF_SHIFT;
61static constexpr uint32_t ESR_ELx_AR_SHIFT = 14;
62static constexpr uint32_t ESR_ELx_AR = 1u << ESR_ELx_AR_SHIFT;
63static constexpr uint32_t ESR_ELx_CM_SHIFT = 8;
64static constexpr uint32_t ESR_ELx_CM = 1u << ESR_ELx_CM_SHIFT;
65
66// ISS field definitions shared by different classes.
67static constexpr uint32_t ESR_ELx_WNR_SHIFT = 6;
68static constexpr uint32_t ESR_ELx_WNR = 1u << ESR_ELx_WNR_SHIFT;
69
70
71static const char* const esr_class_str[] =
72{
73 "Unknown/Uncategorized", // 0x00: ESR_ELx_EC_UNKNOWN
74 "WFI/WFE", // 0x01: ESR_ELx_EC_WFx
75 "UNRECOGNIZED EC", // 0x02
76 "CP15 MCR/MRC", // 0x03: SR_ELx_EC_CP15_32
77 "CP15 MCRR/MRRC", // 0x04: ESR_ELx_EC_CP15_64
78 "CP14 MCR/MRC", // 0x05: ESR_ELx_EC_CP14_MR
79 "CP14 LDC/STC", // 0x06: ESR_ELx_EC_CP14_LS
80 "ASIMD", // 0x07: ESR_ELx_EC_FP_ASIMD
81 "CP10 MRC/VMRS", // 0x08: ESR_ELx_EC_CP10_ID
82 "UNRECOGNIZED EC", // 0x09
83 "UNRECOGNIZED EC", // 0x0a
84 "UNRECOGNIZED EC", // 0x0b
85 "CP14 MCRR/MRRC", // 0x0c: ESR_ELx_EC_CP14_64
86 "UNRECOGNIZED EC", // 0x0d
87 "PSTATE.IL", // 0x0e: ESR_ELx_EC_ILL
88 "UNRECOGNIZED EC", // 0x0f
89 "UNRECOGNIZED EC", // 0x10
90 "SVC (AArch32)", // 0x11: ESR_ELx_EC_SVC32
91 "HVC (AArch32)", // 0x12: ESR_ELx_EC_HVC32
92 "SMC (AArch32)", // 0x13: ESR_ELx_EC_SMC32
93 "UNRECOGNIZED EC", // 0x14
94 "SVC (AArch64)", // 0x15: ESR_ELx_EC_SVC64
95 "HVC (AArch64)", // 0x16: ESR_ELx_EC_HVC64
96 "SMC (AArch64)", // 0x17: ESR_ELx_EC_SMC64
97 "MSR/MRS (AArch64)", // 0x18: ESR_ELx_EC_SYS64
98 "SVE", // 0x19: ESR_ELx_EC_SVE
99 "UNRECOGNIZED EC", // 0x1a
100 "UNRECOGNIZED EC", // 0x1b
101 "UNRECOGNIZED EC", // 0x1c
102 "UNRECOGNIZED EC", // 0x1d
103 "UNRECOGNIZED EC", // 0x1e
104 "EL3 IMP DEF", // 0x1f: ESR_ELx_EC_IMP_DEF
105 "IABT (lower EL)", // 0x20: ESR_ELx_EC_IABT_LOW
106 "IABT (current EL)", // 0x21: ESR_ELx_EC_IABT_CUR
107 "PC Alignment", // 0x22: ESR_ELx_EC_PC_ALIGN
108 "UNRECOGNIZED EC", // 0x23
109 "DABT (lower EL)", // 0x24: ESR_ELx_EC_DABT_LOW
110 "DABT (current EL)", // 0x25: ESR_ELx_EC_DABT_CUR
111 "SP Alignment", // 0x26: ESR_ELx_EC_SP_ALIGN
112 "UNRECOGNIZED EC", // 0x27
113 "FP (AArch32)", // 0x28: ESR_ELx_EC_FP_EXC32
114 "UNRECOGNIZED EC", // 0x29
115 "UNRECOGNIZED EC", // 0x2a
116 "UNRECOGNIZED EC", // 0x2b
117 "FP (AArch64)", // 0x2c: ESR_ELx_EC_FP_EXC64
118 "UNRECOGNIZED EC", // 0x2d
119 "UNRECOGNIZED EC", // 0x2e
120 "SError", // 0x2f: ESR_ELx_EC_SERROR
121 "Breakpoint (lower EL)", // 0x30: ESR_ELx_EC_BREAKPT_LOW
122 "Breakpoint (current EL)", // 0x31: ESR_ELx_EC_BREAKPT_CUR
123 "Software Step (lower EL)", // 0x32: ESR_ELx_EC_SOFTSTP_LOW
124 "Software Step (current EL)", // 0x33: ESR_ELx_EC_SOFTSTP_CUR
125 "Watchpoint (lower EL)", // 0x34: ESR_ELx_EC_WATCHPT_LOW
126 "Watchpoint (current EL)", // 0x35: ESR_ELx_EC_WATCHPT_CUR
127 "UNRECOGNIZED EC", // 0x36
128 "UNRECOGNIZED EC", // 0x37
129 "BKPT (AArch32)", // 0x38: ESR_ELx_EC_BKPT32
130 "UNRECOGNIZED EC", // 0x39
131 "Vector catch (AArch32)", // 0x3a: ESR_ELx_EC_VECTOR32
132 "UNRECOGNIZED EC", // 0x3b
133 "BRK (AArch64)", // 0x3c: ESR_ELx_EC_BRK64
134};
135
136static constexpr uint32_t ESR_ELx_EC_DABT_LOW = 0x24;
137static constexpr uint32_t ESR_ELx_EC_DABT_CUR = 0x25;
138
139
140
141const char* esr_get_class_string (uint32_t esr)
142{
143 uint32_t code = ESR_ELx_EC(esr);
144 if (code >= std::size (esr_class_str))
145 return esr_class_str[2]; // UNRECOGNIZED EC
146 return esr_class_str[code];
147}
148
149
150inline bool esr_is_data_abort(uint32_t esr)
151{
152 const uint32_t ec = ESR_ELx_EC(esr);
153 return ec == ESR_ELx_EC_DABT_LOW || ec == ESR_ELx_EC_DABT_CUR;
154}
155
156
157void esr_data_abort_decode (IOFD fd,
158 char* buf, unsigned int buf_size,
159 uint32_t esr)
160{
161 if (esr & ESR_ELx_ISV) {
162 MYWRITE (fd, buf, snprintf (buf, buf_size,
163 "\n Access size = %u byte(s)",
164 1u << ((esr & ESR_ELx_SAS) >> ESR_ELx_SAS_SHIFT)));
165 MYWRITE (fd, buf, snprintf (buf, buf_size,
166 "\n SSE = %u, SRT = %u",
167 (esr & ESR_ELx_SSE) >> ESR_ELx_SSE_SHIFT,
168 (esr & ESR_ELx_SRT_MASK) >> ESR_ELx_SRT_SHIFT));
169 MYWRITE (fd, buf, snprintf (buf, buf_size,
170 "\n SF = %u, AR = %u",
171 (esr & ESR_ELx_SF) >> ESR_ELx_SF_SHIFT,
172 (esr & ESR_ELx_AR) >> ESR_ELx_AR_SHIFT));
173 } else {
174 MYWRITE (fd, buf, snprintf (buf, buf_size,
175 "\n ISV = 0, ISS = 0x%08x",
176 esr & ESR_ELx_ISS_MASK));
177 }
178
179 MYWRITE (fd, buf, snprintf (buf, buf_size,
180 "\n CM = %u, WnR = %u",
181 (esr & ESR_ELx_CM) >> ESR_ELx_CM_SHIFT,
182 (esr & ESR_ELx_WNR) >> ESR_ELx_WNR_SHIFT));
183}
184
185
186} // anonymous namespace
187
188
189namespace CxxUtils {
190
191
192void aarch64_dump_fpsimd (IOFD fd,
193 char* buf, unsigned int buf_size,
194 const fpsimd_context& ctx)
195{
196 MYWRITE (fd, buf, snprintf (buf, buf_size,
197 "\n"
198 "\n fpsr: %08x fpcr: %08x",
199 ctx.fpsr, ctx.fpcr));
200 for (int i = 0; i < 32; ++i) {
201 union {
202 __uint128_t u128;
203 uint32_t u32[4];
204 } c;
205 c.u128 = ctx.vregs[i];
206 MYWRITE (fd, buf, snprintf (buf, buf_size,
207 "\n v%d:%s [%08x %08x %08x %08x]",
208 i,
209 i < 10 ? " " : "",
210 c.u32[0], c.u32[1], c.u32[2], c.u32[3]));
211 }
212}
213
214
215void aarch64_dump_esr (IOFD fd,
216 char* buf, unsigned int buf_size,
217 const esr_context& ctx)
218{
219 MYWRITE (fd, buf, snprintf (buf, buf_size,
220 "\n\n Mem abort info --- ESR: %016llx",
221 ctx.esr));
222 MYWRITE (fd, buf, snprintf (buf, buf_size,
223 "\n Exception class = %s, IL = %u bits",
224 esr_get_class_string (ctx.esr),
225 (ctx.esr & ESR_ELx_IL) ? 32 : 16));
226 MYWRITE (fd, buf, snprintf (buf, buf_size,
227 "\n SET = %llu, FnV = %llu",
228 (ctx.esr & ESR_ELx_SET_MASK) >> ESR_ELx_SET_SHIFT,
229 (ctx.esr & ESR_ELx_FnV) >> ESR_ELx_FnV_SHIFT));
230 MYWRITE (fd, buf, snprintf (buf, buf_size,
231 "\n EA = %llu, S1PTW = %llu",
232 (ctx.esr & ESR_ELx_EA) >> ESR_ELx_EA_SHIFT,
233 (ctx.esr & ESR_ELx_S1PTW) >> ESR_ELx_S1PTW_SHIFT));
234
235 if (esr_is_data_abort (ctx.esr)) {
236 esr_data_abort_decode (fd, buf, buf_size, ctx.esr);
237 }
238}
239
240
248void aarch64_dump_registers (IOFD fd,
249 char* buf, unsigned int buf_size,
250 const mcontext_t& mc)
251{
252 MYWRITE (fd, buf, snprintf (buf, buf_size,
253 "\n pc: %016llx pstate: %016llx",
254 mc.pc, mc.pstate));
255 for (int i = 0; i < 30; i += 2) {
256 MYWRITE (fd, buf, snprintf (buf, buf_size,
257 "\n x%d:%s %016llx x%d:%s %016llx",
258 i, i < 10 ? " " : "", mc.regs[i],
259 i+1, i+1 < 10 ? " " : "", mc.regs[i+1]));
260 }
261 MYWRITE (fd, buf, snprintf (buf, buf_size,
262 "\n x30: %016llx sp: %016llx",
263 mc.regs[30], mc.sp));
264
265 int ipos = 0;
266 while (ipos + sizeof(_aarch64_ctx) <= sizeof (mc.__reserved)) {
267 const _aarch64_ctx* ctx = reinterpret_cast<const _aarch64_ctx*> (&mc.__reserved[ipos]);
268 if (ctx->magic == 0 || ipos + ctx->size > sizeof (mc.__reserved)) {
269 break;
270 }
271 if (ctx->magic == FPSIMD_MAGIC) {
272 aarch64_dump_fpsimd (fd, buf, buf_size, *reinterpret_cast<const fpsimd_context*>(ctx));
273 }
274 else if (ctx->magic == ESR_MAGIC) {
275 aarch64_dump_esr (fd, buf, buf_size, *reinterpret_cast<const esr_context*>(ctx));
276 }
277 else if (ctx->magic == EXTRA_MAGIC) {
278 MYWRITE (fd, buf, snprintf (buf, buf_size, "\n\n[extra dump not implemented]\n"));
279 }
280 else if (ctx->magic == SVE_MAGIC) {
281 MYWRITE (fd, buf, snprintf (buf, buf_size, "\n\n[SVE dump not implemented]\n"));
282 }
283 ipos += ctx->size;
284 }
285}
286
287
288} // namespace CxxUtils
289
290
291#endif // __aarch64__ && __linux
int IOFD
Type the system uses for channel descriptors.
Definition SealCommon.h:27
This are the SEAL debug aids, adapted to build in Atlas, after the drop of that project.
#define MYWRITE(fd, data, n)
Definition SealDebug.h:44
setEventNumber uint32_t