Author: kib
Date: Tue Nov 18 12:53:32 2014
New Revision: 274648
URL: https://svnweb.freebsd.org/changeset/base/274648

Log:
  Merge the fueword(9) and casueword(9).  In particular,
  
  MFC r273783:
  Add fueword(9) and casueword(9) functions.
  MFC note: ia64 is handled like arm, with NO_FUEWORD define.
  
  MFC r273784:
  Replace some calls to fuword() by fueword() with proper error checking.
  
  MFC r273785:
  Convert kern_umtx.c to use fueword() and casueword().
  MFC note: the sys__umtx_lock and sys__umtx_unlock syscalls are not
  converted, they are removed from HEAD, and not used.  The do_sem2*()
  family is not yet merged to stable/10, corresponding chunk will be
  merged after do_sem2* are committed.
  
  MFC r273788 (by jkim):
  Actually install casuword(9) to fix build.
  
  MFC r273911:
  Add type qualifier volatile to the base (userspace) address argument
  of fuword(9) and suword(9).

Added:
  stable/10/share/man/man9/casuword.9
     - copied unchanged from r273783, head/share/man/man9/casuword.9
Modified:
  stable/10/share/man/man9/Makefile
  stable/10/share/man/man9/fetch.9
  stable/10/share/man/man9/store.9
  stable/10/sys/amd64/amd64/support.S
  stable/10/sys/amd64/ia32/ia32_syscall.c
  stable/10/sys/arm/include/param.h
  stable/10/sys/compat/freebsd32/freebsd32_misc.c
  stable/10/sys/i386/i386/support.s
  stable/10/sys/i386/i386/trap.c
  stable/10/sys/ia64/include/param.h
  stable/10/sys/kern/kern_exec.c
  stable/10/sys/kern/kern_umtx.c
  stable/10/sys/kern/subr_uio.c
  stable/10/sys/kern/vfs_acl.c
  stable/10/sys/mips/include/param.h
  stable/10/sys/net/if_spppsubr.c
  stable/10/sys/powerpc/powerpc/copyinout.c
  stable/10/sys/sparc64/include/param.h
  stable/10/sys/sys/systm.h
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/share/man/man9/Makefile
==============================================================================
--- stable/10/share/man/man9/Makefile   Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/share/man/man9/Makefile   Tue Nov 18 12:53:32 2014        
(r274648)
@@ -46,6 +46,7 @@ MAN=  accept_filter.9 \
        BUS_SETUP_INTR.9 \
        bus_space.9 \
        byteorder.9 \
+       casuword.9 \
        cd.9 \
        condvar.9 \
        config_intrhook.9 \
@@ -566,6 +567,9 @@ MLINKS+=condvar.9 cv_broadcast.9 \
 MLINKS+=config_intrhook.9 config_intrhook_disestablish.9 \
        config_intrhook.9 config_intrhook_establish.9
 MLINKS+=contigmalloc.9 contigfree.9
+MLINKS+=casuword.9 casueword.9 \
+       casuword.9 casueword32.9 \
+       casuword.9 casuword32.9
 MLINKS+=copy.9 copyin.9 \
        copy.9 copyin_nofault.9 \
        copy.9 copyinstr.9 \
@@ -668,7 +672,10 @@ MLINKS+=fetch.9 fubyte.9 \
        fetch.9 fuword.9 \
        fetch.9 fuword16.9 \
        fetch.9 fuword32.9 \
-       fetch.9 fuword64.9
+       fetch.9 fuword64.9 \
+       fetch.9 fueword.9 \
+       fetch.9 fueword32.9 \
+       fetch.9 fueword64.9
 MLINKS+=fpu_kern.9 fpu_kern_alloc_ctx.9 \
        fpu_kern.9 fpu_kern_free_ctx.9 \
        fpu_kern.9 fpu_kern_enter.9 \

