18efc4effSJeff Roberson /* 28efc4effSJeff Roberson * Copyright (c) 2002, Jeffrey Roberson <jroberson@chesapeake.net> 38efc4effSJeff Roberson * All rights reserved. 48efc4effSJeff Roberson * 58efc4effSJeff Roberson * Redistribution and use in source and binary forms, with or without 68efc4effSJeff Roberson * modification, are permitted provided that the following conditions 78efc4effSJeff Roberson * are met: 88efc4effSJeff Roberson * 1. Redistributions of source code must retain the above copyright 98efc4effSJeff Roberson * notice unmodified, this list of conditions, and the following 108efc4effSJeff Roberson * disclaimer. 118efc4effSJeff Roberson * 2. Redistributions in binary form must reproduce the above copyright 128efc4effSJeff Roberson * notice, this list of conditions and the following disclaimer in the 138efc4effSJeff Roberson * documentation and/or other materials provided with the distribution. 148efc4effSJeff Roberson * 158efc4effSJeff Roberson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 168efc4effSJeff Roberson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 178efc4effSJeff Roberson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 188efc4effSJeff Roberson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 198efc4effSJeff Roberson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 208efc4effSJeff Roberson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 218efc4effSJeff Roberson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 228efc4effSJeff Roberson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 238efc4effSJeff Roberson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 248efc4effSJeff Roberson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 258efc4effSJeff Roberson * 268efc4effSJeff Roberson * $FreeBSD$ 278efc4effSJeff Roberson * 288efc4effSJeff Roberson */ 298efc4effSJeff Roberson 308efc4effSJeff Roberson /* 318efc4effSJeff Roberson * uma_dbg.c Debugging features for UMA users 328efc4effSJeff Roberson * 338efc4effSJeff Roberson */ 348efc4effSJeff Roberson 358efc4effSJeff Roberson 368efc4effSJeff Roberson #include <sys/param.h> 378efc4effSJeff Roberson #include <sys/systm.h> 388efc4effSJeff Roberson #include <sys/kernel.h> 398efc4effSJeff Roberson #include <sys/types.h> 408efc4effSJeff Roberson #include <sys/queue.h> 418efc4effSJeff Roberson #include <sys/lock.h> 428efc4effSJeff Roberson #include <sys/mutex.h> 438efc4effSJeff Roberson 448efc4effSJeff Roberson #include <machine/types.h> 458efc4effSJeff Roberson 468efc4effSJeff Roberson #include <vm/uma.h> 478efc4effSJeff Roberson #include <vm/uma_int.h> 488efc4effSJeff Roberson #include <vm/uma_dbg.h> 498efc4effSJeff Roberson 508efc4effSJeff Roberson static const u_int32_t uma_junk = 0xdeadc0de; 518efc4effSJeff Roberson 528efc4effSJeff Roberson /* 538efc4effSJeff Roberson * Checks an item to make sure it hasn't been overwritten since freed. 548efc4effSJeff Roberson * 558efc4effSJeff Roberson * Complies with standard ctor arg/return 568efc4effSJeff Roberson * 578efc4effSJeff Roberson */ 588efc4effSJeff Roberson void 598efc4effSJeff Roberson trash_ctor(void *mem, int size, void *arg) 608efc4effSJeff Roberson { 618efc4effSJeff Roberson int cnt; 628efc4effSJeff Roberson u_int32_t *p; 638efc4effSJeff Roberson 648efc4effSJeff Roberson cnt = size / sizeof(uma_junk); 658efc4effSJeff Roberson 668efc4effSJeff Roberson for (p = mem; cnt > 0; cnt--, p++) 678efc4effSJeff Roberson if (*p != uma_junk) 688efc4effSJeff Roberson panic("Memory modified after free %p(%d)\n", 698efc4effSJeff Roberson mem, size); 708efc4effSJeff Roberson } 718efc4effSJeff Roberson 728efc4effSJeff Roberson /* 738efc4effSJeff Roberson * Fills an item with predictable garbage 748efc4effSJeff Roberson * 758efc4effSJeff Roberson * Complies with standard dtor arg/return 768efc4effSJeff Roberson * 778efc4effSJeff Roberson */ 788efc4effSJeff Roberson void 798efc4effSJeff Roberson trash_dtor(void *mem, int size, void *arg) 808efc4effSJeff Roberson { 818efc4effSJeff Roberson int cnt; 828efc4effSJeff Roberson u_int32_t *p; 838efc4effSJeff Roberson 848efc4effSJeff Roberson cnt = size / sizeof(uma_junk); 858efc4effSJeff Roberson 868efc4effSJeff Roberson for (p = mem; cnt > 0; cnt--, p++) 878efc4effSJeff Roberson *p = uma_junk; 888efc4effSJeff Roberson } 898efc4effSJeff Roberson 908efc4effSJeff Roberson /* 918efc4effSJeff Roberson * Fills an item with predictable garbage 928efc4effSJeff Roberson * 938efc4effSJeff Roberson * Complies with standard init arg/return 948efc4effSJeff Roberson * 958efc4effSJeff Roberson */ 968efc4effSJeff Roberson void 978efc4effSJeff Roberson trash_init(void *mem, int size) 988efc4effSJeff Roberson { 998efc4effSJeff Roberson trash_dtor(mem, size, NULL); 1008efc4effSJeff Roberson } 1018efc4effSJeff Roberson 1028efc4effSJeff Roberson /* 1038efc4effSJeff Roberson * Checks an item to make sure it hasn't been overwritten since it was freed. 1048efc4effSJeff Roberson * 1058efc4effSJeff Roberson * Complies with standard fini arg/return 1068efc4effSJeff Roberson * 1078efc4effSJeff Roberson */ 1088efc4effSJeff Roberson void 1098efc4effSJeff Roberson trash_fini(void *mem, int size) 1108efc4effSJeff Roberson { 1118efc4effSJeff Roberson trash_ctor(mem, size, NULL); 1128efc4effSJeff Roberson } 113639c9550SJeff Roberson 114639c9550SJeff Roberson static uma_slab_t 115639c9550SJeff Roberson uma_dbg_getslab(uma_zone_t zone, void *item) 116639c9550SJeff Roberson { 117639c9550SJeff Roberson uma_slab_t slab; 118639c9550SJeff Roberson u_int8_t *mem; 119639c9550SJeff Roberson 120639c9550SJeff Roberson mem = (u_int8_t *)((unsigned long)item & (~UMA_SLAB_MASK)); 121639c9550SJeff Roberson if (zone->uz_flags & UMA_ZFLAG_MALLOC) { 122639c9550SJeff Roberson slab = hash_sfind(mallochash, mem); 123639c9550SJeff Roberson } else if (zone->uz_flags & UMA_ZFLAG_OFFPAGE) { 124639c9550SJeff Roberson ZONE_LOCK(zone); 125639c9550SJeff Roberson slab = hash_sfind(&zone->uz_hash, mem); 126639c9550SJeff Roberson ZONE_UNLOCK(zone); 127639c9550SJeff Roberson } else { 128639c9550SJeff Roberson mem += zone->uz_pgoff; 129639c9550SJeff Roberson slab = (uma_slab_t)mem; 130639c9550SJeff Roberson } 131639c9550SJeff Roberson 132639c9550SJeff Roberson return (slab); 133639c9550SJeff Roberson } 134639c9550SJeff Roberson 135639c9550SJeff Roberson /* 136639c9550SJeff Roberson * Set up the slab's freei data such that uma_dbg_free can function. 137639c9550SJeff Roberson * 138639c9550SJeff Roberson */ 139639c9550SJeff Roberson 140639c9550SJeff Roberson void 141639c9550SJeff Roberson uma_dbg_alloc(uma_zone_t zone, uma_slab_t slab, void *item) 142639c9550SJeff Roberson { 143639c9550SJeff Roberson int freei; 144639c9550SJeff Roberson 145639c9550SJeff Roberson if (slab == NULL) { 146639c9550SJeff Roberson slab = uma_dbg_getslab(zone, item); 147639c9550SJeff Roberson if (slab == NULL) 148639c9550SJeff Roberson panic("uma: item %p did not belong to zone %s\n", 149639c9550SJeff Roberson item, zone->uz_name); 150639c9550SJeff Roberson } 151639c9550SJeff Roberson 152639c9550SJeff Roberson freei = ((unsigned long)item - (unsigned long)slab->us_data) 153639c9550SJeff Roberson / zone->uz_rsize; 154639c9550SJeff Roberson 155639c9550SJeff Roberson slab->us_freelist[freei] = 255; 156639c9550SJeff Roberson 157639c9550SJeff Roberson return; 158639c9550SJeff Roberson } 159639c9550SJeff Roberson 160639c9550SJeff Roberson /* 161639c9550SJeff Roberson * Verifies freed addresses. Checks for alignment, valid slab membership 162639c9550SJeff Roberson * and duplicate frees. 163639c9550SJeff Roberson * 164639c9550SJeff Roberson */ 165639c9550SJeff Roberson 166639c9550SJeff Roberson void 167639c9550SJeff Roberson uma_dbg_free(uma_zone_t zone, uma_slab_t slab, void *item) 168639c9550SJeff Roberson { 169639c9550SJeff Roberson int freei; 170639c9550SJeff Roberson 171639c9550SJeff Roberson return; 172639c9550SJeff Roberson 173639c9550SJeff Roberson if (slab == NULL) { 174639c9550SJeff Roberson slab = uma_dbg_getslab(zone, item); 175639c9550SJeff Roberson if (slab == NULL) 176639c9550SJeff Roberson panic("uma: Freed item %p did not belong to zone %s\n", 177639c9550SJeff Roberson item, zone->uz_name); 178639c9550SJeff Roberson } 179639c9550SJeff Roberson 180639c9550SJeff Roberson freei = ((unsigned long)item - (unsigned long)slab->us_data) 181639c9550SJeff Roberson / zone->uz_rsize; 182639c9550SJeff Roberson 183639c9550SJeff Roberson if (freei >= zone->uz_ipers) 184639c9550SJeff Roberson panic("zone: %s(%p) slab %p freelist %i out of range 0-%d\n", 185639c9550SJeff Roberson zone->uz_name, zone, slab, freei, zone->uz_ipers-1); 186639c9550SJeff Roberson 187639c9550SJeff Roberson if (((freei * zone->uz_rsize) + slab->us_data) != item) { 188639c9550SJeff Roberson printf("zone: %s(%p) slab %p freed address %p unaligned.\n", 189639c9550SJeff Roberson zone->uz_name, zone, slab, item); 190639c9550SJeff Roberson panic("should be %p\n", 191639c9550SJeff Roberson (freei * zone->uz_rsize) + slab->us_data); 192639c9550SJeff Roberson } 193639c9550SJeff Roberson 194639c9550SJeff Roberson if (slab->us_freelist[freei] != 255) { 195639c9550SJeff Roberson printf("Slab at %p, freei %d = %d.\n", 196639c9550SJeff Roberson slab, freei, slab->us_freelist[freei]); 197639c9550SJeff Roberson panic("Duplicate free of item %p from zone %p(%s)\n", 198639c9550SJeff Roberson item, zone, zone->uz_name); 199639c9550SJeff Roberson } 200639c9550SJeff Roberson 201639c9550SJeff Roberson /* 202639c9550SJeff Roberson * When this is actually linked into the slab this will change. 203639c9550SJeff Roberson * Until then the count of valid slabs will make sure we don't 204639c9550SJeff Roberson * accidentally follow this and assume it's a valid index. 205639c9550SJeff Roberson */ 206639c9550SJeff Roberson slab->us_freelist[freei] = 0; 207639c9550SJeff Roberson } 208