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 (10111B)


      1/* SPDX-License-Identifier: GPL-2.0 */
      2#ifndef _ASM_X86_BITOPS_H
      3#define _ASM_X86_BITOPS_H
      4
      5/*
      6 * Copyright 1992, Linus Torvalds.
      7 *
      8 * Note: inlines with more than a single statement should be marked
      9 * __always_inline to avoid problems with older gcc's inlining heuristics.
     10 */
     11
     12#ifndef _LINUX_BITOPS_H
     13#error only <linux/bitops.h> can be included directly
     14#endif
     15
     16#include <linux/compiler.h>
     17#include <asm/alternative.h>
     18#include <asm/rmwcc.h>
     19#include <asm/barrier.h>
     20
     21#if BITS_PER_LONG == 32
     22# define _BITOPS_LONG_SHIFT 5
     23#elif BITS_PER_LONG == 64
     24# define _BITOPS_LONG_SHIFT 6
     25#else
     26# error "Unexpected BITS_PER_LONG"
     27#endif
     28
     29#define BIT_64(n)			(U64_C(1) << (n))
     30
     31/*
     32 * These have to be done with inline assembly: that way the bit-setting
     33 * is guaranteed to be atomic. All bit operations return 0 if the bit
     34 * was cleared before the operation and != 0 if it was not.
     35 *
     36 * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
     37 */
     38
     39#define RLONG_ADDR(x)			 "m" (*(volatile long *) (x))
     40#define WBYTE_ADDR(x)			"+m" (*(volatile char *) (x))
     41
     42#define ADDR				RLONG_ADDR(addr)
     43
     44/*
     45 * We do the locked ops that don't return the old value as
     46 * a mask operation on a byte.
     47 */
     48#define CONST_MASK_ADDR(nr, addr)	WBYTE_ADDR((void *)(addr) + ((nr)>>3))
     49#define CONST_MASK(nr)			(1 << ((nr) & 7))
     50
     51static __always_inline void
     52arch_set_bit(long nr, volatile unsigned long *addr)
     53{
     54	if (__builtin_constant_p(nr)) {
     55		asm volatile(LOCK_PREFIX "orb %b1,%0"
     56			: CONST_MASK_ADDR(nr, addr)
     57			: "iq" (CONST_MASK(nr))
     58			: "memory");
     59	} else {
     60		asm volatile(LOCK_PREFIX __ASM_SIZE(bts) " %1,%0"
     61			: : RLONG_ADDR(addr), "Ir" (nr) : "memory");
     62	}
     63}
     64
     65static __always_inline void
     66arch___set_bit(long nr, volatile unsigned long *addr)
     67{
     68	asm volatile(__ASM_SIZE(bts) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
     69}
     70
     71static __always_inline void
     72arch_clear_bit(long nr, volatile unsigned long *addr)
     73{
     74	if (__builtin_constant_p(nr)) {
     75		asm volatile(LOCK_PREFIX "andb %b1,%0"
     76			: CONST_MASK_ADDR(nr, addr)
     77			: "iq" (~CONST_MASK(nr)));
     78	} else {
     79		asm volatile(LOCK_PREFIX __ASM_SIZE(btr) " %1,%0"
     80			: : RLONG_ADDR(addr), "Ir" (nr) : "memory");
     81	}
     82}
     83
     84static __always_inline void
     85arch_clear_bit_unlock(long nr, volatile unsigned long *addr)
     86{
     87	barrier();
     88	arch_clear_bit(nr, addr);
     89}
     90
     91static __always_inline void
     92arch___clear_bit(long nr, volatile unsigned long *addr)
     93{
     94	asm volatile(__ASM_SIZE(btr) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
     95}
     96
     97static __always_inline bool
     98arch_clear_bit_unlock_is_negative_byte(long nr, volatile unsigned long *addr)
     99{
    100	bool negative;
    101	asm volatile(LOCK_PREFIX "andb %2,%1"
    102		CC_SET(s)
    103		: CC_OUT(s) (negative), WBYTE_ADDR(addr)
    104		: "ir" ((char) ~(1 << nr)) : "memory");
    105	return negative;
    106}
    107#define arch_clear_bit_unlock_is_negative_byte                                 \
    108	arch_clear_bit_unlock_is_negative_byte
    109
    110static __always_inline void
    111arch___clear_bit_unlock(long nr, volatile unsigned long *addr)
    112{
    113	arch___clear_bit(nr, addr);
    114}
    115
    116static __always_inline void
    117arch___change_bit(long nr, volatile unsigned long *addr)
    118{
    119	asm volatile(__ASM_SIZE(btc) " %1,%0" : : ADDR, "Ir" (nr) : "memory");
    120}
    121
    122static __always_inline void
    123arch_change_bit(long nr, volatile unsigned long *addr)
    124{
    125	if (__builtin_constant_p(nr)) {
    126		asm volatile(LOCK_PREFIX "xorb %b1,%0"
    127			: CONST_MASK_ADDR(nr, addr)
    128			: "iq" (CONST_MASK(nr)));
    129	} else {
    130		asm volatile(LOCK_PREFIX __ASM_SIZE(btc) " %1,%0"
    131			: : RLONG_ADDR(addr), "Ir" (nr) : "memory");
    132	}
    133}
    134
    135static __always_inline bool
    136arch_test_and_set_bit(long nr, volatile unsigned long *addr)
    137{
    138	return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(bts), *addr, c, "Ir", nr);
    139}
    140
    141static __always_inline bool
    142arch_test_and_set_bit_lock(long nr, volatile unsigned long *addr)
    143{
    144	return arch_test_and_set_bit(nr, addr);
    145}
    146
    147static __always_inline bool
    148arch___test_and_set_bit(long nr, volatile unsigned long *addr)
    149{
    150	bool oldbit;
    151
    152	asm(__ASM_SIZE(bts) " %2,%1"
    153	    CC_SET(c)
    154	    : CC_OUT(c) (oldbit)
    155	    : ADDR, "Ir" (nr) : "memory");
    156	return oldbit;
    157}
    158
    159static __always_inline bool
    160arch_test_and_clear_bit(long nr, volatile unsigned long *addr)
    161{
    162	return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btr), *addr, c, "Ir", nr);
    163}
    164
    165/*
    166 * Note: the operation is performed atomically with respect to
    167 * the local CPU, but not other CPUs. Portable code should not
    168 * rely on this behaviour.
    169 * KVM relies on this behaviour on x86 for modifying memory that is also
    170 * accessed from a hypervisor on the same CPU if running in a VM: don't change
    171 * this without also updating arch/x86/kernel/kvm.c
    172 */
    173static __always_inline bool
    174arch___test_and_clear_bit(long nr, volatile unsigned long *addr)
    175{
    176	bool oldbit;
    177
    178	asm volatile(__ASM_SIZE(btr) " %2,%1"
    179		     CC_SET(c)
    180		     : CC_OUT(c) (oldbit)
    181		     : ADDR, "Ir" (nr) : "memory");
    182	return oldbit;
    183}
    184
    185static __always_inline bool
    186arch___test_and_change_bit(long nr, volatile unsigned long *addr)
    187{
    188	bool oldbit;
    189
    190	asm volatile(__ASM_SIZE(btc) " %2,%1"
    191		     CC_SET(c)
    192		     : CC_OUT(c) (oldbit)
    193		     : ADDR, "Ir" (nr) : "memory");
    194
    195	return oldbit;
    196}
    197
    198static __always_inline bool
    199arch_test_and_change_bit(long nr, volatile unsigned long *addr)
    200{
    201	return GEN_BINARY_RMWcc(LOCK_PREFIX __ASM_SIZE(btc), *addr, c, "Ir", nr);
    202}
    203
    204static __always_inline bool constant_test_bit(long nr, const volatile unsigned long *addr)
    205{
    206	return ((1UL << (nr & (BITS_PER_LONG-1))) &
    207		(addr[nr >> _BITOPS_LONG_SHIFT])) != 0;
    208}
    209
    210static __always_inline bool variable_test_bit(long nr, volatile const unsigned long *addr)
    211{
    212	bool oldbit;
    213
    214	asm volatile(__ASM_SIZE(bt) " %2,%1"
    215		     CC_SET(c)
    216		     : CC_OUT(c) (oldbit)
    217		     : "m" (*(unsigned long *)addr), "Ir" (nr) : "memory");
    218
    219	return oldbit;
    220}
    221
    222#define arch_test_bit(nr, addr)			\
    223	(__builtin_constant_p((nr))		\
    224	 ? constant_test_bit((nr), (addr))	\
    225	 : variable_test_bit((nr), (addr)))
    226
    227/**
    228 * __ffs - find first set bit in word
    229 * @word: The word to search
    230 *
    231 * Undefined if no bit exists, so code should check against 0 first.
    232 */
    233static __always_inline unsigned long __ffs(unsigned long word)
    234{
    235	asm("rep; bsf %1,%0"
    236		: "=r" (word)
    237		: "rm" (word));
    238	return word;
    239}
    240
    241/**
    242 * ffz - find first zero bit in word
    243 * @word: The word to search
    244 *
    245 * Undefined if no zero exists, so code should check against ~0UL first.
    246 */
    247static __always_inline unsigned long ffz(unsigned long word)
    248{
    249	asm("rep; bsf %1,%0"
    250		: "=r" (word)
    251		: "r" (~word));
    252	return word;
    253}
    254
    255/*
    256 * __fls: find last set bit in word
    257 * @word: The word to search
    258 *
    259 * Undefined if no set bit exists, so code should check against 0 first.
    260 */
    261static __always_inline unsigned long __fls(unsigned long word)
    262{
    263	asm("bsr %1,%0"
    264	    : "=r" (word)
    265	    : "rm" (word));
    266	return word;
    267}
    268
    269#undef ADDR
    270
    271#ifdef __KERNEL__
    272/**
    273 * ffs - find first set bit in word
    274 * @x: the word to search
    275 *
    276 * This is defined the same way as the libc and compiler builtin ffs
    277 * routines, therefore differs in spirit from the other bitops.
    278 *
    279 * ffs(value) returns 0 if value is 0 or the position of the first
    280 * set bit if value is nonzero. The first (least significant) bit
    281 * is at position 1.
    282 */
    283static __always_inline int ffs(int x)
    284{
    285	int r;
    286
    287#ifdef CONFIG_X86_64
    288	/*
    289	 * AMD64 says BSFL won't clobber the dest reg if x==0; Intel64 says the
    290	 * dest reg is undefined if x==0, but their CPU architect says its
    291	 * value is written to set it to the same as before, except that the
    292	 * top 32 bits will be cleared.
    293	 *
    294	 * We cannot do this on 32 bits because at the very least some
    295	 * 486 CPUs did not behave this way.
    296	 */
    297	asm("bsfl %1,%0"
    298	    : "=r" (r)
    299	    : "rm" (x), "0" (-1));
    300#elif defined(CONFIG_X86_CMOV)
    301	asm("bsfl %1,%0\n\t"
    302	    "cmovzl %2,%0"
    303	    : "=&r" (r) : "rm" (x), "r" (-1));
    304#else
    305	asm("bsfl %1,%0\n\t"
    306	    "jnz 1f\n\t"
    307	    "movl $-1,%0\n"
    308	    "1:" : "=r" (r) : "rm" (x));
    309#endif
    310	return r + 1;
    311}
    312
    313/**
    314 * fls - find last set bit in word
    315 * @x: the word to search
    316 *
    317 * This is defined in a similar way as the libc and compiler builtin
    318 * ffs, but returns the position of the most significant set bit.
    319 *
    320 * fls(value) returns 0 if value is 0 or the position of the last
    321 * set bit if value is nonzero. The last (most significant) bit is
    322 * at position 32.
    323 */
    324static __always_inline int fls(unsigned int x)
    325{
    326	int r;
    327
    328#ifdef CONFIG_X86_64
    329	/*
    330	 * AMD64 says BSRL won't clobber the dest reg if x==0; Intel64 says the
    331	 * dest reg is undefined if x==0, but their CPU architect says its
    332	 * value is written to set it to the same as before, except that the
    333	 * top 32 bits will be cleared.
    334	 *
    335	 * We cannot do this on 32 bits because at the very least some
    336	 * 486 CPUs did not behave this way.
    337	 */
    338	asm("bsrl %1,%0"
    339	    : "=r" (r)
    340	    : "rm" (x), "0" (-1));
    341#elif defined(CONFIG_X86_CMOV)
    342	asm("bsrl %1,%0\n\t"
    343	    "cmovzl %2,%0"
    344	    : "=&r" (r) : "rm" (x), "rm" (-1));
    345#else
    346	asm("bsrl %1,%0\n\t"
    347	    "jnz 1f\n\t"
    348	    "movl $-1,%0\n"
    349	    "1:" : "=r" (r) : "rm" (x));
    350#endif
    351	return r + 1;
    352}
    353
    354/**
    355 * fls64 - find last set bit in a 64-bit word
    356 * @x: the word to search
    357 *
    358 * This is defined in a similar way as the libc and compiler builtin
    359 * ffsll, but returns the position of the most significant set bit.
    360 *
    361 * fls64(value) returns 0 if value is 0 or the position of the last
    362 * set bit if value is nonzero. The last (most significant) bit is
    363 * at position 64.
    364 */
    365#ifdef CONFIG_X86_64
    366static __always_inline int fls64(__u64 x)
    367{
    368	int bitpos = -1;
    369	/*
    370	 * AMD64 says BSRQ won't clobber the dest reg if x==0; Intel64 says the
    371	 * dest reg is undefined if x==0, but their CPU architect says its
    372	 * value is written to set it to the same as before.
    373	 */
    374	asm("bsrq %1,%q0"
    375	    : "+r" (bitpos)
    376	    : "rm" (x));
    377	return bitpos + 1;
    378}
    379#else
    380#include <asm-generic/bitops/fls64.h>
    381#endif
    382
    383#include <asm-generic/bitops/sched.h>
    384
    385#include <asm/arch_hweight.h>
    386
    387#include <asm-generic/bitops/const_hweight.h>
    388
    389#include <asm-generic/bitops/instrumented-atomic.h>
    390#include <asm-generic/bitops/instrumented-non-atomic.h>
    391#include <asm-generic/bitops/instrumented-lock.h>
    392
    393#include <asm-generic/bitops/le.h>
    394
    395#include <asm-generic/bitops/ext2-atomic-setbit.h>
    396
    397#endif /* __KERNEL__ */
    398#endif /* _ASM_X86_BITOPS_H */