1139825Simp/*- 2148078Srwatson * Copyright (c) 2002, 2003, 2004, 2005 Jeffrey Roberson <jeff@FreeBSD.org> 3148078Srwatson * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org> 4148078Srwatson * All rights reserved. 595771Sjeff * 695771Sjeff * Redistribution and use in source and binary forms, with or without 795771Sjeff * modification, are permitted provided that the following conditions 895771Sjeff * are met: 995771Sjeff * 1. Redistributions of source code must retain the above copyright 1095771Sjeff * notice unmodified, this list of conditions, and the following 1195771Sjeff * disclaimer. 1295771Sjeff * 2. Redistributions in binary form must reproduce the above copyright 1395771Sjeff * notice, this list of conditions and the following disclaimer in the 1495771Sjeff * documentation and/or other materials provided with the distribution. 1595771Sjeff * 1695771Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1795771Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1895771Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1995771Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2095771Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2195771Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2295771Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2395771Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2495771Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2595771Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2695771Sjeff */ 2795771Sjeff 2895771Sjeff/* 2995771Sjeff * uma_dbg.c Debugging features for UMA users 3095771Sjeff * 3195771Sjeff */ 3295771Sjeff 33116226Sobrien#include <sys/cdefs.h> 34116226Sobrien__FBSDID("$FreeBSD$"); 3595771Sjeff 36301176Smarkj#include "opt_vm.h" 37301176Smarkj 3895771Sjeff#include <sys/param.h> 3995771Sjeff#include <sys/systm.h> 40251709Sjeff#include <sys/bitset.h> 4195771Sjeff#include <sys/kernel.h> 4295771Sjeff#include <sys/types.h> 4395771Sjeff#include <sys/queue.h> 4495771Sjeff#include <sys/lock.h> 4595771Sjeff#include <sys/mutex.h> 4695931Sjeff#include <sys/malloc.h> 4795771Sjeff 48103531Sjeff#include <vm/vm.h> 49103531Sjeff#include <vm/vm_object.h> 50103531Sjeff#include <vm/vm_page.h> 5195771Sjeff#include <vm/uma.h> 5295771Sjeff#include <vm/uma_int.h> 5395771Sjeff#include <vm/uma_dbg.h> 54301176Smarkj#include <vm/memguard.h> 5595771Sjeff 56249313Sglebiusstatic const uint32_t uma_junk = 0xdeadc0de; 5795771Sjeff 5895771Sjeff/* 59132987Sgreen * Checks an item to make sure it hasn't been overwritten since it was freed, 60132987Sgreen * prior to subsequent reallocation. 6195771Sjeff * 6295771Sjeff * Complies with standard ctor arg/return 6395771Sjeff */ 64132987Sgreenint 65132987Sgreentrash_ctor(void *mem, int size, void *arg, int flags) 6695771Sjeff{ 6795771Sjeff int cnt; 68249313Sglebius uint32_t *p; 6995771Sjeff 70301176Smarkj#ifdef DEBUG_MEMGUARD 71301176Smarkj if (is_memguard_addr(mem)) 72301176Smarkj return (0); 73301176Smarkj#endif 74301176Smarkj 7595771Sjeff cnt = size / sizeof(uma_junk); 7695771Sjeff 7795771Sjeff for (p = mem; cnt > 0; cnt--, p++) 78147615Ssilby if (*p != uma_junk) { 79284861Sjmg#ifdef INVARIANTS 80284861Sjmg panic("Memory modified after free %p(%d) val=%x @ %p\n", 81284861Sjmg mem, size, *p, p); 82284861Sjmg#else 83147615Ssilby printf("Memory modified after free %p(%d) val=%x @ %p\n", 84120526Sphk mem, size, *p, p); 85284861Sjmg#endif 86147615Ssilby return (0); 87147615Ssilby } 88132987Sgreen return (0); 8995771Sjeff} 9095771Sjeff 9195771Sjeff/* 9295771Sjeff * Fills an item with predictable garbage 9395771Sjeff * 9495771Sjeff * Complies with standard dtor arg/return 9595771Sjeff * 9695771Sjeff */ 9795771Sjeffvoid 9895771Sjefftrash_dtor(void *mem, int size, void *arg) 9995771Sjeff{ 10095771Sjeff int cnt; 101249313Sglebius uint32_t *p; 10295771Sjeff 103301176Smarkj#ifdef DEBUG_MEMGUARD 104301176Smarkj if (is_memguard_addr(mem)) 105301176Smarkj return; 106301176Smarkj#endif 107301176Smarkj 10895771Sjeff cnt = size / sizeof(uma_junk); 10995771Sjeff 11095771Sjeff for (p = mem; cnt > 0; cnt--, p++) 11195771Sjeff *p = uma_junk; 11295771Sjeff} 11395771Sjeff 11495771Sjeff/* 11595771Sjeff * Fills an item with predictable garbage 11695771Sjeff * 11795771Sjeff * Complies with standard init arg/return 11895771Sjeff * 11995771Sjeff */ 120132987Sgreenint 121132987Sgreentrash_init(void *mem, int size, int flags) 12295771Sjeff{ 12395771Sjeff trash_dtor(mem, size, NULL); 124132987Sgreen return (0); 12595771Sjeff} 12695771Sjeff 12795771Sjeff/* 12895771Sjeff * Checks an item to make sure it hasn't been overwritten since it was freed. 12995771Sjeff * 13095771Sjeff * Complies with standard fini arg/return 13195771Sjeff * 13295771Sjeff */ 13395771Sjeffvoid 13495771Sjefftrash_fini(void *mem, int size) 13595771Sjeff{ 136132987Sgreen (void)trash_ctor(mem, size, NULL, 0); 13795771Sjeff} 13895899Sjeff 139132987Sgreenint 140132987Sgreenmtrash_ctor(void *mem, int size, void *arg, int flags) 14195931Sjeff{ 14295931Sjeff struct malloc_type **ksp; 143249313Sglebius uint32_t *p = mem; 14495931Sjeff int cnt; 14595931Sjeff 146301176Smarkj#ifdef DEBUG_MEMGUARD 147301176Smarkj if (is_memguard_addr(mem)) 148301176Smarkj return (0); 149301176Smarkj#endif 150301176Smarkj 15195931Sjeff size -= sizeof(struct malloc_type *); 15295931Sjeff ksp = (struct malloc_type **)mem; 15395931Sjeff ksp += size / sizeof(struct malloc_type *); 15495931Sjeff cnt = size / sizeof(uma_junk); 15595931Sjeff 15695931Sjeff for (p = mem; cnt > 0; cnt--, p++) 15795931Sjeff if (*p != uma_junk) { 158120526Sphk printf("Memory modified after free %p(%d) val=%x @ %p\n", 159120526Sphk mem, size, *p, p); 16095931Sjeff panic("Most recently used by %s\n", (*ksp == NULL)? 16195931Sjeff "none" : (*ksp)->ks_shortdesc); 16295931Sjeff } 163132987Sgreen return (0); 16495931Sjeff} 16595931Sjeff 16695931Sjeff/* 16795931Sjeff * Fills an item with predictable garbage 16895931Sjeff * 16995931Sjeff * Complies with standard dtor arg/return 17095931Sjeff * 17195931Sjeff */ 17295931Sjeffvoid 17395931Sjeffmtrash_dtor(void *mem, int size, void *arg) 17495931Sjeff{ 17595931Sjeff int cnt; 176249313Sglebius uint32_t *p; 17795931Sjeff 178301176Smarkj#ifdef DEBUG_MEMGUARD 179301176Smarkj if (is_memguard_addr(mem)) 180301176Smarkj return; 181301176Smarkj#endif 182301176Smarkj 18395931Sjeff size -= sizeof(struct malloc_type *); 18495931Sjeff cnt = size / sizeof(uma_junk); 18595931Sjeff 18695931Sjeff for (p = mem; cnt > 0; cnt--, p++) 18795931Sjeff *p = uma_junk; 18895931Sjeff} 18995931Sjeff 19095931Sjeff/* 19195931Sjeff * Fills an item with predictable garbage 19295931Sjeff * 19395931Sjeff * Complies with standard init arg/return 19495931Sjeff * 19595931Sjeff */ 196132987Sgreenint 197132987Sgreenmtrash_init(void *mem, int size, int flags) 19895931Sjeff{ 19995931Sjeff struct malloc_type **ksp; 20095931Sjeff 201301176Smarkj#ifdef DEBUG_MEMGUARD 202301176Smarkj if (is_memguard_addr(mem)) 203301176Smarkj return (0); 204301176Smarkj#endif 205301176Smarkj 20695931Sjeff mtrash_dtor(mem, size, NULL); 20795931Sjeff 20895931Sjeff ksp = (struct malloc_type **)mem; 20995931Sjeff ksp += (size / sizeof(struct malloc_type *)) - 1; 21095931Sjeff *ksp = NULL; 211132987Sgreen return (0); 21295931Sjeff} 21395931Sjeff 21495931Sjeff/* 215132987Sgreen * Checks an item to make sure it hasn't been overwritten since it was freed, 216132987Sgreen * prior to freeing it back to available memory. 21795931Sjeff * 21895931Sjeff * Complies with standard fini arg/return 21995931Sjeff * 22095931Sjeff */ 22195931Sjeffvoid 22295931Sjeffmtrash_fini(void *mem, int size) 22395931Sjeff{ 224132987Sgreen (void)mtrash_ctor(mem, size, NULL, 0); 22595931Sjeff} 226