~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to kernel/time/tsc-sync.c

  • Committer: Bazaar Package Importer
  • Author(s): Paolo Pisati
  • Date: 2011-06-29 15:23:51 UTC
  • mfrom: (26.1.1 natty-proposed)
  • Revision ID: james.westby@ubuntu.com-20110629152351-xs96tm303d95rpbk
Tags: 3.0.0-1200.2
* Rebased against 3.0.0-6.7
* BSP from TI based on 3.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * kernel/time/tsc-sync.c
3
 
 *
4
 
 * Test TSC synchronization
5
 
 *
6
 
 * marks the tsc as unstable _and_ keep a simple "_tsc_is_sync" variable, which
7
 
 * is fast to read when a simple test must determine which clock source to use
8
 
 * for kernel tracing.
9
 
 *
10
 
 * - CPU init :
11
 
 *
12
 
 * We check whether all boot CPUs have their TSC's synchronized,
13
 
 * print a warning if not and turn off the TSC clock-source.
14
 
 *
15
 
 * Only two CPUs may participate - they can enter in any order.
16
 
 * ( The serial nature of the boot logic and the CPU hotplug lock
17
 
 *   protects against more than 2 CPUs entering this code.
18
 
 *
19
 
 * - When CPUs are up :
20
 
 *
21
 
 * TSC synchronicity of all CPUs can be checked later at run-time by calling
22
 
 * test_tsc_synchronization().
23
 
 *
24
 
 * Copyright 2007, 2008
25
 
 *    Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
26
 
 */
27
 
#include <linux/module.h>
28
 
#include <linux/timer.h>
29
 
#include <linux/timex.h>
30
 
#include <linux/jiffies.h>
31
 
#include <linux/trace-clock.h>
32
 
#include <linux/cpu.h>
33
 
#include <linux/kthread.h>
34
 
#include <linux/mutex.h>
35
 
#include <linux/cpu.h>
36
 
 
37
 
#define MAX_CYCLES_DELTA 3000ULL
38
 
 
39
 
/*
40
 
 * Number of loops to take care of MCE, NMIs, SMIs.
41
 
 */
42
 
#define NR_LOOPS        200
43
 
 
44
 
static DEFINE_MUTEX(tscsync_mutex);
45
 
 
46
 
struct sync_data {
47
 
        int nr_waits;
48
 
        int wait_sync;
49
 
        cycles_t tsc_count;
50
 
} ____cacheline_aligned;
51
 
 
52
 
/* 0 is master, 1 is slave */
53
 
static struct sync_data sync_data[2] = {
54
 
        [0 ... 1] = {
55
 
                .nr_waits = 3 * NR_LOOPS + 1,
56
 
                .wait_sync = 3 * NR_LOOPS + 1,
57
 
        },
58
 
};
59
 
 
60
 
int _tsc_is_sync = 1;
61
 
EXPORT_SYMBOL(_tsc_is_sync);
62
 
 
63
 
static int force_tsc_sync;
64
 
static cycles_t slave_offset;
65
 
static int slave_offset_ready;  /* for 32-bits architectures */
66
 
 
67
 
static int __init force_tsc_sync_setup(char *str)
68
 
{
69
 
        force_tsc_sync = simple_strtoul(str, NULL, 0);
70
 
        return 1;
71
 
}
72
 
__setup("force_tsc_sync=", force_tsc_sync_setup);
73
 
 
74
 
/*
75
 
 * Mark it noinline so we make sure it is not unrolled.
76
 
 * Wait until value is reached.
77
 
 */
78
 
static noinline void tsc_barrier(long this_cpu)
79
 
{
80
 
        sync_core();
81
 
        sync_data[this_cpu].wait_sync--;
82
 
        smp_mb();       /* order master/slave sync_data read/write */
83
 
        while (unlikely(sync_data[1 - this_cpu].wait_sync >=
84
 
                        sync_data[this_cpu].nr_waits))
85
 
                barrier();      /*
86
 
                                 * barrier is used because faster and
87
 
                                 * more predictable than cpu_idle().
88
 
                                 */
89
 
        smp_mb();       /* order master/slave sync_data read/write */
90
 
        sync_data[this_cpu].nr_waits--;
91
 
        get_cycles_barrier();
92
 
        sync_data[this_cpu].tsc_count = get_cycles();
93
 
        get_cycles_barrier();
94
 
}
95
 
 
96
 
/*
97
 
 * Worker thread called on each CPU.
98
 
 * First wait with interrupts enabled, then wait with interrupt disabled,
99
 
 * for precision. We are already bound to one CPU.
100
 
 * this_cpu 0 : master
101
 
 * this_cpu 1 : slave
102
 
 */
103
 
static void test_sync(void *arg)
104
 
{
105
 
        long this_cpu = (long)arg;
106
 
        unsigned long flags;
107
 
 
108
 
        local_irq_save(flags);
109
 
        /* Make sure the instructions are in I-CACHE */
110
 
        tsc_barrier(this_cpu);
111
 
        tsc_barrier(this_cpu);
112
 
        sync_data[this_cpu].wait_sync--;
113
 
        smp_mb();       /* order master/slave sync_data read/write */
114
 
        while (unlikely(sync_data[1 - this_cpu].wait_sync >=
115
 
                        sync_data[this_cpu].nr_waits))
116
 
                barrier();      /*
117
 
                                 * barrier is used because faster and
118
 
                                 * more predictable than cpu_idle().
119
 
                                 */
120
 
        smp_mb();       /* order master/slave sync_data read/write */
121
 
        sync_data[this_cpu].nr_waits--;
122
 
        /*
123
 
         * Here, only the master will wait for the slave to reach this barrier.
124
 
         * This makes sure that the master, which holds the mutex and will reset
125
 
         * the barriers, waits for the slave to stop using the barrier values
126
 
         * before it continues. This is only done at the complete end of all the
127
 
         * loops. This is why there is a + 1 in original wait_sync value.
128
 
         */
129
 
        if (sync_data[this_cpu].nr_waits == 1)
130
 
                sync_data[this_cpu].wait_sync--;
131
 
        local_irq_restore(flags);
132
 
}
133
 
 
134
 
/*
135
 
 * Each CPU (master and target) must decrement the wait_sync value twice (one
136
 
 * for priming in cache), and also once after the get_cycles. After all the
137
 
 * loops, one last synchronization is required to make sure the master waits
138
 
 * for the slave before resetting the barriers.
139
 
 */
140
 
static void reset_barriers(void)
141
 
{
142
 
        int i;
143
 
 
144
 
        /*
145
 
         * Wait until slave is done so that we don't overwrite
146
 
         * wait_end_sync prematurely.
147
 
         */
148
 
        smp_mb();       /* order master/slave sync_data read/write */
149
 
        while (unlikely(sync_data[1].wait_sync >= sync_data[0].nr_waits))
150
 
                barrier();      /*
151
 
                                 * barrier is used because faster and
152
 
                                 * more predictable than cpu_idle().
153
 
                                 */
154
 
        smp_mb();       /* order master/slave sync_data read/write */
155
 
 
156
 
        for (i = 0; i < 2; i++) {
157
 
                WARN_ON(sync_data[i].wait_sync != 0);
158
 
                WARN_ON(sync_data[i].nr_waits != 1);
159
 
                sync_data[i].wait_sync = 3 * NR_LOOPS + 1;
160
 
                sync_data[i].nr_waits = 3 * NR_LOOPS + 1;
161
 
        }
162
 
}
163
 
 
164
 
/*
165
 
 * Do loops (making sure no unexpected event changes the timing), keep the best
166
 
 * one. The result of each loop is the highest tsc delta between the master CPU
167
 
 * and the slaves. Stop CPU hotplug when this code is executed to make sure we
168
 
 * are concurrency-safe wrt CPU hotplug also using this code.  Test TSC
169
 
 * synchronization even if we already "know" CPUs were not synchronized. This
170
 
 * can be used as a test to check if, for some reason, the CPUs eventually got
171
 
 * in sync after a CPU has been unplugged. This code is kept separate from the
172
 
 * CPU hotplug code because the slave CPU executes in an IPI, which we want to
173
 
 * keep as short as possible (this is happening while the system is running).
174
 
 * Therefore, we do not send a single IPI for all the test loops, but rather
175
 
 * send one IPI per loop.
176
 
 */
177
 
int test_tsc_synchronization(void)
178
 
{
179
 
        long cpu, master;
180
 
        cycles_t max_diff = 0, diff, best_loop, worse_loop = 0;
181
 
        int i;
182
 
 
183
 
        mutex_lock(&tscsync_mutex);
184
 
        get_online_cpus();
185
 
 
186
 
        printk(KERN_INFO
187
 
               "checking TSC synchronization across all online CPUs:");
188
 
 
189
 
        preempt_disable();
190
 
        master = smp_processor_id();
191
 
        for_each_online_cpu(cpu) {
192
 
                if (master == cpu)
193
 
                        continue;
194
 
                best_loop = (cycles_t)ULLONG_MAX;
195
 
                for (i = 0; i < NR_LOOPS; i++) {
196
 
                        smp_call_function_single(cpu, test_sync,
197
 
                                                (void *)1UL, 0);
198
 
                        test_sync((void *)0UL);
199
 
                        diff = abs(sync_data[1].tsc_count
200
 
                                - sync_data[0].tsc_count);
201
 
                        best_loop = min(best_loop, diff);
202
 
                        worse_loop = max(worse_loop, diff);
203
 
                }
204
 
                reset_barriers();
205
 
                max_diff = max(best_loop, max_diff);
206
 
        }
207
 
        preempt_enable();
208
 
        if (max_diff >= MAX_CYCLES_DELTA) {
209
 
                printk(KERN_WARNING
210
 
                        "Measured %llu cycles TSC offset between CPUs,"
211
 
                        " turning off TSC clock.\n", (u64)max_diff);
212
 
                mark_tsc_unstable("check_tsc_sync_source failed");
213
 
                _tsc_is_sync = 0;
214
 
        } else {
215
 
                printk(" passed.\n");
216
 
        }
217
 
        put_online_cpus();
218
 
        mutex_unlock(&tscsync_mutex);
219
 
        return max_diff < MAX_CYCLES_DELTA;
220
 
}
221
 
EXPORT_SYMBOL_GPL(test_tsc_synchronization);
222
 
 
223
 
/*
224
 
 * Test synchronicity of a single core when it is hotplugged.
225
 
 * Source CPU calls into this - waits for the freshly booted target CPU to
226
 
 * arrive and then start the measurement:
227
 
 */
228
 
void __cpuinit check_tsc_sync_source(int cpu)
229
 
{
230
 
        cycles_t diff, abs_diff,
231
 
                 best_loop = (cycles_t)ULLONG_MAX, worse_loop = 0;
232
 
        int i;
233
 
 
234
 
        /*
235
 
         * No need to check if we already know that the TSC is not synchronized:
236
 
         */
237
 
        if (!force_tsc_sync && unsynchronized_tsc()) {
238
 
                /*
239
 
                 * Make sure we mark _tsc_is_sync to 0 if the TSC is found
240
 
                 * to be unsynchronized for other causes than non-synchronized
241
 
                 * TSCs across CPUs.
242
 
                 */
243
 
                _tsc_is_sync = 0;
244
 
                set_trace_clock_is_sync(0);
245
 
                return;
246
 
        }
247
 
 
248
 
        printk(KERN_INFO "checking TSC synchronization [CPU#%d -> CPU#%d]:",
249
 
                          smp_processor_id(), cpu);
250
 
 
251
 
        for (i = 0; i < NR_LOOPS; i++) {
252
 
                test_sync((void *)0UL);
253
 
                diff = sync_data[1].tsc_count - sync_data[0].tsc_count;
254
 
                abs_diff = abs(diff);
255
 
                best_loop = min(best_loop, abs_diff);
256
 
                worse_loop = max(worse_loop, abs_diff);
257
 
                if (force_tsc_sync && best_loop == abs_diff)
258
 
                        slave_offset = diff;
259
 
        }
260
 
        reset_barriers();
261
 
 
262
 
        if (!force_tsc_sync && best_loop >= MAX_CYCLES_DELTA) {
263
 
                printk(" failed.\n");
264
 
                printk(KERN_WARNING
265
 
                        "Measured %llu cycles TSC offset between CPUs,"
266
 
                        " turning off TSC clock.\n", (u64)best_loop);
267
 
                mark_tsc_unstable("check_tsc_sync_source failed");
268
 
                _tsc_is_sync = 0;
269
 
                set_trace_clock_is_sync(0);
270
 
        } else {
271
 
                printk(" %s.\n", !force_tsc_sync ? "passed" : "forced");
272
 
        }
273
 
        if (force_tsc_sync) {
274
 
                /* order slave_offset and slave_offset_ready writes */
275
 
                smp_wmb();
276
 
                slave_offset_ready = 1;
277
 
        }
278
 
}
279
 
 
280
 
/*
281
 
 * Freshly booted CPUs call into this:
282
 
 */
283
 
void __cpuinit check_tsc_sync_target(void)
284
 
{
285
 
        int i;
286
 
 
287
 
        if (!force_tsc_sync && unsynchronized_tsc())
288
 
                return;
289
 
 
290
 
        for (i = 0; i < NR_LOOPS; i++)
291
 
                test_sync((void *)1UL);
292
 
 
293
 
        /*
294
 
         * Force slave synchronization if requested.
295
 
         */
296
 
        if (force_tsc_sync) {
297
 
                unsigned long flags;
298
 
                cycles_t new_tsc;
299
 
 
300
 
                while (!slave_offset_ready)
301
 
                        cpu_relax();
302
 
                /* order slave_offset and slave_offset_ready reads */
303
 
                smp_rmb();
304
 
                local_irq_save(flags);
305
 
                /*
306
 
                 * slave_offset is read when master has finished writing to it,
307
 
                 * and is protected by cpu hotplug serialization.
308
 
                 */
309
 
                new_tsc = get_cycles() - slave_offset;
310
 
                write_tsc((u32)new_tsc, (u32)((u64)new_tsc >> 32));
311
 
                local_irq_restore(flags);
312
 
        }
313
 
}