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)36bool 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)87void 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