root/arch/s390/include/asm/bug.h
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_S390_BUG_H
#define _ASM_S390_BUG_H

#include <linux/compiler.h>
#include <linux/const.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(format, file, line)                         \
        "       .long   " format " - .  # bug_entry::format\n"          \
        "       .long   " file " - .    # bug_entry::file\n"            \
        "       .short  " line "        # bug_entry::line\n"
#else
#define __BUG_ENTRY_VERBOSE(format, 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"        \
                __BUG_ENTRY_VERBOSE(format, 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

#endif /* CONFIG_BUG && CONFIG_CC_HAS_ASM_IMMEDIATE_STRINGS */
#endif /* __ASSEMBLER__ */

#include <asm-generic/bug.h>

#endif /* _ASM_S390_BUG_H */