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