diff options
| author | Bradley Morgan <brads@mainlining.org> | 2026-10-04 10:42:10 +0000 |
|---|---|---|
| committer | Bradley Morgan <brads@mainlining.org> | 2026-10-04 10:46:46 +0000 |
| commit | 5ff54a875642962fc857cee00bde17f9a465f1fa (patch) | |
| tree | b265a12d538167c3bbb86b24118a7ad7a062fc74 /arch/arm64/kernel/exceptions.c | |
holy shit it's here, Tashaboot, based from arm arm, enjoy
reading this masterpiece
Signed-off-by: Bradley Morgan <brads@mainlining.org>
Diffstat (limited to 'arch/arm64/kernel/exceptions.c')
| -rw-r--r-- | arch/arm64/kernel/exceptions.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/arch/arm64/kernel/exceptions.c b/arch/arm64/kernel/exceptions.c new file mode 100644 index 0000000..7b40690 --- /dev/null +++ b/arch/arm64/kernel/exceptions.c @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * exceptions.c - report an abort through the console before parking, + * so a firmware handoff bug says why it died instead of hanging quiet. + * ESR/FAR decode follows armv8 DDI 0487, the EC and ISS fields. + * + * Copyright (C) 2026 Bradley Morgan <brads@mainlining.org> + */ + +#include <stdint.h> +#include <debug.h> + +struct exc_frame { + uint64_t esr; + uint64_t far; + uint64_t lr; +}; + +/* + * exception class from ESR, bits 31:26. the classes a bootloader can + * actually hit with any frequency. + */ +static const char *exc_class_str(uint64_t esr) +{ + switch (esr >> 26) { + case 0x04: return "data abort, lower EL"; + case 0x05: return "data abort, same EL"; + case 0x25: return "data abort, same EL"; + case 0x08: return "stack pointer misaligned"; + case 0x11: return "instruction abort, same EL"; + case 0x16: return "SError"; + case 0x1a: return "unhandled exception"; + case 0x22: return "pc alignment fault"; + case 0x24: return "unknown trap"; + case 0x26: return "same EL exception return"; + default: return "unknown EC"; + } +} + +/* + * far is only meaningful for the abort and alignment classes, note it + * for those and skip it otherwise so the report does not mislead. + */ +static int exc_far_valid(uint64_t esr) +{ + switch (esr >> 26) { + case 0x04: + case 0x05: + case 0x25: + case 0x11: + case 0x22: + return 1; + default: + return 0; + } +} + +void exc_report(uint64_t esr, uint64_t far, uint64_t lr) +{ + dprintf(CRITICAL, "tashaboot: exception %s\n", exc_class_str(esr)); + dprintf(CRITICAL, "esr %016llx lr %016llx\n", + (unsigned long long)esr, (unsigned long long)lr); + if (exc_far_valid(esr)) + dprintf(CRITICAL, "far %016llx\n", (unsigned long long)far); + + /* nothing recovers from an abort here, park after reporting */ +} |
