Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 Jul 2014 23:12:56 +0000 (UTC)
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r268194 - stable/10/sys/ia64/ia64
Message-ID:  <201407022312.s62NCun6056507@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: marcel
Date: Wed Jul  2 23:12:56 2014
New Revision: 268194
URL: http://svnweb.freebsd.org/changeset/base/268194

Log:
  MFC r262726: When reading physical memory, make sure to access it using
  the right memory attributes.

Modified:
  stable/10/sys/ia64/ia64/mem.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sys/ia64/ia64/mem.c
==============================================================================
--- stable/10/sys/ia64/ia64/mem.c	Wed Jul  2 23:07:01 2014	(r268193)
+++ stable/10/sys/ia64/ia64/mem.c	Wed Jul  2 23:12:56 2014	(r268194)
@@ -47,19 +47,11 @@ __FBSDID("$FreeBSD$");
 #include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/kernel.h>
-#include <sys/lock.h>
 #include <sys/malloc.h>
 #include <sys/memrange.h>
-#include <sys/module.h>
-#include <sys/msgbuf.h>
-#include <sys/mutex.h>
-#include <sys/proc.h>
-#include <sys/signalvar.h>
 #include <sys/systm.h>
 #include <sys/uio.h>
-
-#include <machine/cpu.h>
-#include <machine/frame.h>
+#include <machine/efi.h>
 
 #include <vm/vm.h>
 #include <vm/pmap.h>
@@ -69,10 +61,25 @@ __FBSDID("$FreeBSD$");
 
 struct mem_range_softc mem_range_softc;
 
-static __inline int
-ia64_pa_access(vm_offset_t pa)
+static int
+mem_phys2virt(vm_offset_t offset, int prot, void **ptr, u_long *limit)
 {
-	return (VM_PROT_READ|VM_PROT_WRITE);
+	struct efi_md *md;
+
+	if (prot & ~(VM_PROT_READ | VM_PROT_WRITE))
+		return (EPERM);
+
+	md = efi_md_find(offset);
+	if (md == NULL)
+		return (EFAULT);
+
+	if (md->md_type == EFI_MD_TYPE_BAD)
+		return (EIO);
+
+	*ptr = (void *)((md->md_attr & EFI_MD_ATTR_WB)
+	    ? IA64_PHYS_TO_RR7(offset) : IA64_PHYS_TO_RR6(offset));
+	*limit = (md->md_pages * EFI_PAGE_SIZE) - (offset - md->md_phys);
+	return (0);
 }
 
 /* ARGSUSED */
@@ -80,10 +87,15 @@ int
 memrw(struct cdev *dev, struct uio *uio, int flags)
 {
 	struct iovec *iov;
-	vm_offset_t addr, eaddr, o, v;
-	int c, error, rw;
+	off_t ofs;
+	vm_offset_t addr;
+	void *ptr;
+	u_long limit;
+	int count, error, phys, rw;
 
 	error = 0;
+	rw = (uio->uio_rw == UIO_READ) ? VM_PROT_READ : VM_PROT_WRITE;
+
 	while (uio->uio_resid > 0 && !error) {
 		iov = uio->uio_iov;
 		if (iov->iov_len == 0) {
@@ -94,51 +106,41 @@ memrw(struct cdev *dev, struct uio *uio,
 			continue;
 		}
 
-		if (dev2unit(dev) == CDEV_MINOR_MEM) {
-			v = uio->uio_offset;
-kmemphys:
-			/* Allow reads only in RAM. */
-			rw = (uio->uio_rw == UIO_READ)
-			    ? VM_PROT_READ : VM_PROT_WRITE;
-			if ((ia64_pa_access(v) & rw) != rw) {
-				error = EFAULT;
-				c = 0;
-				break;
-			}
+		ofs = uio->uio_offset;
 
-			o = uio->uio_offset & PAGE_MASK;
-			c = min(uio->uio_resid, (int)(PAGE_SIZE - o));
-			error = uiomove((caddr_t)IA64_PHYS_TO_RR7(v), c, uio);
-			continue;
+		phys = (dev2unit(dev) == CDEV_MINOR_MEM) ? 1 : 0;
+		if (phys == 0 && ofs >= IA64_RR_BASE(6)) {
+			ofs = IA64_RR_MASK(ofs);
+			phys++;
 		}
-		else if (dev2unit(dev) == CDEV_MINOR_KMEM) {
-			v = uio->uio_offset;
-
-			if (v >= IA64_RR_BASE(6)) {
-				v = IA64_RR_MASK(v);
-				goto kmemphys;
-			}
 
-			c = min(iov->iov_len, MAXPHYS);
+		if (phys) {
+			error = mem_phys2virt(ofs, rw, &ptr, &limit);
+			if (error)
+				return (error);
+
+			count = min(uio->uio_resid, limit);
+			error = uiomove(ptr, count, uio);
+		} else {
+			ptr = (void *)ofs;
+			count = iov->iov_len;
 
 			/*
 			 * Make sure that all of the pages are currently
 			 * resident so that we don't create any zero-fill
 			 * pages.
 			 */
-			addr = trunc_page(v);
-			eaddr = round_page(v + c);
+			limit = round_page(ofs + count);
+			addr = trunc_page(ofs);
 			if (addr < VM_MAXUSER_ADDRESS)
-				return (EFAULT);
-			for (; addr < eaddr; addr += PAGE_SIZE) {
+				return (EINVAL);
+			for (; addr < limit; addr += PAGE_SIZE) {
 				if (pmap_kextract(addr) == 0)
 					return (EFAULT);
 			}
-			if (!kernacc((caddr_t)v, c, (uio->uio_rw == UIO_READ)
-			    ? VM_PROT_READ : VM_PROT_WRITE))
+			if (!kernacc(ptr, count, rw))
 				return (EFAULT);
-			error = uiomove((caddr_t)v, c, uio);
-			continue;
+			error = uiomove(ptr, count, uio);
 		}
 		/* else panic! */
 	}
@@ -153,6 +155,10 @@ int
 memmmap(struct cdev *dev, vm_ooffset_t offset, vm_paddr_t *paddr,
     int prot, vm_memattr_t *memattr)
 {
+	void *ptr;
+	u_long limit;
+	int error;
+
 	/*
 	 * /dev/mem is the only one that makes sense through this
 	 * interface.  For /dev/kmem any physaddr we return here
@@ -160,13 +166,14 @@ memmmap(struct cdev *dev, vm_ooffset_t o
 	 * a later time.
 	 */
 	if (dev2unit(dev) != CDEV_MINOR_MEM)
-		return (-1);
+		return (ENXIO);
 
-	/*
-	 * Allow access only in RAM.
-	 */
-	if ((prot & ia64_pa_access(atop((vm_offset_t)offset))) != prot)
-		return (-1);
-	*paddr = IA64_PHYS_TO_RR7(offset);
+	error = mem_phys2virt(offset, prot, &ptr, &limit);
+	if (error)
+		return (error);
+
+	*paddr = offset;
+	*memattr = ((uintptr_t)ptr >= IA64_RR_BASE(7)) ?
+	    VM_MEMATTR_WRITE_BACK : VM_MEMATTR_UNCACHEABLE;
 	return (0);
 }



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