Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 21 Jun 2026 16:14:39 +0000
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: fc9b28879e89 - main - uiomove_*: centralize the copy function selection
Message-ID:  <6a380def.1a3a0.21375365@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by brooks:

URL: https://cgit.FreeBSD.org/src/commit/?id=fc9b28879e8935cc830b83d8a36d85b9b98b276a

commit fc9b28879e8935cc830b83d8a36d85b9b98b276a
Author:     Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2026-06-21 15:47:53 +0000
Commit:     Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2026-06-21 16:13:27 +0000

    uiomove_*: centralize the copy function selection
    
    Add a uiomove_step() for the central set of switch statements which
    choose between userspace and kernel and if data is going to or from the
    iovec.
    
    Refactor uiomove_fromphys loops to unconditionally free per-iteration
    resources and drop gotos.
    
    While here, switch from bcopy to memcpy.
    
    Reviewed by:    kib
    Suggested by:   emaste
    Sponsored by:   Innovate UK
    Differential Revision:  https://reviews.freebsd.org/D57688
---
 sys/amd64/amd64/uio_machdep.c     | 34 ++------------------
 sys/arm/arm/uio_machdep.c         | 33 ++------------------
 sys/arm64/arm64/uio_machdep.c     | 36 ++--------------------
 sys/i386/i386/uio_machdep.c       | 33 ++------------------
 sys/kern/subr_uio.c               | 65 ++++++++++++++++++++++-----------------
 sys/powerpc/powerpc/uio_machdep.c | 33 ++------------------
 sys/riscv/riscv/uio_machdep.c     | 36 ++--------------------
 sys/sys/uio.h                     |  1 +
 8 files changed, 56 insertions(+), 215 deletions(-)

diff --git a/sys/amd64/amd64/uio_machdep.c b/sys/amd64/amd64/uio_machdep.c
index 11e6ad2b1da9..9fdfc898172b 100644
--- a/sys/amd64/amd64/uio_machdep.c
+++ b/sys/amd64/amd64/uio_machdep.c
@@ -96,38 +96,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 			    &ma[offset >> PAGE_SHIFT], &vaddr, 1, true);
 			cp = (char *)vaddr + page_offset;
 		}
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			maybe_yield();
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				error = copyout(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				error = copyin(iov->iov_base, cp, cnt);
-				break;
-			}
-			if (error)
-				goto out;
-			break;
-		case UIO_SYSSPACE:
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				bcopy(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				bcopy(iov->iov_base, cp, cnt);
-				break;
-			}
-			break;
-		case UIO_NOCOPY:
-			break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
 		if (__predict_false(mapped)) {
 			pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT],
 			    &vaddr, 1, true);
 			mapped = false;
 		}
+		if (error != 0)
+			break;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
@@ -135,10 +111,6 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		offset += cnt;
 		n -= cnt;
 	}
-out:
-	if (__predict_false(mapped))
-		pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1,
-		    true);
 	if (save == 0)
 		td->td_pflags &= ~TDP_DEADLKTREAT;
 	return (error);
diff --git a/sys/arm/arm/uio_machdep.c b/sys/arm/arm/uio_machdep.c
index 6b8e4352e06f..7df6104b25fc 100644
--- a/sys/arm/arm/uio_machdep.c
+++ b/sys/arm/arm/uio_machdep.c
@@ -91,36 +91,10 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		cnt = min(cnt, PAGE_SIZE - page_offset);
 		sf = sf_buf_alloc(ma[offset >> PAGE_SHIFT], 0);
 		cp = (char*)sf_buf_kva(sf) + page_offset;
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			maybe_yield();
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				error = copyout(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				error = copyin(iov->iov_base, cp, cnt);
-				break;
-			}
-			if (error) {
-				sf_buf_free(sf);
-				goto out;
-			}
-			break;
-		case UIO_SYSSPACE:
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				bcopy(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				bcopy(iov->iov_base, cp, cnt);
-				break;
-			}
-			break;
-		case UIO_NOCOPY:
-			break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
 		sf_buf_free(sf);
+		if (error != 0)
+			break;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
@@ -128,7 +102,6 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		offset += cnt;
 		n -= cnt;
 	}
