1 /*
2 * Copyright 2024 The Hafnium Authors.
3 *
4 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
7 */
8
9 #include "hf/arch/host_timer.h"
10
11 #include "hf/arch/gicv3.h"
12
13 #include "hf/plat/interrupts.h"
14
15 #include "msr.h"
16 #include "sysregs.h"
17
18 /**
19 * Disable EL2/S-EL2 physical timer.
20 */
host_timer_disable(void)21 void host_timer_disable(void)
22 {
23 #if SECURE_WORLD == 1
24 write_msr(cnthps_ctl_el2, 0);
25 #else
26 write_msr(cnthp_ctl_el2, 0);
27 #endif
28 /* Ensure that the write to ctl register has taken effect. */
29 isb();
30 }
31
32 /**
33 * Disable host timer and configure the PPI associated with it.
34 */
host_timer_init(void)35 void host_timer_init(void)
36 {
37 host_timer_disable();
38
39 #if SECURE_WORLD == 1
40 struct interrupt_descriptor int_desc = {
41 .interrupt_id = ARM_SEL2_TIMER_PHYS_INT,
42 .type = INT_DESC_TYPE_PPI,
43 .config = 1U, /* Level-sensitive */
44 .sec_state = INT_DESC_SEC_STATE_S,
45 .priority = 0x0,
46 .valid = true,
47 .mpidr_valid = false,
48 .enabled = true,
49 };
50
51 plat_interrupts_configure_interrupt(int_desc);
52 #endif
53 }
54
55 /**
56 * Save the arch timer state being tracked by host timer.
57 */
host_timer_save_arch_timer(struct timer_state * timer)58 void host_timer_save_arch_timer(struct timer_state *timer)
59 {
60 #if SECURE_WORLD == 1
61 timer->cval = read_msr(MSR_CNTHPS_CVAL_EL2);
62 timer->ctl = read_msr(MSR_CNTHPS_CTL_EL2);
63 #else
64 timer->cval = read_msr(MSR_CNTHP_CVAL_EL2);
65 timer->ctl = read_msr(MSR_CNTHP_CTL_EL2);
66 #endif
67 }
68
69 /**
70 * Configure the host timer to track the arch timer deadline.
71 */
host_timer_track_deadline(struct timer_state * timer)72 void host_timer_track_deadline(struct timer_state *timer)
73 {
74 /*
75 * Clear timer control register before restoring compare value, to avoid
76 * a spurious timer interrupt. This could be a problem if the interrupt
77 * is configured as edge-triggered, as it would then be latched in.
78 */
79 #if SECURE_WORLD == 1
80 write_msr(cnthps_ctl_el2, 0);
81 write_msr(cnthps_cval_el2, timer->cval);
82 write_msr(cnthps_ctl_el2, timer->ctl);
83 #else
84 write_msr(cnthp_ctl_el2, 0);
85 write_msr(cnthp_cval_el2, timer->cval);
86 write_msr(cnthp_ctl_el2, timer->ctl);
87 #endif
88 /* Ensure that the write to ctl register has taken effect. */
89 isb();
90 }
91