Index: kern/vfs_bio.c
===================================================================
--- kern/vfs_bio.c	(revision 209902)
+++ kern/vfs_bio.c	(working copy)
@@ -1356,9 +1356,7 @@ brelse(struct buf *bp)
 				}
 
 				if ((bp->b_flags & B_INVAL) == 0) {
-					pmap_qenter(
-					    trunc_page((vm_offset_t)bp->b_data),
-					    bp->b_pages, bp->b_npages);
+					pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 				}
 				m = bp->b_pages[i];
 			}
@@ -1611,7 +1609,7 @@ vfs_vmio_release(struct buf *bp)
 		vm_page_unlock(m);
 	}
 	VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object);
-	pmap_qremove(trunc_page((vm_offset_t) bp->b_data), bp->b_npages);
+	pmap_unmap_buf(bp, 0);
 	
 	if (bp->b_bufsize) {
 		bufspacewakeup();
@@ -2984,8 +2982,7 @@ allocbuf(struct buf *bp, int size)
 					vm_page_unlock(m);
 				}
 				VM_OBJECT_UNLOCK(bp->b_bufobj->bo_object);
-				pmap_qremove((vm_offset_t) trunc_page((vm_offset_t)bp->b_data) +
-				    (desiredpages << PAGE_SHIFT), (bp->b_npages - desiredpages));
+				pmap_unmap_buf(bp, desiredpages);
 				bp->b_npages = desiredpages;
 			}
 		} else if (size > bp->b_bcount) {
@@ -3076,16 +3073,7 @@ allocbuf(struct buf *bp, int size)
 			 * bp->b_offset may be offset into the first page.
 			 */
 
-			bp->b_data = (caddr_t)
-			    trunc_page((vm_offset_t)bp->b_data);
-			pmap_qenter(
-			    (vm_offset_t)bp->b_data,
-			    bp->b_pages, 
-			    bp->b_npages
-			);
-			
-			bp->b_data = (caddr_t)((vm_offset_t)bp->b_data | 
-			    (vm_offset_t)(bp->b_offset & PAGE_MASK));
+			pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 		}
 	}
 	if (newbsize < bp->b_bufsize)
@@ -3404,8 +3392,7 @@ bufdone_finish(struct buf *bp)
 		vm_object_pip_wakeupn(obj, 0);
 		VM_OBJECT_UNLOCK(obj);
 		if (bogus)
