aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <rostedt@goodmis.org>2008-08-14 15:45:08 -0400
committerIngo Molnar <mingo@elte.hu>2008-10-14 04:34:44 -0400
commit68bf21aa15c85d2e9b623dcda2b1ed8893275fa1 (patch)
tree54d4d4f7e8311b77f3166a8807a635347d479081 /kernel/trace
parent8da3821ba5634497da63d58a69e24a97697c4a2b (diff)
ftrace: mcount call site on boot nops core
This is the infrastructure to the converting the mcount call sites recorded by the __mcount_loc section into nops on boot. It also allows for using these sites to enable tracing as normal. When the __mcount_loc section is used, the "ftraced" kernel thread is disabled. This uses the current infrastructure to record the mcount call sites as well as convert them to nops. The mcount function is kept as a stub on boot up and not converted to the ftrace_record_ip function. We use the ftrace_record_ip to only record from the table. This patch does not handle modules. That comes with a later patch. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c148
1 files changed, 105 insertions, 43 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index f6e3af31b403..df96d5990c04 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -792,47 +792,7 @@ static int ftrace_update_code(void)
792 return 1; 792 return 1;
793} 793}
794 794
795static int ftraced(void *ignore) 795static int __init ftrace_dyn_table_alloc(unsigned long num_to_init)
796{
797 unsigned long usecs;
798
799 while (!kthread_should_stop()) {
800
801 set_current_state(TASK_INTERRUPTIBLE);
802
803 /* check once a second */
804 schedule_timeout(HZ);
805
806 if (unlikely(ftrace_disabled))
807 continue;
808
809 mutex_lock(&ftrace_sysctl_lock);
810 mutex_lock(&ftraced_lock);
811 if (!ftraced_suspend && !ftraced_stop &&
812 ftrace_update_code()) {
813 usecs = nsecs_to_usecs(ftrace_update_time);
814 if (ftrace_update_tot_cnt > 100000) {
815 ftrace_update_tot_cnt = 0;
816 pr_info("hm, dftrace overflow: %lu change%s"
817 " (%lu total) in %lu usec%s\n",
818 ftrace_update_cnt,
819 ftrace_update_cnt != 1 ? "s" : "",
820 ftrace_update_tot_cnt,
821 usecs, usecs != 1 ? "s" : "");
822 ftrace_disabled = 1;
823 WARN_ON_ONCE(1);
824 }
825 }
826 mutex_unlock(&ftraced_lock);
827 mutex_unlock(&ftrace_sysctl_lock);
828
829 ftrace_shutdown_replenish();
830 }
831 __set_current_state(TASK_RUNNING);
832 return 0;
833}
834
835static int __init ftrace_dyn_table_alloc(void)
836{ 796{
837 struct ftrace_page *pg; 797 struct ftrace_page *pg;
838 int cnt; 798 int cnt;
@@ -859,7 +819,9 @@ static int __init ftrace_dyn_table_alloc(void)
859 819
860 pg = ftrace_pages = ftrace_pages_start; 820 pg = ftrace_pages = ftrace_pages_start;
861 821
862 cnt = NR_TO_INIT / ENTRIES_PER_PAGE; 822 cnt = num_to_init / ENTRIES_PER_PAGE;
823 pr_info("ftrace: allocating %ld hash entries in %d pages\n",
824 num_to_init, cnt);
863 825
864 for (i = 0; i < cnt; i++) { 826 for (i = 0; i < cnt; i++) {
865 pg->next = (void *)get_zeroed_page(GFP_KERNEL); 827 pg->next = (void *)get_zeroed_page(GFP_KERNEL);
@@ -1556,6 +1518,104 @@ static __init int ftrace_init_debugfs(void)
1556 1518
1557fs_initcall(ftrace_init_debugfs); 1519fs_initcall(ftrace_init_debugfs);
1558 1520
1521#ifdef CONFIG_FTRACE_MCOUNT_RECORD
1522static int ftrace_convert_nops(unsigned long *start,
1523 unsigned long *end)
1524{
1525 unsigned long *p;
1526 unsigned long addr;
1527 unsigned long flags;
1528
1529 p = start;
1530 while (p < end) {
1531 addr = ftrace_call_adjust(*p++);
1532 ftrace_record_ip(addr);
1533 ftrace_shutdown_replenish();
1534 }
1535
1536 /* p is ignored */
1537 local_irq_save(flags);
1538 __ftrace_update_code(p);
1539 local_irq_restore(flags);
1540
1541 return 0;
1542}
1543
1544extern unsigned long __start_mcount_loc[];
1545extern unsigned long __stop_mcount_loc[];
1546
1547void __init ftrace_init(void)
1548{
1549 unsigned long count, addr, flags;
1550 int ret;
1551
1552 /* Keep the ftrace pointer to the stub */
1553 addr = (unsigned long)ftrace_stub;
1554
1555 local_irq_save(flags);
1556 ftrace_dyn_arch_init(&addr);
1557 local_irq_restore(flags);
1558
1559 /* ftrace_dyn_arch_init places the return code in addr */
1560 if (addr)
1561 goto failed;
1562
1563 count = __stop_mcount_loc - __start_mcount_loc;
1564
1565 ret = ftrace_dyn_table_alloc(count);
1566 if (ret)
1567 goto failed;
1568
1569 last_ftrace_enabled = ftrace_enabled = 1;
1570
1571 ret = ftrace_convert_nops(__start_mcount_loc,
1572 __stop_mcount_loc);
1573
1574 return;
1575 failed:
1576 ftrace_disabled = 1;
1577}
1578#else /* CONFIG_FTRACE_MCOUNT_RECORD */
1579static int ftraced(void *ignore)
1580{
1581 unsigned long usecs;
1582
1583 while (!kthread_should_stop()) {
1584
1585 set_current_state(TASK_INTERRUPTIBLE);
1586
1587 /* check once a second */
1588 schedule_timeout(HZ);
1589
1590 if (unlikely(ftrace_disabled))
1591 continue;
1592
1593 mutex_lock(&ftrace_sysctl_lock);
1594 mutex_lock(&ftraced_lock);
1595 if (!ftraced_suspend && !ftraced_stop &&
1596 ftrace_update_code()) {
1597 usecs = nsecs_to_usecs(ftrace_update_time);
1598 if (ftrace_update_tot_cnt > 100000) {
1599 ftrace_update_tot_cnt = 0;
1600 pr_info("hm, dftrace overflow: %lu change%s"
1601 " (%lu total) in %lu usec%s\n",
1602 ftrace_update_cnt,
1603 ftrace_update_cnt != 1 ? "s" : "",
1604 ftrace_update_tot_cnt,
1605 usecs, usecs != 1 ? "s" : "");
1606 ftrace_disabled = 1;
1607 WARN_ON_ONCE(1);
1608 }
1609 }
1610 mutex_unlock(&ftraced_lock);
1611 mutex_unlock(&ftrace_sysctl_lock);
1612
1613 ftrace_shutdown_replenish();
1614 }
1615 __set_current_state(TASK_RUNNING);
1616 return 0;
1617}
1618
1559static int __init ftrace_dynamic_init(void) 1619static int __init ftrace_dynamic_init(void)
1560{ 1620{
1561 struct task_struct *p; 1621 struct task_struct *p;
@@ -1572,7 +1632,7 @@ static int __init ftrace_dynamic_init(void)
1572 goto failed; 1632 goto failed;
1573 } 1633 }
1574 1634
1575 ret = ftrace_dyn_table_alloc(); 1635 ret = ftrace_dyn_table_alloc(NR_TO_INIT);
1576 if (ret) 1636 if (ret)
1577 goto failed; 1637 goto failed;
1578 1638
@@ -1593,6 +1653,8 @@ static int __init ftrace_dynamic_init(void)
1593} 1653}
1594 1654
1595core_initcall(ftrace_dynamic_init); 1655core_initcall(ftrace_dynamic_init);
1656#endif /* CONFIG_FTRACE_MCOUNT_RECORD */
1657
1596#else 1658#else
1597# define ftrace_startup() do { } while (0) 1659# define ftrace_startup() do { } while (0)
1598# define ftrace_shutdown() do { } while (0) 1660# define ftrace_shutdown() do { } while (0)