git: 67d61d18bb8d - main - amd64: extract uiomove_mem() from memrw()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 28 May 2026 12:38:31 UTC
The branch main has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=67d61d18bb8debb4ffc51ef2248aa37ed0bfb8f5
commit 67d61d18bb8debb4ffc51ef2248aa37ed0bfb8f5
Author: Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-05-24 11:48:45 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-05-28 12:38:25 +0000
amd64: extract uiomove_mem() from memrw()
Reviewed by: markj
Tested by: aokblast
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D49566
---
sys/amd64/amd64/mem.c | 103 +++++-------------------------------------
sys/amd64/amd64/uio_machdep.c | 96 +++++++++++++++++++++++++++++++++++++++
sys/amd64/include/md_var.h | 6 +++
3 files changed, 113 insertions(+), 92 deletions(-)
diff --git a/sys/amd64/amd64/mem.c b/sys/amd64/amd64/mem.c
index ab1e6cde6cd5..7d1f0f42d01c 100644
--- a/sys/amd64/amd64/mem.c
+++ b/sys/amd64/amd64/mem.c
@@ -61,10 +61,6 @@
#include <machine/specialreg.h>
#include <machine/vmparam.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <vm/vm_extern.h>
-
#include <machine/memdev.h>
/*
@@ -72,99 +68,22 @@
*/
MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
-/* ARGSUSED */
int
memrw(struct cdev *dev, struct uio *uio, int flags)
{
- struct iovec *iov;
- void *p, *vd;
- ssize_t orig_resid;
- vm_prot_t prot;
- u_long v;
- u_int c;
- int error;
-
- error = 0;
- orig_resid = uio->uio_resid;
- while (uio->uio_resid > 0 && error == 0) {
- iov = uio->uio_iov;
- if (iov->iov_len == 0) {
- uio->uio_iov++;
- uio->uio_iovcnt--;
- if (uio->uio_iovcnt < 0)
- panic("memrw");
- continue;
- }
- v = uio->uio_offset;
- c = ulmin(iov->iov_len, PAGE_SIZE - (u_int)(v & PAGE_MASK));
-
- switch (dev2unit(dev)) {
- case CDEV_MINOR_KMEM:
- /*
- * Since c is clamped to be less or equal than
- * PAGE_SIZE, the uiomove() call does not
- * access past the end of the direct map.
- */
- if (v >= kva_layout.dmap_low &&
- v < kva_layout.dmap_high) {
- error = uiomove((void *)v, c, uio);
- break;
- }
-
- switch (uio->uio_rw) {
- case UIO_READ:
- prot = VM_PROT_READ;
- break;
- case UIO_WRITE:
- prot = VM_PROT_WRITE;
- break;
- }
+ enum uiomove_mem_req req;
- if (!kernacc((void *)v, c, prot)) {
- error = EFAULT;
- break;
- }
-
- /*
- * If the extracted address is not accessible
- * through the direct map, then we make a
- * private (uncached) mapping because we can't
- * depend on the existing kernel mapping
- * remaining valid until the completion of
- * uiomove().
- *
- * XXX We cannot provide access to the
- * physical page 0 mapped into KVA.
- */
- v = pmap_extract(kernel_pmap, v);
- if (v == 0) {
- error = EFAULT;
- break;
- }
- /* FALLTHROUGH */
- case CDEV_MINOR_MEM:
- if (v < dmaplimit) {
- vd = PHYS_TO_DMAP(v);
- error = uiomove(vd, c, uio);
- break;
- }
- if (v > cpu_getmaxphyaddr()) {
- error = EFAULT;
- break;
- }
- p = pmap_mapdev(v, PAGE_SIZE);
- error = uiomove(p, c, uio);
- pmap_unmapdev(p, PAGE_SIZE);
- break;
- }
+ switch (dev2unit(dev)) {
+ case CDEV_MINOR_KMEM:
+ req = UIO_MEM_KMEM;
+ break;
+ case CDEV_MINOR_MEM:
+ req = UIO_MEM_MEM;
+ break;
+ default:
+ __unreachable();
}
- /*
- * Don't return error if any byte was written. Read and write
- * can return error only if no i/o was performed.
- */
- if (uio->uio_resid != orig_resid)
- error = 0;
- return (error);
+ return (uiomove_mem(req, uio));
}
/*
diff --git a/sys/amd64/amd64/uio_machdep.c b/sys/amd64/amd64/uio_machdep.c
index 16915bccf9f5..11e6ad2b1da9 100644
--- a/sys/amd64/amd64/uio_machdep.c
+++ b/sys/amd64/amd64/uio_machdep.c
@@ -44,9 +44,11 @@
#include <sys/uio.h>
#include <vm/vm.h>
+#include <vm/vm_extern.h>
#include <vm/vm_page.h>
#include <machine/vmparam.h>
+#include <machine/md_var.h>
/*
* Implement uiomove(9) from physical memory using the direct map to
@@ -141,3 +143,97 @@ out:
td->td_pflags &= ~TDP_DEADLKTREAT;
return (error);
}
+
+int
+uiomove_mem(enum uiomove_mem_req req, struct uio *uio)
+{
+ struct iovec *iov;
+ void *p, *vd;
+ ssize_t orig_resid;
+ vm_prot_t prot;
+ u_long v;
+ u_int c;
+ int error;
+
+ error = 0;
+ orig_resid = uio->uio_resid;
+ while (uio->uio_resid > 0 && error == 0) {
+ iov = uio->uio_iov;
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ if (uio->uio_iovcnt < 0)
+ panic("memrw");
+ continue;
+ }
+ v = uio->uio_offset;
+ c = ulmin(iov->iov_len, PAGE_SIZE - (u_int)(v & PAGE_MASK));
+
+ switch (req) {
+ case UIO_MEM_KMEM:
+ /*
+ * Since c is clamped to be less or equal than
+ * PAGE_SIZE, the uiomove() call does not
+ * access past the end of the direct map.
+ */
+ if (v >= kva_layout.dmap_low &&
+ v < kva_layout.dmap_high) {
+ error = uiomove((void *)v, c, uio);
+ break;
+ }
+
+ switch (uio->uio_rw) {
+ case UIO_READ:
+ prot = VM_PROT_READ;
+ break;
+ case UIO_WRITE:
+ prot = VM_PROT_WRITE;
+ break;
+ }
+
+ if (!kernacc((void *)v, c, prot)) {
+ error = EFAULT;
+ break;
+ }
+
+ /*
+ * If the extracted address is not accessible
+ * through the direct map, then we make a
+ * private (uncached) mapping because we can't
+ * depend on the existing kernel mapping
+ * remaining valid until the completion of
+ * uiomove().
+ *
+ * XXX We cannot provide access to the
+ * physical page 0 mapped into KVA.
+ */
+ v = pmap_extract(kernel_pmap, v);
+ if (v == 0) {
+ error = EFAULT;
+ break;
+ }
+ /* FALLTHROUGH */
+ case UIO_MEM_MEM:
+ if (v < dmaplimit) {
+ vd = PHYS_TO_DMAP(v);
+ error = uiomove(vd, c, uio);
+ break;
+ }
+ if (v > cpu_getmaxphyaddr()) {
+ error = EFAULT;
+ break;
+ }
+ p = pmap_mapdev(v, PAGE_SIZE);
+ error = uiomove(p, c, uio);
+ pmap_unmapdev(p, PAGE_SIZE);
+ break;
+ }
+ }
+ /*
+ * Don't return error if any byte was written. Read and write
+ * can return error only if no i/o was performed.
+ */
+ if (uio->uio_resid != orig_resid)
+ error = 0;
+ return (error);
+}
diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h
index 4b98c5d8c418..0e8fe916490b 100644
--- a/sys/amd64/include/md_var.h
+++ b/sys/amd64/include/md_var.h
@@ -106,6 +106,12 @@ void wrmsr_early_safe_start(void);
void wrmsr_early_safe_end(void);
int wrmsr_early_safe(u_int msr, uint64_t data);
+enum uiomove_mem_req {
+ UIO_MEM_KMEM = 101,
+ UIO_MEM_MEM,
+};
+int uiomove_mem(enum uiomove_mem_req req, struct uio *uio);
+
#endif /* !_MACHINE_MD_VAR_H_ */
#endif /* __i386__ */