soc: apple: rtkit: Add register dump decoding to crashlog
authorAsahi Lina <lina@asahilina.net>
Mon, 23 Jan 2023 03:17:28 +0000 (12:17 +0900)
committerHector Martin <marcan@marcan.st>
Tue, 31 Jan 2023 11:44:47 +0000 (20:44 +0900)
When the coprocessor crashes, it's useful to get a proper register dump
so we can find out what the firmware was doing. Add a decoder for this.

Originally this had ESR decoding by reusing the ARM64 arch header for
this, but that introduces some module linking and cross-arch compilation
issues, so let's leave that out for now.

Reviewed-by: Sven Peter <sven@svenpeter.dev>
Reviewed-by: Eric Curtin <ecurtin@redhat.com>
Signed-off-by: Asahi Lina <lina@asahilina.net>
Signed-off-by: Hector Martin <marcan@marcan.st>
drivers/soc/apple/rtkit-crashlog.c

index 732deed..dfa74b3 100644 (file)
 #define APPLE_RTKIT_CRASHLOG_VERSION FOURCC('C', 'v', 'e', 'r')
 #define APPLE_RTKIT_CRASHLOG_MBOX FOURCC('C', 'm', 'b', 'x')
 #define APPLE_RTKIT_CRASHLOG_TIME FOURCC('C', 't', 'i', 'm')
+#define APPLE_RTKIT_CRASHLOG_REGS FOURCC('C', 'r', 'g', '8')
+
+/* For COMPILE_TEST on non-ARM64 architectures */
+#ifndef PSR_MODE_EL0t
+#define PSR_MODE_EL0t  0x00000000
+#define PSR_MODE_EL1t  0x00000004
+#define PSR_MODE_EL1h  0x00000005
+#define PSR_MODE_EL2t  0x00000008
+#define PSR_MODE_EL2h  0x00000009
+#define PSR_MODE_MASK  0x0000000f
+#endif
 
 struct apple_rtkit_crashlog_header {
        u32 fourcc;
@@ -31,6 +42,24 @@ struct apple_rtkit_crashlog_mbox_entry {
 };
 static_assert(sizeof(struct apple_rtkit_crashlog_mbox_entry) == 0x18);
 
+struct apple_rtkit_crashlog_regs {
+       u32 unk_0;
+       u32 unk_4;
+       u64 regs[31];
+       u64 sp;
+       u64 pc;
+       u64 psr;
+       u64 cpacr;
+       u64 fpsr;
+       u64 fpcr;
+       u64 unk[64];
+       u64 far;
+       u64 unk_X;
+       u64 esr;
+       u64 unk_Z;
+};
+static_assert(sizeof(struct apple_rtkit_crashlog_regs) == 0x350);
+
 static void apple_rtkit_crashlog_dump_str(struct apple_rtkit *rtk, u8 *bfr,
                                          size_t size)
 {
@@ -94,6 +123,66 @@ static void apple_rtkit_crashlog_dump_mailbox(struct apple_rtkit *rtk, u8 *bfr,
        }
 }
 
+static void apple_rtkit_crashlog_dump_regs(struct apple_rtkit *rtk, u8 *bfr,
+                                          size_t size)
+{
+       struct apple_rtkit_crashlog_regs regs;
+       const char *el;
+       int i;
+
+       if (size < sizeof(regs)) {
+               dev_warn(rtk->dev, "RTKit: Regs section too small: 0x%zx", size);
+               return;
+       }
+
+       memcpy(&regs, bfr, sizeof(regs));
+
+       switch (regs.psr & PSR_MODE_MASK) {
+       case PSR_MODE_EL0t:
+               el = "EL0t";
+               break;
+       case PSR_MODE_EL1t:
+               el = "EL1t";
+               break;
+       case PSR_MODE_EL1h:
+               el = "EL1h";
+               break;
+       case PSR_MODE_EL2t:
+               el = "EL2t";
+               break;
+       case PSR_MODE_EL2h:
+               el = "EL2h";
+               break;
+       default:
+               el = "unknown";
+               break;
+       }
+
+       dev_warn(rtk->dev, "RTKit: Exception dump:");
+       dev_warn(rtk->dev, "  == Exception taken from %s ==", el);
+       dev_warn(rtk->dev, "  PSR    = 0x%llx", regs.psr);
+       dev_warn(rtk->dev, "  PC     = 0x%llx\n", regs.pc);
+       dev_warn(rtk->dev, "  ESR    = 0x%llx\n", regs.esr);
+       dev_warn(rtk->dev, "  FAR    = 0x%llx\n", regs.far);
+       dev_warn(rtk->dev, "  SP     = 0x%llx\n", regs.sp);
+       dev_warn(rtk->dev, "\n");
+
+       for (i = 0; i < 31; i += 4) {
+               if (i < 28)
+                       dev_warn(rtk->dev,
+                                        "  x%02d-x%02d = %016llx %016llx %016llx %016llx\n",
+                                        i, i + 3,
+                                        regs.regs[i], regs.regs[i + 1],
+                                        regs.regs[i + 2], regs.regs[i + 3]);
+               else
+                       dev_warn(rtk->dev,
+                                        "  x%02d-x%02d = %016llx %016llx %016llx\n", i, i + 3,
+                                        regs.regs[i], regs.regs[i + 1], regs.regs[i + 2]);
+       }
+
+       dev_warn(rtk->dev, "\n");
+}
+
 void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
 {
        size_t offset;
@@ -140,6 +229,10 @@ void apple_rtkit_crashlog_dump(struct apple_rtkit *rtk, u8 *bfr, size_t size)
                        apple_rtkit_crashlog_dump_time(rtk, bfr + offset + 16,
                                                       section_size);
                        break;
+               case APPLE_RTKIT_CRASHLOG_REGS:
+                       apple_rtkit_crashlog_dump_regs(rtk, bfr + offset + 16,
+                                                      section_size);
+                       break;
                default:
                        dev_warn(rtk->dev,
                                 "RTKit: Unknown crashlog section: %x",