0001
0002
0003
0004 ATOMICDIR=$(dirname $0)
0005
0006 . ${ATOMICDIR}/atomic-tbl.sh
0007
0008
0009 gen_param_check()
0010 {
0011 local meta="$1"; shift
0012 local arg="$1"; shift
0013 local type="${arg%%:*}"
0014 local name="$(gen_param_name "${arg}")"
0015 local rw="write"
0016
0017 case "${type#c}" in
0018 i) return;;
0019 esac
0020
0021 if [ ${type
0022
0023 rw="read"
0024 elif [ "${meta}" != "s" ]; then
0025
0026
0027 rw="read_write"
0028 fi
0029
0030 printf "\tinstrument_atomic_${rw}(${name}, sizeof(*${name}));\n"
0031 }
0032
0033
0034 gen_params_checks()
0035 {
0036 local meta="$1"; shift
0037 local order="$1"; shift
0038
0039 if [ "${order}" = "_release" ]; then
0040 printf "\tkcsan_release();\n"
0041 elif [ -z "${order}" ] && ! meta_in "$meta" "slv"; then
0042
0043 printf "\tkcsan_mb();\n"
0044 fi
0045
0046 while [ "$#" -gt 0 ]; do
0047 gen_param_check "$meta" "$1"
0048 shift;
0049 done
0050 }
0051
0052
0053 gen_proto_order_variant()
0054 {
0055 local meta="$1"; shift
0056 local pfx="$1"; shift
0057 local name="$1"; shift
0058 local sfx="$1"; shift
0059 local order="$1"; shift
0060 local atomic="$1"; shift
0061 local int="$1"; shift
0062
0063 local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
0064
0065 local ret="$(gen_ret_type "${meta}" "${int}")"
0066 local params="$(gen_params "${int}" "${atomic}" "$@")"
0067 local checks="$(gen_params_checks "${meta}" "${order}" "$@")"
0068 local args="$(gen_args "$@")"
0069 local retstmt="$(gen_ret_stmt "${meta}")"
0070
0071 cat <<EOF
0072 static __always_inline ${ret}
0073 ${atomicname}(${params})
0074 {
0075 ${checks}
0076 ${retstmt}arch_${atomicname}(${args});
0077 }
0078 EOF
0079
0080 printf "\n"
0081 }
0082
0083 gen_xchg()
0084 {
0085 local xchg="$1"; shift
0086 local order="$1"; shift
0087 local mult="$1"; shift
0088
0089 kcsan_barrier=""
0090 if [ "${xchg%_local}" = "${xchg}" ]; then
0091 case "$order" in
0092 _release) kcsan_barrier="kcsan_release()" ;;
0093 "") kcsan_barrier="kcsan_mb()" ;;
0094 esac
0095 fi
0096
0097 if [ "${xchg%${xchg#try_cmpxchg}}" = "try_cmpxchg" ] ; then
0098
0099 cat <<EOF
0100
0101 ({ \\
0102 typeof(ptr) __ai_ptr = (ptr); \\
0103 typeof(oldp) __ai_oldp = (oldp); \\
0104 EOF
0105 [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n"
0106 cat <<EOF
0107 instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
0108 instrument_atomic_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\
0109 arch_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\
0110 })
0111 EOF
0112
0113 else
0114
0115 cat <<EOF
0116
0117 ({ \\
0118 typeof(ptr) __ai_ptr = (ptr); \\
0119 EOF
0120 [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n"
0121 cat <<EOF
0122 instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
0123 arch_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\
0124 })
0125 EOF
0126
0127 fi
0128 }
0129
0130 cat << EOF
0131 // SPDX-License-Identifier: GPL-2.0
0132
0133 // Generated by $0
0134 // DO NOT MODIFY THIS FILE DIRECTLY
0135
0136 /*
0137 * This file provides wrappers with KASAN instrumentation for atomic operations.
0138 * To use this functionality an arch's atomic.h file needs to define all
0139 * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include
0140 * this file at the end. This file provides atomic_read() that forwards to
0141 * arch_atomic_read() for actual atomic operation.
0142 * Note: if an arch atomic operation is implemented by means of other atomic
0143 * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use
0144 * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid
0145 * double instrumentation.
0146 */
0147 #ifndef _LINUX_ATOMIC_INSTRUMENTED_H
0148 #define _LINUX_ATOMIC_INSTRUMENTED_H
0149
0150 #include <linux/build_bug.h>
0151 #include <linux/compiler.h>
0152 #include <linux/instrumented.h>
0153
0154 EOF
0155
0156 grep '^[a-z]' "$1" | while read name meta args; do
0157 gen_proto "${meta}" "${name}" "atomic" "int" ${args}
0158 done
0159
0160 grep '^[a-z]' "$1" | while read name meta args; do
0161 gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
0162 done
0163
0164 grep '^[a-z]' "$1" | while read name meta args; do
0165 gen_proto "${meta}" "${name}" "atomic_long" "long" ${args}
0166 done
0167
0168
0169 for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg" "try_cmpxchg64"; do
0170 for order in "" "_acquire" "_release" "_relaxed"; do
0171 gen_xchg "${xchg}" "${order}" ""
0172 printf "\n"
0173 done
0174 done
0175
0176 for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg"; do
0177 gen_xchg "${xchg}" "" ""
0178 printf "\n"
0179 done
0180
0181 gen_xchg "cmpxchg_double" "" "2 * "
0182
0183 printf "\n\n"
0184
0185 gen_xchg "cmpxchg_double_local" "" "2 * "
0186
0187 cat <<EOF
0188
0189 #endif /* _LINUX_ATOMIC_INSTRUMENTED_H */
0190 EOF