1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4  */
5 
6 #include <arch_helpers.h>
7 #include <attestation_token.h>
8 #include <gic.h>
9 #include <memory_alloc.h>
10 #include <rec.h>
11 #include <smc-rmi.h>
12 
13 /*
14  * Check that timer output is asserted:
15  * Timer enabled: CNTx_CTL_ENABLE = 1
16  * Timer condition is met: CNTx_CTL_ISTATUS = 1
17  * Timer interrupt is not masked: CNTx_CTL_IMASK = 0
18  */
19 #define	TIMER_ASSERTED(reg)						\
20 	(((reg) &							\
21 	(CNTx_CTL_ENABLE | CNTx_CTL_ISTATUS | CNTx_CTL_IMASK)) ==	\
22 	(CNTx_CTL_ENABLE | CNTx_CTL_ISTATUS))
23 
24 /*
25  * Check the pending state of the timers.
26  *
27  * When a timer output is asserted, its interrupt signal should be masked at
28  * EL2 when running the Realm to prevent the physical interrupt from
29  * continuously exiting the Realm.
30  *
31  * When a timer output is not asserted, the interrupt signal should be
32  * unmasked such that if the timer output becomes asserted again, an exit from
33  * the Realm happens due to a physical IRQ and we can inject a virtual
34  * interrupt again.
35  */
check_pending_timers(struct rec * rec)36 bool check_pending_timers(struct rec *rec)
37 {
38 	unsigned long cntv_ctl = read_cntv_ctl_el02();
39 	unsigned long cntp_ctl = read_cntp_ctl_el02();
40 	unsigned long cnthctl_old = rec->sysregs.cnthctl_el2;
41 
42 	if (TIMER_ASSERTED(cntv_ctl)) {
43 		rec->sysregs.cnthctl_el2 |= CNTHCTL_EL2_CNTVMASK;
44 	} else {
45 		rec->sysregs.cnthctl_el2 &= ~CNTHCTL_EL2_CNTVMASK;
46 	}
47 
48 	if (TIMER_ASSERTED(cntp_ctl)) {
49 		rec->sysregs.cnthctl_el2 |= CNTHCTL_EL2_CNTPMASK;
50 	} else {
51 		rec->sysregs.cnthctl_el2 &= ~CNTHCTL_EL2_CNTPMASK;
52 	}
53 
54 	if (cnthctl_old != rec->sysregs.cnthctl_el2) {
55 		write_cnthctl_el2(rec->sysregs.cnthctl_el2);
56 		isb();
57 	}
58 
59 	/*
60 	 * We don't want to run the Realm just to immediately exit due a
61 	 * physical interrupt casused by one of the timer interrupts not having
62 	 * been retired from the CPU interface yet. Check that the interrupts
63 	 * are retired before entering the Realm.
64 	 */
65 	while (true) {
66 		unsigned long hppir = read_icc_hppir1_el1();
67 		unsigned int intid = EXTRACT(ICC_HPPIR1_EL1_INTID, hppir);
68 
69 		if (!((((rec->sysregs.cnthctl_el2 & CNTHCTL_EL2_CNTVMASK) != 0UL) &&
70 			(intid == EL1_VIRT_TIMER_PPI)) ||
71 		      (((rec->sysregs.cnthctl_el2 & CNTHCTL_EL2_CNTPMASK) != 0UL) &&
72 			(intid == EL1_PHYS_TIMER_PPI)))) {
73 			break;
74 		}
75 	}
76 
77 	/*
78 	 * Check if the timers changed their output status based on
79 	 * the previously saved timer state at the last Realm exit.
80 	 */
81 	return (TIMER_ASSERTED(cntv_ctl) !=
82 		TIMER_ASSERTED(rec->sysregs.cntv_ctl_el0)) ||
83 		(TIMER_ASSERTED(cntp_ctl) !=
84 		 TIMER_ASSERTED(rec->sysregs.cntp_ctl_el0));
85 }
86 
report_timer_state_to_ns(struct rmi_rec_exit * rec_exit)87 void report_timer_state_to_ns(struct rmi_rec_exit *rec_exit)
88 {
89 	/* Expose Realm EL1 timer state */
90 	rec_exit->cntv_ctl = read_cntv_ctl_el02();
91 	rec_exit->cntv_cval = read_cntv_cval_el02() - read_cntvoff_el2();
92 
93 	rec_exit->cntp_ctl = read_cntp_ctl_el02();
94 	rec_exit->cntp_cval = read_cntp_cval_el02() - read_cntpoff_el2();
95 }
96