Module Name:    src
Committed By:   bouyer
Date:           Mon Feb 20 19:14:24 UTC 2012

Modified Files:
        src/sys/uvm: uvm_km.c uvm_kmguard.c uvm_map.c

Log Message:
When using uvm_km_pgremove_intrsafe() make sure mappings are removed
before returning the pages to the free pool. Otherwise, under Xen,
a page which still has a writable mapping could be allocated for
a PDP by another CPU and the hypervisor would refuse it (this is
PR port-xen/45975).
For this, move the pmap_kremove() calls inside uvm_km_pgremove_intrsafe(),
and do pmap_kremove()/uvm_pagefree() in batch of (at most) 16 entries
(as suggested by Chuck Silvers on tech-kern@, see also
http://mail-index.netbsd.org/tech-kern/2012/02/17/msg012727.html and
followups).


To generate a diff of this commit:
cvs rdiff -u -r1.121 -r1.122 src/sys/uvm/uvm_km.c
cvs rdiff -u -r1.9 -r1.10 src/sys/uvm/uvm_kmguard.c
cvs rdiff -u -r1.314 -r1.315 src/sys/uvm/uvm_map.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/uvm/uvm_km.c
diff -u src/sys/uvm/uvm_km.c:1.121 src/sys/uvm/uvm_km.c:1.122
--- src/sys/uvm/uvm_km.c:1.121	Sun Feb 19 00:05:56 2012
+++ src/sys/uvm/uvm_km.c	Mon Feb 20 19:14:23 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_km.c,v 1.121 2012/02/19 00:05:56 rmind Exp $	*/
+/*	$NetBSD: uvm_km.c,v 1.122 2012/02/20 19:14:23 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -120,7 +120,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_km.c,v 1.121 2012/02/19 00:05:56 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_km.c,v 1.122 2012/02/20 19:14:23 bouyer Exp $");
 
 #include "opt_uvmhist.h"
 
@@ -459,8 +459,12 @@ uvm_km_pgremove(vaddr_t startva, vaddr_t
 void
 uvm_km_pgremove_intrsafe(struct vm_map *map, vaddr_t start, vaddr_t end)
 {
+#define __PGRM_BATCH 16
 	struct vm_page *pg;
-	paddr_t pa;
+	paddr_t pa[__PGRM_BATCH];
+	int npgrm, i;
+	vaddr_t va, batch_vastart;
+
 	UVMHIST_FUNC(__func__); UVMHIST_CALLED(maphist);
 
 	KASSERT(VM_MAP_IS_KERNEL(map));
@@ -468,16 +472,30 @@ uvm_km_pgremove_intrsafe(struct vm_map *
 	KASSERT(start < end);
 	KASSERT(end <= vm_map_max(map));
 
-	for (; start < end; start += PAGE_SIZE) {
-		if (!pmap_extract(pmap_kernel(), start, &pa)) {
-			continue;
+	for (va = start; va < end;) {
+		batch_vastart = va;
+		/* create a batch of at most __PGRM_BATCH pages to free */
+		for (i = 0;
+		     i < __PGRM_BATCH && va < end;
+		     va += PAGE_SIZE) {
+			if (!pmap_extract(pmap_kernel(), va, &pa[i])) {
+				continue;
+			}
+			i++;
+		}
+		npgrm = i;
+		/* now remove the mappings */
+		pmap_kremove(batch_vastart, PAGE_SIZE * npgrm);
+		/* and free the pages */
+		for (i = 0; i < npgrm; i++) {
+			pg = PHYS_TO_VM_PAGE(pa[i]);
+			KASSERT(pg);
+			KASSERT(pg->uobject == NULL && pg->uanon == NULL);
+			KASSERT((pg->flags & PG_BUSY) == 0);
+			uvm_pagefree(pg);
 		}
-		pg = PHYS_TO_VM_PAGE(pa);
-		KASSERT(pg);
-		KASSERT(pg->uobject == NULL && pg->uanon == NULL);
-		KASSERT((pg->flags & PG_BUSY) == 0);
-		uvm_pagefree(pg);
 	}
+#undef __PGRM_BATCH
 }
 
 #if defined(DEBUG)
@@ -668,7 +686,6 @@ uvm_km_free(struct vm_map *map, vaddr_t 
 		 * remove it after.  See comment below about KVA visibility.
 		 */
 		uvm_km_pgremove_intrsafe(map, addr, addr + size);
-		pmap_kremove(addr, size);
 	}
 
 	/*
@@ -745,7 +762,6 @@ again:
 			} else {
 				uvm_km_pgremove_intrsafe(kernel_map, va,
 				    va + size);
-				pmap_kremove(va, size);
 				vmem_free(kmem_va_arena, va, size);
 				return ENOMEM;
 			}
@@ -781,7 +797,6 @@ uvm_km_kmem_free(vmem_t *vm, vmem_addr_t
 	}
 #endif /* PMAP_UNMAP_POOLPAGE */
 	uvm_km_pgremove_intrsafe(kernel_map, addr, addr + size);
-	pmap_kremove(addr, size);
 	pmap_update(pmap_kernel());
 
 	vmem_free(vm, addr, size);

Index: src/sys/uvm/uvm_kmguard.c
diff -u src/sys/uvm/uvm_kmguard.c:1.9 src/sys/uvm/uvm_kmguard.c:1.10
--- src/sys/uvm/uvm_kmguard.c:1.9	Sun Feb  5 11:08:06 2012
+++ src/sys/uvm/uvm_kmguard.c	Mon Feb 20 19:14:23 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_kmguard.c,v 1.9 2012/02/05 11:08:06 rmind Exp $	*/
+/*	$NetBSD: uvm_kmguard.c,v 1.10 2012/02/20 19:14:23 bouyer Exp $	*/
 
 /*-
  * Copyright (c) 2009 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_kmguard.c,v 1.9 2012/02/05 11:08:06 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_kmguard.c,v 1.10 2012/02/20 19:14:23 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -180,7 +180,6 @@ uvm_kmguard_free(struct uvm_kmguard *kg,
 	 */
 
 	uvm_km_pgremove_intrsafe(kernel_map, va, va + PAGE_SIZE * 2);
-	pmap_kremove(va, PAGE_SIZE * 2);
 	pmap_update(pmap_kernel());
 
 	/*

Index: src/sys/uvm/uvm_map.c
diff -u src/sys/uvm/uvm_map.c:1.314 src/sys/uvm/uvm_map.c:1.315
--- src/sys/uvm/uvm_map.c:1.314	Sun Feb 19 00:05:56 2012
+++ src/sys/uvm/uvm_map.c	Mon Feb 20 19:14:23 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: uvm_map.c,v 1.314 2012/02/19 00:05:56 rmind Exp $	*/
+/*	$NetBSD: uvm_map.c,v 1.315 2012/02/20 19:14:23 bouyer Exp $	*/
 
 /*
  * Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.314 2012/02/19 00:05:56 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_map.c,v 1.315 2012/02/20 19:14:23 bouyer Exp $");
 
 #include "opt_ddb.h"
 #include "opt_uvmhist.h"
@@ -2221,7 +2221,6 @@ uvm_unmap_remove(struct vm_map *map, vad
 			if ((entry->flags & UVM_MAP_KMAPENT) == 0) {
 				uvm_km_pgremove_intrsafe(map, entry->start,
 				    entry->end);
-				pmap_kremove(entry->start, len);
 			}
 		} else if (UVM_ET_ISOBJ(entry) &&
 			   UVM_OBJ_IS_KERN_OBJECT(entry->object.uvm_obj)) {

Reply via email to