mlog_logger.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. #include <linux/types.h>
  2. #include <linux/module.h>
  3. #include <linux/mm.h>
  4. #include <linux/oom.h>
  5. #include <linux/sched.h>
  6. #include <linux/vmstat.h>
  7. #include <linux/sysinfo.h>
  8. #include <linux/swap.h>
  9. #include <linux/cpu.h>
  10. #include <linux/slab.h>
  11. #include <linux/fs.h>
  12. #include <linux/cpumask.h>
  13. #include <linux/cred.h>
  14. #include <linux/rcupdate.h>
  15. #include <linux/seq_file.h>
  16. #include <asm/uaccess.h>
  17. #include <linux/version.h>
  18. #ifdef CONFIG_MTK_GPU_SUPPORT
  19. #define COLLECT_GPU_MEMINFO
  20. #endif
  21. #ifdef COLLECT_GPU_MEMINFO
  22. #include <mt-plat/mtk_gpu_utility.h>
  23. #endif
  24. #ifdef CONFIG_ZRAM
  25. #include <zram_drv.h>
  26. #endif
  27. /* for collecting ion total memory usage*/
  28. #ifdef CONFIG_MTK_ION
  29. #include <mtk/ion_drv.h>
  30. #endif
  31. #include "mlog_internal.h"
  32. #include "mlog_logger.h"
  33. #define CONFIG_MLOG_BUF_SHIFT 16 /* 64KB */
  34. #define P2K(x) (((unsigned long)x) << (PAGE_SHIFT - 10))
  35. #define B2K(x) (((unsigned long)x) >> (10))
  36. #define MLOG_STR_LEN 16
  37. #define MLOG_BUF_LEN ((1 << CONFIG_MLOG_BUF_SHIFT) >> 2)
  38. #define MLOG_BUF_MASK (mlog_buf_len-1)
  39. #define MLOG_BUF(idx) (mlog_buffer[(idx) & MLOG_BUF_MASK])
  40. #define MLOG_ID ULONG_MAX
  41. #define AID_ROOT 0 /* traditional unix root user */
  42. #define AID_SYSTEM 1000 /* system server */
  43. #define M_MEMFREE (1 << 0)
  44. #define M_SWAPFREE (1 << 1)
  45. #define M_CACHED (1 << 2)
  46. #define M_GPUUSE (1 << 3)
  47. #define M_MLOCK (1 << 4)
  48. #define M_ZRAM (1 << 5)
  49. #define M_ACTIVE (1 << 6)
  50. #define M_INACTIVE (1 << 7)
  51. #define M_SHMEM (1 << 8)
  52. #define M_GPU_PAGE_CACHE (1 << 9)
  53. #define M_ION (1 << 10)
  54. #define V_PSWPIN (1 << 0)
  55. #define V_PSWPOUT (1 << 1)
  56. #define V_PGFMFAULT (1 << 2)
  57. #define V_PGANFAULT (1 << 3)
  58. #define P_ADJ (1 << 0)
  59. #define P_RSS (1 << 1)
  60. #define P_RSWAP (1 << 2)
  61. #define P_SWPIN (1 << 3)
  62. #define P_SWPOUT (1 << 4)
  63. #define P_FMFAULT (1 << 5)
  64. #define P_MINFAULT (1 << 6)
  65. #define P_MAJFAULT (1 << 7)
  66. #define B_NORMAL (1 << 0)
  67. #define B_HIGH (1 << 1)
  68. #define P_FMT_SIZE (P_RSS | P_RSWAP)
  69. #define P_FMT_COUNT (P_SWPIN | P_SWPOUT | P_FMFAULT | P_MINFAULT | P_MAJFAULT)
  70. #define M_FILTER_ALL (M_MEMFREE | M_SWAPFREE | M_CACHED | M_GPUUSE \
  71. | M_GPU_PAGE_CACHE | M_MLOCK | M_ZRAM \
  72. | M_ACTIVE | M_INACTIVE | M_SHMEM | M_ION)
  73. #define V_FILTER_ALL (V_PSWPIN | V_PSWPOUT | V_PGFMFAULT | V_PGANFAULT)
  74. #define P_FILTER_ALL (P_ADJ | P_RSS | P_RSWAP | P_SWPIN | P_SWPOUT | P_FMFAULT)
  75. #define B_FILTER_ALL (B_NORMAL | B_HIGH)
  76. #define MLOG_TRIGGER_TIMER 0
  77. #define MLOG_TRIGGER_LMK 1
  78. #define MLOG_TRIGGER_LTK 2
  79. static uint meminfo_filter = M_FILTER_ALL;
  80. static uint vmstat_filter = V_FILTER_ALL;
  81. static uint proc_filter = P_FILTER_ALL;
  82. static uint buddyinfo_filter = B_FILTER_ALL;
  83. static DEFINE_SPINLOCK(mlogbuf_lock);
  84. DECLARE_WAIT_QUEUE_HEAD(mlog_wait);
  85. static long mlog_buffer[MLOG_BUF_LEN];
  86. static int mlog_buf_len = MLOG_BUF_LEN;
  87. static unsigned mlog_start;
  88. static unsigned mlog_end;
  89. static int min_adj = -16;
  90. static int max_adj = 16;
  91. static int limit_pid = -1;
  92. static struct timer_list mlog_timer;
  93. static unsigned long timer_intval = HZ;
  94. static const char **strfmt_list;
  95. static int strfmt_idx;
  96. static int strfmt_len;
  97. static int strfmt_proc;
  98. static const char cr_str[] = "%c";
  99. static const char type_str[] = "<%ld>";
  100. static const char time_sec_str[] = "[%5lu";
  101. static const char time_nanosec_str[] = ".%06lu]";
  102. static const char mem_size_str[] = " %6lu";
  103. static const char acc_count_str[] = " %7lu";
  104. static const char pid_str[] = " [%lu]";
  105. static const char adj_str[] = " %3ld";
  106. /*
  107. buddyinfo
  108. Node 0, zone Normal 486 297 143 59 30 16 7 0 2 1 54
  109. Node 0, zone HighMem 74 18 7 65 161 67 23 10 0 1 21
  110. */
  111. /* 0 1 2 3 4 5 6 7 8 9 10 */
  112. static const char order_start_str[] = " [%6lu";
  113. static const char order_middle_str[] = " %6lu";
  114. static const char order_end_str[] = " %6lu]";
  115. /*
  116. active & inactive
  117. Active: 211748 kB
  118. Inactive: 257988 kB
  119. */
  120. static void mlog_emit_32(long v)
  121. {
  122. MLOG_BUF(mlog_end) = v;
  123. mlog_end++;
  124. if (mlog_end - mlog_start > mlog_buf_len)
  125. mlog_start = mlog_end - mlog_buf_len;
  126. }
  127. /*
  128. static void mlog_emit_32_ex(long v)
  129. {
  130. spin_lock_bh(&mlogbuf_lock);
  131. mlog_emit_32(v);
  132. spin_unlock_bh(&mlogbuf_lock);
  133. }
  134. static void mlog_emit_64(long long v)
  135. {
  136. mlog_emit_32(v >> BITS_PER_LONG);
  137. mlog_emit_32(v & ULONG_MAX);
  138. }
  139. */
  140. static void mlog_reset_format(void)
  141. {
  142. int len;
  143. spin_lock_bh(&mlogbuf_lock);
  144. if (meminfo_filter)
  145. meminfo_filter = M_FILTER_ALL;
  146. if (vmstat_filter)
  147. vmstat_filter = V_FILTER_ALL;
  148. if (buddyinfo_filter)
  149. buddyinfo_filter = B_FILTER_ALL;
  150. if (proc_filter)
  151. proc_filter = P_FILTER_ALL;
  152. /* calc len */
  153. len = 4; /* id, type, sec, nanosec */
  154. len += hweight32(meminfo_filter);
  155. len += hweight32(vmstat_filter);
  156. /* buddyinfo */
  157. len += (2 * MAX_ORDER);
  158. if (proc_filter) {
  159. len++; /* PID */
  160. len += hweight32(proc_filter);
  161. }
  162. if (!strfmt_list || strfmt_len != len) {
  163. kfree(strfmt_list);
  164. strfmt_list = kmalloc_array(len, sizeof(char *), GFP_ATOMIC);
  165. strfmt_len = len;
  166. BUG_ON(!strfmt_list);
  167. }
  168. /* setup str format */
  169. len = 0;
  170. strfmt_proc = 0;
  171. strfmt_list[len++] = cr_str;
  172. strfmt_list[len++] = type_str;
  173. strfmt_list[len++] = time_sec_str;
  174. strfmt_list[len++] = time_nanosec_str;
  175. if (meminfo_filter) {
  176. int i;
  177. for (i = 0; i < hweight32(meminfo_filter); ++i)
  178. strfmt_list[len++] = mem_size_str;
  179. }
  180. if (vmstat_filter) {
  181. int i;
  182. for (i = 0; i < hweight32(vmstat_filter); ++i)
  183. strfmt_list[len++] = acc_count_str;
  184. }
  185. if (buddyinfo_filter) {
  186. int i, j;
  187. /* normal and high zone */
  188. for (i = 0; i < 2; ++i) {
  189. strfmt_list[len++] = order_start_str;
  190. for (j = 0; j < MAX_ORDER - 2; ++j)
  191. strfmt_list[len++] = order_middle_str;
  192. strfmt_list[len++] = order_end_str;
  193. }
  194. }
  195. if (proc_filter) {
  196. int i;
  197. strfmt_proc = len;
  198. strfmt_list[len++] = pid_str; /* PID */
  199. strfmt_list[len++] = adj_str; /* ADJ */
  200. for (i = 0; i < hweight32(proc_filter & (P_FMT_SIZE)); ++i)
  201. strfmt_list[len++] = mem_size_str;
  202. for (i = 0; i < hweight32(proc_filter & (P_FMT_COUNT)); ++i)
  203. strfmt_list[len++] = acc_count_str;
  204. }
  205. strfmt_idx = 0;
  206. BUG_ON(len != strfmt_len);
  207. spin_unlock_bh(&mlogbuf_lock);
  208. MLOG_PRINTK("[mlog] reset format %d", strfmt_len);
  209. for (len = 0; len < strfmt_len; ++len)
  210. MLOG_PRINTK(" %s", strfmt_list[len]);
  211. MLOG_PRINTK("\n");
  212. }
  213. int mlog_print_fmt(struct seq_file *m)
  214. {
  215. seq_puts(m, "<type> [time]");
  216. if (meminfo_filter & M_MEMFREE)
  217. seq_puts(m, " memfr");
  218. if (meminfo_filter & M_SWAPFREE)
  219. seq_puts(m, " swpfr");
  220. if (meminfo_filter & M_CACHED)
  221. seq_puts(m, " cache");
  222. if (meminfo_filter & M_GPUUSE)
  223. seq_puts(m, " gpu");
  224. if (meminfo_filter & M_GPU_PAGE_CACHE)
  225. seq_puts(m, " gpu_page_cache");
  226. if (meminfo_filter & M_MLOCK)
  227. seq_puts(m, " mlock");
  228. if (meminfo_filter & M_ZRAM)
  229. seq_puts(m, " zram");
  230. if (meminfo_filter & M_ACTIVE)
  231. seq_puts(m, " active");
  232. if (meminfo_filter & M_INACTIVE)
  233. seq_puts(m, " inactive");
  234. if (meminfo_filter & M_SHMEM)
  235. seq_puts(m, " shmem");
  236. if (meminfo_filter & M_ION)
  237. seq_puts(m, " ion");
  238. if (vmstat_filter & V_PSWPIN)
  239. seq_puts(m, " swpin");
  240. if (vmstat_filter & V_PSWPOUT)
  241. seq_puts(m, " swpout");
  242. if (vmstat_filter & V_PGFMFAULT)
  243. seq_puts(m, " fmflt");
  244. if (vmstat_filter & V_PGANFAULT)
  245. seq_puts(m, " anflt");
  246. if (buddyinfo_filter) {
  247. seq_puts(m, " [normal]");
  248. seq_puts(m, " [high]");
  249. }
  250. if (proc_filter) {
  251. seq_puts(m, " [pid]");
  252. if (proc_filter & P_ADJ)
  253. seq_puts(m, " adj");
  254. if (proc_filter & P_RSS)
  255. seq_puts(m, " rss");
  256. if (proc_filter & P_RSWAP)
  257. seq_puts(m, " rswp");
  258. if (proc_filter & P_SWPIN)
  259. seq_puts(m, " pswpin");
  260. if (proc_filter & P_SWPOUT)
  261. seq_puts(m, " pswpout");
  262. if (proc_filter & P_FMFAULT)
  263. seq_puts(m, " pfmflt");
  264. }
  265. seq_puts(m, "\n");
  266. return 0;
  267. }
  268. static void mlog_reset_buffer(void)
  269. {
  270. spin_lock_bh(&mlogbuf_lock);
  271. mlog_end = mlog_start = 0;
  272. spin_unlock_bh(&mlogbuf_lock);
  273. MLOG_PRINTK("[mlog] reset buffer\n");
  274. }
  275. #ifndef CONFIG_MTKPASR
  276. #define mtkpasr_show_page_reserved(void) (0)
  277. #endif
  278. static void mlog_meminfo(void)
  279. {
  280. unsigned long memfree;
  281. unsigned long swapfree;
  282. unsigned long cached;
  283. unsigned int gpuuse = 0;
  284. unsigned int gpu_page_cache = 0;
  285. unsigned long mlock;
  286. unsigned long zram;
  287. unsigned long active, inactive;
  288. unsigned long shmem;
  289. unsigned long ion = 0;
  290. memfree = P2K(global_page_state(NR_FREE_PAGES) + mtkpasr_show_page_reserved());
  291. swapfree = P2K(atomic_long_read(&nr_swap_pages));
  292. cached = P2K(global_page_state(NR_FILE_PAGES) - total_swapcache_pages());
  293. /*
  294. use following code if kernel version is under 3.10.
  295. swapfree = P2K(nr_swap_pages);
  296. cached = P2K(global_page_state(NR_FILE_PAGES) - total_swapcache_pages);
  297. */
  298. #ifdef COLLECT_GPU_MEMINFO
  299. if (mtk_get_gpu_memory_usage(&gpuuse))
  300. gpuuse = B2K(gpuuse);
  301. if (mtk_get_gpu_page_cache(&gpu_page_cache))
  302. gpu_page_cache = B2K(gpu_page_cache);
  303. #endif
  304. mlock = P2K(global_page_state(NR_MLOCK));
  305. #if defined(CONFIG_ZRAM) && defined(CONFIG_ZSMALLOC)
  306. zram = zram_mlog();
  307. #else
  308. zram = 0;
  309. #endif
  310. active = P2K(global_page_state(NR_ACTIVE_ANON) + global_page_state(NR_ACTIVE_FILE));
  311. inactive = P2K(global_page_state(NR_INACTIVE_ANON) + global_page_state(NR_INACTIVE_FILE));
  312. /* MLOG_PRINTK("active: %lu, inactive: %lu\n", active, inactive); */
  313. shmem = P2K(global_page_state(NR_SHMEM));
  314. #ifdef CONFIG_MTK_ION
  315. ion = B2K((unsigned long)ion_mm_heap_total_memory());
  316. #endif
  317. spin_lock_bh(&mlogbuf_lock);
  318. mlog_emit_32(memfree);
  319. mlog_emit_32(swapfree);
  320. mlog_emit_32(cached);
  321. mlog_emit_32(gpuuse);
  322. mlog_emit_32(gpu_page_cache);
  323. mlog_emit_32(mlock);
  324. mlog_emit_32(zram);
  325. mlog_emit_32(active);
  326. mlog_emit_32(inactive);
  327. mlog_emit_32(shmem);
  328. mlog_emit_32(ion);
  329. spin_unlock_bh(&mlogbuf_lock);
  330. }
  331. static void mlog_vmstat(void)
  332. {
  333. int cpu;
  334. unsigned long v[NR_VM_EVENT_ITEMS];
  335. memset(v, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));
  336. for_each_online_cpu(cpu) {
  337. struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
  338. v[PSWPIN] += this->event[PSWPIN];
  339. v[PSWPOUT] += this->event[PSWPOUT];
  340. v[PGFMFAULT] += this->event[PGFMFAULT];
  341. }
  342. spin_lock_bh(&mlogbuf_lock);
  343. mlog_emit_32(v[PSWPIN]);
  344. mlog_emit_32(v[PSWPOUT]);
  345. mlog_emit_32(v[PGFMFAULT]);
  346. mlog_emit_32(0);
  347. spin_unlock_bh(&mlogbuf_lock);
  348. }
  349. /* static void mlog_buddyinfo(void) */
  350. void mlog_buddyinfo(void)
  351. {
  352. int i;
  353. struct zone *zone;
  354. struct zone *node_zones;
  355. unsigned int order;
  356. int zone_nr = 0;
  357. unsigned long normal_nr_free[MAX_ORDER] = {0};
  358. unsigned long high_nr_free[MAX_ORDER] = {0};
  359. for_each_online_node(i) {
  360. pg_data_t *pgdat = NODE_DATA(i);
  361. unsigned long flags;
  362. node_zones = pgdat->node_zones;
  363. /* MAX_NR_ZONES 3 */
  364. for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) {
  365. if (!populated_zone(zone))
  366. continue;
  367. spin_lock_irqsave(&zone->lock, flags);
  368. zone_nr++;
  369. for (order = 0; order < MAX_ORDER; ++order) {
  370. if (zone_nr == 1)
  371. normal_nr_free[order] = zone->free_area[order].nr_free;
  372. if (zone_nr == 2)
  373. high_nr_free[order] = zone->free_area[order].nr_free;
  374. }
  375. spin_unlock_irqrestore(&zone->lock, flags);
  376. }
  377. }
  378. if (zone_nr == 1) {
  379. for (order = 0; order < MAX_ORDER; ++order)
  380. high_nr_free[order] = 0;
  381. }
  382. #ifdef CONFIG_MTKPASR
  383. if (zone_nr == 2)
  384. high_nr_free[MAX_ORDER - 1] += (mtkpasr_show_page_reserved() >> (MAX_ORDER - 1));
  385. #endif
  386. spin_lock_bh(&mlogbuf_lock);
  387. for (order = 0; order < MAX_ORDER; ++order)
  388. mlog_emit_32(normal_nr_free[order]);
  389. for (order = 0; order < MAX_ORDER; ++order)
  390. mlog_emit_32(high_nr_free[order]);
  391. spin_unlock_bh(&mlogbuf_lock);
  392. }
  393. struct task_struct *find_trylock_task_mm(struct task_struct *t)
  394. {
  395. if (spin_trylock(&t->alloc_lock)) {
  396. if (likely(t->mm))
  397. return t;
  398. task_unlock(t);
  399. }
  400. return NULL;
  401. }
  402. /*
  403. * it's copied from lowmemorykiller.c
  404. */
  405. static short lowmem_oom_score_adj_to_oom_adj(short oom_score_adj)
  406. {
  407. if (oom_score_adj == OOM_SCORE_ADJ_MAX)
  408. return OOM_ADJUST_MAX;
  409. else
  410. return ((oom_score_adj * -OOM_DISABLE * 10) / OOM_SCORE_ADJ_MAX + 5) / 10; /* round */
  411. }
  412. static void mlog_procinfo(void)
  413. {
  414. struct task_struct *tsk;
  415. rcu_read_lock();
  416. for_each_process(tsk) {
  417. int oom_score_adj;
  418. const struct cred *cred = NULL;
  419. struct task_struct *real_parent;
  420. struct task_struct *p;
  421. pid_t ppid;
  422. struct task_struct *t;
  423. unsigned long swap_in, swap_out, fm_flt, min_flt, maj_flt;
  424. unsigned long rss;
  425. unsigned long rswap;
  426. if (tsk->flags & PF_KTHREAD)
  427. continue;
  428. p = find_trylock_task_mm(tsk);
  429. if (!p)
  430. continue;
  431. if (!p->signal)
  432. goto unlock_continue;
  433. #ifdef CONFIG_ANDROID_LOW_MEMORY_KILLER_AUTODETECT_OOM_ADJ_VALUES
  434. oom_score_adj = lowmem_oom_score_adj_to_oom_adj(p->signal->oom_score_adj);
  435. #else
  436. oom_score_adj = p->signal->oom_adj;
  437. #endif
  438. if (max_adj < oom_score_adj || oom_score_adj < min_adj)
  439. goto unlock_continue;
  440. if (limit_pid != -1 && p->pid != limit_pid)
  441. goto unlock_continue;
  442. cred = get_task_cred(p);
  443. if (!cred)
  444. goto unlock_continue;
  445. /*
  446. * 1. mediaserver is a suspect in many ANR/FLM cases.
  447. * 2. procesname is "mediaserver" not "/system/bin/mediaserver"
  448. */
  449. if (strncmp("mediaserver", p->comm, TASK_COMM_LEN) == 0)
  450. goto collect_proc_mem_info;
  451. /* skip root user */
  452. if (__kuid_val(cred->uid) == AID_ROOT)
  453. goto unlock_continue;
  454. real_parent = rcu_dereference(p->real_parent);
  455. if (!real_parent)
  456. goto unlock_continue;
  457. ppid = real_parent->pid;
  458. /* skip non java proc (parent is init) */
  459. if (ppid == 1)
  460. goto unlock_continue;
  461. if (oom_score_adj == -16) {
  462. /* only keep system server */
  463. if (__kuid_val(cred->uid) != AID_SYSTEM)
  464. goto unlock_continue;
  465. }
  466. collect_proc_mem_info:
  467. /* reset data */
  468. swap_in = swap_out = fm_flt = min_flt = maj_flt = 0;
  469. /* all threads */
  470. t = p;
  471. do {
  472. /* min_flt += t->min_flt; */
  473. /* maj_flt += t->maj_flt; */
  474. fm_flt += t->fm_flt;
  475. #ifdef CONFIG_SWAP
  476. swap_in += t->swap_in;
  477. swap_out += t->swap_out;
  478. #endif
  479. t = next_thread(t);
  480. #ifdef MLOG_DEBUG
  481. #if defined(__LP64__) || defined(_LP64)
  482. if ((long long)t < 0xffffffc000000000)
  483. break;
  484. #endif
  485. #endif
  486. } while (t != p);
  487. /* emit log */
  488. rss = P2K(get_mm_rss(p->mm));
  489. rswap = P2K(get_mm_counter(p->mm, MM_SWAPENTS));
  490. spin_lock_bh(&mlogbuf_lock);
  491. mlog_emit_32(p->pid);
  492. mlog_emit_32(oom_score_adj);
  493. mlog_emit_32(rss);
  494. mlog_emit_32(rswap);
  495. mlog_emit_32(swap_in);
  496. mlog_emit_32(swap_out);
  497. mlog_emit_32(fm_flt);
  498. /* mlog_emit_32(min_flt); */
  499. /* mlog_emit_32(maj_flt); */
  500. spin_unlock_bh(&mlogbuf_lock);
  501. unlock_continue:
  502. if (cred)
  503. put_cred(cred);
  504. task_unlock(p);
  505. }
  506. rcu_read_unlock();
  507. }
  508. void mlog(int type)
  509. {
  510. /* unsigned long flag; */
  511. unsigned long microsec_rem;
  512. unsigned long long t = local_clock();
  513. #ifdef PROFILE_MLOG_OVERHEAD
  514. unsigned long long t1 = t;
  515. #endif
  516. /* MLOG_PRINTK("[mlog] log %d %d %d\n", meminfo_filter, vmstat_filter, proc_filter); */
  517. /* time stamp */
  518. microsec_rem = do_div(t, 1000000000);
  519. /* spin_lock_irqsave(&mlogbuf_lock, flag); */
  520. spin_lock_bh(&mlogbuf_lock);
  521. mlog_emit_32(MLOG_ID); /* tag for correct start point */
  522. mlog_emit_32(type);
  523. mlog_emit_32((unsigned long)t);
  524. mlog_emit_32(microsec_rem / 1000);
  525. spin_unlock_bh(&mlogbuf_lock);
  526. /* memory log */
  527. if (meminfo_filter)
  528. mlog_meminfo();
  529. if (vmstat_filter)
  530. mlog_vmstat();
  531. if (buddyinfo_filter)
  532. mlog_buddyinfo();
  533. if (proc_filter)
  534. mlog_procinfo();
  535. /* spin_unlock_irqrestore(&mlogbuf_lock, flag); */
  536. if (waitqueue_active(&mlog_wait))
  537. wake_up_interruptible(&mlog_wait);
  538. #ifdef PROFILE_MLOG_OVERHEAD
  539. MLOG_PRINTK("[mlog] %llu ns\n", local_clock() - t1);
  540. #endif
  541. }
  542. EXPORT_SYMBOL(mlog);
  543. void mlog_doopen(void)
  544. {
  545. spin_lock_bh(&mlogbuf_lock);
  546. strfmt_idx = 0;
  547. spin_unlock_bh(&mlogbuf_lock);
  548. }
  549. int mlog_unread(void)
  550. {
  551. return mlog_end - mlog_start;
  552. }
  553. int mlog_doread(char __user *buf, size_t len)
  554. {
  555. unsigned i;
  556. int error = -EINVAL;
  557. char mlog_str[MLOG_STR_LEN];
  558. if (!buf || len < 0)
  559. goto out;
  560. error = 0;
  561. if (!len)
  562. goto out;
  563. if (!access_ok(VERIFY_WRITE, buf, len)) {
  564. error = -EFAULT;
  565. goto out;
  566. }
  567. /* MLOG_PRINTK("[mlog] wait %d %d\n", mlog_start, mlog_end); */
  568. error = wait_event_interruptible(mlog_wait, (mlog_start - mlog_end));
  569. if (error)
  570. goto out;
  571. i = 0;
  572. spin_lock_bh(&mlogbuf_lock);
  573. /* MLOG_PRINTK("[mlog] doread %d %d\n", mlog_start, mlog_end); */
  574. while (!error && (mlog_start != mlog_end) && i < len - MLOG_STR_LEN) {
  575. int size;
  576. int v;
  577. /* retrieve value */
  578. v = MLOG_BUF(mlog_start);
  579. mlog_start++;
  580. if (unlikely((v == MLOG_ID) ^ (strfmt_idx == 0))) {
  581. /* find first valid log */
  582. if (strfmt_idx == 0)
  583. continue;
  584. strfmt_idx = 0;
  585. }
  586. if (strfmt_idx == 0)
  587. v = '\n';
  588. /* MLOG_PRINTK("[mlog] %d: %s\n", strfmt_idx, strfmt_list[strfmt_idx]); */
  589. size = snprintf(mlog_str, MLOG_STR_LEN, strfmt_list[strfmt_idx++], v);
  590. if (strfmt_idx >= strfmt_len)
  591. strfmt_idx = strfmt_proc;
  592. spin_unlock_bh(&mlogbuf_lock);
  593. if (__copy_to_user(buf, mlog_str, size))
  594. error = -EFAULT;
  595. else {
  596. buf += size;
  597. i += size;
  598. }
  599. cond_resched();
  600. spin_lock_bh(&mlogbuf_lock);
  601. }
  602. spin_unlock_bh(&mlogbuf_lock);
  603. if (!error)
  604. error = i;
  605. out:
  606. /* MLOG_PRINTK("[mlog] doread end %d\n", error); */
  607. return error;
  608. }
  609. static void mlog_timer_handler(unsigned long data)
  610. {
  611. mlog(MLOG_TRIGGER_TIMER);
  612. mod_timer(&mlog_timer, round_jiffies(jiffies + timer_intval));
  613. }
  614. static void mlog_init_logger(void)
  615. {
  616. spin_lock_init(&mlogbuf_lock);
  617. mlog_reset_format();
  618. mlog_reset_buffer();
  619. setup_timer(&mlog_timer, mlog_timer_handler, 0);
  620. mlog_timer.expires = jiffies + timer_intval;
  621. add_timer(&mlog_timer);
  622. }
  623. static void mlog_exit_logger(void)
  624. {
  625. kfree(strfmt_list);
  626. strfmt_list = NULL;
  627. }
  628. static int __init mlog_init(void)
  629. {
  630. mlog_init_logger();
  631. mlog_init_procfs();
  632. return 0;
  633. }
  634. static void __exit mlog_exit(void)
  635. {
  636. mlog_exit_logger();
  637. }
  638. module_param(min_adj, int, S_IRUGO | S_IWUSR);
  639. module_param(max_adj, int, S_IRUGO | S_IWUSR);
  640. module_param(limit_pid, int, S_IRUGO | S_IWUSR);
  641. static int do_filter_handler(const char *val, const struct kernel_param *kp)
  642. {
  643. const int ret = param_set_uint(val, kp);
  644. mlog_reset_format();
  645. mlog_reset_buffer();
  646. return ret;
  647. }
  648. static const struct kernel_param_ops param_ops_change_filter = {
  649. .set = &do_filter_handler,
  650. .get = &param_get_uint,
  651. .free = NULL,
  652. };
  653. static int do_time_intval_handler(const char *val, const struct kernel_param *kp)
  654. {
  655. const int ret = param_set_uint(val, kp);
  656. mod_timer(&mlog_timer, jiffies + ret);
  657. return ret;
  658. }
  659. static const struct kernel_param_ops param_ops_change_time_intval = {
  660. .set = &do_time_intval_handler,
  661. .get = &param_get_uint,
  662. .free = NULL,
  663. };
  664. param_check_uint(meminfo_filter, &meminfo_filter);
  665. module_param_cb(meminfo_filter, &param_ops_change_filter, &meminfo_filter, S_IRUGO | S_IWUSR);
  666. __MODULE_PARM_TYPE(meminfo_filter, uint);
  667. param_check_uint(vmstat_filter, &vmstat_filter);
  668. module_param_cb(vmstat_filter, &param_ops_change_filter, &vmstat_filter, S_IRUGO | S_IWUSR);
  669. __MODULE_PARM_TYPE(vmstat_filter, uint);
  670. param_check_uint(proc_filter, &proc_filter);
  671. module_param_cb(proc_filter, &param_ops_change_filter, &proc_filter, S_IRUGO | S_IWUSR);
  672. __MODULE_PARM_TYPE(proc_filter, uint);
  673. param_check_ulong(timer_intval, &timer_intval);
  674. module_param_cb(timer_intval, &param_ops_change_time_intval, &timer_intval, S_IRUGO | S_IWUSR);
  675. __MODULE_PARM_TYPE(timer_intval, ulong);
  676. static uint do_mlog;
  677. static int do_mlog_handler(const char *val, const struct kernel_param *kp)
  678. {
  679. const int ret = param_set_uint(val, kp);
  680. mlog(do_mlog);
  681. /* MLOG_PRINTK("[mlog] do_mlog %d\n", do_mlog); */
  682. return ret;
  683. }
  684. static const struct kernel_param_ops param_ops_do_mlog = {
  685. .set = &do_mlog_handler,
  686. .get = &param_get_uint,
  687. .free = NULL,
  688. };
  689. param_check_uint(do_mlog, &do_mlog);
  690. module_param_cb(do_mlog, &param_ops_do_mlog, &do_mlog, S_IRUGO | S_IWUSR);
  691. __MODULE_PARM_TYPE(do_mlog, uint);
  692. module_init(mlog_init);
  693. module_exit(mlog_exit);
  694. /* TODO module license & information */
  695. MODULE_DESCRIPTION("MEDIATEK Memory Log Driver");
  696. MODULE_AUTHOR("Jimmy Su<jimmy.su@mediatek.com>");
  697. MODULE_LICENSE("GPL");