[kvm-unit-tests PATCH v2 4/8] x86: Expand the suite of bitops to cover all set/clear operations

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Provide atomic and non-atomic APIs for clearing and setting bits, along
with "test" versions to return the original value.  Don't bother with
"change" APIs, as they are highly unlikely to be needed.

Opportunistically move the existing definitions to bitops.h so that common
code can access the helpers.

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
 lib/x86/asm/bitops.h | 86 +++++++++++++++++++++++++++++++++++++++++---
 lib/x86/processor.h  | 12 -------
 2 files changed, 81 insertions(+), 17 deletions(-)

diff --git a/lib/x86/asm/bitops.h b/lib/x86/asm/bitops.h
index 54ec9c42..3ece1b67 100644
--- a/lib/x86/asm/bitops.h
+++ b/lib/x86/asm/bitops.h
@@ -13,12 +13,88 @@
 
 #define HAVE_BUILTIN_FLS 1
 
-static inline void test_and_set_bit(long nr, unsigned long *addr)
+/*
+ * Macros to generate condition code outputs from inline assembly,
+ * The output operand must be type "bool".
+ */
+#ifdef __GCC_ASM_FLAG_OUTPUTS__
+# define CC_SET(c) "\n\t/* output condition code " #c "*/\n"
+# define CC_OUT(c) "=@cc" #c
+#else
+# define CC_SET(c) "\n\tset" #c " %[_cc_" #c "]\n"
+# define CC_OUT(c) [_cc_ ## c] "=qm"
+#endif
+
+static inline void __clear_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+
+	__asm__ __volatile__("btr %1, %0"
+			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
+}
+
+static inline void __set_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+
+	__asm__ __volatile__("bts %1, %0"
+			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
+}
+
+static inline bool __test_and_clear_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+	bool v;
+
+	__asm__ __volatile__("btr %2, %1" CC_SET(c)
+			     : CC_OUT(c) (v), "+m" (*addr) : "Ir" (bit));
+	return v;
+}
+
+static inline bool __test_and_set_bit(int bit, void *__addr)
 {
-	asm volatile("lock; bts %1,%0"
-		     : "+m" (*addr)
-		     : "Ir" (nr)
-		     : "memory");
+	unsigned long *addr = __addr;
+	bool v;
+
+	__asm__ __volatile__("bts %2, %1" CC_SET(c)
+			     : CC_OUT(c) (v), "+m" (*addr) : "Ir" (bit));
+	return v;
+}
+
+static inline void clear_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+
+	__asm__ __volatile__("lock; btr %1, %0"
+			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
+}
+
+static inline void set_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+
+	__asm__ __volatile__("lock; bts %1, %0"
+			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
+}
+
+static inline bool test_and_clear_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+	bool v;
+
+	__asm__ __volatile__("lock; btr %2, %1" CC_SET(c)
+			     : CC_OUT(c) (v), "+m" (*addr) : "Ir" (bit));
+	return v;
+}
+
+static inline bool test_and_set_bit(int bit, void *__addr)
+{
+	unsigned long *addr = __addr;
+	bool v;
+
+	__asm__ __volatile__("lock; bts %2, %1" CC_SET(c)
+			     : CC_OUT(c) (v), "+m" (*addr) : "Ir" (bit));
+	return v;
 }
 
 #endif
diff --git a/lib/x86/processor.h b/lib/x86/processor.h
index a0be04c5..5bc9ef89 100644
--- a/lib/x86/processor.h
+++ b/lib/x86/processor.h
@@ -914,18 +914,6 @@ static inline bool is_canonical(u64 addr)
 	return (s64)(addr << shift_amt) >> shift_amt == addr;
 }
 
-static inline void clear_bit(int bit, u8 *addr)
-{
-	__asm__ __volatile__("lock; btr %1, %0"
-			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
-}
-
-static inline void set_bit(int bit, u8 *addr)
-{
-	__asm__ __volatile__("lock; bts %1, %0"
-			     : "+m" (*addr) : "Ir" (bit) : "cc", "memory");
-}
-
 static inline void flush_tlb(void)
 {
 	ulong cr4;
-- 
2.50.0.rc0.604.gd4ff7b7c86-goog





[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux