162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci/* 462306a36Sopenharmony_ci * This file provides wrappers with sanitizer instrumentation for non-atomic 562306a36Sopenharmony_ci * bit operations. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * To use this functionality, an arch's bitops.h file needs to define each of 862306a36Sopenharmony_ci * the below bit operations with an arch_ prefix (e.g. arch_set_bit(), 962306a36Sopenharmony_ci * arch___set_bit(), etc.). 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci#ifndef _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H 1262306a36Sopenharmony_ci#define _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/instrumented.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/** 1762306a36Sopenharmony_ci * ___set_bit - Set a bit in memory 1862306a36Sopenharmony_ci * @nr: the bit to set 1962306a36Sopenharmony_ci * @addr: the address to start counting from 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * Unlike set_bit(), this function is non-atomic. If it is called on the same 2262306a36Sopenharmony_ci * region of memory concurrently, the effect may be that only one operation 2362306a36Sopenharmony_ci * succeeds. 2462306a36Sopenharmony_ci */ 2562306a36Sopenharmony_cistatic __always_inline void 2662306a36Sopenharmony_ci___set_bit(unsigned long nr, volatile unsigned long *addr) 2762306a36Sopenharmony_ci{ 2862306a36Sopenharmony_ci instrument_write(addr + BIT_WORD(nr), sizeof(long)); 2962306a36Sopenharmony_ci arch___set_bit(nr, addr); 3062306a36Sopenharmony_ci} 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci/** 3362306a36Sopenharmony_ci * ___clear_bit - Clears a bit in memory 3462306a36Sopenharmony_ci * @nr: the bit to clear 3562306a36Sopenharmony_ci * @addr: the address to start counting from 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * Unlike clear_bit(), this function is non-atomic. If it is called on the same 3862306a36Sopenharmony_ci * region of memory concurrently, the effect may be that only one operation 3962306a36Sopenharmony_ci * succeeds. 4062306a36Sopenharmony_ci */ 4162306a36Sopenharmony_cistatic __always_inline void 4262306a36Sopenharmony_ci___clear_bit(unsigned long nr, volatile unsigned long *addr) 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci instrument_write(addr + BIT_WORD(nr), sizeof(long)); 4562306a36Sopenharmony_ci arch___clear_bit(nr, addr); 4662306a36Sopenharmony_ci} 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci/** 4962306a36Sopenharmony_ci * ___change_bit - Toggle a bit in memory 5062306a36Sopenharmony_ci * @nr: the bit to change 5162306a36Sopenharmony_ci * @addr: the address to start counting from 5262306a36Sopenharmony_ci * 5362306a36Sopenharmony_ci * Unlike change_bit(), this function is non-atomic. If it is called on the same 5462306a36Sopenharmony_ci * region of memory concurrently, the effect may be that only one operation 5562306a36Sopenharmony_ci * succeeds. 5662306a36Sopenharmony_ci */ 5762306a36Sopenharmony_cistatic __always_inline void 5862306a36Sopenharmony_ci___change_bit(unsigned long nr, volatile unsigned long *addr) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci instrument_write(addr + BIT_WORD(nr), sizeof(long)); 6162306a36Sopenharmony_ci arch___change_bit(nr, addr); 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_cistatic __always_inline void __instrument_read_write_bitop(long nr, volatile unsigned long *addr) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci if (IS_ENABLED(CONFIG_KCSAN_ASSUME_PLAIN_WRITES_ATOMIC)) { 6762306a36Sopenharmony_ci /* 6862306a36Sopenharmony_ci * We treat non-atomic read-write bitops a little more special. 6962306a36Sopenharmony_ci * Given the operations here only modify a single bit, assuming 7062306a36Sopenharmony_ci * non-atomicity of the writer is sufficient may be reasonable 7162306a36Sopenharmony_ci * for certain usage (and follows the permissible nature of the 7262306a36Sopenharmony_ci * assume-plain-writes-atomic rule): 7362306a36Sopenharmony_ci * 1. report read-modify-write races -> check read; 7462306a36Sopenharmony_ci * 2. do not report races with marked readers, but do report 7562306a36Sopenharmony_ci * races with unmarked readers -> check "atomic" write. 7662306a36Sopenharmony_ci */ 7762306a36Sopenharmony_ci kcsan_check_read(addr + BIT_WORD(nr), sizeof(long)); 7862306a36Sopenharmony_ci /* 7962306a36Sopenharmony_ci * Use generic write instrumentation, in case other sanitizers 8062306a36Sopenharmony_ci * or tools are enabled alongside KCSAN. 8162306a36Sopenharmony_ci */ 8262306a36Sopenharmony_ci instrument_write(addr + BIT_WORD(nr), sizeof(long)); 8362306a36Sopenharmony_ci } else { 8462306a36Sopenharmony_ci instrument_read_write(addr + BIT_WORD(nr), sizeof(long)); 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci} 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/** 8962306a36Sopenharmony_ci * ___test_and_set_bit - Set a bit and return its old value 9062306a36Sopenharmony_ci * @nr: Bit to set 9162306a36Sopenharmony_ci * @addr: Address to count from 9262306a36Sopenharmony_ci * 9362306a36Sopenharmony_ci * This operation is non-atomic. If two instances of this operation race, one 9462306a36Sopenharmony_ci * can appear to succeed but actually fail. 9562306a36Sopenharmony_ci */ 9662306a36Sopenharmony_cistatic __always_inline bool 9762306a36Sopenharmony_ci___test_and_set_bit(unsigned long nr, volatile unsigned long *addr) 9862306a36Sopenharmony_ci{ 9962306a36Sopenharmony_ci __instrument_read_write_bitop(nr, addr); 10062306a36Sopenharmony_ci return arch___test_and_set_bit(nr, addr); 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci/** 10462306a36Sopenharmony_ci * ___test_and_clear_bit - Clear a bit and return its old value 10562306a36Sopenharmony_ci * @nr: Bit to clear 10662306a36Sopenharmony_ci * @addr: Address to count from 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci * This operation is non-atomic. If two instances of this operation race, one 10962306a36Sopenharmony_ci * can appear to succeed but actually fail. 11062306a36Sopenharmony_ci */ 11162306a36Sopenharmony_cistatic __always_inline bool 11262306a36Sopenharmony_ci___test_and_clear_bit(unsigned long nr, volatile unsigned long *addr) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci __instrument_read_write_bitop(nr, addr); 11562306a36Sopenharmony_ci return arch___test_and_clear_bit(nr, addr); 11662306a36Sopenharmony_ci} 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_ci/** 11962306a36Sopenharmony_ci * ___test_and_change_bit - Change a bit and return its old value 12062306a36Sopenharmony_ci * @nr: Bit to change 12162306a36Sopenharmony_ci * @addr: Address to count from 12262306a36Sopenharmony_ci * 12362306a36Sopenharmony_ci * This operation is non-atomic. If two instances of this operation race, one 12462306a36Sopenharmony_ci * can appear to succeed but actually fail. 12562306a36Sopenharmony_ci */ 12662306a36Sopenharmony_cistatic __always_inline bool 12762306a36Sopenharmony_ci___test_and_change_bit(unsigned long nr, volatile unsigned long *addr) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci __instrument_read_write_bitop(nr, addr); 13062306a36Sopenharmony_ci return arch___test_and_change_bit(nr, addr); 13162306a36Sopenharmony_ci} 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_ci/** 13462306a36Sopenharmony_ci * _test_bit - Determine whether a bit is set 13562306a36Sopenharmony_ci * @nr: bit number to test 13662306a36Sopenharmony_ci * @addr: Address to start counting from 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_cistatic __always_inline bool 13962306a36Sopenharmony_ci_test_bit(unsigned long nr, const volatile unsigned long *addr) 14062306a36Sopenharmony_ci{ 14162306a36Sopenharmony_ci instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long)); 14262306a36Sopenharmony_ci return arch_test_bit(nr, addr); 14362306a36Sopenharmony_ci} 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci/** 14662306a36Sopenharmony_ci * _test_bit_acquire - Determine, with acquire semantics, whether a bit is set 14762306a36Sopenharmony_ci * @nr: bit number to test 14862306a36Sopenharmony_ci * @addr: Address to start counting from 14962306a36Sopenharmony_ci */ 15062306a36Sopenharmony_cistatic __always_inline bool 15162306a36Sopenharmony_ci_test_bit_acquire(unsigned long nr, const volatile unsigned long *addr) 15262306a36Sopenharmony_ci{ 15362306a36Sopenharmony_ci instrument_atomic_read(addr + BIT_WORD(nr), sizeof(long)); 15462306a36Sopenharmony_ci return arch_test_bit_acquire(nr, addr); 15562306a36Sopenharmony_ci} 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci#endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */ 158