From 1f2335ec9fb4e981d5a99f37f3609facfbf60c69 Mon Sep 17 00:00:00 2001 From: zy Date: Tue, 19 Dec 2023 22:29:11 -0500 Subject: [PATCH] reformat and rename --- source/module/monitor_kernel.c | 17 -- source/module/monitor_kernel.h | 4 + source/module/monitor_kernel_lib.c | 387 ++++++++++++++++------------- 3 files changed, 222 insertions(+), 186 deletions(-) diff --git a/source/module/monitor_kernel.c b/source/module/monitor_kernel.c index 22437aa..e7dc211 100644 --- a/source/module/monitor_kernel.c +++ b/source/module/monitor_kernel.c @@ -48,23 +48,6 @@ typedef struct { int id; } ioctl_id; -// dump log from buffer -static int dump_log(ioctl_dump_param *dump_param, unsigned long ioctl_param, - struct diag_variant_buffer *buffer) { - int ret = 0; - ret = copy_from_user(dump_param, (ioctl_dump_param *)ioctl_param, - sizeof(ioctl_dump_param)); - printk(KERN_INFO "dump_param: %p %lx %p\n", dump_param->user_ptr_len, - dump_param->user_buf_len, dump_param->user_buf); - if (!ret) { - ret = copy_to_user_variant_buffer(buffer, dump_param->user_ptr_len, - dump_param->user_buf, - dump_param->user_buf_len); - printk(KERN_INFO "ret %d, %lx\n", ret, dump_param->user_buf_len); - } - return ret; -} - static long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { int ret = 0; diff --git a/source/module/monitor_kernel.h b/source/module/monitor_kernel.h index fff5547..9b484f5 100644 --- a/source/module/monitor_kernel.h +++ b/source/module/monitor_kernel.h @@ -25,6 +25,10 @@ extern struct diag_variant_buffer load_monitor_variant_buffer; // global buffer extern struct diag_variant_buffer stand_alone_buffer; // buffer for single work #define STAND_ALONE_BUFFER_SIZE 50 * 1024 * 1024 // 50 MB +// for buffer +int dump_log(ioctl_dump_param *dump_param, unsigned long ioctl_param, + struct diag_variant_buffer *buffer); + int monitor_init(void); // monitor init void monitor_exit(void); // monitor exit diff --git a/source/module/monitor_kernel_lib.c b/source/module/monitor_kernel_lib.c index 5a5bdc3..a2df23a 100644 --- a/source/module/monitor_kernel_lib.c +++ b/source/module/monitor_kernel_lib.c @@ -1,7 +1,9 @@ #include "monitor_kernel.h" #include +#include #include +#include #include // #include // #include @@ -11,30 +13,6 @@ (task->flags & PF_FROZEN) == 0 && \ (READ_ONCE(task->__state) & TASK_NOLOAD) == 0) -/** - * @brief watch_arg to kernel_watch_arg - * - * @param ptr: kernel space address - * @param warg: watch_arg - * @param k_watch_arg: kernel_watch_arg - * @return unsigned char - */ -static unsigned char w_arg2k_w_arg(void *kptr, watch_arg warg, - kernel_watch_arg *k_watch_arg) { - // k_watch_arg init - k_watch_arg->task_id = warg.task_id; - strncpy(k_watch_arg->name, warg.name, MAX_NAME_LEN + 1); // name - k_watch_arg->name[MAX_NAME_LEN + 1] = '\0'; // just in case - k_watch_arg->ptr = warg.ptr; - k_watch_arg->kptr = kptr; - k_watch_arg->length_byte = warg.length_byte; - k_watch_arg->threshold = warg.threshold; - k_watch_arg->is_unsigned = warg.is_unsigned; - k_watch_arg->above_threshold = warg.above_threshold; - k_watch_arg->true_value = 0; - return 0; -} - static long long convert_to_longlong(void *ptr, int size, char isUnsigned) { long long ret = 0; // ptr is null @@ -61,6 +39,30 @@ static long long convert_to_longlong(void *ptr, int size, char isUnsigned) { return ret; } +/** + * @brief watch_arg to kernel_watch_arg + * + * @param ptr: kernel space address + * @param warg: watch_arg + * @param k_watch_arg: kernel_watch_arg + * @return unsigned char + */ +static unsigned char w_arg2k_w_arg(void *kptr, watch_arg warg, + kernel_watch_arg *k_watch_arg) { + // k_watch_arg init + k_watch_arg->task_id = warg.task_id; + strncpy(k_watch_arg->name, warg.name, MAX_NAME_LEN + 1); // name + k_watch_arg->name[MAX_NAME_LEN + 1] = '\0'; // just in case + k_watch_arg->ptr = warg.ptr; + k_watch_arg->kptr = kptr; + k_watch_arg->length_byte = warg.length_byte; + k_watch_arg->threshold = warg.threshold; + k_watch_arg->is_unsigned = warg.is_unsigned; + k_watch_arg->above_threshold = warg.above_threshold; + k_watch_arg->true_value = 0; + return 0; +} + /** * @brief kernel_watch_arg to threshold * @@ -85,10 +87,6 @@ static void init_mm_tree(mm_tree *mm_tree) { /** * @brief init buffer - * - * @param buf_size - * @param buffer - * @return int */ static int init_buffer(unsigned int buf_size, struct diag_variant_buffer *buffer) { @@ -109,29 +107,6 @@ static int init_sa_buffer(void) { return init_buffer(STAND_ALONE_BUFFER_SIZE, &stand_alone_buffer); } -/** - * @brief diag task info | brief | kernel stack | proc chains | raw - * stack - * - * @param p - * @param tsk_info - */ -static void diag_tsk(struct task_struct *p, variable_monitor_task *tsk_info) { - unsigned int nr_bt; - // printk(KERN_INFO "diag_tsk\n"); - diag_task_brief(p, &tsk_info->task); // task brief - if (tsk_info->task.sys_task == 1) { // system task - nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack - dump_proc_chains_argv(1, p, &mm_tree_struct, - &tsk_info->proc_chains); // proc chains - } else { // other task - nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack - dump_proc_chains_argv(1, p, &mm_tree_struct, - &tsk_info->proc_chains); // proc chains - diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack - } -} - static void push_tskinfo_2_buffer_orig(variable_monitor_task *tsk_info, unsigned long *flags, struct diag_variant_buffer *buffer) { @@ -146,9 +121,6 @@ static void push_tskinfo_2_buffer_orig(variable_monitor_task *tsk_info, /** * @brief push task info to global buffer - * - * @param tsk_info - * @param flags */ // static void push_tskinfo_2_buffer(variable_monitor_task *tsk_info, // unsigned long *flags) { @@ -157,9 +129,6 @@ static void push_tskinfo_2_buffer_orig(variable_monitor_task *tsk_info, /** * @brief push task info to stand_alone_buffer - * - * @param tsk_info - * @param flags */ static void push_tskinfo_2_sa_buffer(variable_monitor_task *tsk_info, unsigned long *flags) { @@ -172,9 +141,9 @@ static void push_tskinfo_2_sa_buffer(variable_monitor_task *tsk_info, * @param tsk_info * @param flags */ -static void push_tskinfo_22_buffer_orig(variable_monitor_task *tsk_info, - unsigned long *flags, - struct diag_variant_buffer *buffer) { +static void push_tskinfo_2_buffer_unlock_orig(variable_monitor_task *tsk_info, + unsigned long *flags, + struct diag_variant_buffer *buffer) { variable_monitor_task_system *tsk_info_system; if (tsk_info->task.sys_task == 1) // system task { @@ -192,38 +161,42 @@ static void push_tskinfo_22_buffer_orig(variable_monitor_task *tsk_info, } } -static void push_tskinfo_22_buffer(variable_monitor_task *tsk_info, +static void push_tskinfo_2_buffer_unlock(variable_monitor_task *tsk_info, unsigned long *flags) { - push_tskinfo_22_buffer_orig(tsk_info, flags, &load_monitor_variant_buffer); -} - -// static void push_tskinfo_22_sa_buffer(variable_monitor_task *tsk_info, -// unsigned long *flags) { -// push_tskinfo_22_buffer_orig(tsk_info, flags, &stand_alone_buffer); -// } - -/// @brief clear all watch and reset kernel_wtimer_list/kernel_wtimer_num -/// @param -static void clear_all_watch(void) { - printk(KERN_INFO "clear all watch variable\n"); - // cancel timer - cancel_all_hrTimer(); - // stop and destory work - cancel_destory_all_work(); - // unmap and release the page - free_all_page_list(); - // clear timer - kernel_wtimer_num = 0; - memset(kernel_wtimer_list, 0, sizeof(kernel_wtimer_list)); + push_tskinfo_2_buffer_unlock_orig(tsk_info, flags, &load_monitor_variant_buffer); } /** - * @brief all threshold reached info + * @brief diag sign task info + * system task: kernel stack | proc chains + * other task(user / unknow): kernel stack | proc chains | raw stack + * stack + * + * @param p + * @param tsk_info + */ +static void diag_task_signal(struct task_struct *p, variable_monitor_task *tsk_info) { + unsigned int nr_bt; + // printk(KERN_INFO "diag_task_signal\n"); + diag_task_brief(p, &tsk_info->task); // task brief + if (tsk_info->task.sys_task == 1) { // system task + nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack + dump_proc_chains_argv(1, p, &mm_tree_struct, + &tsk_info->proc_chains); // proc chains + } else { // other task + nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack + dump_proc_chains_argv(1, p, &mm_tree_struct, + &tsk_info->proc_chains); // proc chains + diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack + } +} +/** + * @brief get all threshold reached info and pust to global buffer * * @param k_watch_timer - * @param is_print + * @param is_print 1 mean print to dmesg */ -static void diag_vm_record(kernel_watch_timer *k_watch_timer, +static void diag_threshold_reached_record(kernel_watch_timer *k_watch_timer, unsigned char is_print) { unsigned long long start_time = ktime_get_real(); @@ -284,7 +257,9 @@ static void diag_vm_record(kernel_watch_timer *k_watch_timer, * * @param tgid */ -void diag_task_by_tgid_orig(pid_t tgid, struct diag_variant_buffer *buffer) { +static void diag_task_by_tgid_orig(pid_t tgid, struct diag_variant_buffer *buffer) { + + // pr_info("diag_task_by_tgid %d\n", tgid); struct task_struct *tsk; int ret; @@ -305,27 +280,26 @@ void diag_task_by_tgid_orig(pid_t tgid, struct diag_variant_buffer *buffer) { diag_variant_buffer_spin_lock(buffer, flags); - struct task_struct *thread = tsk; + struct task_struct *g, *t; + g = tsk; unsigned long event_id = get_cycles(); - while_each_thread(tsk, thread) { - + for_each_thread(g, t) { tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE; tsk_info.id = event_id; tsk_info.tv = ktime_get_real(); - diag_tsk(tsk, &tsk_info); - - push_tskinfo_22_buffer_orig(&tsk_info, &flags, buffer); // push to buffer + diag_task_signal(t, &tsk_info); + push_tskinfo_2_buffer_unlock_orig(&tsk_info, &flags, buffer); // push to buffer } diag_variant_buffer_spin_unlock(buffer, flags); rcu_read_unlock(); } -void diag_task_by_tgid(pid_t tgid){ +void diag_task_by_tgid(pid_t tgid) { diag_task_by_tgid_orig(tgid, &load_monitor_variant_buffer); } -void diag_task_sa_by_tgid(pid_t tgid){ +void diag_task_sa_by_tgid(pid_t tgid) { diag_task_by_tgid_orig(tgid, &stand_alone_buffer); } @@ -348,15 +322,12 @@ void diag_task_all(void) { ((READ_ONCE(p->__state) & TASK_IDLE) != 0)) { // get_task_struct(p); // count +1 - tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE; tsk_info.id = event_id; tsk_info.tv = ktime_get_real(); - diag_tsk(p, &tsk_info); - + diag_task_signal(p, &tsk_info); // put_task_struct(p); // count -1 - - push_tskinfo_22_buffer(&tsk_info, &flags); // push to buffer + push_tskinfo_2_buffer_unlock(&tsk_info, &flags); // push to buffer } } while_each_thread(g, p); @@ -365,6 +336,29 @@ void diag_task_all(void) { rcu_read_unlock(); } + +void diag_task_by_tsk(struct task_struct *tsk, + struct diag_variant_buffer *buffer) { + unsigned long flags; + + static variable_monitor_task tsk_info; + + rcu_read_lock(); + diag_variant_buffer_spin_lock(buffer, flags); + + unsigned long event_id = get_cycles(); + + tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE; + tsk_info.id = event_id; + tsk_info.tv = ktime_get_real(); + diag_task_signal(tsk, &tsk_info); + + push_tskinfo_2_buffer_unlock_orig(&tsk_info, &flags, buffer); // push to buffer + + diag_variant_buffer_spin_unlock(buffer, flags); + rcu_read_unlock(); +} + /** * @brief diag task entry * @@ -373,19 +367,24 @@ void diag_task_all(void) { void diag_task(kernel_watch_timer *k_watch_timer) { if (k_watch_timer->threshold_over_count <= 0) // if no threshold reached return; - pr_info("diag_stack, tv %lld\n", ktime_get_real()); + // pr_info("diag_stack, tv %lld\n", ktime_get_real()); + diag_threshold_reached_record(k_watch_timer, 1); + if (sample_all) { // sample all task + // pr_info("diag_stack, sample all\n"); diag_task_all(); } else { // only care threshold reached task - int i; - kernel_watch_arg *kwarg; - for (i = 0; i < k_watch_timer->threshold_over_count; i++) { - kwarg = &k_watch_timer->k_watch_args[k_watch_timer->threshold_buffer[i]]; - diag_task_by_tgid_orig(kwarg->task_id, &load_monitor_variant_buffer); - } + // pr_info("diag_stack, sample threshold reached\n"); + diag_task_by_tgid_orig(k_watch_timer->task->tgid, + &load_monitor_variant_buffer); + // int i; + // kernel_watch_arg *kwarg; + // for (i = 0; i < k_watch_timer->threshold_over_count; i++) { + // kwarg = &k_watch_timer->k_watch_args[k_watch_timer->threshold_buffer[i]]; + // diag_task_by_tgid_orig(kwarg->task_id, &load_monitor_variant_buffer); + // } } - pr_info("diag_stack, finish tv %lld\n", ktime_get_real()); - diag_vm_record(k_watch_timer, 1); + // pr_info("diag_stack, finish tv %lld\n", ktime_get_real()); } /** @@ -399,6 +398,21 @@ void diag_task_info_work(struct work_struct *work) { diag_task(k_watch_timer); } +/// @brief clear all watch and reset kernel_wtimer_list/kernel_wtimer_num +/// @param +static void clear_all_watch(void) { + printk(KERN_INFO "clear all watch variable\n"); + // cancel timer + cancel_all_hrTimer(); + // stop and destory work + cancel_destory_all_work(); + // unmap and release the page + free_all_page_list(); + // clear timer + kernel_wtimer_num = 0; + memset(kernel_wtimer_list, 0, sizeof(kernel_wtimer_list)); +} + /** * @brief all module function init. orig_X | buffer * @@ -457,7 +471,7 @@ int start_watch_variable(watch_arg warg) { } // k_watch_arg init w_arg2k_w_arg(kptr, warg, &k_watch_arg); - timer = get_timer(warg.time_ns); // get a valuable timer + timer = get_timer(warg.task_id, warg.time_ns); // get a valuable timer if (timer == NULL) { printk(KERN_ERR "No timer available, ALL timer is full\n"); @@ -509,48 +523,56 @@ void clear_watch(pid_t pid) { start_all_hrTimer(); // restart timer } -#include -#include - -static void ipi_test(void *info) { - // pr_info("CPU%d do task\n", smp_processor_id()); - struct task_struct *tsk = current; - // pr_info("CPU%d pid: %d, name: %s\n", smp_processor_id(), tsk->pid, tsk->comm); - - struct diag_variant_buffer *buffer = &stand_alone_buffer; - unsigned long flags; - - static variable_monitor_task tsk_info; - - rcu_read_lock(); - diag_variant_buffer_spin_lock(buffer, flags); - - unsigned long event_id = get_cycles(); - - tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE; - tsk_info.id = event_id; - tsk_info.tv = ktime_get_real(); - pr_info("diag_tsk tv %lld\n", tsk_info.tv); - diag_tsk(tsk, &tsk_info); - - push_tskinfo_22_buffer_orig(&tsk_info, &flags, buffer); // push to buffer - - diag_variant_buffer_spin_unlock(buffer, flags); - rcu_read_unlock(); +/** + * @brief for ipi call + * + * @param info + */ +static void capture_immediate_diag_ipi(void *info) { + struct task_struct *tsk = current; + struct diag_variant_buffer *buffer = + &stand_alone_buffer; //! todo change to global buffer + diag_task_by_tsk(tsk, buffer); } /** - * @brief main callback function + * @brief immediate capture entry * - * @param timer - * @return enum hrtimer_restart + * @param k_watch_timer + * @return int 0 maean no threshold reached, 1 mean someone reached threshold */ -enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { - kernel_watch_timer *k_watch_timer = - container_of(timer, kernel_watch_timer, hr_timer); - int i = 0, j = 0; - kernel_watch_arg *kwarg; +static int capture_immediate_entry(kernel_watch_timer *k_watch_timer) { + int i = 0; + static kernel_watch_arg *kwarg; + // check all watched kernel_watch_arg + for (i = 0; i < k_watch_timer->sentinel; i++) { + kwarg = &k_watch_timer->k_watch_args[i]; + if (read_and_compare(kwarg->kptr, kwarg->length_byte, + kwarg->above_threshold, kwarg->is_unsigned, + kwarg->threshold)) { + // some value reached threshold + // if task run on cpu, call ipi immediately + if (k_watch_timer->task->on_cpu) { + smp_call_function_single(task_cpu(k_watch_timer->task), + capture_immediate_diag_ipi, NULL, 0); + } else { + diag_task_by_tsk(k_watch_timer->task, &load_monitor_variant_buffer); + } + return 1; + } + } + return 0; +} +/** + * @brief aggregate capture entry + * + * @param k_watch_timer + * @return int 0 maean no threshold reached + */ +static int capture_aggregate_entry(kernel_watch_timer *k_watch_timer) { + int i = 0, j = 0; + static kernel_watch_arg *kwarg; // check all watched kernel_watch_arg for (i = 0; i < k_watch_timer->sentinel; i++) { kwarg = &k_watch_timer->k_watch_args[i]; @@ -564,31 +586,38 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { j++; } } - if (j > 0) // if any threshold reached - { + if (j > 0) { // if any threshold reached k_watch_timer->threshold_over_count = j; k_watch_timer->tv = ktime_get_real(); - pr_info("threshold reached, tv %lld\n", k_watch_timer->tv); // highpri_wq - // queue_work(system_highpri_wq, &k_watch_timer->wk); + queue_work(system_highpri_wq, &k_watch_timer->wk); + } + return j; +} +/** + * @brief main callback function + * + * @param timer + * @return enum hrtimer_restart + */ +enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { + kernel_watch_timer *k_watch_timer = + container_of(timer, kernel_watch_timer, hr_timer); + int j = 0; - pid_t pid = (pid_t)2636; - struct task_struct *tsk; - tsk = NULL; - - rcu_read_lock(); - if (orig_find_task_by_vpid) - tsk = orig_find_task_by_vpid(pid); - rcu_read_unlock(); - if (tsk) { - int cpu = task_cpu(tsk); - // pr_info("diag_pid: %d, cpu %d\n", tsk->pid, cpu); - smp_call_function_single(cpu, ipi_test, NULL, 1); - } - - // diag_task(k_watch_timer); - // orig_raise_softirq(MY_SOFTIRQ); // for swirq test + switch (stack_capture_mode) { + case STACK_CAPTURE_IMMEDIATE: + j = capture_immediate_entry(k_watch_timer); + break; + case STACK_CAPTURE_AGGREGATE: + j = capture_aggregate_entry(k_watch_timer); + break; + default: + j = capture_aggregate_entry(k_watch_timer); + break; + } + if (j > 0) { // if any threshold reached // restart timer after dump_reset_sec sec hrtimer_forward(timer, timer->base->get_time(), ktime_set(dump_reset_sec, 0)); @@ -599,6 +628,23 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { return HRTIMER_RESTART; // restart timer } +// dump log from buffer +int dump_log(ioctl_dump_param *dump_param, unsigned long ioctl_param, + struct diag_variant_buffer *buffer) { + int ret = 0; + ret = copy_from_user(dump_param, (ioctl_dump_param *)ioctl_param, + sizeof(ioctl_dump_param)); + printk(KERN_INFO "dump_param: %p %lx %p\n", dump_param->user_ptr_len, + dump_param->user_buf_len, dump_param->user_buf); + if (!ret) { + ret = copy_to_user_variant_buffer(buffer, dump_param->user_ptr_len, + dump_param->user_buf, + dump_param->user_buf_len); + printk(KERN_INFO "ret %d, %lx\n", ret, dump_param->user_buf_len); + } + return ret; +} + /** * @brief for test only * @@ -630,16 +676,19 @@ int diag_pid(int id) { int cpu = task_cpu(tsk); pr_info("diag_pid: %d, cpu %d\n", tsk->pid, cpu); - // smp_call_function_single(cpu, ipi_test, NULL, 1); // 让 CPU2 执行 print_str() + // smp_call_function_single(cpu, ipi_timer_check_output, NULL, 1); // 让 CPU2 + // 执行 print_str() // get_task_struct(tsk); // count +1 // tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE; // tsk_info.id = event_id; // tsk_info.tv = vm_record.tv; - // diag_tsk(tsk, &tsk_info); + // diag_task_signal(tsk, &tsk_info); // printk(KERN_INFO "pid: %d, name: %s\n", tsk->pid, tsk->comm); - // setup_perf_event_for_task(tsk); // setup perf event for task + + pr_info("perf, tv %lld\n", ktime_get_real()); + setup_perf_event_for_task(tsk); // setup perf event for task // put_task_struct(tsk); // count -1 @@ -685,7 +734,7 @@ int diag_tgid(int id) { tsk_info.et_type = VARIABLE_MONITOR_TASK_TYPE; tsk_info.id = event_id; tsk_info.tv = vm_record.tv; - diag_tsk(thread, &tsk_info); + diag_task_signal(thread, &tsk_info); put_task_struct(thread); // count -1