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