diff options
author | Nicholas Piggin <npiggin@gmail.com> | 2019-09-25 11:01:34 +1000 |
---|---|---|
committer | Oliver O'Halloran <oohall@gmail.com> | 2019-10-03 09:55:58 +1000 |
commit | 9ddc1a6bfaef8669efd00b36fa1b699c04f6488d (patch) | |
tree | 1e3b1585813e5db510f0b7e31914afed040e45b9 /libc | |
parent | b70e8afdb09f56e3c7db643862cd3d2fd15a4544 (diff) | |
download | skiboot-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.h | 45 | ||||
-rw-r--r-- | libc/include/stdlib.h | 7 |
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 |