2 * Jailhouse, a Linux-based partitioning hypervisor
4 * Copyright (c) Siemens AG, 2013
7 * Jan Kiszka <jan.kiszka@siemens.com>
9 * This work is licensed under the terms of the GNU GPL, version 2. See
10 * the COPYING file in the top-level directory.
13 #ifndef _JAILHOUSE_ASM_BITOPS_H
14 #define _JAILHOUSE_ASM_BITOPS_H
16 #include <jailhouse/types.h>
20 #define BITOPT_ALIGN(bits, addr) \
22 (addr) = (unsigned long *)((u32)(addr) & ~0x3) \
23 + (bits) / BITS_PER_LONG; \
24 (bits) %= BITS_PER_LONG; \
27 /* Load the cacheline in exclusive state */
28 #define PRELOAD(addr) \
29 asm volatile (".arch_extension mp\n\t" \
31 : "+Qo" (*(volatile unsigned long *)addr));
33 static inline __attribute__((always_inline)) void
34 clear_bit(int nr, volatile unsigned long *addr)
36 unsigned long ret, val;
38 BITOPT_ALIGN(nr, addr);
45 "strex %0, %1, %2\n\t"
46 : "=r" (ret), "=r" (val),
47 /* declare clobbering of this address to the compiler */
48 "+Qo" (*(volatile unsigned long *)addr)
53 static inline __attribute__((always_inline)) void
54 set_bit(unsigned int nr, volatile unsigned long *addr)
56 unsigned long ret, val;
58 BITOPT_ALIGN(nr, addr);
65 "strex %0, %1, %2\n\t"
66 : "=r" (ret), "=r" (val),
67 "+Qo" (*(volatile unsigned long *)addr)
72 static inline __attribute__((always_inline)) int
73 test_bit(unsigned int nr, const volatile unsigned long *addr)
75 return ((1UL << (nr % BITS_PER_LONG)) &
76 (addr[nr / BITS_PER_LONG])) != 0;
79 static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
81 unsigned long ret, val, test;
83 BITOPT_ALIGN(nr, addr);
92 "strex %0, %1, %3\n\t"
93 : "=r" (ret), "=r" (val), "=r" (test),
94 "+Qo" (*(volatile unsigned long *)addr)
102 /* Count leading zeroes */
103 static inline unsigned long clz(unsigned long word)
106 asm volatile ("clz %0, %1" : "=r" (val) : "r" (word));
110 /* Returns the position of the least significant 1, MSB=31, LSB=0*/
111 static inline unsigned long ffsl(unsigned long word)
115 asm volatile ("rbit %0, %0" : "+r" (word));
119 static inline unsigned long ffzl(unsigned long word)
124 /* Extend the value of 'size' bits to a signed long */
125 static inline unsigned long sign_extend(unsigned long val, unsigned int size)
129 if (size >= sizeof(unsigned long) * 8)
132 mask = 1U << (size - 1);
133 return (val ^ mask) - mask;
136 #endif /* !__ASSEMBLY__ */
137 #endif /* !_JAILHOUSE_ASM_BITOPS_H */