xref: /freebsd/sys/vm/uma_dbg.c (revision fe267a559009cbf34f9341666fe4d88a92c02d5e)
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