svn commit: r252646 - head/sys/amd64/amd64

Neel Natu neel at FreeBSD.org
Wed Jul 3 23:21:25 UTC 2013


Author: neel
Date: Wed Jul  3 23:21:25 2013
New Revision: 252646
URL: http://svnweb.freebsd.org/changeset/base/252646

Log:
  If a superpage mapping is being removed then we need to ignore the PG_PDE_PAT
  bit when looking up the vm_page associated with the superpage's physical
  address.
  
  If the caching attribute for the mapping is write combining or write protected
  then the PG_PDE_PAT bit will be set and thus cause an 'off-by-one' error
  when looking up the vm_page.
  
  Fix this by using the PG_PS_FRAME mask to compute the physical address for
  a superpage mapping instead of PG_FRAME.
  
  This is a theoretical issue at this point since non-writeback attributes are
  currently used only for fictitious mappings and fictitious mappings are not
  subject to promotion.
  
  Discussed with:	alc, kib
  MFC after:	2 weeks

Modified:
  head/sys/amd64/amd64/pmap.c

Modified: head/sys/amd64/amd64/pmap.c
==============================================================================
--- head/sys/amd64/amd64/pmap.c	Wed Jul  3 23:19:57 2013	(r252645)
+++ head/sys/amd64/amd64/pmap.c	Wed Jul  3 23:21:25 2013	(r252646)
@@ -4400,6 +4400,7 @@ pmap_remove_pages(pmap_t pmap)
 	int64_t bit;
 	uint64_t inuse, bitmask;
 	int allfree, field, freed, idx;
+	vm_paddr_t pa;
 
 	if (pmap != PCPU_GET(curpmap)) {
 		printf("warning: pmap_remove_pages called with non-current pmap\n");
@@ -4429,7 +4430,7 @@ pmap_remove_pages(pmap_t pmap)
 					pte = (pt_entry_t *)PHYS_TO_DMAP(tpte &
 					    PG_FRAME);
 					pte = &pte[pmap_pte_index(pv->pv_va)];
-					tpte = *pte & ~PG_PTE_PAT;
+					tpte = *pte;
 				}
 				if ((tpte & PG_V) == 0) {
 					panic("bad pte va %lx pte %lx",
@@ -4444,8 +4445,13 @@ pmap_remove_pages(pmap_t pmap)
 					continue;
 				}
 
-				m = PHYS_TO_VM_PAGE(tpte & PG_FRAME);
-				KASSERT(m->phys_addr == (tpte & PG_FRAME),
+				if (tpte & PG_PS)
+					pa = tpte & PG_PS_FRAME;
+				else
+					pa = tpte & PG_FRAME;
+
+				m = PHYS_TO_VM_PAGE(pa);
+				KASSERT(m->phys_addr == pa,
 				    ("vm_page_t %p phys_addr mismatch %016jx %016jx",
 				    m, (uintmax_t)m->phys_addr,
 				    (uintmax_t)tpte));


More information about the svn-src-all mailing list