- Update Xen patches to 3.3-rc5 and c/s 1157.
[linux-flexiantxendom0-3.2.10.git] / drivers / xen / core / clockevents.c
1 /*
2  *      Xen clockevent functions
3  *
4  *      See arch/x86/xen/time.c for copyright and credits for derived
5  *      portions of this file.
6  *
7  * Xen clockevent implementation
8  *
9  * Xen has two clockevent implementations:
10  *
11  * The old timer_op one works with all released versions of Xen prior
12  * to version 3.0.4.  This version of the hypervisor provides a
13  * single-shot timer with nanosecond resolution.  However, sharing the
14  * same event channel is a 100Hz tick which is delivered while the
15  * vcpu is running.  We don't care about or use this tick, but it will
16  * cause the core time code to think the timer fired too soon, and
17  * will end up resetting it each time.  It could be filtered, but
18  * doing so has complications when the ktime clocksource is not yet
19  * the xen clocksource (ie, at boot time).
20  *
21  * The new vcpu_op-based timer interface allows the tick timer period
22  * to be changed or turned off.  The tick timer is not useful as a
23  * periodic timer because events are only delivered to running vcpus.
24  * The one-shot timer can report when a timeout is in the past, so
25  * set_next_event is capable of returning -ETIME when appropriate.
26  * This interface is used when available.
27  */
28 #include <linux/clockchips.h>
29 #include <linux/interrupt.h>
30 #include <linux/kernel.h>
31 #include <linux/kernel_stat.h>
32 #include <linux/math64.h>
33 #include <asm/hypervisor.h>
34 #include <xen/clock.h>
35 #include <xen/evtchn.h>
36 #include <xen/interface/vcpu.h>
37
38 #define XEN_SHIFT 22
39
40 /* Xen may fire a timer up to this many ns early */
41 #define TIMER_SLOP      100000
42 #define NS_PER_TICK     (1000000000LL / HZ)
43
44 /*
45  * Get a hypervisor absolute time.  In theory we could maintain an
46  * offset between the kernel's time and the hypervisor's time, and
47  * apply that to a kernel's absolute timeout.  Unfortunately the
48  * hypervisor and kernel times can drift even if the kernel is using
49  * the Xen clocksource, because ntp can warp the kernel's clocksource.
50  */
51 static u64 get_abs_timeout(unsigned long delta)
52 {
53         return xen_local_clock() + delta;
54 }
55
56 #if CONFIG_XEN_COMPAT <= 0x030004
57 static void timerop_set_mode(enum clock_event_mode mode,
58                              struct clock_event_device *evt)
59 {
60         switch (mode) {
61         case CLOCK_EVT_MODE_PERIODIC:
62                 WARN_ON(1); /* unsupported */
63                 break;
64
65         case CLOCK_EVT_MODE_ONESHOT:
66         case CLOCK_EVT_MODE_RESUME:
67                 break;
68
69         case CLOCK_EVT_MODE_UNUSED:
70         case CLOCK_EVT_MODE_SHUTDOWN:
71                 if (HYPERVISOR_set_timer_op(0)) /* cancel timeout */
72                         BUG();
73                 break;
74         }
75 }
76
77 static int timerop_set_next_event(unsigned long delta,
78                                   struct clock_event_device *evt)
79 {
80         WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
81
82         if (HYPERVISOR_set_timer_op(get_abs_timeout(delta)) < 0)
83                 BUG();
84
85         /*
86          * We may have missed the deadline, but there's no real way of
87          * knowing for sure.  If the event was in the past, then we'll
88          * get an immediate interrupt.
89          */
90
91         return 0;
92 }
93 #endif
94
95 static void vcpuop_set_mode(enum clock_event_mode mode,
96                             struct clock_event_device *evt)
97 {
98         switch (mode) {
99         case CLOCK_EVT_MODE_PERIODIC:
100                 WARN_ON(1); /* unsupported */
101                 break;
102
103         case CLOCK_EVT_MODE_UNUSED:
104         case CLOCK_EVT_MODE_SHUTDOWN:
105                 if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer,
106                                        smp_processor_id(), NULL))
107                         BUG();
108                 /* fall through */
109         case CLOCK_EVT_MODE_ONESHOT:
110                 if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer,
111                                        smp_processor_id(), NULL))
112                         BUG();
113                 break;
114
115         case CLOCK_EVT_MODE_RESUME:
116                 break;
117         }
118 }
119
120 static int vcpuop_set_next_event(unsigned long delta,
121                                  struct clock_event_device *evt)
122 {
123         struct vcpu_set_singleshot_timer single;
124         int ret;
125
126         WARN_ON(evt->mode != CLOCK_EVT_MODE_ONESHOT);
127
128         single.timeout_abs_ns = get_abs_timeout(delta);
129         single.flags = VCPU_SSHOTTMR_future;
130
131         ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer,
132                                  smp_processor_id(), &single);
133
134         BUG_ON(ret != 0 && ret != -ETIME);
135
136         return ret;
137 }
138
139 static DEFINE_PER_CPU(struct clock_event_device, xen_clock_event) = {
140         .name           = "xen",
141         .features       = CLOCK_EVT_FEAT_ONESHOT,
142
143         .max_delta_ns   = 0xffffffff,
144         .min_delta_ns   = TIMER_SLOP,
145
146         .mult           = 1,
147         .shift          = 0,
148         .rating         = 500,
149
150         .irq            = -1,
151 };
152
153 /* snapshots of runstate info */
154 static DEFINE_PER_CPU(u64, runnable_snapshot);
155 static DEFINE_PER_CPU(u64, offline_snapshot);
156
157 /* unused ns of stolen time */
158 static DEFINE_PER_CPU(unsigned int, residual_stolen);
159
160 static void init_missing_ticks_accounting(unsigned int cpu)
161 {
162         setup_runstate_area(cpu);
163         if (cpu == smp_processor_id()) {
164                 this_cpu_write(runnable_snapshot,
165                                this_vcpu_read(runstate.time[RUNSTATE_runnable]));
166                 this_cpu_write(offline_snapshot,
167                                this_vcpu_read(runstate.time[RUNSTATE_offline]));
168         }
169         per_cpu(residual_stolen, cpu) = 0;
170 }
171
172 static irqreturn_t timer_interrupt(int irq, void *dev_id)
173 {
174         struct clock_event_device *evt = &__get_cpu_var(xen_clock_event);
175         u64 runnable, offline;
176         s64 stolen;
177         irqreturn_t ret = IRQ_NONE;
178
179         if (evt->event_handler) {
180                 evt->event_handler(evt);
181                 ret = IRQ_HANDLED;
182         }
183
184         xen_check_wallclock_update();
185
186         runnable = this_vcpu_read(runstate.time[RUNSTATE_runnable]);
187         offline = this_vcpu_read(runstate.time[RUNSTATE_offline]);
188
189         stolen = runnable - __this_cpu_read(runnable_snapshot)
190                  + offline - __this_cpu_read(offline_snapshot)
191                  + __this_cpu_read(residual_stolen);
192
193         if (stolen >= NS_PER_TICK)
194                 account_steal_ticks(div_u64_rem(stolen, NS_PER_TICK,
195                                                 &__get_cpu_var(residual_stolen)));
196         else
197                 __this_cpu_write(residual_stolen, stolen > 0 ? stolen : 0);
198
199         __this_cpu_write(runnable_snapshot, runnable);
200         __this_cpu_write(offline_snapshot, offline);
201
202         return ret;
203 }
204
205 static struct irqaction timer_action = {
206         .handler = timer_interrupt,
207         .flags   = IRQF_DISABLED|IRQF_TIMER,
208         .name    = "timer"
209 };
210
211 void __cpuinit xen_setup_cpu_clockevents(void)
212 {
213         unsigned int cpu = smp_processor_id();
214         struct clock_event_device *evt = &per_cpu(xen_clock_event, cpu);
215
216         init_missing_ticks_accounting(cpu);
217
218         evt->cpumask = cpumask_of(cpu);
219         clockevents_register_device(evt);
220 }
221
222 #ifdef CONFIG_SMP
223 int __cpuinit local_setup_timer(unsigned int cpu)
224 {
225         struct clock_event_device *evt = &per_cpu(xen_clock_event, cpu);
226
227         BUG_ON(cpu == smp_processor_id());
228
229         evt->irq = bind_virq_to_irqaction(VIRQ_TIMER, cpu, &timer_action);
230         if (evt->irq < 0)
231                 return evt->irq;
232         BUG_ON(per_cpu(xen_clock_event.irq, 0) != evt->irq);
233
234         evt->set_mode = percpu_read(xen_clock_event.set_mode);
235         evt->set_next_event = percpu_read(xen_clock_event.set_next_event);
236
237         return 0;
238 }
239
240 void __cpuinit local_teardown_timer(unsigned int cpu)
241 {
242         struct clock_event_device *evt = &per_cpu(xen_clock_event, cpu);
243
244         BUG_ON(cpu == 0);
245         unbind_from_per_cpu_irq(evt->irq, cpu, &timer_action);
246 }
247 #endif
248
249 void xen_clockevents_resume(void)
250 {
251         unsigned int cpu;
252
253         if (percpu_read(xen_clock_event.set_mode) != vcpuop_set_mode)
254                 return;
255
256         for_each_online_cpu(cpu) {
257                 init_missing_ticks_accounting(cpu);
258                 if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, cpu, NULL))
259                         BUG();
260         }
261 }
262
263 void __init xen_clockevents_init(void)
264 {
265         unsigned int cpu = smp_processor_id();
266         struct clock_event_device *evt = &__get_cpu_var(xen_clock_event);
267
268         switch (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer,
269                                    cpu, NULL)) {
270         case 0:
271                 /*
272                  * Successfully turned off 100Hz tick, so we have the
273                  * vcpuop-based timer interface
274                  */
275                 evt->set_mode = vcpuop_set_mode;
276                 evt->set_next_event = vcpuop_set_next_event;
277                 break;
278 #if CONFIG_XEN_COMPAT <= 0x030004
279         case -ENOSYS:
280                 printk(KERN_DEBUG "Xen: using timerop interface\n");
281                 evt->set_mode = timerop_set_mode;
282                 evt->set_next_event = timerop_set_next_event;
283                 break;
284 #endif
285         default:
286                 BUG();
287         }
288
289         evt->irq = bind_virq_to_irqaction(VIRQ_TIMER, cpu, &timer_action);
290         BUG_ON(evt->irq < 0);
291
292         xen_setup_cpu_clockevents();
293 }