-			pmap_qenter(trunc_page((vm_offset_t)bp->b_data),
-			    bp->b_pages, bp->b_npages);
+			pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 	}
 
 	/*
@@ -3448,8 +3435,7 @@ vfs_unbusy_pages(struct buf *bp)
 			if (!m)
 				panic("vfs_unbusy_pages: page missing\n");
 			bp->b_pages[i] = m;
-			pmap_qenter(trunc_page((vm_offset_t)bp->b_data),
-			    bp->b_pages, bp->b_npages);
+			pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 		}
 		vm_object_pip_subtract(obj, 1);
 		vm_page_io_finish(m);
@@ -3615,8 +3601,7 @@ vfs_busy_pages(struct buf *bp, int clear_modify)
 	}
 	VM_OBJECT_UNLOCK(obj);
 	if (bogus)
-		pmap_qenter(trunc_page((vm_offset_t)bp->b_data),
-		    bp->b_pages, bp->b_npages);
+		pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 }
 
 /*
@@ -3800,7 +3785,7 @@ vm_hold_free_pages(struct buf *bp, int newbsize)
 int
 vmapbuf(struct buf *bp)
 {
-	caddr_t addr, kva;
+	caddr_t addr;
 	vm_prot_t prot;
 	int pidx, i;
 	struct vm_page *m;
@@ -3840,12 +3825,10 @@ retry:
 	}
 	if (pidx > btoc(MAXPHYS))
 		panic("vmapbuf: mapped more than MAXPHYS");
-	pmap_qenter((vm_offset_t)bp->b_saveaddr, bp->b_pages, pidx);
 	
-	kva = bp->b_saveaddr;
 	bp->b_npages = pidx;
 	bp->b_saveaddr = bp->b_data;
-	bp->b_data = kva + (((vm_offset_t) bp->b_data) & PAGE_MASK);
+	pmap_map_buf(bp, (vm_offset_t)bp->b_data & PAGE_MASK);
 	return(0);
 }
 
@@ -3860,7 +3843,7 @@ vunmapbuf(struct buf *bp)
 	int npages;
 
 	npages = bp->b_npages;
-	pmap_qremove(trunc_page((vm_offset_t)bp->b_data), npages);
+	pmap_unmap_buf(bp, 0);
 	for (pidx = 0; pidx < npages; pidx++) {
 		vm_page_lock(bp->b_pages[pidx]);
 		vm_page_unhold(bp->b_pages[pidx]);
Index: kern/vfs_cluster.c
===================================================================
--- kern/vfs_cluster.c	(revision 209864)
+++ kern/vfs_cluster.c	(working copy)
@@ -499,8 +499,7 @@ cluster_rbuild(vp, filesize, lbn, blkno, size, run
 		    bp->b_bufsize, bp->b_kvasize);
 	bp->b_kvasize = bp->b_bufsize;
 
-	pmap_qenter(trunc_page((vm_offset_t) bp->b_data),
-		(vm_page_t *)bp->b_pages, bp->b_npages);
+	pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 	return (bp);
 }
 
@@ -523,7 +522,7 @@ cluster_callback(bp)
 	if (bp->b_ioflags & BIO_ERROR)
 		error = bp->b_error;
 
-	pmap_qremove(trunc_page((vm_offset_t) bp->b_data), bp->b_npages);
+	pmap_unmap_buf(bp, 0);
 	/*
 	 * Move memory from the large cluster buffer into the component
 	 * buffers and mark IO as done on these.
@@ -956,8 +955,7 @@ cluster_wbuild(vp, size, start_lbn, len)
 				tbp, b_cluster.cluster_entry);
 		}
 	finishcluster:
-		pmap_qenter(trunc_page((vm_offset_t) bp->b_data),
-			(vm_page_t *) bp->b_pages, bp->b_npages);
+		pmap_map_buf(bp, bp->b_offset & PAGE_MASK);
 		if (bp->b_bufsize > bp->b_kvasize)
 			panic(
 			    "cluster_wbuild: b_bufsize(%ld) > b_kvasize(%d)\n",
Index: vm/pmap.h
===================================================================
--- vm/pmap.h	(revision 209864)
+++ vm/pmap.h	(working copy)
@@ -89,6 +89,7 @@ typedef struct pmap_statistics *pmap_statistics_t;
 #include <machine/pmap.h>
 
 #ifdef _KERNEL
+struct buf;
 struct thread;
 
 /*
@@ -122,6 +123,7 @@ boolean_t	 pmap_is_prefaultable(pmap_t pmap, vm_of
 boolean_t	 pmap_is_referenced(vm_page_t m);
 boolean_t	 pmap_ts_referenced(vm_page_t m);
 vm_offset_t	 pmap_map(vm_offset_t *, vm_paddr_t, vm_paddr_t, int);
+void		 pmap_map_buf(struct buf *bp, u_int offset);
 int		 pmap_mincore(pmap_t pmap, vm_offset_t addr,
 		    vm_paddr_t *locked_pa);
 void		 pmap_object_init_pt(pmap_t pmap, vm_offset_t addr,
@@ -140,6 +142,7 @@ void		 pmap_remove_all(vm_page_t m);
 void		 pmap_remove_pages(pmap_t);
 void		 pmap_remove_write(vm_page_t m);
 void		 pmap_sync_icache(pmap_t, vm_offset_t, vm_size_t);
+void		 pmap_unmap_buf(struct buf *bp, int desiredpages);
 void		 pmap_zero_page(vm_page_t);
 void		 pmap_zero_page_area(vm_page_t, int off, int size);
 void		 pmap_zero_page_idle(vm_page_t);
Index: vm/vnode_pager.c
===================================================================
--- vm/vnode_pager.c	(revision 209864)
+++ vm/vnode_pager.c	(working copy)
@@ -682,7 +682,6 @@ vnode_pager_generic_getpages(vp, m, bytecount, req
 	int reqpage;
 {
 	vm_object_t object;
-	vm_offset_t kva;
 	off_t foff, tfoff, nextoff;
 	int i, j, size, bsize, first;
 	daddr_t firstaddr, reqblock;
@@ -892,12 +891,13 @@ vnode_pager_generic_getpages(vp, m, bytecount, req
 	}
 
 	bp = getpbuf(&vnode_pbuf_freecnt);
-	kva = (vm_offset_t) bp->b_data;
+	bp->b_npages = count;
+	bcopy(m, bp->b_pages, count * sizeof(vm_page_t));
 
 	/*
 	 * and map the pages to be read into the kva
 	 */
