160727d8bSWarner Losh /*- 2*fe267a55SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*fe267a55SPedro F. Giffuni * 408ecce74SRobert Watson * Copyright (c) 2002, 2003, 2004, 2005 Jeffrey Roberson <jeff@FreeBSD.org> 508ecce74SRobert Watson * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org> 608ecce74SRobert Watson * All rights reserved. 78efc4effSJeff Roberson * 88efc4effSJeff Roberson * Redistribution and use in source and binary forms, with or without 98efc4effSJeff Roberson * modification, are permitted provided that the following conditions 108efc4effSJeff Roberson * are met: 118efc4effSJeff Roberson * 1. Redistributions of source code must retain the above copyright 128efc4effSJeff Roberson * notice unmodified, this list of conditions, and the following 138efc4effSJeff Roberson * disclaimer. 148efc4effSJeff Roberson * 2. Redistributions in binary form must reproduce the above copyright 158efc4effSJeff Roberson * notice, this list of conditions and the following disclaimer in the 168efc4effSJeff Roberson * documentation and/or other materials provided with the distribution. 178efc4effSJeff Roberson * 188efc4effSJeff Roberson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 198efc4effSJeff Roberson * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 208efc4effSJeff Roberson * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 218efc4effSJeff Roberson * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 228efc4effSJeff Roberson * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 238efc4effSJeff Roberson * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 248efc4effSJeff Roberson * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 258efc4effSJeff Roberson * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 268efc4effSJeff Roberson * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 278efc4effSJeff Roberson * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 288efc4effSJeff Roberson */ 298efc4effSJeff Roberson 308efc4effSJeff Roberson /* 318efc4effSJeff Roberson * uma_dbg.c Debugging features for UMA users 328efc4effSJeff Roberson * 338efc4effSJeff Roberson */ 348efc4effSJeff Roberson 35874651b1SDavid E. O'Brien #include <sys/cdefs.h> 36874651b1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 378efc4effSJeff Roberson 38bc9d08e1SMark Johnston #include "opt_vm.h" 39bc9d08e1SMark Johnston 408efc4effSJeff Roberson #include <sys/param.h> 418efc4effSJeff Roberson #include <sys/systm.h> 42ef72505eSJeff Roberson #include <sys/bitset.h> 438efc4effSJeff Roberson #include <sys/kernel.h> 448efc4effSJeff Roberson #include <sys/types.h> 458efc4effSJeff Roberson #include <sys/queue.h> 468efc4effSJeff Roberson #include <sys/lock.h> 478efc4effSJeff Roberson #include <sys/mutex.h> 488f70816cSJeff Roberson #include <sys/malloc.h> 498efc4effSJeff Roberson 5099571dc3SJeff Roberson #include <vm/vm.h> 5199571dc3SJeff Roberson #include <vm/vm_object.h> 5299571dc3SJeff Roberson #include <vm/vm_page.h> 538efc4effSJeff Roberson #include <vm/uma.h> 548efc4effSJeff Roberson #include <vm/uma_int.h> 558efc4effSJeff Roberson #include <vm/uma_dbg.h> 56bc9d08e1SMark Johnston #include <vm/memguard.h> 578efc4effSJeff Roberson 5885dcf349SGleb Smirnoff static const uint32_t uma_junk = 0xdeadc0de; 598efc4effSJeff Roberson 608efc4effSJeff Roberson /* 61b23f72e9SBrian Feldman * Checks an item to make sure it hasn't been overwritten since it was freed, 62b23f72e9SBrian Feldman * prior to subsequent reallocation. 638efc4effSJeff Roberson * 648efc4effSJeff Roberson * Complies with standard ctor arg/return 658efc4effSJeff Roberson */ 66b23f72e9SBrian Feldman int 67b23f72e9SBrian Feldman trash_ctor(void *mem, int size, void *arg, int flags) 688efc4effSJeff Roberson { 698efc4effSJeff Roberson int cnt; 7085dcf349SGleb Smirnoff uint32_t *p; 718efc4effSJeff Roberson 72bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 73bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 74bc9d08e1SMark Johnston return (0); 75bc9d08e1SMark Johnston #endif 76bc9d08e1SMark Johnston 778efc4effSJeff Roberson cnt = size / sizeof(uma_junk); 788efc4effSJeff Roberson 798efc4effSJeff Roberson for (p = mem; cnt > 0; cnt--, p++) 80cb6e5c1aSMike Silbersack if (*p != uma_junk) { 81afc6dc36SJohn-Mark Gurney #ifdef INVARIANTS 82afc6dc36SJohn-Mark Gurney panic("Memory modified after free %p(%d) val=%x @ %p\n", 83afc6dc36SJohn-Mark Gurney mem, size, *p, p); 84afc6dc36SJohn-Mark Gurney #else 85cb6e5c1aSMike Silbersack printf("Memory modified after free %p(%d) val=%x @ %p\n", 86e0f86251SPoul-Henning Kamp mem, size, *p, p); 87afc6dc36SJohn-Mark Gurney #endif 88b23f72e9SBrian Feldman return (0); 898efc4effSJeff Roberson } 90cb6e5c1aSMike Silbersack return (0); 91cb6e5c1aSMike Silbersack } 928efc4effSJeff Roberson 938efc4effSJeff Roberson /* 948efc4effSJeff Roberson * Fills an item with predictable garbage 958efc4effSJeff Roberson * 968efc4effSJeff Roberson * Complies with standard dtor arg/return 978efc4effSJeff Roberson * 988efc4effSJeff Roberson */ 998efc4effSJeff Roberson void 1008efc4effSJeff Roberson trash_dtor(void *mem, int size, void *arg) 1018efc4effSJeff Roberson { 1028efc4effSJeff Roberson int cnt; 10385dcf349SGleb Smirnoff uint32_t *p; 1048efc4effSJeff Roberson 105bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 106bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 107bc9d08e1SMark Johnston return; 108bc9d08e1SMark Johnston #endif 109bc9d08e1SMark Johnston 1108efc4effSJeff Roberson cnt = size / sizeof(uma_junk); 1118efc4effSJeff Roberson 1128efc4effSJeff Roberson for (p = mem; cnt > 0; cnt--, p++) 1138efc4effSJeff Roberson *p = uma_junk; 1148efc4effSJeff Roberson } 1158efc4effSJeff Roberson 1168efc4effSJeff Roberson /* 1178efc4effSJeff Roberson * Fills an item with predictable garbage 1188efc4effSJeff Roberson * 1198efc4effSJeff Roberson * Complies with standard init arg/return 1208efc4effSJeff Roberson * 1218efc4effSJeff Roberson */ 122b23f72e9SBrian Feldman int 123b23f72e9SBrian Feldman trash_init(void *mem, int size, int flags) 1248efc4effSJeff Roberson { 1258efc4effSJeff Roberson trash_dtor(mem, size, NULL); 126b23f72e9SBrian Feldman return (0); 1278efc4effSJeff Roberson } 1288efc4effSJeff Roberson 1298efc4effSJeff Roberson /* 1308efc4effSJeff Roberson * Checks an item to make sure it hasn't been overwritten since it was freed. 1318efc4effSJeff Roberson * 1328efc4effSJeff Roberson * Complies with standard fini arg/return 1338efc4effSJeff Roberson * 1348efc4effSJeff Roberson */ 1358efc4effSJeff Roberson void 1368efc4effSJeff Roberson trash_fini(void *mem, int size) 1378efc4effSJeff Roberson { 138b23f72e9SBrian Feldman (void)trash_ctor(mem, size, NULL, 0); 1398efc4effSJeff Roberson } 140639c9550SJeff Roberson 141b23f72e9SBrian Feldman int 142b23f72e9SBrian Feldman mtrash_ctor(void *mem, int size, void *arg, int flags) 1438f70816cSJeff Roberson { 1448f70816cSJeff Roberson struct malloc_type **ksp; 14585dcf349SGleb Smirnoff uint32_t *p = mem; 1468f70816cSJeff Roberson int cnt; 1478f70816cSJeff Roberson 148bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 149bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 150bc9d08e1SMark Johnston return (0); 151bc9d08e1SMark Johnston #endif 152bc9d08e1SMark Johnston 1538f70816cSJeff Roberson size -= sizeof(struct malloc_type *); 1548f70816cSJeff Roberson ksp = (struct malloc_type **)mem; 1558f70816cSJeff Roberson ksp += size / sizeof(struct malloc_type *); 1568f70816cSJeff Roberson cnt = size / sizeof(uma_junk); 1578f70816cSJeff Roberson 1588f70816cSJeff Roberson for (p = mem; cnt > 0; cnt--, p++) 1598f70816cSJeff Roberson if (*p != uma_junk) { 160e0f86251SPoul-Henning Kamp printf("Memory modified after free %p(%d) val=%x @ %p\n", 161e0f86251SPoul-Henning Kamp mem, size, *p, p); 1628f70816cSJeff Roberson panic("Most recently used by %s\n", (*ksp == NULL)? 1638f70816cSJeff Roberson "none" : (*ksp)->ks_shortdesc); 1648f70816cSJeff Roberson } 165b23f72e9SBrian Feldman return (0); 1668f70816cSJeff Roberson } 1678f70816cSJeff Roberson 1688f70816cSJeff Roberson /* 1698f70816cSJeff Roberson * Fills an item with predictable garbage 1708f70816cSJeff Roberson * 1718f70816cSJeff Roberson * Complies with standard dtor arg/return 1728f70816cSJeff Roberson * 1738f70816cSJeff Roberson */ 1748f70816cSJeff Roberson void 1758f70816cSJeff Roberson mtrash_dtor(void *mem, int size, void *arg) 1768f70816cSJeff Roberson { 1778f70816cSJeff Roberson int cnt; 17885dcf349SGleb Smirnoff uint32_t *p; 1798f70816cSJeff Roberson 180bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 181bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 182bc9d08e1SMark Johnston return; 183bc9d08e1SMark Johnston #endif 184bc9d08e1SMark Johnston 1858f70816cSJeff Roberson size -= sizeof(struct malloc_type *); 1868f70816cSJeff Roberson cnt = size / sizeof(uma_junk); 1878f70816cSJeff Roberson 1888f70816cSJeff Roberson for (p = mem; cnt > 0; cnt--, p++) 1898f70816cSJeff Roberson *p = uma_junk; 1908f70816cSJeff Roberson } 1918f70816cSJeff Roberson 1928f70816cSJeff Roberson /* 1938f70816cSJeff Roberson * Fills an item with predictable garbage 1948f70816cSJeff Roberson * 1958f70816cSJeff Roberson * Complies with standard init arg/return 1968f70816cSJeff Roberson * 1978f70816cSJeff Roberson */ 198b23f72e9SBrian Feldman int 199b23f72e9SBrian Feldman mtrash_init(void *mem, int size, int flags) 2008f70816cSJeff Roberson { 2018f70816cSJeff Roberson struct malloc_type **ksp; 2028f70816cSJeff Roberson 203bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 204bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 205bc9d08e1SMark Johnston return (0); 206bc9d08e1SMark Johnston #endif 207bc9d08e1SMark Johnston 2088f70816cSJeff Roberson mtrash_dtor(mem, size, NULL); 2098f70816cSJeff Roberson 2108f70816cSJeff Roberson ksp = (struct malloc_type **)mem; 2118f70816cSJeff Roberson ksp += (size / sizeof(struct malloc_type *)) - 1; 2128f70816cSJeff Roberson *ksp = NULL; 213b23f72e9SBrian Feldman return (0); 2148f70816cSJeff Roberson } 2158f70816cSJeff Roberson 2168f70816cSJeff Roberson /* 217b23f72e9SBrian Feldman * Checks an item to make sure it hasn't been overwritten since it was freed, 218b23f72e9SBrian Feldman * prior to freeing it back to available memory. 2198f70816cSJeff Roberson * 2208f70816cSJeff Roberson * Complies with standard fini arg/return 2218f70816cSJeff Roberson * 2228f70816cSJeff Roberson */ 2238f70816cSJeff Roberson void 2248f70816cSJeff Roberson mtrash_fini(void *mem, int size) 2258f70816cSJeff Roberson { 226b23f72e9SBrian Feldman (void)mtrash_ctor(mem, size, NULL, 0); 2278f70816cSJeff Roberson } 228