xref: /linux-6.15/lib/debugobjects.c (revision 3ac7fe5a)
1*3ac7fe5aSThomas Gleixner /*
2*3ac7fe5aSThomas Gleixner  * Generic infrastructure for lifetime debugging of objects.
3*3ac7fe5aSThomas Gleixner  *
4*3ac7fe5aSThomas Gleixner  * Started by Thomas Gleixner
5*3ac7fe5aSThomas Gleixner  *
6*3ac7fe5aSThomas Gleixner  * Copyright (C) 2008, Thomas Gleixner <[email protected]>
7*3ac7fe5aSThomas Gleixner  *
8*3ac7fe5aSThomas Gleixner  * For licencing details see kernel-base/COPYING
9*3ac7fe5aSThomas Gleixner  */
10*3ac7fe5aSThomas Gleixner #include <linux/debugobjects.h>
11*3ac7fe5aSThomas Gleixner #include <linux/interrupt.h>
12*3ac7fe5aSThomas Gleixner #include <linux/seq_file.h>
13*3ac7fe5aSThomas Gleixner #include <linux/debugfs.h>
14*3ac7fe5aSThomas Gleixner #include <linux/hash.h>
15*3ac7fe5aSThomas Gleixner 
16*3ac7fe5aSThomas Gleixner #define ODEBUG_HASH_BITS	14
17*3ac7fe5aSThomas Gleixner #define ODEBUG_HASH_SIZE	(1 << ODEBUG_HASH_BITS)
18*3ac7fe5aSThomas Gleixner 
19*3ac7fe5aSThomas Gleixner #define ODEBUG_POOL_SIZE	512
20*3ac7fe5aSThomas Gleixner #define ODEBUG_POOL_MIN_LEVEL	256
21*3ac7fe5aSThomas Gleixner 
22*3ac7fe5aSThomas Gleixner #define ODEBUG_CHUNK_SHIFT	PAGE_SHIFT
23*3ac7fe5aSThomas Gleixner #define ODEBUG_CHUNK_SIZE	(1 << ODEBUG_CHUNK_SHIFT)
24*3ac7fe5aSThomas Gleixner #define ODEBUG_CHUNK_MASK	(~(ODEBUG_CHUNK_SIZE - 1))
25*3ac7fe5aSThomas Gleixner 
26*3ac7fe5aSThomas Gleixner struct debug_bucket {
27*3ac7fe5aSThomas Gleixner 	struct hlist_head	list;
28*3ac7fe5aSThomas Gleixner 	spinlock_t		lock;
29*3ac7fe5aSThomas Gleixner };
30*3ac7fe5aSThomas Gleixner 
31*3ac7fe5aSThomas Gleixner static struct debug_bucket	obj_hash[ODEBUG_HASH_SIZE];
32*3ac7fe5aSThomas Gleixner 
33*3ac7fe5aSThomas Gleixner static struct debug_obj		obj_static_pool[ODEBUG_POOL_SIZE];
34*3ac7fe5aSThomas Gleixner 
35*3ac7fe5aSThomas Gleixner static DEFINE_SPINLOCK(pool_lock);
36*3ac7fe5aSThomas Gleixner 
37*3ac7fe5aSThomas Gleixner static HLIST_HEAD(obj_pool);
38*3ac7fe5aSThomas Gleixner 
39*3ac7fe5aSThomas Gleixner static int			obj_pool_min_free = ODEBUG_POOL_SIZE;
40*3ac7fe5aSThomas Gleixner static int			obj_pool_free = ODEBUG_POOL_SIZE;
41*3ac7fe5aSThomas Gleixner static int			obj_pool_used;
42*3ac7fe5aSThomas Gleixner static int			obj_pool_max_used;
43*3ac7fe5aSThomas Gleixner static struct kmem_cache	*obj_cache;
44*3ac7fe5aSThomas Gleixner 
45*3ac7fe5aSThomas Gleixner static int			debug_objects_maxchain __read_mostly;
46*3ac7fe5aSThomas Gleixner static int			debug_objects_fixups __read_mostly;
47*3ac7fe5aSThomas Gleixner static int			debug_objects_warnings __read_mostly;
48*3ac7fe5aSThomas Gleixner static int			debug_objects_enabled __read_mostly;
49*3ac7fe5aSThomas Gleixner static struct debug_obj_descr	*descr_test  __read_mostly;
50*3ac7fe5aSThomas Gleixner 
51*3ac7fe5aSThomas Gleixner static int __init enable_object_debug(char *str)
52*3ac7fe5aSThomas Gleixner {
53*3ac7fe5aSThomas Gleixner 	debug_objects_enabled = 1;
54*3ac7fe5aSThomas Gleixner 	return 0;
55*3ac7fe5aSThomas Gleixner }
56*3ac7fe5aSThomas Gleixner early_param("debug_objects", enable_object_debug);
57*3ac7fe5aSThomas Gleixner 
58*3ac7fe5aSThomas Gleixner static const char *obj_states[ODEBUG_STATE_MAX] = {
59*3ac7fe5aSThomas Gleixner 	[ODEBUG_STATE_NONE]		= "none",
60*3ac7fe5aSThomas Gleixner 	[ODEBUG_STATE_INIT]		= "initialized",
61*3ac7fe5aSThomas Gleixner 	[ODEBUG_STATE_INACTIVE]		= "inactive",
62*3ac7fe5aSThomas Gleixner 	[ODEBUG_STATE_ACTIVE]		= "active",
63*3ac7fe5aSThomas Gleixner 	[ODEBUG_STATE_DESTROYED]	= "destroyed",
64*3ac7fe5aSThomas Gleixner 	[ODEBUG_STATE_NOTAVAILABLE]	= "not available",
65*3ac7fe5aSThomas Gleixner };
66*3ac7fe5aSThomas Gleixner 
67*3ac7fe5aSThomas Gleixner static int fill_pool(void)
68*3ac7fe5aSThomas Gleixner {
69*3ac7fe5aSThomas Gleixner 	gfp_t gfp = GFP_ATOMIC | __GFP_NORETRY | __GFP_NOWARN;
70*3ac7fe5aSThomas Gleixner 	struct debug_obj *new;
71*3ac7fe5aSThomas Gleixner 
72*3ac7fe5aSThomas Gleixner 	if (likely(obj_pool_free >= ODEBUG_POOL_MIN_LEVEL))
73*3ac7fe5aSThomas Gleixner 		return obj_pool_free;
74*3ac7fe5aSThomas Gleixner 
75*3ac7fe5aSThomas Gleixner 	if (unlikely(!obj_cache))
76*3ac7fe5aSThomas Gleixner 		return obj_pool_free;
77*3ac7fe5aSThomas Gleixner 
78*3ac7fe5aSThomas Gleixner 	while (obj_pool_free < ODEBUG_POOL_MIN_LEVEL) {
79*3ac7fe5aSThomas Gleixner 
80*3ac7fe5aSThomas Gleixner 		new = kmem_cache_zalloc(obj_cache, gfp);
81*3ac7fe5aSThomas Gleixner 		if (!new)
82*3ac7fe5aSThomas Gleixner 			return obj_pool_free;
83*3ac7fe5aSThomas Gleixner 
84*3ac7fe5aSThomas Gleixner 		spin_lock(&pool_lock);
85*3ac7fe5aSThomas Gleixner 		hlist_add_head(&new->node, &obj_pool);
86*3ac7fe5aSThomas Gleixner 		obj_pool_free++;
87*3ac7fe5aSThomas Gleixner 		spin_unlock(&pool_lock);
88*3ac7fe5aSThomas Gleixner 	}
89*3ac7fe5aSThomas Gleixner 	return obj_pool_free;
90*3ac7fe5aSThomas Gleixner }
91*3ac7fe5aSThomas Gleixner 
92*3ac7fe5aSThomas Gleixner /*
93*3ac7fe5aSThomas Gleixner  * Lookup an object in the hash bucket.
94*3ac7fe5aSThomas Gleixner  */
95*3ac7fe5aSThomas Gleixner static struct debug_obj *lookup_object(void *addr, struct debug_bucket *b)
96*3ac7fe5aSThomas Gleixner {
97*3ac7fe5aSThomas Gleixner 	struct hlist_node *node;
98*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
99*3ac7fe5aSThomas Gleixner 	int cnt = 0;
100*3ac7fe5aSThomas Gleixner 
101*3ac7fe5aSThomas Gleixner 	hlist_for_each_entry(obj, node, &b->list, node) {
102*3ac7fe5aSThomas Gleixner 		cnt++;
103*3ac7fe5aSThomas Gleixner 		if (obj->object == addr)
104*3ac7fe5aSThomas Gleixner 			return obj;
105*3ac7fe5aSThomas Gleixner 	}
106*3ac7fe5aSThomas Gleixner 	if (cnt > debug_objects_maxchain)
107*3ac7fe5aSThomas Gleixner 		debug_objects_maxchain = cnt;
108*3ac7fe5aSThomas Gleixner 
109*3ac7fe5aSThomas Gleixner 	return NULL;
110*3ac7fe5aSThomas Gleixner }
111*3ac7fe5aSThomas Gleixner 
112*3ac7fe5aSThomas Gleixner /*
113*3ac7fe5aSThomas Gleixner  * Allocate a new object. If the pool is empty and no refill possible,
114*3ac7fe5aSThomas Gleixner  * switch off the debugger.
115*3ac7fe5aSThomas Gleixner  */
116*3ac7fe5aSThomas Gleixner static struct debug_obj *
117*3ac7fe5aSThomas Gleixner alloc_object(void *addr, struct debug_bucket *b, struct debug_obj_descr *descr)
118*3ac7fe5aSThomas Gleixner {
119*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj = NULL;
120*3ac7fe5aSThomas Gleixner 	int retry = 0;
121*3ac7fe5aSThomas Gleixner 
122*3ac7fe5aSThomas Gleixner repeat:
123*3ac7fe5aSThomas Gleixner 	spin_lock(&pool_lock);
124*3ac7fe5aSThomas Gleixner 	if (obj_pool.first) {
125*3ac7fe5aSThomas Gleixner 		obj	    = hlist_entry(obj_pool.first, typeof(*obj), node);
126*3ac7fe5aSThomas Gleixner 
127*3ac7fe5aSThomas Gleixner 		obj->object = addr;
128*3ac7fe5aSThomas Gleixner 		obj->descr  = descr;
129*3ac7fe5aSThomas Gleixner 		obj->state  = ODEBUG_STATE_NONE;
130*3ac7fe5aSThomas Gleixner 		hlist_del(&obj->node);
131*3ac7fe5aSThomas Gleixner 
132*3ac7fe5aSThomas Gleixner 		hlist_add_head(&obj->node, &b->list);
133*3ac7fe5aSThomas Gleixner 
134*3ac7fe5aSThomas Gleixner 		obj_pool_used++;
135*3ac7fe5aSThomas Gleixner 		if (obj_pool_used > obj_pool_max_used)
136*3ac7fe5aSThomas Gleixner 			obj_pool_max_used = obj_pool_used;
137*3ac7fe5aSThomas Gleixner 
138*3ac7fe5aSThomas Gleixner 		obj_pool_free--;
139*3ac7fe5aSThomas Gleixner 		if (obj_pool_free < obj_pool_min_free)
140*3ac7fe5aSThomas Gleixner 			obj_pool_min_free = obj_pool_free;
141*3ac7fe5aSThomas Gleixner 	}
142*3ac7fe5aSThomas Gleixner 	spin_unlock(&pool_lock);
143*3ac7fe5aSThomas Gleixner 
144*3ac7fe5aSThomas Gleixner 	if (fill_pool() && !obj && !retry++)
145*3ac7fe5aSThomas Gleixner 		goto repeat;
146*3ac7fe5aSThomas Gleixner 
147*3ac7fe5aSThomas Gleixner 	return obj;
148*3ac7fe5aSThomas Gleixner }
149*3ac7fe5aSThomas Gleixner 
150*3ac7fe5aSThomas Gleixner /*
151*3ac7fe5aSThomas Gleixner  * Put the object back into the pool or give it back to kmem_cache:
152*3ac7fe5aSThomas Gleixner  */
153*3ac7fe5aSThomas Gleixner static void free_object(struct debug_obj *obj)
154*3ac7fe5aSThomas Gleixner {
155*3ac7fe5aSThomas Gleixner 	unsigned long idx = (unsigned long)(obj - obj_static_pool);
156*3ac7fe5aSThomas Gleixner 
157*3ac7fe5aSThomas Gleixner 	if (obj_pool_free < ODEBUG_POOL_SIZE || idx < ODEBUG_POOL_SIZE) {
158*3ac7fe5aSThomas Gleixner 		spin_lock(&pool_lock);
159*3ac7fe5aSThomas Gleixner 		hlist_add_head(&obj->node, &obj_pool);
160*3ac7fe5aSThomas Gleixner 		obj_pool_free++;
161*3ac7fe5aSThomas Gleixner 		obj_pool_used--;
162*3ac7fe5aSThomas Gleixner 		spin_unlock(&pool_lock);
163*3ac7fe5aSThomas Gleixner 	} else {
164*3ac7fe5aSThomas Gleixner 		spin_lock(&pool_lock);
165*3ac7fe5aSThomas Gleixner 		obj_pool_used--;
166*3ac7fe5aSThomas Gleixner 		spin_unlock(&pool_lock);
167*3ac7fe5aSThomas Gleixner 		kmem_cache_free(obj_cache, obj);
168*3ac7fe5aSThomas Gleixner 	}
169*3ac7fe5aSThomas Gleixner }
170*3ac7fe5aSThomas Gleixner 
171*3ac7fe5aSThomas Gleixner /*
172*3ac7fe5aSThomas Gleixner  * We run out of memory. That means we probably have tons of objects
173*3ac7fe5aSThomas Gleixner  * allocated.
174*3ac7fe5aSThomas Gleixner  */
175*3ac7fe5aSThomas Gleixner static void debug_objects_oom(void)
176*3ac7fe5aSThomas Gleixner {
177*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db = obj_hash;
178*3ac7fe5aSThomas Gleixner 	struct hlist_node *node, *tmp;
179*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
180*3ac7fe5aSThomas Gleixner 	unsigned long flags;
181*3ac7fe5aSThomas Gleixner 	int i;
182*3ac7fe5aSThomas Gleixner 
183*3ac7fe5aSThomas Gleixner 	printk(KERN_WARNING "ODEBUG: Out of memory. ODEBUG disabled\n");
184*3ac7fe5aSThomas Gleixner 
185*3ac7fe5aSThomas Gleixner 	for (i = 0; i < ODEBUG_HASH_SIZE; i++, db++) {
186*3ac7fe5aSThomas Gleixner 		spin_lock_irqsave(&db->lock, flags);
187*3ac7fe5aSThomas Gleixner 		hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
188*3ac7fe5aSThomas Gleixner 			hlist_del(&obj->node);
189*3ac7fe5aSThomas Gleixner 			free_object(obj);
190*3ac7fe5aSThomas Gleixner 		}
191*3ac7fe5aSThomas Gleixner 		spin_unlock_irqrestore(&db->lock, flags);
192*3ac7fe5aSThomas Gleixner 	}
193*3ac7fe5aSThomas Gleixner }
194*3ac7fe5aSThomas Gleixner 
195*3ac7fe5aSThomas Gleixner /*
196*3ac7fe5aSThomas Gleixner  * We use the pfn of the address for the hash. That way we can check
197*3ac7fe5aSThomas Gleixner  * for freed objects simply by checking the affected bucket.
198*3ac7fe5aSThomas Gleixner  */
199*3ac7fe5aSThomas Gleixner static struct debug_bucket *get_bucket(unsigned long addr)
200*3ac7fe5aSThomas Gleixner {
201*3ac7fe5aSThomas Gleixner 	unsigned long hash;
202*3ac7fe5aSThomas Gleixner 
203*3ac7fe5aSThomas Gleixner 	hash = hash_long((addr >> ODEBUG_CHUNK_SHIFT), ODEBUG_HASH_BITS);
204*3ac7fe5aSThomas Gleixner 	return &obj_hash[hash];
205*3ac7fe5aSThomas Gleixner }
206*3ac7fe5aSThomas Gleixner 
207*3ac7fe5aSThomas Gleixner static void debug_print_object(struct debug_obj *obj, char *msg)
208*3ac7fe5aSThomas Gleixner {
209*3ac7fe5aSThomas Gleixner 	static int limit;
210*3ac7fe5aSThomas Gleixner 
211*3ac7fe5aSThomas Gleixner 	if (limit < 5 && obj->descr != descr_test) {
212*3ac7fe5aSThomas Gleixner 		limit++;
213*3ac7fe5aSThomas Gleixner 		printk(KERN_ERR "ODEBUG: %s %s object type: %s\n", msg,
214*3ac7fe5aSThomas Gleixner 		       obj_states[obj->state], obj->descr->name);
215*3ac7fe5aSThomas Gleixner 		WARN_ON(1);
216*3ac7fe5aSThomas Gleixner 	}
217*3ac7fe5aSThomas Gleixner 	debug_objects_warnings++;
218*3ac7fe5aSThomas Gleixner }
219*3ac7fe5aSThomas Gleixner 
220*3ac7fe5aSThomas Gleixner /*
221*3ac7fe5aSThomas Gleixner  * Try to repair the damage, so we have a better chance to get useful
222*3ac7fe5aSThomas Gleixner  * debug output.
223*3ac7fe5aSThomas Gleixner  */
224*3ac7fe5aSThomas Gleixner static void
225*3ac7fe5aSThomas Gleixner debug_object_fixup(int (*fixup)(void *addr, enum debug_obj_state state),
226*3ac7fe5aSThomas Gleixner 		   void * addr, enum debug_obj_state state)
227*3ac7fe5aSThomas Gleixner {
228*3ac7fe5aSThomas Gleixner 	if (fixup)
229*3ac7fe5aSThomas Gleixner 		debug_objects_fixups += fixup(addr, state);
230*3ac7fe5aSThomas Gleixner }
231*3ac7fe5aSThomas Gleixner 
232*3ac7fe5aSThomas Gleixner static void debug_object_is_on_stack(void *addr, int onstack)
233*3ac7fe5aSThomas Gleixner {
234*3ac7fe5aSThomas Gleixner 	void *stack = current->stack;
235*3ac7fe5aSThomas Gleixner 	int is_on_stack;
236*3ac7fe5aSThomas Gleixner 	static int limit;
237*3ac7fe5aSThomas Gleixner 
238*3ac7fe5aSThomas Gleixner 	if (limit > 4)
239*3ac7fe5aSThomas Gleixner 		return;
240*3ac7fe5aSThomas Gleixner 
241*3ac7fe5aSThomas Gleixner 	is_on_stack = (addr >= stack && addr < (stack + THREAD_SIZE));
242*3ac7fe5aSThomas Gleixner 
243*3ac7fe5aSThomas Gleixner 	if (is_on_stack == onstack)
244*3ac7fe5aSThomas Gleixner 		return;
245*3ac7fe5aSThomas Gleixner 
246*3ac7fe5aSThomas Gleixner 	limit++;
247*3ac7fe5aSThomas Gleixner 	if (is_on_stack)
248*3ac7fe5aSThomas Gleixner 		printk(KERN_WARNING
249*3ac7fe5aSThomas Gleixner 		       "ODEBUG: object is on stack, but not annotated\n");
250*3ac7fe5aSThomas Gleixner 	else
251*3ac7fe5aSThomas Gleixner 		printk(KERN_WARNING
252*3ac7fe5aSThomas Gleixner 		       "ODEBUG: object is not on stack, but annotated\n");
253*3ac7fe5aSThomas Gleixner 	WARN_ON(1);
254*3ac7fe5aSThomas Gleixner }
255*3ac7fe5aSThomas Gleixner 
256*3ac7fe5aSThomas Gleixner static void
257*3ac7fe5aSThomas Gleixner __debug_object_init(void *addr, struct debug_obj_descr *descr, int onstack)
258*3ac7fe5aSThomas Gleixner {
259*3ac7fe5aSThomas Gleixner 	enum debug_obj_state state;
260*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
261*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
262*3ac7fe5aSThomas Gleixner 	unsigned long flags;
263*3ac7fe5aSThomas Gleixner 
264*3ac7fe5aSThomas Gleixner 	db = get_bucket((unsigned long) addr);
265*3ac7fe5aSThomas Gleixner 
266*3ac7fe5aSThomas Gleixner 	spin_lock_irqsave(&db->lock, flags);
267*3ac7fe5aSThomas Gleixner 
268*3ac7fe5aSThomas Gleixner 	obj = lookup_object(addr, db);
269*3ac7fe5aSThomas Gleixner 	if (!obj) {
270*3ac7fe5aSThomas Gleixner 		obj = alloc_object(addr, db, descr);
271*3ac7fe5aSThomas Gleixner 		if (!obj) {
272*3ac7fe5aSThomas Gleixner 			debug_objects_enabled = 0;
273*3ac7fe5aSThomas Gleixner 			spin_unlock_irqrestore(&db->lock, flags);
274*3ac7fe5aSThomas Gleixner 			debug_objects_oom();
275*3ac7fe5aSThomas Gleixner 			return;
276*3ac7fe5aSThomas Gleixner 		}
277*3ac7fe5aSThomas Gleixner 		debug_object_is_on_stack(addr, onstack);
278*3ac7fe5aSThomas Gleixner 	}
279*3ac7fe5aSThomas Gleixner 
280*3ac7fe5aSThomas Gleixner 	switch (obj->state) {
281*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_NONE:
282*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_INIT:
283*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_INACTIVE:
284*3ac7fe5aSThomas Gleixner 		obj->state = ODEBUG_STATE_INIT;
285*3ac7fe5aSThomas Gleixner 		break;
286*3ac7fe5aSThomas Gleixner 
287*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
288*3ac7fe5aSThomas Gleixner 		debug_print_object(obj, "init");
289*3ac7fe5aSThomas Gleixner 		state = obj->state;
290*3ac7fe5aSThomas Gleixner 		spin_unlock_irqrestore(&db->lock, flags);
291*3ac7fe5aSThomas Gleixner 		debug_object_fixup(descr->fixup_init, addr, state);
292*3ac7fe5aSThomas Gleixner 		return;
293*3ac7fe5aSThomas Gleixner 
294*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_DESTROYED:
295*3ac7fe5aSThomas Gleixner 		debug_print_object(obj, "init");
296*3ac7fe5aSThomas Gleixner 		break;
297*3ac7fe5aSThomas Gleixner 	default:
298*3ac7fe5aSThomas Gleixner 		break;
299*3ac7fe5aSThomas Gleixner 	}
300*3ac7fe5aSThomas Gleixner 
301*3ac7fe5aSThomas Gleixner 	spin_unlock_irqrestore(&db->lock, flags);
302*3ac7fe5aSThomas Gleixner }
303*3ac7fe5aSThomas Gleixner 
304*3ac7fe5aSThomas Gleixner /**
305*3ac7fe5aSThomas Gleixner  * debug_object_init - debug checks when an object is initialized
306*3ac7fe5aSThomas Gleixner  * @addr:	address of the object
307*3ac7fe5aSThomas Gleixner  * @descr:	pointer to an object specific debug description structure
308*3ac7fe5aSThomas Gleixner  */
309*3ac7fe5aSThomas Gleixner void debug_object_init(void *addr, struct debug_obj_descr *descr)
310*3ac7fe5aSThomas Gleixner {
311*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
312*3ac7fe5aSThomas Gleixner 		return;
313*3ac7fe5aSThomas Gleixner 
314*3ac7fe5aSThomas Gleixner 	__debug_object_init(addr, descr, 0);
315*3ac7fe5aSThomas Gleixner }
316*3ac7fe5aSThomas Gleixner 
317*3ac7fe5aSThomas Gleixner /**
318*3ac7fe5aSThomas Gleixner  * debug_object_init_on_stack - debug checks when an object on stack is
319*3ac7fe5aSThomas Gleixner  *				initialized
320*3ac7fe5aSThomas Gleixner  * @addr:	address of the object
321*3ac7fe5aSThomas Gleixner  * @descr:	pointer to an object specific debug description structure
322*3ac7fe5aSThomas Gleixner  */
323*3ac7fe5aSThomas Gleixner void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
324*3ac7fe5aSThomas Gleixner {
325*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
326*3ac7fe5aSThomas Gleixner 		return;
327*3ac7fe5aSThomas Gleixner 
328*3ac7fe5aSThomas Gleixner 	__debug_object_init(addr, descr, 1);
329*3ac7fe5aSThomas Gleixner }
330*3ac7fe5aSThomas Gleixner 
331*3ac7fe5aSThomas Gleixner /**
332*3ac7fe5aSThomas Gleixner  * debug_object_activate - debug checks when an object is activated
333*3ac7fe5aSThomas Gleixner  * @addr:	address of the object
334*3ac7fe5aSThomas Gleixner  * @descr:	pointer to an object specific debug description structure
335*3ac7fe5aSThomas Gleixner  */
336*3ac7fe5aSThomas Gleixner void debug_object_activate(void *addr, struct debug_obj_descr *descr)
337*3ac7fe5aSThomas Gleixner {
338*3ac7fe5aSThomas Gleixner 	enum debug_obj_state state;
339*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
340*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
341*3ac7fe5aSThomas Gleixner 	unsigned long flags;
342*3ac7fe5aSThomas Gleixner 
343*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
344*3ac7fe5aSThomas Gleixner 		return;
345*3ac7fe5aSThomas Gleixner 
346*3ac7fe5aSThomas Gleixner 	db = get_bucket((unsigned long) addr);
347*3ac7fe5aSThomas Gleixner 
348*3ac7fe5aSThomas Gleixner 	spin_lock_irqsave(&db->lock, flags);
349*3ac7fe5aSThomas Gleixner 
350*3ac7fe5aSThomas Gleixner 	obj = lookup_object(addr, db);
351*3ac7fe5aSThomas Gleixner 	if (obj) {
352*3ac7fe5aSThomas Gleixner 		switch (obj->state) {
353*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_INIT:
354*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_INACTIVE:
355*3ac7fe5aSThomas Gleixner 			obj->state = ODEBUG_STATE_ACTIVE;
356*3ac7fe5aSThomas Gleixner 			break;
357*3ac7fe5aSThomas Gleixner 
358*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_ACTIVE:
359*3ac7fe5aSThomas Gleixner 			debug_print_object(obj, "activate");
360*3ac7fe5aSThomas Gleixner 			state = obj->state;
361*3ac7fe5aSThomas Gleixner 			spin_unlock_irqrestore(&db->lock, flags);
362*3ac7fe5aSThomas Gleixner 			debug_object_fixup(descr->fixup_activate, addr, state);
363*3ac7fe5aSThomas Gleixner 			return;
364*3ac7fe5aSThomas Gleixner 
365*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_DESTROYED:
366*3ac7fe5aSThomas Gleixner 			debug_print_object(obj, "activate");
367*3ac7fe5aSThomas Gleixner 			break;
368*3ac7fe5aSThomas Gleixner 		default:
369*3ac7fe5aSThomas Gleixner 			break;
370*3ac7fe5aSThomas Gleixner 		}
371*3ac7fe5aSThomas Gleixner 		spin_unlock_irqrestore(&db->lock, flags);
372*3ac7fe5aSThomas Gleixner 		return;
373*3ac7fe5aSThomas Gleixner 	}
374*3ac7fe5aSThomas Gleixner 
375*3ac7fe5aSThomas Gleixner 	spin_unlock_irqrestore(&db->lock, flags);
376*3ac7fe5aSThomas Gleixner 	/*
377*3ac7fe5aSThomas Gleixner 	 * This happens when a static object is activated. We
378*3ac7fe5aSThomas Gleixner 	 * let the type specific code decide whether this is
379*3ac7fe5aSThomas Gleixner 	 * true or not.
380*3ac7fe5aSThomas Gleixner 	 */
381*3ac7fe5aSThomas Gleixner 	debug_object_fixup(descr->fixup_activate, addr,
382*3ac7fe5aSThomas Gleixner 			   ODEBUG_STATE_NOTAVAILABLE);
383*3ac7fe5aSThomas Gleixner }
384*3ac7fe5aSThomas Gleixner 
385*3ac7fe5aSThomas Gleixner /**
386*3ac7fe5aSThomas Gleixner  * debug_object_deactivate - debug checks when an object is deactivated
387*3ac7fe5aSThomas Gleixner  * @addr:	address of the object
388*3ac7fe5aSThomas Gleixner  * @descr:	pointer to an object specific debug description structure
389*3ac7fe5aSThomas Gleixner  */
390*3ac7fe5aSThomas Gleixner void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
391*3ac7fe5aSThomas Gleixner {
392*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
393*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
394*3ac7fe5aSThomas Gleixner 	unsigned long flags;
395*3ac7fe5aSThomas Gleixner 
396*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
397*3ac7fe5aSThomas Gleixner 		return;
398*3ac7fe5aSThomas Gleixner 
399*3ac7fe5aSThomas Gleixner 	db = get_bucket((unsigned long) addr);
400*3ac7fe5aSThomas Gleixner 
401*3ac7fe5aSThomas Gleixner 	spin_lock_irqsave(&db->lock, flags);
402*3ac7fe5aSThomas Gleixner 
403*3ac7fe5aSThomas Gleixner 	obj = lookup_object(addr, db);
404*3ac7fe5aSThomas Gleixner 	if (obj) {
405*3ac7fe5aSThomas Gleixner 		switch (obj->state) {
406*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_INIT:
407*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_INACTIVE:
408*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_ACTIVE:
409*3ac7fe5aSThomas Gleixner 			obj->state = ODEBUG_STATE_INACTIVE;
410*3ac7fe5aSThomas Gleixner 			break;
411*3ac7fe5aSThomas Gleixner 
412*3ac7fe5aSThomas Gleixner 		case ODEBUG_STATE_DESTROYED:
413*3ac7fe5aSThomas Gleixner 			debug_print_object(obj, "deactivate");
414*3ac7fe5aSThomas Gleixner 			break;
415*3ac7fe5aSThomas Gleixner 		default:
416*3ac7fe5aSThomas Gleixner 			break;
417*3ac7fe5aSThomas Gleixner 		}
418*3ac7fe5aSThomas Gleixner 	} else {
419*3ac7fe5aSThomas Gleixner 		struct debug_obj o = { .object = addr,
420*3ac7fe5aSThomas Gleixner 				       .state = ODEBUG_STATE_NOTAVAILABLE,
421*3ac7fe5aSThomas Gleixner 				       .descr = descr };
422*3ac7fe5aSThomas Gleixner 
423*3ac7fe5aSThomas Gleixner 		debug_print_object(&o, "deactivate");
424*3ac7fe5aSThomas Gleixner 	}
425*3ac7fe5aSThomas Gleixner 
426*3ac7fe5aSThomas Gleixner 	spin_unlock_irqrestore(&db->lock, flags);
427*3ac7fe5aSThomas Gleixner }
428*3ac7fe5aSThomas Gleixner 
429*3ac7fe5aSThomas Gleixner /**
430*3ac7fe5aSThomas Gleixner  * debug_object_destroy - debug checks when an object is destroyed
431*3ac7fe5aSThomas Gleixner  * @addr:	address of the object
432*3ac7fe5aSThomas Gleixner  * @descr:	pointer to an object specific debug description structure
433*3ac7fe5aSThomas Gleixner  */
434*3ac7fe5aSThomas Gleixner void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
435*3ac7fe5aSThomas Gleixner {
436*3ac7fe5aSThomas Gleixner 	enum debug_obj_state state;
437*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
438*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
439*3ac7fe5aSThomas Gleixner 	unsigned long flags;
440*3ac7fe5aSThomas Gleixner 
441*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
442*3ac7fe5aSThomas Gleixner 		return;
443*3ac7fe5aSThomas Gleixner 
444*3ac7fe5aSThomas Gleixner 	db = get_bucket((unsigned long) addr);
445*3ac7fe5aSThomas Gleixner 
446*3ac7fe5aSThomas Gleixner 	spin_lock_irqsave(&db->lock, flags);
447*3ac7fe5aSThomas Gleixner 
448*3ac7fe5aSThomas Gleixner 	obj = lookup_object(addr, db);
449*3ac7fe5aSThomas Gleixner 	if (!obj)
450*3ac7fe5aSThomas Gleixner 		goto out_unlock;
451*3ac7fe5aSThomas Gleixner 
452*3ac7fe5aSThomas Gleixner 	switch (obj->state) {
453*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_NONE:
454*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_INIT:
455*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_INACTIVE:
456*3ac7fe5aSThomas Gleixner 		obj->state = ODEBUG_STATE_DESTROYED;
457*3ac7fe5aSThomas Gleixner 		break;
458*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
459*3ac7fe5aSThomas Gleixner 		debug_print_object(obj, "destroy");
460*3ac7fe5aSThomas Gleixner 		state = obj->state;
461*3ac7fe5aSThomas Gleixner 		spin_unlock_irqrestore(&db->lock, flags);
462*3ac7fe5aSThomas Gleixner 		debug_object_fixup(descr->fixup_destroy, addr, state);
463*3ac7fe5aSThomas Gleixner 		return;
464*3ac7fe5aSThomas Gleixner 
465*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_DESTROYED:
466*3ac7fe5aSThomas Gleixner 		debug_print_object(obj, "destroy");
467*3ac7fe5aSThomas Gleixner 		break;
468*3ac7fe5aSThomas Gleixner 	default:
469*3ac7fe5aSThomas Gleixner 		break;
470*3ac7fe5aSThomas Gleixner 	}
471*3ac7fe5aSThomas Gleixner out_unlock:
472*3ac7fe5aSThomas Gleixner 	spin_unlock_irqrestore(&db->lock, flags);
473*3ac7fe5aSThomas Gleixner }
474*3ac7fe5aSThomas Gleixner 
475*3ac7fe5aSThomas Gleixner /**
476*3ac7fe5aSThomas Gleixner  * debug_object_free - debug checks when an object is freed
477*3ac7fe5aSThomas Gleixner  * @addr:	address of the object
478*3ac7fe5aSThomas Gleixner  * @descr:	pointer to an object specific debug description structure
479*3ac7fe5aSThomas Gleixner  */
480*3ac7fe5aSThomas Gleixner void debug_object_free(void *addr, struct debug_obj_descr *descr)
481*3ac7fe5aSThomas Gleixner {
482*3ac7fe5aSThomas Gleixner 	enum debug_obj_state state;
483*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
484*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
485*3ac7fe5aSThomas Gleixner 	unsigned long flags;
486*3ac7fe5aSThomas Gleixner 
487*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
488*3ac7fe5aSThomas Gleixner 		return;
489*3ac7fe5aSThomas Gleixner 
490*3ac7fe5aSThomas Gleixner 	db = get_bucket((unsigned long) addr);
491*3ac7fe5aSThomas Gleixner 
492*3ac7fe5aSThomas Gleixner 	spin_lock_irqsave(&db->lock, flags);
493*3ac7fe5aSThomas Gleixner 
494*3ac7fe5aSThomas Gleixner 	obj = lookup_object(addr, db);
495*3ac7fe5aSThomas Gleixner 	if (!obj)
496*3ac7fe5aSThomas Gleixner 		goto out_unlock;
497*3ac7fe5aSThomas Gleixner 
498*3ac7fe5aSThomas Gleixner 	switch (obj->state) {
499*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
500*3ac7fe5aSThomas Gleixner 		debug_print_object(obj, "free");
501*3ac7fe5aSThomas Gleixner 		state = obj->state;
502*3ac7fe5aSThomas Gleixner 		spin_unlock_irqrestore(&db->lock, flags);
503*3ac7fe5aSThomas Gleixner 		debug_object_fixup(descr->fixup_free, addr, state);
504*3ac7fe5aSThomas Gleixner 		return;
505*3ac7fe5aSThomas Gleixner 	default:
506*3ac7fe5aSThomas Gleixner 		hlist_del(&obj->node);
507*3ac7fe5aSThomas Gleixner 		free_object(obj);
508*3ac7fe5aSThomas Gleixner 		break;
509*3ac7fe5aSThomas Gleixner 	}
510*3ac7fe5aSThomas Gleixner out_unlock:
511*3ac7fe5aSThomas Gleixner 	spin_unlock_irqrestore(&db->lock, flags);
512*3ac7fe5aSThomas Gleixner }
513*3ac7fe5aSThomas Gleixner 
514*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_FREE
515*3ac7fe5aSThomas Gleixner static void __debug_check_no_obj_freed(const void *address, unsigned long size)
516*3ac7fe5aSThomas Gleixner {
517*3ac7fe5aSThomas Gleixner 	unsigned long flags, oaddr, saddr, eaddr, paddr, chunks;
518*3ac7fe5aSThomas Gleixner 	struct hlist_node *node, *tmp;
519*3ac7fe5aSThomas Gleixner 	struct debug_obj_descr *descr;
520*3ac7fe5aSThomas Gleixner 	enum debug_obj_state state;
521*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
522*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
523*3ac7fe5aSThomas Gleixner 	int cnt;
524*3ac7fe5aSThomas Gleixner 
525*3ac7fe5aSThomas Gleixner 	saddr = (unsigned long) address;
526*3ac7fe5aSThomas Gleixner 	eaddr = saddr + size;
527*3ac7fe5aSThomas Gleixner 	paddr = saddr & ODEBUG_CHUNK_MASK;
528*3ac7fe5aSThomas Gleixner 	chunks = ((eaddr - paddr) + (ODEBUG_CHUNK_SIZE - 1));
529*3ac7fe5aSThomas Gleixner 	chunks >>= ODEBUG_CHUNK_SHIFT;
530*3ac7fe5aSThomas Gleixner 
531*3ac7fe5aSThomas Gleixner 	for (;chunks > 0; chunks--, paddr += ODEBUG_CHUNK_SIZE) {
532*3ac7fe5aSThomas Gleixner 		db = get_bucket(paddr);
533*3ac7fe5aSThomas Gleixner 
534*3ac7fe5aSThomas Gleixner repeat:
535*3ac7fe5aSThomas Gleixner 		cnt = 0;
536*3ac7fe5aSThomas Gleixner 		spin_lock_irqsave(&db->lock, flags);
537*3ac7fe5aSThomas Gleixner 		hlist_for_each_entry_safe(obj, node, tmp, &db->list, node) {
538*3ac7fe5aSThomas Gleixner 			cnt++;
539*3ac7fe5aSThomas Gleixner 			oaddr = (unsigned long) obj->object;
540*3ac7fe5aSThomas Gleixner 			if (oaddr < saddr || oaddr >= eaddr)
541*3ac7fe5aSThomas Gleixner 				continue;
542*3ac7fe5aSThomas Gleixner 
543*3ac7fe5aSThomas Gleixner 			switch (obj->state) {
544*3ac7fe5aSThomas Gleixner 			case ODEBUG_STATE_ACTIVE:
545*3ac7fe5aSThomas Gleixner 				debug_print_object(obj, "free");
546*3ac7fe5aSThomas Gleixner 				descr = obj->descr;
547*3ac7fe5aSThomas Gleixner 				state = obj->state;
548*3ac7fe5aSThomas Gleixner 				spin_unlock_irqrestore(&db->lock, flags);
549*3ac7fe5aSThomas Gleixner 				debug_object_fixup(descr->fixup_free,
550*3ac7fe5aSThomas Gleixner 						   (void *) oaddr, state);
551*3ac7fe5aSThomas Gleixner 				goto repeat;
552*3ac7fe5aSThomas Gleixner 			default:
553*3ac7fe5aSThomas Gleixner 				hlist_del(&obj->node);
554*3ac7fe5aSThomas Gleixner 				free_object(obj);
555*3ac7fe5aSThomas Gleixner 				break;
556*3ac7fe5aSThomas Gleixner 			}
557*3ac7fe5aSThomas Gleixner 		}
558*3ac7fe5aSThomas Gleixner 		spin_unlock_irqrestore(&db->lock, flags);
559*3ac7fe5aSThomas Gleixner 		if (cnt > debug_objects_maxchain)
560*3ac7fe5aSThomas Gleixner 			debug_objects_maxchain = cnt;
561*3ac7fe5aSThomas Gleixner 	}
562*3ac7fe5aSThomas Gleixner }
563*3ac7fe5aSThomas Gleixner 
564*3ac7fe5aSThomas Gleixner void debug_check_no_obj_freed(const void *address, unsigned long size)
565*3ac7fe5aSThomas Gleixner {
566*3ac7fe5aSThomas Gleixner 	if (debug_objects_enabled)
567*3ac7fe5aSThomas Gleixner 		__debug_check_no_obj_freed(address, size);
568*3ac7fe5aSThomas Gleixner }
569*3ac7fe5aSThomas Gleixner #endif
570*3ac7fe5aSThomas Gleixner 
571*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_FS
572*3ac7fe5aSThomas Gleixner 
573*3ac7fe5aSThomas Gleixner static int debug_stats_show(struct seq_file *m, void *v)
574*3ac7fe5aSThomas Gleixner {
575*3ac7fe5aSThomas Gleixner 	seq_printf(m, "max_chain     :%d\n", debug_objects_maxchain);
576*3ac7fe5aSThomas Gleixner 	seq_printf(m, "warnings      :%d\n", debug_objects_warnings);
577*3ac7fe5aSThomas Gleixner 	seq_printf(m, "fixups        :%d\n", debug_objects_fixups);
578*3ac7fe5aSThomas Gleixner 	seq_printf(m, "pool_free     :%d\n", obj_pool_free);
579*3ac7fe5aSThomas Gleixner 	seq_printf(m, "pool_min_free :%d\n", obj_pool_min_free);
580*3ac7fe5aSThomas Gleixner 	seq_printf(m, "pool_used     :%d\n", obj_pool_used);
581*3ac7fe5aSThomas Gleixner 	seq_printf(m, "pool_max_used :%d\n", obj_pool_max_used);
582*3ac7fe5aSThomas Gleixner 	return 0;
583*3ac7fe5aSThomas Gleixner }
584*3ac7fe5aSThomas Gleixner 
585*3ac7fe5aSThomas Gleixner static int debug_stats_open(struct inode *inode, struct file *filp)
586*3ac7fe5aSThomas Gleixner {
587*3ac7fe5aSThomas Gleixner 	return single_open(filp, debug_stats_show, NULL);
588*3ac7fe5aSThomas Gleixner }
589*3ac7fe5aSThomas Gleixner 
590*3ac7fe5aSThomas Gleixner static const struct file_operations debug_stats_fops = {
591*3ac7fe5aSThomas Gleixner 	.open		= debug_stats_open,
592*3ac7fe5aSThomas Gleixner 	.read		= seq_read,
593*3ac7fe5aSThomas Gleixner 	.llseek		= seq_lseek,
594*3ac7fe5aSThomas Gleixner 	.release	= single_release,
595*3ac7fe5aSThomas Gleixner };
596*3ac7fe5aSThomas Gleixner 
597*3ac7fe5aSThomas Gleixner static int __init debug_objects_init_debugfs(void)
598*3ac7fe5aSThomas Gleixner {
599*3ac7fe5aSThomas Gleixner 	struct dentry *dbgdir, *dbgstats;
600*3ac7fe5aSThomas Gleixner 
601*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
602*3ac7fe5aSThomas Gleixner 		return 0;
603*3ac7fe5aSThomas Gleixner 
604*3ac7fe5aSThomas Gleixner 	dbgdir = debugfs_create_dir("debug_objects", NULL);
605*3ac7fe5aSThomas Gleixner 	if (!dbgdir)
606*3ac7fe5aSThomas Gleixner 		return -ENOMEM;
607*3ac7fe5aSThomas Gleixner 
608*3ac7fe5aSThomas Gleixner 	dbgstats = debugfs_create_file("stats", 0444, dbgdir, NULL,
609*3ac7fe5aSThomas Gleixner 				       &debug_stats_fops);
610*3ac7fe5aSThomas Gleixner 	if (!dbgstats)
611*3ac7fe5aSThomas Gleixner 		goto err;
612*3ac7fe5aSThomas Gleixner 
613*3ac7fe5aSThomas Gleixner 	return 0;
614*3ac7fe5aSThomas Gleixner 
615*3ac7fe5aSThomas Gleixner err:
616*3ac7fe5aSThomas Gleixner 	debugfs_remove(dbgdir);
617*3ac7fe5aSThomas Gleixner 
618*3ac7fe5aSThomas Gleixner 	return -ENOMEM;
619*3ac7fe5aSThomas Gleixner }
620*3ac7fe5aSThomas Gleixner __initcall(debug_objects_init_debugfs);
621*3ac7fe5aSThomas Gleixner 
622*3ac7fe5aSThomas Gleixner #else
623*3ac7fe5aSThomas Gleixner static inline void debug_objects_init_debugfs(void) { }
624*3ac7fe5aSThomas Gleixner #endif
625*3ac7fe5aSThomas Gleixner 
626*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_SELFTEST
627*3ac7fe5aSThomas Gleixner 
628*3ac7fe5aSThomas Gleixner /* Random data structure for the self test */
629*3ac7fe5aSThomas Gleixner struct self_test {
630*3ac7fe5aSThomas Gleixner 	unsigned long	dummy1[6];
631*3ac7fe5aSThomas Gleixner 	int		static_init;
632*3ac7fe5aSThomas Gleixner 	unsigned long	dummy2[3];
633*3ac7fe5aSThomas Gleixner };
634*3ac7fe5aSThomas Gleixner 
635*3ac7fe5aSThomas Gleixner static __initdata struct debug_obj_descr descr_type_test;
636*3ac7fe5aSThomas Gleixner 
637*3ac7fe5aSThomas Gleixner /*
638*3ac7fe5aSThomas Gleixner  * fixup_init is called when:
639*3ac7fe5aSThomas Gleixner  * - an active object is initialized
640*3ac7fe5aSThomas Gleixner  */
641*3ac7fe5aSThomas Gleixner static int __init fixup_init(void *addr, enum debug_obj_state state)
642*3ac7fe5aSThomas Gleixner {
643*3ac7fe5aSThomas Gleixner 	struct self_test *obj = addr;
644*3ac7fe5aSThomas Gleixner 
645*3ac7fe5aSThomas Gleixner 	switch (state) {
646*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
647*3ac7fe5aSThomas Gleixner 		debug_object_deactivate(obj, &descr_type_test);
648*3ac7fe5aSThomas Gleixner 		debug_object_init(obj, &descr_type_test);
649*3ac7fe5aSThomas Gleixner 		return 1;
650*3ac7fe5aSThomas Gleixner 	default:
651*3ac7fe5aSThomas Gleixner 		return 0;
652*3ac7fe5aSThomas Gleixner 	}
653*3ac7fe5aSThomas Gleixner }
654*3ac7fe5aSThomas Gleixner 
655*3ac7fe5aSThomas Gleixner /*
656*3ac7fe5aSThomas Gleixner  * fixup_activate is called when:
657*3ac7fe5aSThomas Gleixner  * - an active object is activated
658*3ac7fe5aSThomas Gleixner  * - an unknown object is activated (might be a statically initialized object)
659*3ac7fe5aSThomas Gleixner  */
660*3ac7fe5aSThomas Gleixner static int __init fixup_activate(void *addr, enum debug_obj_state state)
661*3ac7fe5aSThomas Gleixner {
662*3ac7fe5aSThomas Gleixner 	struct self_test *obj = addr;
663*3ac7fe5aSThomas Gleixner 
664*3ac7fe5aSThomas Gleixner 	switch (state) {
665*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_NOTAVAILABLE:
666*3ac7fe5aSThomas Gleixner 		if (obj->static_init == 1) {
667*3ac7fe5aSThomas Gleixner 			debug_object_init(obj, &descr_type_test);
668*3ac7fe5aSThomas Gleixner 			debug_object_activate(obj, &descr_type_test);
669*3ac7fe5aSThomas Gleixner 			/*
670*3ac7fe5aSThomas Gleixner 			 * Real code should return 0 here ! This is
671*3ac7fe5aSThomas Gleixner 			 * not a fixup of some bad behaviour. We
672*3ac7fe5aSThomas Gleixner 			 * merily call the debug_init function to keep
673*3ac7fe5aSThomas Gleixner 			 * track of the object.
674*3ac7fe5aSThomas Gleixner 			 */
675*3ac7fe5aSThomas Gleixner 			return 1;
676*3ac7fe5aSThomas Gleixner 		} else {
677*3ac7fe5aSThomas Gleixner 			/* Real code needs to emit a warning here */
678*3ac7fe5aSThomas Gleixner 		}
679*3ac7fe5aSThomas Gleixner 		return 0;
680*3ac7fe5aSThomas Gleixner 
681*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
682*3ac7fe5aSThomas Gleixner 		debug_object_deactivate(obj, &descr_type_test);
683*3ac7fe5aSThomas Gleixner 		debug_object_activate(obj, &descr_type_test);
684*3ac7fe5aSThomas Gleixner 		return 1;
685*3ac7fe5aSThomas Gleixner 
686*3ac7fe5aSThomas Gleixner 	default:
687*3ac7fe5aSThomas Gleixner 		return 0;
688*3ac7fe5aSThomas Gleixner 	}
689*3ac7fe5aSThomas Gleixner }
690*3ac7fe5aSThomas Gleixner 
691*3ac7fe5aSThomas Gleixner /*
692*3ac7fe5aSThomas Gleixner  * fixup_destroy is called when:
693*3ac7fe5aSThomas Gleixner  * - an active object is destroyed
694*3ac7fe5aSThomas Gleixner  */
695*3ac7fe5aSThomas Gleixner static int __init fixup_destroy(void *addr, enum debug_obj_state state)
696*3ac7fe5aSThomas Gleixner {
697*3ac7fe5aSThomas Gleixner 	struct self_test *obj = addr;
698*3ac7fe5aSThomas Gleixner 
699*3ac7fe5aSThomas Gleixner 	switch (state) {
700*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
701*3ac7fe5aSThomas Gleixner 		debug_object_deactivate(obj, &descr_type_test);
702*3ac7fe5aSThomas Gleixner 		debug_object_destroy(obj, &descr_type_test);
703*3ac7fe5aSThomas Gleixner 		return 1;
704*3ac7fe5aSThomas Gleixner 	default:
705*3ac7fe5aSThomas Gleixner 		return 0;
706*3ac7fe5aSThomas Gleixner 	}
707*3ac7fe5aSThomas Gleixner }
708*3ac7fe5aSThomas Gleixner 
709*3ac7fe5aSThomas Gleixner /*
710*3ac7fe5aSThomas Gleixner  * fixup_free is called when:
711*3ac7fe5aSThomas Gleixner  * - an active object is freed
712*3ac7fe5aSThomas Gleixner  */
713*3ac7fe5aSThomas Gleixner static int __init fixup_free(void *addr, enum debug_obj_state state)
714*3ac7fe5aSThomas Gleixner {
715*3ac7fe5aSThomas Gleixner 	struct self_test *obj = addr;
716*3ac7fe5aSThomas Gleixner 
717*3ac7fe5aSThomas Gleixner 	switch (state) {
718*3ac7fe5aSThomas Gleixner 	case ODEBUG_STATE_ACTIVE:
719*3ac7fe5aSThomas Gleixner 		debug_object_deactivate(obj, &descr_type_test);
720*3ac7fe5aSThomas Gleixner 		debug_object_free(obj, &descr_type_test);
721*3ac7fe5aSThomas Gleixner 		return 1;
722*3ac7fe5aSThomas Gleixner 	default:
723*3ac7fe5aSThomas Gleixner 		return 0;
724*3ac7fe5aSThomas Gleixner 	}
725*3ac7fe5aSThomas Gleixner }
726*3ac7fe5aSThomas Gleixner 
727*3ac7fe5aSThomas Gleixner static int
728*3ac7fe5aSThomas Gleixner check_results(void *addr, enum debug_obj_state state, int fixups, int warnings)
729*3ac7fe5aSThomas Gleixner {
730*3ac7fe5aSThomas Gleixner 	struct debug_bucket *db;
731*3ac7fe5aSThomas Gleixner 	struct debug_obj *obj;
732*3ac7fe5aSThomas Gleixner 	unsigned long flags;
733*3ac7fe5aSThomas Gleixner 	int res = -EINVAL;
734*3ac7fe5aSThomas Gleixner 
735*3ac7fe5aSThomas Gleixner 	db = get_bucket((unsigned long) addr);
736*3ac7fe5aSThomas Gleixner 
737*3ac7fe5aSThomas Gleixner 	spin_lock_irqsave(&db->lock, flags);
738*3ac7fe5aSThomas Gleixner 
739*3ac7fe5aSThomas Gleixner 	obj = lookup_object(addr, db);
740*3ac7fe5aSThomas Gleixner 	if (!obj && state != ODEBUG_STATE_NONE) {
741*3ac7fe5aSThomas Gleixner 		printk(KERN_ERR "ODEBUG: selftest object not found\n");
742*3ac7fe5aSThomas Gleixner 		WARN_ON(1);
743*3ac7fe5aSThomas Gleixner 		goto out;
744*3ac7fe5aSThomas Gleixner 	}
745*3ac7fe5aSThomas Gleixner 	if (obj && obj->state != state) {
746*3ac7fe5aSThomas Gleixner 		printk(KERN_ERR "ODEBUG: selftest wrong state: %d != %d\n",
747*3ac7fe5aSThomas Gleixner 		       obj->state, state);
748*3ac7fe5aSThomas Gleixner 		WARN_ON(1);
749*3ac7fe5aSThomas Gleixner 		goto out;
750*3ac7fe5aSThomas Gleixner 	}
751*3ac7fe5aSThomas Gleixner 	if (fixups != debug_objects_fixups) {
752*3ac7fe5aSThomas Gleixner 		printk(KERN_ERR "ODEBUG: selftest fixups failed %d != %d\n",
753*3ac7fe5aSThomas Gleixner 		       fixups, debug_objects_fixups);
754*3ac7fe5aSThomas Gleixner 		WARN_ON(1);
755*3ac7fe5aSThomas Gleixner 		goto out;
756*3ac7fe5aSThomas Gleixner 	}
757*3ac7fe5aSThomas Gleixner 	if (warnings != debug_objects_warnings) {
758*3ac7fe5aSThomas Gleixner 		printk(KERN_ERR "ODEBUG: selftest warnings failed %d != %d\n",
759*3ac7fe5aSThomas Gleixner 		       warnings, debug_objects_warnings);
760*3ac7fe5aSThomas Gleixner 		WARN_ON(1);
761*3ac7fe5aSThomas Gleixner 		goto out;
762*3ac7fe5aSThomas Gleixner 	}
763*3ac7fe5aSThomas Gleixner 	res = 0;
764*3ac7fe5aSThomas Gleixner out:
765*3ac7fe5aSThomas Gleixner 	spin_unlock_irqrestore(&db->lock, flags);
766*3ac7fe5aSThomas Gleixner 	if (res)
767*3ac7fe5aSThomas Gleixner 		debug_objects_enabled = 0;
768*3ac7fe5aSThomas Gleixner 	return res;
769*3ac7fe5aSThomas Gleixner }
770*3ac7fe5aSThomas Gleixner 
771*3ac7fe5aSThomas Gleixner static __initdata struct debug_obj_descr descr_type_test = {
772*3ac7fe5aSThomas Gleixner 	.name			= "selftest",
773*3ac7fe5aSThomas Gleixner 	.fixup_init		= fixup_init,
774*3ac7fe5aSThomas Gleixner 	.fixup_activate		= fixup_activate,
775*3ac7fe5aSThomas Gleixner 	.fixup_destroy		= fixup_destroy,
776*3ac7fe5aSThomas Gleixner 	.fixup_free		= fixup_free,
777*3ac7fe5aSThomas Gleixner };
778*3ac7fe5aSThomas Gleixner 
779*3ac7fe5aSThomas Gleixner static __initdata struct self_test obj = { .static_init = 0 };
780*3ac7fe5aSThomas Gleixner 
781*3ac7fe5aSThomas Gleixner static void __init debug_objects_selftest(void)
782*3ac7fe5aSThomas Gleixner {
783*3ac7fe5aSThomas Gleixner 	int fixups, oldfixups, warnings, oldwarnings;
784*3ac7fe5aSThomas Gleixner 	unsigned long flags;
785*3ac7fe5aSThomas Gleixner 
786*3ac7fe5aSThomas Gleixner 	local_irq_save(flags);
787*3ac7fe5aSThomas Gleixner 
788*3ac7fe5aSThomas Gleixner 	fixups = oldfixups = debug_objects_fixups;
789*3ac7fe5aSThomas Gleixner 	warnings = oldwarnings = debug_objects_warnings;
790*3ac7fe5aSThomas Gleixner 	descr_test = &descr_type_test;
791*3ac7fe5aSThomas Gleixner 
792*3ac7fe5aSThomas Gleixner 	debug_object_init(&obj, &descr_type_test);
793*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings))
794*3ac7fe5aSThomas Gleixner 		goto out;
795*3ac7fe5aSThomas Gleixner 	debug_object_activate(&obj, &descr_type_test);
796*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
797*3ac7fe5aSThomas Gleixner 		goto out;
798*3ac7fe5aSThomas Gleixner 	debug_object_activate(&obj, &descr_type_test);
799*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, ++warnings))
800*3ac7fe5aSThomas Gleixner 		goto out;
801*3ac7fe5aSThomas Gleixner 	debug_object_deactivate(&obj, &descr_type_test);
802*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_INACTIVE, fixups, warnings))
803*3ac7fe5aSThomas Gleixner 		goto out;
804*3ac7fe5aSThomas Gleixner 	debug_object_destroy(&obj, &descr_type_test);
805*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, warnings))
806*3ac7fe5aSThomas Gleixner 		goto out;
807*3ac7fe5aSThomas Gleixner 	debug_object_init(&obj, &descr_type_test);
808*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
809*3ac7fe5aSThomas Gleixner 		goto out;
810*3ac7fe5aSThomas Gleixner 	debug_object_activate(&obj, &descr_type_test);
811*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
812*3ac7fe5aSThomas Gleixner 		goto out;
813*3ac7fe5aSThomas Gleixner 	debug_object_deactivate(&obj, &descr_type_test);
814*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_DESTROYED, fixups, ++warnings))
815*3ac7fe5aSThomas Gleixner 		goto out;
816*3ac7fe5aSThomas Gleixner 	debug_object_free(&obj, &descr_type_test);
817*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings))
818*3ac7fe5aSThomas Gleixner 		goto out;
819*3ac7fe5aSThomas Gleixner 
820*3ac7fe5aSThomas Gleixner 	obj.static_init = 1;
821*3ac7fe5aSThomas Gleixner 	debug_object_activate(&obj, &descr_type_test);
822*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_ACTIVE, ++fixups, warnings))
823*3ac7fe5aSThomas Gleixner 		goto out;
824*3ac7fe5aSThomas Gleixner 	debug_object_init(&obj, &descr_type_test);
825*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_INIT, ++fixups, ++warnings))
826*3ac7fe5aSThomas Gleixner 		goto out;
827*3ac7fe5aSThomas Gleixner 	debug_object_free(&obj, &descr_type_test);
828*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_NONE, fixups, warnings))
829*3ac7fe5aSThomas Gleixner 		goto out;
830*3ac7fe5aSThomas Gleixner 
831*3ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_FREE
832*3ac7fe5aSThomas Gleixner 	debug_object_init(&obj, &descr_type_test);
833*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_INIT, fixups, warnings))
834*3ac7fe5aSThomas Gleixner 		goto out;
835*3ac7fe5aSThomas Gleixner 	debug_object_activate(&obj, &descr_type_test);
836*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_ACTIVE, fixups, warnings))
837*3ac7fe5aSThomas Gleixner 		goto out;
838*3ac7fe5aSThomas Gleixner 	__debug_check_no_obj_freed(&obj, sizeof(obj));
839*3ac7fe5aSThomas Gleixner 	if (check_results(&obj, ODEBUG_STATE_NONE, ++fixups, ++warnings))
840*3ac7fe5aSThomas Gleixner 		goto out;
841*3ac7fe5aSThomas Gleixner #endif
842*3ac7fe5aSThomas Gleixner 	printk(KERN_INFO "ODEBUG: selftest passed\n");
843*3ac7fe5aSThomas Gleixner 
844*3ac7fe5aSThomas Gleixner out:
845*3ac7fe5aSThomas Gleixner 	debug_objects_fixups = oldfixups;
846*3ac7fe5aSThomas Gleixner 	debug_objects_warnings = oldwarnings;
847*3ac7fe5aSThomas Gleixner 	descr_test = NULL;
848*3ac7fe5aSThomas Gleixner 
849*3ac7fe5aSThomas Gleixner 	local_irq_restore(flags);
850*3ac7fe5aSThomas Gleixner }
851*3ac7fe5aSThomas Gleixner #else
852*3ac7fe5aSThomas Gleixner static inline void debug_objects_selftest(void) { }
853*3ac7fe5aSThomas Gleixner #endif
854*3ac7fe5aSThomas Gleixner 
855*3ac7fe5aSThomas Gleixner /*
856*3ac7fe5aSThomas Gleixner  * Called during early boot to initialize the hash buckets and link
857*3ac7fe5aSThomas Gleixner  * the static object pool objects into the poll list. After this call
858*3ac7fe5aSThomas Gleixner  * the object tracker is fully operational.
859*3ac7fe5aSThomas Gleixner  */
860*3ac7fe5aSThomas Gleixner void __init debug_objects_early_init(void)
861*3ac7fe5aSThomas Gleixner {
862*3ac7fe5aSThomas Gleixner 	int i;
863*3ac7fe5aSThomas Gleixner 
864*3ac7fe5aSThomas Gleixner 	for (i = 0; i < ODEBUG_HASH_SIZE; i++)
865*3ac7fe5aSThomas Gleixner 		spin_lock_init(&obj_hash[i].lock);
866*3ac7fe5aSThomas Gleixner 
867*3ac7fe5aSThomas Gleixner 	for (i = 0; i < ODEBUG_POOL_SIZE; i++)
868*3ac7fe5aSThomas Gleixner 		hlist_add_head(&obj_static_pool[i].node, &obj_pool);
869*3ac7fe5aSThomas Gleixner }
870*3ac7fe5aSThomas Gleixner 
871*3ac7fe5aSThomas Gleixner /*
872*3ac7fe5aSThomas Gleixner  * Called after the kmem_caches are functional to setup a dedicated
873*3ac7fe5aSThomas Gleixner  * cache pool, which has the SLAB_DEBUG_OBJECTS flag set. This flag
874*3ac7fe5aSThomas Gleixner  * prevents that the debug code is called on kmem_cache_free() for the
875*3ac7fe5aSThomas Gleixner  * debug tracker objects to avoid recursive calls.
876*3ac7fe5aSThomas Gleixner  */
877*3ac7fe5aSThomas Gleixner void __init debug_objects_mem_init(void)
878*3ac7fe5aSThomas Gleixner {
879*3ac7fe5aSThomas Gleixner 	if (!debug_objects_enabled)
880*3ac7fe5aSThomas Gleixner 		return;
881*3ac7fe5aSThomas Gleixner 
882*3ac7fe5aSThomas Gleixner 	obj_cache = kmem_cache_create("debug_objects_cache",
883*3ac7fe5aSThomas Gleixner 				      sizeof (struct debug_obj), 0,
884*3ac7fe5aSThomas Gleixner 				      SLAB_DEBUG_OBJECTS, NULL);
885*3ac7fe5aSThomas Gleixner 
886*3ac7fe5aSThomas Gleixner 	if (!obj_cache)
887*3ac7fe5aSThomas Gleixner 		debug_objects_enabled = 0;
888*3ac7fe5aSThomas Gleixner 	else
889*3ac7fe5aSThomas Gleixner 		debug_objects_selftest();
890*3ac7fe5aSThomas Gleixner }
891