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("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("XXX %s[%d/%d]: nnitializing tmstamp(%p) on cpu(%d)\n",
186 current->comm, current->tgid, current->pid, tm, cpu);
187 tm_stat_set_timestamp(tm, start_time);
190 tm_stat_update(tm, now);
191 tm_stat_set_timestamp(tm, 0); /* set timestamp to 0 */
199 /* for __switch_to */
203 atomic64_t bytes_read;
206 atomic64_t bytes_written;
209 atomic64_t bytes_recv;
212 atomic64_t bytes_send;
215 atomic64_t bytes_l2cap_recv_acldata;
217 /* for sco_recv_scodata */
218 atomic64_t bytes_sco_recv_scodata;
220 /* for hci_send_acl */
221 atomic64_t bytes_hci_send_acl;
223 /* for hci_send_sco */
224 atomic64_t bytes_hci_send_sco;
227 static sspt_feature_id_t feature_id = SSPT_FEATURE_ID_BAD;
229 static void init_ed(struct energy_data *ed)
231 /* instead of get_ntime(), CPU time is initialized to 0 here. Timestamp
232 * value will be properly set when the corresponding __switch_to event
234 cpus_time_init(&ed->ct, 0);
235 atomic64_set(&ed->bytes_read, 0);
236 atomic64_set(&ed->bytes_written, 0);
237 atomic64_set(&ed->bytes_recv, 0);
238 atomic64_set(&ed->bytes_send, 0);
239 atomic64_set(&ed->bytes_l2cap_recv_acldata, 0);
240 atomic64_set(&ed->bytes_sco_recv_scodata, 0);
241 atomic64_set(&ed->bytes_hci_send_acl, 0);
242 atomic64_set(&ed->bytes_hci_send_sco, 0);
245 static void uninit_ed(struct energy_data *ed)
247 cpus_time_init(&ed->ct, 0);
248 atomic64_set(&ed->bytes_read, 0);
249 atomic64_set(&ed->bytes_written, 0);
250 atomic64_set(&ed->bytes_recv, 0);
251 atomic64_set(&ed->bytes_send, 0);
252 atomic64_set(&ed->bytes_l2cap_recv_acldata, 0);
253 atomic64_set(&ed->bytes_sco_recv_scodata, 0);
254 atomic64_set(&ed->bytes_hci_send_acl, 0);
255 atomic64_set(&ed->bytes_hci_send_sco, 0);
258 static void *create_ed(void)
260 struct energy_data *ed;
262 ed = kmalloc(sizeof(*ed), GFP_ATOMIC);
269 static void destroy_ed(void *data)
271 struct energy_data *ed = (struct energy_data *)data;
276 static int init_feature(void)
278 feature_id = sspt_register_feature(create_ed, destroy_ed);
280 if (feature_id == SSPT_FEATURE_ID_BAD)
286 static void uninit_feature(void)
288 sspt_unregister_feature(feature_id);
289 feature_id = SSPT_FEATURE_ID_BAD;
292 static struct energy_data *get_energy_data(struct task_struct *task)
295 struct sspt_proc *proc;
297 proc = sspt_proc_get_by_task(task);
299 data = sspt_get_feature_data(proc->feature, feature_id);
301 return (struct energy_data *)data;
304 static int check_fs(unsigned long magic)
307 case EXT2_SUPER_MAGIC: /* == EXT3_SUPER_MAGIC == EXT4_SUPER_MAGIC */
308 case MSDOS_SUPER_MAGIC:
315 static int check_ftype(int fd)
320 err = vfs_fstat(fd, &kstat);
321 if (err == 0 && S_ISREG(kstat.mode))
327 static int check_file(int fd)
334 if (file->f_dentry && file->f_dentry->d_sb)
335 magic = file->f_dentry->d_sb->s_magic;
339 if (check_fs(magic) && check_ftype(fd))
346 static unsigned long get_arg0(struct pt_regs *regs)
348 #if defined(CONFIG_ARM)
350 #elif defined(CONFIG_X86_32)
353 #error "this architecture is not supported"
354 #endif /* CONFIG_arch */
361 static struct cpus_time ct_idle;
362 static struct energy_data ed_system;
363 static u64 start_time;
365 static void init_data_energy(void)
367 start_time = get_ntime();
369 cpus_time_init(&ct_idle, 0);
372 static void uninit_data_energy(void)
375 uninit_ed(&ed_system);
376 cpus_time_init(&ct_idle, 0);
383 /* ============================================================================
385 * ============================================================================
387 static int entry_handler_switch(struct kretprobe_instance *ri, struct pt_regs *regs)
390 struct cpus_time *ct;
391 struct energy_data *ed;
394 cpu = smp_processor_id();
396 ct = current->tgid ? &ed_system.ct: &ct_idle;
397 cpus_time_lock(ct, flags);
398 cpus_time_update_running(ct, cpu, get_ntime(), start_time);
399 cpus_time_unlock(ct, flags);
401 ed = get_energy_data(current);
404 cpus_time_lock(ct, flags);
405 cpus_time_update_running(ct, cpu, get_ntime(), start_time);
406 cpus_time_unlock(ct, flags);
412 static int ret_handler_switch(struct kretprobe_instance *ri, struct pt_regs *regs)
415 struct cpus_time *ct;
416 struct energy_data *ed;
419 cpu = smp_processor_id();
421 ct = current->tgid ? &ed_system.ct: &ct_idle;
422 cpus_time_lock(ct, flags);
423 cpus_time_save_entry(ct, cpu, get_ntime());
424 cpus_time_unlock(ct, flags);
426 ed = get_energy_data(current);
429 cpus_time_lock(ct, flags);
430 cpus_time_save_entry(ct, cpu, get_ntime());
431 cpus_time_unlock(ct, flags);
437 static struct kretprobe switch_to_krp = {
438 .entry_handler = entry_handler_switch,
439 .handler = ret_handler_switch,
446 /* ============================================================================
448 * ============================================================================
450 struct sys_read_data {
454 static int entry_handler_sys_read(struct kretprobe_instance *ri, struct pt_regs *regs)
456 struct sys_read_data *srd = (struct sys_read_data *)ri->data;
458 srd->fd = (int)get_arg0(regs);
463 static int ret_handler_sys_read(struct kretprobe_instance *ri,
464 struct pt_regs *regs)
466 int ret = regs_return_value(regs);
469 struct sys_read_data *srd;
471 srd = (struct sys_read_data *)ri->data;
472 if (check_file(srd->fd)) {
473 struct energy_data *ed;
475 ed = get_energy_data(current);
477 atomic64_add(ret, &ed->bytes_read);
479 atomic64_add(ret, &ed_system.bytes_read);
486 static struct kretprobe sys_read_krp = {
487 .entry_handler = entry_handler_sys_read,
488 .handler = ret_handler_sys_read,
489 .data_size = sizeof(struct sys_read_data)
496 /* ============================================================================
498 * ============================================================================
500 static int entry_handler_sys_write(struct kretprobe_instance *ri, struct pt_regs *regs)
502 struct sys_read_data *srd = (struct sys_read_data *)ri->data;
504 srd->fd = (int)get_arg0(regs);
509 static int ret_handler_sys_write(struct kretprobe_instance *ri, struct pt_regs *regs)
511 int ret = regs_return_value(regs);
514 struct sys_read_data *srd;
516 srd = (struct sys_read_data *)ri->data;
517 if (check_file(srd->fd)) {
518 struct energy_data *ed;
520 ed = get_energy_data(current);
522 atomic64_add(ret, &ed->bytes_written);
524 atomic64_add(ret, &ed_system.bytes_written);
531 static struct kretprobe sys_write_krp = {
532 .entry_handler = entry_handler_sys_write,
533 .handler = ret_handler_sys_write,
534 .data_size = sizeof(struct sys_read_data)
541 /* ============================================================================
543 * ============================================================================
545 static bool check_wlan0(struct socket *sock)
547 /* FIXME: hardcode interface */
548 const char *name_intrf = "wlan0";
550 if (sock->sk->sk_dst_cache &&
551 sock->sk->sk_dst_cache->dev &&
552 !strcmp(sock->sk->sk_dst_cache->dev->name, name_intrf))
558 static bool check_socket(struct task_struct *task, struct socket *socket)
562 struct files_struct *files;
564 files = swap_get_files_struct(task);
569 for (fd = 0; fd < files_fdtable(files)->max_fds; ++fd) {
570 if (fcheck_files(files, fd) == socket->file) {
578 swap_put_files_struct(files);
582 static struct energy_data *get_energy_data_by_socket(struct task_struct *task,
583 struct socket *socket)
585 struct energy_data *ed;
587 ed = get_energy_data(task);
589 ed = check_socket(task, socket) ? ed : NULL;
594 static int wf_sock_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
596 struct socket *socket = (struct socket *)swap_get_karg(regs, 0);
598 *(struct socket **)ri->data = check_wlan0(socket) ? socket : NULL;
603 static int wf_sock_aio_eh(struct kretprobe_instance *ri, struct pt_regs *regs)
605 struct kiocb *iocb = (struct kiocb *)swap_get_karg(regs, 0);
606 struct socket *socket = iocb->ki_filp->private_data;
608 *(struct socket **)ri->data = check_wlan0(socket) ? socket : NULL;
613 static int wf_sock_recv_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
615 int ret = regs_return_value(regs);
618 struct socket *socket = *(struct socket **)ri->data;
621 struct energy_data *ed;
623 ed = get_energy_data_by_socket(current, socket);
625 atomic64_add(ret, &ed->bytes_recv);
626 atomic64_add(ret, &ed_system.bytes_recv);
633 static int wf_sock_send_rh(struct kretprobe_instance *ri, struct pt_regs *regs)
635 int ret = regs_return_value(regs);
638 struct socket *socket = *(struct socket **)ri->data;
641 struct energy_data *ed;
643 ed = get_energy_data_by_socket(current, socket);
645 atomic64_add(ret, &ed->bytes_send);
646 atomic64_add(ret, &ed_system.bytes_send);
653 static struct kretprobe sock_recv_krp = {
654 .entry_handler = wf_sock_eh,
655 .handler = wf_sock_recv_rh,
656 .data_size = sizeof(struct socket *)
659 static struct kretprobe sock_send_krp = {
660 .entry_handler = wf_sock_eh,
661 .handler = wf_sock_send_rh,
662 .data_size = sizeof(struct socket *)
665 static struct kretprobe sock_aio_read_krp = {
666 .entry_handler = wf_sock_aio_eh,
667 .handler = wf_sock_recv_rh,
668 .data_size = sizeof(struct socket *)
671 static struct kretprobe sock_aio_write_krp = {
672 .entry_handler = wf_sock_aio_eh,
673 .handler = wf_sock_send_rh,
674 .data_size = sizeof(struct socket *)
677 static struct kern_probe wifi_probes[] = {
679 .name = "sock_recvmsg",
680 .rp = &sock_recv_krp,
683 .name = "sock_sendmsg",
684 .rp = &sock_send_krp,
687 .name = "sock_aio_read",
688 .rp = &sock_aio_read_krp,
691 .name = "sock_aio_write",
692 .rp = &sock_aio_write_krp,
696 enum { wifi_probes_cnt = ARRAY_SIZE(wifi_probes) };
697 static int wifi_flag = 0;
703 /* ============================================================================
705 * ============================================================================
707 #define RET_HANDLER_BT_NAME(name) ret_handler_bt_##name
708 #define DEFINE_RET_HANDLER_BT(name) \
709 int RET_HANDLER_BT_NAME(name)(struct kretprobe_instance *ri, \
710 struct pt_regs *regs) \
712 unsigned int len = *(unsigned int *)ri->data; \
714 struct energy_data *ed = get_energy_data(current); \
716 atomic64_add(len, &ed->bytes_##name); \
717 atomic64_add(len, &ed_system.bytes_##name); \
722 static DEFINE_RET_HANDLER_BT(l2cap_recv_acldata)
723 static DEFINE_RET_HANDLER_BT(sco_recv_scodata)
724 static DEFINE_RET_HANDLER_BT(hci_send_acl)
725 static DEFINE_RET_HANDLER_BT(hci_send_sco)
727 static int entry_handler_generic_bt(struct kretprobe_instance *ri,
728 struct pt_regs *regs)
730 struct sk_buff *skb = (struct sk_buff *)swap_get_sarg(regs, 1);
731 unsigned int *len = (unsigned int *)ri->data;
733 *len = skb ? skb->len : 0;
738 static struct kretprobe l2cap_recv_acldata_krp = {
739 .entry_handler = entry_handler_generic_bt,
740 .handler = RET_HANDLER_BT_NAME(l2cap_recv_acldata),
741 .data_size = sizeof(unsigned int)
744 static struct kretprobe sco_recv_scodata_krp = {
745 .entry_handler = entry_handler_generic_bt,
746 .handler = RET_HANDLER_BT_NAME(sco_recv_scodata),
747 .data_size = sizeof(unsigned int)
750 static struct kretprobe hci_send_acl_krp = {
751 .entry_handler = entry_handler_generic_bt,
752 .handler = RET_HANDLER_BT_NAME(hci_send_acl),
753 .data_size = sizeof(unsigned int)
756 static struct kretprobe hci_send_sco_krp = {
757 .entry_handler = entry_handler_generic_bt,
758 .handler = RET_HANDLER_BT_NAME(hci_send_sco),
759 .data_size = sizeof(unsigned int)
763 static int energy_bt_once(void)
767 sym = "l2cap_recv_acldata";
768 l2cap_recv_acldata_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
769 if (l2cap_recv_acldata_krp.kp.addr == NULL)
772 sym = "sco_recv_scodata";
773 sco_recv_scodata_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
774 if (sco_recv_scodata_krp.kp.addr == NULL)
777 sym = "hci_send_acl";
778 hci_send_acl_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
779 if (hci_send_acl_krp.kp.addr == NULL)
782 sym = "hci_send_sco";
783 hci_send_sco_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
784 if (hci_send_sco_krp.kp.addr == NULL)
790 printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
794 static int energy_bt_flag = 0;
796 static int energy_bt_set(void)
800 ret = swap_register_kretprobe(&l2cap_recv_acldata_krp);
802 pr_err("register fail 'l2cap_recv_acldata_krp' ret=%d\n", ret);
806 ret = swap_register_kretprobe(&sco_recv_scodata_krp);
808 printk("register fail 'sco_recv_scodata_krp' ret=%d\n" ,ret);
809 goto unreg_l2cap_recv_acldata;
812 ret = swap_register_kretprobe(&hci_send_acl_krp);
814 printk("register fail 'hci_send_acl_krp' ret=%d\n", ret);
815 goto unreg_sco_recv_scodata;
818 ret = swap_register_kretprobe(&hci_send_sco_krp);
820 printk("register fail 'hci_send_sco_krp' ret=%d\n", ret);
821 goto unreg_hci_send_acl;
829 swap_unregister_kretprobe(&hci_send_acl_krp);
831 unreg_sco_recv_scodata:
832 swap_unregister_kretprobe(&sco_recv_scodata_krp);
834 unreg_l2cap_recv_acldata:
835 swap_unregister_kretprobe(&l2cap_recv_acldata_krp);
840 static void energy_bt_unset(void)
842 if (energy_bt_flag == 0)
845 swap_unregister_kretprobe(&hci_send_sco_krp);
846 swap_unregister_kretprobe(&hci_send_acl_krp);
847 swap_unregister_kretprobe(&sco_recv_scodata_krp);
848 swap_unregister_kretprobe(&l2cap_recv_acldata_krp);
857 enum parameter_type {
870 enum parameter_type pt;
875 static void callback_for_proc(struct sspt_proc *proc, void *data)
877 void *f_data = sspt_get_feature_data(proc->feature, feature_id);
878 struct energy_data *ed = (struct energy_data *)f_data;
882 struct cmd_pt *cmdp = (struct cmd_pt *)data;
883 u64 *val = cmdp->buf;
887 cpus_time_lock(&ed->ct, flags);
888 cpus_time_sum_running_all(&ed->ct, val, get_ntime());
889 cpus_time_unlock(&ed->ct, flags);
892 *val += atomic64_read(&ed->bytes_read);
895 *val += atomic64_read(&ed->bytes_written);
898 *val += atomic64_read(&ed->bytes_recv);
901 *val += atomic64_read(&ed->bytes_send);
904 *val += atomic64_read(&ed->bytes_l2cap_recv_acldata);
907 *val += atomic64_read(&ed->bytes_sco_recv_scodata);
910 *val += atomic64_read(&ed->bytes_hci_send_acl);
913 *val += atomic64_read(&ed->bytes_hci_send_sco);
921 static int current_parameter_apps(enum parameter_type pt, void *buf, int sz)
929 on_each_proc(callback_for_proc, (void *)&cmdp);
935 * @brief Get energy parameter
937 * @param pe Type of energy parameter
939 * @param sz Buffer size
942 int get_parameter_energy(enum parameter_energy pe, void *buf, size_t sz)
945 u64 *val = buf; /* currently all parameters are u64 vals */
950 cpus_time_lock(&ct_idle, flags);
951 /* for the moment we consider only CPU[0] idle time */
952 *val = cpu_time_get_running(&ct_idle, 0, get_ntime());
953 cpus_time_unlock(&ct_idle, flags);
956 cpus_time_lock(&ed_system.ct, flags);
957 cpus_time_get_running_all(&ed_system.ct, val, get_ntime());
958 cpus_time_unlock(&ed_system.ct, flags);
961 current_parameter_apps(PT_CPU, buf, sz);
964 *val = atomic64_read(&ed_system.bytes_read);
966 case PE_WRITE_SYSTEM:
967 *val = atomic64_read(&ed_system.bytes_written);
969 case PE_WF_RECV_SYSTEM:
970 *val = atomic64_read(&ed_system.bytes_recv);
972 case PE_WF_SEND_SYSTEM:
973 *val = atomic64_read(&ed_system.bytes_send);
975 case PE_L2CAP_RECV_SYSTEM:
976 *val = atomic64_read(&ed_system.bytes_l2cap_recv_acldata);
978 case PE_SCO_RECV_SYSTEM:
979 *val = atomic64_read(&ed_system.bytes_sco_recv_scodata);
981 case PT_SEND_ACL_SYSTEM:
982 *val = atomic64_read(&ed_system.bytes_hci_send_acl);
984 case PT_SEND_SCO_SYSTEM:
985 *val = atomic64_read(&ed_system.bytes_hci_send_sco);
988 current_parameter_apps(PT_READ, buf, sz);
991 current_parameter_apps(PT_WRITE, buf, sz);
993 case PE_WF_RECV_APPS:
994 current_parameter_apps(PT_WF_RECV, buf, sz);
996 case PE_WF_SEND_APPS:
997 current_parameter_apps(PT_WF_SEND, buf, sz);
999 case PE_L2CAP_RECV_APPS:
1000 current_parameter_apps(PT_L2CAP_RECV, buf, sz);
1002 case PE_SCO_RECV_APPS:
1003 current_parameter_apps(PT_SCO_RECV, buf, sz);
1005 case PT_SEND_ACL_APPS:
1006 current_parameter_apps(PT_SEND_ACL, buf, sz);
1008 case PT_SEND_SCO_APPS:
1009 current_parameter_apps(PT_SEND_SCO, buf, sz);
1019 int do_set_energy(void)
1025 ret = swap_register_kretprobe(&sys_read_krp);
1027 printk("swap_register_kretprobe(sys_read) result=%d!\n", ret);
1031 ret = swap_register_kretprobe(&sys_write_krp);
1033 printk("swap_register_kretprobe(sys_write) result=%d!\n", ret);
1034 goto unregister_sys_read;
1037 ret = swap_register_kretprobe(&switch_to_krp);
1039 printk("swap_register_kretprobe(__switch_to) result=%d!\n",
1041 goto unregister_sys_write;
1045 energy_xxx_set(wifi_probes, wifi_probes_cnt, &wifi_flag);
1047 /* TODO: check return value */
1052 unregister_sys_read:
1053 swap_unregister_kretprobe(&sys_read_krp);
1055 unregister_sys_write:
1056 swap_unregister_kretprobe(&sys_write_krp);
1061 void do_unset_energy(void)
1064 energy_xxx_unset(wifi_probes, wifi_probes_cnt, &wifi_flag);
1067 swap_unregister_kretprobe(&switch_to_krp);
1068 swap_unregister_kretprobe(&sys_write_krp);
1069 swap_unregister_kretprobe(&sys_read_krp);
1071 uninit_data_energy();
1074 static DEFINE_MUTEX(mutex_enable);
1075 static int energy_enable = 0;
1078 * @brief Start measuring the energy consumption
1080 * @return Error code
1082 int set_energy(void)
1086 mutex_lock(&mutex_enable);
1087 if (energy_enable) {
1088 printk("energy profiling is already run!\n");
1092 ret = do_set_energy();
1097 mutex_unlock(&mutex_enable);
1101 EXPORT_SYMBOL_GPL(set_energy);
1104 * @brief Stop measuring the energy consumption
1106 * @return Error code
1108 int unset_energy(void)
1112 mutex_lock(&mutex_enable);
1113 if (energy_enable == 0) {
1114 printk("energy profiling is not running!\n");
1123 mutex_unlock(&mutex_enable);
1127 EXPORT_SYMBOL_GPL(unset_energy);
1129 int energy_once(void)
1133 sym = "__switch_to";
1134 switch_to_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
1135 if (switch_to_krp.kp.addr == NULL)
1139 sys_read_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
1140 if (sys_read_krp.kp.addr == NULL)
1144 sys_write_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
1145 if (sys_write_krp.kp.addr == NULL)
1149 energy_xxx_once(wifi_probes, wifi_probes_cnt);
1154 printk("ERROR: symbol '%s' not found\n", sym);
1159 * @brief Initialization energy
1161 * @return Error code
1163 int energy_init(void)
1167 ret = init_feature();
1169 printk(KERN_INFO "Cannot init feature\n");
1175 * @brief Deinitialization energy
1179 void energy_uninit(void)