Copied: stable/10/share/man/man9/casuword.9 (from r273783, 
head/share/man/man9/casuword.9)
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ stable/10/share/man/man9/casuword.9 Tue Nov 18 12:53:32 2014        
(r274648, copy of r273783, head/share/man/man9/casuword.9)
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2014 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" Part of this documentation was written by
+.\" Konstantin Belousov <k...@freebsd.org> under sponsorship
+.\" from the FreeBSD Foundation.
+.\"
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS 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 AUTHORS 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$
+.\"
+.Dd October 21, 2014
+.Dt CASU 9
+.Os
+.Sh NAME
+.Nm casueword ,
+.Nm casueword32 ,
+.Nm casuword ,
+.Nm casuword32
+.Nd fetch, compare and store data from user-space
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/systm.h
+.Ft int
+.Fn casueword "volatile u_long *base" "u_long oldval" "u_long *oldvalp" 
"u_long newval"
+.Ft int
+.Fn casueword32 "volatile uint32_t *base" "uint32_t oldval" "uint32_t 
*oldvalp" "uint32_t newval"
+.Ft u_long
+.Fn casuword "volatile u_long *base" "u_long oldval" "u_long newval"
+.Ft uint32_t
+.Fn casuword32 "volatile uint32_t *base" "uint32_t oldval" "uint32_t newval"
+.Sh DESCRIPTION
+The
+.Nm
+functions are designed to perform atomic compare-and-swap operation on
+the value in the usermode memory of the current process.
+.Pp
+The
+.Nm
+routines reads the value from user memory with address
+.Pa base ,
+and compare the value read with
+.Pa oldval .
+If the values are equal,
+.Pa newval
+is written to the
+.Pa *base .
+In case of
+.Fn casueword32
+and
+.Fn casueword ,
+old value is stored into the (kernel-mode) variable pointed by
+.Pa *oldvalp .
+The userspace value must be naturally aligned.
+.Pp
+The callers of
+.Fn casuword
+and
+.Fn casuword32
+functions cannot distinguish between -1 read from
+userspace and function failure.
+.Sh RETURN VALUES
+The
+.Fn casuword
+and
+.Fn casuword32
+functions return the data fetched or -1 on failure.
+The
+.Fn casueword
+and
+.Fn casueword32
+functions return 0 on success and -1 on failure.
+.Sh SEE ALSO
+.Xr atomic 9 ,
+.Xr fetch 9 ,
+.Xr store 9

Modified: stable/10/share/man/man9/fetch.9
==============================================================================
--- stable/10/share/man/man9/fetch.9    Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/share/man/man9/fetch.9    Tue Nov 18 12:53:32 2014        
(r274648)
@@ -34,7 +34,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 5, 2009
+.Dd October 29, 2014
 .Dt FETCH 9
 .Os
 .Sh NAME
@@ -44,43 +44,56 @@
 .Nm fuword ,
 .Nm fuword16 ,
 .Nm fuword32 ,
-.Nm fuword64
+.Nm fuword64 ,
+.Nm fueword ,
+.Nm fueword32 ,
+.Nm fueword64
 .Nd fetch data from user-space
 .Sh SYNOPSIS
 .In sys/types.h
-.In sys/time.h
 .In sys/systm.h
 .Ft int
-.Fn fubyte "const void *base"
+.Fn fubyte "volatile const void *base"
 .Ft long
-.Fn fuword "const void *base"
+.Fn fuword "volatile const void *base"
 .Ft int
-.Fn fuword16 "void *base"
+.Fn fuword16 "volatile const void *base"
 .Ft int32_t
-.Fn fuword32 "const void *base"
+.Fn fuword32 "volatile const void *base"
 .Ft int64_t
-.Fn fuword64 "const void *base"
+.Fn fuword64 "volatile const void *base"
+.Ft long
+.Fn fueword "volatile const void *base" "long *val"
+.Ft int32_t
+.Fn fueword32 "volatile const void *base" "int32_t *val"
+.Ft int64_t
+.Fn fueword64 "volatile const void *base" "int64_t *val"
 .In sys/resourcevar.h
 .Ft int
 .Fn fuswintr "void *base"
 .Sh DESCRIPTION
 The
 .Nm
-functions are designed to copy small amounts of data from user-space.
+functions are designed to copy small amounts of data from user-space
+of the current process.
+If read is successful, it is performed atomically.
+The data read must be naturally aligned.
 .Pp
 The
 .Nm
 routines provide the following functionality:
-.Bl -tag -width "fuswintr()"
+.Bl -tag -width "fueword32()"
 .It Fn fubyte
 Fetches a byte of data from the user-space address
 .Pa base .
+The byte read is zero-extended into the results variable.
 .It Fn fuword
-Fetches a word of data from the user-space address
+Fetches a word of data (long) from the user-space address
 .Pa base .
 .It Fn fuword16
 Fetches 16 bits of data from the user-space address
 .Pa base .
+The half-word read is zero-extended into the results variable.
 .It Fn fuword32
 Fetches 32 bits of data from the user-space address
 .Pa base .
@@ -91,11 +104,46 @@ Fetches 64 bits of data from the user-sp
 Fetches a short word of data from the user-space address
 .Pa base .
 This function is safe to call during an interrupt context.
+.It Fn fueword
+Fetches a word of data (long) from the user-space address
+.Pa base
+and stores the result in the variable pointed by
+.Pa val .
+.It Fn fueword32
+Fetches 32 bits of data from the user-space address
+.Pa base
+and stores the result in the variable pointed by
+.Pa val .
+.It Fn fueword64
+Fetches 64 bits of data from the user-space address
+.Pa base
+and stores the result in the variable pointed by
+.Pa val .
 .El
+.Pp
+The callers of
+.Fn fuword ,
+.Fn fuword32
+and
+.Fn fuword64
+functions cannot distinguish between -1 read from
+userspace and function failure.
 .Sh RETURN VALUES
 The
