mirror of
https://github.com/torvalds/linux.git
synced 2024-12-02 09:01:34 +00:00
c9268ac615
Currently a number of arch_atomic*_<op>() functions are optional, and where an arch does not provide a given arch_atomic*_<op>() we will define an implementation of arch_atomic*_<op>() in atomic-arch-fallback.h. Filling in the missing ops requires special care as we want to select the optimal definition of each op (e.g. preferentially defining ops in terms of their relaxed form rather than their fully-ordered form). The ifdeffery necessary for this requires us to group ordering variants together, which can be a bit painful to read, and is painful for kerneldoc generation. It would be easier to handle this if we generated ops into a separate namespace, as this would remove the need to take special care with the ifdeffery, and allow each ordering variant to be generated separately. This patch adds a new set of raw_atomic_<op>() definitions, which are currently trivial wrappers of their arch_atomic_<op>() equivalent. This will allow us to move treewide users of arch_atomic_<op>() over to raw atomic op before we rework the fallback generation to generate raw_atomic_<op> directly. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Kees Cook <keescook@chromium.org> Link: https://lore.kernel.org/r/20230605070124.3741859-18-mark.rutland@arm.com
179 lines
4.0 KiB
Bash
Executable File
179 lines
4.0 KiB
Bash
Executable File
#!/bin/sh
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
|
|
ATOMICDIR=$(dirname $0)
|
|
|
|
. ${ATOMICDIR}/atomic-tbl.sh
|
|
|
|
#gen_param_check(meta, arg)
|
|
gen_param_check()
|
|
{
|
|
local meta="$1"; shift
|
|
local arg="$1"; shift
|
|
local type="${arg%%:*}"
|
|
local name="$(gen_param_name "${arg}")"
|
|
local rw="write"
|
|
|
|
case "${type#c}" in
|
|
i) return;;
|
|
esac
|
|
|
|
if [ ${type#c} != ${type} ]; then
|
|
# We don't write to constant parameters.
|
|
rw="read"
|
|
elif [ "${meta}" != "s" ]; then
|
|
# An atomic RMW: if this parameter is not a constant, and this atomic is
|
|
# not just a 's'tore, this parameter is both read from and written to.
|
|
rw="read_write"
|
|
fi
|
|
|
|
printf "\tinstrument_atomic_${rw}(${name}, sizeof(*${name}));\n"
|
|
}
|
|
|
|
#gen_params_checks(meta, arg...)
|
|
gen_params_checks()
|
|
{
|
|
local meta="$1"; shift
|
|
local order="$1"; shift
|
|
|
|
if [ "${order}" = "_release" ]; then
|
|
printf "\tkcsan_release();\n"
|
|
elif [ -z "${order}" ] && ! meta_in "$meta" "slv"; then
|
|
# RMW with return value is fully ordered
|
|
printf "\tkcsan_mb();\n"
|
|
fi
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
gen_param_check "$meta" "$1"
|
|
shift;
|
|
done
|
|
}
|
|
|
|
#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...)
|
|
gen_proto_order_variant()
|
|
{
|
|
local meta="$1"; shift
|
|
local pfx="$1"; shift
|
|
local name="$1"; shift
|
|
local sfx="$1"; shift
|
|
local order="$1"; shift
|
|
local atomic="$1"; shift
|
|
local int="$1"; shift
|
|
|
|
local atomicname="${atomic}_${pfx}${name}${sfx}${order}"
|
|
|
|
local ret="$(gen_ret_type "${meta}" "${int}")"
|
|
local params="$(gen_params "${int}" "${atomic}" "$@")"
|
|
local checks="$(gen_params_checks "${meta}" "${order}" "$@")"
|
|
local args="$(gen_args "$@")"
|
|
local retstmt="$(gen_ret_stmt "${meta}")"
|
|
|
|
cat <<EOF
|
|
static __always_inline ${ret}
|
|
${atomicname}(${params})
|
|
{
|
|
${checks}
|
|
${retstmt}raw_${atomicname}(${args});
|
|
}
|
|
EOF
|
|
|
|
printf "\n"
|
|
}
|
|
|
|
gen_xchg()
|
|
{
|
|
local xchg="$1"; shift
|
|
local order="$1"; shift
|
|
|
|
kcsan_barrier=""
|
|
if [ "${xchg%_local}" = "${xchg}" ]; then
|
|
case "$order" in
|
|
_release) kcsan_barrier="kcsan_release()" ;;
|
|
"") kcsan_barrier="kcsan_mb()" ;;
|
|
esac
|
|
fi
|
|
|
|
if [ "${xchg%${xchg#try_cmpxchg}}" = "try_cmpxchg" ] ; then
|
|
|
|
cat <<EOF
|
|
#define ${xchg}${order}(ptr, oldp, ...) \\
|
|
({ \\
|
|
typeof(ptr) __ai_ptr = (ptr); \\
|
|
typeof(oldp) __ai_oldp = (oldp); \\
|
|
EOF
|
|
[ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n"
|
|
cat <<EOF
|
|
instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\
|
|
instrument_read_write(__ai_oldp, sizeof(*__ai_oldp)); \\
|
|
raw_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\
|
|
})
|
|
EOF
|
|
|
|
else
|
|
|
|
cat <<EOF
|
|
#define ${xchg}${order}(ptr, ...) \\
|
|
({ \\
|
|
typeof(ptr) __ai_ptr = (ptr); \\
|
|
EOF
|
|
[ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n"
|
|
cat <<EOF
|
|
instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\
|
|
raw_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\
|
|
})
|
|
EOF
|
|
|
|
fi
|
|
}
|
|
|
|
cat << EOF
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
// Generated by $0
|
|
// DO NOT MODIFY THIS FILE DIRECTLY
|
|
|
|
/*
|
|
* This file provoides atomic operations with explicit instrumentation (e.g.
|
|
* KASAN, KCSAN), which should be used unless it is necessary to avoid
|
|
* instrumentation. Where it is necessary to aovid instrumenation, the
|
|
* raw_atomic*() operations should be used.
|
|
*/
|
|
#ifndef _LINUX_ATOMIC_INSTRUMENTED_H
|
|
#define _LINUX_ATOMIC_INSTRUMENTED_H
|
|
|
|
#include <linux/build_bug.h>
|
|
#include <linux/compiler.h>
|
|
#include <linux/instrumented.h>
|
|
|
|
EOF
|
|
|
|
grep '^[a-z]' "$1" | while read name meta args; do
|
|
gen_proto "${meta}" "${name}" "atomic" "int" ${args}
|
|
done
|
|
|
|
grep '^[a-z]' "$1" | while read name meta args; do
|
|
gen_proto "${meta}" "${name}" "atomic64" "s64" ${args}
|
|
done
|
|
|
|
grep '^[a-z]' "$1" | while read name meta args; do
|
|
gen_proto "${meta}" "${name}" "atomic_long" "long" ${args}
|
|
done
|
|
|
|
|
|
for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128" "try_cmpxchg" "try_cmpxchg64" "try_cmpxchg128"; do
|
|
for order in "" "_acquire" "_release" "_relaxed"; do
|
|
gen_xchg "${xchg}" "${order}"
|
|
printf "\n"
|
|
done
|
|
done
|
|
|
|
for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local"; do
|
|
gen_xchg "${xchg}" ""
|
|
printf "\n"
|
|
done
|
|
|
|
cat <<EOF
|
|
|
|
#endif /* _LINUX_ATOMIC_INSTRUMENTED_H */
|
|
EOF
|