-out:
 	if (save == 0)
 		td->td_pflags &= ~TDP_DEADLKTREAT;
 	return (error);
diff --git a/sys/arm64/arm64/uio_machdep.c b/sys/arm64/arm64/uio_machdep.c
index 976055a69491..77f596498c45 100644
--- a/sys/arm64/arm64/uio_machdep.c
+++ b/sys/arm64/arm64/uio_machdep.c
@@ -92,38 +92,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 			    &ma[offset >> PAGE_SHIFT], &vaddr, 1, true);
 			cp = (char *)vaddr + page_offset;
 		}
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			maybe_yield();
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				error = copyout(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				error = copyin(iov->iov_base, cp, cnt);
-				break;
-			}
-			if (error)
-				goto out;
-			break;
-		case UIO_SYSSPACE:
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				bcopy(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				bcopy(iov->iov_base, cp, cnt);
-				break;
-			}
-			break;
-		case UIO_NOCOPY:
-			break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
 		if (__predict_false(mapped)) {
 			pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT],
 			    &vaddr, 1, true);
 			mapped = false;
 		}
+		if (error != 0)
+			break;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
@@ -131,12 +107,6 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		offset += cnt;
 		n -= cnt;
 	}
-out:
-	if (__predict_false(mapped)) {
-		panic("ARM64TODO: uiomove_fromphys");
-		pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1,
-		    true);
-	}
 	if (save == 0)
 		td->td_pflags &= ~TDP_DEADLKTREAT;
 	return (error);
diff --git a/sys/i386/i386/uio_machdep.c b/sys/i386/i386/uio_machdep.c
index b41460aef5b4..674de877d2a1 100644
--- a/sys/i386/i386/uio_machdep.c
+++ b/sys/i386/i386/uio_machdep.c
@@ -91,38 +91,11 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		sched_pin();
 		sf = sf_buf_alloc(ma[offset >> PAGE_SHIFT], SFB_CPUPRIVATE);
 		cp = (char *)sf_buf_kva(sf) + page_offset;
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			maybe_yield();
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				error = copyout(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				error = copyin(iov->iov_base, cp, cnt);
-				break;
-			}
-			if (error) {
-				sf_buf_free(sf);
-				sched_unpin();
-				goto out;
-			}
-			break;
-		case UIO_SYSSPACE:
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				bcopy(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				bcopy(iov->iov_base, cp, cnt);
-				break;
-			}
-			break;
-		case UIO_NOCOPY:
-			break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
 		sf_buf_free(sf);
 		sched_unpin();
+		if (error != 0)
+			break;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c
index fa5865fbe938..fea1395a7f77 100644
--- a/sys/kern/subr_uio.c
+++ b/sys/kern/subr_uio.c
@@ -200,6 +200,40 @@ uiomove_nofault(void *cp, int n, struct uio *uio)
 	return (uiomove_faultflag(cp, n, uio, 1));
 }
 
+int
+uiomove_step(void *cp, void *base, size_t len, struct uio *uio)
+{
+	int error = 0;
+
+	switch (uio->uio_segflg) {
+	case UIO_USERSPACE:
+		maybe_yield();
+		switch (uio->uio_rw) {
+		case UIO_READ:
+			error = copyout(cp, base, len);
+			break;
+		case UIO_WRITE:
+			error = copyin(base, cp, len);
+			break;
+		}
+		break;
+	case UIO_SYSSPACE:
+		switch (uio->uio_rw) {
+		case UIO_READ:
+			memcpy(base, cp, len);
+			break;
+		case UIO_WRITE:
+			memcpy(cp, base, len);
+			break;
+		}
+		break;
+	case UIO_NOCOPY:
+		break;
+	}
+
+	return (error);
+}
+
 static int
 uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault)
 {
@@ -246,34 +280,9 @@ uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault)
 		if (cnt > n)
 			cnt = n;
 
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			maybe_yield();
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				error = copyout(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				error = copyin(iov->iov_base, cp, cnt);
-				break;
-			}
-			if (error)
-				goto out;
-			break;
-
-		case UIO_SYSSPACE:
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				bcopy(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				bcopy(iov->iov_base, cp, cnt);
-				break;
-			}
-			break;
-		case UIO_NOCOPY:
-			break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
+		if (error != 0)
+			goto out;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
diff --git a/sys/powerpc/powerpc/uio_machdep.c b/sys/powerpc/powerpc/uio_machdep.c
index 63911963279a..05d06a95f544 100644
--- a/sys/powerpc/powerpc/uio_machdep.c
+++ b/sys/powerpc/powerpc/uio_machdep.c
@@ -97,36 +97,10 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		sf = sf_buf_alloc(m, 0);
 		cp = (char*)sf_buf_kva(sf) + page_offset;
 
