[PATCH] [RFC] um: x86: unbreak build by reintroducingthis_cpu_cmpxchg16b_emu

From: Sergei Trofimovich
Date: Wed Apr 06 2011 - 17:16:20 EST


I'm sure fix can be nices, but initial patch should express an idea.

The main offender is privileged 'cli'.

Thanks!

--

Sergei
From 59c59c76b0238ff2469bb7f4201b9b88ec436df4 Mon Sep 17 00:00:00 2001
From: Sergei Trofimovich <slyfox@xxxxxxxxxx>
Date: Thu, 7 Apr 2011 00:09:37 +0300
Subject: [PATCH] [RFC] um: x86: unbreak build by reintroducing this_cpu_cmpxchg16b_emu

LD .tmp_vmlinux1
mm/built-in.o: In function `slab_free':
/home/slyfox/linux-2.6/mm/slub.c:2148: undefined reference to `this_cpu_cmpxchg16b_emu'
/home/slyfox/linux-2.6/mm/slub.c:2148: undefined reference to `this_cpu_cmpxchg16b_emu'
mm/built-in.o: In function `slab_alloc':
/home/slyfox/linux-2.6/mm/slub.c:1943: undefined reference to `this_cpu_cmpxchg16b_emu'
/home/slyfox/linux-2.6/mm/slub.c:1943: undefined reference to `this_cpu_cmpxchg16b_emu'
/home/slyfox/linux-2.6/mm/slub.c:1943: undefined reference to `this_cpu_cmpxchg16b_emu'

Original implementation of this_cpu_cmpxchg16b_emu contained privileged 'cli' instruction
so copied implementation to private um/ space. Tested on x86_64, untested on i386.

Signed-off-by: Sergei Trofimovich <slyfox@xxxxxxxxxx>
---
arch/um/sys-i386/Makefile | 2 +-
arch/um/sys-i386/cmpxchg8b_emu_um.S | 56 ++++++++++++++++++++++++++++
arch/um/sys-x86_64/Makefile | 2 +-
arch/um/sys-x86_64/cmpxchg16b_emu_um.S | 64 ++++++++++++++++++++++++++++++++
4 files changed, 122 insertions(+), 2 deletions(-)
create mode 100644 arch/um/sys-i386/cmpxchg8b_emu_um.S
create mode 100644 arch/um/sys-x86_64/cmpxchg16b_emu_um.S

diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile
index 804b28d..40d7940 100644
--- a/arch/um/sys-i386/Makefile
+++ b/arch/um/sys-i386/Makefile
@@ -4,7 +4,7 @@

obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
- sys_call_table.o tls.o
+ sys_call_table.o tls.o cmpxchg8b_emu_um.o

obj-$(CONFIG_BINFMT_ELF) += elfcore.o

diff --git a/arch/um/sys-i386/cmpxchg8b_emu_um.S b/arch/um/sys-i386/cmpxchg8b_emu_um.S
new file mode 100644
index 0000000..b2f0d5f
--- /dev/null
+++ b/arch/um/sys-i386/cmpxchg8b_emu_um.S
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+
+.text
+
+/*
+ * Inputs:
+ * %esi : memory location to compare
+ * %eax : low 32 bits of old value
+ * %edx : high 32 bits of old value
+ * %ebx : low 32 bits of new value
+ * %ecx : high 32 bits of new value
+ */
+ENTRY(cmpxchg8b_emu)
+CFI_STARTPROC
+
+#
+# Emulate 'cmpxchg8b (%esi)' on UP except we don't
+# set the whole ZF thing (caller will just compare
+# eax:edx with the expected value)
+#
+cmpxchg8b_emu:
+ pushfl
+
+ cmpl (%esi), %eax
+ jne not_same
+ cmpl 4(%esi), %edx
+ jne half_same
+
+ movl %ebx, (%esi)
+ movl %ecx, 4(%esi)
+
+ popfl
+ ret
+
+ not_same:
+ movl (%esi), %eax
+ half_same:
+ movl 4(%esi), %edx
+
+ popfl
+ ret
+
+CFI_ENDPROC
+ENDPROC(cmpxchg8b_emu)
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile
index c1ea9eb..3259f54 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_um.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_um.S b/arch/um/sys-x86_64/cmpxchg16b_emu_um.S
new file mode 100644
index 0000000..e954084
--- /dev/null
+++ b/arch/um/sys-x86_64/cmpxchg16b_emu_um.S
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ *
+ */
+#include <linux/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+#ifdef CONFIG_SMP
+#define SEG_PREFIX %gs:
+#else
+#define SEG_PREFIX
+#endif
+
+.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:
+ pushf
+
+ cmpq SEG_PREFIX(%rsi), %rax
+ jne not_same
+ cmpq SEG_PREFIX 8(%rsi), %rdx
+ jne not_same
+
+ movq %rbx, SEG_PREFIX(%rsi)
+ movq %rcx, SEG_PREFIX 8(%rsi)
+
+ popf
+ mov $1, %al
+ ret
+
+ not_same:
+ popf
+ xor %al,%al
+ ret
+
+CFI_ENDPROC
+
+ENDPROC(this_cpu_cmpxchg16b_emu)
--
1.7.3.4

Attachment: signature.asc
Description: PGP signature