2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/energy/swap_energy.c
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Copyright (C) Samsung Electronics, 2013
21 * 2013 Vasiliy Ulyanov <v.ulyanov@samsung.com>
22 * Vyacheslav Cherkashin <v.cherkashin@samsung.com>
27 #include <linux/module.h>
28 #include <linux/file.h>
29 #include <linux/spinlock.h>
30 #include <linux/magic.h>
31 #include <linux/slab.h>
32 #include <linux/spinlock.h>
33 #include <linux/net.h>
34 #include <linux/socket.h>
35 #include <linux/skbuff.h>
36 #include <linux/string.h>
37 #include <linux/fdtable.h>
39 #include <kprobe/swap_kprobes.h>
40 #include <ksyms/ksyms.h>
41 #include <master/swap_deps.h>
42 #include <us_manager/sspt/sspt_proc.h>
43 #include <us_manager/sspt/sspt_feature.h>
44 #include <linux/atomic.h>
46 #include "lcd/lcd_base.h"
50 /* ============================================================================
52 * ============================================================================
59 static int energy_xxx_once(struct kern_probe p[], int size)
64 for (i = 0; i < size; ++i) {
65 struct kretprobe *rp = p[i].rp;
68 rp->kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
69 if (rp->kp.addr == NULL)
76 printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
80 static int energy_xxx_set(struct kern_probe p[], int size, int *flag)
84 for (i = 0; i < size; ++i) {
85 ret = swap_register_kretprobe(p[i].rp);
94 pr_err("swap_register_kretprobe(%s) ret=%d\n", p[i].name, ret);
96 for (--i; i != -1; --i)
97 swap_unregister_kretprobe(p[i].rp);
102 static void energy_xxx_unset(struct kern_probe p[], int size, int *flag)
109 for (i = size - 1; i != -1; --i)
110 swap_unregister_kretprobe(p[i].rp);
119 /* ============================================================================
121 * ============================================================================
124 spinlock_t lock; /* for concurrent access */
125 struct tm_stat tm[NR_CPUS];
128 #define cpus_time_lock(ct, flags) spin_lock_irqsave(&(ct)->lock, flags)
129 #define cpus_time_unlock(ct, flags) spin_unlock_irqrestore(&(ct)->lock, flags)
131 static void cpus_time_init(struct cpus_time *ct, u64 time)
135 spin_lock_init(&ct->lock);
137 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
138 tm_stat_init(&ct->tm[cpu]);
139 tm_stat_set_timestamp(&ct->tm[cpu], time);
143 static inline u64 cpu_time_get_running(struct cpus_time *ct, int cpu, u64 now)
145 return tm_stat_current_running(&ct->tm[cpu], now);
148 static void *cpus_time_get_running_all(struct cpus_time *ct, u64 *buf, u64 now)
152 for (cpu = 0; cpu < NR_CPUS; ++cpu)
153 buf[cpu] = tm_stat_current_running(&ct->tm[cpu], now);
158 static void *cpus_time_sum_running_all(struct cpus_time *ct, u64 *buf, u64 now)
162 for (cpu = 0; cpu < NR_CPUS; ++cpu)
163 buf[cpu] += tm_stat_current_running(&ct->tm[cpu], now);
168 static void cpus_time_save_entry(struct cpus_time *ct, int cpu, u64 time)
170 struct tm_stat *tm = &ct->tm[cpu];
172 if (unlikely(tm_stat_timestamp(tm))) /* should never happen */
173 printk(KERN_INFO "XXX %s[%d/%d]: WARNING tmstamp(%p) set on cpu(%d)\n",
174 current->comm, current->tgid, current->pid, tm, cpu);
175 tm_stat_set_timestamp(&ct->tm[cpu], time);
178 static void cpus_time_update_running(struct cpus_time *ct, int cpu, u64 now,
181 struct tm_stat *tm = &ct->tm[cpu];
183 if (unlikely(tm_stat_timestamp(tm) == 0)) {
184 /* not initialized. should happen only once per cpu/task */
185 printk(KERN_INFO "XXX %s[%d/%d]: nnitializing tmstamp(%p) "
187 current->comm, current->tgid, current->pid, tm, cpu);
188 tm_stat_set_timestamp(tm, start_time);
191 tm_stat_update(tm, now);
192 tm_stat_set_timestamp(tm, 0); /* set timestamp to 0 */
200 /* for __switch_to */
204 atomic64_t bytes_read;
207 atomic64_t bytes_written;
210 atomic64_t bytes_recv;
213 atomic64_t bytes_send;
216 atomic64_t bytes_l2cap_recv_acldata;
218 /* for sco_recv_scodata */
219 atomic64_t bytes_sco_recv_scodata;
221 /* for hci_send_acl */
222 atomic64_t bytes_hci_send_acl;
224 /* for hci_send_sco */
225 atomic64_t bytes_hci_send_sco;
228 static sspt_feature_id_t feature_id = SSPT_FEATURE_ID_BAD;
230 static void init_ed(struct energy_data *ed)
232 /* instead of get_ntime(), CPU time is initialized to 0 here. Timestamp
233 * value will be properly set when the corresponding __switch_to event
235 cpus_time_init(&ed->ct, 0);
236 atomic64_set(&ed->bytes_read, 0);
237 atomic64_set(&ed->bytes_written, 0);
238 atomic64_set(&ed->bytes_recv, 0);
239 atomic64_set(&ed->bytes_send, 0);
240 atomic64_set(&ed->bytes_l2cap_recv_acldata, 0);
241 atomic64_set(&ed->bytes_sco_recv_scodata, 0);
242 atomic64_set(&ed->bytes_hci_send_acl, 0);
243 atomic64_set(&ed->bytes_hci_send_sco, 0);
246 static void uninit_ed(struct energy_data *ed)
248 cpus_time_init(&ed->ct, 0);
249 atomic64_set(&ed->bytes_read, 0);
250 atomic64_set(&ed->bytes_written, 0);
251 atomic64_set(&ed->bytes_recv, 0);
252 atomic64_set(&ed->bytes_send, 0);
253 atomic64_set(&ed->bytes_l2cap_recv_acldata, 0);
254 atomic64_set(&ed->bytes_sco_recv_scodata, 0);
255 atomic64_set(&ed->bytes_hci_send_acl, 0);
256 atomic64_set(&ed->bytes_hci_send_sco, 0);
259 static void *create_ed(void)
261 struct energy_data *ed;
263 ed = kmalloc(sizeof(*ed), GFP_ATOMIC);
270 static void destroy_ed(void *data)
272 struct energy_data *ed = (struct energy_data *)data;
277 static int init_feature(void)
279 feature_id = sspt_register_feature(create_ed, destroy_ed);
281 if (feature_id == SSPT_FEATURE_ID_BAD)
287 static void uninit_feature(void)
289 sspt_unregister_feature(feature_id);
290 feature_id = SSPT_FEATURE_ID_BAD;
293 static struct energy_data *get_energy_data(struct task_struct *task)
296 struct sspt_proc *proc;
298 proc = sspt_proc_by_task(task);
300 data = sspt_get_feature_data(proc->feature, feature_id);
302 return (struct energy_data *)data;
305 static int check_fs(unsigned long magic)
308 case EXT2_SUPER_MAGIC: /* == EXT3_SUPER_MAGIC == EXT4_SUPER_MAGIC */
309 case MSDOS_SUPER_MAGIC:
316 static int check_ftype(int fd)
321 err = vfs_fstat(fd, &kstat);
322 if (err == 0 && S_ISREG(kstat.mode))
328 static int check_file(int fd)
335 if (file->f_path.dentry && file->f_path.dentry->d_sb)
336 magic = file->f_path.dentry->d_sb->s_magic;
340 if (check_fs(magic) && check_ftype(fd))
347 static unsigned long get_arg0(struct pt_regs *regs)
349 #if defined(CONFIG_ARM)
351 #elif defined(CONFIG_X86_32)
354 #error "this architecture is not supported"
355 #endif /* CONFIG_arch */
362 static struct cpus_time ct_idle;
363 static struct energy_data ed_system;
364 static u64 start_time;
366 static void init_data_energy(void)
368 start_time = get_ntime();
370 cpus_time_init(&ct_idle, 0);
373 static void uninit_data_energy(void)
376 uninit_ed(&ed_system);
377 cpus_time_init(&ct_idle, 0);
384 /* ============================================================================
386 * ============================================================================
388 static int entry_handler_switch(struct kretprobe_instance *ri,
389 struct pt_regs *regs)
392 struct cpus_time *ct;
393 struct energy_data *ed;
396 cpu = smp_processor_id();
398 ct = current->tgid ? &ed_system.ct : &ct_idle;
399 cpus_time_lock(ct, flags);
400 cpus_time_update_running(ct, cpu, get_ntime(), start_time);
401 cpus_time_unlock(ct, flags);
403 ed = get_energy_data(current);
406 cpus_time_lock(ct, flags);
407 cpus_time_update_running(ct, cpu, get_ntime(), start_time);
408 cpus_time_unlock(ct, flags);
414 static int ret_handler_switch(struct kretprobe_instance *ri,
415 struct pt_regs *regs)
418 struct cpus_time *ct;
419 struct energy_data *ed;
422 cpu = smp_processor_id();
424 ct = current->tgid ? &ed_system.ct : &ct_idle;
425 cpus_time_lock(ct, flags);
426 cpus_time_save_entry(ct, cpu, get_ntime());
427 cpus_time_unlock(ct, flags);
429 ed = get_energy_data(current);
432 cpus_time_lock(ct, flags);
433 cpus_time_save_entry(ct, cpu, get_ntime());
434 cpus_time_unlock(ct, flags);
440 static struct kretprobe switch_to_krp = {
441 .entry_handler = entry_handler_switch,
442 .handler = ret_handler_switch,
449 /* ============================================================================
451 * ============================================================================
453 struct sys_read_data {
457 static int entry_handler_sys_read(struct kretprobe_instance *ri,
458 struct pt_regs *regs)
460 struct sys_read_data *srd = (struct sys_read_data *)ri->data;
462 srd->fd = (int)get_arg0(regs);
467 static int ret_handler_sys_read(struct kretprobe_instance *ri,
468 struct pt_regs *regs)
470 int ret = regs_return_value(regs);
473 struct sys_read_data *srd;
475 srd = (struct sys_read_data *)ri->data;
476 if (check_file(srd->fd)) {
477 struct energy_data *ed;
479 ed = get_energy_data(current);
481 atomic64_add(ret, &ed->bytes_read);
483 atomic64_add(ret, &ed_system.bytes_read);
490 static struct kretprobe sys_read_krp = {
491 .entry_handler = entry_handler_sys_read,
492 .handler = ret_handler_sys_read,
493 .data_size = sizeof(struct sys_read_data)
500 /* ============================================================================
502 * ============================================================================
504 static int entry_handler_sys_write(struct kretprobe_instance *ri,
505 struct pt_regs *regs)
507 struct sys_read_data *srd = (struct sys_read_data *)ri->data;
509 srd->fd = (int)get_arg0(regs);
514 static int ret_handler_sys_write(struct kretprobe_instance *ri,
515 struct pt_regs *regs)
517 int ret = regs_return_value(regs);
520 struct sys_read_data *srd;
522 srd = (struct sys_read_data *)ri->data;
523 if (check_file(srd->fd)) {
524 struct energy_data *ed;
526 ed = get_energy_data(current);
528 atomic64_add(ret, &ed->bytes_written);
530 atomic64_add(ret, &ed_system.bytes_written);
537 static struct kretprobe sys_write_krp = {
538 .entry_handler = entry_handler_sys_write,
539 .handler = ret_handler_sys_write,
540 .data_size = sizeof(struct sys_read_data)
547 /* ============================================================================
549 * ============================================================================
551 static bool check_wlan0(struct socket *sock)
553 /* FIXME: hardcode interface */
554 const char *name_intrf = "wlan0";
556 if (sock->sk->sk_dst_cache &&
557 sock->sk->sk_dst_cache->dev &&
558 !strcmp(sock->sk->sk_dst_cache->dev->name, name_intrf))
564 static bool check_socket(struct task_struct *task, struct socket *socket)
568 struct files_struct *files;
570 files = swap_get_files_struct(task);
575 for (fd = 0; fd < files_fdtable(files)->max_fds; ++fd) {
576 if (fcheck_files(files, fd) == socket->file) {
584 swap_put_files_struct(files);
588 static struct energy_data *get_energy_data_by_socket(struct task_struct *task,
589 struct socket *socket)
591 struct energy_data *ed;
593 ed = get_energy_data(task);
595 ed = check_socket(task, socket) ? ed : NULL;
600 static int wf_sock_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
602 struct socket *socket = (struct socket *)swap_get_karg(regs, 0);
604 *(struct socket **)ri->data = check_wlan0(socket) ? socket : NULL;
609 static int wf_sock_aio_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
611 struct kiocb *iocb = (struct kiocb *)swap_get_karg(regs, 0);
612 struct socket *socket = iocb->ki_filp->private_data;
614 *(struct socket **)ri->data = check_wlan0(socket) ? socket : NULL;
619 static int wf_sock_recv_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
621 int ret = regs_return_value(regs);
624 struct socket *socket = *(struct socket **)ri->data;
627 struct energy_data *ed;
629 ed = get_energy_data_by_socket(current, socket);
631 atomic64_add(ret, &ed->bytes_recv);
632 atomic64_add(ret, &ed_system.bytes_recv);
639 static int wf_sock_send_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
641 int ret = regs_return_value(regs);
644 struct socket *socket = *(struct socket **)ri->data;
647 struct energy_data *ed;
649 ed = get_energy_data_by_socket(current, socket);
651 atomic64_add(ret, &ed->bytes_send);
652 atomic64_add(ret, &ed_system.bytes_send);
659 static struct kretprobe sock_recv_krp = {
660 .entry_handler = wf_sock_eh,
661 .handler = wf_sock_recv_rh,
662 .data_size = sizeof(struct socket *)
665 static struct kretprobe sock_send_krp = {
666 .entry_handler = wf_sock_eh,
667 .handler = wf_sock_send_rh,
668 .data_size = sizeof(struct socket *)
671 static struct kretprobe sock_aio_read_krp = {
672 .entry_handler = wf_sock_aio_eh,
673 .handler = wf_sock_recv_rh,
674 .data_size = sizeof(struct socket *)
677 static struct kretprobe sock_aio_write_krp = {
678 .entry_handler = wf_sock_aio_eh,
679 .handler = wf_sock_send_rh,
680 .data_size = sizeof(struct socket *)
683 static struct kern_probe wifi_probes[] = {
685 .name = "sock_recvmsg",
686 .rp = &sock_recv_krp,
689 .name = "sock_sendmsg",
690 .rp = &sock_send_krp,
693 .name = "sock_aio_read",
694 .rp = &sock_aio_read_krp,
697 .name = "sock_aio_write",
698 .rp = &sock_aio_write_krp,
702 enum { wifi_probes_cnt = ARRAY_SIZE(wifi_probes) };
703 static int wifi_flag = 0;
709 /* ============================================================================
711 * ============================================================================
714 struct swap_bt_data {
715 struct socket *socket;
718 static int bt_entry_handler(struct kretprobe_instance *ri,
719 struct pt_regs *regs)
721 struct swap_bt_data *data = (struct swap_bt_data *)ri->data;
722 struct socket *sock = (struct socket *)swap_get_sarg(regs, 1);
724 data->socket = sock ? sock : NULL;
729 static int bt_recvmsg_handler(struct kretprobe_instance *ri,
730 struct pt_regs *regs)
732 int ret = regs_return_value(regs);
733 struct swap_bt_data *data = (struct swap_bt_data *)ri->data;
736 struct socket *socket = data->socket;
739 struct energy_data *ed;
741 ed = get_energy_data_by_socket(current, socket);
743 atomic64_add(ret, &ed->bytes_l2cap_recv_acldata);
745 atomic64_add(ret, &ed_system.bytes_l2cap_recv_acldata);
751 static int bt_sendmsg_handler(struct kretprobe_instance *ri,
752 struct pt_regs *regs)
754 int ret = regs_return_value(regs);
755 struct swap_bt_data *data = (struct swap_bt_data *)ri->data;
758 struct socket *socket = data->socket;
761 struct energy_data *ed;
763 ed = get_energy_data_by_socket(current, socket);
765 atomic64_add(ret, &ed->bytes_hci_send_sco);
767 atomic64_add(ret, &ed_system.bytes_hci_send_sco);
773 static struct kretprobe rfcomm_sock_recvmsg_krp = {
774 .entry_handler = bt_entry_handler,
775 .handler = bt_recvmsg_handler,
776 .data_size = sizeof(struct swap_bt_data)
779 static struct kretprobe l2cap_sock_recvmsg_krp = {
780 .entry_handler = bt_entry_handler,
781 .handler = bt_recvmsg_handler,
782 .data_size = sizeof(struct swap_bt_data)
785 static struct kretprobe hci_sock_recvmsg_krp = {
786 .entry_handler = bt_entry_handler,
787 .handler = bt_recvmsg_handler,
788 .data_size = sizeof(struct swap_bt_data)
791 static struct kretprobe sco_sock_recvmsg_krp = {
792 .entry_handler = bt_entry_handler,
793 .handler = bt_recvmsg_handler,
794 .data_size = sizeof(struct swap_bt_data)
796 static struct kretprobe rfcomm_sock_sendmsg_krp = {
797 .entry_handler = bt_entry_handler,
798 .handler = bt_sendmsg_handler,
799 .data_size = sizeof(struct swap_bt_data)
802 static struct kretprobe l2cap_sock_sendmsg_krp = {
803 .entry_handler = bt_entry_handler,
804 .handler = bt_sendmsg_handler,
805 .data_size = sizeof(struct swap_bt_data)
808 static struct kretprobe hci_sock_sendmsg_krp = {
809 .entry_handler = bt_entry_handler,
810 .handler = bt_sendmsg_handler,
811 .data_size = sizeof(struct swap_bt_data)
814 static struct kretprobe sco_sock_sendmsg_krp = {
815 .entry_handler = bt_entry_handler,
816 .handler = bt_sendmsg_handler,
817 .data_size = sizeof(struct swap_bt_data)
820 static struct kern_probe bt_probes[] = {
822 .name = "rfcomm_sock_recvmsg",
823 .rp = &rfcomm_sock_recvmsg_krp,
826 .name = "l2cap_sock_recvmsg",
827 .rp = &l2cap_sock_recvmsg_krp,
830 .name = "hci_sock_recvmsg",
831 .rp = &hci_sock_recvmsg_krp,
834 .name = "sco_sock_recvmsg",
835 .rp = &sco_sock_recvmsg_krp,
838 .name = "rfcomm_sock_sendmsg",
839 .rp = &rfcomm_sock_sendmsg_krp,
842 .name = "l2cap_sock_sendmsg",
843 .rp = &l2cap_sock_sendmsg_krp,
846 .name = "hci_sock_sendmsg",
847 .rp = &hci_sock_sendmsg_krp,
850 .name = "sco_sock_sendmsg",
851 .rp = &sco_sock_sendmsg_krp,
855 enum { bt_probes_cnt = ARRAY_SIZE(bt_probes) };
856 static int energy_bt_flag = 0;
858 enum parameter_type {
871 enum parameter_type pt;
876 static void callback_for_proc(struct sspt_proc *proc, void *data)
878 void *f_data = sspt_get_feature_data(proc->feature, feature_id);
879 struct energy_data *ed = (struct energy_data *)f_data;
883 struct cmd_pt *cmdp = (struct cmd_pt *)data;
884 u64 *val = cmdp->buf;
888 cpus_time_lock(&ed->ct, flags);
889 cpus_time_sum_running_all(&ed->ct, val, get_ntime());
890 cpus_time_unlock(&ed->ct, flags);
893 *val += atomic64_read(&ed->bytes_read);
896 *val += atomic64_read(&ed->bytes_written);
899 *val += atomic64_read(&ed->bytes_recv);
902 *val += atomic64_read(&ed->bytes_send);
905 *val += atomic64_read(&ed->bytes_l2cap_recv_acldata);
908 *val += atomic64_read(&ed->bytes_sco_recv_scodata);
911 *val += atomic64_read(&ed->bytes_hci_send_acl);
914 *val += atomic64_read(&ed->bytes_hci_send_sco);
922 static int current_parameter_apps(enum parameter_type pt, void *buf, int sz)
930 on_each_proc(callback_for_proc, (void *)&cmdp);
936 * @brief Get energy parameter
938 * @param pe Type of energy parameter
940 * @param sz Buffer size
943 int get_parameter_energy(enum parameter_energy pe, void *buf, size_t sz)
946 u64 *val = buf; /* currently all parameters are u64 vals */
951 cpus_time_lock(&ct_idle, flags);
952 /* for the moment we consider only CPU[0] idle time */
953 *val = cpu_time_get_running(&ct_idle, 0, get_ntime());
954 cpus_time_unlock(&ct_idle, flags);
957 cpus_time_lock(&ed_system.ct, flags);
958 cpus_time_get_running_all(&ed_system.ct, val, get_ntime());
959 cpus_time_unlock(&ed_system.ct, flags);
962 current_parameter_apps(PT_CPU, buf, sz);
965 *val = atomic64_read(&ed_system.bytes_read);
967 case PE_WRITE_SYSTEM:
968 *val = atomic64_read(&ed_system.bytes_written);
970 case PE_WF_RECV_SYSTEM:
971 *val = atomic64_read(&ed_system.bytes_recv);
973 case PE_WF_SEND_SYSTEM:
974 *val = atomic64_read(&ed_system.bytes_send);
976 case PE_L2CAP_RECV_SYSTEM:
977 *val = atomic64_read(&ed_system.bytes_l2cap_recv_acldata);
979 case PE_SCO_RECV_SYSTEM:
980 *val = atomic64_read(&ed_system.bytes_sco_recv_scodata);
982 case PT_SEND_ACL_SYSTEM:
983 *val = atomic64_read(&ed_system.bytes_hci_send_acl);
985 case PT_SEND_SCO_SYSTEM:
986 *val = atomic64_read(&ed_system.bytes_hci_send_sco);
989 current_parameter_apps(PT_READ, buf, sz);
992 current_parameter_apps(PT_WRITE, buf, sz);
994 case PE_WF_RECV_APPS:
995 current_parameter_apps(PT_WF_RECV, buf, sz);
997 case PE_WF_SEND_APPS:
998 current_parameter_apps(PT_WF_SEND, buf, sz);
1000 case PE_L2CAP_RECV_APPS:
1001 current_parameter_apps(PT_L2CAP_RECV, buf, sz);
1003 case PE_SCO_RECV_APPS:
1004 current_parameter_apps(PT_SCO_RECV, buf, sz);
1006 case PT_SEND_ACL_APPS:
1007 current_parameter_apps(PT_SEND_ACL, buf, sz);
1009 case PT_SEND_SCO_APPS:
1010 current_parameter_apps(PT_SEND_SCO, buf, sz);
1020 int do_set_energy(void)
1026 ret = swap_register_kretprobe(&sys_read_krp);
1028 printk(KERN_INFO "swap_register_kretprobe(sys_read) "
1029 "result=%d!\n", ret);
1033 ret = swap_register_kretprobe(&sys_write_krp);
1035 printk(KERN_INFO "swap_register_kretprobe(sys_write) "
1036 "result=%d!\n", ret);
1037 goto unregister_sys_read;
1040 ret = swap_register_kretprobe(&switch_to_krp);
1042 printk(KERN_INFO "swap_register_kretprobe(__switch_to) "
1045 goto unregister_sys_write;
1048 energy_xxx_set(bt_probes, bt_probes_cnt, &energy_bt_flag);
1049 energy_xxx_set(wifi_probes, wifi_probes_cnt, &wifi_flag);
1051 /* TODO: check return value */
1056 unregister_sys_read:
1057 swap_unregister_kretprobe(&sys_read_krp);
1059 unregister_sys_write:
1060 swap_unregister_kretprobe(&sys_write_krp);
1065 void do_unset_energy(void)
1068 energy_xxx_unset(wifi_probes, wifi_probes_cnt, &wifi_flag);
1069 energy_xxx_unset(bt_probes, bt_probes_cnt, &energy_bt_flag);
1071 swap_unregister_kretprobe(&switch_to_krp);
1072 swap_unregister_kretprobe(&sys_write_krp);
1073 swap_unregister_kretprobe(&sys_read_krp);
1075 uninit_data_energy();
1078 static DEFINE_MUTEX(mutex_enable);
1079 static int energy_enable;
1082 * @brief Start measuring the energy consumption
1084 * @return Error code
1086 int set_energy(void)
1090 mutex_lock(&mutex_enable);
1091 if (energy_enable) {
1092 printk(KERN_INFO "energy profiling is already run!\n");
1096 ret = do_set_energy();
1101 mutex_unlock(&mutex_enable);
1105 EXPORT_SYMBOL_GPL(set_energy);
1108 * @brief Stop measuring the energy consumption
1110 * @return Error code
1112 int unset_energy(void)
1116 mutex_lock(&mutex_enable);
1117 if (energy_enable == 0) {
1118 printk(KERN_INFO "energy profiling is not running!\n");
1127 mutex_unlock(&mutex_enable);
1131 EXPORT_SYMBOL_GPL(unset_energy);
1133 int energy_once(void)
1137 sym = "__switch_to";
1138 switch_to_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
1139 if (switch_to_krp.kp.addr == NULL)
1143 sys_read_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
1144 if (sys_read_krp.kp.addr == NULL)
1148 sys_write_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
1149 if (sys_write_krp.kp.addr == NULL)
1152 energy_xxx_once(bt_probes, bt_probes_cnt);
1153 energy_xxx_once(wifi_probes, wifi_probes_cnt);
1158 printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
1163 * @brief Initialization energy
1165 * @return Error code
1167 int energy_init(void)
1171 ret = init_feature();
1173 printk(KERN_INFO "Cannot init feature\n");
1179 * @brief Deinitialization energy
1183 void energy_uninit(void)