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