-		switch (uio->uio_segflg) {
-			case UIO_USERSPACE:
-				maybe_yield();
-				switch (uio->uio_rw) {
-				case UIO_READ:
-					error = copyout(cp, iov->iov_base, cnt);
-					break;
-				case UIO_WRITE:
-					error = copyin(iov->iov_base, cp, cnt);
-					break;
-				}
-				if (error) {
-					sf_buf_free(sf);
-					goto out;
-				}
-				break;
-			case UIO_SYSSPACE:
-				switch (uio->uio_rw) {
-				case UIO_READ:
-					bcopy(cp, iov->iov_base, cnt);
-					break;
-				case UIO_WRITE:
-					bcopy(iov->iov_base, cp, cnt);
-					break;
-				}
-				break;
-			case UIO_NOCOPY:
-				break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
 		sf_buf_free(sf);
+		if (error != 0)
+			break;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
@@ -134,7 +108,6 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		offset += cnt;
 		n -= cnt;
 	}
-out:
 	if (save == 0)
 		td->td_pflags &= ~TDP_DEADLKTREAT;
 	return (error);
diff --git a/sys/riscv/riscv/uio_machdep.c b/sys/riscv/riscv/uio_machdep.c
index f171feb1a4bd..77f596498c45 100644
--- a/sys/riscv/riscv/uio_machdep.c
+++ b/sys/riscv/riscv/uio_machdep.c
@@ -92,38 +92,14 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 			    &ma[offset >> PAGE_SHIFT], &vaddr, 1, true);
 			cp = (char *)vaddr + page_offset;
 		}
-		switch (uio->uio_segflg) {
-		case UIO_USERSPACE:
-			maybe_yield();
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				error = copyout(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				error = copyin(iov->iov_base, cp, cnt);
-				break;
-			}
-			if (error)
-				goto out;
-			break;
-		case UIO_SYSSPACE:
-			switch (uio->uio_rw) {
-			case UIO_READ:
-				bcopy(cp, iov->iov_base, cnt);
-				break;
-			case UIO_WRITE:
-				bcopy(iov->iov_base, cp, cnt);
-				break;
-			}
-			break;
-		case UIO_NOCOPY:
-			break;
-		}
+		error = uiomove_step(cp, iov->iov_base, cnt, uio);
 		if (__predict_false(mapped)) {
 			pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT],
 			    &vaddr, 1, true);
 			mapped = false;
 		}
+		if (error != 0)
+			break;
 		iov->iov_base = (char *)iov->iov_base + cnt;
 		iov->iov_len -= cnt;
 		uio->uio_resid -= cnt;
@@ -131,12 +107,6 @@ uiomove_fromphys(vm_page_t ma[], vm_offset_t offset, int n, struct uio *uio)
 		offset += cnt;
 		n -= cnt;
 	}
-out:
-	if (__predict_false(mapped)) {
-		panic("TODO 3");
-		pmap_unmap_io_transient(&ma[offset >> PAGE_SHIFT], &vaddr, 1,
-		    true);
-	}
 	if (save == 0)
 		td->td_pflags &= ~TDP_DEADLKTREAT;
 	return (error);
diff --git a/sys/sys/uio.h b/sys/sys/uio.h
index 58bb7b13b253..217f65365cb0 100644
--- a/sys/sys/uio.h
+++ b/sys/sys/uio.h
@@ -98,6 +98,7 @@ 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	uiomove_object(struct vm_object *obj, off_t obj_size, struct uio *uio);
+int	uiomove_step(void *cp, void *base, size_t cnt, struct uio *uio);
 
 #else /* !_KERNEL */
 


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a380def.1a3a0.21375365>