diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 16:22:30 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-11 16:22:30 -0400 |
commit | b9356c53ba2f593081e5aa45eb67adcce243d1c0 (patch) | |
tree | debf2b72d5241dbaa5b4f2088feb0a2584388792 /drivers | |
parent | d90a7e86401ffea2163a4337f3a47f3909c4e255 (diff) | |
parent | 4680e64a88c4ce2c4e736dade99233e3def13fa7 (diff) |
Merge branch 'oprofile-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'oprofile-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (55 commits)
arch/x86/oprofile/op_model_amd.c: fix op_amd_handle_ibs() return type
Revert "x86: oprofile/op_model_amd.c set return values for op_amd_handle_ibs()"
x86/oprofile: Small coding style fixes
x86/oprofile: Add counter reservation check for virtual counters
x86/oprofile: Implement op_x86_virt_to_phys()
oprofile: Adding switch counter to oprofile statistic variables
x86/oprofile: Implement mux_clone()
x86/oprofile: Enable multiplexing only if the model supports it
x86/oprofile: Add function has_mux() to check multiplexing support
x86/oprofile: Modify initialization of num_virt_counters
x86/oprofile: Remove unused num_virt_controls from struct op_x86_model_spec
x86/oprofile: Remove const qualifier from struct op_x86_model_spec
x86/oprofile: Moving nmi_cpu_switch() in nmi_int.c
x86/oprofile: Moving nmi_cpu_save/restore_mpx_registers() in nmi_int.c
x86/oprofile: Moving nmi_setup_cpu_mux() in nmi_int.c
x86/oprofile: Implement multiplexing setup/shutdown functions
oprofile: Grouping multiplexing code in op_model_amd.c
oprofile: Introduce op_x86_phys_to_virt()
oprofile: Grouping multiplexing code in oprof.c
oprofile: Remove oprofile_multiplexing_init()
...
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/oprofile/cpu_buffer.c | 16 | ||||
-rw-r--r-- | drivers/oprofile/oprof.c | 71 | ||||
-rw-r--r-- | drivers/oprofile/oprof.h | 3 | ||||
-rw-r--r-- | drivers/oprofile/oprofile_files.c | 46 | ||||
-rw-r--r-- | drivers/oprofile/oprofile_stats.c | 5 | ||||
-rw-r--r-- | drivers/oprofile/oprofile_stats.h | 1 |
6 files changed, 140 insertions, 2 deletions
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 242257b19441..a7aae24f2889 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
@@ -21,7 +21,6 @@ | |||
21 | 21 | ||
22 | #include <linux/sched.h> | 22 | #include <linux/sched.h> |
23 | #include <linux/oprofile.h> | 23 | #include <linux/oprofile.h> |
24 | #include <linux/vmalloc.h> | ||
25 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
26 | 25 | ||
27 | #include "event_buffer.h" | 26 | #include "event_buffer.h" |
@@ -407,6 +406,21 @@ int oprofile_add_data(struct op_entry *entry, unsigned long val) | |||
407 | return op_cpu_buffer_add_data(entry, val); | 406 | return op_cpu_buffer_add_data(entry, val); |
408 | } | 407 | } |
409 | 408 | ||
409 | int oprofile_add_data64(struct op_entry *entry, u64 val) | ||
410 | { | ||
411 | if (!entry->event) | ||
412 | return 0; | ||
413 | if (op_cpu_buffer_get_size(entry) < 2) | ||
414 | /* | ||
415 | * the function returns 0 to indicate a too small | ||
416 | * buffer, even if there is some space left | ||
417 | */ | ||
418 | return 0; | ||
419 | if (!op_cpu_buffer_add_data(entry, (u32)val)) | ||
420 | return 0; | ||
421 | return op_cpu_buffer_add_data(entry, (u32)(val >> 32)); | ||
422 | } | ||
423 | |||
410 | int oprofile_write_commit(struct op_entry *entry) | 424 | int oprofile_write_commit(struct op_entry *entry) |
411 | { | 425 | { |
412 | if (!entry->event) | 426 | if (!entry->event) |
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index 3cffce90f82a..dc8a0428260d 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c | |||
@@ -12,6 +12,8 @@ | |||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/oprofile.h> | 13 | #include <linux/oprofile.h> |
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/workqueue.h> | ||
16 | #include <linux/time.h> | ||
15 | #include <asm/mutex.h> | 17 | #include <asm/mutex.h> |
16 | 18 | ||
17 | #include "oprof.h" | 19 | #include "oprof.h" |
@@ -87,6 +89,69 @@ out: | |||
87 | return err; | 89 | return err; |
88 | } | 90 | } |
89 | 91 | ||
92 | #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX | ||
93 | |||
94 | static void switch_worker(struct work_struct *work); | ||
95 | static DECLARE_DELAYED_WORK(switch_work, switch_worker); | ||
96 | |||
97 | static void start_switch_worker(void) | ||
98 | { | ||
99 | if (oprofile_ops.switch_events) | ||
100 | schedule_delayed_work(&switch_work, oprofile_time_slice); | ||
101 | } | ||
102 | |||
103 | static void stop_switch_worker(void) | ||
104 | { | ||
105 | cancel_delayed_work_sync(&switch_work); | ||
106 | } | ||
107 | |||
108 | static void switch_worker(struct work_struct *work) | ||
109 | { | ||
110 | if (oprofile_ops.switch_events()) | ||
111 | return; | ||
112 | |||
113 | atomic_inc(&oprofile_stats.multiplex_counter); | ||
114 | start_switch_worker(); | ||
115 | } | ||
116 | |||
117 | /* User inputs in ms, converts to jiffies */ | ||
118 | int oprofile_set_timeout(unsigned long val_msec) | ||
119 | { | ||
120 | int err = 0; | ||
121 | unsigned long time_slice; | ||
122 | |||
123 | mutex_lock(&start_mutex); | ||
124 | |||
125 | if (oprofile_started) { | ||
126 | err = -EBUSY; | ||
127 | goto out; | ||
128 | } | ||
129 | |||
130 | if (!oprofile_ops.switch_events) { | ||
131 | err = -EINVAL; | ||
132 | goto out; | ||
133 | } | ||
134 | |||
135 | time_slice = msecs_to_jiffies(val_msec); | ||
136 | if (time_slice == MAX_JIFFY_OFFSET) { | ||
137 | err = -EINVAL; | ||
138 | goto out; | ||
139 | } | ||
140 | |||
141 | oprofile_time_slice = time_slice; | ||
142 | |||
143 | out: | ||
144 | mutex_unlock(&start_mutex); | ||
145 | return err; | ||
146 | |||
147 | } | ||
148 | |||
149 | #else | ||
150 | |||
151 | static inline void start_switch_worker(void) { } | ||
152 | static inline void stop_switch_worker(void) { } | ||
153 | |||
154 | #endif | ||
90 | 155 | ||
91 | /* Actually start profiling (echo 1>/dev/oprofile/enable) */ | 156 | /* Actually start profiling (echo 1>/dev/oprofile/enable) */ |
92 | int oprofile_start(void) | 157 | int oprofile_start(void) |
@@ -108,6 +173,8 @@ int oprofile_start(void) | |||
108 | if ((err = oprofile_ops.start())) | 173 | if ((err = oprofile_ops.start())) |
109 | goto out; | 174 | goto out; |
110 | 175 | ||
176 | start_switch_worker(); | ||
177 | |||
111 | oprofile_started = 1; | 178 | oprofile_started = 1; |
112 | out: | 179 | out: |
113 | mutex_unlock(&start_mutex); | 180 | mutex_unlock(&start_mutex); |
@@ -123,6 +190,9 @@ void oprofile_stop(void) | |||
123 | goto out; | 190 | goto out; |
124 | oprofile_ops.stop(); | 191 | oprofile_ops.stop(); |
125 | oprofile_started = 0; | 192 | oprofile_started = 0; |
193 | |||
194 | stop_switch_worker(); | ||
195 | |||
126 | /* wake up the daemon to read what remains */ | 196 | /* wake up the daemon to read what remains */ |
127 | wake_up_buffer_waiter(); | 197 | wake_up_buffer_waiter(); |
128 | out: | 198 | out: |
@@ -155,7 +225,6 @@ post_sync: | |||
155 | mutex_unlock(&start_mutex); | 225 | mutex_unlock(&start_mutex); |
156 | } | 226 | } |
157 | 227 | ||
158 | |||
159 | int oprofile_set_backtrace(unsigned long val) | 228 | int oprofile_set_backtrace(unsigned long val) |
160 | { | 229 | { |
161 | int err = 0; | 230 | int err = 0; |
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index c288d3c24b50..cb92f5c98c1a 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h | |||
@@ -24,6 +24,8 @@ struct oprofile_operations; | |||
24 | extern unsigned long oprofile_buffer_size; | 24 | extern unsigned long oprofile_buffer_size; |
25 | extern unsigned long oprofile_cpu_buffer_size; | 25 | extern unsigned long oprofile_cpu_buffer_size; |
26 | extern unsigned long oprofile_buffer_watershed; | 26 | extern unsigned long oprofile_buffer_watershed; |
27 | extern unsigned long oprofile_time_slice; | ||
28 | |||
27 | extern struct oprofile_operations oprofile_ops; | 29 | extern struct oprofile_operations oprofile_ops; |
28 | extern unsigned long oprofile_started; | 30 | extern unsigned long oprofile_started; |
29 | extern unsigned long oprofile_backtrace_depth; | 31 | extern unsigned long oprofile_backtrace_depth; |
@@ -35,5 +37,6 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root); | |||
35 | void oprofile_timer_init(struct oprofile_operations *ops); | 37 | void oprofile_timer_init(struct oprofile_operations *ops); |
36 | 38 | ||
37 | int oprofile_set_backtrace(unsigned long depth); | 39 | int oprofile_set_backtrace(unsigned long depth); |
40 | int oprofile_set_timeout(unsigned long time); | ||
38 | 41 | ||
39 | #endif /* OPROF_H */ | 42 | #endif /* OPROF_H */ |
diff --git a/drivers/oprofile/oprofile_files.c b/drivers/oprofile/oprofile_files.c index 5d36ffc30dd5..bbd7516e0869 100644 --- a/drivers/oprofile/oprofile_files.c +++ b/drivers/oprofile/oprofile_files.c | |||
@@ -9,6 +9,7 @@ | |||
9 | 9 | ||
10 | #include <linux/fs.h> | 10 | #include <linux/fs.h> |
11 | #include <linux/oprofile.h> | 11 | #include <linux/oprofile.h> |
12 | #include <linux/jiffies.h> | ||
12 | 13 | ||
13 | #include "event_buffer.h" | 14 | #include "event_buffer.h" |
14 | #include "oprofile_stats.h" | 15 | #include "oprofile_stats.h" |
@@ -17,10 +18,51 @@ | |||
17 | #define BUFFER_SIZE_DEFAULT 131072 | 18 | #define BUFFER_SIZE_DEFAULT 131072 |
18 | #define CPU_BUFFER_SIZE_DEFAULT 8192 | 19 | #define CPU_BUFFER_SIZE_DEFAULT 8192 |
19 | #define BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */ | 20 | #define BUFFER_WATERSHED_DEFAULT 32768 /* FIXME: tune */ |
21 | #define TIME_SLICE_DEFAULT 1 | ||
20 | 22 | ||
21 | unsigned long oprofile_buffer_size; | 23 | unsigned long oprofile_buffer_size; |
22 | unsigned long oprofile_cpu_buffer_size; | 24 | unsigned long oprofile_cpu_buffer_size; |
23 | unsigned long oprofile_buffer_watershed; | 25 | unsigned long oprofile_buffer_watershed; |
26 | unsigned long oprofile_time_slice; | ||
27 | |||
28 | #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX | ||
29 | |||
30 | static ssize_t timeout_read(struct file *file, char __user *buf, | ||
31 | size_t count, loff_t *offset) | ||
32 | { | ||
33 | return oprofilefs_ulong_to_user(jiffies_to_msecs(oprofile_time_slice), | ||
34 | buf, count, offset); | ||
35 | } | ||
36 | |||
37 | |||
38 | static ssize_t timeout_write(struct file *file, char const __user *buf, | ||
39 | size_t count, loff_t *offset) | ||
40 | { | ||
41 | unsigned long val; | ||
42 | int retval; | ||
43 | |||
44 | if (*offset) | ||
45 | return -EINVAL; | ||
46 | |||
47 | retval = oprofilefs_ulong_from_user(&val, buf, count); | ||
48 | if (retval) | ||
49 | return retval; | ||
50 | |||
51 | retval = oprofile_set_timeout(val); | ||
52 | |||
53 | if (retval) | ||
54 | return retval; | ||
55 | return count; | ||
56 | } | ||
57 | |||
58 | |||
59 | static const struct file_operations timeout_fops = { | ||
60 | .read = timeout_read, | ||
61 | .write = timeout_write, | ||
62 | }; | ||
63 | |||
64 | #endif | ||
65 | |||
24 | 66 | ||
25 | static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset) | 67 | static ssize_t depth_read(struct file *file, char __user *buf, size_t count, loff_t *offset) |
26 | { | 68 | { |
@@ -129,6 +171,7 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root) | |||
129 | oprofile_buffer_size = BUFFER_SIZE_DEFAULT; | 171 | oprofile_buffer_size = BUFFER_SIZE_DEFAULT; |
130 | oprofile_cpu_buffer_size = CPU_BUFFER_SIZE_DEFAULT; | 172 | oprofile_cpu_buffer_size = CPU_BUFFER_SIZE_DEFAULT; |
131 | oprofile_buffer_watershed = BUFFER_WATERSHED_DEFAULT; | 173 | oprofile_buffer_watershed = BUFFER_WATERSHED_DEFAULT; |
174 | oprofile_time_slice = msecs_to_jiffies(TIME_SLICE_DEFAULT); | ||
132 | 175 | ||
133 | oprofilefs_create_file(sb, root, "enable", &enable_fops); | 176 | oprofilefs_create_file(sb, root, "enable", &enable_fops); |
134 | oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); | 177 | oprofilefs_create_file_perm(sb, root, "dump", &dump_fops, 0666); |
@@ -139,6 +182,9 @@ void oprofile_create_files(struct super_block *sb, struct dentry *root) | |||
139 | oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops); | 182 | oprofilefs_create_file(sb, root, "cpu_type", &cpu_type_fops); |
140 | oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops); | 183 | oprofilefs_create_file(sb, root, "backtrace_depth", &depth_fops); |
141 | oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops); | 184 | oprofilefs_create_file(sb, root, "pointer_size", &pointer_size_fops); |
185 | #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX | ||
186 | oprofilefs_create_file(sb, root, "time_slice", &timeout_fops); | ||
187 | #endif | ||
142 | oprofile_create_stats_files(sb, root); | 188 | oprofile_create_stats_files(sb, root); |
143 | if (oprofile_ops.create_files) | 189 | if (oprofile_ops.create_files) |
144 | oprofile_ops.create_files(sb, root); | 190 | oprofile_ops.create_files(sb, root); |
diff --git a/drivers/oprofile/oprofile_stats.c b/drivers/oprofile/oprofile_stats.c index 3c2270a8300c..61689e814d46 100644 --- a/drivers/oprofile/oprofile_stats.c +++ b/drivers/oprofile/oprofile_stats.c | |||
@@ -34,6 +34,7 @@ void oprofile_reset_stats(void) | |||
34 | atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); | 34 | atomic_set(&oprofile_stats.sample_lost_no_mapping, 0); |
35 | atomic_set(&oprofile_stats.event_lost_overflow, 0); | 35 | atomic_set(&oprofile_stats.event_lost_overflow, 0); |
36 | atomic_set(&oprofile_stats.bt_lost_no_mapping, 0); | 36 | atomic_set(&oprofile_stats.bt_lost_no_mapping, 0); |
37 | atomic_set(&oprofile_stats.multiplex_counter, 0); | ||
37 | } | 38 | } |
38 | 39 | ||
39 | 40 | ||
@@ -76,4 +77,8 @@ void oprofile_create_stats_files(struct super_block *sb, struct dentry *root) | |||
76 | &oprofile_stats.event_lost_overflow); | 77 | &oprofile_stats.event_lost_overflow); |
77 | oprofilefs_create_ro_atomic(sb, dir, "bt_lost_no_mapping", | 78 | oprofilefs_create_ro_atomic(sb, dir, "bt_lost_no_mapping", |
78 | &oprofile_stats.bt_lost_no_mapping); | 79 | &oprofile_stats.bt_lost_no_mapping); |
80 | #ifdef CONFIG_OPROFILE_EVENT_MULTIPLEX | ||
81 | oprofilefs_create_ro_atomic(sb, dir, "multiplex_counter", | ||
82 | &oprofile_stats.multiplex_counter); | ||
83 | #endif | ||
79 | } | 84 | } |
diff --git a/drivers/oprofile/oprofile_stats.h b/drivers/oprofile/oprofile_stats.h index 3da0d08dc1f9..0b54e46c3c14 100644 --- a/drivers/oprofile/oprofile_stats.h +++ b/drivers/oprofile/oprofile_stats.h | |||
@@ -17,6 +17,7 @@ struct oprofile_stat_struct { | |||
17 | atomic_t sample_lost_no_mapping; | 17 | atomic_t sample_lost_no_mapping; |
18 | atomic_t bt_lost_no_mapping; | 18 | atomic_t bt_lost_no_mapping; |
19 | atomic_t event_lost_overflow; | 19 | atomic_t event_lost_overflow; |
20 | atomic_t multiplex_counter; | ||
20 | }; | 21 | }; |
21 | 22 | ||
22 | extern struct oprofile_stat_struct oprofile_stats; | 23 | extern struct oprofile_stat_struct oprofile_stats; |