1 // SPDX-License-Identifier: GPL-2.0-only OR MIT 2 /* 3 * Apple RTKit IPC library 4 * Copyright (C) The Asahi Linux Contributors 5 */ 6 #include "rtkit-internal.h" 7 8 #define FOURCC(a, b, c, d) \ 9 (((u32)(a) << 24) | ((u32)(b) << 16) | ((u32)(c) << 8) | ((u32)(d))) 10 11 #define APPLE_RTKIT_CRASHLOG_HEADER FOURCC('C', 'L', 'H', 'E') 12 #define APPLE_RTKIT_CRASHLOG_STR FOURCC('C', 's', 't', 'r') 13 #define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r') 14 #define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x') 15 #define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm') 16 #define APPLE_RTKIT_CRASHLOG_AARCH32 FOURCC('C', 'r', 'g', 'A') 17 #define APPLE_RTKIT_CRASHLOG_AARCH64 FOURCC('C', 'r', 'g', '8') 18 19 /* For COMPILE_TEST on non-ARM64 architectures */ 20 #ifndef PSR_MODE_EL0t 21 #define PSR_MODE_EL0t 0x00000000 22 #define PSR_MODE_EL1t 0x00000004 23 #define PSR_MODE_EL1h 0x00000005 24 #define PSR_MODE_EL2t 0x00000008 25 #define PSR_MODE_EL2h 0x00000009 26 #define PSR_MODE_MASK 0x0000000f 27 #endif 28 29 /* 30 * AArch32 mode definitions: APPLE_RTKIT depends on APPLE_MAILBOX, which 31 * depends on 64BIT, so there is no need to care about COMPILE_TEST on ARM. 32 */ 33 #define USR_MODE 0x00000010 34 #define FIQ_MODE 0x00000011 35 #define IRQ_MODE 0x00000012 36 #define SVC_MODE 0x00000013 37 #define MON_MODE 0x00000016 38 #define ABT_MODE 0x00000017 39 #define HYP_MODE 0x0000001a 40 #define UND_MODE 0x0000001b 41 #define SYSTEM_MODE 0x0000001f 42 #define MODE_MASK_32 0x0000001f 43 44 struct apple_rtkit_crashlog_header { 45 u32 fourcc; 46 u32 version; 47 u32 size; 48 u32 flags; 49 u8 _unk[16]; 50 }; 51 static_assert(sizeof(struct apple_rtkit_crashlog_header) == 0x20); 52 53 struct apple_rtkit_crashlog_mbox_entry { 54 u64 msg0; 55 u64 msg1; 56 u32 timestamp; 57 u8 _unk[4]; 58 }; 59 static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18); 60 61 struct apple_rtkit_crashlog_aarch64 { 62 u32 unk_0; 63 u32 unk_4; 64 u64 regs[31]; 65 u64 sp; 66 u64 pc; 67 u64 psr; 68 u64 cpacr; 69 u64 fpsr; 70 u64 fpcr; 71 u64 unk[64]; 72 u64 far; 73 u64 unk_X; 74 u64 esr; 75 u64 unk_Z; 76 } __packed; 77 static_assert(sizeof(struct apple_rtkit_crashlog_aarch64) == 0x350); 78 79 struct apple_rtkit_crashlog_aarch32 { 80 u32 unk_0; 81 u32 unk_4; 82 u32 regs[16]; 83 u32 psr; 84 u32 unk_x1; 85 u8 stack[0x100]; 86 u32 unk_x2; 87 u32 unk_x3; 88 u32 unk_x4; 89 u32 unk_x5; 90 } __packed; 91 static_assert(sizeof(struct apple_rtkit_crashlog_aarch32) == 0x160); 92 93 static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr, 94 size_t size) 95 { 96 u32 idx; 97 u8 *ptr, *end; 98 99 memcpy(&idx, bfr, 4); 100 101 ptr = bfr + 4; 102 end = bfr + size; 103 while (ptr < end) { 104 u8 *newline = memchr(ptr, '\n', end - ptr); 105 106 if (newline) { 107 u8 tmp = *newline; 108 *newline = '\0'; 109 dev_warn(rtk->dev, "RTKit: Message (id=%x): %s\n", idx, 110 ptr); 111 *newline = tmp; 112 ptr = newline + 1; 113 } else { 114 dev_warn(rtk->dev, "RTKit: Message (id=%x): %s", idx, 115 ptr); 116 break; 117 } 118 } 119 } 120 121 static void apple_rtkit_crashlog_dump_version(struct apple_rtkit *rtk, u8 *bfr, 122 size_t size) 123 { 124 dev_warn(rtk->dev, "RTKit: Version: %s", bfr + 16); 125 } 126 127 static void apple_rtkit_crashlog_dump_time(struct apple_rtkit *rtk, u8 *bfr, 128 size_t size) 129 { 130 u64 crash_time; 131 132 memcpy(&crash_time, bfr, 8); 133 dev_warn(rtk->dev, "RTKit: Crash time: %lld", crash_time); 134 } 135 136 static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr, 137 size_t size) 138 { 139 u32 type, index, i; 140 size_t n_messages; 141 struct apple_rtkit_crashlog_mbox_entry entry; 142 143 memcpy(&type, bfr + 16, 4); 144 memcpy(&index, bfr + 24, 4); 145 n_messages = (size - 28) / sizeof(entry); 146 147 dev_warn(rtk->dev, "RTKit: Mailbox history (type = %d, index = %d)", 148 type, index); 149 for (i = 0; i < n_messages; ++i) { 150 memcpy(&entry, bfr + 28 + i * sizeof(entry), sizeof(entry)); 151 dev_warn(rtk->dev, "RTKit: #%03d@%08x: %016llx %016llx", i, 152 entry.timestamp, entry.msg0, entry.msg1); 153 } 154 } 155 156 static void apple_rtkit_crashlog_dump_aarch32(struct apple_rtkit *rtk, u8 *bfr, 157 size_t size) 158 { 159 struct apple_rtkit_crashlog_aarch32 *state; 160 const char *mode; 161 int i; 162 163 if (size < sizeof(*state)) { 164 dev_warn(rtk->dev, "RTKit: AArch32 section too small: 0x%zx", size); 165 return; 166 } 167 168 state = (struct apple_rtkit_crashlog_aarch32 *)bfr; 169 170 switch (state->psr & MODE_MASK_32) { 171 case USR_MODE: 172 mode = "User"; 173 break; 174 case FIQ_MODE: 175 mode = "FIQ"; 176 break; 177 case IRQ_MODE: 178 mode = "IRQ"; 179 break; 180 case SVC_MODE: 181 mode = "Supervisor"; 182 break; 183 case MON_MODE: 184 mode = "Monitor"; 185 break; 186 case ABT_MODE: 187 mode = "Abort"; 188 break; 189 case HYP_MODE: 190 mode = "Hypervisor"; 191 break; 192 case UND_MODE: 193 mode = "Undefined"; 194 break; 195 case SYSTEM_MODE: 196 mode = "System"; 197 break; 198 default: 199 mode = "Unknown"; 200 break; 201 } 202 203 dev_warn(rtk->dev, "RTKit: Exception dump:"); 204 dev_warn(rtk->dev, " == Exception taken from %s mode ==", mode); 205 dev_warn(rtk->dev, " PSR = 0x%x", state->psr); 206 dev_warn(rtk->dev, "\n"); 207 208 for (i = 0; i < 16; i += 4) 209 dev_warn(rtk->dev, 210 " r%02d-r%02d = %08x %08x %08x %08x\n", 211 i, i + 3, 212 state->regs[i], state->regs[i + 1], 213 state->regs[i + 2], state->regs[i + 3]); 214 215 dev_warn(rtk->dev, "\n"); 216 } 217 218 static void apple_rtkit_crashlog_dump_aarch64(struct apple_rtkit *rtk, u8 *bfr, 219 size_t size) 220 { 221 struct apple_rtkit_crashlog_aarch64 *state; 222 const char *el; 223 int i; 224 225 if (size < sizeof(*state)) { 226 dev_warn(rtk->dev, "RTKit: AArch64 section too small: 0x%zx", 227 size); 228 return; 229 } 230 231 state = (struct apple_rtkit_crashlog_aarch64 *)bfr; 232 233 switch (state->psr & PSR_MODE_MASK) { 234 case PSR_MODE_EL0t: 235 el = "EL0t"; 236 break; 237 case PSR_MODE_EL1t: 238 el = "EL1t"; 239 break; 240 case PSR_MODE_EL1h: 241 el = "EL1h"; 242 break; 243 case PSR_MODE_EL2t: 244 el = "EL2t"; 245 break; 246 case PSR_MODE_EL2h: 247 el = "EL2h"; 248 break; 249 default: 250 el = "unknown"; 251 break; 252 } 253 254 dev_warn(rtk->dev, "RTKit: Exception dump:"); 255 dev_warn(rtk->dev, " == Exception taken from %s ==", el); 256 dev_warn(rtk->dev, " PSR = 0x%llx", state->psr); 257 dev_warn(rtk->dev, " PC = 0x%llx\n", state->pc); 258 dev_warn(rtk->dev, " ESR = 0x%llx\n", state->esr); 259 dev_warn(rtk->dev, " FAR = 0x%llx\n", state->far); 260 dev_warn(rtk->dev, " SP = 0x%llx\n", state->sp); 261 dev_warn(rtk->dev, "\n"); 262 263 for (i = 0; i < 31; i += 4) { 264 if (i < 28) 265 dev_warn(rtk->dev, 266 " x%02d-x%02d = %016llx %016llx %016llx %016llx\n", 267 i, i + 3, 268 state->regs[i], state->regs[i + 1], 269 state->regs[i + 2], state->regs[i + 3]); 270 else 271 dev_warn(rtk->dev, 272 " x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3, 273 state->regs[i], state->regs[i + 1], state->regs[i + 2]); 274 } 275 276 dev_warn(rtk->dev, "\n"); 277 } 278 279 void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size) 280 { 281 size_t offset; 282 u32 section_fourcc, section_size; 283 struct apple_rtkit_crashlog_header header; 284 285 memcpy(&header, bfr, sizeof(header)); 286 if (header.fourcc != APPLE_RTKIT_CRASHLOG_HEADER) { 287 dev_warn(rtk->dev, "RTKit: Expected crashlog header but got %x", 288 header.fourcc); 289 return; 290 } 291 292 if (header.size > size) { 293 dev_warn(rtk->dev, "RTKit: Crashlog size (%x) is too large", 294 header.size); 295 return; 296 } 297 298 size = header.size; 299 offset = sizeof(header); 300 301 while (offset < size) { 302 memcpy(§ion_fourcc, bfr + offset, 4); 303 memcpy(§ion_size, bfr + offset + 12, 4); 304 305 switch (section_fourcc) { 306 case APPLE_RTKIT_CRASHLOG_HEADER: 307 dev_dbg(rtk->dev, "RTKit: End of crashlog reached"); 308 return; 309 case APPLE_RTKIT_CRASHLOG_STR: 310 apple_rtkit_crashlog_dump_str(rtk, bfr + offset + 16, 311 section_size); 312 break; 313 case APPLE_RTKIT_CRASHLOG_VERSION: 314 apple_rtkit_crashlog_dump_version( 315 rtk, bfr + offset + 16, section_size); 316 break; 317 case APPLE_RTKIT_CRASHLOG_MBOX: 318 apple_rtkit_crashlog_dump_mailbox( 319 rtk, bfr + offset + 16, section_size); 320 break; 321 case APPLE_RTKIT_CRASHLOG_TIME: 322 apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16, 323 section_size); 324 break; 325 case APPLE_RTKIT_CRASHLOG_AARCH32: 326 apple_rtkit_crashlog_dump_aarch32(rtk, bfr + offset + 16, 327 section_size); 328 break; 329 case APPLE_RTKIT_CRASHLOG_AARCH64: 330 apple_rtkit_crashlog_dump_aarch64(rtk, bfr + offset + 16, 331 section_size); 332 break; 333 default: 334 dev_warn(rtk->dev, 335 "RTKit: Unknown crashlog section: %x", 336 section_fourcc); 337 } 338 339 offset += section_size; 340 } 341 342 dev_warn(rtk->dev, 343 "RTKit: End of crashlog reached but no footer present"); 344 } 345