Date: Fri, 23 Mar 2012 15:37:41 +0000 (UTC) From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-8@freebsd.org Subject: svn commit: r233365 - in stable/8/sys: kern sys vm Message-ID: <201203231537.q2NFbf9k082283@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: kib Date: Fri Mar 23 15:37:41 2012 New Revision: 233365 URL: http://svn.freebsd.org/changeset/base/233365 Log: MFC r223889: Add a facility to disable processing page faults. When activated, uiomove generates EFAULT if any accessed address is not mapped, as opposed to handling the fault. Modified: stable/8/sys/kern/kern_subr.c stable/8/sys/sys/proc.h stable/8/sys/sys/systm.h stable/8/sys/sys/uio.h stable/8/sys/vm/vm_extern.h stable/8/sys/vm/vm_fault.c Directory Properties: stable/8/sys/ (props changed) Modified: stable/8/sys/kern/kern_subr.c ============================================================================== --- stable/8/sys/kern/kern_subr.c Fri Mar 23 14:12:51 2012 (r233364) +++ stable/8/sys/kern/kern_subr.c Fri Mar 23 15:37:41 2012 (r233365) @@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$"); SYSCTL_INT(_kern, KERN_IOV_MAX, iov_max, CTLFLAG_RD, NULL, UIO_MAXIOV, "Maximum number of elements in an I/O vector; sysconf(_SC_IOV_MAX)"); +static int uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault); + #ifdef ZERO_COPY_SOCKETS /* Declared in uipc_socket.c */ extern int so_zero_copy_receive; @@ -132,23 +134,65 @@ retry: #endif /* ZERO_COPY_SOCKETS */ int +copyin_nofault(const void *udaddr, void *kaddr, size_t len) +{ + int error, save; + + save = vm_fault_disable_pagefaults(); + error = copyin(udaddr, kaddr, len); + vm_fault_enable_pagefaults(save); + return (error); +} + +int +copyout_nofault(const void *kaddr, void *udaddr, size_t len) +{ + int error, save; + + save = vm_fault_disable_pagefaults(); + error = copyout(kaddr, udaddr, len); + vm_fault_enable_pagefaults(save); + return (error); +} + +int uiomove(void *cp, int n, struct uio *uio) { - struct thread *td = curthread; + + return (uiomove_faultflag(cp, n, uio, 0)); +} + +int +uiomove_nofault(void *cp, int n, struct uio *uio) +{ + + return (uiomove_faultflag(cp, n, uio, 1)); +} + +static int +uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault) +{ + struct thread *td; struct iovec *iov; u_int cnt; - int error = 0; - int save = 0; + int error, newflags, save; + + td = curthread; + error = 0; KASSERT(uio->uio_rw == UIO_READ || uio->uio_rw == UIO_WRITE, ("uiomove: mode")); - KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == curthread, + KASSERT(uio->uio_segflg != UIO_USERSPACE || uio->uio_td == td, ("uiomove proc")); - WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, - "Calling uiomove()"); - - save = td->td_pflags & TDP_DEADLKTREAT; - td->td_pflags |= TDP_DEADLKTREAT; + if (!nofault) + WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, + "Calling uiomove()"); + + /* XXX does it make a sense to set TDP_DEADLKTREAT for UIO_SYSSPACE ? */ + newflags = TDP_DEADLKTREAT; + if (uio->uio_segflg == UIO_USERSPACE && nofault) + newflags |= TDP_NOFAULTING; + save = curthread_pflags_set(newflags); while (n > 0 && uio->uio_resid) { iov = uio->uio_iov; @@ -191,8 +235,7 @@ uiomove(void *cp, int n, struct uio *uio n -= cnt; } out: - if (save == 0) - td->td_pflags &= ~TDP_DEADLKTREAT; + curthread_pflags_restore(save); return (error); } Modified: stable/8/sys/sys/proc.h ============================================================================== --- stable/8/sys/sys/proc.h Fri Mar 23 14:12:51 2012 (r233364) +++ stable/8/sys/sys/proc.h Fri Mar 23 15:37:41 2012 (r233365) @@ -391,7 +391,7 @@ do { \ #define TDP_COWINPROGRESS 0x00000010 /* Snapshot copy-on-write in progress. */ #define TDP_ALTSTACK 0x00000020 /* Have alternate signal stack. */ #define TDP_DEADLKTREAT 0x00000040 /* Lock aquisition - deadlock treatment. */ -#define TDP_UNUSED80 0x00000080 /* available. */ +#define TDP_NOFAULTING 0x00000080 /* Do not handle page faults. */ #define TDP_NOSLEEPING 0x00000100 /* Thread is not allowed to sleep on a sq. */ #define TDP_OWEUPC 0x00000200 /* Call addupc() at next AST. */ #define TDP_ITHREAD 0x00000400 /* Thread is an interrupt thread. */ Modified: stable/8/sys/sys/systm.h ============================================================================== --- stable/8/sys/sys/systm.h Fri Mar 23 14:12:51 2012 (r233364) +++ stable/8/sys/sys/systm.h Fri Mar 23 15:37:41 2012 (r233365) @@ -216,8 +216,12 @@ int copyinstr(const void * __restrict ud __nonnull(1) __nonnull(2); int copyin(const void * __restrict udaddr, void * __restrict kaddr, size_t len) __nonnull(1) __nonnull(2); +int copyin_nofault(const void * __restrict udaddr, void * __restrict kaddr, + size_t len) __nonnull(1) __nonnull(2); int copyout(const void * __restrict kaddr, void * __restrict udaddr, size_t len) __nonnull(1) __nonnull(2); +int copyout_nofault(const void * __restrict kaddr, void * __restrict udaddr, + size_t len) __nonnull(1) __nonnull(2); int fubyte(const void *base); long fuword(const void *base); Modified: stable/8/sys/sys/uio.h ============================================================================== --- stable/8/sys/sys/uio.h Fri Mar 23 14:12:51 2012 (r233364) +++ stable/8/sys/sys/uio.h Fri Mar 23 15:37:41 2012 (r233365) @@ -101,6 +101,7 @@ int uiomove(void *cp, int n, struct uio int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomove_fromphys(struct vm_page *ma[], vm_offset_t offset, int n, struct uio *uio); +int uiomove_nofault(void *cp, int n, struct uio *uio); int uiomoveco(void *cp, int n, struct uio *uio, int disposable); #else /* !_KERNEL */ Modified: stable/8/sys/vm/vm_extern.h ============================================================================== --- stable/8/sys/vm/vm_extern.h Fri Mar 23 14:12:51 2012 (r233364) +++ stable/8/sys/vm/vm_extern.h Fri Mar 23 15:37:41 2012 (r233365) @@ -61,6 +61,8 @@ int useracc(void *, int, int); int vm_fault(vm_map_t, vm_offset_t, vm_prot_t, int); void vm_fault_copy_entry(vm_map_t, vm_map_t, vm_map_entry_t, vm_map_entry_t, vm_ooffset_t *); +int vm_fault_disable_pagefaults(void); +void vm_fault_enable_pagefaults(int save); void vm_fault_unwire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t); int vm_fault_wire(vm_map_t, vm_offset_t, vm_offset_t, boolean_t, boolean_t); int vm_forkproc(struct thread *, struct proc *, struct thread *, struct vmspace *, int); Modified: stable/8/sys/vm/vm_fault.c ============================================================================== --- stable/8/sys/vm/vm_fault.c Fri Mar 23 14:12:51 2012 (r233364) +++ stable/8/sys/vm/vm_fault.c Fri Mar 23 15:37:41 2012 (r233365) @@ -222,6 +222,9 @@ vm_fault(vm_map_t map, vm_offset_t vaddr struct vnode *vp; int locked, error; + if ((curthread->td_pflags & TDP_NOFAULTING) != 0) + return (KERN_PROTECTION_FAILURE); + hardfault = 0; growstack = TRUE; PCPU_INC(cnt.v_vm_faults); @@ -1405,3 +1408,17 @@ vm_fault_additional_pages(m, rbehind, ra /* return number of pages */ return i; } + +int +vm_fault_disable_pagefaults(void) +{ + + return (curthread_pflags_set(TDP_NOFAULTING)); +} + +void +vm_fault_enable_pagefaults(int save) +{ + + curthread_pflags_restore(save); +}
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203231537.q2NFbf9k082283>