1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
23ac7fe5aSThomas Gleixner #ifndef _LINUX_DEBUGOBJECTS_H
33ac7fe5aSThomas Gleixner #define _LINUX_DEBUGOBJECTS_H
43ac7fe5aSThomas Gleixner
53ac7fe5aSThomas Gleixner #include <linux/list.h>
63ac7fe5aSThomas Gleixner #include <linux/spinlock.h>
73ac7fe5aSThomas Gleixner
83ac7fe5aSThomas Gleixner enum debug_obj_state {
93ac7fe5aSThomas Gleixner ODEBUG_STATE_NONE,
103ac7fe5aSThomas Gleixner ODEBUG_STATE_INIT,
113ac7fe5aSThomas Gleixner ODEBUG_STATE_INACTIVE,
123ac7fe5aSThomas Gleixner ODEBUG_STATE_ACTIVE,
133ac7fe5aSThomas Gleixner ODEBUG_STATE_DESTROYED,
143ac7fe5aSThomas Gleixner ODEBUG_STATE_NOTAVAILABLE,
153ac7fe5aSThomas Gleixner ODEBUG_STATE_MAX,
163ac7fe5aSThomas Gleixner };
173ac7fe5aSThomas Gleixner
183ac7fe5aSThomas Gleixner struct debug_obj_descr;
193ac7fe5aSThomas Gleixner
203ac7fe5aSThomas Gleixner /**
21c23c8082SZhen Lei * struct debug_obj - representation of an tracked object
223ac7fe5aSThomas Gleixner * @node: hlist node to link the object into the tracker list
233ac7fe5aSThomas Gleixner * @state: tracked object state
24a5d8e467SMathieu Desnoyers * @astate: current active state
253ac7fe5aSThomas Gleixner * @object: pointer to the real object
26*74fe1ad4SThomas Gleixner * @batch_last: pointer to the last hlist node in a batch
273ac7fe5aSThomas Gleixner * @descr: pointer to an object type specific debug description structure
283ac7fe5aSThomas Gleixner */
293ac7fe5aSThomas Gleixner struct debug_obj {
303ac7fe5aSThomas Gleixner struct hlist_node node;
313ac7fe5aSThomas Gleixner enum debug_obj_state state;
32a5d8e467SMathieu Desnoyers unsigned int astate;
33*74fe1ad4SThomas Gleixner union {
343ac7fe5aSThomas Gleixner void *object;
35*74fe1ad4SThomas Gleixner struct hlist_node *batch_last;
36*74fe1ad4SThomas Gleixner };
37aedcade6SStephen Boyd const struct debug_obj_descr *descr;
383ac7fe5aSThomas Gleixner };
393ac7fe5aSThomas Gleixner
403ac7fe5aSThomas Gleixner /**
413ac7fe5aSThomas Gleixner * struct debug_obj_descr - object type specific debug description structure
4299777288SStanislaw Gruszka *
433ac7fe5aSThomas Gleixner * @name: name of the object typee
4499777288SStanislaw Gruszka * @debug_hint: function returning address, which have associated
4599777288SStanislaw Gruszka * kernel symbol, to allow identify the object
4617359a80SRandy Dunlap * @is_static_object: return true if the obj is static, otherwise return false
473ac7fe5aSThomas Gleixner * @fixup_init: fixup function, which is called when the init check
48b1e4d9d8SDu, Changbin * fails. All fixup functions must return true if fixup
49b1e4d9d8SDu, Changbin * was successful, otherwise return false
503ac7fe5aSThomas Gleixner * @fixup_activate: fixup function, which is called when the activate check
513ac7fe5aSThomas Gleixner * fails
523ac7fe5aSThomas Gleixner * @fixup_destroy: fixup function, which is called when the destroy check
533ac7fe5aSThomas Gleixner * fails
543ac7fe5aSThomas Gleixner * @fixup_free: fixup function, which is called when the free check
553ac7fe5aSThomas Gleixner * fails
56b84d435cSChristine Chan * @fixup_assert_init: fixup function, which is called when the assert_init
57b84d435cSChristine Chan * check fails
583ac7fe5aSThomas Gleixner */
593ac7fe5aSThomas Gleixner struct debug_obj_descr {
603ac7fe5aSThomas Gleixner const char *name;
6199777288SStanislaw Gruszka void *(*debug_hint)(void *addr);
62b9fdac7fSDu, Changbin bool (*is_static_object)(void *addr);
63b1e4d9d8SDu, Changbin bool (*fixup_init)(void *addr, enum debug_obj_state state);
64b1e4d9d8SDu, Changbin bool (*fixup_activate)(void *addr, enum debug_obj_state state);
65b1e4d9d8SDu, Changbin bool (*fixup_destroy)(void *addr, enum debug_obj_state state);
66b1e4d9d8SDu, Changbin bool (*fixup_free)(void *addr, enum debug_obj_state state);
67b1e4d9d8SDu, Changbin bool (*fixup_assert_init)(void *addr, enum debug_obj_state state);
683ac7fe5aSThomas Gleixner };
693ac7fe5aSThomas Gleixner
703ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS
71aedcade6SStephen Boyd extern void debug_object_init (void *addr, const struct debug_obj_descr *descr);
723ac7fe5aSThomas Gleixner extern void
73aedcade6SStephen Boyd debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr);
74aedcade6SStephen Boyd extern int debug_object_activate (void *addr, const struct debug_obj_descr *descr);
75aedcade6SStephen Boyd extern void debug_object_deactivate(void *addr, const struct debug_obj_descr *descr);
76aedcade6SStephen Boyd extern void debug_object_destroy (void *addr, const struct debug_obj_descr *descr);
77aedcade6SStephen Boyd extern void debug_object_free (void *addr, const struct debug_obj_descr *descr);
78aedcade6SStephen Boyd extern void debug_object_assert_init(void *addr, const struct debug_obj_descr *descr);
793ac7fe5aSThomas Gleixner
80a5d8e467SMathieu Desnoyers /*
81a5d8e467SMathieu Desnoyers * Active state:
82a5d8e467SMathieu Desnoyers * - Set at 0 upon initialization.
83a5d8e467SMathieu Desnoyers * - Must return to 0 before deactivation.
84a5d8e467SMathieu Desnoyers */
85a5d8e467SMathieu Desnoyers extern void
86aedcade6SStephen Boyd debug_object_active_state(void *addr, const struct debug_obj_descr *descr,
87a5d8e467SMathieu Desnoyers unsigned int expect, unsigned int next);
88a5d8e467SMathieu Desnoyers
893ac7fe5aSThomas Gleixner extern void debug_objects_early_init(void);
903ac7fe5aSThomas Gleixner extern void debug_objects_mem_init(void);
913ac7fe5aSThomas Gleixner #else
923ac7fe5aSThomas Gleixner static inline void
debug_object_init(void * addr,const struct debug_obj_descr * descr)93aedcade6SStephen Boyd debug_object_init (void *addr, const struct debug_obj_descr *descr) { }
943ac7fe5aSThomas Gleixner static inline void
debug_object_init_on_stack(void * addr,const struct debug_obj_descr * descr)95aedcade6SStephen Boyd debug_object_init_on_stack(void *addr, const struct debug_obj_descr *descr) { }
96b778ae25SPaul E. McKenney static inline int
debug_object_activate(void * addr,const struct debug_obj_descr * descr)97aedcade6SStephen Boyd debug_object_activate (void *addr, const struct debug_obj_descr *descr) { return 0; }
983ac7fe5aSThomas Gleixner static inline void
debug_object_deactivate(void * addr,const struct debug_obj_descr * descr)99aedcade6SStephen Boyd debug_object_deactivate(void *addr, const struct debug_obj_descr *descr) { }
1003ac7fe5aSThomas Gleixner static inline void
debug_object_destroy(void * addr,const struct debug_obj_descr * descr)101aedcade6SStephen Boyd debug_object_destroy (void *addr, const struct debug_obj_descr *descr) { }
1023ac7fe5aSThomas Gleixner static inline void
debug_object_free(void * addr,const struct debug_obj_descr * descr)103aedcade6SStephen Boyd debug_object_free (void *addr, const struct debug_obj_descr *descr) { }
104b84d435cSChristine Chan static inline void
debug_object_assert_init(void * addr,const struct debug_obj_descr * descr)105aedcade6SStephen Boyd debug_object_assert_init(void *addr, const struct debug_obj_descr *descr) { }
1063ac7fe5aSThomas Gleixner
debug_objects_early_init(void)1073ac7fe5aSThomas Gleixner static inline void debug_objects_early_init(void) { }
debug_objects_mem_init(void)1083ac7fe5aSThomas Gleixner static inline void debug_objects_mem_init(void) { }
1093ac7fe5aSThomas Gleixner #endif
1103ac7fe5aSThomas Gleixner
1113ac7fe5aSThomas Gleixner #ifdef CONFIG_DEBUG_OBJECTS_FREE
1123ac7fe5aSThomas Gleixner extern void debug_check_no_obj_freed(const void *address, unsigned long size);
1133ac7fe5aSThomas Gleixner #else
1143ac7fe5aSThomas Gleixner static inline void
debug_check_no_obj_freed(const void * address,unsigned long size)1153ac7fe5aSThomas Gleixner debug_check_no_obj_freed(const void *address, unsigned long size) { }
1163ac7fe5aSThomas Gleixner #endif
1173ac7fe5aSThomas Gleixner
1183ac7fe5aSThomas Gleixner #endif
119