#include "monitor_kernel.h" /** * @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 *ptr, 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->kptr = ptr; k_watch_arg->length_byte = warg.length_byte; k_watch_arg->threshold = warg.threshold; k_watch_arg->unsigned_flag = warg.unsigned_flag; k_watch_arg->greater_flag = warg.greater_flag; return 0; } static void init_mm_tree(mm_tree *mm_tree) { INIT_RADIX_TREE(&mm_tree->mm_tree, GFP_ATOMIC); spin_lock_init(&mm_tree->mm_tree_lock); } static int init_buffer(unsigned int buf_size) { init_mm_tree(&mm_tree_struct); // init mm_tree init_diag_variant_buffer(&load_monitor_variant_buffer, buf_size); int ret = 0; ret = alloc_diag_variant_buffer(&load_monitor_variant_buffer); return ret; } /// @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"); // unmap and release the page free_all_page_list(); // cancel timer cancel_all_hrTimer(); // clear timer kernel_wtimer_num = 0; memset(kernel_wtimer_list, 0, sizeof(kernel_wtimer_list)); } /** * @brief all module function init. orig_X | buffer * * @return int */ int monitor_init(void) { int ret = 0; init_orig_fun(); // init orig_X ret = init_buffer(50 * 1024 * 1024); // 50M if (ret) return 0; return 0; } /** * @brief monitor exit: clear all watch and free buffer * */ void monitor_exit() { // clear all watch clear_all_watch(); // free buffer destroy_diag_variant_buffer(&load_monitor_variant_buffer); } /** * @brief start watch variable * * @param warg: uapi watch_arg * @return int 0 is success * !todo: adjust printk */ int start_watch_variable(watch_arg warg) { void *kptr; kernel_watch_timer *timer = NULL; kernel_watch_arg k_watch_arg; // user space address to kernel space address kptr = convert_user_space_ptr(warg.task_id, (unsigned long)warg.ptr); if (kptr == NULL) { printk(KERN_ERR "Cannot access user space\n"); return -EACCES; } // check length if (warg.length_byte != 1 && warg.length_byte != 2 && warg.length_byte != 4 && warg.length_byte != 8) { printk(KERN_ERR "Invalid length %d\n", warg.length_byte); return -EINVAL; } // k_watch_arg init w_arg2k_w_arg(kptr, warg, &k_watch_arg); timer = get_timer(warg.time_ns); // get a valuable timer printk(KERN_INFO "ptr transform kptr: %p\n", kptr); printk(KERN_INFO "timer: %p\n", timer); printk(KERN_INFO "timer->sentinel: %d, timer->time_ns: %lld\n", timer->sentinel, timer->time_ns); printk(KERN_INFO "timer->hr_timer: %p\n", &timer->hr_timer); TIMER_CANCEL(timer); // just in case timer_add_watch(timer, k_watch_arg); TIMER_START(timer); printk(KERN_INFO "Start watching var: %s\n", warg.name); return 0; } /** * @brief clear watch with pid * * @param pid */ void clear_watch(pid_t pid) { printk(KERN_INFO "clear pid %d 's watch variable\n", pid); cancel_all_hrTimer(); // just in case del_all_kwarg_by_pid(pid); // delete all kwarg with pid free_page_list(pid); // free page with pid start_all_hrTimer(); // restart timer }