mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
xen/riscv: introduce bitops.h
Taken from Linux-6.4.0-rc1
Xen's bitops.h consists of several Linux's headers:
* linux/arch/include/asm/bitops.h:
* The following function were removed as they aren't used in Xen:
* test_and_set_bit_lock
* clear_bit_unlock
* __clear_bit_unlock
* The following functions were renamed in the way how they are
used by common code:
* __test_and_set_bit
* __test_and_clear_bit
* The declaration and implementation of the following functios
were updated to make Xen build happy:
* clear_bit
* set_bit
* __test_and_clear_bit
* __test_and_set_bit
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Acked-by: Jan Beulich <jbeulich@suse.com>
This commit is contained in:
1 parent
f1879b2c25
commit
bf34f99c33
1 file changed
+137
@@ -0,0 +1,137 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2012 Regents of the University of California */
|
||||
|
||||
#ifndef _ASM_RISCV_BITOPS_H
|
||||
#define _ASM_RISCV_BITOPS_H
|
||||
|
||||
#include <asm/system.h>
|
||||
|
||||
#if BITOP_BITS_PER_WORD == 64
|
||||
#define __AMO(op) "amo" #op ".d"
|
||||
#elif BITOP_BITS_PER_WORD == 32
|
||||
#define __AMO(op) "amo" #op ".w"
|
||||
#else
|
||||
#error "Unexpected BITOP_BITS_PER_WORD"
|
||||
#endif
|
||||
|
||||
/* Based on linux/arch/include/asm/bitops.h */
|
||||
|
||||
/*
|
||||
* Non-atomic bit manipulation.
|
||||
*
|
||||
* Implemented using atomics to be interrupt safe. Could alternatively
|
||||
* implement with local interrupt masking.
|
||||
*/
|
||||
#define __set_bit(n, p) set_bit(n, p)
|
||||
#define __clear_bit(n, p) clear_bit(n, p)
|
||||
|
||||
#define test_and_op_bit_ord(op, mod, nr, addr, ord) \
|
||||
({ \
|
||||
bitop_uint_t res, mask; \
|
||||
mask = BITOP_MASK(nr); \
|
||||
asm volatile ( \
|
||||
__AMO(op) #ord " %0, %2, %1" \
|
||||
: "=r" (res), "+A" (addr[BITOP_WORD(nr)]) \
|
||||
: "r" (mod(mask)) \
|
||||
: "memory"); \
|
||||
((res & mask) != 0); \
|
||||
})
|
||||
|
||||
#define op_bit_ord(op, mod, nr, addr, ord) \
|
||||
asm volatile ( \
|
||||
__AMO(op) #ord " zero, %1, %0" \
|
||||
: "+A" (addr[BITOP_WORD(nr)]) \
|
||||
: "r" (mod(BITOP_MASK(nr))) \
|
||||
: "memory");
|
||||
|
||||
#define test_and_op_bit(op, mod, nr, addr) \
|
||||
test_and_op_bit_ord(op, mod, nr, addr, .aqrl)
|
||||
#define op_bit(op, mod, nr, addr) \
|
||||
op_bit_ord(op, mod, nr, addr, )
|
||||
|
||||
/* Bitmask modifiers */
|
||||
#define NOP(x) (x)
|
||||
#define NOT(x) (~(x))
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline bool test_and_set_bit(int nr, volatile void *p)
|
||||
{
|
||||
volatile bitop_uint_t *addr = p;
|
||||
|
||||
return test_and_op_bit(or, NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline bool test_and_clear_bit(int nr, volatile void *p)
|
||||
{
|
||||
volatile bitop_uint_t *addr = p;
|
||||
|
||||
return test_and_op_bit(and, NOT, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Toggle (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 bool test_and_change_bit(int nr, volatile void *p)
|
||||
{
|
||||
volatile bitop_uint_t *addr = p;
|
||||
|
||||
return test_and_op_bit(xor, NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* set_bit - Atomically set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*
|
||||
* 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 void *p)
|
||||
{
|
||||
volatile bitop_uint_t *addr = p;
|
||||
|
||||
op_bit(or, NOP, nr, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit(int nr, volatile void *p)
|
||||
{
|
||||
volatile bitop_uint_t *addr = p;
|
||||
|
||||
op_bit(and, NOT, nr, addr);
|
||||
}
|
||||
|
||||
#undef test_and_op_bit
|
||||
#undef op_bit
|
||||
#undef NOP
|
||||
#undef NOT
|
||||
#undef __AMO
|
||||
|
||||
#endif /* _ASM_RISCV_BITOPS_H */
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
* c-file-style: "BSD"
|
||||
* c-basic-offset: 4
|
||||
* indent-tabs-mode: nil
|
||||
* End:
|
||||
*/
|
||||