gic_v3_distributor.cc revision 14253
1/* 2 * Copyright (c) 2019 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2018 Metempsy Technology Consulting 15 * All rights reserved. 16 * 17 * Redistribution and use in source and binary forms, with or without 18 * modification, are permitted provided that the following conditions are 19 * met: redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer; 21 * redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution; 24 * neither the name of the copyright holders nor the names of its 25 * contributors may be used to endorse or promote products derived from 26 * this software without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 39 * 40 * Authors: Jairo Balart 41 */ 42 43#include "dev/arm/gic_v3_distributor.hh" 44 45#include <algorithm> 46 47#include "debug/GIC.hh" 48#include "dev/arm/gic_v3.hh" 49#include "dev/arm/gic_v3_cpu_interface.hh" 50#include "dev/arm/gic_v3_redistributor.hh" 51 52const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff); 53const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f); 54const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff); 55const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f); 56const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff); 57const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f); 58const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff); 59const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff); 60const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff); 61const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff); 62const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f); 63const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff); 64const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f); 65const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f); 66const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0); 67 68Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) 69 : gic(gic), 70 itLines(it_lines), 71 irqGroup(it_lines), 72 irqEnabled(it_lines), 73 irqPending(it_lines), 74 irqActive(it_lines), 75 irqPriority(it_lines), 76 irqConfig(it_lines), 77 irqGrpmod(it_lines), 78 irqNsacr(it_lines), 79 irqAffinityRouting(it_lines), 80 gicdPidr0(0x92), 81 gicdPidr1(0xb4), 82 gicdPidr2(0x3b), 83 gicdPidr3(0), 84 gicdPidr4(0x44) 85{ 86 panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!"); 87} 88 89void 90Gicv3Distributor::init() 91{ 92} 93 94void 95Gicv3Distributor::initState() 96{ 97 reset(); 98} 99 100void 101Gicv3Distributor::reset() 102{ 103 std::fill(irqGroup.begin(), irqGroup.end(), 0); 104 // Imp. defined reset value 105 std::fill(irqEnabled.begin(), irqEnabled.end(), false); 106 std::fill(irqPending.begin(), irqPending.end(), false); 107 std::fill(irqActive.begin(), irqActive.end(), false); 108 // Imp. defined reset value 109 std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA); 110 std::fill(irqConfig.begin(), irqConfig.end(), 111 Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value 112 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 113 std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 114 /* 115 * For our implementation affinity routing is always enabled, 116 * no GICv2 legacy 117 */ 118 ARE = true; 119 120 if (gic->getSystem()->haveSecurity()) { 121 DS = false; 122 } else { 123 DS = true; 124 } 125 126 EnableGrp0 = 0; 127 EnableGrp1NS = 0; 128 EnableGrp1S = 0; 129} 130 131uint64_t 132Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) 133{ 134 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 135 uint64_t val = 0x0; 136 137 if (!DS && !is_secure_access) { 138 // RAZ/WI for non-secure accesses 139 return 0; 140 } 141 142 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 143 144 if (isNotSPI(first_intid)) { 145 return 0; 146 } 147 148 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 149 i++, int_id++) { 150 val |= irqGroup[int_id] << i; 151 } 152 153 return val; 154 } else if (GICD_ISENABLER.contains(addr)) { 155 // Interrupt Set-Enable Registers 156 uint64_t val = 0x0; 157 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 158 159 if (isNotSPI(first_intid)) { 160 return 0; 161 } 162 163 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 164 i++, int_id++) { 165 166 if (nsAccessToSecInt(int_id, is_secure_access)) 167 { 168 continue; 169 } 170 171 val |= irqEnabled[int_id] << i; 172 } 173 174 return val; 175 } else if (GICD_ICENABLER.contains(addr)) { 176 // Interrupt Clear-Enable Registers 177 uint64_t val = 0x0; 178 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 179 180 if (isNotSPI(first_intid)) { 181 return 0; 182 } 183 184 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 185 i++, int_id++) { 186 187 if (nsAccessToSecInt(int_id, is_secure_access)) 188 { 189 continue; 190 } 191 192 val |= (irqEnabled[int_id] << i); 193 } 194 195 return val; 196 } else if (GICD_ISPENDR.contains(addr)) { 197 // Interrupt Set-Pending Registers 198 uint64_t val = 0x0; 199 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 200 201 if (isNotSPI(first_intid)) { 202 return 0; 203 } 204 205 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 206 i++, int_id++) { 207 208 if (nsAccessToSecInt(int_id, is_secure_access)) 209 { 210 if (irqNsacr[int_id] == 0) { 211 // Group 0 or Secure Group 1 interrupts are RAZ/WI 212 continue; 213 } 214 } 215 216 val |= (irqPending[int_id] << i); 217 } 218 219 return val; 220 } else if (GICD_ICPENDR.contains(addr)) { 221 // Interrupt Clear-Pending Registers 222 uint64_t val = 0x0; 223 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 224 225 if (isNotSPI(first_intid)) { 226 return 0; 227 } 228 229 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 230 i++, int_id++) { 231 232 if (nsAccessToSecInt(int_id, is_secure_access)) 233 { 234 if (irqNsacr[int_id] < 2) { 235 // Group 0 or Secure Group 1 interrupts are RAZ/WI 236 continue; 237 } 238 } 239 240 val |= (irqPending[int_id] << i); 241 } 242 243 return val; 244 } else if (GICD_ISACTIVER.contains(addr)) { 245 // Interrupt Set-Active Registers 246 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 247 248 if (isNotSPI(first_intid)) { 249 return 0; 250 } 251 252 uint64_t val = 0x0; 253 254 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 255 i++, int_id++) { 256 257 if (nsAccessToSecInt(int_id, is_secure_access)) 258 { 259 // Group 0 or Secure Group 1 interrupts are RAZ/WI 260 if (irqNsacr[int_id] < 2) { 261 continue; 262 } 263 } 264 265 val |= (irqActive[int_id] << i); 266 } 267 268 return val; 269 } else if (GICD_ICACTIVER.contains(addr)) { 270 // Interrupt Clear-Active Registers 271 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 272 273 if (isNotSPI(first_intid)) { 274 return 0; 275 } 276 277 uint64_t val = 0x0; 278 279 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 280 i++, int_id++) { 281 282 if (nsAccessToSecInt(int_id, is_secure_access)) 283 { 284 if (irqNsacr[int_id] < 2) { 285 continue; 286 } 287 } 288 289 val |= (irqActive[int_id] << i); 290 } 291 292 return val; 293 } else if (GICD_IPRIORITYR.contains(addr)) { 294 // Interrupt Priority Registers 295 uint64_t val = 0x0; 296 int first_intid = addr - GICD_IPRIORITYR.start(); 297 298 if (isNotSPI(first_intid)) { 299 return 0; 300 } 301 302 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 303 i++, int_id++) { 304 305 uint8_t prio = irqPriority[int_id]; 306 307 if (!DS && !is_secure_access) { 308 if (getIntGroup(int_id) != Gicv3::G1NS) { 309 // RAZ/WI for non-secure accesses for secure interrupts 310 continue; 311 } else { 312 // NS view 313 prio = (prio << 1) & 0xff; 314 } 315 } 316 317 val |= prio << (i * 8); 318 } 319 320 return val; 321 } else if (GICD_ITARGETSR.contains(addr)) { 322 // Interrupt Processor Targets Registers 323 // ARE always on, RAZ/WI 324 warn("Gicv3Distributor::read(): " 325 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 326 return 0; 327 } else if (GICD_ICFGR.contains(addr)) { 328 // Interrupt Configuration Registers 329 int first_intid = (addr - GICD_ICFGR.start()) * 4; 330 331 if (isNotSPI(first_intid)) { 332 return 0; 333 } 334 335 uint64_t val = 0x0; 336 337 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 338 i = i + 2, int_id++) { 339 340 if (nsAccessToSecInt(int_id, is_secure_access)) 341 { 342 continue; 343 } 344 345 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 346 val |= (0x2 << i); 347 } 348 } 349 350 return val; 351 } else if (GICD_IGRPMODR.contains(addr)) { 352 // Interrupt Group Modifier Registers 353 if (DS) { 354 // RAZ/WI if security disabled 355 return 0; 356 } else { 357 if (!is_secure_access) { 358 // RAZ/WI for non-secure accesses 359 return 0; 360 } else { 361 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 362 363 if (isNotSPI(first_intid)) { 364 return 0; 365 } 366 367 uint64_t val = 0x0; 368 369 for (int i = 0, int_id = first_intid; 370 i < 8 * size && int_id < itLines; i++, int_id++) { 371 val |= irqGrpmod[int_id] << i; 372 } 373 374 return val; 375 } 376 } 377 } else if (GICD_NSACR.contains(addr)) { 378 // Non-secure Access Control Registers 379 // 2 bits per interrupt 380 int first_intid = (addr - GICD_NSACR.start()) * 4; 381 382 if (isNotSPI(first_intid)) { 383 return 0; 384 } 385 386 if (DS || (!DS && !is_secure_access)) { 387 return 0; 388 } 389 390 uint64_t val = 0x0; 391 392 for (int i = 0, int_id = first_intid; 393 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 394 val |= irqNsacr[int_id] << i; 395 } 396 397 return val; 398 } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers 399 // ARE always on, RAZ/WI 400 warn("Gicv3Distributor::read(): " 401 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n"); 402 return 0x0; 403 } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers 404 // ARE always on, RAZ/WI 405 warn("Gicv3Distributor::read(): " 406 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n"); 407 return 0x0; 408 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 409 // 64 bit registers. 2 or 1 access. 410 int int_id = (addr - GICD_IROUTER.start()) / 8; 411 412 if (isNotSPI(int_id)) { 413 return 0; 414 } 415 416 if (nsAccessToSecInt(int_id, is_secure_access)) 417 { 418 if (irqNsacr[int_id] < 3) { 419 return 0; 420 } 421 } 422 423 if (size == 4) { 424 if (addr & 7) { // high half of 64 bit register 425 return irqAffinityRouting[int_id] >> 32; 426 } else { // high low of 64 bit register 427 return irqAffinityRouting[int_id] & 0xFFFFFFFF; 428 } 429 } else { 430 return irqAffinityRouting[int_id]; 431 } 432 } 433 434 switch (addr) { 435 case GICD_CTLR: // Control Register 436 if (!DS) { 437 if (is_secure_access) { 438 // E1NWF [7] RAZ/WI 439 // DS [6] - Disable Security 440 // ARE_NS [5] RAO/WI 441 // ARE_S [4] RAO/WI 442 // EnableGrp1S [2] 443 // EnableGrp1NS [1] 444 // EnableGrp0 [0] 445 return (EnableGrp0 << 0) | 446 (EnableGrp1NS << 1) | 447 (EnableGrp1S << 2) | 448 (1 << 4) | 449 (1 << 5) | 450 (DS << 6); 451 } else { 452 // ARE_NS [4] RAO/WI; 453 // EnableGrp1A [1] is a read-write alias of the Secure 454 // GICD_CTLR.EnableGrp1NS 455 // EnableGrp1 [0] RES0 456 return (1 << 4) | (EnableGrp1NS << 1); 457 } 458 } else { 459 return (DS << 6) | (ARE << 4) | 460 (EnableGrp1NS << 1) | (EnableGrp0 << 0); 461 } 462 463 case GICD_TYPER: // Interrupt Controller Type Register 464 /* 465 * RSS [26] == 1 466 * (The implementation does supports targeted SGIs with affinity 467 * level 0 values of 0 - 255) 468 * No1N [25] == 1 469 * (1 of N SPI interrupts are not supported) 470 * A3V [24] == 1 471 * (Supports nonzero values of Affinity level 3) 472 * IDbits [23:19] == 0xf 473 * (The number of interrupt identifier bits supported, minus one) 474 * DVIS [18] == 0 475 * (The implementation does not support Direct Virtual LPI 476 * injection) 477 * LPIS [17] == 1 478 * (The implementation does not support LPIs) 479 * MBIS [16] == 1 480 * (The implementation supports message-based interrupts 481 * by writing to Distributor registers) 482 * SecurityExtn [10] == X 483 * (The GIC implementation supports two Security states) 484 * CPUNumber [7:5] == 0 485 * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy]) 486 * ITLinesNumber [4:0] == N 487 * (MaxSPIIntId = 32 (N + 1) - 1) 488 */ 489 { 490 int max_spi_int_id = itLines - 1; 491 int it_lines_number = ceil((max_spi_int_id + 1) / 32.0) - 1; 492 return (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) | 493 (1 << 17) | (1 << 16) | 494 (gic->getSystem()->haveSecurity() << 10) | 495 (it_lines_number << 0); 496 } 497 498 case GICD_IIDR: // Implementer Identification Register 499 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 500 return 0; 501 502 case GICD_STATUSR: // Error Reporting Status Register 503 // Optional register, RAZ/WI 504 return 0x0; 505 506 case GICD_PIDR0: // Peripheral ID0 Register 507 return gicdPidr0; 508 509 case GICD_PIDR1: // Peripheral ID1 Register 510 return gicdPidr1; 511 512 case GICD_PIDR2: // Peripheral ID2 Register 513 return gicdPidr2; 514 515 case GICD_PIDR3: // Peripheral ID3 Register 516 return gicdPidr3; 517 518 case GICD_PIDR4: // Peripheral ID4 Register 519 return gicdPidr4; 520 521 case GICD_PIDR5: // Peripheral ID5 Register 522 case GICD_PIDR6: // Peripheral ID6 Register 523 case GICD_PIDR7: // Peripheral ID7 Register 524 return 0; // RES0 525 526 default: 527 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); 528 break; 529 } 530} 531 532void 533Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, 534 bool is_secure_access) 535{ 536 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 537 if (!DS && !is_secure_access) { 538 // RAZ/WI for non-secure accesses 539 return; 540 } 541 542 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 543 544 if (isNotSPI(first_intid)) { 545 return; 546 } 547 548 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 549 i++, int_id++) { 550 irqGroup[int_id] = data & (1 << i) ? 1 : 0; 551 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n", 552 int_id, irqGroup[int_id]); 553 } 554 555 return; 556 } else if (GICD_ISENABLER.contains(addr)) { 557 // Interrupt Set-Enable Registers 558 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 559 560 if (isNotSPI(first_intid)) { 561 return; 562 } 563 564 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 565 i++, int_id++) { 566 567 if (nsAccessToSecInt(int_id, is_secure_access)) 568 { 569 continue; 570 } 571 572 bool enable = data & (1 << i) ? 1 : 0; 573 574 if (enable) { 575 if (!irqEnabled[int_id]) { 576 DPRINTF(GIC, "Gicv3Distributor::write(): " 577 "int_id %d enabled\n", int_id); 578 } 579 580 irqEnabled[int_id] = true; 581 } 582 } 583 584 return; 585 } else if (GICD_ICENABLER.contains(addr)) { 586 // Interrupt Clear-Enable Registers 587 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 588 589 if (isNotSPI(first_intid)) { 590 return; 591 } 592 593 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 594 i++, int_id++) { 595 596 if (nsAccessToSecInt(int_id, is_secure_access)) 597 { 598 continue; 599 } 600 601 bool disable = data & (1 << i) ? 1 : 0; 602 603 if (disable) { 604 if (irqEnabled[int_id]) { 605 DPRINTF(GIC, "Gicv3Distributor::write(): " 606 "int_id %d disabled\n", int_id); 607 } 608 609 irqEnabled[int_id] = false; 610 } 611 } 612 613 return; 614 } else if (GICD_ISPENDR.contains(addr)) { 615 // Interrupt Set-Pending Registers 616 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 617 618 if (isNotSPI(first_intid)) { 619 return; 620 } 621 622 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 623 i++, int_id++) { 624 625 if (nsAccessToSecInt(int_id, is_secure_access)) 626 { 627 if (irqNsacr[int_id] == 0) { 628 // Group 0 or Secure Group 1 interrupts are RAZ/WI 629 continue; 630 } 631 } 632 633 bool pending = data & (1 << i) ? 1 : 0; 634 635 if (pending) { 636 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 637 "int_id %d (SPI) pending bit set\n", int_id); 638 irqPending[int_id] = true; 639 } 640 } 641 642 update(); 643 return; 644 } else if (GICD_ICPENDR.contains(addr)) { 645 // Interrupt Clear-Pending Registers 646 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 647 648 if (isNotSPI(first_intid)) { 649 return; 650 } 651 652 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 653 i++, int_id++) { 654 655 if (nsAccessToSecInt(int_id, is_secure_access)) 656 { 657 if (irqNsacr[int_id] < 2) { 658 // Group 0 or Secure Group 1 interrupts are RAZ/WI 659 continue; 660 } 661 } 662 663 bool clear = data & (1 << i) ? 1 : 0; 664 665 if (clear) { 666 irqPending[int_id] = false; 667 clearIrqCpuInterface(int_id); 668 } 669 } 670 671 update(); 672 return; 673 } else if (GICD_ISACTIVER.contains(addr)) { 674 // Interrupt Set-Active Registers 675 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 676 677 if (isNotSPI(first_intid)) { 678 return; 679 } 680 681 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 682 i++, int_id++) { 683 684 if (nsAccessToSecInt(int_id, is_secure_access)) 685 { 686 continue; 687 } 688 689 bool active = data & (1 << i) ? 1 : 0; 690 691 if (active) { 692 irqActive[int_id] = 1; 693 } 694 } 695 696 return; 697 } else if (GICD_ICACTIVER.contains(addr)) { 698 // Interrupt Clear-Active Registers 699 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 700 701 if (isNotSPI(first_intid)) { 702 return; 703 } 704 705 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 706 i++, int_id++) { 707 708 if (nsAccessToSecInt(int_id, is_secure_access)) 709 { 710 continue; 711 } 712 713 bool clear = data & (1 << i) ? 1 : 0; 714 715 if (clear) { 716 if (irqActive[int_id]) { 717 DPRINTF(GIC, "Gicv3Distributor::write(): " 718 "int_id %d active cleared\n", int_id); 719 } 720 721 irqActive[int_id] = false; 722 } 723 } 724 725 return; 726 } else if (GICD_IPRIORITYR.contains(addr)) { 727 // Interrupt Priority Registers 728 int first_intid = addr - GICD_IPRIORITYR.start(); 729 730 if (isNotSPI(first_intid)) { 731 return; 732 } 733 734 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 735 i++, int_id++) { 736 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 737 738 if (!DS && !is_secure_access) { 739 if (getIntGroup(int_id) != Gicv3::G1NS) { 740 // RAZ/WI for non-secure accesses to secure interrupts 741 continue; 742 } else { 743 prio = 0x80 | (prio >> 1); 744 } 745 } 746 747 irqPriority[int_id] = prio; 748 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 749 int_id, irqPriority[int_id]); 750 } 751 752 return; 753 } else if (GICD_ITARGETSR.contains(addr)) { 754 // Interrupt Processor Targets Registers 755 // ARE always on, RAZ/WI 756 warn("Gicv3Distributor::write(): " 757 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 758 return; 759 } else if (GICD_ICFGR.contains(addr)) { 760 // Interrupt Configuration Registers 761 // for x = 0 to 15: 762 // GICD_ICFGR[2x] = RES0 763 // GICD_ICFGR[2x + 1] = 764 // 0 level-sensitive 765 // 1 edge-triggered 766 int first_intid = (addr - GICD_ICFGR.start()) * 4; 767 768 if (isNotSPI(first_intid)) { 769 return; 770 } 771 772 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 773 i = i + 2, int_id++) { 774 irqConfig[int_id] = data & (0x2 << i) ? 775 Gicv3::INT_EDGE_TRIGGERED : 776 Gicv3::INT_LEVEL_SENSITIVE; 777 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 778 int_id, irqConfig[int_id]); 779 } 780 781 return; 782 } else if (GICD_IGRPMODR.contains(addr)) { 783 // Interrupt Group Modifier Registers 784 if (DS) { 785 return; 786 } else { 787 if (!is_secure_access) { 788 // RAZ/WI for non-secure accesses 789 return; 790 } else { 791 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 792 793 if (isNotSPI(first_intid)) { 794 return; 795 } 796 797 for (int i = 0, int_id = first_intid; 798 i < 8 * size && int_id < itLines; i++, int_id++) { 799 irqGrpmod[int_id] = bits(data, i); 800 } 801 802 return ; 803 } 804 } 805 806 } else if (GICD_NSACR.contains(addr)) { 807 // Non-secure Access Control Registers 808 // 2 bits per interrupt 809 int first_intid = (addr - GICD_NSACR.start()) * 4; 810 811 if (isNotSPI(first_intid)) { 812 return; 813 } 814 815 if (DS || (!DS && !is_secure_access)) { 816 return; 817 } 818 819 for (int i = 0, int_id = first_intid; 820 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 821 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 822 } 823 824 return; 825 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 826 // 64 bit registers. 2 accesses. 827 int int_id = (addr - GICD_IROUTER.start()) / 8; 828 829 if (isNotSPI(int_id)) { 830 return; 831 } 832 833 if (nsAccessToSecInt(int_id, is_secure_access)) 834 { 835 if (irqNsacr[int_id] < 3) { 836 // Group 0 or Secure Group 1 interrupts are RAZ/WI 837 return; 838 } 839 } 840 841 if (size == 4) { 842 if (addr & 7) { // high half of 64 bit register 843 irqAffinityRouting[int_id] = 844 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 845 } else { // low half of 64 bit register 846 irqAffinityRouting[int_id] = 847 (irqAffinityRouting[int_id] & 0xffffffff00000000) | 848 (data & 0xffffffff); 849 } 850 } else { 851 irqAffinityRouting[int_id] = data; 852 } 853 854 DPRINTF(GIC, "Gicv3Distributor::write(): " 855 "int_id %d GICD_IROUTER %#llx\n", 856 int_id, irqAffinityRouting[int_id]); 857 return; 858 } 859 860 switch (addr) { 861 case GICD_CTLR: // Control Register 862 if (DS) { 863 /* 864 * E1NWF [7] 865 * 1 of N wakeup functionality not supported, RAZ/WI 866 * DS [6] - RAO/WI 867 * ARE [4] 868 * affinity routing always on, no GICv2 legacy, RAO/WI 869 * EnableGrp1 [1] 870 * EnableGrp0 [0] 871 */ 872 if ((data & (1 << 4)) == 0) { 873 warn("Gicv3Distributor::write(): " 874 "setting ARE to 0 is not supported!\n"); 875 } 876 877 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 878 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 879 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 880 "EnableGrp1NS %d EnableGrp0 %d\n", 881 EnableGrp1NS, EnableGrp0); 882 } else { 883 if (is_secure_access) { 884 /* 885 * E1NWF [7] 886 * 1 of N wakeup functionality not supported, RAZ/WI 887 * DS [6] 888 * ARE_NS [5] 889 * affinity routing always on, no GICv2 legacy, RAO/WI 890 * ARE_S [4] 891 * affinity routing always on, no GICv2 legacy, RAO/WI 892 * EnableGrp1S [2] 893 * EnableGrp1NS [1] 894 * EnableGrp0 [0] 895 */ 896 if ((data & (1 << 5)) == 0) { 897 warn("Gicv3Distributor::write(): " 898 "setting ARE_NS to 0 is not supported!\n"); 899 } 900 901 if ((data & (1 << 4)) == 0) { 902 warn("Gicv3Distributor::write(): " 903 "setting ARE_S to 0 is not supported!\n"); 904 } 905 906 DS = data & GICD_CTLR_DS; 907 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 908 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 909 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 910 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 911 "DS %d " 912 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 913 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 914 915 if (data & GICD_CTLR_DS) { 916 EnableGrp1S = 0; 917 } 918 } else { 919 /* 920 * ARE_NS [4] RAO/WI; 921 * EnableGrp1A [1] is a read-write alias of the Secure 922 * GICD_CTLR.EnableGrp1NS 923 * EnableGrp1 [0] RES0 924 */ 925 if ((data & (1 << 4)) == 0) { 926 warn("Gicv3Distributor::write(): " 927 "setting ARE_NS to 0 is not supported!\n"); 928 } 929 930 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 931 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 932 "EnableGrp1NS %d\n", EnableGrp1NS); 933 } 934 } 935 936 update(); 937 938 break; 939 940 case GICD_SGIR: // Error Reporting Status Register 941 // Only if affinity routing is disabled, RES0 942 break; 943 944 case GICD_SETSPI_NSR: { 945 // Writes to this register have no effect if: 946 // * The value written specifies an invalid SPI. 947 // * The SPI is already pending. 948 // * The value written specifies a Secure SPI, the value is 949 // written by a Non-secure access, and the value of the 950 // corresponding GICD_NSACR<n> register is 0. 951 const uint32_t intid = bits(data, 9, 0); 952 if (isNotSPI(intid) || irqPending[intid] || 953 (nsAccessToSecInt(intid, is_secure_access) && 954 irqNsacr[intid] == 0)) { 955 return; 956 } else { 957 // Valid SPI, set interrupt pending 958 sendInt(intid); 959 } 960 break; 961 } 962 963 case GICD_CLRSPI_NSR: { 964 // Writes to this register have no effect if: 965 // * The value written specifies an invalid SPI. 966 // * The SPI is not pending. 967 // * The value written specifies a Secure SPI, the value is 968 // written by a Non-secure access, and the value of the 969 // corresponding GICD_NSACR<n> register is less than 0b10. 970 const uint32_t intid = bits(data, 9, 0); 971 if (isNotSPI(intid) || !irqPending[intid] || 972 (nsAccessToSecInt(intid, is_secure_access) && 973 irqNsacr[intid] < 2)) { 974 return; 975 } else { 976 // Valid SPI, clear interrupt pending 977 deassertSPI(intid); 978 } 979 break; 980 } 981 982 case GICD_SETSPI_SR: { 983 // Writes to this register have no effect if: 984 // * GICD_CTLR.DS = 1 (WI) 985 // * The value written specifies an invalid SPI. 986 // * The SPI is already pending. 987 // * The value is written by a Non-secure access. 988 const uint32_t intid = bits(data, 9, 0); 989 if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) { 990 return; 991 } else { 992 // Valid SPI, set interrupt pending 993 sendInt(intid); 994 } 995 break; 996 } 997 998 case GICD_CLRSPI_SR: { 999 // Writes to this register have no effect if: 1000 // * GICD_CTLR.DS = 1 (WI) 1001 // * The value written specifies an invalid SPI. 1002 // * The SPI is not pending. 1003 // * The value is written by a Non-secure access. 1004 const uint32_t intid = bits(data, 9, 0); 1005 if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) { 1006 return; 1007 } else { 1008 // Valid SPI, clear interrupt pending 1009 deassertSPI(intid); 1010 } 1011 break; 1012 } 1013 1014 default: 1015 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 1016 break; 1017 } 1018} 1019 1020void 1021Gicv3Distributor::sendInt(uint32_t int_id) 1022{ 1023 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1024 panic_if(int_id > itLines, "Invalid SPI!"); 1025 irqPending[int_id] = true; 1026 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 1027 "int_id %d (SPI) pending bit set\n", int_id); 1028 update(); 1029} 1030 1031void 1032Gicv3Distributor::deassertSPI(uint32_t int_id) 1033{ 1034 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1035 panic_if(int_id > itLines, "Invalid SPI!"); 1036 irqPending[int_id] = false; 1037 clearIrqCpuInterface(int_id); 1038 1039 update(); 1040} 1041 1042Gicv3CPUInterface* 1043Gicv3Distributor::route(uint32_t int_id) 1044{ 1045 IROUTER affinity_routing = irqAffinityRouting[int_id]; 1046 Gicv3Redistributor * target_redistributor = nullptr; 1047 1048 const Gicv3::GroupId int_group = getIntGroup(int_id); 1049 1050 if (affinity_routing.IRM) { 1051 // Interrupts routed to any PE defined as a participating node 1052 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1053 Gicv3Redistributor * redistributor_i = 1054 gic->getRedistributor(i); 1055 1056 if (redistributor_i-> 1057 canBeSelectedFor1toNInterrupt(int_group)) { 1058 target_redistributor = redistributor_i; 1059 break; 1060 } 1061 } 1062 } else { 1063 uint32_t affinity = (affinity_routing.Aff3 << 24) | 1064 (affinity_routing.Aff2 << 16) | 1065 (affinity_routing.Aff1 << 8) | 1066 (affinity_routing.Aff0 << 0); 1067 target_redistributor = 1068 gic->getRedistributorByAffinity(affinity); 1069 } 1070 1071 if (!target_redistributor) { 1072 // Interrrupts targeting not present cpus must remain pending 1073 return nullptr; 1074 } else { 1075 return target_redistributor->getCPUInterface(); 1076 } 1077} 1078 1079void 1080Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) 1081{ 1082 auto cpu_interface = route(int_id); 1083 if (cpu_interface) 1084 cpu_interface->hppi.prio = 0xff; 1085} 1086 1087void 1088Gicv3Distributor::update() 1089{ 1090 // Find the highest priority pending SPI 1091 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 1092 int_id++) { 1093 Gicv3::GroupId int_group = getIntGroup(int_id); 1094 bool group_enabled = groupEnabled(int_group); 1095 1096 if (irqPending[int_id] && irqEnabled[int_id] && 1097 !irqActive[int_id] && group_enabled) { 1098 1099 // Find the cpu interface where to route the interrupt 1100 Gicv3CPUInterface *target_cpu_interface = route(int_id); 1101 1102 // Invalid routing 1103 if (!target_cpu_interface) continue; 1104 1105 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 1106 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1107 int_id < target_cpu_interface->hppi.intid)) { 1108 1109 target_cpu_interface->hppi.intid = int_id; 1110 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1111 target_cpu_interface->hppi.group = int_group; 1112 } 1113 } 1114 } 1115 1116 // Update all redistributors 1117 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1118 gic->getRedistributor(i)->update(); 1119 } 1120} 1121 1122Gicv3::IntStatus 1123Gicv3Distributor::intStatus(uint32_t int_id) const 1124{ 1125 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1126 panic_if(int_id > itLines, "Invalid SPI!"); 1127 1128 if (irqPending[int_id]) { 1129 if (irqActive[int_id]) { 1130 return Gicv3::INT_ACTIVE_PENDING; 1131 } 1132 1133 return Gicv3::INT_PENDING; 1134 } else if (irqActive[int_id]) { 1135 return Gicv3::INT_ACTIVE; 1136 } else { 1137 return Gicv3::INT_INACTIVE; 1138 } 1139} 1140 1141Gicv3::GroupId 1142Gicv3Distributor::getIntGroup(int int_id) const 1143{ 1144 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1145 panic_if(int_id > itLines, "Invalid SPI!"); 1146 1147 if (DS) { 1148 if (irqGroup[int_id] == 1) { 1149 return Gicv3::G1NS; 1150 } else { 1151 return Gicv3::G0S; 1152 } 1153 } else { 1154 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 1155 return Gicv3::G0S; 1156 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 1157 return Gicv3::G1NS; 1158 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 1159 return Gicv3::G1S; 1160 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 1161 return Gicv3::G1NS; 1162 } 1163 } 1164 1165 M5_UNREACHABLE; 1166} 1167 1168void 1169Gicv3Distributor::activateIRQ(uint32_t int_id) 1170{ 1171 irqPending[int_id] = false; 1172 irqActive[int_id] = true; 1173} 1174 1175void 1176Gicv3Distributor::deactivateIRQ(uint32_t int_id) 1177{ 1178 irqActive[int_id] = false; 1179} 1180 1181void 1182Gicv3Distributor::serialize(CheckpointOut & cp) const 1183{ 1184 SERIALIZE_SCALAR(ARE); 1185 SERIALIZE_SCALAR(DS); 1186 SERIALIZE_SCALAR(EnableGrp1S); 1187 SERIALIZE_SCALAR(EnableGrp1NS); 1188 SERIALIZE_SCALAR(EnableGrp0); 1189 SERIALIZE_CONTAINER(irqGroup); 1190 SERIALIZE_CONTAINER(irqEnabled); 1191 SERIALIZE_CONTAINER(irqPending); 1192 SERIALIZE_CONTAINER(irqActive); 1193 SERIALIZE_CONTAINER(irqPriority); 1194 SERIALIZE_CONTAINER(irqConfig); 1195 SERIALIZE_CONTAINER(irqGrpmod); 1196 SERIALIZE_CONTAINER(irqNsacr); 1197 SERIALIZE_CONTAINER(irqAffinityRouting); 1198} 1199 1200void 1201Gicv3Distributor::unserialize(CheckpointIn & cp) 1202{ 1203 UNSERIALIZE_SCALAR(ARE); 1204 UNSERIALIZE_SCALAR(DS); 1205 UNSERIALIZE_SCALAR(EnableGrp1S); 1206 UNSERIALIZE_SCALAR(EnableGrp1NS); 1207 UNSERIALIZE_SCALAR(EnableGrp0); 1208 UNSERIALIZE_CONTAINER(irqGroup); 1209 UNSERIALIZE_CONTAINER(irqEnabled); 1210 UNSERIALIZE_CONTAINER(irqPending); 1211 UNSERIALIZE_CONTAINER(irqActive); 1212 UNSERIALIZE_CONTAINER(irqPriority); 1213 UNSERIALIZE_CONTAINER(irqConfig); 1214 UNSERIALIZE_CONTAINER(irqGrpmod); 1215 UNSERIALIZE_CONTAINER(irqNsacr); 1216 UNSERIALIZE_CONTAINER(irqAffinityRouting); 1217} 1218