cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bitops.h (11074B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _ASM_IA64_BITOPS_H
      3#define _ASM_IA64_BITOPS_H
      4
      5/*
      6 * Copyright (C) 1998-2003 Hewlett-Packard Co
      7 *	David Mosberger-Tang <davidm@hpl.hp.com>
      8 *
      9 * 02/06/02 find_next_bit() and find_first_bit() added from Erich Focht's ia64
     10 * O(1) scheduler patch
     11 */
     12
     13#ifndef _LINUX_BITOPS_H
     14#error only <linux/bitops.h> can be included directly
     15#endif
     16
     17#include <linux/compiler.h>
     18#include <linux/types.h>
     19#include <asm/intrinsics.h>
     20#include <asm/barrier.h>
     21
     22/**
     23 * set_bit - Atomically set a bit in memory
     24 * @nr: the bit to set
     25 * @addr: the address to start counting from
     26 *
     27 * This function is atomic and may not be reordered.  See __set_bit()
     28 * if you do not require the atomic guarantees.
     29 * Note that @nr may be almost arbitrarily large; this function is not
     30 * restricted to acting on a single-word quantity.
     31 *
     32 * The address must be (at least) "long" aligned.
     33 * Note that there are driver (e.g., eepro100) which use these operations to
     34 * operate on hw-defined data-structures, so we can't easily change these
     35 * operations to force a bigger alignment.
     36 *
     37 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
     38 */
     39static __inline__ void
     40set_bit (int nr, volatile void *addr)
     41{
     42	__u32 bit, old, new;
     43	volatile __u32 *m;
     44	CMPXCHG_BUGCHECK_DECL
     45
     46	m = (volatile __u32 *) addr + (nr >> 5);
     47	bit = 1 << (nr & 31);
     48	do {
     49		CMPXCHG_BUGCHECK(m);
     50		old = *m;
     51		new = old | bit;
     52	} while (cmpxchg_acq(m, old, new) != old);
     53}
     54
     55/**
     56 * __set_bit - Set a bit in memory
     57 * @nr: the bit to set
     58 * @addr: the address to start counting from
     59 *
     60 * Unlike set_bit(), this function is non-atomic and may be reordered.
     61 * If it's called on the same region of memory simultaneously, the effect
     62 * may be that only one operation succeeds.
     63 */
     64static __inline__ void
     65__set_bit (int nr, volatile void *addr)
     66{
     67	*((__u32 *) addr + (nr >> 5)) |= (1 << (nr & 31));
     68}
     69
     70/**
     71 * clear_bit - Clears a bit in memory
     72 * @nr: Bit to clear
     73 * @addr: Address to start counting from
     74 *
     75 * clear_bit() is atomic and may not be reordered.  However, it does
     76 * not contain a memory barrier, so if it is used for locking purposes,
     77 * you should call smp_mb__before_atomic() and/or smp_mb__after_atomic()
     78 * in order to ensure changes are visible on other processors.
     79 */
     80static __inline__ void
     81clear_bit (int nr, volatile void *addr)
     82{
     83	__u32 mask, old, new;
     84	volatile __u32 *m;
     85	CMPXCHG_BUGCHECK_DECL
     86
     87	m = (volatile __u32 *) addr + (nr >> 5);
     88	mask = ~(1 << (nr & 31));
     89	do {
     90		CMPXCHG_BUGCHECK(m);
     91		old = *m;
     92		new = old & mask;
     93	} while (cmpxchg_acq(m, old, new) != old);
     94}
     95
     96/**
     97 * clear_bit_unlock - Clears a bit in memory with release
     98 * @nr: Bit to clear
     99 * @addr: Address to start counting from
    100 *
    101 * clear_bit_unlock() is atomic and may not be reordered.  It does
    102 * contain a memory barrier suitable for unlock type operations.
    103 */
    104static __inline__ void
    105clear_bit_unlock (int nr, volatile void *addr)
    106{
    107	__u32 mask, old, new;
    108	volatile __u32 *m;
    109	CMPXCHG_BUGCHECK_DECL
    110
    111	m = (volatile __u32 *) addr + (nr >> 5);
    112	mask = ~(1 << (nr & 31));
    113	do {
    114		CMPXCHG_BUGCHECK(m);
    115		old = *m;
    116		new = old & mask;
    117	} while (cmpxchg_rel(m, old, new) != old);
    118}
    119
    120/**
    121 * __clear_bit_unlock - Non-atomically clears a bit in memory with release
    122 * @nr: Bit to clear
    123 * @addr: Address to start counting from
    124 *
    125 * Similarly to clear_bit_unlock, the implementation uses a store
    126 * with release semantics. See also arch_spin_unlock().
    127 */
    128static __inline__ void
    129__clear_bit_unlock(int nr, void *addr)
    130{
    131	__u32 * const m = (__u32 *) addr + (nr >> 5);
    132	__u32 const new = *m & ~(1 << (nr & 31));
    133
    134	ia64_st4_rel_nta(m, new);
    135}
    136
    137/**
    138 * __clear_bit - Clears a bit in memory (non-atomic version)
    139 * @nr: the bit to clear
    140 * @addr: the address to start counting from
    141 *
    142 * Unlike clear_bit(), this function is non-atomic and may be reordered.
    143 * If it's called on the same region of memory simultaneously, the effect
    144 * may be that only one operation succeeds.
    145 */
    146static __inline__ void
    147__clear_bit (int nr, volatile void *addr)
    148{
    149	*((__u32 *) addr + (nr >> 5)) &= ~(1 << (nr & 31));
    150}
    151
    152/**
    153 * change_bit - Toggle a bit in memory
    154 * @nr: Bit to toggle
    155 * @addr: Address to start counting from
    156 *
    157 * change_bit() is atomic and may not be reordered.
    158 * Note that @nr may be almost arbitrarily large; this function is not
    159 * restricted to acting on a single-word quantity.
    160 */
    161static __inline__ void
    162change_bit (int nr, volatile void *addr)
    163{
    164	__u32 bit, old, new;
    165	volatile __u32 *m;
    166	CMPXCHG_BUGCHECK_DECL
    167
    168	m = (volatile __u32 *) addr + (nr >> 5);
    169	bit = (1 << (nr & 31));
    170	do {
    171		CMPXCHG_BUGCHECK(m);
    172		old = *m;
    173		new = old ^ bit;
    174	} while (cmpxchg_acq(m, old, new) != old);
    175}
    176
    177/**
    178 * __change_bit - Toggle a bit in memory
    179 * @nr: the bit to toggle
    180 * @addr: the address to start counting from
    181 *
    182 * Unlike change_bit(), this function is non-atomic and may be reordered.
    183 * If it's called on the same region of memory simultaneously, the effect
    184 * may be that only one operation succeeds.
    185 */
    186static __inline__ void
    187__change_bit (int nr, volatile void *addr)
    188{
    189	*((__u32 *) addr + (nr >> 5)) ^= (1 << (nr & 31));
    190}
    191
    192/**
    193 * test_and_set_bit - Set a bit and return its old value
    194 * @nr: Bit to set
    195 * @addr: Address to count from
    196 *
    197 * This operation is atomic and cannot be reordered.  
    198 * It also implies the acquisition side of the memory barrier.
    199 */
    200static __inline__ int
    201test_and_set_bit (int nr, volatile void *addr)
    202{
    203	__u32 bit, old, new;
    204	volatile __u32 *m;
    205	CMPXCHG_BUGCHECK_DECL
    206
    207	m = (volatile __u32 *) addr + (nr >> 5);
    208	bit = 1 << (nr & 31);
    209	do {
    210		CMPXCHG_BUGCHECK(m);
    211		old = *m;
    212		new = old | bit;
    213	} while (cmpxchg_acq(m, old, new) != old);
    214	return (old & bit) != 0;
    215}
    216
    217/**
    218 * test_and_set_bit_lock - Set a bit and return its old value for lock
    219 * @nr: Bit to set
    220 * @addr: Address to count from
    221 *
    222 * This is the same as test_and_set_bit on ia64
    223 */
    224#define test_and_set_bit_lock test_and_set_bit
    225
    226/**
    227 * __test_and_set_bit - Set a bit and return its old value
    228 * @nr: Bit to set
    229 * @addr: Address to count from
    230 *
    231 * This operation is non-atomic and can be reordered.  
    232 * If two examples of this operation race, one can appear to succeed
    233 * but actually fail.  You must protect multiple accesses with a lock.
    234 */
    235static __inline__ int
    236__test_and_set_bit (int nr, volatile void *addr)
    237{
    238	__u32 *p = (__u32 *) addr + (nr >> 5);
    239	__u32 m = 1 << (nr & 31);
    240	int oldbitset = (*p & m) != 0;
    241
    242	*p |= m;
    243	return oldbitset;
    244}
    245
    246/**
    247 * test_and_clear_bit - Clear a bit and return its old value
    248 * @nr: Bit to clear
    249 * @addr: Address to count from
    250 *
    251 * This operation is atomic and cannot be reordered.  
    252 * It also implies the acquisition side of the memory barrier.
    253 */
    254static __inline__ int
    255test_and_clear_bit (int nr, volatile void *addr)
    256{
    257	__u32 mask, old, new;
    258	volatile __u32 *m;
    259	CMPXCHG_BUGCHECK_DECL
    260
    261	m = (volatile __u32 *) addr + (nr >> 5);
    262	mask = ~(1 << (nr & 31));
    263	do {
    264		CMPXCHG_BUGCHECK(m);
    265		old = *m;
    266		new = old & mask;
    267	} while (cmpxchg_acq(m, old, new) != old);
    268	return (old & ~mask) != 0;
    269}
    270
    271/**
    272 * __test_and_clear_bit - Clear a bit and return its old value
    273 * @nr: Bit to clear
    274 * @addr: Address to count from
    275 *
    276 * This operation is non-atomic and can be reordered.  
    277 * If two examples of this operation race, one can appear to succeed
    278 * but actually fail.  You must protect multiple accesses with a lock.
    279 */
    280static __inline__ int
    281__test_and_clear_bit(int nr, volatile void * addr)
    282{
    283	__u32 *p = (__u32 *) addr + (nr >> 5);
    284	__u32 m = 1 << (nr & 31);
    285	int oldbitset = (*p & m) != 0;
    286
    287	*p &= ~m;
    288	return oldbitset;
    289}
    290
    291/**
    292 * test_and_change_bit - Change a bit and return its old value
    293 * @nr: Bit to change
    294 * @addr: Address to count from
    295 *
    296 * This operation is atomic and cannot be reordered.  
    297 * It also implies the acquisition side of the memory barrier.
    298 */
    299static __inline__ int
    300test_and_change_bit (int nr, volatile void *addr)
    301{
    302	__u32 bit, old, new;
    303	volatile __u32 *m;
    304	CMPXCHG_BUGCHECK_DECL
    305
    306	m = (volatile __u32 *) addr + (nr >> 5);
    307	bit = (1 << (nr & 31));
    308	do {
    309		CMPXCHG_BUGCHECK(m);
    310		old = *m;
    311		new = old ^ bit;
    312	} while (cmpxchg_acq(m, old, new) != old);
    313	return (old & bit) != 0;
    314}
    315
    316/**
    317 * __test_and_change_bit - Change a bit and return its old value
    318 * @nr: Bit to change
    319 * @addr: Address to count from
    320 *
    321 * This operation is non-atomic and can be reordered.
    322 */
    323static __inline__ int
    324__test_and_change_bit (int nr, void *addr)
    325{
    326	__u32 old, bit = (1 << (nr & 31));
    327	__u32 *m = (__u32 *) addr + (nr >> 5);
    328
    329	old = *m;
    330	*m = old ^ bit;
    331	return (old & bit) != 0;
    332}
    333
    334static __inline__ int
    335test_bit (int nr, const volatile void *addr)
    336{
    337	return 1 & (((const volatile __u32 *) addr)[nr >> 5] >> (nr & 31));
    338}
    339
    340/**
    341 * ffz - find the first zero bit in a long word
    342 * @x: The long word to find the bit in
    343 *
    344 * Returns the bit-number (0..63) of the first (least significant) zero bit.
    345 * Undefined if no zero exists, so code should check against ~0UL first...
    346 */
    347static inline unsigned long
    348ffz (unsigned long x)
    349{
    350	unsigned long result;
    351
    352	result = ia64_popcnt(x & (~x - 1));
    353	return result;
    354}
    355
    356/**
    357 * __ffs - find first bit in word.
    358 * @x: The word to search
    359 *
    360 * Undefined if no bit exists, so code should check against 0 first.
    361 */
    362static __inline__ unsigned long
    363__ffs (unsigned long x)
    364{
    365	unsigned long result;
    366
    367	result = ia64_popcnt((x-1) & ~x);
    368	return result;
    369}
    370
    371#ifdef __KERNEL__
    372
    373/*
    374 * Return bit number of last (most-significant) bit set.  Undefined
    375 * for x==0.  Bits are numbered from 0..63 (e.g., ia64_fls(9) == 3).
    376 */
    377static inline unsigned long
    378ia64_fls (unsigned long x)
    379{
    380	long double d = x;
    381	long exp;
    382
    383	exp = ia64_getf_exp(d);
    384	return exp - 0xffff;
    385}
    386
    387/*
    388 * Find the last (most significant) bit set.  Returns 0 for x==0 and
    389 * bits are numbered from 1..32 (e.g., fls(9) == 4).
    390 */
    391static inline int fls(unsigned int t)
    392{
    393	unsigned long x = t & 0xffffffffu;
    394
    395	if (!x)
    396		return 0;
    397	x |= x >> 1;
    398	x |= x >> 2;
    399	x |= x >> 4;
    400	x |= x >> 8;
    401	x |= x >> 16;
    402	return ia64_popcnt(x);
    403}
    404
    405/*
    406 * Find the last (most significant) bit set.  Undefined for x==0.
    407 * Bits are numbered from 0..63 (e.g., __fls(9) == 3).
    408 */
    409static inline unsigned long
    410__fls (unsigned long x)
    411{
    412	x |= x >> 1;
    413	x |= x >> 2;
    414	x |= x >> 4;
    415	x |= x >> 8;
    416	x |= x >> 16;
    417	x |= x >> 32;
    418	return ia64_popcnt(x) - 1;
    419}
    420
    421#include <asm-generic/bitops/fls64.h>
    422
    423#include <asm-generic/bitops/builtin-ffs.h>
    424
    425/*
    426 * hweightN: returns the hamming weight (i.e. the number
    427 * of bits set) of a N-bit word
    428 */
    429static __inline__ unsigned long __arch_hweight64(unsigned long x)
    430{
    431	unsigned long result;
    432	result = ia64_popcnt(x);
    433	return result;
    434}
    435
    436#define __arch_hweight32(x) ((unsigned int) __arch_hweight64((x) & 0xfffffffful))
    437#define __arch_hweight16(x) ((unsigned int) __arch_hweight64((x) & 0xfffful))
    438#define __arch_hweight8(x)  ((unsigned int) __arch_hweight64((x) & 0xfful))
    439
    440#include <asm-generic/bitops/const_hweight.h>
    441
    442#endif /* __KERNEL__ */
    443
    444#ifdef __KERNEL__
    445
    446#include <asm-generic/bitops/le.h>
    447
    448#include <asm-generic/bitops/ext2-atomic-setbit.h>
    449
    450#include <asm-generic/bitops/sched.h>
    451
    452#endif /* __KERNEL__ */
    453
    454#endif /* _ASM_IA64_BITOPS_H */