| /* SPDX-License-Identifier: GPL-2.0 */ | |
| #ifndef _ASM_S390_BUG_H | |
| #define _ASM_S390_BUG_H | |
| #include <linux/compiler.h> | |
| #include <linux/const.h> | |
| #include <linux/stringify.h> | |
| #define MONCODE_BUG _AC(0, U) | |
| #define MONCODE_BUG_ARG _AC(1, U) | |
| #ifndef __ASSEMBLER__ | |
| #if defined(CONFIG_BUG) && defined(CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS) | |
| #ifdef CONFIG_DEBUG_BUGVERBOSE | |
| #define __BUG_ENTRY_VERBOSE(file, line) \ | |
| " .long " file " - . # bug_entry::file\n" \ | |
| " .short " line " # bug_entry::line\n" | |
| #else | |
| #define __BUG_ENTRY_VERBOSE(file, line) | |
| #endif | |
| #ifdef CONFIG_DEBUG_BUGVERBOSE_DETAILED | |
| #define WARN_CONDITION_STR(cond_str) cond_str | |
| #else | |
| #define WARN_CONDITION_STR(cond_str) "" | |
| #endif | |
| #define __BUG_ENTRY(format, file, line, flags, size) \ | |
| " .section __bug_table,\"aw\"\n" \ | |
| "1: .long 0b - . # bug_entry::bug_addr\n"\ | |
| " .long " format " - . # bug_entry::format\n" \ | |
| __BUG_ENTRY_VERBOSE(file, line) \ | |
| " .short "flags" # bug_entry::flags\n" \ | |
| " .org 1b+"size"\n" \ | |
| " .previous" | |
| #define __BUG_ASM(cond_str, flags) \ | |
| do { \ | |
| asm_inline volatile("\n" \ | |
| "0: mc %[monc](%%r0),0\n" \ | |
| __BUG_ENTRY("%[frmt]", "%[file]", "%[line]", \ | |
| "%[flgs]", "%[size]") \ | |
| : \ | |
| : [monc] "i" (MONCODE_BUG), \ | |
| [frmt] "i" (WARN_CONDITION_STR(cond_str)), \ | |
| [file] "i" (__FILE__), \ | |
| [line] "i" (__LINE__), \ | |
| [flgs] "i" (flags), \ | |
| [size] "i" (sizeof(struct bug_entry))); \ | |
| } while (0) | |
| #define BUG() \ | |
| do { \ | |
| __BUG_ASM("", 0); \ | |
| unreachable(); \ | |
| } while (0) | |
| #define __WARN_FLAGS(cond_str, flags) \ | |
| do { \ | |
| __BUG_ASM(cond_str, BUGFLAG_WARNING | (flags)); \ | |
| } while (0) | |
| #define __WARN_bug_entry(flags, format) \ | |
| ({ \ | |
| struct bug_entry *bug; \ | |
| \ | |
| asm_inline volatile("\n" \ | |
| "0: larl %[bug],1f\n" \ | |
| __BUG_ENTRY("%[frmt]", "%[file]", "%[line]", \ | |
| "%[flgs]", "%[size]") \ | |
| : [bug] "=d" (bug) \ | |
| : [frmt] "i" (format), \ | |
| [file] "i" (__FILE__), \ | |
| [line] "i" (__LINE__), \ | |
| [flgs] "i" (flags), \ | |
| [size] "i" (sizeof(struct bug_entry))); \ | |
| bug; \ | |
| }) | |
| /* | |
| * Variable Argument List (va_list) as defined in ELF Application | |
| * Binary Interface s390x Supplement documentation. | |
| */ | |
| struct arch_va_list { | |
| long __gpr; | |
| long __fpr; | |
| void *__overflow_arg_area; | |
| void *__reg_save_area; | |
| }; | |
| struct bug_entry; | |
| struct pt_regs; | |
| void *__warn_args(struct arch_va_list *args, struct pt_regs *regs); | |
| void __WARN_trap(struct bug_entry *bug, ...); | |
| #define __WARN_print_arg(flags, format, arg...) \ | |
| do { \ | |
| int __flags = (flags) | BUGFLAG_WARNING | BUGFLAG_ARGS; \ | |
| \ | |
| __WARN_trap(__WARN_bug_entry(__flags, format), ## arg); \ | |
| /* prevent tail-call optimization */ \ | |
| asm(""); \ | |
| } while (0) | |
| #define __WARN_printf(taint, fmt, arg...) \ | |
| __WARN_print_arg(BUGFLAG_TAINT(taint), fmt, ## arg) | |
| #define WARN_ONCE(cond, format, arg...) \ | |
| ({ \ | |
| int __ret_warn_on = !!(cond); \ | |
| \ | |
| if (unlikely(__ret_warn_on)) { \ | |
| __WARN_print_arg(BUGFLAG_ONCE|BUGFLAG_TAINT(TAINT_WARN),\ | |
| format, ## arg); \ | |
| } \ | |
| __ret_warn_on; \ | |
| }) | |
| #define HAVE_ARCH_BUG | |
| #define HAVE_ARCH_BUG_FORMAT | |
| #define HAVE_ARCH_BUG_FORMAT_ARGS | |
| #define ARCH_WARN_ASM(file, line, flags, size) \ | |
| ".section .rodata.str,\"aMS\",@progbits,1\n" \ | |
| "9:\n" \ | |
| ".asciz \"\"\n" /* Empty string for compatibility */ \ | |
| ".previous\n" \ | |
| "0:\n" \ | |
| __stringify(mc 0(%r0),0) "\n" \ | |
| __BUG_ENTRY("9b", file, line, flags, size) | |
| #define ARCH_WARN_REACHABLE | |
| #endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */ | |
| #endif /* __ASSEMBLER__ */ | |
| #include <asm-generic/bug.h> | |
| #endif /* _ASM_S390_BUG_H */ |