summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'driver/gator_main.c')
-rw-r--r--driver/gator_main.c110
1 files changed, 100 insertions, 10 deletions
diff --git a/driver/gator_main.c b/driver/gator_main.c
index ead7eae..19f51c7 100644
--- a/driver/gator_main.c
+++ b/driver/gator_main.c
@@ -8,7 +8,8 @@
8 */ 8 */
9 9
10// This version must match the gator daemon version 10// This version must match the gator daemon version
11static unsigned long gator_protocol_version = 16; 11#define PROTOCOL_VERSION 17
12static unsigned long gator_protocol_version = PROTOCOL_VERSION;
12 13
13#include <linux/slab.h> 14#include <linux/slab.h>
14#include <linux/cpu.h> 15#include <linux/cpu.h>
@@ -22,16 +23,20 @@ static unsigned long gator_protocol_version = 16;
22#include <linux/module.h> 23#include <linux/module.h>
23#include <linux/perf_event.h> 24#include <linux/perf_event.h>
24#include <linux/utsname.h> 25#include <linux/utsname.h>
26#include <linux/kthread.h>
25#include <asm/stacktrace.h> 27#include <asm/stacktrace.h>
26#include <asm/uaccess.h> 28#include <asm/uaccess.h>
27 29
28#include "gator.h" 30#include "gator.h"
29#include "gator_events.h"
30 31
31#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32) 32#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
32#error kernels prior to 2.6.32 are not supported 33#error kernels prior to 2.6.32 are not supported
33#endif 34#endif
34 35
36#if defined(MODULE) && !defined(CONFIG_MODULES)
37#error Cannot build a module against a kernel that does not support modules. To resolve, either rebuild the kernel to support modules or build gator as part of the kernel.
38#endif
39
35#if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING) 40#if !defined(CONFIG_GENERIC_TRACER) && !defined(CONFIG_TRACING)
36#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined 41#error gator requires the kernel to have CONFIG_GENERIC_TRACER or CONFIG_TRACING defined
37#endif 42#endif
@@ -44,11 +49,9 @@ static unsigned long gator_protocol_version = 16;
44#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined to support PC sampling 49#error gator requires the kernel to have CONFIG_HIGH_RES_TIMERS defined to support PC sampling
45#endif 50#endif
46 51
47#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) /* Because CONFIG_LOCAL_TIMERS was removed in 3.12 */ 52#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0) && defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
48#if defined(__arm__) && defined(CONFIG_SMP) && !defined(CONFIG_LOCAL_TIMERS)
49#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems 53#error gator requires the kernel to have CONFIG_LOCAL_TIMERS defined on SMP systems
50#endif 54#endif
51#endif
52 55
53#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT)) 56#if (GATOR_PERF_SUPPORT) && (!(GATOR_PERF_PMU_SUPPORT))
54#ifndef CONFIG_PERF_EVENTS 57#ifndef CONFIG_PERF_EVENTS
@@ -89,6 +92,7 @@ static unsigned long gator_protocol_version = 16;
89#define MESSAGE_COOKIE 1 92#define MESSAGE_COOKIE 1
90#define MESSAGE_THREAD_NAME 2 93#define MESSAGE_THREAD_NAME 2
91#define HRTIMER_CORE_NAME 3 94#define HRTIMER_CORE_NAME 3
95#define MESSAGE_LINK 4
92 96
93#define MESSAGE_GPU_START 1 97#define MESSAGE_GPU_START 1
94#define MESSAGE_GPU_STOP 2 98#define MESSAGE_GPU_STOP 2
@@ -138,6 +142,7 @@ static u64 gator_live_rate;
138 142
139static unsigned long gator_started; 143static unsigned long gator_started;
140static u64 gator_monotonic_started; 144static u64 gator_monotonic_started;
145static u64 gator_hibernate_time;
141static unsigned long gator_buffer_opened; 146static unsigned long gator_buffer_opened;
142static unsigned long gator_timer_count; 147static unsigned long gator_timer_count;
143static unsigned long gator_response_type; 148static unsigned long gator_response_type;
@@ -149,6 +154,8 @@ bool event_based_sampling;
149static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait); 154static DECLARE_WAIT_QUEUE_HEAD(gator_buffer_wait);
150static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait); 155static DECLARE_WAIT_QUEUE_HEAD(gator_annotate_wait);
151static struct timer_list gator_buffer_wake_up_timer; 156static struct timer_list gator_buffer_wake_up_timer;
157static bool gator_buffer_wake_stop;
158static struct task_struct *gator_buffer_wake_thread;
152static LIST_HEAD(gator_events); 159static LIST_HEAD(gator_events);
153 160
154static DEFINE_PER_CPU(u64, last_timestamp); 161static DEFINE_PER_CPU(u64, last_timestamp);
@@ -191,6 +198,34 @@ static DEFINE_PER_CPU(char *[NUM_GATOR_BUFS], gator_buffer);
191// The time after which the buffer should be committed for live display 198// The time after which the buffer should be committed for live display
192static DEFINE_PER_CPU(u64, gator_buffer_commit_time); 199static DEFINE_PER_CPU(u64, gator_buffer_commit_time);
193 200
201// List of all gator events - new events must be added to this list
202#define GATOR_EVENTS_LIST \
203 GATOR_EVENT(gator_events_armv6_init) \
204 GATOR_EVENT(gator_events_armv7_init) \
205 GATOR_EVENT(gator_events_block_init) \
206 GATOR_EVENT(gator_events_ccn504_init) \
207 GATOR_EVENT(gator_events_irq_init) \
208 GATOR_EVENT(gator_events_l2c310_init) \
209 GATOR_EVENT(gator_events_mali_init) \
210 GATOR_EVENT(gator_events_mali_t6xx_hw_init) \
211 GATOR_EVENT(gator_events_mali_t6xx_init) \
212 GATOR_EVENT(gator_events_meminfo_init) \
213 GATOR_EVENT(gator_events_mmapped_init) \
214 GATOR_EVENT(gator_events_net_init) \
215 GATOR_EVENT(gator_events_perf_pmu_init) \
216 GATOR_EVENT(gator_events_sched_init) \
217 GATOR_EVENT(gator_events_scorpion_init) \
218
219#define GATOR_EVENT(EVENT_INIT) __weak int EVENT_INIT(void);
220GATOR_EVENTS_LIST
221#undef GATOR_EVENT
222
223static int (*gator_events_list[])(void) = {
224#define GATOR_EVENT(EVENT_INIT) EVENT_INIT,
225GATOR_EVENTS_LIST
226#undef GATOR_EVENT
227};
228
194/****************************************************************************** 229/******************************************************************************
195 * Application Includes 230 * Application Includes
196 ******************************************************************************/ 231 ******************************************************************************/
@@ -394,6 +429,21 @@ static void gator_buffer_wake_up(unsigned long data)
394 wake_up(&gator_buffer_wait); 429 wake_up(&gator_buffer_wait);
395} 430}
396 431
432static int gator_buffer_wake_func(void *data)
433{
434 while (!gator_buffer_wake_stop) {
435 set_current_state(TASK_INTERRUPTIBLE);
436 schedule();
437 if (gator_buffer_wake_stop) {
438 break;
439 }
440
441 gator_buffer_wake_up(0);
442 }
443
444 return 0;
445}
446
397/****************************************************************************** 447/******************************************************************************
398 * Commit interface 448 * Commit interface
399 ******************************************************************************/ 449 ******************************************************************************/
@@ -519,7 +569,14 @@ static void gator_commit_buffer(int cpu, int buftype, u64 time)
519 marshal_frame(cpu, buftype); 569 marshal_frame(cpu, buftype);
520 570
521 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater 571 // had to delay scheduling work as attempting to schedule work during the context switch is illegal in kernel versions 3.5 and greater
522 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1); 572 if (per_cpu(in_scheduler_context, cpu)) {
573#ifndef CONFIG_PREEMPT_RT_FULL
574 // mod_timer can not be used in interrupt context in RT-Preempt full
575 mod_timer(&gator_buffer_wake_up_timer, jiffies + 1);
576#endif
577 } else {
578 wake_up_process(gator_buffer_wake_thread);
579 }
523} 580}
524 581
525static void buffer_check(int cpu, int buftype, u64 time) 582static void buffer_check(int cpu, int buftype, u64 time)
@@ -592,8 +649,13 @@ void gator_backtrace_handler(struct pt_regs *const regs)
592 649
593 // Collect counters 650 // Collect counters
594 if (!per_cpu(collecting, cpu)) { 651 if (!per_cpu(collecting, cpu)) {
595 collect_counters(time); 652 collect_counters(time, NULL);
596 } 653 }
654
655 // No buffer flushing occurs during sched switch for RT-Preempt full. The block counter frame will be flushed by collect_counters, but the sched buffer needs to be explicitly flushed
656#ifdef CONFIG_PREEMPT_RT_FULL
657 buffer_check(cpu, SCHED_TRACE_BUF, time);
658#endif
597} 659}
598 660
599static int gator_running; 661static int gator_running;
@@ -817,6 +879,7 @@ static struct notifier_block __refdata gator_hotcpu_notifier = {
817static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy) 879static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void *dummy)
818{ 880{
819 int cpu; 881 int cpu;
882 struct timespec ts;
820 883
821 switch (event) { 884 switch (event) {
822 case PM_HIBERNATION_PREPARE: 885 case PM_HIBERNATION_PREPARE:
@@ -827,9 +890,20 @@ static int gator_pm_notify(struct notifier_block *nb, unsigned long event, void
827 for_each_online_cpu(cpu) { 890 for_each_online_cpu(cpu) {
828 gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false); 891 gator_timer_offline_dispatch(lcpu_to_pcpu(cpu), false);
829 } 892 }
893
894 // Record the wallclock hibernate time
895 getnstimeofday(&ts);
896 gator_hibernate_time = timespec_to_ns(&ts) - gator_get_time();
830 break; 897 break;
831 case PM_POST_HIBERNATION: 898 case PM_POST_HIBERNATION:
832 case PM_POST_SUSPEND: 899 case PM_POST_SUSPEND:
900 // Adjust gator_monotonic_started for the time spent sleeping, as gator_get_time does not account for it
901 if (gator_hibernate_time > 0) {
902 getnstimeofday(&ts);
903 gator_monotonic_started += gator_hibernate_time + gator_get_time() - timespec_to_ns(&ts);
904 gator_hibernate_time = 0;
905 }
906
833 for_each_online_cpu(cpu) { 907 for_each_online_cpu(cpu) {
834 gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false); 908 gator_timer_online_dispatch(lcpu_to_pcpu(cpu), false);
835 } 909 }
@@ -904,8 +978,10 @@ int gator_events_install(struct gator_interface *interface)
904 978
905int gator_events_get_key(void) 979int gator_events_get_key(void)
906{ 980{
907 // key of zero is reserved as a timestamp 981 // key 0 is reserved as a timestamp
908 static int key = 1; 982 // key 1 is reserved as the marker for thread specific counters
983 // Odd keys are assigned by the driver, even keys by the daemon
984 static int key = 3;
909 985
910 const int ret = key; 986 const int ret = key;
911 key += 2; 987 key += 2;
@@ -918,7 +994,7 @@ static int gator_init(void)
918 994
919 calc_first_cluster_size(); 995 calc_first_cluster_size();
920 996
921 // events sources (gator_events.h, generated by gator_events.sh) 997 // events sources
922 for (i = 0; i < ARRAY_SIZE(gator_events_list); i++) 998 for (i = 0; i < ARRAY_SIZE(gator_events_list); i++)
923 if (gator_events_list[i]) 999 if (gator_events_list[i])
924 gator_events_list[i](); 1000 gator_events_list[i]();
@@ -943,6 +1019,11 @@ static int gator_start(void)
943 unsigned long cpu, i; 1019 unsigned long cpu, i;
944 struct gator_interface *gi; 1020 struct gator_interface *gi;
945 1021
1022 gator_buffer_wake_stop = false;
1023 if (IS_ERR(gator_buffer_wake_thread = kthread_run(gator_buffer_wake_func, NULL, "gator_bwake"))) {
1024 goto bwake_failure;
1025 }
1026
946 if (gator_migrate_start()) 1027 if (gator_migrate_start())
947 goto migrate_failure; 1028 goto migrate_failure;
948 1029
@@ -1013,6 +1094,9 @@ cookies_failure:
1013events_failure: 1094events_failure:
1014 gator_migrate_stop(); 1095 gator_migrate_stop();
1015migrate_failure: 1096migrate_failure:
1097 gator_buffer_wake_stop = true;
1098 wake_up_process(gator_buffer_wake_thread);
1099bwake_failure:
1016 1100
1017 return -1; 1101 return -1;
1018} 1102}
@@ -1036,6 +1120,9 @@ static void gator_stop(void)
1036 gi->stop(); 1120 gi->stop();
1037 1121
1038 gator_migrate_stop(); 1122 gator_migrate_stop();
1123
1124 gator_buffer_wake_stop = true;
1125 wake_up_process(gator_buffer_wake_thread);
1039} 1126}
1040 1127
1041/****************************************************************************** 1128/******************************************************************************
@@ -1440,3 +1527,6 @@ module_exit(gator_module_exit);
1440MODULE_LICENSE("GPL"); 1527MODULE_LICENSE("GPL");
1441MODULE_AUTHOR("ARM Ltd"); 1528MODULE_AUTHOR("ARM Ltd");
1442MODULE_DESCRIPTION("Gator system profiler"); 1529MODULE_DESCRIPTION("Gator system profiler");
1530#define STRIFY2(ARG) #ARG
1531#define STRIFY(ARG) STRIFY2(ARG)
1532MODULE_VERSION(STRIFY(PROTOCOL_VERSION));