Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 31 Jul 2015 13:39:52 +0000 (UTC)
From:      Andrew Turner <andrew@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r286129 - head/sys/arm64/arm64
Message-ID:  <201507311339.t6VDdq8G035004@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: andrew
Date: Fri Jul 31 13:39:51 2015
New Revision: 286129
URL: https://svnweb.freebsd.org/changeset/base/286129

Log:
  Add memrw. This has had minimal testing, and will likely panic the kernel
  when trying to read data from outside the DMAP region. I expect this panic
  to be from within uiomove_fromphys, which needs to grow support to support
  such addresses.
  
  Obtained from:	ABT Systems Ltd
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/arm64/arm64/mem.c

Modified: head/sys/arm64/arm64/mem.c
==============================================================================
--- head/sys/arm64/arm64/mem.c	Fri Jul 31 13:34:43 2015	(r286128)
+++ head/sys/arm64/arm64/mem.c	Fri Jul 31 13:39:51 2015	(r286129)
@@ -33,15 +33,84 @@ __FBSDID("$FreeBSD$");
 #include <sys/conf.h>
 #include <sys/malloc.h>
 #include <sys/memrange.h>
+#include <sys/uio.h>
 
 #include <machine/memdev.h>
+#include <machine/vmparam.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_extern.h>
+#include <vm/vm_page.h>
 
 struct mem_range_softc mem_range_softc;
 
 int
 memrw(struct cdev *dev, struct uio *uio, int flags)
 {
+	struct iovec *iov;
+	struct vm_page m;
+	vm_page_t marr;
+	vm_offset_t off, v;
+	u_int cnt;
+	int error;
+
+	error = 0;
+
+	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;
+		off = v & PAGE_MASK;
+		cnt = ulmin(iov->iov_len, PAGE_SIZE - (u_int)off);
+		if (cnt == 0)
+			continue;
+
+		switch(dev2unit(dev)) {
+		case CDEV_MINOR_KMEM:
+			/* If the address is in the DMAP just copy it */
+			if (VIRT_IN_DMAP(v)) {
+				error = uiomove((void *)v, cnt, uio);
+				break;
+			}
+
+			if (!kernacc((void *)v, cnt, uio->uio_rw == UIO_READ ?
+			    VM_PROT_READ : VM_PROT_WRITE)) {
+				error = EFAULT;
+				break;
+			}
+
+			/* Get the physical address to read */
+			v = pmap_extract(kernel_pmap, v);
+			if (v == 0) {
+				error = EFAULT;
+				break;
+			}
+
+			/* FALLTHROUGH */
+		case CDEV_MINOR_MEM:
+			/* If within the DMAP use this to copy from */
+			if (PHYS_IN_DMAP(v)) {
+				v = PHYS_TO_DMAP(v);
+				error = uiomove((void *)v, cnt, uio);
+				break;
+			}
+
+			/* Have uiomove_fromphys handle the data */
+			m.phys_addr = trunc_page(v);
+			marr = &m;
+			uiomove_fromphys(&marr, off, cnt, uio);
+			break;
+		}
+	}
 
-	panic("ARM64TODO: memrw");
+	return (error);
 }
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201507311339.t6VDdq8G035004>