1 /*
2 * xen/arch/arm/time.c
3 *
4 * Time and timer support, using the ARM Generic Timer interfaces
5 *
6 * Tim Deegan <tim@xen.org>
7 * Copyright (c) 2011 Citrix Systems.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20 #include <xen/console.h>
21 #include <xen/device_tree.h>
22 #include <xen/init.h>
23 #include <xen/irq.h>
24 #include <xen/lib.h>
25 #include <xen/mm.h>
26 #include <xen/softirq.h>
27 #include <xen/sched.h>
28 #include <xen/time.h>
29 #include <xen/sched.h>
30 #include <xen/event.h>
31 #include <xen/acpi.h>
32 #include <xen/cpu.h>
33 #include <xen/notifier.h>
34 #include <asm/system.h>
35 #include <asm/time.h>
36 #include <asm/vgic.h>
37 #include <asm/cpufeature.h>
38 #include <asm/platform.h>
39
40 uint64_t __read_mostly boot_count;
41
42 /* For fine-grained timekeeping, we use the ARM "Generic Timer", a
43 * register-mapped time source in the SoC. */
44 unsigned long __read_mostly cpu_khz; /* CPU clock frequency in kHz. */
45
46 uint32_t __read_mostly timer_dt_clock_frequency;
47
48 static unsigned int timer_irq[MAX_TIMER_PPI];
49
timer_get_irq(enum timer_ppi ppi)50 unsigned int timer_get_irq(enum timer_ppi ppi)
51 {
52 ASSERT(ppi >= TIMER_PHYS_SECURE_PPI && ppi < MAX_TIMER_PPI);
53
54 return timer_irq[ppi];
55 }
56
ticks_to_ns(uint64_t ticks)57 /*static inline*/ s_time_t ticks_to_ns(uint64_t ticks)
58 {
59 return muldiv64(ticks, SECONDS(1), 1000 * cpu_khz);
60 }
61
ns_to_ticks(s_time_t ns)62 /*static inline*/ uint64_t ns_to_ticks(s_time_t ns)
63 {
64 return muldiv64(ns, 1000 * cpu_khz, SECONDS(1));
65 }
66
67 static __initdata struct dt_device_node *timer;
68
69 #ifdef CONFIG_ACPI
acpi_get_timer_irq_type(u32 flags)70 static u32 __init acpi_get_timer_irq_type(u32 flags)
71 {
72 return (flags & ACPI_GTDT_INTERRUPT_MODE) ? IRQ_TYPE_EDGE_BOTH
73 : IRQ_TYPE_LEVEL_MASK;
74 }
75
76 /* Initialize per-processor generic timer */
arch_timer_acpi_init(struct acpi_table_header * header)77 static int __init arch_timer_acpi_init(struct acpi_table_header *header)
78 {
79 u32 irq_type;
80 struct acpi_table_gtdt *gtdt;
81
82 gtdt = container_of(header, struct acpi_table_gtdt, header);
83
84 /* Initialize all the generic timer IRQ variable from GTDT table */
85 irq_type = acpi_get_timer_irq_type(gtdt->non_secure_el1_flags);
86 irq_set_type(gtdt->non_secure_el1_interrupt, irq_type);
87 timer_irq[TIMER_PHYS_NONSECURE_PPI] = gtdt->non_secure_el1_interrupt;
88
89 irq_type = acpi_get_timer_irq_type(gtdt->secure_el1_flags);
90 irq_set_type(gtdt->secure_el1_interrupt, irq_type);
91 timer_irq[TIMER_PHYS_SECURE_PPI] = gtdt->secure_el1_interrupt;
92
93 irq_type = acpi_get_timer_irq_type(gtdt->virtual_timer_flags);
94 irq_set_type(gtdt->virtual_timer_interrupt, irq_type);
95 timer_irq[TIMER_VIRT_PPI] = gtdt->virtual_timer_interrupt;
96
97 irq_type = acpi_get_timer_irq_type(gtdt->non_secure_el2_flags);
98 irq_set_type(gtdt->non_secure_el2_interrupt, irq_type);
99 timer_irq[TIMER_HYP_PPI] = gtdt->non_secure_el2_interrupt;
100
101 return 0;
102 }
103
preinit_acpi_xen_time(void)104 static void __init preinit_acpi_xen_time(void)
105 {
106 acpi_table_parse(ACPI_SIG_GTDT, arch_timer_acpi_init);
107 }
108 #else
preinit_acpi_xen_time(void)109 static void __init preinit_acpi_xen_time(void) { }
110 #endif
111
112 /* Set up the timer on the boot CPU (early init function) */
preinit_dt_xen_time(void)113 static void __init preinit_dt_xen_time(void)
114 {
115 static const struct dt_device_match timer_ids[] __initconst =
116 {
117 DT_MATCH_TIMER,
118 { /* sentinel */ },
119 };
120 int res;
121 u32 rate;
122
123 timer = dt_find_matching_node(NULL, timer_ids);
124 if ( !timer )
125 panic("Unable to find a compatible timer in the device tree\n");
126
127 dt_device_set_used_by(timer, DOMID_XEN);
128
129 res = dt_property_read_u32(timer, "clock-frequency", &rate);
130 if ( res )
131 {
132 cpu_khz = rate / 1000;
133 timer_dt_clock_frequency = rate;
134 }
135 }
136
preinit_xen_time(void)137 void __init preinit_xen_time(void)
138 {
139 int res;
140
141 /* Initialize all the generic timers presented in GTDT */
142 if ( acpi_disabled )
143 preinit_dt_xen_time();
144 else
145 preinit_acpi_xen_time();
146
147 if ( !cpu_khz )
148 cpu_khz = READ_SYSREG32(CNTFRQ_EL0) / 1000;
149
150 res = platform_init_time();
151 if ( res )
152 panic("Timer: Cannot initialize platform timer\n");
153
154 boot_count = get_cycles();
155 }
156
init_dt_xen_time(void)157 static void __init init_dt_xen_time(void)
158 {
159 int res;
160 unsigned int i;
161
162 /* Retrieve all IRQs for the timer */
163 for ( i = TIMER_PHYS_SECURE_PPI; i < MAX_TIMER_PPI; i++ )
164 {
165 res = platform_get_irq(timer, i);
166
167 if ( res < 0 )
168 panic("Timer: Unable to retrieve IRQ %u from the device tree\n", i);
169 timer_irq[i] = res;
170 }
171 }
172
173 /* Set up the timer on the boot CPU (late init function) */
init_xen_time(void)174 int __init init_xen_time(void)
175 {
176 if ( acpi_disabled )
177 init_dt_xen_time();
178
179 /* Check that this CPU supports the Generic Timer interface */
180 if ( !cpu_has_gentimer )
181 panic("CPU does not support the Generic Timer v1 interface\n");
182
183 printk("Generic Timer IRQ: phys=%u hyp=%u virt=%u Freq: %lu KHz\n",
184 timer_irq[TIMER_PHYS_NONSECURE_PPI],
185 timer_irq[TIMER_HYP_PPI],
186 timer_irq[TIMER_VIRT_PPI],
187 cpu_khz);
188
189 return 0;
190 }
191
192 /* Return number of nanoseconds since boot */
get_s_time(void)193 s_time_t get_s_time(void)
194 {
195 uint64_t ticks = get_cycles() - boot_count;
196 return ticks_to_ns(ticks);
197 }
198
199 /* Set the timer to wake us up at a particular time.
200 * Timeout is a Xen system time (nanoseconds since boot); 0 disables the timer.
201 * Returns 1 on success; 0 if the timeout is too soon or is in the past. */
reprogram_timer(s_time_t timeout)202 int reprogram_timer(s_time_t timeout)
203 {
204 uint64_t deadline;
205
206 if ( timeout == 0 )
207 {
208 WRITE_SYSREG32(0, CNTHP_CTL_EL2);
209 return 1;
210 }
211
212 deadline = ns_to_ticks(timeout) + boot_count;
213 WRITE_SYSREG64(deadline, CNTHP_CVAL_EL2);
214 WRITE_SYSREG32(CNTx_CTL_ENABLE, CNTHP_CTL_EL2);
215 isb();
216
217 /* No need to check for timers in the past; the Generic Timer fires
218 * on a signed 63-bit comparison. */
219 return 1;
220 }
221
222 /* Handle the firing timer */
timer_interrupt(int irq,void * dev_id,struct cpu_user_regs * regs)223 static void timer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
224 {
225 if ( irq == (timer_irq[TIMER_HYP_PPI]) &&
226 READ_SYSREG32(CNTHP_CTL_EL2) & CNTx_CTL_PENDING )
227 {
228 perfc_incr(hyp_timer_irqs);
229 /* Signal the generic timer code to do its work */
230 raise_softirq(TIMER_SOFTIRQ);
231 /* Disable the timer to avoid more interrupts */
232 WRITE_SYSREG32(0, CNTHP_CTL_EL2);
233 }
234
235 if ( irq == (timer_irq[TIMER_PHYS_NONSECURE_PPI]) &&
236 READ_SYSREG32(CNTP_CTL_EL0) & CNTx_CTL_PENDING )
237 {
238 perfc_incr(phys_timer_irqs);
239 /* Signal the generic timer code to do its work */
240 raise_softirq(TIMER_SOFTIRQ);
241 /* Disable the timer to avoid more interrupts */
242 WRITE_SYSREG32(0, CNTP_CTL_EL0);
243 }
244 }
245
vtimer_interrupt(int irq,void * dev_id,struct cpu_user_regs * regs)246 static void vtimer_interrupt(int irq, void *dev_id, struct cpu_user_regs *regs)
247 {
248 /*
249 * Edge-triggered interrupts can be used for the virtual timer. Even
250 * if the timer output signal is masked in the context switch, the
251 * GIC will keep track that of any interrupts raised while IRQS are
252 * disabled. As soon as IRQs are re-enabled, the virtual interrupt
253 * will be injected to Xen.
254 *
255 * If an IDLE vCPU was scheduled next then we should ignore the
256 * interrupt.
257 */
258 if ( unlikely(is_idle_vcpu(current)) )
259 return;
260
261 perfc_incr(virt_timer_irqs);
262
263 current->arch.virt_timer.ctl = READ_SYSREG32(CNTV_CTL_EL0);
264 WRITE_SYSREG32(current->arch.virt_timer.ctl | CNTx_CTL_MASK, CNTV_CTL_EL0);
265 vgic_inject_irq(current->domain, current, current->arch.virt_timer.irq, true);
266 }
267
268 /*
269 * Arch timer interrupt really ought to be level triggered, since the
270 * design of the timer/comparator mechanism is based around that
271 * concept.
272 *
273 * However some firmware (incorrectly) describes the interrupts as
274 * edge triggered and, worse, some hardware allows us to program the
275 * interrupt controller as edge triggered.
276 *
277 * Check each interrupt and warn if we find ourselves in this situation.
278 */
check_timer_irq_cfg(unsigned int irq,const char * which)279 static void check_timer_irq_cfg(unsigned int irq, const char *which)
280 {
281 struct irq_desc *desc = irq_to_desc(irq);
282
283 /*
284 * The interrupt controller driver will update desc->arch.type with
285 * the actual type which ended up configured in the hardware.
286 */
287 if ( desc->arch.type & IRQ_TYPE_LEVEL_MASK )
288 return;
289
290 printk(XENLOG_WARNING
291 "WARNING: %s-timer IRQ%u is not level triggered.\n", which, irq);
292 }
293
294 /* Set up the timer interrupt on this CPU */
init_timer_interrupt(void)295 void init_timer_interrupt(void)
296 {
297 /* Sensible defaults */
298 WRITE_SYSREG64(0, CNTVOFF_EL2); /* No VM-specific offset */
299 /* Do not let the VMs program the physical timer, only read the physical counter */
300 WRITE_SYSREG32(CNTHCTL_EL2_EL1PCTEN, CNTHCTL_EL2);
301 WRITE_SYSREG32(0, CNTP_CTL_EL0); /* Physical timer disabled */
302 WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Hypervisor's timer disabled */
303 isb();
304
305 request_irq(timer_irq[TIMER_HYP_PPI], 0, timer_interrupt,
306 "hyptimer", NULL);
307 request_irq(timer_irq[TIMER_VIRT_PPI], 0, vtimer_interrupt,
308 "virtimer", NULL);
309 request_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], 0, timer_interrupt,
310 "phytimer", NULL);
311
312 check_timer_irq_cfg(timer_irq[TIMER_HYP_PPI], "hypervisor");
313 check_timer_irq_cfg(timer_irq[TIMER_VIRT_PPI], "virtual");
314 check_timer_irq_cfg(timer_irq[TIMER_PHYS_NONSECURE_PPI], "NS-physical");
315 }
316
317 /*
318 * Revert actions done in init_timer_interrupt that are required to properly
319 * disable this CPU.
320 */
deinit_timer_interrupt(void)321 static void deinit_timer_interrupt(void)
322 {
323 WRITE_SYSREG32(0, CNTP_CTL_EL0); /* Disable physical timer */
324 WRITE_SYSREG32(0, CNTHP_CTL_EL2); /* Disable hypervisor's timer */
325 isb();
326
327 release_irq(timer_irq[TIMER_HYP_PPI], NULL);
328 release_irq(timer_irq[TIMER_VIRT_PPI], NULL);
329 release_irq(timer_irq[TIMER_PHYS_NONSECURE_PPI], NULL);
330 }
331
332 /* Wait a set number of microseconds */
udelay(unsigned long usecs)333 void udelay(unsigned long usecs)
334 {
335 s_time_t deadline = get_s_time() + 1000 * (s_time_t) usecs;
336 while ( get_s_time() - deadline < 0 )
337 ;
338 dsb(sy);
339 isb();
340 }
341
342 /* VCPU PV timers. */
send_timer_event(struct vcpu * v)343 void send_timer_event(struct vcpu *v)
344 {
345 send_guest_vcpu_virq(v, VIRQ_TIMER);
346 }
347
348 /* VCPU PV clock. */
update_vcpu_system_time(struct vcpu * v)349 void update_vcpu_system_time(struct vcpu *v)
350 {
351 /* XXX update shared_info->wc_* */
352 }
353
domain_set_time_offset(struct domain * d,int64_t time_offset_seconds)354 void domain_set_time_offset(struct domain *d, int64_t time_offset_seconds)
355 {
356 d->time_offset.seconds = time_offset_seconds;
357 d->time_offset.set = true;
358 /* XXX update guest visible wallclock time */
359 }
360
cpu_time_callback(struct notifier_block * nfb,unsigned long action,void * hcpu)361 static int cpu_time_callback(struct notifier_block *nfb,
362 unsigned long action,
363 void *hcpu)
364 {
365 switch ( action )
366 {
367 case CPU_DYING:
368 deinit_timer_interrupt();
369 break;
370 default:
371 break;
372 }
373
374 return NOTIFY_DONE;
375 }
376
377 static struct notifier_block cpu_time_nfb = {
378 .notifier_call = cpu_time_callback,
379 };
380
cpu_time_notifier_init(void)381 static int __init cpu_time_notifier_init(void)
382 {
383 register_cpu_notifier(&cpu_time_nfb);
384
385 return 0;
386 }
387 __initcall(cpu_time_notifier_init);
388
389 /*
390 * Local variables:
391 * mode: C
392 * c-file-style: "BSD"
393 * c-basic-offset: 4
394 * indent-tabs-mode: nil
395 * End:
396 */
397