From 513252c043361454a0d8c6802898318d602260f0 Mon Sep 17 00:00:00 2001 From: zhujiaxin Date: Fri, 24 Feb 2023 10:34:45 +0800 Subject: [PATCH] hck Signed-off-by: zhujiaxin --- drivers/Kconfig | 2 + drivers/Makefile | 1 + drivers/hck/Kconfig | 21 +++++ drivers/hck/Makefile | 4 + drivers/hck/vendor_hooks.c | 13 +++ include/asm-generic/vmlinux.lds.h | 1 + include/linux/hck/lite_hck_sample.h | 36 ++++++++ include/linux/hck/lite_vendor_hooks.h | 126 ++++++++++++++++++++++++++ samples/Kconfig | 23 +++++ samples/Makefile | 1 + samples/hck/Makefile | 6 ++ samples/hck/call.c | 24 +++++ samples/hck/register.c | 60 ++++++++++++ samples/hck/register_one.c | 35 +++++++ 14 files changed, 353 insertions(+) create mode 100644 drivers/hck/Kconfig create mode 100644 drivers/hck/Makefile create mode 100644 drivers/hck/vendor_hooks.c create mode 100644 include/linux/hck/lite_hck_sample.h create mode 100644 include/linux/hck/lite_vendor_hooks.h create mode 100644 samples/hck/Makefile create mode 100644 samples/hck/call.c create mode 100644 samples/hck/register.c create mode 100644 samples/hck/register_one.c diff --git a/drivers/Kconfig b/drivers/Kconfig index 3584901f1252..abf8938eb35f 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -242,4 +242,6 @@ source "drivers/accesstokenid/Kconfig" source "drivers/hooks/Kconfig" +source "drivers/hck/Kconfig" + endmenu diff --git a/drivers/Makefile b/drivers/Makefile index f13d70df6557..d9e92b5e31e1 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -194,3 +194,4 @@ obj-$(CONFIG_COUNTER) += counter/ obj-$(CONFIG_MOST) += most/ obj-$(CONFIG_ACCESS_TOKENID) += accesstokenid/ obj-$(CONFIG_VENDOR_HOOKS) += hooks/ +obj-$(CONFIG_HCK_VENDOR_HOOKS) += hck/ diff --git a/drivers/hck/Kconfig b/drivers/hck/Kconfig new file mode 100644 index 000000000000..1028c52a3840 --- /dev/null +++ b/drivers/hck/Kconfig @@ -0,0 +1,21 @@ +# SPDX-License-Identifier: GPL-2.0-only +menu "Hck" + +config HCK + bool "Hck Drivers" + help + Enable support for various drivers needed on the OpenHarmony Common Kernel + +if HCK + +config HCK_VENDOR_HOOKS + bool "Hck Vendor Hooks" + help + Enable vendor hooks implemented as tracepoints + + Allow vendor modules to attach to tracepoint "hooks" defined via + DECLARE_HCK_HOOK DECLARE_HCK_RESTRICTED_HOOK + +endif # if HCK + +endmenu diff --git a/drivers/hck/Makefile b/drivers/hck/Makefile new file mode 100644 index 000000000000..93dc6acc727a --- /dev/null +++ b/drivers/hck/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0-only +ccflags-y += -I$(src) + +obj-$(CONFIG_HCK_VENDOR_HOOKS) += vendor_hooks.o \ No newline at end of file diff --git a/drivers/hck/vendor_hooks.c b/drivers/hck/vendor_hooks.c new file mode 100644 index 000000000000..28046b8d5a1f --- /dev/null +++ b/drivers/hck/vendor_hooks.c @@ -0,0 +1,13 @@ +//SPDX-License-Identifier: GPL-2.0-only +/*vendor_hooks.c + * + *OpenHarmony Common Kernel Vendor Hook Support + * + */ + +/* lite vendor hook */ +#define CREATE_LITE_VENDOR_HOOK +/* add your lite vendor hook header file here */ +#include + +#undef CREATE_LITE_VENDOR_HOOK \ No newline at end of file diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 24709c120d0b..6fabece27f7e 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -341,6 +341,7 @@ __end_once = .; \ STRUCT_ALIGN(); \ *(__tracepoints) \ + *(__vendor_hooks) \ /* implement dynamic printk debug */ \ . = ALIGN(8); \ __start___dyndbg = .; \ diff --git a/include/linux/hck/lite_hck_sample.h b/include/linux/hck/lite_hck_sample.h new file mode 100644 index 000000000000..f29dec41a626 --- /dev/null +++ b/include/linux/hck/lite_hck_sample.h @@ -0,0 +1,36 @@ +//SPDX-License-Identifier: GPL-2.0-only +/*lite_hck_sample.h + * + *OpenHarmony Common Kernel Vendor Hook Smaple + * + */ + +#ifndef LITE_HCK_SAMPLE_H +#define LITE_HCK_SAMPLE_H + +#include + + +struct sample_hck_data { + int stat; + char* name; +}; + +/* + * Follwing tracepoints are not exported in trace and provide a + * mechanism for vendor modules to hok and extend functionality + */ +#ifndef CONFIG_HCK + +#define CALL_HCK_LITE_HOOK(name, args...) +#define REGISTER_HCK_LITE_HOOK(name, probe) +#define REGISTER_HCK_LITE_DATA_HOOK(name, probe, data) + +#else + +DECLARE_HCK_LITE_HOOK(get_boot_config_lhck, TP_PROTO(int* s), TP_ARGS(s)); +DECLARE_HCK_LITE_HOOK(set_boot_stat_lhck, TP_PROTO(int m), TP_ARGS(m)); + +#endif + +#endif /* LITE_HCK_SAMPLE_H */ diff --git a/include/linux/hck/lite_vendor_hooks.h b/include/linux/hck/lite_vendor_hooks.h new file mode 100644 index 000000000000..4b0f30f6c493 --- /dev/null +++ b/include/linux/hck/lite_vendor_hooks.h @@ -0,0 +1,126 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2022-2022. All rights reserved. + * OpenHarmony Common Kernel Vendor Hook Support + * Based on include/trace/hooks/lite_vendor_hooks.h + * + */ + +#ifndef LITE_VENDOR_HOOK_H +#define LITE_VENDOR_HOOK_H + +#include +#include +#include +#include +#include +#include + +struct __lvh_func { + void *func; + void *data; + bool has_data; +}; + +struct lite_vendor_hook { + struct mutex mutex; + struct __lvh_func *funcs; +}; +#endif // LITE_VENDOR_HOOK_H + +#ifdef CREATE_LITE_VENDOR_HOOK + +#define DEFINE_HCK_LITE_HOOK(name, proto, args) \ + struct lite_vendor_hook __lvh_##name __used \ + __section("__vendor_hooks") = { \ + .mutex = __MUTEX_INITIALIZER(__lvh_##name.mutex), \ + .funcs = NULL }; \ + EXPORT_SYMBOL(__lvh_##name); \ + void lvh_probe_##name(proto) { return; } \ + void lvh_probe_data_##name(void *lvh_data, proto) { return; } + +#undef DECLARE_HCK_LITE_HOOK +#define DECLARE_HCK_LITE_HOOK(name, proto, args) \ + DEFINE_HCK_LITE_HOOK(name, PARAMS(proto), PARAMS(args)) + +#else // #ifndef CREATE_LITE_VENDOR_HOOK + +#define REGISTER_HCK_LITE_HOOK(name, probe) \ + extern typeof(lvh_probe_##name) (probe); \ + do { \ + if (register_lvh_##name(probe)) \ + WARN_ONCE(1, "LVH register failed!\n"); \ + } while (0) + +#define REGISTER_HCK_LITE_DATA_HOOK(name, probe, data) \ + extern typeof(lvh_probe_data_##name) (probe); \ + do { \ + if (register_lvh_data_##name(probe, data)) \ + WARN_ONCE(1, "LVH register failed!\n"); \ + } while (0) + +#define CALL_HCK_LITE_HOOK(name, args...) \ + call_lvh_##name(args) + +#define __DECLARE_HCK_LITE_HOOK(name, proto, args) \ + extern struct lite_vendor_hook __lvh_##name; \ + extern void lvh_probe_##name(proto); \ + extern void lvh_probe_data_##name(void *lvh_data, proto); \ + static inline void \ + call_lvh_##name(proto) \ + { \ + struct __lvh_func *funcs = (&__lvh_##name)->funcs; \ + if (funcs && funcs->func) { \ + if (funcs->has_data) \ + ((void(*)(void *, proto))funcs->func)(funcs->data, args); \ + else \ + ((void(*)(proto))funcs->func)(args); \ + } \ + } \ + static inline int \ + __register_lvh_##name(void *probe, void *data, bool has_data) \ + { \ + int err = 0; \ + struct __lvh_func *funcs; \ + struct module *mod; \ + mutex_lock(&__lvh_##name.mutex); \ + funcs = (&__lvh_##name)->funcs; \ + if (funcs) { \ + if (funcs->func != probe || funcs->data != data) \ + err = -EBUSY; \ + goto out; \ + } \ + \ + funcs = (struct __lvh_func*)kmalloc(sizeof(struct __lvh_func), GFP_KERNEL); \ + if (!funcs) { \ + err = -ENOMEM; \ + goto out; \ + } \ + \ + funcs->func = probe; \ + funcs->data = data; \ + funcs->has_data = has_data; \ + mod = __module_address((uintptr_t)probe); \ + if (mod) \ + (void)try_module_get(mod); \ + (&__lvh_##name)->funcs = funcs; \ + out: \ + mutex_unlock(&__lvh_##name.mutex); \ + return err; \ + } \ + static inline int \ + register_lvh_##name(void (*probe)(proto)) \ + { \ + return __register_lvh_##name((void *)probe, NULL, false); \ + } \ + static inline int \ + register_lvh_data_##name(void (*probe)(void *lvh_data, proto), void *data) \ + { \ + return __register_lvh_##name((void *)probe, data, true); \ + } + +#undef DECLARE_HCK_LITE_HOOK +#define DECLARE_HCK_LITE_HOOK(name, proto, args) \ + __DECLARE_HCK_LITE_HOOK(name, PARAMS(proto), PARAMS(args)) + +#endif // CREATE_LITE_VENDOR_HOOK diff --git a/samples/Kconfig b/samples/Kconfig index e76cdfc50e25..0dbd22e06d1d 100644 --- a/samples/Kconfig +++ b/samples/Kconfig @@ -216,4 +216,27 @@ config SAMPLE_WATCH_QUEUE Build example userspace program to use the new mount_notify(), sb_notify() syscalls and the KEYCTL_WATCH_KEY keyctl() function. +config SAMPLE_HCK + bool "HCK sample" + help + HCK sample + +config SAMPLE_HCK_CALL + bool "HCK call sample" + depends on SAMPLE_HCK + help + HCK call sample + +config SAMPLE_HCK_REGISTER + bool "HCK register sample" + depends on SAMPLE_HCK + help + HCK register sample + +config SAMPLE_HCK_REGISTER_ONE + bool "HCK register one interface sample" + depends on SAMPLE_HCK + help + HCK register sample + endif # SAMPLES diff --git a/samples/Makefile b/samples/Makefile index c3392a595e4b..e002c114a9f3 100644 --- a/samples/Makefile +++ b/samples/Makefile @@ -29,3 +29,4 @@ obj-$(CONFIG_SAMPLE_INTEL_MEI) += mei/ subdir-$(CONFIG_SAMPLE_WATCHDOG) += watchdog subdir-$(CONFIG_SAMPLE_WATCH_QUEUE) += watch_queue obj-$(CONFIG_DEBUG_KMEMLEAK_TEST) += kmemleak/ +obj-$(CONFIG_SAMPLE_HCK) += hck/ diff --git a/samples/hck/Makefile b/samples/hck/Makefile new file mode 100644 index 000000000000..1f24a99a46f4 --- /dev/null +++ b/samples/hck/Makefile @@ -0,0 +1,6 @@ +# SPDX-License-Identifier: GPL-2.0-only +ccflags-y += -I$(src) + +obj-$(CONFIG_SAMPLE_HCK_CALL) += call.o +obj-$(CONFIG_SAMPLE_HCK_REGISTER) += register.o +obj-$(CONFIG_SAMPLE_HCK_REGISTER_ONE) += register_one.o \ No newline at end of file diff --git a/samples/hck/call.c b/samples/hck/call.c new file mode 100644 index 000000000000..69d61e7f35f9 --- /dev/null +++ b/samples/hck/call.c @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sample Call HCK + * + */ +#include +#include +#include + +static int __init samplecallhck_init(void) +{ + int retval = 0; + + printk(KERN_INFO "hck sample: call\n"); + + CALL_HCK_LITE_HOOK(get_boot_config_lhck, &retval); + printk(KERN_INFO "hck sample retval changed: %d\n", retval); + + CALL_HCK_LITE_HOOK(set_boot_stat_lhck, retval); + printk(KERN_INFO "hck sample retval not changed: %d\n", retval); + + return retval; +} +late_initcall(samplecallhck_init); \ No newline at end of file diff --git a/samples/hck/register.c b/samples/hck/register.c new file mode 100644 index 000000000000..f3c44cda4ec5 --- /dev/null +++ b/samples/hck/register.c @@ -0,0 +1,60 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sample HCK + * + */ +#include +#include +#include +#include + +static struct sample_hck_data* data; + +void get_boot_config(int* info) +{ + printk(KERN_INFO "hck sample: %s\n", __func__); + *info = 1; + return; +} + +void set_boot_stat(void* data, int info) +{ + printk(KERN_INFO "hck sample: %s\n", __func__); + info = 2; + if (NULL != data) { + printk(KERN_INFO "hck data: stat = %d, name = %s\n", ((struct sample_hck_data*)data)->stat, ((struct sample_hck_data*)data)->name); + } + return; +} + +static int __init samplehck_init(void) +{ + int retval = 0; + data = (struct sample_hck_data*)kzalloc(sizeof(struct sample_hck_data), GFP_KERNEL); + if (NULL == data) { + return retval; + } + data->stat = 999; + data->name = "sample test"; + + printk(KERN_INFO "hck sample register\n"); + + REGISTER_HCK_LITE_HOOK(get_boot_config_lhck, get_boot_config); + REGISTER_HCK_LITE_DATA_HOOK(set_boot_stat_lhck, set_boot_stat, data); + + return retval; +} + +static void __exit samplehck_exit(void) +{ + if (NULL != data) { + kfree(data); + data = NULL; + } + return; +} + +module_init(samplehck_init); +module_exit(samplehck_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("zhujiaxin "); diff --git a/samples/hck/register_one.c b/samples/hck/register_one.c new file mode 100644 index 000000000000..7edc8f7bf5c3 --- /dev/null +++ b/samples/hck/register_one.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Sample HCK + * + */ +#include +#include +#include + +void get_boot_power_config(int* info) +{ + printk(KERN_INFO "hck sample: intf-2 run\n"); + *info = 2; + return; +} + +static int __init samplehckone_init(void) +{ + int retval = 0; + + printk(KERN_INFO "hck sample register_one\n"); + REGISTER_HCK_LITE_HOOK(get_boot_config_lhck, get_boot_power_config); + + return retval; +} + +static void __exit samplehckone_exit(void) +{ + return; +} + +module_init(samplehckone_init); +module_exit(samplehckone_exit); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("zhujiaxin "); -- Gitee