-.Nm
+.Fn fubyte ,
+.Fn fuword ,
+.Fn fuword16 ,
+.Fn fuword32 ,
+.Fn fuword64 ,
+and
+.Fn fuswintr
 functions return the data fetched or -1 on failure.
+The
+.Fn fueword ,
+.Fn fueword32
+and
+.Fn fueword64
+functions return 0 on success and -1 on failure.
 .Sh SEE ALSO
 .Xr copy 9 ,
 .Xr store 9

Modified: stable/10/share/man/man9/store.9
==============================================================================
--- stable/10/share/man/man9/store.9    Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/share/man/man9/store.9    Tue Nov 18 12:53:32 2014        
(r274648)
@@ -34,7 +34,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 5, 2009
+.Dd October 29, 2014
 .Dt STORE 9
 .Os
 .Sh NAME
@@ -48,15 +48,15 @@
 .In sys/time.h
 .In sys/systm.h
 .Ft int
-.Fn subyte "void *base" "int byte"
+.Fn subyte "volatile void *base" "int byte"
 .Ft int
-.Fn suword "void *base" "long word"
+.Fn suword "volatile void *base" "long word"
 .Ft int
-.Fn suword16 "void *base" "int word"
+.Fn suword16 "volatile void *base" "int word"
 .Ft int
-.Fn suword32 "void *base" "int32_t word"
+.Fn suword32 "volatile void *base" "int32_t word"
 .Ft int
-.Fn suword64 "void *base" "int64_t word"
+.Fn suword64 "volatile void *base" "int64_t word"
 .In sys/resourcevar.h
 .Ft int
 .Fn suswintr "void *base" "int word"
@@ -64,6 +64,8 @@
 The
 .Nm
 functions are designed to copy small amounts of data to user-space.
+If write is successful, it is performed atomically.
+The data written must be naturally aligned.
 .Pp
 The
 .Nm

Modified: stable/10/sys/amd64/amd64/support.S
==============================================================================
--- stable/10/sys/amd64/amd64/support.S Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/amd64/amd64/support.S Tue Nov 18 12:53:32 2014        
(r274648)
@@ -312,12 +312,13 @@ copyin_fault:
 END(copyin)
 
 /*
- * casuword32.  Compare and set user integer.  Returns -1 or the current value.
- *        dst = %rdi, old = %rsi, new = %rdx
+ * casueword32.  Compare and set user integer.  Returns -1 on fault,
+ *        0 if access was successful.  Old value is written to *oldp.
+ *        dst = %rdi, old = %esi, oldp = %rdx, new = %ecx
  */
-ENTRY(casuword32)
-       movq    PCPU(CURPCB),%rcx
-       movq    $fusufault,PCB_ONFAULT(%rcx)
+ENTRY(casueword32)
+       movq    PCPU(CURPCB),%r8
+       movq    $fusufault,PCB_ONFAULT(%r8)
 
        movq    $VM_MAXUSER_ADDRESS-4,%rax
        cmpq    %rax,%rdi                       /* verify address is valid */
@@ -327,26 +328,34 @@ ENTRY(casuword32)
 #ifdef SMP
        lock
 #endif
-       cmpxchgl %edx,(%rdi)                    /* new = %edx */
+       cmpxchgl %ecx,(%rdi)                    /* new = %ecx */
 
        /*
         * The old value is in %eax.  If the store succeeded it will be the
         * value we expected (old) from before the store, otherwise it will
-        * be the current value.
+        * be the current value.  Save %eax into %esi to prepare the return
+        * value.
         */
+       movl    %eax,%esi
+       xorl    %eax,%eax
+       movq    %rax,PCB_ONFAULT(%r8)
 
-       movq    PCPU(CURPCB),%rcx
-       movq    $0,PCB_ONFAULT(%rcx)
+       /*
+        * Access the oldp after the pcb_onfault is cleared, to correctly
+        * catch corrupted pointer.
+        */
+       movl    %esi,(%rdx)                     /* oldp = %rdx */
        ret
-END(casuword32)
+END(casueword32)
 
 /*
- * casuword.  Compare and set user word.  Returns -1 or the current value.
- *        dst = %rdi, old = %rsi, new = %rdx
+ * casueword.  Compare and set user long.  Returns -1 on fault,
+ *        0 if access was successful.  Old value is written to *oldp.
+ *        dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx
  */
-ENTRY(casuword)
-       movq    PCPU(CURPCB),%rcx
-       movq    $fusufault,PCB_ONFAULT(%rcx)
+ENTRY(casueword)
+       movq    PCPU(CURPCB),%r8
+       movq    $fusufault,PCB_ONFAULT(%r8)
 
        movq    $VM_MAXUSER_ADDRESS-4,%rax
        cmpq    %rax,%rdi                       /* verify address is valid */
