[PATCH 2/2] riscv: Enable bitops instrumentation
Alexandre Ghiti
alex at ghiti.fr
Thu Aug 1 03:31:56 PDT 2024
On 01/08/2024 05:37, Samuel Holland wrote:
> Instead of implementing the bitops functions directly in assembly,
> provide the arch_-prefixed versions and use the wrappers from
> asm-generic to add instrumentation. This improves KASAN coverage and
> fixes the kasan_bitops_generic() unit test.
>
> Signed-off-by: Samuel Holland <samuel.holland at sifive.com>
> ---
>
> arch/riscv/include/asm/bitops.h | 43 ++++++++++++++++++---------------
> 1 file changed, 23 insertions(+), 20 deletions(-)
>
> diff --git a/arch/riscv/include/asm/bitops.h b/arch/riscv/include/asm/bitops.h
> index 71af9ecfcfcb..fae152ea0508 100644
> --- a/arch/riscv/include/asm/bitops.h
> +++ b/arch/riscv/include/asm/bitops.h
> @@ -222,44 +222,44 @@ static __always_inline int variable_fls(unsigned int x)
> #define __NOT(x) (~(x))
>
> /**
> - * test_and_set_bit - Set a bit and return its old value
> + * arch_test_and_set_bit - Set a bit and return its old value
> * @nr: Bit to set
> * @addr: Address to count from
> *
> * This operation may be reordered on other architectures than x86.
> */
> -static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
> +static inline int arch_test_and_set_bit(int nr, volatile unsigned long *addr)
> {
> return __test_and_op_bit(or, __NOP, nr, addr);
> }
>
> /**
> - * test_and_clear_bit - Clear a bit and return its old value
> + * arch_test_and_clear_bit - Clear a bit and return its old value
> * @nr: Bit to clear
> * @addr: Address to count from
> *
> * This operation can be reordered on other architectures other than x86.
> */
> -static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
> +static inline int arch_test_and_clear_bit(int nr, volatile unsigned long *addr)
> {
> return __test_and_op_bit(and, __NOT, nr, addr);
> }
>
> /**
> - * test_and_change_bit - Change a bit and return its old value
> + * arch_test_and_change_bit - Change a bit and return its old value
> * @nr: Bit to change
> * @addr: Address to count from
> *
> * This operation is atomic and cannot be reordered.
> * It also implies a memory barrier.
> */
> -static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
> +static inline int arch_test_and_change_bit(int nr, volatile unsigned long *addr)
> {
> return __test_and_op_bit(xor, __NOP, nr, addr);
> }
>
> /**
> - * set_bit - Atomically set a bit in memory
> + * arch_set_bit - Atomically set a bit in memory
> * @nr: the bit to set
> * @addr: the address to start counting from
> *
> @@ -270,13 +270,13 @@ static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
> * Note that @nr may be almost arbitrarily large; this function is not
> * restricted to acting on a single-word quantity.
> */
> -static inline void set_bit(int nr, volatile unsigned long *addr)
> +static inline void arch_set_bit(int nr, volatile unsigned long *addr)
> {
> __op_bit(or, __NOP, nr, addr);
> }
>
> /**
> - * clear_bit - Clears a bit in memory
> + * arch_clear_bit - Clears a bit in memory
> * @nr: Bit to clear
> * @addr: Address to start counting from
> *
> @@ -284,13 +284,13 @@ static inline void set_bit(int nr, volatile unsigned long *addr)
> * on non x86 architectures, so if you are writing portable code,
> * make sure not to rely on its reordering guarantees.
> */
> -static inline void clear_bit(int nr, volatile unsigned long *addr)
> +static inline void arch_clear_bit(int nr, volatile unsigned long *addr)
> {
> __op_bit(and, __NOT, nr, addr);
> }
>
> /**
> - * change_bit - Toggle a bit in memory
> + * arch_change_bit - Toggle a bit in memory
> * @nr: Bit to change
> * @addr: Address to start counting from
> *
> @@ -298,40 +298,40 @@ static inline void clear_bit(int nr, volatile unsigned long *addr)
> * Note that @nr may be almost arbitrarily large; this function is not
> * restricted to acting on a single-word quantity.
> */
> -static inline void change_bit(int nr, volatile unsigned long *addr)
> +static inline void arch_change_bit(int nr, volatile unsigned long *addr)
> {
> __op_bit(xor, __NOP, nr, addr);
> }
>
> /**
> - * test_and_set_bit_lock - Set a bit and return its old value, for lock
> + * arch_test_and_set_bit_lock - Set a bit and return its old value, for lock
> * @nr: Bit to set
> * @addr: Address to count from
> *
> * This operation is atomic and provides acquire barrier semantics.
> * It can be used to implement bit locks.
> */
> -static inline int test_and_set_bit_lock(
> +static inline int arch_test_and_set_bit_lock(
> unsigned long nr, volatile unsigned long *addr)
> {
> return __test_and_op_bit_ord(or, __NOP, nr, addr, .aq);
> }
>
> /**
> - * clear_bit_unlock - Clear a bit in memory, for unlock
> + * arch_clear_bit_unlock - Clear a bit in memory, for unlock
> * @nr: the bit to set
> * @addr: the address to start counting from
> *
> * This operation is atomic and provides release barrier semantics.
> */
> -static inline void clear_bit_unlock(
> +static inline void arch_clear_bit_unlock(
> unsigned long nr, volatile unsigned long *addr)
> {
> __op_bit_ord(and, __NOT, nr, addr, .rl);
> }
>
> /**
> - * __clear_bit_unlock - Clear a bit in memory, for unlock
> + * arch___clear_bit_unlock - Clear a bit in memory, for unlock
> * @nr: the bit to set
> * @addr: the address to start counting from
> *
Reviewed-by: Alexandre Ghiti <alexghiti at rivosinc.com>
Tested-by: Alexandre Ghiti <alexghiti at rivosinc.com>
Thanks,
Alex
> @@ -345,13 +345,13 @@ static inline void clear_bit_unlock(
> * non-atomic property here: it's a lot more instructions and we still have to
> * provide release semantics anyway.
> */
> -static inline void __clear_bit_unlock(
> +static inline void arch___clear_bit_unlock(
> unsigned long nr, volatile unsigned long *addr)
> {
> - clear_bit_unlock(nr, addr);
> + arch_clear_bit_unlock(nr, addr);
> }
>
> -static inline bool xor_unlock_is_negative_byte(unsigned long mask,
> +static inline bool arch_xor_unlock_is_negative_byte(unsigned long mask,
> volatile unsigned long *addr)
> {
> unsigned long res;
> @@ -369,6 +369,9 @@ static inline bool xor_unlock_is_negative_byte(unsigned long mask,
> #undef __NOT
> #undef __AMO
>
> +#include <asm-generic/bitops/instrumented-atomic.h>
> +#include <asm-generic/bitops/instrumented-lock.h>
> +
> #include <asm-generic/bitops/non-atomic.h>
> #include <asm-generic/bitops/le.h>
> #include <asm-generic/bitops/ext2-atomic.h>
More information about the linux-riscv
mailing list