-	pmap_qenter(kva, m, count);
+	pmap_map_buf(bp, 0);
 
 	/* build a minimal buffer header */
 	bp->b_iocmd = BIO_READ;
@@ -927,9 +927,9 @@ vnode_pager_generic_getpages(vp, m, bytecount, req
 
 	if (!error) {
 		if (size != count * PAGE_SIZE)
-			bzero((caddr_t) kva + size, PAGE_SIZE * count - size);
+			bzero(bp->b_data + size, PAGE_SIZE * count - size);
 	}
-	pmap_qremove(kva, count);
+	pmap_unmap_buf(bp, 0);
 
 	/*
 	 * free the buffer header back to the swap buffer pool
Index: amd64/amd64/pmap.c
===================================================================
--- amd64/amd64/pmap.c	(revision 209887)
+++ amd64/amd64/pmap.c	(working copy)
@@ -110,6 +110,7 @@ __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
 #include <sys/systm.h>
+#include <sys/buf.h>
 #include <sys/kernel.h>
 #include <sys/ktr.h>
 #include <sys/lock.h>
@@ -1318,8 +1319,49 @@ pmap_map(vm_offset_t *virt, vm_paddr_t start, vm_p
 	return PHYS_TO_DMAP(start);
 }
 
+u_int counters[2];
+SYSCTL_OPAQUE(_debug, OID_AUTO, counters, CTLFLAG_RW, counters,
+    sizeof(counters), "IU", "");
 
 /*
+ * XXX
+ */
+void
+pmap_map_buf(struct buf *bp, u_int offset)
+{
+	int i;
+
+	if (bp->b_npages > 0) {
+		for (i = 1; i < bp->b_npages; i++)
+			if (bp->b_pages[i - 1] + 1 != bp->b_pages[i])
+				break;
+		if (i != bp->b_npages) {
+			pmap_qenter((vm_offset_t)bp->b_kvabase, bp->b_pages,
+			    bp->b_npages);
+			bp->b_data = bp->b_kvabase + offset;
+		} else
+			bp->b_data = (caddr_t)
+			    PHYS_TO_DMAP(VM_PAGE_TO_PHYS(bp->b_pages[0])) +
+			    offset;
+		/* XXX */
+		atomic_add_int(&counters[i == bp->b_npages], 1);
+	}
+}
+
+/*
+ * XXX
+ */
+void
+pmap_unmap_buf(struct buf *bp, int desiredpages)
+{
+
+	if ((vm_offset_t)bp->b_data >= DMAP_MAX_ADDRESS)
+		pmap_qremove(trunc_page((vm_offset_t)bp->b_data) +
+		    (desiredpages << PAGE_SHIFT), bp->b_npages - desiredpages);
+}
+
+
+/*
  * Add a list of wired pages to the kva
  * this routine is only used for temporary
  * kernel mappings that do not need to have
