Soby Mathew | b4c6df4 | 2022-11-09 11:13:29 +0000 | [diff] [blame^] | 1 | /* |
| 2 | * SPDX-License-Identifier: BSD-3-Clause |
| 3 | * SPDX-FileCopyrightText: Copyright TF-RMM Contributors. |
| 4 | */ |
| 5 | |
| 6 | #ifndef GIC_H |
| 7 | #define GIC_H |
| 8 | |
| 9 | #include <stdbool.h> |
| 10 | #include <utils_def.h> |
| 11 | |
| 12 | /* The number of implemented List registers, minus one */ |
| 13 | #define ICH_VTR_EL2_LIST_REGS_SHIFT UL(0) |
| 14 | #define ICH_VTR_EL2_LIST_REGS_WIDTH UL(5) |
| 15 | #define ICH_VTR_EL2_LIST_REGS_MASK MASK(ICH_VTR_EL2_LIST_REGS) |
| 16 | |
| 17 | /* The number of virtual interrupt identifier bits supported */ |
| 18 | #define ICH_VTR_EL2_ID_BITS_SHIFT UL(23) |
| 19 | #define ICH_VTR_EL2_ID_BITS_WIDTH UL(3) |
| 20 | #define ICH_VTR_EL2_ID_BITS_MASK MASK(ICH_VTR_EL2_ID_BITS) |
| 21 | |
| 22 | /* The number of virtual preemption bits implemented, minus one */ |
| 23 | #define ICH_VTR_EL2_PRE_BITS_SHIFT UL(26) |
| 24 | #define ICH_VTR_EL2_PRE_BITS_WIDTH UL(3) |
| 25 | #define ICH_VTR_EL2_PRE_BITS_MASK MASK(ICH_VTR_EL2_PRE_BITS) |
| 26 | |
| 27 | /* The number of virtual priority bits implemented, minus one */ |
| 28 | #define ICH_VTR_EL2_PRI_BITS_SHIFT UL(29) |
| 29 | #define ICH_VTR_EL2_PRI_BITS_WIDTH UL(3) |
| 30 | #define ICH_VTR_EL2_PRI_BITS_MASK MASK(ICH_VTR_EL2_PRI_BITS) |
| 31 | |
| 32 | /* Global enable bit for the virtual CPU interface */ |
| 33 | #define ICH_HCR_EL2_EN_SHIFT UL(0) |
| 34 | #define ICH_HCR_EL2_EN_BIT INPLACE(ICH_HCR_EL2_EN, UL(1)) |
| 35 | |
| 36 | /* Underflow Interrupt Enable */ |
| 37 | #define ICH_HCR_EL2_UIE_SHIFT UL(1) |
| 38 | #define ICH_HCR_EL2_UIE_BIT INPLACE(ICH_HCR_EL2_UIE, UL(1)) |
| 39 | |
| 40 | /* List Register Entry Not Present Interrupt Enable */ |
| 41 | #define ICH_HCR_EL2_LRENPIE_SHIFT UL(2) |
| 42 | #define ICH_HCR_EL2_LRENPIE_BIT INPLACE(ICH_HCR_EL2_LRENPIE, UL(1)) |
| 43 | |
| 44 | /* No Pending Interrupt Enable */ |
| 45 | #define ICH_HCR_EL2_NPIE_SHIFT UL(3) |
| 46 | #define ICH_HCR_EL2_NPIE_BIT INPLACE(ICH_HCR_EL2_NPIE, UL(1)) |
| 47 | |
| 48 | /* VM Group 0 Enabled Interrupt Enable */ |
| 49 | #define ICH_HCR_EL2_VGRP0EIE_SHIFT UL(4) |
| 50 | #define ICH_HCR_EL2_VGRP0EIE_BIT INPLACE(ICH_HCR_EL2_VGRP0EIE, UL(1)) |
| 51 | |
| 52 | /* VM Group 0 Disabled Interrupt Enable */ |
| 53 | #define ICH_HCR_EL2_VGRP0DIE_SHIFT UL(5) |
| 54 | #define ICH_HCR_EL2_VGRP0DIE_BIT INPLACE(ICH_HCR_EL2_VGRP0DIE, UL(1)) |
| 55 | |
| 56 | /* VM Group 1 Enabled Interrupt Enable */ |
| 57 | #define ICH_HCR_EL2_VGRP1EIE_SHIFT UL(6) |
| 58 | #define ICH_HCR_EL2_VGRP1EIE_BIT INPLACE(ICH_HCR_EL2_VGRP1EIE, UL(1)) |
| 59 | |
| 60 | /* VM Group 1 Disabled Interrupt Enable */ |
| 61 | #define ICH_HCR_EL2_VGRP1DIE_SHIFT UL(7) |
| 62 | #define ICH_HCR_EL2_VGRP1DIE_BIT INPLACE(ICH_HCR_EL2_VGRP1DIE, UL(1)) |
| 63 | |
| 64 | /* |
| 65 | * When FEAT_GICv4p1 is implemented: |
| 66 | * Controls whether deactivation of virtual SGIs |
| 67 | * can increment ICH_HCR_EL2.EOIcount |
| 68 | */ |
| 69 | #define ICH_HCR_EL2_VSGIEEOICOUNT_SHIFT UL(8) |
| 70 | #define ICH_HCR_EL2_VSGIEEOICOUNT_BIT INPLACE(ICH_HCR_EL2_VSGIEEOICOUNT, UL(1)) |
| 71 | |
| 72 | /* |
| 73 | * Trap all EL1 accesses to System registers |
| 74 | * that are common to Group 0 and Group 1 to EL2 |
| 75 | */ |
| 76 | #define ICH_HCR_EL2_TC_SHIFT UL(10) |
| 77 | #define ICH_HCR_EL2_TC_BIT INPLACE(ICH_HCR_EL2_TC, UL(1)) |
| 78 | |
| 79 | /* |
| 80 | * Trap all EL1 accesses to ICC_* and ICV_* System registers |
| 81 | * for Group 0 interrupts to EL2 |
| 82 | */ |
| 83 | #define ICH_HCR_EL2_TALL0_SHIFT UL(11) |
| 84 | #define ICH_HCR_EL2_TALL0_BIT INPLACE(ICH_HCR_EL2_TALL0, UL(1)) |
| 85 | |
| 86 | /* |
| 87 | * Trap all EL1 accesses to ICC_* and ICV_* System registers |
| 88 | * for Group 1 interrupts to EL2 |
| 89 | */ |
| 90 | #define ICH_HCR_EL2_TALL1_SHIFT UL(12) |
| 91 | #define ICH_HCR_EL2_TALL1_BIT INPLACE(ICH_HCR_EL2_TALL1, UL(1)) |
| 92 | |
| 93 | /* Trap all locally generated SEIs */ |
| 94 | #define ICH_HCR_EL2_TSEI_SHIFT UL(13) |
| 95 | #define ICH_HCR_EL2_TSEI_BIT INPLACE(ICH_HCR_EL2_TSEI, UL(1)) |
| 96 | |
| 97 | /* |
| 98 | * When FEAT_GICv3_TDIR is implemented: |
| 99 | * Trap EL1 writes to ICC_DIR_EL1 and ICV_DIR_EL1 |
| 100 | */ |
| 101 | #define ICH_HCR_EL2_TDIR_SHIFT UL(14) |
| 102 | #define ICH_HCR_EL2_TDIR_BIT INPLACE(ICH_HCR_EL2_TDIR, UL(1)) |
| 103 | |
| 104 | /* |
| 105 | * When ICH_VTR_EL2.DVIM == 1: |
| 106 | * Directly-injected Virtual Interrupt Mask |
| 107 | */ |
| 108 | #define ICH_HCR_EL2_DVIM_SHIFT UL(15) |
| 109 | #define ICH_HCR_EL2_DVIM_BIT INPLACE(ICH_HCR_EL2_DVIM, UL(1)) |
| 110 | |
| 111 | #define ICH_HCR_EL2_EOI_COUNT_SHIFT UL(27) |
| 112 | #define ICH_HCR_EL2_EOI_COUNT_WIDTH UL(5) |
| 113 | #define ICH_HCR_EL2_EOI_COUNT_MASK MASK(ICH_HCR_EL2_EOI_COUNT) |
| 114 | |
| 115 | /* Virtual INTID of the interrupt */ |
| 116 | #define ICH_LR_VINTID_SHIFT UL(0) |
| 117 | #define ICH_LR_VINTID_WIDTH UL(32) |
| 118 | #define ICH_LR_VINTID_MASK MASK(ICH_LR_VINTID) |
| 119 | |
| 120 | /* |
| 121 | * Physical INTID, for hardware interrupts |
| 122 | * When ICH_LR<n>_EL2.HW is 0 (there is no corresponding physical interrupt), |
| 123 | * this field has the following meaning: |
| 124 | * Bits[44:42] : RES0. |
| 125 | * Bit[41] : EOI. If this bit is 1, then when the interrupt identified by |
| 126 | * vINTID is deactivated, a maintenance interrupt is asserted. |
| 127 | * Bits[40:32] : RES0 |
| 128 | */ |
| 129 | #define ICH_LR_PINTID_SHIFT UL(32) |
| 130 | #define ICH_LR_PINTID_WIDTH UL(13) |
| 131 | #define ICH_LR_PINTID_MASK MASK(ICH_LR_PINTID) |
| 132 | |
| 133 | #define ICH_LR_EOI_SHIFT UL(41) |
| 134 | #define ICH_LR_EOI_BIT INPLACE(ICH_LR_EOI, UL(1)) |
| 135 | |
| 136 | /* The priority of this interrupt */ |
| 137 | #define ICH_LR_PRIORITY_SHIFT UL(48) |
| 138 | #define ICH_LR_PRIORITY_WIDTH UL(8) |
| 139 | #define ICH_LR_PRIORITY_MASK MASK(ICH_LR_PRIORITY) |
| 140 | |
| 141 | /* The group for this virtual interrupt */ |
| 142 | #define ICH_LR_GROUP_SHIFT UL(60) |
| 143 | #define ICH_LR_GROUP_BIT INPLACE(ICH_LR_GROUP, UL(1)) |
| 144 | |
| 145 | /* |
| 146 | * Indicates whether this virtual interrupt |
| 147 | * maps directly to a hardware interrupt |
| 148 | */ |
| 149 | #define ICH_LR_HW_SHIFT UL(61) |
| 150 | #define ICH_LR_HW_BIT INPLACE(ICH_LR_HW, UL(1)) |
| 151 | |
| 152 | /* |
| 153 | * The state of the interrupt: |
| 154 | * 0b00 Invalid (Inactive) |
| 155 | * 0b01 Pending |
| 156 | * 0b10 Active |
| 157 | * 0b11 Pending and active |
| 158 | */ |
| 159 | #define ICH_LR_STATE_SHIFT UL(62) |
| 160 | #define ICH_LR_STATE_WIDTH UL(2) |
| 161 | #define ICH_LR_STATE_MASK MASK(ICH_LR_STATE) |
| 162 | |
| 163 | #define ICH_LR_STATE_INVALID INPLACE(ICH_LR_STATE, UL(0)) |
| 164 | #define ICH_LR_STATE_PENDING INPLACE(ICH_LR_STATE, UL(1)) |
| 165 | #define ICH_LR_STATE_ACTIVE INPLACE(ICH_LR_STATE, UL(2)) |
| 166 | #define ICH_LR_STATE_PENDING_ACTIVE INPLACE(ICH_LR_STATE, UL(3)) |
| 167 | |
| 168 | /* |
| 169 | * A `_ns` mask defines bits that can be set/cleared by the NS hypervisor. |
| 170 | */ |
| 171 | |
| 172 | #define ICH_HCR_EL2_NS_MASK \ |
| 173 | (ICH_HCR_EL2_UIE_BIT | \ |
| 174 | ICH_HCR_EL2_LRENPIE_BIT | \ |
| 175 | ICH_HCR_EL2_NPIE_BIT | \ |
| 176 | ICH_HCR_EL2_VGRP0EIE_BIT | \ |
| 177 | ICH_HCR_EL2_VGRP0DIE_BIT | \ |
| 178 | ICH_HCR_EL2_VGRP1EIE_BIT | \ |
| 179 | ICH_HCR_EL2_VGRP1DIE_BIT | \ |
| 180 | ICH_HCR_EL2_TDIR_BIT) |
| 181 | /* |
| 182 | * Maximum number of Interrupt Controller |
| 183 | * Hyp Active Priorities Group 0/1 Registers [0..3] |
| 184 | */ |
| 185 | #define ICH_MAX_APRS 4 |
| 186 | |
| 187 | /* Maximum number of Interrupt Controller List Registers */ |
| 188 | #define ICH_MAX_LRS 16 |
| 189 | |
| 190 | /******************************************************************************* |
| 191 | * GICv3 and 3.1 definitions |
| 192 | ******************************************************************************/ |
| 193 | #define MIN_SGI_ID U(0) |
| 194 | #define MIN_SEC_SGI_ID U(8) |
| 195 | |
| 196 | /* PPIs INTIDs 16-31 */ |
| 197 | #define MIN_PPI_ID U(16) |
| 198 | #define MAX_PPI_ID U(31) |
| 199 | |
| 200 | /* SPIs INTIDs 32-1019 */ |
| 201 | #define MIN_SPI_ID U(32) |
| 202 | #define MAX_SPI_ID U(1019) |
| 203 | |
| 204 | /* GICv3.1 extended PPIs INTIDs 1056-1119 */ |
| 205 | #define MIN_EPPI_ID U(1056) |
| 206 | #define MAX_EPPI_ID U(1119) |
| 207 | |
| 208 | /* GICv3.1 extended SPIs INTIDs 4096 - 5119 */ |
| 209 | #define MIN_ESPI_ID U(4096) |
| 210 | #define MAX_ESPI_ID U(5119) |
| 211 | |
| 212 | /* Constant to categorize LPI interrupt */ |
| 213 | #define MIN_LPI_ID U(8192) |
| 214 | |
| 215 | struct gic_cpu_state { |
| 216 | /* Interrupt Controller Hyp Active Priorities Group 0 Registers */ |
| 217 | unsigned long ich_ap0r_el2[ICH_MAX_APRS]; |
| 218 | /* Interrupt Controller Hyp Active Priorities Group 1 Registers */ |
| 219 | unsigned long ich_ap1r_el2[ICH_MAX_APRS]; |
| 220 | /* GICv3 Virtual Machine Control Register */ |
| 221 | unsigned long ich_vmcr_el2; /* RecRun out */ |
| 222 | /* Interrupt Controller Hyp Control Register */ |
| 223 | unsigned long ich_hcr_el2; /* RecRun in/out */ |
| 224 | |
| 225 | /* GICv3 List Registers */ |
| 226 | unsigned long ich_lr_el2[ICH_MAX_LRS]; /* RecRun in/out */ |
| 227 | /* GICv3 Maintenance Interrupt State Register */ |
| 228 | unsigned long ich_misr_el2; /* RecRun out */ |
| 229 | }; |
| 230 | |
| 231 | struct rmi_rec_entry; |
| 232 | struct rmi_rec_exit; |
| 233 | |
| 234 | void gic_get_virt_features(void); |
| 235 | void gic_cpu_state_init(struct gic_cpu_state *gicstate); |
| 236 | void gic_copy_state_from_ns(struct gic_cpu_state *gicstate, |
| 237 | struct rmi_rec_entry *rec_entry); |
| 238 | void gic_copy_state_to_ns(struct gic_cpu_state *gicstate, |
| 239 | struct rmi_rec_exit *rec_exit); |
| 240 | bool gic_validate_state(struct gic_cpu_state *gicstate); |
| 241 | void gic_restore_state(struct gic_cpu_state *gicstate); |
| 242 | void gic_save_state(struct gic_cpu_state *gicstate); |
| 243 | |
| 244 | #endif /* GIC_H */ |