248 lines · c
1// SPDX-License-Identifier: GPL-2.0-only OR MIT2/*3 * Apple RTKit IPC library4 * Copyright (C) The Asahi Linux Contributors5 */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_REGS FOURCC('C', 'r', 'g', '8')17 18/* For COMPILE_TEST on non-ARM64 architectures */19#ifndef PSR_MODE_EL0t20#define PSR_MODE_EL0t 0x0000000021#define PSR_MODE_EL1t 0x0000000422#define PSR_MODE_EL1h 0x0000000523#define PSR_MODE_EL2t 0x0000000824#define PSR_MODE_EL2h 0x0000000925#define PSR_MODE_MASK 0x0000000f26#endif27 28struct apple_rtkit_crashlog_header {29 u32 fourcc;30 u32 version;31 u32 size;32 u32 flags;33 u8 _unk[16];34};35static_assert(sizeof(struct apple_rtkit_crashlog_header) == 0x20);36 37struct apple_rtkit_crashlog_mbox_entry {38 u64 msg0;39 u64 msg1;40 u32 timestamp;41 u8 _unk[4];42};43static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18);44 45struct apple_rtkit_crashlog_regs {46 u32 unk_0;47 u32 unk_4;48 u64 regs[31];49 u64 sp;50 u64 pc;51 u64 psr;52 u64 cpacr;53 u64 fpsr;54 u64 fpcr;55 u64 unk[64];56 u64 far;57 u64 unk_X;58 u64 esr;59 u64 unk_Z;60} __packed;61static_assert(sizeof(struct apple_rtkit_crashlog_regs) == 0x350);62 63static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,64 size_t size)65{66 u32 idx;67 u8 *ptr, *end;68 69 memcpy(&idx, bfr, 4);70 71 ptr = bfr + 4;72 end = bfr + size;73 while (ptr < end) {74 u8 *newline = memchr(ptr, '\n', end - ptr);75 76 if (newline) {77 u8 tmp = *newline;78 *newline = '\0';79 dev_warn(rtk->dev, "RTKit: Message (id=%x): %s\n", idx,80 ptr);81 *newline = tmp;82 ptr = newline + 1;83 } else {84 dev_warn(rtk->dev, "RTKit: Message (id=%x): %s", idx,85 ptr);86 break;87 }88 }89}90 91static void apple_rtkit_crashlog_dump_version(struct apple_rtkit *rtk, u8 *bfr,92 size_t size)93{94 dev_warn(rtk->dev, "RTKit: Version: %s", bfr + 16);95}96 97static void apple_rtkit_crashlog_dump_time(struct apple_rtkit *rtk, u8 *bfr,98 size_t size)99{100 u64 crash_time;101 102 memcpy(&crash_time, bfr, 8);103 dev_warn(rtk->dev, "RTKit: Crash time: %lld", crash_time);104}105 106static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,107 size_t size)108{109 u32 type, index, i;110 size_t n_messages;111 struct apple_rtkit_crashlog_mbox_entry entry;112 113 memcpy(&type, bfr + 16, 4);114 memcpy(&index, bfr + 24, 4);115 n_messages = (size - 28) / sizeof(entry);116 117 dev_warn(rtk->dev, "RTKit: Mailbox history (type = %d, index = %d)",118 type, index);119 for (i = 0; i < n_messages; ++i) {120 memcpy(&entry, bfr + 28 + i * sizeof(entry), sizeof(entry));121 dev_warn(rtk->dev, "RTKit: #%03d@%08x: %016llx %016llx", i,122 entry.timestamp, entry.msg0, entry.msg1);123 }124}125 126static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr,127 size_t size)128{129 struct apple_rtkit_crashlog_regs *regs;130 const char *el;131 int i;132 133 if (size < sizeof(*regs)) {134 dev_warn(rtk->dev, "RTKit: Regs section too small: 0x%zx", size);135 return;136 }137 138 regs = (struct apple_rtkit_crashlog_regs *)bfr;139 140 switch (regs->psr & PSR_MODE_MASK) {141 case PSR_MODE_EL0t:142 el = "EL0t";143 break;144 case PSR_MODE_EL1t:145 el = "EL1t";146 break;147 case PSR_MODE_EL1h:148 el = "EL1h";149 break;150 case PSR_MODE_EL2t:151 el = "EL2t";152 break;153 case PSR_MODE_EL2h:154 el = "EL2h";155 break;156 default:157 el = "unknown";158 break;159 }160 161 dev_warn(rtk->dev, "RTKit: Exception dump:");162 dev_warn(rtk->dev, " == Exception taken from %s ==", el);163 dev_warn(rtk->dev, " PSR = 0x%llx", regs->psr);164 dev_warn(rtk->dev, " PC = 0x%llx\n", regs->pc);165 dev_warn(rtk->dev, " ESR = 0x%llx\n", regs->esr);166 dev_warn(rtk->dev, " FAR = 0x%llx\n", regs->far);167 dev_warn(rtk->dev, " SP = 0x%llx\n", regs->sp);168 dev_warn(rtk->dev, "\n");169 170 for (i = 0; i < 31; i += 4) {171 if (i < 28)172 dev_warn(rtk->dev,173 " x%02d-x%02d = %016llx %016llx %016llx %016llx\n",174 i, i + 3,175 regs->regs[i], regs->regs[i + 1],176 regs->regs[i + 2], regs->regs[i + 3]);177 else178 dev_warn(rtk->dev,179 " x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3,180 regs->regs[i], regs->regs[i + 1], regs->regs[i + 2]);181 }182 183 dev_warn(rtk->dev, "\n");184}185 186void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)187{188 size_t offset;189 u32 section_fourcc, section_size;190 struct apple_rtkit_crashlog_header header;191 192 memcpy(&header, bfr, sizeof(header));193 if (header.fourcc != APPLE_RTKIT_CRASHLOG_HEADER) {194 dev_warn(rtk->dev, "RTKit: Expected crashlog header but got %x",195 header.fourcc);196 return;197 }198 199 if (header.size > size) {200 dev_warn(rtk->dev, "RTKit: Crashlog size (%x) is too large",201 header.size);202 return;203 }204 205 size = header.size;206 offset = sizeof(header);207 208 while (offset < size) {209 memcpy(§ion_fourcc, bfr + offset, 4);210 memcpy(§ion_size, bfr + offset + 12, 4);211 212 switch (section_fourcc) {213 case APPLE_RTKIT_CRASHLOG_HEADER:214 dev_dbg(rtk->dev, "RTKit: End of crashlog reached");215 return;216 case APPLE_RTKIT_CRASHLOG_STR:217 apple_rtkit_crashlog_dump_str(rtk, bfr + offset + 16,218 section_size);219 break;220 case APPLE_RTKIT_CRASHLOG_VERSION:221 apple_rtkit_crashlog_dump_version(222 rtk, bfr + offset + 16, section_size);223 break;224 case APPLE_RTKIT_CRASHLOG_MBOX:225 apple_rtkit_crashlog_dump_mailbox(226 rtk, bfr + offset + 16, section_size);227 break;228 case APPLE_RTKIT_CRASHLOG_TIME:229 apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16,230 section_size);231 break;232 case APPLE_RTKIT_CRASHLOG_REGS:233 apple_rtkit_crashlog_dump_regs(rtk, bfr + offset + 16,234 section_size);235 break;236 default:237 dev_warn(rtk->dev,238 "RTKit: Unknown crashlog section: %x",239 section_fourcc);240 }241 242 offset += section_size;243 }244 245 dev_warn(rtk->dev,246 "RTKit: End of crashlog reached but no footer present");247}248