@@ -356,28 +365,28 @@ ENTRY(casuword)
 #ifdef SMP
        lock
 #endif
-       cmpxchgq %rdx,(%rdi)                    /* new = %rdx */
+       cmpxchgq %rcx,(%rdi)                    /* new = %rcx */
 
        /*
-        * The old value is in %eax.  If the store succeeded it will be the
+        * The old value is in %rax.  If the store succeeded it will be the
         * value we expected (old) from before the store, otherwise it will
         * be the current value.
         */
-
-       movq    PCPU(CURPCB),%rcx
-       movq    $fusufault,PCB_ONFAULT(%rcx)
-       movq    $0,PCB_ONFAULT(%rcx)
+       movq    %rax,%rsi
+       xorl    %eax,%eax
+       movq    %rax,PCB_ONFAULT(%r8)
+       movq    %rsi,(%rdx)
        ret
-END(casuword)
+END(casueword)
 
 /*
  * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
- * byte from user memory.  All these functions are MPSAFE.
- * addr = %rdi
+ * byte from user memory.
+ * addr = %rdi, valp = %rsi
  */
 
-ALTENTRY(fuword64)
-ENTRY(fuword)
+ALTENTRY(fueword64)
+ENTRY(fueword)
        movq    PCPU(CURPCB),%rcx
        movq    $fusufault,PCB_ONFAULT(%rcx)
 
@@ -385,13 +394,15 @@ ENTRY(fuword)
        cmpq    %rax,%rdi                       /* verify address is valid */
        ja      fusufault
 
-       movq    (%rdi),%rax
-       movq    $0,PCB_ONFAULT(%rcx)
+       xorl    %eax,%eax
+       movq    (%rdi),%r11
+       movq    %rax,PCB_ONFAULT(%rcx)
+       movq    %r11,(%rsi)
        ret
 END(fuword64)
 END(fuword)
 
-ENTRY(fuword32)
+ENTRY(fueword32)
        movq    PCPU(CURPCB),%rcx
        movq    $fusufault,PCB_ONFAULT(%rcx)
 
@@ -399,10 +410,12 @@ ENTRY(fuword32)
        cmpq    %rax,%rdi                       /* verify address is valid */
        ja      fusufault
 
-       movl    (%rdi),%eax
-       movq    $0,PCB_ONFAULT(%rcx)
+       xorl    %eax,%eax
+       movl    (%rdi),%r11d
+       movq    %rax,PCB_ONFAULT(%rcx)
+       movl    %r11d,(%rsi)
        ret
-END(fuword32)
+END(fueword32)
 
 /*
  * fuswintr() and suswintr() are specialized variants of fuword16() and

Modified: stable/10/sys/amd64/ia32/ia32_syscall.c
==============================================================================
--- stable/10/sys/amd64/ia32/ia32_syscall.c     Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/amd64/ia32/ia32_syscall.c     Tue Nov 18 12:53:32 2014        
(r274648)
@@ -110,7 +110,7 @@ ia32_fetch_syscall_args(struct thread *t
        struct proc *p;
        struct trapframe *frame;
        caddr_t params;
-       u_int32_t args[8];
+       u_int32_t args[8], tmp;
        int error, i;
 
        p = td->td_proc;
@@ -126,7 +126,10 @@ ia32_fetch_syscall_args(struct thread *t
                /*
                 * Code is first argument, followed by actual args.
                 */
-               sa->code = fuword32(params);
+               error = fueword32(params, &tmp);
+               if (error == -1)
+                       return (EFAULT);
+               sa->code = tmp;
                params += sizeof(int);
        } else if (sa->code == SYS___syscall) {
                /*
@@ -135,7 +138,10 @@ ia32_fetch_syscall_args(struct thread *t
                 * We use a 32-bit fetch in case params is not
                 * aligned.
                 */
-               sa->code = fuword32(params);
+               error = fueword32(params, &tmp);
+               if (error == -1)
+                       return (EFAULT);
+               sa->code = tmp;
                params += sizeof(quad_t);
        }
        if (p->p_sysent->sv_mask)

Modified: stable/10/sys/arm/include/param.h
==============================================================================
--- stable/10/sys/arm/include/param.h   Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/arm/include/param.h   Tue Nov 18 12:53:32 2014        
(r274648)
@@ -149,4 +149,8 @@
 
 #define        pgtok(x)                ((x) * (PAGE_SIZE / 1024))
 
+#ifdef _KERNEL
+#define        NO_FUEWORD      1
+#endif
+
 #endif /* !_ARM_INCLUDE_PARAM_H_ */

