1 /* 2 * Copyright (c) 2015-2024, Arm Limited and Contributors. All rights reserved. 3 * Portions copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 */ 7 8 #include <assert.h> 9 #include <stdbool.h> 10 11 #include <arch_helpers.h> 12 #include <common/bl_common.h> 13 #include <common/debug.h> 14 #include <bl31/interrupt_mgmt.h> 15 #include <drivers/arm/gic_common.h> 16 #include <drivers/arm/gicv3.h> 17 #include <lib/cassert.h> 18 #include <plat/common/platform.h> 19 20 #ifdef IMAGE_BL31 21 22 /* 23 * The following platform GIC functions are weakly defined. They 24 * provide typical implementations that may be re-used by multiple 25 * platforms but may also be overridden by a platform if required. 26 */ 27 #pragma weak plat_ic_get_pending_interrupt_id 28 #pragma weak plat_ic_get_pending_interrupt_type 29 #pragma weak plat_ic_acknowledge_interrupt 30 #pragma weak plat_ic_get_interrupt_type 31 #pragma weak plat_ic_end_of_interrupt 32 #pragma weak plat_interrupt_type_to_line 33 34 #pragma weak plat_ic_get_running_priority 35 #pragma weak plat_ic_is_spi 36 #pragma weak plat_ic_is_ppi 37 #pragma weak plat_ic_is_sgi 38 #pragma weak plat_ic_get_interrupt_active 39 #pragma weak plat_ic_enable_interrupt 40 #pragma weak plat_ic_disable_interrupt 41 #pragma weak plat_ic_set_interrupt_priority 42 #pragma weak plat_ic_set_interrupt_type 43 #pragma weak plat_ic_raise_el3_sgi 44 #pragma weak plat_ic_raise_ns_sgi 45 #pragma weak plat_ic_raise_s_el1_sgi 46 #pragma weak plat_ic_set_spi_routing 47 #pragma weak plat_ic_set_interrupt_pending 48 #pragma weak plat_ic_clear_interrupt_pending 49 50 /* 51 * This function returns the highest priority pending interrupt at 52 * the Interrupt controller 53 */ 54 uint32_t plat_ic_get_pending_interrupt_id(void) 55 { 56 unsigned int irqnr; 57 58 assert(IS_IN_EL3()); 59 irqnr = gicv3_get_pending_interrupt_id(); 60 return gicv3_is_intr_id_special_identifier(irqnr) ? 61 INTR_ID_UNAVAILABLE : irqnr; 62 } 63 64 /* 65 * This function returns the type of the highest priority pending interrupt 66 * at the Interrupt controller. In the case of GICv3, the Highest Priority 67 * Pending interrupt system register (`ICC_HPPIR0_EL1`) is read to determine 68 * the id of the pending interrupt. The type of interrupt depends upon the 69 * id value as follows. 70 * 1. id = PENDING_G1S_INTID (1020) is reported as a S-EL1 interrupt 71 * 2. id = PENDING_G1NS_INTID (1021) is reported as a Non-secure interrupt. 72 * 3. id = GIC_SPURIOUS_INTERRUPT (1023) is reported as an invalid interrupt 73 * type. 74 * 4. All other interrupt id's are reported as EL3 interrupt. 75 */ 76 uint32_t plat_ic_get_pending_interrupt_type(void) 77 { 78 unsigned int irqnr; 79 uint32_t type; 80 81 assert(IS_IN_EL3()); 82 irqnr = gicv3_get_pending_interrupt_type(); 83 84 switch (irqnr) { 85 case PENDING_G1S_INTID: 86 type = INTR_TYPE_S_EL1; 87 break; 88 case PENDING_G1NS_INTID: 89 type = INTR_TYPE_NS; 90 break; 91 case GIC_SPURIOUS_INTERRUPT: 92 type = INTR_TYPE_INVAL; 93 break; 94 default: 95 type = INTR_TYPE_EL3; 96 break; 97 } 98 99 return type; 100 } 101 102 /* 103 * This function returns the highest priority pending interrupt at 104 * the Interrupt controller and indicates to the Interrupt controller 105 * that the interrupt processing has started. 106 */ 107 uint32_t plat_ic_acknowledge_interrupt(void) 108 { 109 assert(IS_IN_EL3()); 110 return gicv3_acknowledge_interrupt(); 111 } 112 113 /* 114 * This function returns the type of the interrupt `id`, depending on how 115 * the interrupt has been configured in the interrupt controller. 116 */ 117 uint32_t plat_ic_get_interrupt_type(uint32_t id) 118 { 119 unsigned int group; 120 121 assert(IS_IN_EL3()); 122 group = gicv3_get_interrupt_group(id, plat_my_core_pos()); 123 124 switch (group) { 125 case INTR_GROUP0: 126 return INTR_TYPE_EL3; 127 case INTR_GROUP1S: 128 return INTR_TYPE_S_EL1; 129 case INTR_GROUP1NS: 130 return INTR_TYPE_NS; 131 default: 132 assert(false); /* Unreachable */ 133 return INTR_TYPE_EL3; 134 } 135 } 136 137 /* 138 * This functions is used to indicate to the interrupt controller that 139 * the processing of the interrupt corresponding to the `id` has 140 * finished. 141 */ 142 void plat_ic_end_of_interrupt(uint32_t id) 143 { 144 assert(IS_IN_EL3()); 145 gicv3_end_of_interrupt(id); 146 } 147 148 /* 149 * An ARM processor signals interrupt exceptions through the IRQ and FIQ pins. 150 * The interrupt controller knows which pin/line it uses to signal a type of 151 * interrupt. It lets the interrupt management framework determine for a type of 152 * interrupt and security state, which line should be used in the SCR_EL3 to 153 * control its routing to EL3. The interrupt line is represented as the bit 154 * position of the IRQ or FIQ bit in the SCR_EL3. 155 */ 156 uint32_t plat_interrupt_type_to_line(uint32_t type, 157 uint32_t security_state) 158 { 159 assert((type == INTR_TYPE_S_EL1) || 160 (type == INTR_TYPE_EL3) || 161 (type == INTR_TYPE_NS)); 162 163 assert(sec_state_is_valid(security_state)); 164 assert(IS_IN_EL3()); 165 166 switch (type) { 167 case INTR_TYPE_S_EL1: 168 /* 169 * The S-EL1 interrupts are signaled as IRQ in S-EL0/1 contexts 170 * and as FIQ in the NS-EL0/1/2 contexts 171 */ 172 if (security_state == SECURE) 173 return __builtin_ctz(SCR_IRQ_BIT); 174 else 175 return __builtin_ctz(SCR_FIQ_BIT); 176 assert(0); /* Unreachable */ 177 case INTR_TYPE_NS: 178 /* 179 * The Non secure interrupts will be signaled as FIQ in S-EL0/1 180 * contexts and as IRQ in the NS-EL0/1/2 contexts. 181 */ 182 if (security_state == SECURE) 183 return __builtin_ctz(SCR_FIQ_BIT); 184 else 185 return __builtin_ctz(SCR_IRQ_BIT); 186 assert(0); /* Unreachable */ 187 case INTR_TYPE_EL3: 188 /* 189 * The EL3 interrupts are signaled as FIQ in both S-EL0/1 and 190 * NS-EL0/1/2 contexts 191 */ 192 return __builtin_ctz(SCR_FIQ_BIT); 193 default: 194 panic(); 195 } 196 } 197 198 unsigned int plat_ic_get_running_priority(void) 199 { 200 return gicv3_get_running_priority(); 201 } 202 203 int plat_ic_is_spi(unsigned int id) 204 { 205 return (id >= MIN_SPI_ID) && (id <= MAX_SPI_ID); 206 } 207 208 int plat_ic_is_ppi(unsigned int id) 209 { 210 return (id >= MIN_PPI_ID) && (id < MIN_SPI_ID); 211 } 212 213 int plat_ic_is_sgi(unsigned int id) 214 { 215 return (id >= MIN_SGI_ID) && (id < MIN_PPI_ID); 216 } 217 218 unsigned int plat_ic_get_interrupt_active(unsigned int id) 219 { 220 return gicv3_get_interrupt_active(id, plat_my_core_pos()); 221 } 222 223 void plat_ic_enable_interrupt(unsigned int id) 224 { 225 gicv3_enable_interrupt(id, plat_my_core_pos()); 226 } 227 228 void plat_ic_disable_interrupt(unsigned int id) 229 { 230 gicv3_disable_interrupt(id, plat_my_core_pos()); 231 } 232 233 void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority) 234 { 235 gicv3_set_interrupt_priority(id, plat_my_core_pos(), priority); 236 } 237 238 bool plat_ic_has_interrupt_type(unsigned int type) 239 { 240 if ((type == INTR_TYPE_EL3) || (type == INTR_TYPE_S_EL1) || 241 (type == INTR_TYPE_NS)) { 242 return true; 243 } 244 245 return false; 246 } 247 248 void plat_ic_set_interrupt_type(unsigned int id, unsigned int type) 249 { 250 unsigned int group; 251 252 switch (type) { 253 case INTR_TYPE_EL3: 254 group = INTR_GROUP0; 255 break; 256 case INTR_TYPE_S_EL1: 257 group = INTR_GROUP1S; 258 break; 259 case INTR_TYPE_NS: 260 group = INTR_GROUP1NS; 261 break; 262 default: 263 assert(false); /* Unreachable */ 264 group = INTR_GROUP0; 265 break; 266 } 267 268 gicv3_set_interrupt_group(id, plat_my_core_pos(), group); 269 } 270 271 void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target) 272 { 273 /* Target must be a valid MPIDR in the system */ 274 assert(plat_core_pos_by_mpidr(target) >= 0); 275 276 /* Verify that this is a secure EL3 SGI */ 277 assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == 278 INTR_TYPE_EL3); 279 280 gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G0, target); 281 } 282 283 void plat_ic_raise_ns_sgi(int sgi_num, u_register_t target) 284 { 285 /* Target must be a valid MPIDR in the system */ 286 assert(plat_core_pos_by_mpidr(target) >= 0); 287 288 /* Verify that this is a non-secure SGI */ 289 assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == 290 INTR_TYPE_NS); 291 292 gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1NS, target); 293 } 294 295 void plat_ic_raise_s_el1_sgi(int sgi_num, u_register_t target) 296 { 297 /* Target must be a valid MPIDR in the system */ 298 assert(plat_core_pos_by_mpidr(target) >= 0); 299 300 /* Verify that this is a secure EL1 SGI */ 301 assert(plat_ic_get_interrupt_type((unsigned int)sgi_num) == 302 INTR_TYPE_S_EL1); 303 304 gicv3_raise_sgi((unsigned int)sgi_num, GICV3_G1S, target); 305 } 306 307 void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, 308 u_register_t mpidr) 309 { 310 unsigned int irm = 0; 311 312 switch (routing_mode) { 313 case INTR_ROUTING_MODE_PE: 314 assert(plat_core_pos_by_mpidr(mpidr) >= 0); 315 irm = GICV3_IRM_PE; 316 break; 317 case INTR_ROUTING_MODE_ANY: 318 irm = GICV3_IRM_ANY; 319 break; 320 default: 321 assert(0); /* Unreachable */ 322 break; 323 } 324 325 gicv3_set_spi_routing(id, irm, mpidr); 326 } 327 328 void plat_ic_set_interrupt_pending(unsigned int id) 329 { 330 /* Disallow setting SGIs pending */ 331 assert(id >= MIN_PPI_ID); 332 gicv3_set_interrupt_pending(id, plat_my_core_pos()); 333 } 334 335 void plat_ic_clear_interrupt_pending(unsigned int id) 336 { 337 /* Disallow setting SGIs pending */ 338 assert(id >= MIN_PPI_ID); 339 gicv3_clear_interrupt_pending(id, plat_my_core_pos()); 340 } 341 342 unsigned int plat_ic_set_priority_mask(unsigned int mask) 343 { 344 return gicv3_set_pmr(mask); 345 } 346 347 unsigned int plat_ic_deactivate_priority(unsigned int mask) 348 { 349 return gicv3_deactivate_priority(mask); 350 } 351 352 unsigned int plat_ic_get_interrupt_id(unsigned int raw) 353 { 354 unsigned int id = raw & INT_ID_MASK; 355 356 return gicv3_is_intr_id_special_identifier(id) ? 357 INTR_ID_UNAVAILABLE : id; 358 } 359 #endif 360 #ifdef IMAGE_BL32 361 362 #pragma weak plat_ic_get_pending_interrupt_id 363 #pragma weak plat_ic_acknowledge_interrupt 364 #pragma weak plat_ic_end_of_interrupt 365 366 /* In AArch32, the secure group1 interrupts are targeted to Secure PL1 */ 367 #ifndef __aarch64__ 368 #define IS_IN_EL1() IS_IN_SECURE() 369 #endif 370 371 /* 372 * This function returns the highest priority pending interrupt at 373 * the Interrupt controller 374 */ 375 uint32_t plat_ic_get_pending_interrupt_id(void) 376 { 377 unsigned int irqnr; 378 379 assert(IS_IN_EL1()); 380 irqnr = gicv3_get_pending_interrupt_id_sel1(); 381 return (irqnr == GIC_SPURIOUS_INTERRUPT) ? 382 INTR_ID_UNAVAILABLE : irqnr; 383 } 384 385 /* 386 * This function returns the highest priority pending interrupt at 387 * the Interrupt controller and indicates to the Interrupt controller 388 * that the interrupt processing has started. 389 */ 390 uint32_t plat_ic_acknowledge_interrupt(void) 391 { 392 assert(IS_IN_EL1()); 393 return gicv3_acknowledge_interrupt_sel1(); 394 } 395 396 /* 397 * This functions is used to indicate to the interrupt controller that 398 * the processing of the interrupt corresponding to the `id` has 399 * finished. 400 */ 401 void plat_ic_end_of_interrupt(uint32_t id) 402 { 403 assert(IS_IN_EL1()); 404 gicv3_end_of_interrupt_sel1(id); 405 } 406 #endif 407