aboutsummaryrefslogtreecommitdiff
path: root/libc
diff options
context:
space:
mode:
authorNicholas Piggin <npiggin@gmail.com>2019-09-25 11:01:34 +1000
committerOliver O'Halloran <oohall@gmail.com>2019-10-03 09:55:58 +1000
commit9ddc1a6bfaef8669efd00b36fa1b699c04f6488d (patch)
tree1e3b1585813e5db510f0b7e31914afed040e45b9 /libc
parentb70e8afdb09f56e3c7db643862cd3d2fd15a4544 (diff)
downloadskiboot-9ddc1a6bfaef8669efd00b36fa1b699c04f6488d.zip
skiboot-9ddc1a6bfaef8669efd00b36fa1b699c04f6488d.tar.gz
skiboot-9ddc1a6bfaef8669efd00b36fa1b699c04f6488d.tar.bz2
core/util: trap based assertions
Using traps for assertions like Linux does gives a few advantages: - The asm code leading to the failure condition is nicer. - The interrupt gives a clean snapshot of machine state to dump. The difficulty with using traps for this in OPAL is that the runtime component will not deal well with the OS taking the 0x700 interrupt caused by a trap in OPAL. The long term goal is to improve the ability of the OS to inspect and debug OPAL at runtime. For now though, the traps are patched out before passing control to the OS, and the assert falls through to in-line failure handling. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> [oliver: commit prefix, added and renamed the FWTS label, fix tests] Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
Diffstat (limited to 'libc')
-rw-r--r--libc/include/assert.h45
-rw-r--r--libc/include/stdlib.h7
2 files changed, 39 insertions, 13 deletions
diff --git a/libc/include/assert.h b/libc/include/assert.h
index 2c49fd7..1e511fb 100644
--- a/libc/include/assert.h
+++ b/libc/include/assert.h
@@ -13,17 +13,48 @@
#ifndef _ASSERT_H
#define _ASSERT_H
-#define assert(cond) \
- do { if (!(cond)) { \
- assert_fail(__FILE__ \
- ":" stringify(__LINE__) \
- ":" stringify(cond)); } \
- } while(0)
+struct trap_table_entry {
+ unsigned long address;
+ const char *message;
+};
-void __attribute__((noreturn)) assert_fail(const char *msg);
+extern struct trap_table_entry __trap_table_start[];
+extern struct trap_table_entry __trap_table_end[];
#define stringify(expr) stringify_1(expr)
/* Double-indirection required to stringify expansions */
#define stringify_1(expr) #expr
+void __attribute__((noreturn)) assert_fail(const char *msg,
+ const char *file,
+ unsigned int line,
+ const char *function);
+
+/*
+ * The 'nop' gets patched to 'trap' after skiboot takes over the exception
+ * vectors, then patched to 'nop' before booting the OS (see patch_traps).
+ * This makes assert fall through to assert_fail when we can't use the 0x700
+ * interrupt.
+ */
+#define assert(cond) \
+do { \
+ /* evaluate cond exactly once */ \
+ const unsigned long __cond = (unsigned long)(cond); \
+ asm volatile( \
+ " cmpdi %0,0" "\n\t" \
+ " bne 2f" "\n\t" \
+ "1: nop # assert" "\n\t" \
+ "2:" "\n\t" \
+ ".section .rodata" "\n\t" \
+ "3: .string \"assert failed at " __FILE__ ":" stringify(__LINE__) "\"" "\n\t" \
+ ".previous" "\n\t" \
+ ".section .trap_table,\"aw\"" "\n\t" \
+ ".llong 1b" "\n\t" \
+ ".llong 3b" "\n\t" \
+ ".previous" "\n\t" \
+ : : "r"(__cond) : "cr0"); \
+ if (!__cond) \
+ assert_fail(stringify(cond), __FILE__, __LINE__, __FUNCTION__); \
+} while (0)
+
#endif
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 234bd11..43d5c24 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -26,11 +26,6 @@ long int strtol(const char *nptr, char **endptr, int base);
int rand(void);
long int __attribute__((const)) labs(long int n);
-void __attribute__((noreturn)) _abort(const char *msg);
-#define abort() do { \
- _abort("abort():" __FILE__ \
- ":" stringify(__LINE__)); \
- } while(0)
-
+#define abort() assert(0)
#endif