[PATCH] um: Implement this_cpu_cmpxchg16b_emu()

From: Richard Weinberger
Date: Mon Apr 11 2011 - 13:22:38 EST


Commit 8a5ec0ba "Lockless (and preemptless) fastpaths for slub"
makes use of this_cpu_cmpxchg_double() which needs
this_cpu_cmpxchg16b_emu() on x86_64.
User Mode Linux has to serve this function too.

Reported-by: Sergei Trofimovich <slyich@xxxxxxxxx>
Signed-off-by: Richard Weinberger <richard@xxxxxx>
---
arch/um/sys-x86_64/Makefile | 2 +-
arch/um/sys-x86_64/cmpxchg16b_emu.S | 72 ++++++++++++++++++++++++++++++++
arch/um/sys-x86_64/cmpxchg16b_helper.c | 22 ++++++++++
3 files changed, 95 insertions(+), 1 deletions(-)
create mode 100644 arch/um/sys-x86_64/cmpxchg16b_emu.S
create mode 100644 arch/um/sys-x86_64/cmpxchg16b_helper.c

diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c1ea9eb..9a66afe 100644
--- a/arch/um/sys-x86_64/Makefile
+++ b/arch/um/sys-x86_64/Makefile
@@ -6,7 +6,7 @@

obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \
setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \
- sysrq.o ksyms.o tls.o
+ sysrq.o ksyms.o tls.o cmpxchg16b_emu.o cmpxchg16b_helper.o

subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o \
lib/rwsem_64.o
diff --git a/arch/um/sys-x86_64/cmpxchg16b_emu.S b/arch/um/sys-x86_64/cmpxchg16b_emu.S
new file mode 100644
index 0000000..170b6fa
--- /dev/null
+++ b/arch/um/sys-x86_64/cmpxchg16b_emu.S
@@ -0,0 +1,72 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Copyright 2011 Richard Weinberger <richard@xxxxxx>
+ * Mostly copied from arch/x86/lib/cmpxchg16b_emu.S
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+.text
+
+/*
+ * Inputs:
+ * %rsi : memory location to compare
+ * %rax : low 64 bits of old value
+ * %rdx : high 64 bits of old value
+ * %rbx : low 64 bits of new value
+ * %rcx : high 64 bits of new value
+ * %al : Operation successful
+ */
+ENTRY(this_cpu_cmpxchg16b_emu)
+CFI_STARTPROC
+
+#
+# Emulate 'cmpxchg16b %gs:(%rsi)' except we return the result in %al not
+# via the ZF. Caller will access %al to get result.
+#
+# Note that this is only useful for a cpuops operation. Meaning that we
+# do *not* have a fully atomic operation but just an operation that is
+# *atomic* on a single cpu (as provided by the this_cpu_xx class of
+# macros).
+#
+this_cpu_cmpxchg16b_emu:
+ pushq %rdi
+ pushq %rax
+ pushq %rdx
+ call arch_local_irq_save_asm
+ movq %rax, %rdi
+ popq %rdx
+ popq %rax
+
+ cmpq (%rsi), %rax
+ jne not_same
+ cmpq 8(%rsi), %rdx
+ jne not_same
+
+ movq %rbx, (%rsi)
+ movq %rcx, 8(%rsi)
+
+ mov $1, %al
+ jmp out
+
+ not_same:
+ xor %al,%al
+
+ out:
+ pushq %rax
+ pushq %rdx
+ call arch_local_irq_restore_asm
+ popq %rdx
+ popq %rax
+ popq %rdi
+ ret
+CFI_ENDPROC
+
+ENDPROC(this_cpu_cmpxchg16b_emu)
diff --git a/arch/um/sys-x86_64/cmpxchg16b_helper.c b/arch/um/sys-x86_64/cmpxchg16b_helper.c
new file mode 100644
index 0000000..b7e665c
--- /dev/null
+++ b/arch/um/sys-x86_64/cmpxchg16b_helper.c
@@ -0,0 +1,22 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ *
+ * Copyright 2011 Richard Weinberger <richard@xxxxxx>
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/system.h>
+
+asmlinkage unsigned long arch_local_irq_save_asm(void)
+{
+ return arch_local_irq_save();
+}
+
+asmlinkage void arch_local_irq_restore_asm(unsigned long flags)
+{
+ arch_local_irq_restore(flags);
+}
--
1.7.4.2

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/