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).
This commit is contained in:
parent
50a2d17c77
commit
aa488cdf00
@ -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 endva)
|
||||
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 *map, vaddr_t start, vaddr_t end)
|
||||
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 addr, vsize_t size, uvm_flag_t flags)
|
||||
* 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 addr, size_t size)
|
||||
}
|
||||
#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);
|
||||
|
@ -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, size_t len, void *p)
|
||||
*/
|
||||
|
||||
uvm_km_pgremove_intrsafe(kernel_map, va, va + PAGE_SIZE * 2);
|
||||
pmap_kremove(va, PAGE_SIZE * 2);
|
||||
pmap_update(pmap_kernel());
|
||||
|
||||
/*
|
||||
|
@ -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, vaddr_t start, vaddr_t end,
|
||||
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)) {
|
||||
|
Loading…
Reference in New Issue
Block a user