Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm
[linux-2.6-microblaze.git] / scripts / atomic / gen-atomic-instrumented.sh
1 #!/bin/sh
2 # SPDX-License-Identifier: GPL-2.0
3
4 ATOMICDIR=$(dirname $0)
5
6 . ${ATOMICDIR}/atomic-tbl.sh
7
8 #gen_param_check(meta, arg)
9 gen_param_check()
10 {
11         local meta="$1"; shift
12         local arg="$1"; shift
13         local type="${arg%%:*}"
14         local name="$(gen_param_name "${arg}")"
15         local rw="write"
16
17         case "${type#c}" in
18         i) return;;
19         esac
20
21         if [ ${type#c} != ${type} ]; then
22                 # We don't write to constant parameters.
23                 rw="read"
24         elif [ "${meta}" != "s" ]; then
25                 # An atomic RMW: if this parameter is not a constant, and this atomic is
26                 # not just a 's'tore, this parameter is both read from and written to.
27                 rw="read_write"
28         fi
29
30         printf "\tinstrument_atomic_${rw}(${name}, sizeof(*${name}));\n"
31 }
32
33 #gen_params_checks(meta, arg...)
34 gen_params_checks()
35 {
36         local meta="$1"; shift
37
38         while [ "$#" -gt 0 ]; do
39                 gen_param_check "$meta" "$1"
40                 shift;
41         done
42 }
43
44 # gen_guard(meta, atomic, pfx, name, sfx, order)
45 gen_guard()
46 {
47         local meta="$1"; shift
48         local atomic="$1"; shift
49         local pfx="$1"; shift
50         local name="$1"; shift
51         local sfx="$1"; shift
52         local order="$1"; shift
53
54         local atomicname="arch_${atomic}_${pfx}${name}${sfx}${order}"
55
56         local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")"
57
58         # We definitely need a preprocessor symbol for this atomic if it is an
59         # ordering variant, or if there's a generic fallback.
60         if [ ! -z "${order}" ] || [ ! -z "${template}" ]; then
61                 printf "defined(${atomicname})"
62                 return
63         fi
64
65         # If this is a base variant, but a relaxed variant *may* exist, then we
66         # only have a preprocessor symbol if the relaxed variant isn't defined
67         if meta_has_relaxed "${meta}"; then
68                 printf "!defined(${atomicname}_relaxed) || defined(${atomicname})"
69         fi
70 }
71
72 #gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...)
73 gen_proto_order_variant()
74 {
75         local meta="$1"; shift
76         local pfx="$1"; shift
77         local name="$1"; shift
78         local sfx="$1"; shift
79         local order="$1"; shift
80         local atomic="$1"; shift
81         local int="$1"; shift
82
83         local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
84
85         local guard="$(gen_guard "${meta}" "${atomic}" "${pfx}" "${name}" "${sfx}" "${order}")"
86
87         local ret="$(gen_ret_type "${meta}" "${int}")"
88         local params="$(gen_params "${int}" "${atomic}" "$@")"
89         local checks="$(gen_params_checks "${meta}" "$@")"
90         local args="$(gen_args "$@")"
91         local retstmt="$(gen_ret_stmt "${meta}")"
92
93         [ ! -z "${guard}" ] && printf "#if ${guard}\n"
94
95 cat <<EOF
96 static __always_inline ${ret}
97 ${atomicname}(${params})
98 {
99 ${checks}
100         ${retstmt}arch_${atomicname}(${args});
101 }
102 #define ${atomicname} ${atomicname}
103 EOF
104
105         [ ! -z "${guard}" ] && printf "#endif\n"
106
107         printf "\n"
108 }
109
110 gen_xchg()
111 {
112         local xchg="$1"; shift
113         local mult="$1"; shift
114
115         if [ "${xchg%${xchg#try_cmpxchg}}" = "try_cmpxchg" ] ; then
116
117 cat <<EOF
118 #define ${xchg}(ptr, oldp, ...) \\
119 ({ \\
120         typeof(ptr) __ai_ptr = (ptr); \\
121         typeof(oldp) __ai_oldp = (oldp); \\
122         instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
123         instrument_atomic_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\
124         arch_${xchg}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\
125 })
126 EOF
127
128         else
129
130 cat <<EOF
131 #define ${xchg}(ptr, ...) \\
132 ({ \\
133         typeof(ptr) __ai_ptr = (ptr); \\
134         instrument_atomic_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\
135         arch_${xchg}(__ai_ptr, __VA_ARGS__); \\
136 })
137 EOF
138
139         fi
140 }
141
142 gen_optional_xchg()
143 {
144         local name="$1"; shift
145         local sfx="$1"; shift
146         local guard="defined(arch_${name}${sfx})"
147
148         [ -z "${sfx}" ] && guard="!defined(arch_${name}_relaxed) || defined(arch_${name})"
149
150         printf "#if ${guard}\n"
151         gen_xchg "${name}${sfx}" ""
152         printf "#endif\n\n"
153 }
154
155 cat << EOF
156 // SPDX-License-Identifier: GPL-2.0
157
158 // Generated by $0
159 // DO NOT MODIFY THIS FILE DIRECTLY
160
161 /*
162  * This file provides wrappers with KASAN instrumentation for atomic operations.
163  * To use this functionality an arch's atomic.h file needs to define all
164  * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include
165  * this file at the end. This file provides atomic_read() that forwards to
166  * arch_atomic_read() for actual atomic operation.
167  * Note: if an arch atomic operation is implemented by means of other atomic
168  * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use
169  * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid
170  * double instrumentation.
171  */
172 #ifndef _ASM_GENERIC_ATOMIC_INSTRUMENTED_H
173 #define _ASM_GENERIC_ATOMIC_INSTRUMENTED_H
174
175 #include <linux/build_bug.h>
176 #include <linux/compiler.h>
177 #include <linux/instrumented.h>
178
179 EOF
180
181 grep '^[a-z]' "$1" | while read name meta args; do
182         gen_proto "${meta}" "${name}" "atomic" "int" ${args}
183 done
184
185 grep '^[a-z]' "$1" | while read name meta args; do
186         gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
187 done
188
189 for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg"; do
190         for order in "" "_acquire" "_release" "_relaxed"; do
191                 gen_optional_xchg "${xchg}" "${order}"
192         done
193 done
194
195 for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg"; do
196         gen_xchg "${xchg}" ""
197         printf "\n"
198 done
199
200 gen_xchg "cmpxchg_double" "2 * "
201
202 printf "\n\n"
203
204 gen_xchg "cmpxchg_double_local" "2 * "
205
206 cat <<EOF
207
208 #endif /* _ASM_GENERIC_ATOMIC_INSTRUMENTED_H */
209 EOF