160727d8bSWarner Losh /*- 24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 3fe267a55SPedro 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> 36bc9d08e1SMark Johnston #include "opt_vm.h" 37bc9d08e1SMark Johnston 388efc4effSJeff Roberson #include <sys/param.h> 398efc4effSJeff Roberson #include <sys/systm.h> 40ef72505eSJeff Roberson #include <sys/bitset.h> 418efc4effSJeff Roberson #include <sys/kernel.h> 428efc4effSJeff Roberson #include <sys/types.h> 438efc4effSJeff Roberson #include <sys/queue.h> 448efc4effSJeff Roberson #include <sys/lock.h> 458efc4effSJeff Roberson #include <sys/mutex.h> 468f70816cSJeff Roberson #include <sys/malloc.h> 478efc4effSJeff Roberson 4899571dc3SJeff Roberson #include <vm/vm.h> 4999571dc3SJeff Roberson #include <vm/vm_object.h> 5099571dc3SJeff Roberson #include <vm/vm_page.h> 518efc4effSJeff Roberson #include <vm/uma.h> 528efc4effSJeff Roberson #include <vm/uma_int.h> 538efc4effSJeff Roberson #include <vm/uma_dbg.h> 54bc9d08e1SMark Johnston #include <vm/memguard.h> 558efc4effSJeff Roberson 56*7c566d6cSAlexander Motin static const u_long uma_junk = (u_long)0xdeadc0dedeadc0de; 578efc4effSJeff Roberson 588efc4effSJeff Roberson /* 59b23f72e9SBrian Feldman * Checks an item to make sure it hasn't been overwritten since it was freed, 60b23f72e9SBrian Feldman * prior to subsequent reallocation. 618efc4effSJeff Roberson * 628efc4effSJeff Roberson * Complies with standard ctor arg/return 638efc4effSJeff Roberson */ 64b23f72e9SBrian Feldman int 65b23f72e9SBrian Feldman trash_ctor(void *mem, int size, void *arg, int flags) 668efc4effSJeff Roberson { 67*7c566d6cSAlexander Motin u_long *p = mem, *e; 688efc4effSJeff Roberson 69bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 70bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 71bc9d08e1SMark Johnston return (0); 72bc9d08e1SMark Johnston #endif 73bc9d08e1SMark Johnston 74*7c566d6cSAlexander Motin e = p + size / sizeof(*p); 75*7c566d6cSAlexander Motin for (; p < e; p++) { 76*7c566d6cSAlexander Motin if (__predict_true(*p == uma_junk)) 77*7c566d6cSAlexander Motin continue; 78*7c566d6cSAlexander Motin panic("Memory modified after free %p(%d) val=%lx @ %p\n", 79afc6dc36SJohn-Mark Gurney mem, size, *p, p); 808efc4effSJeff Roberson } 81cb6e5c1aSMike Silbersack return (0); 82cb6e5c1aSMike Silbersack } 838efc4effSJeff Roberson 848efc4effSJeff Roberson /* 858efc4effSJeff Roberson * Fills an item with predictable garbage 868efc4effSJeff Roberson * 878efc4effSJeff Roberson * Complies with standard dtor arg/return 888efc4effSJeff Roberson * 898efc4effSJeff Roberson */ 908efc4effSJeff Roberson void 918efc4effSJeff Roberson trash_dtor(void *mem, int size, void *arg) 928efc4effSJeff Roberson { 93*7c566d6cSAlexander Motin u_long *p = mem, *e; 948efc4effSJeff Roberson 95bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 96bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 97bc9d08e1SMark Johnston return; 98bc9d08e1SMark Johnston #endif 99bc9d08e1SMark Johnston 100*7c566d6cSAlexander Motin e = p + size / sizeof(*p); 101*7c566d6cSAlexander Motin for (; p < e; p++) 1028efc4effSJeff Roberson *p = uma_junk; 1038efc4effSJeff Roberson } 1048efc4effSJeff Roberson 1058efc4effSJeff Roberson /* 1068efc4effSJeff Roberson * Fills an item with predictable garbage 1078efc4effSJeff Roberson * 1088efc4effSJeff Roberson * Complies with standard init arg/return 1098efc4effSJeff Roberson * 1108efc4effSJeff Roberson */ 111b23f72e9SBrian Feldman int 112b23f72e9SBrian Feldman trash_init(void *mem, int size, int flags) 1138efc4effSJeff Roberson { 1148efc4effSJeff Roberson trash_dtor(mem, size, NULL); 115b23f72e9SBrian Feldman return (0); 1168efc4effSJeff Roberson } 1178efc4effSJeff Roberson 1188efc4effSJeff Roberson /* 1198efc4effSJeff Roberson * Checks an item to make sure it hasn't been overwritten since it was freed. 1208efc4effSJeff Roberson * 1218efc4effSJeff Roberson * Complies with standard fini arg/return 1228efc4effSJeff Roberson * 1238efc4effSJeff Roberson */ 1248efc4effSJeff Roberson void 1258efc4effSJeff Roberson trash_fini(void *mem, int size) 1268efc4effSJeff Roberson { 127b23f72e9SBrian Feldman (void)trash_ctor(mem, size, NULL, 0); 1288efc4effSJeff Roberson } 129639c9550SJeff Roberson 130b23f72e9SBrian Feldman int 131b23f72e9SBrian Feldman mtrash_ctor(void *mem, int size, void *arg, int flags) 1328f70816cSJeff Roberson { 1338f70816cSJeff Roberson struct malloc_type **ksp; 134*7c566d6cSAlexander Motin u_long *p = mem, *e; 1358f70816cSJeff Roberson 136bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 137bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 138bc9d08e1SMark Johnston return (0); 139bc9d08e1SMark Johnston #endif 140bc9d08e1SMark Johnston 1418f70816cSJeff Roberson size -= sizeof(struct malloc_type *); 1428f70816cSJeff Roberson ksp = (struct malloc_type **)mem; 1438f70816cSJeff Roberson ksp += size / sizeof(struct malloc_type *); 1448f70816cSJeff Roberson 145*7c566d6cSAlexander Motin e = p + size / sizeof(*p); 146*7c566d6cSAlexander Motin for (; p < e; p++) { 147*7c566d6cSAlexander Motin if (__predict_true(*p == uma_junk)) 148*7c566d6cSAlexander Motin continue; 149*7c566d6cSAlexander Motin printf("Memory modified after free %p(%d) val=%lx @ %p\n", 150e0f86251SPoul-Henning Kamp mem, size, *p, p); 1518f70816cSJeff Roberson panic("Most recently used by %s\n", (*ksp == NULL)? 1528f70816cSJeff Roberson "none" : (*ksp)->ks_shortdesc); 1538f70816cSJeff Roberson } 154b23f72e9SBrian Feldman return (0); 1558f70816cSJeff Roberson } 1568f70816cSJeff Roberson 1578f70816cSJeff Roberson /* 1588f70816cSJeff Roberson * Fills an item with predictable garbage 1598f70816cSJeff Roberson * 1608f70816cSJeff Roberson * Complies with standard dtor arg/return 1618f70816cSJeff Roberson * 1628f70816cSJeff Roberson */ 1638f70816cSJeff Roberson void 1648f70816cSJeff Roberson mtrash_dtor(void *mem, int size, void *arg) 1658f70816cSJeff Roberson { 166*7c566d6cSAlexander Motin u_long *p = mem, *e; 1678f70816cSJeff Roberson 168bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 169bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 170bc9d08e1SMark Johnston return; 171bc9d08e1SMark Johnston #endif 172bc9d08e1SMark Johnston 1738f70816cSJeff Roberson size -= sizeof(struct malloc_type *); 1748f70816cSJeff Roberson 175*7c566d6cSAlexander Motin e = p + size / sizeof(*p); 176*7c566d6cSAlexander Motin for (; p < e; p++) 1778f70816cSJeff Roberson *p = uma_junk; 1788f70816cSJeff Roberson } 1798f70816cSJeff Roberson 1808f70816cSJeff Roberson /* 1818f70816cSJeff Roberson * Fills an item with predictable garbage 1828f70816cSJeff Roberson * 1838f70816cSJeff Roberson * Complies with standard init arg/return 1848f70816cSJeff Roberson * 1858f70816cSJeff Roberson */ 186b23f72e9SBrian Feldman int 187b23f72e9SBrian Feldman mtrash_init(void *mem, int size, int flags) 1888f70816cSJeff Roberson { 1898f70816cSJeff Roberson struct malloc_type **ksp; 1908f70816cSJeff Roberson 191bc9d08e1SMark Johnston #ifdef DEBUG_MEMGUARD 192bc9d08e1SMark Johnston if (is_memguard_addr(mem)) 193bc9d08e1SMark Johnston return (0); 194bc9d08e1SMark Johnston #endif 195bc9d08e1SMark Johnston 1968f70816cSJeff Roberson mtrash_dtor(mem, size, NULL); 1978f70816cSJeff Roberson 1988f70816cSJeff Roberson ksp = (struct malloc_type **)mem; 1998f70816cSJeff Roberson ksp += (size / sizeof(struct malloc_type *)) - 1; 2008f70816cSJeff Roberson *ksp = NULL; 201b23f72e9SBrian Feldman return (0); 2028f70816cSJeff Roberson } 2038f70816cSJeff Roberson 2048f70816cSJeff Roberson /* 205b23f72e9SBrian Feldman * Checks an item to make sure it hasn't been overwritten since it was freed, 206b23f72e9SBrian Feldman * prior to freeing it back to available memory. 2078f70816cSJeff Roberson * 2088f70816cSJeff Roberson * Complies with standard fini arg/return 2098f70816cSJeff Roberson * 2108f70816cSJeff Roberson */ 2118f70816cSJeff Roberson void 2128f70816cSJeff Roberson mtrash_fini(void *mem, int size) 2138f70816cSJeff Roberson { 214b23f72e9SBrian Feldman (void)mtrash_ctor(mem, size, NULL, 0); 2158f70816cSJeff Roberson } 216