bootprof.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * Copyright (C) 2015 MediaTek Inc.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <linux/proc_fs.h>
  14. #include <linux/sched.h>
  15. #include <linux/kallsyms.h>
  16. #include <linux/utsname.h>
  17. #include <linux/module.h>
  18. #include <linux/moduleparam.h>
  19. #include <asm/uaccess.h>
  20. #include <linux/printk.h>
  21. #include "internal.h"
  22. /* #include <mt_hotplug_strategy.h> */
  23. #ifdef CONFIG_MT_SCHED_MON_DEFAULT_ENABLE
  24. #include "mt_sched_mon.h"
  25. #endif
  26. #include <mt_cpufreq.h>
  27. #define BOOT_STR_SIZE 256 /* Before: 128 */
  28. #define BOOT_LOG_NUM 192
  29. /* Memory Usage
  30. * Before: (128+8)*64 = 8704.
  31. * Now: (64+8)*128 = 9216 */
  32. struct boot_log_struct {
  33. u64 timestamp;
  34. char *event;
  35. #ifdef TRACK_TASK_COMM
  36. pid_t pid;
  37. char comm[TASK_COMM_LEN];
  38. #endif
  39. } mt_bootprof[BOOT_LOG_NUM];
  40. static int boot_log_count;
  41. static DEFINE_MUTEX(mt_bootprof_lock);
  42. static bool mt_bootprof_enabled;
  43. static int bootprof_lk_t, bootprof_pl_t;
  44. static u64 timestamp_on, timestamp_off;
  45. int boot_finish = 0;
  46. module_param_named(pl_t, bootprof_pl_t, int, S_IRUGO | S_IWUSR);
  47. module_param_named(lk_t, bootprof_lk_t, int, S_IRUGO | S_IWUSR);
  48. void log_boot(char *str)
  49. {
  50. unsigned long long ts;
  51. struct boot_log_struct *p = &mt_bootprof[boot_log_count];
  52. size_t n = strlen(str);
  53. if (!mt_bootprof_enabled)
  54. return;
  55. ts = sched_clock();
  56. pr_err("BOOTPROF:%10Ld.%06ld:%s\n", nsec_high(ts), nsec_low(ts), str);
  57. if (boot_log_count >= BOOT_LOG_NUM) {
  58. pr_err("[BOOTPROF] not enuough bootprof buffer\n");
  59. return;
  60. }
  61. mutex_lock(&mt_bootprof_lock);
  62. p->timestamp = ts;
  63. #ifdef TRACK_TASK_COMM
  64. p->pid = current->pid;
  65. memcpy(p->comm, current->comm, TASK_COMM_LEN);
  66. #endif
  67. p->event = kzalloc(n, GFP_ATOMIC | __GFP_NORETRY |
  68. __GFP_NOWARN);
  69. if (!p->event) {
  70. /* pr_err("log_boot alloc size %zu fail\n", n); */
  71. mt_bootprof_enabled = false;
  72. goto out;
  73. }
  74. memcpy(p->event, str, n);
  75. boot_log_count++;
  76. out:
  77. mutex_unlock(&mt_bootprof_lock);
  78. }
  79. static void bootup_finish(void)
  80. {
  81. initcall_debug = 0;
  82. #ifdef CONFIG_MT_PRINTK_UART_CONSOLE
  83. mt_disable_uart();
  84. #endif
  85. #ifdef CONFIG_MT_SCHED_MON_DEFAULT_ENABLE
  86. mt_sched_monitor_switch(1);
  87. #endif
  88. set_logtoomuch_enable(1);
  89. /* mt_cpufreq_set_min_freq(MT_CPU_DVFS_LITTLE, 0); */
  90. /* hps_set_cpu_num_base(BASE_PERF_SERV, 1, 0); */
  91. }
  92. /* extern void (*set_intact_mode)(void); */
  93. static void mt_bootprof_switch(int on)
  94. {
  95. mutex_lock(&mt_bootprof_lock);
  96. if (mt_bootprof_enabled ^ on) {
  97. unsigned long long ts = sched_clock();
  98. pr_err("BOOTPROF:%10Ld.%06ld: %s\n",
  99. nsec_high(ts), nsec_low(ts), on ? "ON" : "OFF");
  100. if (on) {
  101. mt_bootprof_enabled = 1;
  102. timestamp_on = ts;
  103. } else { /* boot up complete */
  104. mt_bootprof_enabled = 0;
  105. timestamp_off = ts;
  106. boot_finish = 1;
  107. /* log_store_bootup(); */
  108. bootup_finish();
  109. }
  110. }
  111. mutex_unlock(&mt_bootprof_lock);
  112. }
  113. static ssize_t
  114. mt_bootprof_write(struct file *filp, const char *ubuf, size_t cnt, loff_t *data)
  115. {
  116. char buf[BOOT_STR_SIZE];
  117. size_t copy_size = cnt;
  118. if (cnt >= sizeof(buf))
  119. copy_size = BOOT_STR_SIZE - 1;
  120. if (copy_from_user(&buf, ubuf, copy_size))
  121. return -EFAULT;
  122. if (cnt == 1) {
  123. if (buf[0] == '0')
  124. mt_bootprof_switch(0);
  125. else if (buf[0] == '1')
  126. mt_bootprof_switch(1);
  127. return 1;
  128. }
  129. buf[copy_size] = 0;
  130. log_boot(buf);
  131. return cnt;
  132. }
  133. static int mt_bootprof_show(struct seq_file *m, void *v)
  134. {
  135. int i;
  136. SEQ_printf(m, "----------------------------------------\n");
  137. SEQ_printf(m, "%d BOOT PROF (unit:msec)\n", mt_bootprof_enabled);
  138. SEQ_printf(m, "----------------------------------------\n");
  139. if (bootprof_pl_t > 0 && bootprof_lk_t > 0) {
  140. SEQ_printf(m, "%10d : %s\n", bootprof_pl_t, "preloader");
  141. SEQ_printf(m, "%10d : %s\n", bootprof_lk_t, "lk");
  142. SEQ_printf(m, "%10d : %s\n",
  143. gpt_boot_time() - bootprof_pl_t - bootprof_lk_t, "lk->Kernel");
  144. SEQ_printf(m, "----------------------------------------\n");
  145. }
  146. SEQ_printf(m, "%10Ld.%06ld : ON\n",
  147. nsec_high(timestamp_on), nsec_low(timestamp_on));
  148. for (i = 0; i < boot_log_count; i++) {
  149. if (!mt_bootprof[i].event)
  150. continue;
  151. SEQ_printf(m, "%10Ld.%06ld : %s\n",
  152. nsec_high(mt_bootprof[i].timestamp),
  153. nsec_low(mt_bootprof[i].timestamp),
  154. #ifdef TRACK_TASK_COMM
  155. mt_bootprof[i].pid, mt_bootprof[i].comm,
  156. #endif
  157. mt_bootprof[i].event);
  158. }
  159. SEQ_printf(m, "%10Ld.%06ld : OFF\n",
  160. nsec_high(timestamp_off), nsec_low(timestamp_off));
  161. SEQ_printf(m, "----------------------------------------\n");
  162. return 0;
  163. }
  164. /*** Seq operation of mtprof ****/
  165. static int mt_bootprof_open(struct inode *inode, struct file *file)
  166. {
  167. return single_open(file, mt_bootprof_show, inode->i_private);
  168. }
  169. static const struct file_operations mt_bootprof_fops = {
  170. .open = mt_bootprof_open,
  171. .write = mt_bootprof_write,
  172. .read = seq_read,
  173. .llseek = seq_lseek,
  174. .release = single_release,
  175. };
  176. static int __init init_boot_prof(void)
  177. {
  178. struct proc_dir_entry *pe;
  179. pe = proc_create("bootprof", 0664, NULL, &mt_bootprof_fops);
  180. if (!pe)
  181. return -ENOMEM;
  182. /* set_intact_mode = NULL; */
  183. return 0;
  184. }
  185. static int __init init_bootprof_buf(void)
  186. {
  187. mt_bootprof_switch(1);
  188. return 0;
  189. }
  190. early_initcall(init_bootprof_buf);
  191. device_initcall(init_boot_prof);