diff mbox

[RFC,1/5] KVM: introduce a set_bit function for bitmaps in user space

Message ID 20100409183021.843ca432.yoshikawa.takuya@oss.ntt.co.jp (mailing list archive)
State New, archived
Headers show

Commit Message

Takuya Yoshikawa April 9, 2010, 9:30 a.m. UTC
None
diff mbox

Patch

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index abd3e0e..25a694e 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -98,6 +98,43 @@  struct exception_table_entry {
 
 extern int fixup_exception(struct pt_regs *regs);
 
+/**
+ * set_bit_user: - Set a bit of a bitmap in user space.
+ * @nr:   Bit offset to set.
+ * @addr: Base address, in user space.
+ *
+ * Context: User context only.  This function may sleep.
+ *
+ * This macro sets a bit of a bitmap in user space. Note that this
+ * is same as __set_bit but not set_bit in the sense that setting
+ * the bit is not done atomically.
+ *
+ * Returns zero on success, -EFAULT on error.
+ */
+#define __set_bit_user_asm(nr, addr, err, errret)			\
+	asm volatile("1:	bts %1,%2\n"				\
+		     "2:\n"						\
+		     ".section .fixup,\"ax\"\n"				\
+		     "3:	mov %3,%0\n"				\
+		     "	jmp 2b\n"					\
+		     ".previous\n"					\
+		     _ASM_EXTABLE(1b, 3b)				\
+		     : "=r"(err)					\
+		     : "r" (nr), "m" (__m(addr)), "i" (errret), "0" (err))
+
+#define set_bit_user(nr, addr)						\
+({									\
+	int __ret_sbu = 0;						\
+									\
+	might_fault();							\
+	if (access_ok(VERIFY_WRITE, addr, nr/8 + 1))			\
+		__set_bit_user_asm(nr, addr, __ret_sbu, -EFAULT);	\
+	else								\
+		__ret_sbu = -EFAULT;					\
+									\
+	__ret_sbu;							\
+})
+
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.