Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Sep 2012 17:20:17 +0000 (UTC)
From:      Alan Cox <alc@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r241054 - head/sys/arm/arm
Message-ID:  <201209291720.q8THKHbq063058@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: alc
Date: Sat Sep 29 17:20:16 2012
New Revision: 241054
URL: http://svn.freebsd.org/changeset/base/241054

Log:
  Add support for mincore().  Specifically, this is an adaptation of the
  pmap_mincore() implementation that was added to the original arm pmap
  in r235717.

Modified:
  head/sys/arm/arm/pmap-v6.c

Modified: head/sys/arm/arm/pmap-v6.c
==============================================================================
--- head/sys/arm/arm/pmap-v6.c	Sat Sep 29 16:47:56 2012	(r241053)
+++ head/sys/arm/arm/pmap-v6.c	Sat Sep 29 17:20:16 2012	(r241054)
@@ -3462,9 +3462,59 @@ pmap_remove_write(vm_page_t m)
 int
 pmap_mincore(pmap_t pmap, vm_offset_t addr, vm_paddr_t *locked_pa)
 {
-	printf("pmap_mincore()\n");
-
-	return (0);
+	struct l2_bucket *l2b;
+	pt_entry_t *ptep, pte;
+	vm_paddr_t pa;
+	vm_page_t m;
+	int val;
+	boolean_t managed;
+
+	PMAP_LOCK(pmap);
+retry:
+	l2b = pmap_get_l2_bucket(pmap, addr);
+	if (l2b == NULL) {
+		val = 0;
+		goto out;
+	}
+	ptep = &l2b->l2b_kva[l2pte_index(addr)];
+	pte = *ptep;
+	if (!l2pte_valid(pte)) {
+		val = 0;
+		goto out;
+	}
+	val = MINCORE_INCORE;
+	if (L2_S_WRITABLE(pte))
+		val |= MINCORE_MODIFIED | MINCORE_MODIFIED_OTHER;
+	managed = FALSE;
+	pa = l2pte_pa(pte);
+	m = PHYS_TO_VM_PAGE(pa);
+	if (m != NULL && (m->oflags & VPO_UNMANAGED) == 0)
+		managed = TRUE;
+	if (managed) {
+		/*
+		 * The ARM pmap tries to maintain a per-mapping
+		 * reference bit.  The trouble is that it's kept in
+		 * the PV entry, not the PTE, so it's costly to access
+		 * here.  You would need to acquire the pvh global
+		 * lock, call pmap_find_pv(), and introduce a custom
+		 * version of vm_page_pa_tryrelock() that releases and
+		 * reacquires the pvh global lock.  In the end, I
+		 * doubt it's worthwhile.  This may falsely report
+		 * the given address as referenced.
+		 */
+		if ((m->md.pvh_attrs & PVF_REF) != 0)
+			val |= MINCORE_REFERENCED | MINCORE_REFERENCED_OTHER;
+	}
+	if ((val & (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER)) !=
+	    (MINCORE_MODIFIED_OTHER | MINCORE_REFERENCED_OTHER) && managed) {
+		/* Ensure that "PHYS_TO_VM_PAGE(pa)->object" doesn't change. */
+		if (vm_page_pa_tryrelock(pmap, pa, locked_pa))
+			goto retry;
+	} else
+out:
+		PA_UNLOCK_COND(*locked_pa);
+	PMAP_UNLOCK(pmap);
+	return (val);
 }
 
 void



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