diff --git a/arch/x86/kernel/include/arch-bitops.h b/arch/x86/kernel/include/arch-bitops.h new file mode 100644 index 00000000..00682b14 --- /dev/null +++ b/arch/x86/kernel/include/arch-bitops.h @@ -0,0 +1,96 @@ +/** + * \file arch-bitops.h + * License details are found in the file LICENSE. + * \brief + * Find last set bit in word. + * \author Taku Shimosawa \par + * Copyright (C) 2011 - 2012 Taku Shimosawa + */ +/* + * HISTORY + */ + +#ifndef HEADER_X86_COMMON_ARCH_BITOPS_H +#define HEADER_X86_COMMON_ARCH_BITOPS_H + +static inline int fls(int x) +{ + int r; + asm("bsrl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" : "=r" (r) : "rm" (x)); + + return r + 1; +} + +/** + * ffs - find first set bit in word + * @x: the word to search + * + * This is defined the same way as the libc and compiler builtin ffs + * routines, therefore differs in spirit from the other bitops. + * + * ffs(value) returns 0 if value is 0 or the position of the first + * set bit if value is nonzero. The first (least significant) bit + * is at position 1. + */ +static inline int ffs(int x) +{ + int r; + asm("bsfl %1,%0\n\t" + "jnz 1f\n\t" + "movl $-1,%0\n" + "1:" : "=r" (r) : "rm" (x)); + return r + 1; +} + + +/** + * __ffs - find first set bit in word + * @word: The word to search + * + * Undefined if no bit exists, so code should check against 0 first. + */ +static inline unsigned long __ffs(unsigned long word) +{ + asm("bsf %1,%0" + : "=r" (word) + : "rm" (word)); + return word; +} + +/** + * ffz - find first zero bit in word + * @word: The word to search + * + * Undefined if no zero exists, so code should check against ~0UL first. + */ +static inline unsigned long ffz(unsigned long word) +{ + asm("bsf %1,%0" + : "=r" (word) + : "r" (~word)); + return word; +} + + +#define ADDR (*(volatile long *)addr) + +static inline void set_bit(int nr, volatile unsigned long *addr) +{ + asm volatile("lock; btsl %1,%0" + : "+m" (ADDR) + : "Ir" (nr) + : "memory"); +} + +static inline void clear_bit(int nr, volatile unsigned long *addr) +{ + asm volatile("lock; btrl %1,%0" + : "+m" (ADDR) + : "Ir" (nr) + : "memory"); +} + +#endif diff --git a/arch/x86/kernel/include/ihk/types.h b/arch/x86/kernel/include/ihk/types.h index 2d44b196..9f000a96 100644 --- a/arch/x86/kernel/include/ihk/types.h +++ b/arch/x86/kernel/include/ihk/types.h @@ -31,9 +31,5 @@ typedef int64_t off_t; #define NULL ((void *)0) -#define BITS_PER_LONG_SHIFT 6 -#define BITS_PER_LONG (1 << BITS_PER_LONG_SHIFT) - - #endif diff --git a/arch/x86/kernel/include/bitops.h b/lib/bitops.c similarity index 53% rename from arch/x86/kernel/include/bitops.h rename to lib/bitops.c index 72aca0ca..6be43cd7 100644 --- a/arch/x86/kernel/include/bitops.h +++ b/lib/bitops.c @@ -1,109 +1,12 @@ -/** - * \file bitops.h - * License details are found in the file LICENSE. - * \brief - * Find last set bit in word. - * \author Taku Shimosawa \par - * Copyright (C) 2011 - 2012 Taku Shimosawa - */ -/* - * HISTORY - */ - -#ifndef HEADER_X86_COMMON_BITOPS_H -#define HEADER_X86_COMMON_BITOPS_H - -static inline int fls(int x) -{ - int r; - asm("bsrl %1,%0\n\t" - "jnz 1f\n\t" - "movl $-1,%0\n" - "1:" : "=r" (r) : "rm" (x)); - - return r + 1; -} - -/** - * ffs - find first set bit in word - * @x: the word to search - * - * This is defined the same way as the libc and compiler builtin ffs - * routines, therefore differs in spirit from the other bitops. - * - * ffs(value) returns 0 if value is 0 or the position of the first - * set bit if value is nonzero. The first (least significant) bit - * is at position 1. - */ -static inline int ffs(int x) -{ - int r; - asm("bsfl %1,%0\n\t" - "jnz 1f\n\t" - "movl $-1,%0\n" - "1:" : "=r" (r) : "rm" (x)); - return r + 1; -} - - -/** - * __ffs - find first set bit in word - * @word: The word to search - * - * Undefined if no bit exists, so code should check against 0 first. - */ -static inline unsigned long __ffs(unsigned long word) -{ - asm("bsf %1,%0" - : "=r" (word) - : "rm" (word)); - return word; -} - -/** - * ffz - find first zero bit in word - * @word: The word to search - * - * Undefined if no zero exists, so code should check against ~0UL first. - */ -static inline unsigned long ffz(unsigned long word) -{ - asm("bsf %1,%0" - : "=r" (word) - : "r" (~word)); - return word; -} - - -#define ADDR (*(volatile long *)addr) - -static inline void set_bit(int nr, volatile unsigned long *addr) -{ - asm volatile("lock; btsl %1,%0" - : "+m" (ADDR) - : "Ir" (nr) - : "memory"); -} - -static inline void clear_bit(int nr, volatile unsigned long *addr) -{ - asm volatile("lock; btrl %1,%0" - : "+m" (ADDR) - : "Ir" (nr) - : "memory"); -} - -#define for_each_set_bit(bit, addr, size) \ - for ((bit) = find_first_bit((addr), (size)); \ - (bit) < (size); \ - (bit) = find_next_bit((addr), (size), (bit) + 1)) +/* bitops.c COPYRIGHT FUJITSU LIMITED 2014 */ +#include #define BITOP_WORD(nr) ((nr) / BITS_PER_LONG) /* * Find the next set bit in a memory region. */ -static unsigned long find_next_bit(const unsigned long *addr, unsigned long size, +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + BITOP_WORD(offset); @@ -146,7 +49,7 @@ found_middle: * This implementation of find_{first,next}_zero_bit was stolen from * Linus' asm-alpha/bitops.h. */ -static unsigned long find_next_zero_bit(const unsigned long *addr, +unsigned long find_next_zero_bit(const unsigned long *addr, unsigned long size, unsigned long offset) { const unsigned long *p = addr + BITOP_WORD(offset); @@ -188,7 +91,7 @@ found_middle: /* * Find the first set bit in a memory region. */ -static unsigned long find_first_bit(const unsigned long *addr, +unsigned long find_first_bit(const unsigned long *addr, unsigned long size) { const unsigned long *p = addr; @@ -214,7 +117,7 @@ found: /* * Find the first cleared bit in a memory region. */ -static unsigned long find_first_zero_bit(const unsigned long *addr, +unsigned long find_first_zero_bit(const unsigned long *addr, unsigned long size) { const unsigned long *p = addr; @@ -237,4 +140,3 @@ found: return result + ffz(tmp); } -#endif diff --git a/lib/include/bitops-__ffs.h b/lib/include/bitops-__ffs.h new file mode 100644 index 00000000..6cc4152f --- /dev/null +++ b/lib/include/bitops-__ffs.h @@ -0,0 +1,37 @@ +/* bitops-__ffs.h COPYRIGHT FUJITSU LIMITED 2014 */ +#ifndef INCLUDE_BITOPS___FFS_H +#define INCLUDE_BITOPS___FFS_H + +static inline unsigned long __ffs(unsigned long word) +{ + int num = 0; + + if (BITS_PER_LONG == 64) { + if ((word & 0xffffffff) == 0) { + num += 32; + word >>= 32; + } + } + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +#endif diff --git a/lib/include/bitops-clear_bit.h b/lib/include/bitops-clear_bit.h new file mode 100644 index 00000000..4db6869f --- /dev/null +++ b/lib/include/bitops-clear_bit.h @@ -0,0 +1,14 @@ +/* bitops-clear_bit.h COPYRIGHT FUJITSU LIMITED 2014 */ +#ifndef INCLUDE_BITOPS_CLEAR_BIT_H +#define INCLUDE_BITOPS_CLEAR_BIT_H + +static inline void clear_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + unsigned long *p = ((unsigned long *)addr) + (nr / BITS_PER_LONG); + + *p &= ~mask; +} + +#endif + diff --git a/lib/include/bitops-ffz.h b/lib/include/bitops-ffz.h new file mode 100644 index 00000000..e07afefe --- /dev/null +++ b/lib/include/bitops-ffz.h @@ -0,0 +1,8 @@ +/* bitops-ffz.h COPYRIGHT FUJITSU LIMITED 2014 */ +#ifndef INCLUDE_BITOPS_FFZ_H +#define INCLUDE_BITOPS_FFZ_H + +#define ffz(x) __ffs(~(x)) + +#endif + diff --git a/lib/include/bitops-fls.h b/lib/include/bitops-fls.h new file mode 100644 index 00000000..a0abe9ac --- /dev/null +++ b/lib/include/bitops-fls.h @@ -0,0 +1,36 @@ +/* bitops-fls.h COPYRIGHT FUJITSU LIMITED 2014 */ +#ifndef INCLUDE_BITOPS_FLS_H +#define INCLUDE_BITOPS_FLS_H + +static inline int fls(int x) +{ + int r = 32; + if (!x) { + return 0; + } + + if (!(x & 0xffff0000u)) { + x <<= 16; + r -= 16; + } + if (!(x & 0xff000000u)) { + x <<= 8; + r -= 8; + } + if (!(x & 0xf0000000u)) { + x <<= 4; + r -= 4; + } + if (!(x & 0xc0000000u)) { + x <<= 2; + r -= 2; + } + if (!(x & 0x80000000u)) { + x <<= 1; + r -= 1; + } + return r; +} + +#endif + diff --git a/lib/include/bitops-set_bit.h b/lib/include/bitops-set_bit.h new file mode 100644 index 00000000..fb2b8e88 --- /dev/null +++ b/lib/include/bitops-set_bit.h @@ -0,0 +1,14 @@ +/* bitops-set_bit.h COPYRIGHT FUJITSU LIMITED 2014 */ +#ifndef INCLUDE_BITOPS_SET_BIT_H +#define INCLUDE_BITOPS_SET_BIT_H + +static inline void set_bit(int nr, volatile unsigned long *addr) +{ + unsigned long mask = (1UL << (nr % BITS_PER_LONG)); + unsigned long *p = ((unsigned long *)addr) + (nr / BITS_PER_LONG); + + *p |= mask; +} + +#endif + diff --git a/lib/include/bitops.h b/lib/include/bitops.h new file mode 100644 index 00000000..11be8d74 --- /dev/null +++ b/lib/include/bitops.h @@ -0,0 +1,35 @@ +/* bitops.h COPYRIGHT FUJITSU LIMITED 2014 */ +#ifndef INCLUDE_BITOPS_H +#define INCLUDE_BITOPS_H + +#include + +#define __BITS_TO_LONGS(n,d) (((n) + (d) - 1) / (d)) +#define BITS_TO_LONGS(nr) __BITS_TO_LONGS(nr, BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) unsigned long name[BITS_TO_LONGS(bits)] + +#define for_each_set_bit(bit, addr, size) \ + for ((bit) = find_first_bit((addr), (size)); \ + (bit) < (size); \ + (bit) = find_next_bit((addr), (size), (bit) + 1)) + +#ifndef __ASSEMBLY__ + +unsigned long find_next_bit(const unsigned long *addr, unsigned long size, + unsigned long offset); + +unsigned long find_next_zero_bit(const unsigned long *addr, + unsigned long size, unsigned long offset); + +unsigned long find_first_bit(const unsigned long *addr, + unsigned long size); + +unsigned long find_first_zero_bit(const unsigned long *addr, + unsigned long size); + +#endif /*__ASSEMBLY__*/ + +#include + +#endif /*INCLUDE_BITOPS_H*/ + diff --git a/lib/include/types.h b/lib/include/types.h index dab987fb..703a706c 100644 --- a/lib/include/types.h +++ b/lib/include/types.h @@ -13,7 +13,9 @@ #ifndef TYPES_H #define TYPES_H +#define BITS_PER_BYTE 8 +#define BITS_PER_LONG (sizeof(long) * BITS_PER_BYTE) + #include #endif -