ANDROID: add support for vendor hooks

Add support for vendor hooks. Adds include/trace/hooks
directory for trace definition headers where hooks
can be defined and vendor_hook.c for instantiating
and exporting them for vendor modules.

There are two variants of vendor hooks, both based
on tracepoints:

Normal: this uses the DECLARE_HOOK macro
to create a tracepoint function with the name trace_<name>
where <name> is the unique identifier for the trace.

Restricted: restricted hooks are needed for cases like
scheduler hooks where the attached function must be
called even if the cpu is offline or requires a
non-atomic context. Restricted vendor hooks cannot
be detached, so modules that attach to a restricted
hook can never unload. Also, only 1 attachment is
allowed (any other attempts to attach will fail with
-EBUSY).

For either case, modules attach to the hook by using
register_trace_<name>(func_ptr, NULL).

New hooks should be defined in headers in the
include/trace/hooks/ directory using the
DECLARE_HOOK() or DECLARE_RESTRICTED_HOOK()
macros.

New files added to include/trace/hooks should
be #include'd from drivers/android/vendor_hooks.c.
The EXPORT_TRACEPOINT_SYMBOL_GPL() should be
also added to drivers/android/vendor_hooks.c.

For example, if a new hook, 'android_vh_foo(int &ret)'
is added in do_exit() in exit.c, these changes are
needed:

1. create a new header file include/trace/hooks/foo.h
which contains:
	#include <trace/hooks/vendor_hooks.h>
	...
 	DECLARE_HOOK(android_vh_foo,
		     TP_PROTO(int *retp),
		     TP_ARGS(retp);

2. in exit.c, add
	#include <trace/hooks/foo.h>
	...
  	int ret = 0;
	...
  	android_vh_foo(&ret);
  	if (ret)
    		return ret;
	...

3. in drivers/android/vendor_hooks.c, add
	#include <trace/hooks/foo.h>
	...
	EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_foo);

The hook can then be attached by adding the registration code
to the module:

	#include <trace/hooks/sched.h>
	...
	static void my_foo(int *retp)
	{
		*retp = 0;
	}
	...
	rc = register_trace_android_vh_sched_exit(my_foo, NULL);

Bug: 156285741
Signed-off-by: Todd Kjos <tkjos@google.com>
Change-Id: I6a7d1c8919dae91c965e2a0450df50eac2d282db
This commit is contained in:
Todd Kjos
2020-04-24 10:12:38 -07:00
parent 626b817511
commit 7f62740112
6 changed files with 100 additions and 0 deletions

View File

@@ -398,6 +398,7 @@ CONFIG_GENERIC_PHY=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_VENDOR_HOOKS=y
CONFIG_LIBNVDIMM=y
# CONFIG_ND_BLK is not set
CONFIG_INTERCONNECT=y

View File

@@ -339,6 +339,7 @@ CONFIG_IIO_TRIGGER=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_ANDROID_BINDERFS=y
CONFIG_ANDROID_VENDOR_HOOKS=y
CONFIG_LIBNVDIMM=y
# CONFIG_ND_BLK is not set
CONFIG_INTERCONNECT=y

View File

@@ -54,6 +54,15 @@ config ANDROID_BINDER_IPC_SELFTEST
exhaustively with combinations of various buffer sizes and
alignments.
config ANDROID_VENDOR_HOOKS
bool "Android Vendor Hooks"
depends on TRACEPOINTS
---help---
Enable vendor hooks implemented as tracepoints
Allow vendor modules to attach to tracepoint "hooks" defined via
DECLARE_HOOK or DECLARE_RESTRICTED_HOOK.
endif # if ANDROID
endmenu

View File

@@ -4,3 +4,4 @@ ccflags-y += -I$(src) # needed for trace events
obj-$(CONFIG_ANDROID_BINDERFS) += binderfs.o
obj-$(CONFIG_ANDROID_BINDER_IPC) += binder.o binder_alloc.o
obj-$(CONFIG_ANDROID_BINDER_IPC_SELFTEST) += binder_alloc_selftest.o
obj-$(CONFIG_ANDROID_VENDOR_HOOKS) += vendor_hooks.o

View File

@@ -0,0 +1,16 @@
// SPDX-License-Identifier: GPL-2.0-only
/* vendor_hook.c
*
* Android Vendor Hook Support
*
* Copyright (C) 2020 Google, Inc.
*/
#define CREATE_TRACE_POINTS
#include <trace/hooks/vendor_hooks.h>
/*
* Export tracepoints that act as a bare tracehook (ie: have no trace event
* associated with them) to allow external modules to probe them.
*/

View File

@@ -0,0 +1,72 @@
/* SPDX-License-Identifier: GPL-2.0 */
#if !defined(_TRACE_VENDOR_HOOKS_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_VENDOR_HOOKS_H
#include <linux/tracepoint.h>
#define DECLARE_HOOK DECLARE_TRACE
#ifdef TRACE_HEADER_MULTI_READ
#undef DECLARE_RESTRICTED_HOOK
#define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \
DEFINE_TRACE(name)
/* prevent additional recursion */
#undef TRACE_HEADER_MULTI_READ
#else /* TRACE_HEADER_MULTI_READ */
#define DO_HOOK(tp, proto, args, cond) \
do { \
struct tracepoint_func *it_func_ptr; \
void *it_func; \
void *__data; \
\
if (!(cond)) \
return; \
\
it_func_ptr = (tp)->funcs; \
if (it_func_ptr) { \
it_func = (it_func_ptr)->func; \
__data = (it_func_ptr)->data; \
((void(*)(proto))(it_func))(args); \
WARN_ON(((++it_func_ptr)->func)); \
} \
} while (0)
#define __DECLARE_HOOK(name, proto, args, cond, data_proto, data_args) \
extern struct tracepoint __tracepoint_##name; \
static inline void trace_##name(proto) \
{ \
if (static_key_false(&__tracepoint_##name.key)) \
DO_HOOK(&__tracepoint_##name, \
TP_PROTO(data_proto), \
TP_ARGS(data_args), \
TP_CONDITION(cond)); \
} \
static inline bool \
trace_##name##_enabled(void) \
{ \
return static_key_false(&__tracepoint_##name.key); \
} \
static inline int \
register_trace_##name(void (*probe)(data_proto), void *data) \
{ \
/* only allow a single attachment */ \
if (trace_##name##_enabled()) \
return -EBUSY; \
return tracepoint_probe_register(&__tracepoint_##name, \
(void *)probe, data); \
} \
/* vendor hooks cannot be unregistered */ \
#define DECLARE_RESTRICTED_HOOK(name, proto, args, cond) \
__DECLARE_HOOK(name, PARAMS(proto), PARAMS(args), \
cond, \
PARAMS(void *__data, proto), \
PARAMS(__data, args))
#endif /* TRACE_HEADER_MULTI_READ */
#endif /* _TRACE_VENDOR_HOOKS_H */