import PULS_20160108
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / misc / mediatek / aee / aed / aed-debug.c
1
2 #include <linux/proc_fs.h>
3 #include <linux/seq_file.h>
4 #include <linux/delay.h>
5 #include <linux/kthread.h>
6 #include <linux/kallsyms.h>
7 #include <linux/notifier.h>
8 #include <linux/kprobes.h>
9 #include <linux/cpumask.h>
10 #include <linux/slab.h>
11 #include <linux/kdebug.h>
12 #include <asm/uaccess.h>
13 #if defined(CONFIG_ARM_PSCI) || (CONFIG_ARM64)
14 #include <mach/mt_secure_api.h>
15 #endif
16 #include <mach/smp.h>
17 #include "aed.h"
18
19 #ifndef PARTIAL_BUILD
20
21 #define BUFSIZE 128
22 static int test_case;
23 static int test_cpu;
24 static struct task_struct *wk_tsk[NR_CPUS];
25 extern struct atomic_notifier_head panic_notifier_list;
26
27 #ifdef __aarch64__
28 #undef BUG
29 #define BUG() *((unsigned *)0xaed) = 0xDEAD
30 #endif
31
32 static int force_panic_hang(struct notifier_block *this, unsigned long event, void *ptr)
33 {
34 LOGW("\n ==> force panic flow hang\n");
35 while (1);
36 LOGW("\n You should not see this\n");
37 return 0;
38 }
39
40 static struct notifier_block panic_test = {
41 .notifier_call = force_panic_hang,
42 .priority = INT_MAX,
43 };
44
45 void notrace wdt_atf_hang(void)
46 {
47 int cpu = get_HW_cpuid();
48 LOGE(" CPU %d : wdt_atf_hang\n", cpu);
49 local_fiq_disable();
50 preempt_disable();
51 local_irq_disable();
52 while (1);
53 }
54
55 static int kwdt_thread_test(void *arg)
56 {
57 struct sched_param param = {.sched_priority = RTPM_PRIO_WDT };
58 int cpu = get_HW_cpuid();
59
60 sched_setscheduler(current, SCHED_FIFO, &param);
61 set_current_state(TASK_INTERRUPTIBLE);
62 LOGW("\n ==> kwdt_thread_test on CPU %d, test_case = %d\n", cpu, test_case);
63 msleep(1000);
64
65 if (test_case == 1) {
66 if (cpu == test_cpu) {
67 LOGW("\n CPU %d : disable preemption and local IRQ forever", cpu);
68 preempt_disable();
69 local_irq_disable();
70 while (1);
71 LOGW("\n Error : You should not see this !\n");
72 } else {
73 LOGW("\n CPU %d : Do nothing and exit\n ", cpu);
74 }
75 } else if (test_case == 2) {
76 if (cpu == test_cpu) {
77 msleep(1000);
78 LOGW("\n CPU %d : disable preemption and local IRQ forever", cpu);
79 preempt_disable();
80 local_irq_disable();
81 while (1);
82 LOGE("\n Error : You should not see this !\n");
83 } else {
84 LOGW("\n CPU %d : disable irq\n ", cpu);
85 local_irq_disable();
86 while (1);
87 LOGE("\n Error : You should not see this !\n");
88 }
89 } else if (test_case == 3) {
90 if (cpu == test_cpu) {
91 LOGW("\n CPU %d : register panic notifier and force hang \n",
92 cpu);
93 atomic_notifier_chain_register(&panic_notifier_list, &panic_test);
94 preempt_disable();
95 local_irq_disable();
96 while (1);
97 LOGE("\n Error : You should not see this !\n");
98 } else {
99 LOGW("\n CPU %d : Do nothing and exit\n ", cpu);
100 }
101 } else if (test_case == 4) {
102 LOGW("\n CPU %d : disable preemption and local IRQ forever\n ", cpu);
103 preempt_disable();
104 local_irq_disable();
105 while (1);
106 LOGW("\n Error : You should not see this !\n");
107 } else if (test_case == 5) {
108 LOGW("\n CPU %d : disable preemption and local IRQ/FIQ forever\n ", cpu);
109 local_fiq_disable();
110 preempt_disable();
111 local_irq_disable();
112 while (1);
113 LOGW("\n Error : You should not see this !\n");
114 } else if (test_case == 6) {
115 LOGW("\n CPU %d : disable preemption and local IRQ/FIQ forever\n ", cpu);
116 local_fiq_disable();
117 preempt_disable();
118 local_irq_disable();
119 while (1);
120 LOGW("\n Error : You should not see this !\n");
121 }
122 return 0;
123 }
124
125 static ssize_t proc_generate_wdt_write(struct file *file,
126 const char __user *buf, size_t size, loff_t *ppos)
127 {
128 unsigned int i = 0;
129 char msg[4];
130 unsigned char name[20] = { 0 };
131
132 if ((size < 2) || (size > sizeof(msg))) {
133 LOGW("\n size = %zx\n", size);
134 return -EINVAL;
135 }
136 if (copy_from_user(msg, buf, size)) {
137 LOGW("copy_from_user error");
138 return -EFAULT;
139 }
140 test_case = (unsigned int)msg[0] - '0';
141 test_cpu = (unsigned int)msg[2] - '0';
142 LOGW("test_case = %d, test_cpu = %d", test_case, test_cpu);
143 if ((msg[1] != ':') || (test_case < 1) || (test_case > 6)
144 || (test_cpu < 0) || (test_cpu > nr_cpu_ids)) {
145 LOGW("WDT test - Usage: [test case number(1~6):test cpu(0~%d)]\n", nr_cpu_ids);
146 return -EINVAL;
147 }
148
149 if (test_case == 1) {
150 LOGW("Test 1 : One CPU WDT timeout (smp_send_stop succeed)\n");
151 } else if (test_case == 2) {
152 LOGW("Test 2 : One CPU WDT timeout, other CPU disable irq (smp_send_stop fail in old design)\n");
153 } else if (test_case == 3) {
154 LOGW("Test 3 : WDT timeout and loop in panic flow\n");
155 } else if (test_case == 4) {
156 LOGW("Test 4 : All CPU WDT timeout (other CPU stop in the loop)\n");
157 } else if (test_case == 5) {
158 LOGW("Test 5 : Disable ALL CPU IRQ/FIQ (FIQ : HW_reboot, ATF : HWT \n");
159 } else if (test_case == 6) {
160 LOGW("Test 6 : (For ATF) HW_REBOOT : change SMC call back function and while loop \n");
161 #ifdef CONFIG_ARM64
162 mt_secure_call(MTK_SIP_KERNEL_WDT, (u64)&wdt_atf_hang, 0, 0);
163 #endif
164 #ifdef CONFIG_ARM_PSCI
165 mt_secure_call(MTK_SIP_KERNEL_WDT, (u32)&wdt_atf_hang, 0, 0);
166 #endif
167 } else {
168 LOGE("\n Unknown test_case %d\n", test_case);
169 return -EINVAL;
170 }
171
172 /* create kernel threads and bind on every cpu */
173 for (i = 0; i < nr_cpu_ids; i++) {
174 sprintf(name, "wd-test-%d", i);
175 LOGW("[WDK]thread name: %s\n", name);
176 wk_tsk[i] = kthread_create(kwdt_thread_test, NULL, name);
177 if (IS_ERR(wk_tsk[i])) {
178 int ret = PTR_ERR(wk_tsk[i]);
179 wk_tsk[i] = NULL;
180 return ret;
181 }
182 kthread_bind(wk_tsk[i], i);
183 }
184
185 for (i = 0; i < nr_cpu_ids; i++) {
186 LOGW(" wake_up_process(wk_tsk[%d])\n", i);
187 wake_up_process(wk_tsk[i]);
188 }
189
190 return size;
191 }
192
193 static ssize_t proc_generate_wdt_read(struct file *file,
194 char __user *buf, size_t size, loff_t *ppos)
195 {
196 char buffer[BUFSIZE];
197 return sprintf(buffer, "WDT test - Usage: [test case number:test cpu]\n");
198 }
199
200
201 /*****************************BEGIN OOPS***************************/
202 /**********BEGIN ISR trigger HWT**********/
203 /* kprobe pre_handler: called just before the probed instruction is executed */
204 static int handler_pre(struct kprobe *p, struct pt_regs *regs)
205 {
206 LOGI("process_name:[%s], pid = %d.\n", current->comm, current->pid);
207 return 0;
208 }
209
210
211 /* kprobe post_handler: called after the probed instruction is executed */
212 int flag = 1;
213 void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
214 {
215 if (flag) {
216 flag = 0;
217 mdelay(30 * 1000);
218 }
219 }
220
221 static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr);
222
223 static struct kprobe kp_kpd_irq_handler = {
224 .symbol_name = "kpd_irq_handler",
225 .pre_handler = handler_pre,
226 .post_handler = handler_post,
227 .fault_handler = handler_fault,
228 };
229
230 /*
231 * fault_handler: this is called if an exception is generated for any
232 * instruction within the pre- or post-handler, or when Kprobes
233 * single-steps the probed instruction.
234 */
235 static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
236 {
237 LOGE("fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr);
238 unregister_kprobe(&kp_kpd_irq_handler);
239 LOGI("kprobe at %p unregistered\n", kp_kpd_irq_handler.addr);
240
241 /* Return 0 because we don't handle the fault. */
242 return 0;
243 }
244
245 static int register_kprobe_kpd_irq_handler(void)
246 {
247 int ret = 0;
248
249 /* All set to register with Kprobes */
250 ret = register_kprobe(&kp_kpd_irq_handler);
251 if (ret < 0) {
252 LOGI("register_kprobe failed, returned %d\n", ret);
253 } else {
254 LOGI("Planted kprobe at %p, press Vol+/- to trigger.\n", kp_kpd_irq_handler.addr);
255 }
256 return ret;
257 }
258
259 /**********END ISR trigger HWT**********/
260 /**********BEGIN panic case**********/
261 static int noinline stack_overflow_routine(int x, int y, int z)
262 {
263 char a[4];
264 char *p = a;
265 int i;
266 for (i = 0; i < (x + y + z) * 2; i++) {
267 *(p + i) = i;
268 }
269 /* stack overflow */
270 return a[0] + a[3];
271 }
272
273 static void noinline buffer_over_flow(void)
274 {
275 int n;
276 LOGI("test case : buffer overflow\n");
277 n = stack_overflow_routine(10, 1, 22);
278 LOGI("%s: %d\n", __func__, n);
279 }
280
281 static void noinline access_null_pointer(void)
282 {
283 LOGI("test case : derefence Null pointer\n");
284 *((unsigned *)0) = 0xDEAD;
285 }
286
287 static void noinline double_free(void)
288 {
289 char *p = kmalloc(32, GFP_KERNEL);
290 int i;
291 LOGI("test case : double free\n");
292 for (i = 0; i < 32; i++) {
293 p[i] = (char)i;
294 }
295 LOGI("aee_ut_ke: call free\n");
296 kfree(p);
297 LOGI("aee_ut_ke: call free again\n");
298 kfree(p);
299 }
300
301 static void noinline devide_by_0(void)
302 {
303 int ZERO = 0;
304 int number;
305 LOGI("test case: division by %d\n", ZERO);
306 number = 100 / ZERO;
307 LOGI("%s: %d\n", __func__, number);
308 }
309
310 /**********END panic case**********/
311
312 static ssize_t proc_generate_oops_read(struct file *file,
313 char __user *buf, size_t size, loff_t *ppos)
314 {
315 int len;
316 char buffer[BUFSIZE];
317 len = snprintf(buffer, BUFSIZE, "Oops Generated!\n");
318 if (copy_to_user(buf, buffer, len)) {
319 LOGE("%s fail to output info.\n", __func__);
320 }
321
322 BUG();
323 return len;
324 }
325
326 static ssize_t proc_generate_oops_write(struct file *file,
327 const char __user *buf, size_t size, loff_t *ppos)
328 {
329 char msg[6];
330 int test_case, test_subcase, test_cpu;
331
332 if ((size < 2) || (size > sizeof(msg))) {
333 LOGW("%s: count = %zx\n", __func__, size);
334 return -EINVAL;
335 }
336 if (copy_from_user(msg, buf, size)) {
337 LOGW("%s: error\n", __func__);
338 return -EFAULT;
339 }
340 test_case = (unsigned int)msg[0] - '0';
341 test_subcase = (unsigned int)msg[2] - '0';
342 test_cpu = (unsigned int)msg[4] - '0';
343 LOGW("test_case = %d-%d, test_cpu = %d\n", test_case, test_subcase, test_cpu);
344 switch (test_case) {
345 case 1:
346 switch (test_subcase) {
347 case 1:
348 buffer_over_flow();
349 break;
350 case 2:
351 access_null_pointer();
352 break;
353 case 3:
354 double_free();
355 break;
356 case 4:
357 devide_by_0();
358 break;
359 default:
360 break;
361 }
362 break;
363 case 2:
364 register_kprobe_kpd_irq_handler();
365 break;
366 case 3:
367 panic("aee test");
368 break;
369 default:
370 break;
371 }
372 return size;
373 }
374
375 static int nested_panic(struct notifier_block *this, unsigned long event, void *ptr)
376 {
377 LOGE("\n => force nested panic\n");
378 BUG();
379 return 0;
380 }
381
382 static struct notifier_block panic_blk = {
383 .notifier_call = nested_panic,
384 .priority = INT_MAX - 100,
385 };
386
387 static ssize_t proc_generate_nested_ke_read(struct file *file,
388 char __user *buf, size_t size, loff_t *ppos)
389 {
390 int len = 0;
391 atomic_notifier_chain_register(&panic_notifier_list, &panic_blk);
392 LOGE("\n => panic_notifier_list registered\n");
393 BUG();
394 /* len = sprintf(page, "Nested panic generated\n"); */
395
396 return len;
397 }
398
399 static ssize_t proc_generate_nested_ke_write(struct file *file,
400 const char __user *buf, size_t size, loff_t *ppos)
401 {
402 char msg[6];
403 int test_case, test_subcase, test_cpu;
404
405 if ((size < 2) || (size > sizeof(msg))) {
406 LOGW("%s: count = %zx\n", __func__, size);
407 return -EINVAL;
408 }
409 if (copy_from_user(msg, buf, size)) {
410 LOGW("%s: error\n", __func__);
411 return -EFAULT;
412 }
413 test_case = (unsigned int)msg[0] - '0';
414 test_subcase = (unsigned int)msg[2] - '0';
415 test_cpu = (unsigned int)msg[4] - '0';
416 LOGW("test_case = %d-%d, test_cpu = %d\n", test_case, test_subcase, test_cpu);
417 switch (test_case) {
418 case 1:
419 register_die_notifier(&panic_blk);
420 break;
421 }
422 BUG();
423 return 0;
424 }
425
426
427 static ssize_t proc_generate_ee_read(struct file *file,
428 char __user *buf, size_t size, loff_t *ppos)
429 {
430 #define TEST_EE_LOG_SIZE 2048
431 #define TEST_EE_PHY_SIZE 65536
432
433 char buffer[BUFSIZE];
434 char *ptr, *log;
435 int i;
436
437 if ((*ppos)++)
438 return 0;
439 ptr = kmalloc(TEST_EE_PHY_SIZE, GFP_KERNEL);
440 log = kmalloc(TEST_EE_LOG_SIZE, GFP_KERNEL);
441 if (ptr == NULL) {
442 LOGE("proc_generate_ee_read kmalloc fail\n");
443 return sprintf(buffer, "kmalloc fail\n");
444 }
445 for (i = 0; i < TEST_EE_PHY_SIZE; i++) {
446 ptr[i] = (i % 26) + 'A';
447 }
448 for (i = 0; i < TEST_EE_LOG_SIZE; i++) {
449 log[i] = i % 255;
450 }
451 aed_md_exception_api((int *)log, TEST_EE_LOG_SIZE, (int *)ptr, TEST_EE_PHY_SIZE, __FILE__, DB_OPT_FTRACE);
452 kfree(ptr);
453 kfree(log);
454
455 return sprintf(buffer, "Modem EE Generated\n");
456 }
457
458 static ssize_t proc_generate_ee_write(struct file *file,
459 const char __user *buf, size_t size, loff_t *ppos)
460 {
461 return 0;
462 }
463
464 static ssize_t proc_generate_combo_read(struct file *file,
465 char __user *buf, size_t size, loff_t *ppos)
466 {
467 #define TEST_COMBO_PHY_SIZE 65536
468 char buffer[BUFSIZE];
469 int i;
470 char *ptr;
471 if ((*ppos)++)
472 return 0;
473 ptr = kmalloc(TEST_COMBO_PHY_SIZE, GFP_KERNEL);
474 if (ptr == NULL) {
475 LOGE("proc_generate_combo_read kmalloc fail\n");
476 return sprintf(buffer, "kmalloc fail\n");
477 }
478 for (i = 0; i < TEST_COMBO_PHY_SIZE; i++) {
479 ptr[i] = (i % 26) + 'A';
480 }
481
482 aee_kernel_dal_show("Oops, MT662X is generating core dump, please wait up to 5 min\n");
483 aed_combo_exception(NULL, 0, (int *)ptr, TEST_COMBO_PHY_SIZE, __FILE__);
484 kfree(ptr);
485
486 return sprintf(buffer, "Combo EE Generated\n");
487 }
488
489 static ssize_t proc_generate_combo_write(struct file *file,
490 const char __user *buf, size_t size, loff_t *ppos)
491 {
492 return 0;
493 }
494
495 static ssize_t proc_generate_md32_read(struct file *file,
496 char __user *buf, size_t size, loff_t *ppos)
497 {
498 #define TEST_MD32_PHY_SIZE 65536
499 char buffer[BUFSIZE];
500 int i;
501 char *ptr;
502 if ((*ppos)++)
503 return 0;
504 ptr = kmalloc(TEST_MD32_PHY_SIZE, GFP_KERNEL);
505 if (ptr == NULL) {
506 LOGE("proc_generate_md32_read kmalloc fail\n");
507 return sprintf(buffer, "kmalloc fail\n");
508 }
509 for (i = 0; i < TEST_MD32_PHY_SIZE; i++) {
510 ptr[i] = (i % 26) + 'a';
511 }
512
513 sprintf(buffer, "MD32 EE log here\n");
514 aed_md32_exception((int *)buffer, (int)sizeof(buffer), (int *)ptr, TEST_MD32_PHY_SIZE, __FILE__);
515 kfree(ptr);
516
517 return sprintf(buffer, "MD32 EE Generated\n");
518 }
519
520 static ssize_t proc_generate_md32_write(struct file *file,
521 const char __user *buf, size_t size, loff_t *ppos)
522 {
523 return 0;
524 }
525
526 static ssize_t proc_generate_kernel_notify_read(struct file *file,
527 char __user *buf, size_t size, loff_t *ppos)
528 {
529 char buffer[BUFSIZE];
530 int len =
531 snprintf(buffer, BUFSIZE,
532 "Usage: write message with format \"R|W|E:Tag:You Message\" into this file to generate kernel warning\n");
533 if (*ppos)
534 return 0;
535 if (copy_to_user(buf, buffer, len)) {
536 LOGE("%s fail to output info.\n", __func__);
537 return -EFAULT;
538 }
539 *ppos += len;
540 return len;
541 }
542
543
544 static ssize_t proc_generate_kernel_notify_write(struct file *file,
545 const char __user *buf, size_t size, loff_t *ppos)
546 {
547 char msg[164], *colon_ptr;
548
549 if (size == 0) {
550 return -EINVAL;
551 }
552
553 if ((size < 5) || (size >= sizeof(msg))) {
554 LOGW("aed: %s size sould be >= 5 and <= %zx bytes.\n", __func__, sizeof(msg));
555 return -EINVAL;
556 }
557
558 if (copy_from_user(msg, buf, size)) {
559 LOGW("aed: %s unable to read message\n", __func__);
560 return -EFAULT;
561 }
562 /* Be safe */
563 msg[size] = 0;
564
565 if (msg[1] != ':') {
566 return -EINVAL;
567 }
568 colon_ptr = strchr(&msg[2], ':');
569 if ((colon_ptr == NULL) || ((colon_ptr - msg) > 32)) {
570 LOGW("aed: %s cannot find valid module name\n", __func__);
571 return -EINVAL;
572 }
573 *colon_ptr = 0;
574
575 switch (msg[0]) {
576 case 'R':
577 aee_kernel_reminding(&msg[2], colon_ptr + 1);
578 break;
579
580 case 'W':
581 aee_kernel_warning(&msg[2], colon_ptr + 1);
582 break;
583
584 case 'E':
585 aee_kernel_exception(&msg[2], colon_ptr + 1);
586 break;
587
588 default:
589 return -EINVAL;
590 }
591
592 return size;
593 }
594
595 static ssize_t proc_generate_dal_read(struct file *file,
596 char __user *buf, size_t size, loff_t *ppos)
597 {
598 char buffer[BUFSIZE];
599 int len;
600 if ((*ppos)++)
601 return 0;
602 aee_kernel_dal_show("Test for DAL\n");
603 len = sprintf(buffer, "DAL Generated\n");
604
605 return len;
606 }
607
608 static ssize_t proc_generate_dal_write(struct file *file,
609 const char __user *buf, size_t size, loff_t *ppos)
610 {
611 return 0;
612 }
613
614 AED_FILE_OPS(generate_oops);
615 AED_FILE_OPS(generate_nested_ke);
616 AED_FILE_OPS(generate_kernel_notify);
617 AED_FILE_OPS(generate_wdt);
618 AED_FILE_OPS(generate_ee);
619 AED_FILE_OPS(generate_combo);
620 AED_FILE_OPS(generate_md32);
621 AED_FILE_OPS(generate_dal);
622
623 int aed_proc_debug_init(struct proc_dir_entry *aed_proc_dir)
624 {
625 AED_PROC_ENTRY(generate-oops, generate_oops, S_IRUSR | S_IWUSR);
626 AED_PROC_ENTRY(generate-nested-ke, generate_nested_ke, S_IRUSR);
627 AED_PROC_ENTRY(generate-kernel-notify, generate_kernel_notify, S_IRUSR | S_IWUSR);
628 AED_PROC_ENTRY(generate-wdt, generate_wdt, S_IRUSR | S_IWUSR);
629 AED_PROC_ENTRY(generate-ee, generate_ee, S_IRUSR);
630 AED_PROC_ENTRY(generate-combo, generate_combo, S_IRUSR);
631 AED_PROC_ENTRY(generate-md32, generate_md32, S_IRUSR);
632 AED_PROC_ENTRY(generate-dal, generate_dal, S_IRUSR);
633
634 return 0;
635 }
636
637 int aed_proc_debug_done(struct proc_dir_entry *aed_proc_dir)
638 {
639 remove_proc_entry("generate-oops", aed_proc_dir);
640 remove_proc_entry("generate-nested-ke", aed_proc_dir);
641 remove_proc_entry("generate-kernel-notify", aed_proc_dir);
642 remove_proc_entry("generate-ee", aed_proc_dir);
643 remove_proc_entry("generate-combo", aed_proc_dir);
644 remove_proc_entry("generate-md32", aed_proc_dir);
645 remove_proc_entry("generate-wdt", aed_proc_dir);
646 remove_proc_entry("generate-dal", aed_proc_dir);
647 return 0;
648 }
649
650 #else
651
652 int aed_proc_debug_init(struct proc_dir_entry *aed_proc_dir)
653 {
654 return 0;
655 }
656
657 int aed_proc_debug_done(struct proc_dir_entry *aed_proc_dir)
658 {
659 return 0;
660 }
661
662 #endif