[IMPROVE] added wifi consumption
[kernel/swap-modules.git] / energy / energy.c
1 /*
2  *  Dynamic Binary Instrumentation Module based on KProbes
3  *  modules/energy/swap_energy.c
4  *
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.
9  *
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.
14  *
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.
18  *
19  * Copyright (C) Samsung Electronics, 2013
20  *
21  * 2013         Vasiliy Ulyanov <v.ulyanov@samsung.com>
22  *              Vyacheslav Cherkashin <v.cherkashin@samsung.com>
23  *
24  */
25
26
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 <net/sock.h>
38 #include <kprobe/swap_kprobes.h>
39 #include <ksyms/ksyms.h>
40 #include <us_manager/sspt/sspt_proc.h>
41 #include <us_manager/sspt/sspt_feature.h>
42 #include <linux/atomic.h>
43 #include "energy.h"
44 #include "lcd/lcd_base.h"
45 #include "tm_stat.h"
46
47
48 /* ============================================================================
49  * =                              CPUS_TIME                                   =
50  * ============================================================================
51  */
52 struct cpus_time {
53         spinlock_t lock; /* for concurrent access */
54         struct tm_stat tm[NR_CPUS];
55 };
56
57 #define cpus_time_lock(ct, flags) spin_lock_irqsave(&(ct)->lock, flags)
58 #define cpus_time_unlock(ct, flags) spin_unlock_irqrestore(&(ct)->lock, flags)
59
60 static void cpus_time_init(struct cpus_time *ct, u64 time)
61 {
62         int cpu;
63
64         spin_lock_init(&ct->lock);
65
66         for (cpu = 0; cpu < NR_CPUS; ++cpu) {
67                 tm_stat_init(&ct->tm[cpu]);
68                 tm_stat_set_timestamp(&ct->tm[cpu], time);
69         }
70 }
71
72 static inline u64 cpu_time_get_running(struct cpus_time *ct, int cpu, u64 now)
73 {
74         return tm_stat_current_running(&ct->tm[cpu], now);
75 }
76
77 static void *cpus_time_get_running_all(struct cpus_time *ct, u64 *buf, u64 now)
78 {
79         int cpu;
80
81         for (cpu = 0; cpu < NR_CPUS; ++cpu)
82                 buf[cpu] = tm_stat_current_running(&ct->tm[cpu], now);
83
84         return buf;
85 }
86
87 static void *cpus_time_sum_running_all(struct cpus_time *ct, u64 *buf, u64 now)
88 {
89         int cpu;
90
91         for (cpu = 0; cpu < NR_CPUS; ++cpu)
92                 buf[cpu] += tm_stat_current_running(&ct->tm[cpu], now);
93
94         return buf;
95 }
96
97 static void cpus_time_save_entry(struct cpus_time *ct, int cpu, u64 time)
98 {
99         struct tm_stat *tm = &ct->tm[cpu];
100
101         if (unlikely(tm_stat_timestamp(tm))) /* should never happen */
102                 printk(KERN_INFO "XXX %s[%d/%d]: WARNING tmstamp(%p) set on cpu(%d)\n",
103                        current->comm, current->tgid, current->pid, tm, cpu);
104         tm_stat_set_timestamp(&ct->tm[cpu], time);
105 }
106
107 static void cpus_time_update_running(struct cpus_time *ct, int cpu, u64 now,
108                                      u64 start_time)
109 {
110         struct tm_stat *tm = &ct->tm[cpu];
111
112         if (unlikely(tm_stat_timestamp(tm) == 0)) {
113                 /* not initialized. should happen only once per cpu/task */
114                 printk(KERN_INFO "XXX %s[%d/%d]: nnitializing tmstamp(%p) "
115                        "on cpu(%d)\n",
116                        current->comm, current->tgid, current->pid, tm, cpu);
117                 tm_stat_set_timestamp(tm, start_time);
118         }
119
120         tm_stat_update(tm, now);
121         tm_stat_set_timestamp(tm, 0); /* set timestamp to 0 */
122 }
123
124
125
126
127
128 struct energy_data {
129         /* for __switch_to */
130         struct cpus_time ct;
131
132         /* for sys_read */
133         atomic64_t bytes_read;
134
135         /*for sys_write */
136         atomic64_t bytes_written;
137
138         /*for recvmsg*/
139         atomic64_t bytes_recv;
140
141         /* for sock_send */
142         atomic64_t bytes_send;
143 };
144
145 static sspt_feature_id_t feature_id = SSPT_FEATURE_ID_BAD;
146
147 static void init_ed(struct energy_data *ed)
148 {
149         /* instead of get_ntime(), CPU time is initialized to 0 here. Timestamp
150          * value will be properly set when the corresponding __switch_to event
151          * occurs */
152         cpus_time_init(&ed->ct, 0);
153         atomic64_set(&ed->bytes_read, 0);
154         atomic64_set(&ed->bytes_written, 0);
155         atomic64_set(&ed->bytes_recv, 0);
156         atomic64_set(&ed->bytes_send, 0);
157 }
158
159 static void uninit_ed(struct energy_data *ed)
160 {
161         cpus_time_init(&ed->ct, 0);
162         atomic64_set(&ed->bytes_read, 0);
163         atomic64_set(&ed->bytes_written, 0);
164         atomic64_set(&ed->bytes_recv, 0);
165         atomic64_set(&ed->bytes_send, 0);
166 }
167
168 static void *create_ed(void)
169 {
170         struct energy_data *ed;
171
172         ed = kmalloc(sizeof(*ed), GFP_ATOMIC);
173         if (ed)
174                 init_ed(ed);
175
176         return (void *)ed;
177 }
178
179 static void destroy_ed(void *data)
180 {
181         struct energy_data *ed = (struct energy_data *)data;
182         kfree(ed);
183 }
184
185
186 static int init_feature(void)
187 {
188         feature_id = sspt_register_feature(create_ed, destroy_ed);
189
190         if (feature_id == SSPT_FEATURE_ID_BAD)
191                 return -EPERM;
192
193         return 0;
194 }
195
196 static void uninit_feature(void)
197 {
198         sspt_unregister_feature(feature_id);
199         feature_id = SSPT_FEATURE_ID_BAD;
200 }
201
202 static struct energy_data *get_energy_data(struct task_struct *task)
203 {
204         void *data = NULL;
205         struct sspt_proc *proc;
206
207         proc = sspt_proc_get_by_task(task);
208         if (proc)
209                 data = sspt_get_feature_data(proc->feature, feature_id);
210
211         return (struct energy_data *)data;
212 }
213
214 static int check_fs(unsigned long magic)
215 {
216         switch (magic) {
217         case EXT2_SUPER_MAGIC: /* == EXT3_SUPER_MAGIC == EXT4_SUPER_MAGIC */
218         case MSDOS_SUPER_MAGIC:
219                 return 1;
220         }
221
222         return 0;
223 }
224
225 static int check_ftype(int fd)
226 {
227         int err, ret = 0;
228         struct kstat kstat;
229
230         err = vfs_fstat(fd, &kstat);
231         if (err == 0 && S_ISREG(kstat.mode))
232                 ret = 1;
233
234         return ret;
235 }
236
237 static int check_file(int fd)
238 {
239         struct file *file;
240
241         file = fget(fd);
242         if (file) {
243                 int magic = 0;
244                 if (file->f_dentry && file->f_dentry->d_sb)
245                         magic = file->f_dentry->d_sb->s_magic;
246
247                 fput(file);
248
249                 if (check_fs(magic) && check_ftype(fd))
250                         return 1;
251         }
252
253         return 0;
254 }
255
256 static unsigned long get_arg0(struct pt_regs *regs)
257 {
258 #if defined(CONFIG_ARM)
259         return regs->ARM_r0;
260 #elif defined(CONFIG_X86_32)
261         return regs->bx;
262 #else
263         #error "this architecture is not supported"
264 #endif /* CONFIG_arch */
265 }
266
267
268
269
270
271 static struct cpus_time ct_idle;
272 static struct energy_data ed_system;
273 static u64 start_time;
274
275 static void init_data_energy(void)
276 {
277         start_time = get_ntime();
278         init_ed(&ed_system);
279         cpus_time_init(&ct_idle, 0);
280 }
281
282 static void uninit_data_energy(void)
283 {
284         start_time = 0;
285         uninit_ed(&ed_system);
286         cpus_time_init(&ct_idle, 0);
287 }
288
289
290
291
292
293 /* ============================================================================
294  * =                             __switch_to                                  =
295  * ============================================================================
296  */
297 static int entry_handler_switch(struct kretprobe_instance *ri,
298                                 struct pt_regs *regs)
299 {
300         int cpu;
301         struct cpus_time *ct;
302         struct energy_data *ed;
303         unsigned long flags;
304
305         cpu = smp_processor_id();
306
307         ct = current->tgid ? &ed_system.ct : &ct_idle;
308         cpus_time_lock(ct, flags);
309         cpus_time_update_running(ct, cpu, get_ntime(), start_time);
310         cpus_time_unlock(ct, flags);
311
312         ed = get_energy_data(current);
313         if (ed) {
314                 ct = &ed->ct;
315                 cpus_time_lock(ct, flags);
316                 cpus_time_update_running(ct, cpu, get_ntime(), start_time);
317                 cpus_time_unlock(ct, flags);
318         }
319
320         return 0;
321 }
322
323 static int ret_handler_switch(struct kretprobe_instance *ri,
324                               struct pt_regs *regs)
325 {
326         int cpu;
327         struct cpus_time *ct;
328         struct energy_data *ed;
329         unsigned long flags;
330
331         cpu = smp_processor_id();
332
333         ct = current->tgid ? &ed_system.ct : &ct_idle;
334         cpus_time_lock(ct, flags);
335         cpus_time_save_entry(ct, cpu, get_ntime());
336         cpus_time_unlock(ct, flags);
337
338         ed = get_energy_data(current);
339         if (ed) {
340                 ct = &ed->ct;
341                 cpus_time_lock(ct, flags);
342                 cpus_time_save_entry(ct, cpu, get_ntime());
343                 cpus_time_unlock(ct, flags);
344         }
345
346         return 0;
347 }
348
349 static struct kretprobe switch_to_krp = {
350         .entry_handler = entry_handler_switch,
351         .handler = ret_handler_switch,
352 };
353
354
355
356
357
358 /* ============================================================================
359  * =                                sys_read                                  =
360  * ============================================================================
361  */
362 struct sys_read_data {
363         int fd;
364 };
365
366 static int entry_handler_sys_read(struct kretprobe_instance *ri,
367                                   struct pt_regs *regs)
368 {
369         struct sys_read_data *srd = (struct sys_read_data *)ri->data;
370
371         srd->fd = (int)get_arg0(regs);
372
373         return 0;
374 }
375
376 static int ret_handler_sys_read(struct kretprobe_instance *ri,
377                                 struct pt_regs *regs)
378 {
379         int ret = regs_return_value(regs);
380
381         if (ret > 0) {
382                 struct sys_read_data *srd;
383
384                 srd = (struct sys_read_data *)ri->data;
385                 if (check_file(srd->fd)) {
386                         struct energy_data *ed;
387
388                         ed = get_energy_data(current);
389                         if (ed)
390                                 atomic64_add(ret, &ed->bytes_read);
391
392                         atomic64_add(ret, &ed_system.bytes_read);
393                 }
394         }
395
396         return 0;
397 }
398
399 static struct kretprobe sys_read_krp = {
400         .entry_handler = entry_handler_sys_read,
401         .handler = ret_handler_sys_read,
402         .data_size = sizeof(struct sys_read_data)
403 };
404
405
406
407
408
409 /* ============================================================================
410  * =                               sys_write                                  =
411  * ============================================================================
412  */
413 static int entry_handler_sys_write(struct kretprobe_instance *ri,
414                                    struct pt_regs *regs)
415 {
416         struct sys_read_data *srd = (struct sys_read_data *)ri->data;
417
418         srd->fd = (int)get_arg0(regs);
419
420         return 0;
421 }
422
423 static int ret_handler_sys_write(struct kretprobe_instance *ri,
424                                  struct pt_regs *regs)
425 {
426         int ret = regs_return_value(regs);
427
428         if (ret > 0) {
429                 struct sys_read_data *srd;
430
431                 srd = (struct sys_read_data *)ri->data;
432                 if (check_file(srd->fd)) {
433                         struct energy_data *ed;
434
435                         ed = get_energy_data(current);
436                         if (ed)
437                                 atomic64_add(ret, &ed->bytes_written);
438
439                         atomic64_add(ret, &ed_system.bytes_written);
440                 }
441         }
442
443         return 0;
444 }
445
446 static struct kretprobe sys_write_krp = {
447         .entry_handler = entry_handler_sys_write,
448         .handler = ret_handler_sys_write,
449         .data_size = sizeof(struct sys_read_data)
450 };
451
452
453
454
455
456 /* ============================================================================
457  * =                                wifi                                      =
458  * ============================================================================
459  */
460 static bool check_wlan0(struct socket *sock)
461 {
462         /* FIXME: hardcode interface */
463         const char *name_intrf = "wlan0";
464
465         if (sock->sk->sk_dst_cache &&
466             sock->sk->sk_dst_cache->dev &&
467             !strcmp(sock->sk->sk_dst_cache->dev->name, name_intrf))
468                 return true;
469
470         return false;
471 }
472
473 static int entry_handler_wf_sock(struct kretprobe_instance *ri,
474                                  struct pt_regs *regs)
475 {
476         bool *ok = (bool *)ri->data;
477         struct socket *socket = (struct socket *)swap_get_karg(regs, 0);
478
479         *ok = check_wlan0(socket);
480
481         return 0;
482 }
483
484 static int ret_handler_wf_sock_recv(struct kretprobe_instance *ri,
485                                     struct pt_regs *regs)
486 {
487         int ret = regs_return_value(regs);
488
489         if (ret > 0) {
490                 bool ok = *(bool *)ri->data;
491
492                 if (ok) {
493                         struct energy_data *ed;
494
495                         ed = get_energy_data(current);
496                         if (ed)
497                                 atomic64_add(ret, &ed->bytes_recv);
498                         atomic64_add(ret, &ed_system.bytes_recv);
499                 }
500         }
501
502         return 0;
503 }
504
505 static int ret_handler_wf_sock_send(struct kretprobe_instance *ri,
506                                     struct pt_regs *regs)
507 {
508         int ret = regs_return_value(regs);
509
510         if (ret > 0) {
511                 bool ok = *(bool *)ri->data;
512
513                 if (ok) {
514                         struct energy_data *ed;
515
516                         ed = get_energy_data(current);
517                         if (ed)
518                                 atomic64_add(ret, &ed->bytes_send);
519                         atomic64_add(ret, &ed_system.bytes_send);
520                 }
521         }
522
523         return 0;
524 }
525
526 static struct kretprobe sock_recv_krp = {
527         .entry_handler = entry_handler_wf_sock,
528         .handler = ret_handler_wf_sock_recv,
529         .data_size = sizeof(bool)
530 };
531
532 static struct kretprobe sock_send_krp = {
533         .entry_handler = entry_handler_wf_sock,
534         .handler = ret_handler_wf_sock_send,
535         .data_size = sizeof(bool)
536 };
537
538 static int energy_wifi_once(void)
539 {
540         const char *sym;
541
542         sym = "sock_recvmsg";
543         sock_recv_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
544         if (sock_recv_krp.kp.addr == NULL)
545                 goto not_found;
546
547         sym = "sock_sendmsg";
548         sock_send_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
549         if (sock_send_krp.kp.addr == NULL)
550                 goto  not_found;
551
552         return 0;
553
554 not_found:
555         printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
556         return -ESRCH;
557 }
558
559 static int energy_wifi_flag = 0;
560
561 static int energy_wifi_set(void)
562 {
563         int ret;
564
565         ret = swap_register_kretprobe(&sock_recv_krp);
566         if (ret) {
567                 pr_err("swap_register_kretprobe(sock_recv_krp) ret=%d\n" ,ret);
568                 return ret;
569         }
570
571         ret = swap_register_kretprobe(&sock_send_krp);
572         if (ret) {
573                 pr_err("swap_register_kretprobe(sock_send_krp) ret=%d\n" ,ret);
574                 swap_unregister_kretprobe(&sock_recv_krp);
575         }
576
577         energy_wifi_flag = 1;
578
579         return ret;
580 }
581
582 static void energy_wifi_unset(void)
583 {
584         if (energy_wifi_flag == 0)
585                 return;
586
587         swap_unregister_kretprobe(&sock_send_krp);
588         swap_unregister_kretprobe(&sock_recv_krp);
589
590         energy_wifi_flag = 0;
591 }
592
593
594
595
596
597 enum parameter_type {
598         PT_CPU,
599         PT_READ,
600         PT_WRITE,
601         PT_WF_RECV,
602         PT_WF_SEND
603 };
604
605 struct cmd_pt {
606         enum parameter_type pt;
607         void *buf;
608         int sz;
609 };
610
611 static void callback_for_proc(struct sspt_proc *proc, void *data)
612 {
613         void *f_data = sspt_get_feature_data(proc->feature, feature_id);
614         struct energy_data *ed = (struct energy_data *)f_data;
615
616         if (ed) {
617                 unsigned long flags;
618                 struct cmd_pt *cmdp = (struct cmd_pt *)data;
619                 u64 *val = cmdp->buf;
620
621                 switch (cmdp->pt) {
622                 case PT_CPU:
623                         cpus_time_lock(&ed->ct, flags);
624                         cpus_time_sum_running_all(&ed->ct, val, get_ntime());
625                         cpus_time_unlock(&ed->ct, flags);
626                         break;
627                 case PT_READ:
628                         *val += atomic64_read(&ed->bytes_read);
629                         break;
630                 case PT_WRITE:
631                         *val += atomic64_read(&ed->bytes_written);
632                         break;
633                 case PT_WF_RECV:
634                         *val += atomic64_read(&ed->bytes_recv);
635                         break;
636                 case PT_WF_SEND:
637                         *val += atomic64_read(&ed->bytes_send);
638                         break;
639                 default:
640                         break;
641                 }
642         }
643 }
644
645 static int current_parameter_apps(enum parameter_type pt, void *buf, int sz)
646 {
647         struct cmd_pt cmdp;
648
649         cmdp.pt = pt;
650         cmdp.buf = buf;
651         cmdp.sz = sz;
652
653         on_each_proc(callback_for_proc, (void *)&cmdp);
654
655         return 0;
656 }
657
658 /**
659  * @brief Get energy parameter
660  *
661  * @param pe Type of energy parameter
662  * @param buf Buffer
663  * @param sz Buffer size
664  * @return Error code
665  */
666 int get_parameter_energy(enum parameter_energy pe, void *buf, size_t sz)
667 {
668         unsigned long flags;
669         u64 *val = buf; /* currently all parameters are u64 vals */
670         int ret = 0;
671
672         switch (pe) {
673         case PE_TIME_IDLE:
674                 cpus_time_lock(&ct_idle, flags);
675                 /* for the moment we consider only CPU[0] idle time */
676                 *val = cpu_time_get_running(&ct_idle, 0, get_ntime());
677                 cpus_time_unlock(&ct_idle, flags);
678                 break;
679         case PE_TIME_SYSTEM:
680                 cpus_time_lock(&ed_system.ct, flags);
681                 cpus_time_get_running_all(&ed_system.ct, val, get_ntime());
682                 cpus_time_unlock(&ed_system.ct, flags);
683                 break;
684         case PE_TIME_APPS:
685                 current_parameter_apps(PT_CPU, buf, sz);
686                 break;
687         case PE_READ_SYSTEM:
688                 *val = atomic64_read(&ed_system.bytes_read);
689                 break;
690         case PE_WRITE_SYSTEM:
691                 *val = atomic64_read(&ed_system.bytes_written);
692                 break;
693         case PE_WF_RECV_SYSTEM:
694                 *val = atomic64_read(&ed_system.bytes_recv);
695                 break;
696         case PE_WF_SEND_SYSTEM:
697                 *val = atomic64_read(&ed_system.bytes_send);
698                 break;
699         case PE_READ_APPS:
700                 current_parameter_apps(PT_READ, buf, sz);
701                 break;
702         case PE_WRITE_APPS:
703                 current_parameter_apps(PT_WRITE, buf, sz);
704                 break;
705         case PE_WF_RECV_APPS:
706                 current_parameter_apps(PT_WF_RECV, buf, sz);
707                 break;
708         case PE_WF_SEND_APPS:
709                 current_parameter_apps(PT_WF_SEND, buf, sz);
710                 break;
711         default:
712                 ret = -EINVAL;
713                 break;
714         }
715
716         return ret;
717 }
718
719 int do_set_energy(void)
720 {
721         int ret = 0;
722
723         init_data_energy();
724
725         ret = swap_register_kretprobe(&sys_read_krp);
726         if (ret) {
727                 printk(KERN_INFO "swap_register_kretprobe(sys_read) "
728                        "result=%d!\n", ret);
729                 return ret;
730         }
731
732         ret = swap_register_kretprobe(&sys_write_krp);
733         if (ret != 0) {
734                 printk(KERN_INFO "swap_register_kretprobe(sys_write) "
735                        "result=%d!\n", ret);
736                 goto unregister_sys_read;
737         }
738
739         ret = swap_register_kretprobe(&switch_to_krp);
740         if (ret) {
741                 printk(KERN_INFO "swap_register_kretprobe(__switch_to) "
742                        "result=%d!\n",
743                        ret);
744                 goto unregister_sys_write;
745         }
746
747         energy_wifi_set();
748
749         /* TODO: check return value */
750         lcd_set_energy();
751
752         return ret;
753
754 unregister_sys_read:
755         swap_unregister_kretprobe(&sys_read_krp);
756
757 unregister_sys_write:
758         swap_unregister_kretprobe(&sys_write_krp);
759
760         return ret;
761 }
762
763 void do_unset_energy(void)
764 {
765         lcd_unset_energy();
766         energy_wifi_unset();
767
768         swap_unregister_kretprobe(&switch_to_krp);
769         swap_unregister_kretprobe(&sys_write_krp);
770         swap_unregister_kretprobe(&sys_read_krp);
771
772         uninit_data_energy();
773 }
774
775 static DEFINE_MUTEX(mutex_enable);
776 static int energy_enable;
777
778 /**
779  * @brief Start measuring the energy consumption
780  *
781  * @return Error code
782  */
783 int set_energy(void)
784 {
785         int ret = -EINVAL;
786
787         mutex_lock(&mutex_enable);
788         if (energy_enable) {
789                 printk(KERN_INFO "energy profiling is already run!\n");
790                 goto unlock;
791         }
792
793         ret = do_set_energy();
794         if (ret == 0)
795                 energy_enable = 1;
796
797 unlock:
798         mutex_unlock(&mutex_enable);
799
800         return ret;
801 }
802 EXPORT_SYMBOL_GPL(set_energy);
803
804 /**
805  * @brief Stop measuring the energy consumption
806  *
807  * @return Error code
808  */
809 int unset_energy(void)
810 {
811         int ret = 0;
812
813         mutex_lock(&mutex_enable);
814         if (energy_enable == 0) {
815                 printk(KERN_INFO "energy profiling is not running!\n");
816                 ret = -EINVAL;
817                 goto unlock;
818         }
819
820         do_unset_energy();
821
822         energy_enable = 0;
823 unlock:
824         mutex_unlock(&mutex_enable);
825
826         return ret;
827 }
828 EXPORT_SYMBOL_GPL(unset_energy);
829
830 int energy_once(void)
831 {
832         const char *sym;
833
834         sym = "__switch_to";
835         switch_to_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
836         if (switch_to_krp.kp.addr == NULL)
837                 goto not_found;
838
839         sym = "sys_read";
840         sys_read_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
841         if (sys_read_krp.kp.addr == NULL)
842                 goto not_found;
843
844         sym = "sys_write";
845         sys_write_krp.kp.addr = (kprobe_opcode_t *)swap_ksyms(sym);
846         if (sys_write_krp.kp.addr == NULL)
847                 goto not_found;
848
849         energy_wifi_once();
850
851         return 0;
852
853 not_found:
854         printk(KERN_INFO "ERROR: symbol '%s' not found\n", sym);
855         return -ESRCH;
856 }
857
858 /**
859  * @brief Initialization energy
860  *
861  * @return Error code
862  */
863 int energy_init(void)
864 {
865         int ret;
866
867         ret = init_feature();
868         if (ret)
869                 printk(KERN_INFO "Cannot init feature\n");
870
871         return ret;
872 }
873
874 /**
875  * @brief Deinitialization energy
876  *
877  * @return Void
878  */
879 void energy_uninit(void)
880 {
881         uninit_feature();
882
883         if (energy_enable)
884                 do_unset_energy();
885 }