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