Skip site navigation (1)Skip section navigation (2)
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>