Modified: stable/10/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- stable/10/sys/compat/freebsd32/freebsd32_misc.c     Tue Nov 18 09:18:35 
2014        (r274647)
+++ stable/10/sys/compat/freebsd32/freebsd32_misc.c     Tue Nov 18 12:53:32 
2014        (r274648)
@@ -1924,16 +1924,21 @@ freebsd32_sysctl(struct thread *td, stru
 {
        int error, name[CTL_MAXNAME];
        size_t j, oldlen;
+       uint32_t tmp;
 
        if (uap->namelen > CTL_MAXNAME || uap->namelen < 2)
                return (EINVAL);
        error = copyin(uap->name, name, uap->namelen * sizeof(int));
        if (error)
                return (error);
-       if (uap->oldlenp)
-               oldlen = fuword32(uap->oldlenp);
-       else
+       if (uap->oldlenp) {
+               error = fueword32(uap->oldlenp, &tmp);
+               oldlen = tmp;
+       } else {
                oldlen = 0;
+       }
+       if (error != 0)
+               return (EFAULT);
        error = userland_sysctl(td, name, uap->namelen,
                uap->old, &oldlen, 1,
                uap->new, uap->newlen, &j, SCTL_MASK32);

Modified: stable/10/sys/i386/i386/support.s
==============================================================================
--- stable/10/sys/i386/i386/support.s   Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/i386/i386/support.s   Tue Nov 18 12:53:32 2014        
(r274648)
@@ -389,16 +389,16 @@ copyin_fault:
        ret
 
 /*
- * casuword.  Compare and set user word.  Returns -1 or the current value.
+ * casueword.  Compare and set user word.  Returns -1 on fault,
+ * 0 on non-faulting access.  The current value is in *oldp.
  */
-
-ALTENTRY(casuword32)
-ENTRY(casuword)
+ALTENTRY(casueword32)
+ENTRY(casueword)
        movl    PCPU(CURPCB),%ecx
        movl    $fusufault,PCB_ONFAULT(%ecx)
        movl    4(%esp),%edx                    /* dst */
        movl    8(%esp),%eax                    /* old */
-       movl    12(%esp),%ecx                   /* new */
+       movl    16(%esp),%ecx                   /* new */
 
        cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address is valid */
        ja      fusufault
@@ -416,17 +416,20 @@ ENTRY(casuword)
 
        movl    PCPU(CURPCB),%ecx
        movl    $0,PCB_ONFAULT(%ecx)
+       movl    12(%esp),%edx                   /* oldp */
+       movl    %eax,(%edx)
+       xorl    %eax,%eax
        ret
-END(casuword32)
-END(casuword)
+END(casueword32)
+END(casueword)
 
 /*
  * Fetch (load) a 32-bit word, a 16-bit word, or an 8-bit byte from user
- * memory.  All these functions are MPSAFE.
+ * memory.
  */
 
-ALTENTRY(fuword32)
-ENTRY(fuword)
+ALTENTRY(fueword32)
+ENTRY(fueword)
        movl    PCPU(CURPCB),%ecx
        movl    $fusufault,PCB_ONFAULT(%ecx)
        movl    4(%esp),%edx                    /* from */
@@ -436,9 +439,12 @@ ENTRY(fuword)
 
        movl    (%edx),%eax
        movl    $0,PCB_ONFAULT(%ecx)
+       movl    8(%esp),%edx
+       movl    %eax,(%edx)
+       xorl    %eax,%eax
        ret
-END(fuword32)
-END(fuword)
+END(fueword32)
+END(fueword)
 
 /*
  * fuswintr() and suswintr() are specialized variants of fuword16() and

Modified: stable/10/sys/i386/i386/trap.c
==============================================================================
--- stable/10/sys/i386/i386/trap.c      Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/i386/i386/trap.c      Tue Nov 18 12:53:32 2014        
(r274648)
@@ -1062,6 +1062,7 @@ cpu_fetch_syscall_args(struct thread *td
        struct proc *p;
        struct trapframe *frame;
        caddr_t params;
+       long tmp;
        int error;
 
        p = td->td_proc;
@@ -1077,14 +1078,20 @@ cpu_fetch_syscall_args(struct thread *td
                /*
                 * Code is first argument, followed by actual args.
                 */
-               sa->code = fuword(params);
+               error = fueword(params, &tmp);
+               if (error == -1)
+                       return (EFAULT);
+               sa->code = tmp;
                params += sizeof(int);
        } else if (sa->code == SYS___syscall) {
                /*
                 * Like syscall, but code is a quad, so as to maintain
                 * quad alignment for the rest of the arguments.
                 */
-               sa->code = fuword(params);
+               error = fueword(params, &tmp);
+               if (error == -1)
+                       return (EFAULT);
+               sa->code = tmp;
                params += sizeof(quad_t);
        }
 

Modified: stable/10/sys/ia64/include/param.h
==============================================================================
--- stable/10/sys/ia64/include/param.h  Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/ia64/include/param.h  Tue Nov 18 12:53:32 2014        
(r274648)
@@ -121,4 +121,8 @@
 
 #define pgtok(x)                ((x) * (PAGE_SIZE / 1024)) 
 
+#ifdef _KERNEL
+#define        NO_FUEWORD      1
+#endif
+
 #endif /* !_IA64_INCLUDE_PARAM_H_ */

Modified: stable/10/sys/kern/kern_exec.c
==============================================================================
--- stable/10/sys/kern/kern_exec.c      Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/kern/kern_exec.c      Tue Nov 18 12:53:32 2014        
(r274648)
@@ -1124,7 +1124,7 @@ int
 exec_copyin_args(struct image_args *args, char *fname,
     enum uio_seg segflg, char **argv, char **envv)
 {
-       char *argp, *envp;
+       u_long argp, envp;
        int error;
        size_t length;
 
@@ -1160,13 +1160,17 @@ exec_copyin_args(struct image_args *args
        /*
         * extract arguments first
         */
-       while ((argp = (caddr_t) (intptr_t) fuword(argv++))) {
-               if (argp == (caddr_t) -1) {
+       for (;;) {
+               error = fueword(argv++, &argp);
+               if (error == -1) {
                        error = EFAULT;
                        goto err_exit;
                }
-               if ((error = copyinstr(argp, args->endp,
-                   args->stringspace, &length))) {
+               if (argp == 0)
+                       break;
+               error = copyinstr((void *)(uintptr_t)argp, args->endp,
+                   args->stringspace, &length);
+               if (error != 0) {
                        if (error == ENAMETOOLONG) 
                                error = E2BIG;
                        goto err_exit;
@@ -1182,13 +1186,17 @@ exec_copyin_args(struct image_args *args
         * extract environment strings
         */
        if (envv) {
-               while ((envp = (caddr_t)(intptr_t)fuword(envv++))) {
-                       if (envp == (caddr_t)-1) {
+               for (;;) {
+                       error = fueword(envv++, &envp);
+                       if (error == -1) {
                                error = EFAULT;
                                goto err_exit;
                        }
-                       if ((error = copyinstr(envp, args->endp,
-                           args->stringspace, &length))) {
+                       if (envp == 0)
+                               break;
+                       error = copyinstr((void *)(uintptr_t)envp,
+                           args->endp, args->stringspace, &length);
+                       if (error != 0) {
                                if (error == ENAMETOOLONG)
                                        error = E2BIG;
                                goto err_exit;

Modified: stable/10/sys/kern/kern_umtx.c
==============================================================================
--- stable/10/sys/kern/kern_umtx.c      Tue Nov 18 09:18:35 2014        
(r274647)
+++ stable/10/sys/kern/kern_umtx.c      Tue Nov 18 12:53:32 2014        
(r274648)
@@ -510,6 +510,15 @@ umtxq_unbusy(struct umtx_key *key)
                wakeup_one(uc);
 }
 
+static inline void
+umtxq_unbusy_unlocked(struct umtx_key *key)
+{
+
+       umtxq_lock(key);
+       umtxq_unbusy(key);
+       umtxq_unlock(key);
+}
+
 static struct umtxq_queue *
 umtxq_queue_lookup(struct umtx_key *key, int q)
 {
@@ -1208,6 +1217,7 @@ do_wait(struct thread *td, void *addr, u
        struct abs_timeout timo;
        struct umtx_q *uq;
        u_long tmp;
+       uint32_t tmp32;
        int error = 0;
 
        uq = td->td_umtxq;
@@ -1221,18 +1231,29 @@ do_wait(struct thread *td, void *addr, u
        umtxq_lock(&uq->uq_key);
        umtxq_insert(uq);
        umtxq_unlock(&uq->uq_key);
-       if (compat32 == 0)
-               tmp = fuword(addr);
-        else
-               tmp = (unsigned int)fuword32(addr);
+       if (compat32 == 0) {
+               error = fueword(addr, &tmp);
+               if (error != 0)
+                       error = EFAULT;
+       } else {
+               error = fueword32(addr, &tmp32);
+               if (error == 0)
+                       tmp = tmp32;
+               else
+                       error = EFAULT;
+       }
        umtxq_lock(&uq->uq_key);
-       if (tmp == id)
-               error = umtxq_sleep(uq, "uwait", timeout == NULL ?
-                   NULL : &timo);
-       if ((uq->uq_flags & UQF_UMTXQ) == 0)
-               error = 0;
-       else
+       if (error == 0) {
+               if (tmp == id)
+                       error = umtxq_sleep(uq, "uwait", timeout == NULL ?
+                           NULL : &timo);
+               if ((uq->uq_flags & UQF_UMTXQ) == 0)
+                       error = 0;
+               else
+                       umtxq_remove(uq);
+       } else if ((uq->uq_flags & UQF_UMTXQ) != 0) {
                umtxq_remove(uq);
+       }
        umtxq_unlock(&uq->uq_key);
        umtx_key_release(&uq->uq_key);
        if (error == ERESTART)
@@ -1269,11 +1290,11 @@ do_lock_normal(struct thread *td, struct
        struct abs_timeout timo;
        struct umtx_q *uq;
        uint32_t owner, old, id;
-       int error = 0;
+       int error, rv;
 
        id = td->td_tid;
        uq = td->td_umtxq;
-
+       error = 0;
        if (timeout != NULL)
                abs_timeout_init2(&timo, timeout);
 
@@ -1282,7 +1303,9 @@ do_lock_normal(struct thread *td, struct
         * can fault on any access.
         */
        for (;;) {
-               owner = fuword32(__DEVOLATILE(void *, &m->m_owner));
+               rv = fueword32(&m->m_owner, &owner);
+               if (rv == -1)
+                       return (EFAULT);
                if (mode == _UMUTEX_WAIT) {
                        if (owner == UMUTEX_UNOWNED || owner == 
UMUTEX_CONTESTED)
                                return (0);
@@ -1290,31 +1313,31 @@ do_lock_normal(struct thread *td, struct
                        /*
                         * Try the uncontested case.  This should be done in 
userland.
                         */
-                       owner = casuword32(&m->m_owner, UMUTEX_UNOWNED, id);
+                       rv = casueword32(&m->m_owner, UMUTEX_UNOWNED,
+                           &owner, id);
+                       /* The address was invalid. */
+                       if (rv == -1)
+                               return (EFAULT);
 
                        /* The acquire succeeded. */
                        if (owner == UMUTEX_UNOWNED)
                                return (0);
 
-                       /* The address was invalid. */
-                       if (owner == -1)
-                               return (EFAULT);
-
                        /* If no one owns it but it is contested try to acquire 
it. */
                        if (owner == UMUTEX_CONTESTED) {
-                               owner = casuword32(&m->m_owner,
-                                   UMUTEX_CONTESTED, id | UMUTEX_CONTESTED);
+                               rv = casueword32(&m->m_owner,
+                                   UMUTEX_CONTESTED, &owner,
+                                   id | UMUTEX_CONTESTED);
+                               /* The address was invalid. */
+                               if (rv == -1)
+                                       return (EFAULT);
 
                                if (owner == UMUTEX_CONTESTED)
                                        return (0);
 
-                               /* The address was invalid. */
-                               if (owner == -1)
-                                       return (EFAULT);
-
-                               error = umtxq_check_susp(td);
-                               if (error != 0)
-                                       return (error);
+                               rv = umtxq_check_susp(td);
+                               if (rv != 0)
+                                       return (rv);
 
                                /* If this failed the lock has changed, 
restart. */
                                continue;
@@ -1350,10 +1373,11 @@ do_lock_normal(struct thread *td, struct
                 * either some one else has acquired the lock or it has been
                 * released.
                 */
-               old = casuword32(&m->m_owner, owner, owner | UMUTEX_CONTESTED);
+               rv = casueword32(&m->m_owner, owner, &old,
+                   owner | UMUTEX_CONTESTED);
 
                /* The address was invalid. */
-               if (old == -1) {
+               if (rv == -1) {
                        umtxq_lock(&uq->uq_key);
                        umtxq_remove(uq);
                        umtxq_unbusy(&uq->uq_key);
@@ -1398,16 +1422,16 @@ do_unlock_normal(struct thread *td, stru
        /*
         * Make sure we own this mtx.
         */
-       owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
-       if (owner == -1)
+       error = fueword32(&m->m_owner, &owner);
+       if (error == -1)
                return (EFAULT);
 
        if ((owner & ~UMUTEX_CONTESTED) != id)
                return (EPERM);
 
        if ((owner & UMUTEX_CONTESTED) == 0) {
-               old = casuword32(&m->m_owner, owner, UMUTEX_UNOWNED);
-               if (old == -1)
+               error = casueword32(&m->m_owner, owner, &old, UMUTEX_UNOWNED);
+               if (error == -1)
                        return (EFAULT);
                if (old == owner)
                        return (0);
@@ -1429,14 +1453,14 @@ do_unlock_normal(struct thread *td, stru
         * there is zero or one thread only waiting for it.
         * Otherwise, it must be marked as contested.
         */
-       old = casuword32(&m->m_owner, owner,
-               count <= 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED);
+       error = casueword32(&m->m_owner, owner, &old,
+           count <= 1 ? UMUTEX_UNOWNED : UMUTEX_CONTESTED);
        umtxq_lock(&key);
        umtxq_signal(&key,1);
        umtxq_unbusy(&key);
        umtxq_unlock(&key);
        umtx_key_release(&key);
-       if (old == -1)
+       if (error == -1)
                return (EFAULT);
        if (old != owner)
                return (EINVAL);
@@ -1456,14 +1480,16 @@ do_wake_umutex(struct thread *td, struct
        int error;
        int count;
 
-       owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
-       if (owner == -1)
+       error = fueword32(&m->m_owner, &owner);
+       if (error == -1)
                return (EFAULT);
 
        if ((owner & ~UMUTEX_CONTESTED) != 0)
                return (0);
 
-       flags = fuword32(&m->m_flags);
+       error = fueword32(&m->m_flags, &flags);
+       if (error == -1)
+               return (EFAULT);
 
        /* We should only ever be in here for contested locks */
        if ((error = umtx_key_get(m, TYPE_NORMAL_UMUTEX, GET_SHARE(flags),
@@ -1475,16 +1501,20 @@ do_wake_umutex(struct thread *td, struct
        count = umtxq_count(&key);
        umtxq_unlock(&key);
 
-       if (count <= 1)
-               owner = casuword32(&m->m_owner, UMUTEX_CONTESTED, 
UMUTEX_UNOWNED);
+       if (count <= 1) {
+               error = casueword32(&m->m_owner, UMUTEX_CONTESTED, &owner,
+                   UMUTEX_UNOWNED);
+               if (error == -1)
+                       error = EFAULT;
+       }
 
        umtxq_lock(&key);
-       if (count != 0 && (owner & ~UMUTEX_CONTESTED) == 0)
+       if (error == 0 && count != 0 && (owner & ~UMUTEX_CONTESTED) == 0)
                umtxq_signal(&key, 1);
        umtxq_unbusy(&key);
        umtxq_unlock(&key);
        umtx_key_release(&key);
-       return (0);
+       return (error);
 }
 
 /*
@@ -1527,41 +1557,47 @@ do_wake2_umutex(struct thread *td, struc
         * any memory.
         */
        if (count > 1) {
-               owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
-               while ((owner & UMUTEX_CONTESTED) ==0) {
-                       old = casuword32(&m->m_owner, owner,
-                           owner|UMUTEX_CONTESTED);
+               error = fueword32(&m->m_owner, &owner);
+               if (error == -1)
+                       error = EFAULT;
+               while (error == 0 && (owner & UMUTEX_CONTESTED) == 0) {
+                       error = casueword32(&m->m_owner, owner, &old,
+                           owner | UMUTEX_CONTESTED);
+                       if (error == -1) {
+                               error = EFAULT;
+                               break;
+                       }
                        if (old == owner)
                                break;
                        owner = old;
-                       if (old == -1)
-                               break;
                        error = umtxq_check_susp(td);
                        if (error != 0)
                                break;
                }
        } else if (count == 1) {
-               owner = fuword32(__DEVOLATILE(uint32_t *, &m->m_owner));
-               while ((owner & ~UMUTEX_CONTESTED) != 0 &&
+               error = fueword32(&m->m_owner, &owner);
+               if (error == -1)
+                       error = EFAULT;
+               while (error == 0 && (owner & ~UMUTEX_CONTESTED) != 0 &&
                       (owner & UMUTEX_CONTESTED) == 0) {
-                       old = casuword32(&m->m_owner, owner,
-                           owner|UMUTEX_CONTESTED);
+                       error = casueword32(&m->m_owner, owner, &old,
+                           owner | UMUTEX_CONTESTED);
+                       if (error == -1) {
+                               error = EFAULT;
+                               break;
+                       }
                        if (old == owner)
                                break;
                        owner = old;
-                       if (old == -1)
-                               break;
                        error = umtxq_check_susp(td);
                        if (error != 0)
                                break;
                }
        }
        umtxq_lock(&key);
-       if (owner == -1) {
-               error = EFAULT;
+       if (error == EFAULT) {
                umtxq_signal(&key, INT_MAX);
-       }
-       else if (count != 0 && (owner & ~UMUTEX_CONTESTED) == 0)
+       } else if (count != 0 && (owner & ~UMUTEX_CONTESTED) == 0)
                umtxq_signal(&key, 1);
        umtxq_unbusy(&key);
        umtxq_unlock(&key);
@@ -1941,7 +1977,7 @@ do_lock_pi(struct thread *td, struct umu
        struct umtx_q *uq;
        struct umtx_pi *pi, *new_pi;
        uint32_t id, owner, old;
-       int error;
+       int error, rv;
 
        id = td->td_tid;
        uq = td->td_umtxq;
@@ -1984,7 +2020,12 @@ do_lock_pi(struct thread *td, struct umu
                /*
                 * Try the uncontested case.  This should be done in userland.
                 */
-               owner = casuword32(&m->m_owner, UMUTEX_UNOWNED, id);
+               rv = casueword32(&m->m_owner, UMUTEX_UNOWNED, &owner, id);
+               /* The address was invalid. */
+               if (rv == -1) {
+                       error = EFAULT;
+                       break;
+               }
 
                /* The acquire succeeded. */
                if (owner == UMUTEX_UNOWNED) {
@@ -1992,16 +2033,15 @@ do_lock_pi(struct thread *td, struct umu
                        break;
                }

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to