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)) {