From 59c59c76b0238ff2469bb7f4201b9b88ec436df4 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich 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 --- 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 +#include +#include +#include + + +.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 +#include +#include +#include + +#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