Module Name: src Committed By: rmind Date: Sun Feb 5 03:40:08 UTC 2012
Modified Files: src/sys/kern: subr_kmem.c src/sys/sys: kmem.h src/sys/uvm: uvm_kmguard.c uvm_kmguard.h Log Message: - Make KMGUARD interrupt-safe. - kmem_intr_{alloc,free}: remove workaround. Changes affect KMGUARD-enabled debug kernels only. To generate a diff of this commit: cvs rdiff -u -r1.41 -r1.42 src/sys/kern/subr_kmem.c cvs rdiff -u -r1.8 -r1.9 src/sys/sys/kmem.h cvs rdiff -u -r1.7 -r1.8 src/sys/uvm/uvm_kmguard.c cvs rdiff -u -r1.1 -r1.2 src/sys/uvm/uvm_kmguard.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/subr_kmem.c diff -u src/sys/kern/subr_kmem.c:1.41 src/sys/kern/subr_kmem.c:1.42 --- src/sys/kern/subr_kmem.c:1.41 Mon Jan 30 21:05:40 2012 +++ src/sys/kern/subr_kmem.c Sun Feb 5 03:40:08 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: subr_kmem.c,v 1.41 2012/01/30 21:05:40 rmind Exp $ */ +/* $NetBSD: subr_kmem.c,v 1.42 2012/02/05 03:40:08 rmind Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -61,7 +61,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: subr_kmem.c,v 1.41 2012/01/30 21:05:40 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: subr_kmem.c,v 1.42 2012/02/05 03:40:08 rmind Exp $"); #include <sys/param.h> #include <sys/callback.h> @@ -170,8 +170,7 @@ kmem_intr_alloc(size_t size, km_flag_t k KASSERT(size > 0); #ifdef KMEM_GUARD - if (size <= kmem_guard_size && - __builtin_return_address(0) == &kmem_alloc) { + if (size <= kmem_guard_size) { return uvm_kmguard_alloc(&kmem_guard, size, (kmflags & KM_SLEEP) != 0); } @@ -220,8 +219,7 @@ kmem_intr_free(void *p, size_t size) KASSERT(size > 0); #ifdef KMEM_GUARD - if (size <= kmem_guard_size && - __builtin_return_address(0) == &kmem_free) { + if (size <= kmem_guard_size) { uvm_kmguard_free(&kmem_guard, size, p); return; } @@ -344,7 +342,7 @@ kmem_init(void) #ifdef KMEM_GUARD uvm_kmguard_init(&kmem_guard, &kmem_guard_depth, &kmem_guard_size, - kernel_map); + kmem_va_arena); #endif kmem_create_caches(kmem_cache_sizes, kmem_cache, KMEM_MAXSIZE); } Index: src/sys/sys/kmem.h diff -u src/sys/sys/kmem.h:1.8 src/sys/sys/kmem.h:1.9 --- src/sys/sys/kmem.h:1.8 Sat Jan 28 23:09:07 2012 +++ src/sys/sys/kmem.h Sun Feb 5 03:40:08 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: kmem.h,v 1.8 2012/01/28 23:09:07 rmind Exp $ */ +/* $NetBSD: kmem.h,v 1.9 2012/02/05 03:40:08 rmind Exp $ */ /*- * Copyright (c)2006 YAMAMOTO Takashi, @@ -42,7 +42,7 @@ void kmem_free(void *, size_t); void * kmem_intr_alloc(size_t, km_flag_t); void * kmem_intr_zalloc(size_t, km_flag_t); -void kmem_intr_free(void *, size_t size); +void kmem_intr_free(void *, size_t); char * kmem_asprintf(const char *, ...) __printflike(1, 2); Index: src/sys/uvm/uvm_kmguard.c diff -u src/sys/uvm/uvm_kmguard.c:1.7 src/sys/uvm/uvm_kmguard.c:1.8 --- src/sys/uvm/uvm_kmguard.c:1.7 Sat Jan 28 00:00:06 2012 +++ src/sys/uvm/uvm_kmguard.c Sun Feb 5 03:40:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_kmguard.c,v 1.7 2012/01/28 00:00:06 rmind Exp $ */ +/* $NetBSD: uvm_kmguard.c,v 1.8 2012/02/05 03:40:07 rmind Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -37,8 +37,9 @@ * - Invalid pointer/size passed, at free * - Use-after-free */ + #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: uvm_kmguard.c,v 1.7 2012/01/28 00:00:06 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: uvm_kmguard.c,v 1.8 2012/02/05 03:40:07 rmind Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -52,8 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: uvm_kmguard. #define MAXSIZE (PAGE_SIZE - sizeof(void *)) void -uvm_kmguard_init(struct uvm_kmguard *kg, u_int *depth, size_t *size, - struct vm_map *map) +uvm_kmguard_init(struct uvm_kmguard *kg, u_int *depth, size_t *size, vmem_t *vm) { vaddr_t va; @@ -67,7 +67,7 @@ uvm_kmguard_init(struct uvm_kmguard *kg, *depth = roundup((*depth), PAGE_SIZE / sizeof(void *)); KASSERT(*depth != 0); - /* + /* * allocate fifo. */ @@ -84,7 +84,7 @@ uvm_kmguard_init(struct uvm_kmguard *kg, * init object. */ - kg->kg_map = map; + kg->kg_vmem = vm; kg->kg_fifo = (void *)va; kg->kg_depth = *depth; kg->kg_rotor = 0; @@ -96,9 +96,9 @@ void * uvm_kmguard_alloc(struct uvm_kmguard *kg, size_t len, bool waitok) { struct vm_page *pg; + vm_flag_t flags; void **p; vaddr_t va; - int flag; /* * can't handle >PAGE_SIZE allocations. let the caller handle it @@ -113,15 +113,8 @@ uvm_kmguard_alloc(struct uvm_kmguard *kg * allocate two pages of kernel VA, but do not map anything in yet. */ - if (waitok) { - flag = UVM_KMF_WAITVA; - } else { - flag = UVM_KMF_TRYLOCK | UVM_KMF_NOWAIT; - } - va = vm_map_min(kg->kg_map); - if (__predict_false(uvm_map(kg->kg_map, &va, PAGE_SIZE*2, NULL, - UVM_UNKNOWN_OFFSET, PAGE_SIZE, UVM_MAPFLAG(UVM_PROT_ALL, - UVM_PROT_ALL, UVM_INH_NONE, UVM_ADV_RANDOM, flag)) != 0)) { + flags = VM_BESTFIT | (waitok ? VM_SLEEP : VM_NOSLEEP); + if (vmem_alloc(kg->kg_vmem, PAGE_SIZE * 2, flags, &va) != 0) { return NULL; } @@ -131,7 +124,7 @@ uvm_kmguard_alloc(struct uvm_kmguard *kg */ for (;;) { - pg = uvm_pagealloc(NULL, va - vm_map_min(kg->kg_map), NULL, 0); + pg = uvm_pagealloc(NULL, va, NULL, 0); if (__predict_true(pg != NULL)) { break; } @@ -139,8 +132,7 @@ uvm_kmguard_alloc(struct uvm_kmguard *kg uvm_wait("kmguard"); /* sleep here */ continue; } else { - uvm_km_free(kg->kg_map, va, PAGE_SIZE*2, - UVM_KMF_VAONLY); + vmem_free(kg->kg_vmem, va, PAGE_SIZE * 2); return NULL; } } @@ -157,7 +149,7 @@ uvm_kmguard_alloc(struct uvm_kmguard *kg p = (void **)((va + PAGE_SIZE - len) & ~(uintptr_t)ALIGNBYTES); p[-1] = CANARY(va, len); - return (void *)p; + return (void *)p; } bool @@ -187,7 +179,7 @@ uvm_kmguard_free(struct uvm_kmguard *kg, * allocated . */ - uvm_km_pgremove_intrsafe(kg->kg_map, va, va + PAGE_SIZE * 2); + uvm_km_pgremove_intrsafe(kernel_map, va, va + PAGE_SIZE * 2); pmap_kremove(va, PAGE_SIZE * 2); pmap_update(pmap_kernel()); @@ -199,7 +191,7 @@ uvm_kmguard_free(struct uvm_kmguard *kg, rotor = atomic_inc_uint_nv(&kg->kg_rotor) % kg->kg_depth; va = (vaddr_t)atomic_swap_ptr(&kg->kg_fifo[rotor], (void *)va); if (va != 0) { - uvm_km_free(kg->kg_map, va, PAGE_SIZE*2, UVM_KMF_VAONLY); + vmem_free(kg->kg_vmem, va, PAGE_SIZE * 2); } return true; Index: src/sys/uvm/uvm_kmguard.h diff -u src/sys/uvm/uvm_kmguard.h:1.1 src/sys/uvm/uvm_kmguard.h:1.2 --- src/sys/uvm/uvm_kmguard.h:1.1 Sun Mar 29 10:51:53 2009 +++ src/sys/uvm/uvm_kmguard.h Sun Feb 5 03:40:07 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: uvm_kmguard.h,v 1.1 2009/03/29 10:51:53 ad Exp $ */ +/* $NetBSD: uvm_kmguard.h,v 1.2 2012/02/05 03:40:07 rmind Exp $ */ /*- * Copyright (c) 2009 The NetBSD Foundation, Inc. @@ -33,15 +33,14 @@ #define _UVM_KMGUARD_H_ struct uvm_kmguard { - u_int kg_depth; - intptr_t *kg_fifo; - u_int kg_rotor; - struct vm_map *kg_map; + u_int kg_depth; + intptr_t * kg_fifo; + u_int kg_rotor; + vmem_t * kg_vmem; }; -void uvm_kmguard_init(struct uvm_kmguard *, u_int *, size_t *, - struct vm_map *); -void *uvm_kmguard_alloc(struct uvm_kmguard *, size_t, bool); +void uvm_kmguard_init(struct uvm_kmguard *, u_int *, size_t *, vmem_t *); +void * uvm_kmguard_alloc(struct uvm_kmguard *, size_t, bool); bool uvm_kmguard_free(struct uvm_kmguard *, size_t, void *); #endif /* _UVM_KMGUARD_H_ */