1139825Simp/*-
2148078Srwatson * Copyright (c) 2002, 2003, 2004, 2005 Jeffrey Roberson <jeff@FreeBSD.org>
3148078Srwatson * Copyright (c) 2004, 2005 Bosko Milekic <bmilekic@FreeBSD.org>
4148078Srwatson * All rights reserved.
595771Sjeff *
695771Sjeff * Redistribution and use in source and binary forms, with or without
795771Sjeff * modification, are permitted provided that the following conditions
895771Sjeff * are met:
995771Sjeff * 1. Redistributions of source code must retain the above copyright
1095771Sjeff *    notice unmodified, this list of conditions, and the following
1195771Sjeff *    disclaimer.
1295771Sjeff * 2. Redistributions in binary form must reproduce the above copyright
1395771Sjeff *    notice, this list of conditions and the following disclaimer in the
1495771Sjeff *    documentation and/or other materials provided with the distribution.
1595771Sjeff *
1695771Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1795771Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1895771Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1995771Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2095771Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2195771Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2295771Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2395771Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2495771Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2595771Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2695771Sjeff */
2795771Sjeff
2895771Sjeff/*
2995771Sjeff * uma_dbg.c	Debugging features for UMA users
3095771Sjeff *
3195771Sjeff */
3295771Sjeff
33116226Sobrien#include <sys/cdefs.h>
34116226Sobrien__FBSDID("$FreeBSD$");
3595771Sjeff
36301176Smarkj#include "opt_vm.h"
37301176Smarkj
3895771Sjeff#include <sys/param.h>
3995771Sjeff#include <sys/systm.h>
40251709Sjeff#include <sys/bitset.h>
4195771Sjeff#include <sys/kernel.h>
4295771Sjeff#include <sys/types.h>
4395771Sjeff#include <sys/queue.h>
4495771Sjeff#include <sys/lock.h>
4595771Sjeff#include <sys/mutex.h>
4695931Sjeff#include <sys/malloc.h>
4795771Sjeff
48103531Sjeff#include <vm/vm.h>
49103531Sjeff#include <vm/vm_object.h>
50103531Sjeff#include <vm/vm_page.h>
5195771Sjeff#include <vm/uma.h>
5295771Sjeff#include <vm/uma_int.h>
5395771Sjeff#include <vm/uma_dbg.h>
54301176Smarkj#include <vm/memguard.h>
5595771Sjeff
56249313Sglebiusstatic const uint32_t uma_junk = 0xdeadc0de;
5795771Sjeff
5895771Sjeff/*
59132987Sgreen * Checks an item to make sure it hasn't been overwritten since it was freed,
60132987Sgreen * prior to subsequent reallocation.
6195771Sjeff *
6295771Sjeff * Complies with standard ctor arg/return
6395771Sjeff */
64132987Sgreenint
65132987Sgreentrash_ctor(void *mem, int size, void *arg, int flags)
6695771Sjeff{
6795771Sjeff	int cnt;
68249313Sglebius	uint32_t *p;
6995771Sjeff
70301176Smarkj#ifdef DEBUG_MEMGUARD
71301176Smarkj	if (is_memguard_addr(mem))
72301176Smarkj		return (0);
73301176Smarkj#endif
74301176Smarkj
7595771Sjeff	cnt = size / sizeof(uma_junk);
7695771Sjeff
7795771Sjeff	for (p = mem; cnt > 0; cnt--, p++)
78147615Ssilby		if (*p != uma_junk) {
79284861Sjmg#ifdef INVARIANTS
80284861Sjmg			panic("Memory modified after free %p(%d) val=%x @ %p\n",
81284861Sjmg			    mem, size, *p, p);
82284861Sjmg#else
83147615Ssilby			printf("Memory modified after free %p(%d) val=%x @ %p\n",
84120526Sphk			    mem, size, *p, p);
85284861Sjmg#endif
86147615Ssilby			return (0);
87147615Ssilby		}
88132987Sgreen	return (0);
8995771Sjeff}
9095771Sjeff
9195771Sjeff/*
9295771Sjeff * Fills an item with predictable garbage
9395771Sjeff *
9495771Sjeff * Complies with standard dtor arg/return
9595771Sjeff *
9695771Sjeff */
9795771Sjeffvoid
9895771Sjefftrash_dtor(void *mem, int size, void *arg)
9995771Sjeff{
10095771Sjeff	int cnt;
101249313Sglebius	uint32_t *p;
10295771Sjeff
103301176Smarkj#ifdef DEBUG_MEMGUARD
104301176Smarkj	if (is_memguard_addr(mem))
105301176Smarkj		return;
106301176Smarkj#endif
107301176Smarkj
10895771Sjeff	cnt = size / sizeof(uma_junk);
10995771Sjeff
11095771Sjeff	for (p = mem; cnt > 0; cnt--, p++)
11195771Sjeff		*p = uma_junk;
11295771Sjeff}
11395771Sjeff
11495771Sjeff/*
11595771Sjeff * Fills an item with predictable garbage
11695771Sjeff *
11795771Sjeff * Complies with standard init arg/return
11895771Sjeff *
11995771Sjeff */
120132987Sgreenint
121132987Sgreentrash_init(void *mem, int size, int flags)
12295771Sjeff{
12395771Sjeff	trash_dtor(mem, size, NULL);
124132987Sgreen	return (0);
12595771Sjeff}
12695771Sjeff
12795771Sjeff/*
12895771Sjeff * Checks an item to make sure it hasn't been overwritten since it was freed.
12995771Sjeff *
13095771Sjeff * Complies with standard fini arg/return
13195771Sjeff *
13295771Sjeff */
13395771Sjeffvoid
13495771Sjefftrash_fini(void *mem, int size)
13595771Sjeff{
136132987Sgreen	(void)trash_ctor(mem, size, NULL, 0);
13795771Sjeff}
13895899Sjeff
139132987Sgreenint
140132987Sgreenmtrash_ctor(void *mem, int size, void *arg, int flags)
14195931Sjeff{
14295931Sjeff	struct malloc_type **ksp;
143249313Sglebius	uint32_t *p = mem;
14495931Sjeff	int cnt;
14595931Sjeff
146301176Smarkj#ifdef DEBUG_MEMGUARD
147301176Smarkj	if (is_memguard_addr(mem))
148301176Smarkj		return (0);
149301176Smarkj#endif
150301176Smarkj
15195931Sjeff	size -= sizeof(struct malloc_type *);
15295931Sjeff	ksp = (struct malloc_type **)mem;
15395931Sjeff	ksp += size / sizeof(struct malloc_type *);
15495931Sjeff	cnt = size / sizeof(uma_junk);
15595931Sjeff
15695931Sjeff	for (p = mem; cnt > 0; cnt--, p++)
15795931Sjeff		if (*p != uma_junk) {
158120526Sphk			printf("Memory modified after free %p(%d) val=%x @ %p\n",
159120526Sphk			    mem, size, *p, p);
16095931Sjeff			panic("Most recently used by %s\n", (*ksp == NULL)?
16195931Sjeff			    "none" : (*ksp)->ks_shortdesc);
16295931Sjeff		}
163132987Sgreen	return (0);
16495931Sjeff}
16595931Sjeff
16695931Sjeff/*
16795931Sjeff * Fills an item with predictable garbage
16895931Sjeff *
16995931Sjeff * Complies with standard dtor arg/return
17095931Sjeff *
17195931Sjeff */
17295931Sjeffvoid
17395931Sjeffmtrash_dtor(void *mem, int size, void *arg)
17495931Sjeff{
17595931Sjeff	int cnt;
176249313Sglebius	uint32_t *p;
17795931Sjeff
178301176Smarkj#ifdef DEBUG_MEMGUARD
179301176Smarkj	if (is_memguard_addr(mem))
180301176Smarkj		return;
181301176Smarkj#endif
182301176Smarkj
18395931Sjeff	size -= sizeof(struct malloc_type *);
18495931Sjeff	cnt = size / sizeof(uma_junk);
18595931Sjeff
18695931Sjeff	for (p = mem; cnt > 0; cnt--, p++)
18795931Sjeff		*p = uma_junk;
18895931Sjeff}
18995931Sjeff
19095931Sjeff/*
19195931Sjeff * Fills an item with predictable garbage
19295931Sjeff *
19395931Sjeff * Complies with standard init arg/return
19495931Sjeff *
19595931Sjeff */
196132987Sgreenint
197132987Sgreenmtrash_init(void *mem, int size, int flags)
19895931Sjeff{
19995931Sjeff	struct malloc_type **ksp;
20095931Sjeff
201301176Smarkj#ifdef DEBUG_MEMGUARD
202301176Smarkj	if (is_memguard_addr(mem))
203301176Smarkj		return (0);
204301176Smarkj#endif
205301176Smarkj
20695931Sjeff	mtrash_dtor(mem, size, NULL);
20795931Sjeff
20895931Sjeff	ksp = (struct malloc_type **)mem;
20995931Sjeff	ksp += (size / sizeof(struct malloc_type *)) - 1;
21095931Sjeff	*ksp = NULL;
211132987Sgreen	return (0);
21295931Sjeff}
21395931Sjeff
21495931Sjeff/*
215132987Sgreen * Checks an item to make sure it hasn't been overwritten since it was freed,
216132987Sgreen * prior to freeing it back to available memory.
21795931Sjeff *
21895931Sjeff * Complies with standard fini arg/return
21995931Sjeff *
22095931Sjeff */
22195931Sjeffvoid
22295931Sjeffmtrash_fini(void *mem, int size)
22395931Sjeff{
224132987Sgreen	(void)mtrash_ctor(mem, size, NULL, 0);
22595931Sjeff}
226