diff --git a/source/module/monitor_kernel.c b/source/module/monitor_kernel.c index aa5754d..c6350d4 100644 --- a/source/module/monitor_kernel.c +++ b/source/module/monitor_kernel.c @@ -42,31 +42,35 @@ static int device_release(struct inode *inode, struct file *file) { return 0; } +typedef struct { + int pid; +} ioctl_pid; + static long device_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { int ret = 0; - watch_arg warg; + // watch_arg warg; ioctl_dump_param dump_param; - int wpid; + ioctl_pid wpid; printk(KERN_INFO "variable_monitor fun: %s with ioctl_num %d\n", __FUNCTION__, ioctl_num); switch (ioctl_num) { - case 0: - // copy watch_arg - if (copy_from_user(&warg, (watch_arg *)ioctl_param, sizeof(warg))) { - return -EACCES; - } - printk(KERN_INFO - "Watch_arg: task_id=%d, name=%s, ptr=%p, length_byte=%d, " - "time_ns=%ld, threshold=%lld\n", - warg.task_id, warg.name, warg.ptr, warg.length_byte, warg.time_ns, - warg.threshold); - // start watch variable - start_watch_variable(warg); - break; + // case 0: + // // copy watch_arg + // if (copy_from_user(&warg, (watch_arg *)ioctl_param, sizeof(warg))) { + // return -EACCES; + // } + // printk(KERN_INFO + // "Watch_arg: task_id=%d, name=%s, ptr=%p, length_byte=%d, " + // "time_ns=%ld, threshold=%lld\n", + // warg.task_id, warg.name, warg.ptr, warg.length_byte, warg.time_ns, + // warg.threshold); + // // start watch variable + // start_watch_variable(warg); + // break; case 1: printk(KERN_INFO "variable_monitor 1\n"); ret = copy_from_user(&dump_param, (ioctl_dump_param *)ioctl_param, @@ -82,13 +86,16 @@ static long device_ioctl(struct file *file, unsigned int ioctl_num, } printk(KERN_INFO "copy_to_user \n"); break; - case 2: + case 0: printk(KERN_INFO "variable_monitor test 2\n"); - ret = copy_from_user(&wpid, (int *)ioctl_param, sizeof(int)); - diag_test(wpid); + ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid)); + diag_test(wpid.pid); /* code */ break; default: + printk(KERN_INFO "variable_monitor test default\n"); + ret = copy_from_user(&wpid, (ioctl_pid *)ioctl_param, sizeof(ioctl_pid)); + diag_test(wpid.pid); break; } return 0; @@ -107,21 +114,6 @@ int init_module(void) { return -1; } - if ((watch_cdev = cdev_alloc()) == NULL) { - printk(KERN_ALERT "Failed to allocate cdev structure\n"); - unregister_chrdev_region(dev_num, 1); - return -1; - } - - cdev_init(watch_cdev, &fops); - if (cdev_add(watch_cdev, dev_num, 1) == -1) { - printk(KERN_ALERT "Failed to add cdev structure\n"); - device_destroy(watch_class, dev_num); - class_destroy(watch_class); - unregister_chrdev_region(dev_num, 1); - return -1; - } - if ((watch_class = class_create(THIS_MODULE, DEVICE_NAME)) == NULL) { printk(KERN_ALERT "Failed to create class\n"); cdev_del(watch_cdev); @@ -137,6 +129,21 @@ int init_module(void) { return -1; } + if ((watch_cdev = cdev_alloc()) == NULL) { + printk(KERN_ALERT "Failed to allocate cdev structure\n"); + unregister_chrdev_region(dev_num, 1); + return -1; + } + + cdev_init(watch_cdev, &fops); + if (cdev_add(watch_cdev, dev_num, 1) == -1) { + printk(KERN_ALERT "Failed to add cdev structure\n"); + device_destroy(watch_class, dev_num); + class_destroy(watch_class); + unregister_chrdev_region(dev_num, 1); + return -1; + } + printk(KERN_INFO "dev number: %d\n", dev_num); printk(KERN_INFO "path: /dev/%s %d\n", DEVICE_NAME, dev_num); diff --git a/source/module/monitor_kernel.h b/source/module/monitor_kernel.h index 1171f2e..be6f2ca 100644 --- a/source/module/monitor_kernel.h +++ b/source/module/monitor_kernel.h @@ -14,4 +14,4 @@ void clear_watch(pid_t pid); enum hrtimer_restart check_variable_cb(struct hrtimer *timer); // callback -static int diag_test(int nid); // for test +int diag_test(int nid); \ No newline at end of file diff --git a/source/module/monitor_kernel_lib.c b/source/module/monitor_kernel_lib.c index 1e5af32..05515d4 100644 --- a/source/module/monitor_kernel_lib.c +++ b/source/module/monitor_kernel_lib.c @@ -55,14 +55,12 @@ static int init_buffer(unsigned int buf_size) { return ret; } -void diag_tsk(struct task_struct *p, variable_monitor_task *tsk_info, - unsigned long *flags) { +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 // printk("1\n"); diag_task_user_stack(p, &tsk_info->user_stack); // user stack - diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack // printk("2\n"); nr_bt = diag_task_kern_stack(p, &tsk_info->kern_stack); // kernel stack // int i = 0; @@ -76,14 +74,16 @@ void diag_tsk(struct task_struct *p, variable_monitor_task *tsk_info, // printk("3\n"); dump_proc_chains_argv(1, p, &mm_tree_struct, &tsk_info->proc_chains); // proc chains - // printk("4\n"); + diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack +} + +static void push_tsk_info(variable_monitor_task *tsk_info,unsigned long *flags) { + printk(KERN_INFO "push_tsk_info\n"); diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, *flags); diag_variant_buffer_reserve(&load_monitor_variant_buffer, sizeof(variable_monitor_task)); - // printk("5\n"); diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, tsk_info, sizeof(variable_monitor_task)); - // printk("6\n"); diag_variant_buffer_seal(&load_monitor_variant_buffer); diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, *flags); } @@ -243,24 +243,18 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { do_each_thread(g, p) { if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) || p->__state == TASK_IDLE || 1) { + + get_task_struct(p); + tsk_info.et_type = 1; //! todo event type tsk_info.id = event_id; tsk_info.tv = vm_record.tv; - diag_tsk(p, &tsk_info, &flags); - // diag_task_brief(p, &tsk_info.task); // task brief - // diag_task_user_stack(p, &tsk_info.user_stack); // user stack - // 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_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags); - // diag_variant_buffer_reserve(&load_monitor_variant_buffer, - // sizeof(variable_monitor_task)); - // diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, - // &tsk_info, - // sizeof(variable_monitor_task)); - // diag_variant_buffer_seal(&load_monitor_variant_buffer); - // diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags); + diag_tsk(p, &tsk_info); + + put_task_struct(p); + + push_tsk_info(&tsk_info, &flags); } } while_each_thread(g, p); @@ -276,62 +270,129 @@ enum hrtimer_restart check_variable_cb(struct hrtimer *timer) { return HRTIMER_RESTART; // restart timer } -static void test(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 - // printk("1\n"); - diag_task_user_stack(p, &tsk_info->user_stack); // user stack - diag_task_raw_stack(p, &tsk_info->raw_stack); // raw stack - 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 -} +// static int diag_test(int nid); // for test +// static void test(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 +// // printk("1\n"); +// diag_task_user_stack(p, &tsk_info->user_stack); // user stack +// 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 +// printk(KERN_INFO "diag_tsk finish\n"); +// } -static void test2(variable_monitor_task *tsk_info, unsigned long *flags){ - diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, *flags); - diag_variant_buffer_reserve(&load_monitor_variant_buffer,sizeof(variable_monitor_task)); - diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, &tsk_info, - sizeof(variable_monitor_task)); - diag_variant_buffer_seal(&load_monitor_variant_buffer); - diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, *flags); -} +// static void test2(variable_monitor_task *tsk_info, unsigned long flags){ +// printk(KERN_INFO "test2\n"); +// diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags); +// diag_variant_buffer_reserve(&load_monitor_variant_buffer,sizeof(variable_monitor_task)); +// diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, tsk_info, +// sizeof(variable_monitor_task)); +// diag_variant_buffer_seal(&load_monitor_variant_buffer); +// diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags); +// printk(KERN_INFO "test2 finish\n"); +// } -static int diag_test(int nid){ - struct task_struct *tsk; - struct task_struct *leader; - variable_monitor_task tsk_info; - // unsigned int nr_bt; +int diag_test(int nid){ + // static struct task_struct *tsk; + // static struct task_struct *leader; + // static variable_monitor_task tsk_info; + // // unsigned int nr_bt; - int ret; - unsigned long flags; - pid_t id = (pid_t)nid; + // int ret; + // unsigned long flags; + // pid_t id = (pid_t)nid; - rcu_read_lock(); - tsk = NULL; - if (orig_find_task_by_vpid) - tsk = orig_find_task_by_vpid(id); - if (!tsk) { - ret = -EINVAL; - rcu_read_unlock(); - return ret; - } + // rcu_read_lock(); + // tsk = NULL; + // if (orig_find_task_by_vpid) + // tsk = orig_find_task_by_vpid(id); + // if (!tsk) { + // ret = -EINVAL; + // rcu_read_unlock(); + // return ret; + // } - leader = tsk->group_leader; - if (leader == NULL || leader->exit_state == EXIT_ZOMBIE){ - ret = -EINVAL; - rcu_read_unlock(); - return ret; - } + // leader = tsk->group_leader; + // if (leader == NULL || leader->exit_state == EXIT_ZOMBIE){ + // ret = -EINVAL; + // rcu_read_unlock(); + // return ret; + // } - get_task_struct(tsk); - rcu_read_unlock(); + // get_task_struct(tsk); + // rcu_read_unlock(); - test(tsk, &tsk_info); + // tsk_info.et_type = 1; + // test(tsk, &tsk_info); - put_task_struct(tsk); + // put_task_struct(tsk); + // printk(KERN_INFO "put_task_struct finish\n"); - test2(&tsk_info, &flags); + // diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags); + // printk(KERN_INFO "1\n"); + // diag_variant_buffer_reserve(&load_monitor_variant_buffer,sizeof(variable_monitor_task)); + // printk(KERN_INFO "2\n"); + // diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, &tsk_info, + // sizeof(variable_monitor_task)); + // printk(KERN_INFO "3\n"); + // diag_variant_buffer_seal(&load_monitor_variant_buffer); + // printk(KERN_INFO "4\n"); + // diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags); + // printk(KERN_INFO "5\n"); + + struct task_struct *g, *p; // g: task group; p: task + unsigned long flags; + unsigned long event_id = get_cycles(); + + static variable_monitor_task tsk_info = {0}; + static variable_monitor_record vm_record = {0}; + + // vm_record.id = event_id; + // vm_record.et_type = 0; //! todo event type + vm_record.tv = ktime_get_real(); + // vm_record.threshold_num = j; + + // printk("-------------------------------------\n"); + // printk("-------------watch monitor-----------\n"); + // printk("Threshold reached:\n"); + // for (i = 0; i < j; i++) { + // kwarg = &k_watch_timer->k_watch_args[buffer[i]]; + // k_w_arg2threshold(kwarg, &vm_record.threshold_record[i]); + // } + // rcu_read_lock(); + + // diag_variant_buffer_spin_lock(&load_monitor_variant_buffer, flags); + // diag_variant_buffer_reserve(&load_monitor_variant_buffer, + // sizeof(variable_monitor_record)); + // diag_variant_buffer_write_nolock(&load_monitor_variant_buffer, &vm_record, + // sizeof(variable_monitor_record)); + // diag_variant_buffer_seal(&load_monitor_variant_buffer); + // diag_variant_buffer_spin_unlock(&load_monitor_variant_buffer, flags); + + rcu_read_unlock(); + + do_each_thread(g, p) { + if (p->__state == TASK_RUNNING || __task_contributes_to_load(p) || + p->__state == TASK_IDLE || 1) { + + get_task_struct(p); + + tsk_info.et_type = 1; //! todo event type + tsk_info.id = event_id; + tsk_info.tv = vm_record.tv; + + diag_tsk(p, &tsk_info); + + put_task_struct(p); + + push_tsk_info(&tsk_info, &flags); + } + } + while_each_thread(g, p); + printk("-------------------------------------\n"); return 0; } \ No newline at end of file diff --git a/source/module/monitor_trace.c b/source/module/monitor_trace.c index 3455204..b5cebe0 100644 --- a/source/module/monitor_trace.c +++ b/source/module/monitor_trace.c @@ -266,9 +266,9 @@ static int diagnose_task_raw_stack_remote(struct task_struct *tsk, void *to, return 0; } - // if (in_atomic() || irqs_disabled()) { - // return 0; - // } + if (in_atomic() || irqs_disabled()) { + return 0; + } mm = get_task_mm(tsk); if (!mm) @@ -277,7 +277,7 @@ static int diagnose_task_raw_stack_remote(struct task_struct *tsk, void *to, ret = orig_access_remote_vm(mm, (unsigned long)from, to, n, 0); mmput(mm); - printk("task_raw_stack_remote %d access_remote_vm %d\n", tsk->pid, ret); + printk("task_raw_stack_remote %d access_remote_vm ret: %d\n", tsk->pid, ret); return ret < 0 ? ret : 0; } @@ -493,6 +493,7 @@ void diag_task_raw_stack(struct task_struct *tsk, raw_stack_detail *detail) { ret = diagnose_task_raw_stack_remote( tsk, stack, (void __user *)sp + detail->stack_size, 1024); } + printk("diag_task_raw_stack %d i:%d ret:%d\n", tsk->pid, i, ret); if (ret) break; else diff --git a/source/module/monitor_trace.h b/source/module/monitor_trace.h index 0d8420b..e940b86 100644 --- a/source/module/monitor_trace.h +++ b/source/module/monitor_trace.h @@ -89,9 +89,9 @@ typedef struct { unsigned long long tv; task_detail task; // brief user_stack_detail user_stack; // user stack - raw_stack_detail raw_stack; kern_stack_detail kern_stack; // kernel stack proc_chains_detail proc_chains; // process chains argv + raw_stack_detail raw_stack; } variable_monitor_task; typedef struct { diff --git a/source/ucli_py/lib.py b/source/ucli_py/lib.py index 9b7874c..79d22ae 100644 --- a/source/ucli_py/lib.py +++ b/source/ucli_py/lib.py @@ -12,6 +12,7 @@ TASK_COMM_LEN = 16 BACKTRACE_DEPTH = 30 PROCESS_CHAINS_COUNT = 10 PROCESS_ARGV_LEN = 128 +DIAG_USER_STACK_SIZE = 16 * 1024 class threshold(ctypes.Structure): @@ -86,6 +87,17 @@ class user_stack_detail(ctypes.Structure): ] +class raw_stack_detail(ctypes.Structure): + _fields_ = [ + ("regs", PtRegs), # Replace with actual type + ("ip", c_ulong), + ("bp", c_ulong), + ("sp", c_ulong), + ("stack_size", c_ulong), + ("stack", c_ulong * (DIAG_USER_STACK_SIZE // 8)), + ] + + class kern_stack_detail(ctypes.Structure): _fields_ = [ ("stack", c_ulong * BACKTRACE_DEPTH), @@ -120,6 +132,7 @@ class variable_monitor_task(ctypes.Structure): ("user_stack", user_stack_detail), ("kern_stack", kern_stack_detail), ("proc_chains", proc_chains_detail), + ("raw_stack", raw_stack_detail), ] diff --git a/source/ucli_py/ucli.py b/source/ucli_py/ucli.py index 55c2f33..8e42110 100644 --- a/source/ucli_py/ucli.py +++ b/source/ucli_py/ucli.py @@ -255,16 +255,16 @@ def load_monitor_extract(buf, len, _): if __name__ == "__main__": - # open_device() - # do_dump(None) - # close_device() + open_device() + do_dump(None) + close_device() - with open("buff", "rb") as f: - buf_bytes = pickle.load(f) + # with open("buff", "rb") as f: + # buf_bytes = pickle.load(f) - buf2 = ctypes.create_string_buffer(len(buf_bytes)) - buf2.raw = buf_bytes + # buf2 = ctypes.create_string_buffer(len(buf_bytes)) + # buf2.raw = buf_bytes - with open("len", "rb") as f: - len2 = pickle.load(f) - do_extract(buf2, len2.value) + # with open("len", "rb") as f: + # len2 = pickle.load(f) + # do_extract(buf2, len2.value) diff --git a/tools/diag.c b/tools/diag.c new file mode 100644 index 0000000..62ef582 --- /dev/null +++ b/tools/diag.c @@ -0,0 +1,63 @@ +// #include "monitor_user.h" +#include +#include +#include +#include +#include + +#define DEVICE "/dev/variable_monitor" +int file_desc = -1; + +pid_t pid = 0; + +/// @brief start watch +/// @param w_arg +/// @return 0 means success, other means fail +int start_watch() { + if (file_desc < 0) { + file_desc = open(DEVICE, 0); + } + if (file_desc < 0) { + printf("Can't open device file: %s\n", DEVICE); + return -1; + } + + printf("1 \n"); + + if (ioctl(file_desc, 2, &pid) < 0) { + printf("ioctl failed\n"); + close(file_desc); + return -1; + } + + printf("2 \n"); + return 0; +} + +/// @brief cancel watch +/// @return 0 means success, other means fail +int cancel_watch() { + if (file_desc < 0) { + file_desc = open(DEVICE, 0); + } + if (file_desc < 0) { + printf("Device not open: %s,%d \n", DEVICE, file_desc); + return file_desc; + } + + close(file_desc); + file_desc = -1; + return 0; +} + +int main(int argc, char **argv){ + if (argc != 2) + printf("USAGE: unwind-pid \n"); + + pid = atoi(argv[1]); + + printf("%d \n", pid); + + start_watch(); + cancel_watch(); +} \ No newline at end of file diff --git a/tools/diag.py b/tools/diag.py new file mode 100644 index 0000000..6affd08 --- /dev/null +++ b/tools/diag.py @@ -0,0 +1,53 @@ +DEVICE = "/dev/variable_monitor" +import os, sys +import ctypes +from ctypes import * +import fcntl + +file_desc = None + + +def open_device(): + global file_desc + if file_desc is None: + try: + file_desc = os.open(DEVICE, os.O_RDWR) + except OSError: + print(f"Can't open device file: {DEVICE}") + return -1 + return 0 + + +def close_device(): + global file_desc + if file_desc is None: + print(f"Device not open: {DEVICE}, {file_desc}") + return file_desc + + os.close(file_desc) + file_desc = None + return 0 + + +class ioctl_pid(Structure): + _fields_ = [ + ("pid", c_int), + ] + + +def ioctl(pid: int): + pidc = ioctl_pid( + pid=c_int(pid), + ) + ret = fcntl.ioctl(file_desc, 0, pidc) + if ret == 0: + print("success") + + +pid = int(sys.argv[1]) + +open_device() + +ioctl(pid) + +close_device()