diff --git a/sys/amd64/amd64/support.S b/sys/amd64/amd64/support.S index 8c55214..46f1ea5 100644 --- a/sys/amd64/amd64/support.S +++ b/sys/amd64/amd64/support.S @@ -671,49 +671,6 @@ ENTRY(longjmp) incl %eax ret -/*****************************************************************************/ -/* linux_futex support */ -/*****************************************************************************/ - -futex_fault: - movq $0,PCB_ONFAULT(%rcx) - movq $-EFAULT,%rax - ret - -ENTRY(futex_xchgl) - movq PCPU(CURPCB),%rcx - movq $futex_fault,PCB_ONFAULT(%rcx) - - movq $VM_MAXUSER_ADDRESS-4,%rax - cmpq %rax,%rsi - ja futex_fault - -#ifdef SMP - lock -#endif - xchgl %edi,(%rsi) - movl %edi,(%rdx) - xorl %eax,%eax - movq %rax,PCB_ONFAULT(%rcx) - ret - -ENTRY(futex_addl) - movq PCPU(CURPCB),%rcx - movq $futex_fault,PCB_ONFAULT(%rcx) - - movq $VM_MAXUSER_ADDRESS-4,%rax - cmpq %rax,%rsi - ja futex_fault - -#ifdef SMP - lock -#endif - xaddl %edi,(%rsi) - movl %edi,(%rdx) - xorl %eax,%eax - movq %rax,PCB_ONFAULT(%rcx) - ret - /* * Support for BB-profiling (gcc -a). The kernbb program will extract * the data from the kernel. diff --git a/sys/amd64/linux32/linux32_support.s b/sys/amd64/linux32/linux32_support.s new file mode 100644 index 0000000..42375c3 --- /dev/null +++ b/sys/amd64/linux32/linux32_support.s @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2007 Konstantin Belousov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "linux32_assym.h" /* system definitions */ +#include /* miscellaneous asm macros */ + +#include "assym.s" + +futex_fault: + movq $0,PCB_ONFAULT(%r8) + movl $-EFAULT,%eax + ret + +ENTRY(futex_xchgl) + movq PCPU(CURPCB),%r8 + movq $futex_fault,PCB_ONFAULT(%r8) + movq $VM_MAXUSER_ADDRESS-4,%rax + cmpq %rax,%rsi + ja futex_fault + xchgl %edi,(%rsi) + movl %edi,(%rdx) + xorl %eax,%eax + movq %rax,PCB_ONFAULT(%r8) + ret + +ENTRY(futex_addl) + movq PCPU(CURPCB),%r8 + movq $futex_fault,PCB_ONFAULT(%r8) + movq $VM_MAXUSER_ADDRESS-4,%rax + cmpq %rax,%rsi + ja futex_fault +#ifdef SMP + lock +#endif + xaddl %edi,(%rsi) + movl %edi,(%rdx) + xorl %eax,%eax + movq %rax,PCB_ONFAULT(%r8) + ret + +ENTRY(futex_orl) + movq PCPU(CURPCB),%r8 + movq $futex_fault,PCB_ONFAULT(%r8) + movq $VM_MAXUSER_ADDRESS-4,%rax + cmpq %rax,%rsi + ja futex_fault + movl (%rsi),%eax +1: movl %eax,%ecx + orl %edi,%ecx +#ifdef SMP + lock +#endif + cmpxchgl %ecx,(%rsi) + jnz 1b + movl %eax,(%rdx) + xorl %eax,%eax + movq %rax,PCB_ONFAULT(%r8) + ret + +ENTRY(futex_andl) + movq PCPU(CURPCB),%r8 + movq $futex_fault,PCB_ONFAULT(%r8) + movq $VM_MAXUSER_ADDRESS-4,%rax + cmpq %rax,%rsi + ja futex_fault + movl (%rsi),%eax +1: movl %eax,%ecx + andl %edi,%ecx +#ifdef SMP + lock +#endif + cmpxchgl %ecx,(%rsi) + jnz 1b + movl %eax,(%rdx) + xorl %eax,%eax + movq %rax,PCB_ONFAULT(%r8) + ret + +ENTRY(futex_xorl) + movq PCPU(CURPCB),%r8 + movq $futex_fault,PCB_ONFAULT(%r8) + movq $VM_MAXUSER_ADDRESS-4,%rax + cmpq %rax,%rsi + ja futex_fault + movl (%rsi),%eax +1: movl %eax,%ecx + xorl %edi,%ecx +#ifdef SMP + lock +#endif + cmpxchgl %ecx,(%rsi) + jnz 1b + movl %eax,(%rdx) + xorl %eax,%eax + movq %rax,PCB_ONFAULT(%r8) + ret diff --git a/sys/compat/linux/linux_futex.c b/sys/compat/linux/linux_futex.c index 3dff26d..576d4b8 100644 --- a/sys/compat/linux/linux_futex.c +++ b/sys/compat/linux/linux_futex.c @@ -90,13 +90,13 @@ static void futex_put(struct futex *); static int futex_sleep(struct futex *, struct thread *, unsigned long); static int futex_wake(struct futex *, int, struct futex *, int); static int futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr); -static int futex_orl(int oparg, caddr_t uaddr, int *oldval); -static int futex_andl(int oparg, caddr_t uaddr, int *oldval); -static int futex_xorl(int oparg, caddr_t uaddr, int *oldval); /* support.s */ int futex_xchgl(int oparg, caddr_t uaddr, int *oldval); int futex_addl(int oparg, caddr_t uaddr, int *oldval); +int futex_orl(int oparg, caddr_t uaddr, int *oldval); +int futex_andl(int oparg, caddr_t uaddr, int *oldval); +int futex_xorl(int oparg, caddr_t uaddr, int *oldval); int linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) @@ -114,8 +114,8 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) #ifdef DEBUG if (ldebug(sys_futex)) - printf(ARGS(futex, "%p, %i, %i"), args->uaddr, args->op, - args->val); + printf(ARGS(futex, "%p, %i, %i, *, %p, %i"), args->uaddr, args->op, + args->val, args->uaddr2, args->val3); #endif switch (args->op) { @@ -274,7 +274,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) #ifdef DEBUG if (ldebug(sys_futex)) printf("FUTEX_WAKE_OP: %d: uaddr = %p, op = %d, " - "val = %d, uaddr2 = %p, val3 = %d\n", + "val = %x, uaddr2 = %p, val3 = %x\n", td->td_proc->p_pid, args->uaddr, args->op, args->val, args->uaddr2, args->val3); #endif @@ -286,8 +286,11 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) * negative as errors */ op_ret = futex_atomic_op(td, args->val3, args->uaddr2); +#ifdef DEBUG + if (ldebug(sys_futex)) + printf("futex_atomic_op ret %d\n", op_ret); +#endif if (op_ret < 0) { - /* XXX: We don't handle the EFAULT yet. */ if (op_ret != -EFAULT) { futex_put(f); @@ -301,7 +304,6 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) FUTEX_SYSTEM_UNLOCK; return (EFAULT); - } ret = futex_wake(f, args->val, NULL, 0); @@ -327,7 +329,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args) args->op); break; } - return 0; + return (0); } static struct futex * @@ -401,9 +403,12 @@ futex_sleep(struct futex *f, struct thread *td, unsigned long timeout) TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); FUTEX_UNLOCK; + /* if we got woken up in futex_wake */ if ((ret == 0) && (wp->wp_new_futex != NULL)) { + /* suspend us on the new futex */ ret = futex_sleep(wp->wp_new_futex, td, timeout); - futex_put(wp->wp_new_futex); /* futex_get called in wakeup */ + /* and release the old one */ + futex_put(wp->wp_new_futex); } free(wp, M_LINUX); @@ -458,8 +463,10 @@ futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr) oparg = 1 << oparg; #ifdef DEBUG - printf("futex_atomic_op: op = %d, cmp = %d, oparg = %d, cmparg = %d, " - "uaddr = %p\n", op, cmp, oparg, cmparg, uaddr); + if (ldebug(sys_futex)) + printf("futex_atomic_op: op = %d, cmp = %d, oparg = %x, " + "cmparg = %x, uaddr = %p\n", + op, cmp, oparg, cmparg, uaddr); #endif /* XXX: linux verifies access here and returns EFAULT */ @@ -481,70 +488,26 @@ futex_atomic_op(struct thread *td, int encoded_op, caddr_t uaddr) break; default: ret = -ENOSYS; + break; } - if (!ret) - switch (cmp) { - case FUTEX_OP_CMP_EQ: - ret = (oldval == cmparg); - break; - case FUTEX_OP_CMP_NE: - ret = (oldval != cmparg); - break; - case FUTEX_OP_CMP_LT: - ret = (oldval < cmparg); - break; - case FUTEX_OP_CMP_GE: - ret = (oldval >= cmparg); - break; - case FUTEX_OP_CMP_LE: - ret = (oldval <= cmparg); - break; - case FUTEX_OP_CMP_GT: - ret = (oldval > cmparg); - break; - default: - ret = -ENOSYS; - } - - return (ret); -} - -static int -futex_orl(int oparg, caddr_t uaddr, int *oldval) -{ - uint32_t ua, ua_old; - - for (;;) { - ua = ua_old = fuword32(uaddr); - ua |= oparg; - if (casuword32((void *)uaddr, ua_old, ua) == ua_old) - return ua_old; - } -} - -static int -futex_andl(int oparg, caddr_t uaddr, int *oldval) -{ - uint32_t ua, ua_old; - - for (;;) { - ua = ua_old = fuword32(uaddr); - ua &= oparg; - if (casuword32((void *)uaddr, ua_old, ua) == ua_old) - return ua_old; - } -} - -static int -futex_xorl(int oparg, caddr_t uaddr, int *oldval) -{ - uint32_t ua, ua_old; - - for (;;) { - ua = ua_old = fuword32(uaddr); - ua ^= oparg; - if (casuword32((void *)uaddr, ua_old, ua) == ua_old) - return ua_old; + if (ret) + return (ret); + + switch (cmp) { + case FUTEX_OP_CMP_EQ: + return (oldval == cmparg); + case FUTEX_OP_CMP_NE: + return (oldval != cmparg); + case FUTEX_OP_CMP_LT: + return (oldval < cmparg); + case FUTEX_OP_CMP_GE: + return (oldval >= cmparg); + case FUTEX_OP_CMP_LE: + return (oldval <= cmparg); + case FUTEX_OP_CMP_GT: + return (oldval > cmparg); + default: + return (-ENOSYS); } } diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 60cbbd7..745a2d2 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -231,9 +231,10 @@ amd64/linux32/linux32_dummy.c optional compat_linux32 amd64/linux32/linux32_locore.s optional compat_linux32 \ dependency "linux32_assym.h" amd64/linux32/linux32_machdep.c optional compat_linux32 +amd64/linux32/linux32_support.s optional compat_linux32 amd64/linux32/linux32_sysent.c optional compat_linux32 amd64/linux32/linux32_sysvec.c optional compat_linux32 -compat/linux/linux_emul.c optional compat_linux32 +compat/linux/linux_emul.c optional compat_linux32 compat/linux/linux_file.c optional compat_linux32 compat/linux/linux_futex.c optional compat_linux32 compat/linux/linux_getcwd.c optional compat_linux32 diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 9a2ac37..ab991e5 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -345,6 +345,7 @@ i386/linux/linux_locore.s optional compat_linux \ dependency "linux_assym.h" i386/linux/linux_machdep.c optional compat_linux i386/linux/linux_ptrace.c optional compat_linux +i386/linux/linux_support.s optional compat_linux i386/linux/linux_sysent.c optional compat_linux i386/linux/linux_sysvec.c optional compat_linux i386/pci/pci_bus.c optional pci diff --git a/sys/i386/i386/support.s b/sys/i386/i386/support.s index 1e6de36..1828cdc 100644 --- a/sys/i386/i386/support.s +++ b/sys/i386/i386/support.s @@ -1513,51 +1513,6 @@ ENTRY(longjmp) incl %eax ret -/*****************************************************************************/ -/* linux_futex support */ -/*****************************************************************************/ - -futex_fault: - movl $0,PCB_ONFAULT(%ecx) - movl $-EFAULT,%eax - ret - -ENTRY(futex_xchgl) - movl PCPU(CURPCB),%ecx - movl $futex_fault,PCB_ONFAULT(%ecx) - movl 4(%esp),%eax - movl 8(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-4,%edx - ja futex_fault - -#ifdef SMP - lock -#endif - xchgl %eax,(%edx) - movl 12(%esp),%edx - movl %eax,(%edx) - xorl %eax,%eax - movl $0,PCB_ONFAULT(%ecx) - ret - -ENTRY(futex_addl) - movl PCPU(CURPCB),%ecx - movl $futex_fault,PCB_ONFAULT(%ecx) - movl 4(%esp),%eax - movl 8(%esp),%edx - cmpl $VM_MAXUSER_ADDRESS-4,%edx - ja futex_fault - -#ifdef SMP - lock -#endif - xaddl %eax,(%edx) - movl 12(%esp),%edx - movl %eax,(%edx) - xorl %eax,%eax - movl $0,PCB_ONFAULT(%ecx) - ret - /* * Support for BB-profiling (gcc -a). The kernbb program will extract * the data from the kernel. diff --git a/sys/i386/linux/linux_support.s b/sys/i386/linux/linux_support.s new file mode 100644 index 0000000..e073dc6 --- /dev/null +++ b/sys/i386/linux/linux_support.s @@ -0,0 +1,131 @@ +/*- + * Copyright (c) 2006,2007 Konstantin Belousov + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include "linux_assym.h" /* system definitions */ +#include /* miscellaneous asm macros */ + +#include "assym.s" + +/*****************************************************************************/ +/* linux_futex support */ +/*****************************************************************************/ + +futex_fault_decx: + movl PCPU(CURPCB),%ecx +futex_fault: + movl $0,PCB_ONFAULT(%ecx) + movl $-EFAULT,%eax + ret + +ENTRY(futex_xchgl) + movl PCPU(CURPCB),%ecx + movl $futex_fault,PCB_ONFAULT(%ecx) + movl 4(%esp),%eax + movl 8(%esp),%edx + cmpl $VM_MAXUSER_ADDRESS-4,%edx + ja futex_fault + xchgl %eax,(%edx) + movl 12(%esp),%edx + movl %eax,(%edx) + xorl %eax,%eax + movl %eax,PCB_ONFAULT(%ecx) + ret + +ENTRY(futex_addl) + movl PCPU(CURPCB),%ecx + movl $futex_fault,PCB_ONFAULT(%ecx) + movl 4(%esp),%eax + movl 8(%esp),%edx + cmpl $VM_MAXUSER_ADDRESS-4,%edx + ja futex_fault +#ifdef SMP + lock +#endif + xaddl %eax,(%edx) + movl 12(%esp),%edx + movl %eax,(%edx) + xorl %eax,%eax + movl %eax,PCB_ONFAULT(%ecx) + ret + +ENTRY(futex_orl) + movl PCPU(CURPCB),%ecx + movl $futex_fault_decx,PCB_ONFAULT(%ecx) + movl 8(%esp),%edx + cmpl $VM_MAXUSER_ADDRESS-4,%edx + ja futex_fault + movl (%edx),%eax +1: movl %eax,%ecx + orl 4(%esp),%ecx +#ifdef SMP + lock +#endif + cmpxchgl %ecx,(%edx) + jnz 1b +futex_tail: + movl 12(%esp),%edx + movl %eax,(%edx) + xorl %eax,%eax + movl PCPU(CURPCB),%ecx + movl %eax,PCB_ONFAULT(%ecx) + ret + +ENTRY(futex_andl) + movl PCPU(CURPCB),%ecx + movl $futex_fault_decx,PCB_ONFAULT(%ecx) + movl 8(%esp),%edx + cmpl $VM_MAXUSER_ADDRESS-4,%edx + ja futex_fault + movl (%edx),%eax +1: movl %eax,%ecx + andl 4(%esp),%ecx +#ifdef SMP + lock +#endif + cmpxchgl %ecx,(%edx) + jnz 1b + jmp futex_tail + +ENTRY(futex_xorl) + movl PCPU(CURPCB),%ecx + movl $futex_fault_decx,PCB_ONFAULT(%ecx) + movl 8(%esp),%edx + cmpl $VM_MAXUSER_ADDRESS-4,%edx + ja futex_fault + movl (%edx),%eax +1: movl %eax,%ecx + xorl 4(%esp),%ecx +#ifdef SMP + lock +#endif + cmpxchgl %ecx,(%edx) + jnz 1b + jmp futex_tail diff --git a/sys/modules/linux/Makefile b/sys/modules/linux/Makefile index ba57078..0672acd 100644 --- a/sys/modules/linux/Makefile +++ b/sys/modules/linux/Makefile @@ -1,5 +1,7 @@ # $FreeBSD: src/sys/modules/linux/Makefile,v 1.70 2006/10/29 14:02:39 netchild Exp $ +CFLAGS+=-DDEBUG + .if ${MACHINE_ARCH} == "amd64" SFX= 32 CFLAGS+=-DCOMPAT_IA32 -DCOMPAT_LINUX32 @@ -14,8 +16,12 @@ SRCS= linux${SFX}_dummy.c linux_emul.c linux_file.c \ linux_socket.c linux_stats.c linux_sysctl.c linux${SFX}_sysent.c \ linux${SFX}_sysvec.c linux_uid16.c linux_util.c linux_time.c \ opt_inet6.h opt_mac.h opt_compat.h opt_posix.h vnode_if.h \ - device_if.h bus_if.h -OBJS= linux${SFX}_locore.o + device_if.h bus_if.h assym.s + +# XXX: for assym.s +SRCS+= opt_kstack_pages.h opt_nfs.h opt_apic.h opt_compat.h + +OBJS= linux${SFX}_locore.o linux${SFX}_support.o .if ${MACHINE_ARCH} == "i386" SRCS+= linux_ptrace.c imgact_linux.c opt_cpu.h @@ -41,6 +47,10 @@ linux${SFX}_locore.o: linux${SFX}_locore.s linux${SFX}_assym.h ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ ${.IMPSRC} -o ${.TARGET} +linux${SFX}_support.o: linux${SFX}_support.s assym.s + ${CC} -c -x assembler-with-cpp -DLOCORE ${CFLAGS} \ + ${.IMPSRC} -o ${.TARGET} + linux${SFX}_genassym.o: linux${SFX}_genassym.c linux.h @ machine ${CC} -c ${CFLAGS:N-fno-common} ${.IMPSRC}