gic_v3_distributor.cc revision 14251
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] == 0 480 * (The implementation does not support 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) | (gic->getSystem()->haveSecurity() << 10) | 494 (it_lines_number << 0); 495 } 496 497 case GICD_IIDR: // Implementer Identification Register 498 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 499 return 0; 500 501 case GICD_STATUSR: // Error Reporting Status Register 502 // Optional register, RAZ/WI 503 return 0x0; 504 505 case GICD_PIDR0: // Peripheral ID0 Register 506 return gicdPidr0; 507 508 case GICD_PIDR1: // Peripheral ID1 Register 509 return gicdPidr1; 510 511 case GICD_PIDR2: // Peripheral ID2 Register 512 return gicdPidr2; 513 514 case GICD_PIDR3: // Peripheral ID3 Register 515 return gicdPidr3; 516 517 case GICD_PIDR4: // Peripheral ID4 Register 518 return gicdPidr4; 519 520 case GICD_PIDR5: // Peripheral ID5 Register 521 case GICD_PIDR6: // Peripheral ID6 Register 522 case GICD_PIDR7: // Peripheral ID7 Register 523 return 0; // RES0 524 525 default: 526 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); 527 break; 528 } 529} 530 531void 532Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, 533 bool is_secure_access) 534{ 535 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 536 if (!DS && !is_secure_access) { 537 // RAZ/WI for non-secure accesses 538 return; 539 } 540 541 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 542 543 if (isNotSPI(first_intid)) { 544 return; 545 } 546 547 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 548 i++, int_id++) { 549 irqGroup[int_id] = data & (1 << i) ? 1 : 0; 550 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n", 551 int_id, irqGroup[int_id]); 552 } 553 554 return; 555 } else if (GICD_ISENABLER.contains(addr)) { 556 // Interrupt Set-Enable Registers 557 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 558 559 if (isNotSPI(first_intid)) { 560 return; 561 } 562 563 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 564 i++, int_id++) { 565 566 if (nsAccessToSecInt(int_id, is_secure_access)) 567 { 568 continue; 569 } 570 571 bool enable = data & (1 << i) ? 1 : 0; 572 573 if (enable) { 574 if (!irqEnabled[int_id]) { 575 DPRINTF(GIC, "Gicv3Distributor::write(): " 576 "int_id %d enabled\n", int_id); 577 } 578 579 irqEnabled[int_id] = true; 580 } 581 } 582 583 return; 584 } else if (GICD_ICENABLER.contains(addr)) { 585 // Interrupt Clear-Enable Registers 586 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 587 588 if (isNotSPI(first_intid)) { 589 return; 590 } 591 592 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 593 i++, int_id++) { 594 595 if (nsAccessToSecInt(int_id, is_secure_access)) 596 { 597 continue; 598 } 599 600 bool disable = data & (1 << i) ? 1 : 0; 601 602 if (disable) { 603 if (irqEnabled[int_id]) { 604 DPRINTF(GIC, "Gicv3Distributor::write(): " 605 "int_id %d disabled\n", int_id); 606 } 607 608 irqEnabled[int_id] = false; 609 } 610 } 611 612 return; 613 } else if (GICD_ISPENDR.contains(addr)) { 614 // Interrupt Set-Pending Registers 615 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 616 617 if (isNotSPI(first_intid)) { 618 return; 619 } 620 621 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 622 i++, int_id++) { 623 624 if (nsAccessToSecInt(int_id, is_secure_access)) 625 { 626 if (irqNsacr[int_id] == 0) { 627 // Group 0 or Secure Group 1 interrupts are RAZ/WI 628 continue; 629 } 630 } 631 632 bool pending = data & (1 << i) ? 1 : 0; 633 634 if (pending) { 635 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 636 "int_id %d (SPI) pending bit set\n", int_id); 637 irqPending[int_id] = true; 638 } 639 } 640 641 update(); 642 return; 643 } else if (GICD_ICPENDR.contains(addr)) { 644 // Interrupt Clear-Pending Registers 645 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 646 647 if (isNotSPI(first_intid)) { 648 return; 649 } 650 651 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 652 i++, int_id++) { 653 654 if (nsAccessToSecInt(int_id, is_secure_access)) 655 { 656 if (irqNsacr[int_id] < 2) { 657 // Group 0 or Secure Group 1 interrupts are RAZ/WI 658 continue; 659 } 660 } 661 662 bool clear = data & (1 << i) ? 1 : 0; 663 664 if (clear) { 665 irqPending[int_id] = false; 666 clearIrqCpuInterface(int_id); 667 } 668 } 669 670 update(); 671 return; 672 } else if (GICD_ISACTIVER.contains(addr)) { 673 // Interrupt Set-Active Registers 674 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 675 676 if (isNotSPI(first_intid)) { 677 return; 678 } 679 680 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 681 i++, int_id++) { 682 683 if (nsAccessToSecInt(int_id, is_secure_access)) 684 { 685 continue; 686 } 687 688 bool active = data & (1 << i) ? 1 : 0; 689 690 if (active) { 691 irqActive[int_id] = 1; 692 } 693 } 694 695 return; 696 } else if (GICD_ICACTIVER.contains(addr)) { 697 // Interrupt Clear-Active Registers 698 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 699 700 if (isNotSPI(first_intid)) { 701 return; 702 } 703 704 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 705 i++, int_id++) { 706 707 if (nsAccessToSecInt(int_id, is_secure_access)) 708 { 709 continue; 710 } 711 712 bool clear = data & (1 << i) ? 1 : 0; 713 714 if (clear) { 715 if (irqActive[int_id]) { 716 DPRINTF(GIC, "Gicv3Distributor::write(): " 717 "int_id %d active cleared\n", int_id); 718 } 719 720 irqActive[int_id] = false; 721 } 722 } 723 724 return; 725 } else if (GICD_IPRIORITYR.contains(addr)) { 726 // Interrupt Priority Registers 727 int first_intid = addr - GICD_IPRIORITYR.start(); 728 729 if (isNotSPI(first_intid)) { 730 return; 731 } 732 733 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 734 i++, int_id++) { 735 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 736 737 if (!DS && !is_secure_access) { 738 if (getIntGroup(int_id) != Gicv3::G1NS) { 739 // RAZ/WI for non-secure accesses to secure interrupts 740 continue; 741 } else { 742 prio = 0x80 | (prio >> 1); 743 } 744 } 745 746 irqPriority[int_id] = prio; 747 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 748 int_id, irqPriority[int_id]); 749 } 750 751 return; 752 } else if (GICD_ITARGETSR.contains(addr)) { 753 // Interrupt Processor Targets Registers 754 // ARE always on, RAZ/WI 755 warn("Gicv3Distributor::write(): " 756 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 757 return; 758 } else if (GICD_ICFGR.contains(addr)) { 759 // Interrupt Configuration Registers 760 // for x = 0 to 15: 761 // GICD_ICFGR[2x] = RES0 762 // GICD_ICFGR[2x + 1] = 763 // 0 level-sensitive 764 // 1 edge-triggered 765 int first_intid = (addr - GICD_ICFGR.start()) * 4; 766 767 if (isNotSPI(first_intid)) { 768 return; 769 } 770 771 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 772 i = i + 2, int_id++) { 773 irqConfig[int_id] = data & (0x2 << i) ? 774 Gicv3::INT_EDGE_TRIGGERED : 775 Gicv3::INT_LEVEL_SENSITIVE; 776 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 777 int_id, irqConfig[int_id]); 778 } 779 780 return; 781 } else if (GICD_IGRPMODR.contains(addr)) { 782 // Interrupt Group Modifier Registers 783 if (DS) { 784 return; 785 } else { 786 if (!is_secure_access) { 787 // RAZ/WI for non-secure accesses 788 return; 789 } else { 790 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 791 792 if (isNotSPI(first_intid)) { 793 return; 794 } 795 796 for (int i = 0, int_id = first_intid; 797 i < 8 * size && int_id < itLines; i++, int_id++) { 798 irqGrpmod[int_id] = bits(data, i); 799 } 800 801 return ; 802 } 803 } 804 805 } else if (GICD_NSACR.contains(addr)) { 806 // Non-secure Access Control Registers 807 // 2 bits per interrupt 808 int first_intid = (addr - GICD_NSACR.start()) * 4; 809 810 if (isNotSPI(first_intid)) { 811 return; 812 } 813 814 if (DS || (!DS && !is_secure_access)) { 815 return; 816 } 817 818 for (int i = 0, int_id = first_intid; 819 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 820 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 821 } 822 823 return; 824 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 825 // 64 bit registers. 2 accesses. 826 int int_id = (addr - GICD_IROUTER.start()) / 8; 827 828 if (isNotSPI(int_id)) { 829 return; 830 } 831 832 if (nsAccessToSecInt(int_id, is_secure_access)) 833 { 834 if (irqNsacr[int_id] < 3) { 835 // Group 0 or Secure Group 1 interrupts are RAZ/WI 836 return; 837 } 838 } 839 840 if (size == 4) { 841 if (addr & 7) { // high half of 64 bit register 842 irqAffinityRouting[int_id] = 843 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 844 } else { // low half of 64 bit register 845 irqAffinityRouting[int_id] = 846 (irqAffinityRouting[int_id] & 0xffffffff00000000) | 847 (data & 0xffffffff); 848 } 849 } else { 850 irqAffinityRouting[int_id] = data; 851 } 852 853 DPRINTF(GIC, "Gicv3Distributor::write(): " 854 "int_id %d GICD_IROUTER %#llx\n", 855 int_id, irqAffinityRouting[int_id]); 856 return; 857 } 858 859 switch (addr) { 860 case GICD_CTLR: // Control Register 861 if (DS) { 862 /* 863 * E1NWF [7] 864 * 1 of N wakeup functionality not supported, RAZ/WI 865 * DS [6] - RAO/WI 866 * ARE [4] 867 * affinity routing always on, no GICv2 legacy, RAO/WI 868 * EnableGrp1 [1] 869 * EnableGrp0 [0] 870 */ 871 if ((data & (1 << 4)) == 0) { 872 warn("Gicv3Distributor::write(): " 873 "setting ARE to 0 is not supported!\n"); 874 } 875 876 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 877 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 878 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 879 "EnableGrp1NS %d EnableGrp0 %d\n", 880 EnableGrp1NS, EnableGrp0); 881 } else { 882 if (is_secure_access) { 883 /* 884 * E1NWF [7] 885 * 1 of N wakeup functionality not supported, RAZ/WI 886 * DS [6] 887 * ARE_NS [5] 888 * affinity routing always on, no GICv2 legacy, RAO/WI 889 * ARE_S [4] 890 * affinity routing always on, no GICv2 legacy, RAO/WI 891 * EnableGrp1S [2] 892 * EnableGrp1NS [1] 893 * EnableGrp0 [0] 894 */ 895 if ((data & (1 << 5)) == 0) { 896 warn("Gicv3Distributor::write(): " 897 "setting ARE_NS to 0 is not supported!\n"); 898 } 899 900 if ((data & (1 << 4)) == 0) { 901 warn("Gicv3Distributor::write(): " 902 "setting ARE_S to 0 is not supported!\n"); 903 } 904 905 DS = data & GICD_CTLR_DS; 906 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 907 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 908 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 909 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 910 "DS %d " 911 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 912 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 913 914 if (data & GICD_CTLR_DS) { 915 EnableGrp1S = 0; 916 } 917 } else { 918 /* 919 * ARE_NS [4] RAO/WI; 920 * EnableGrp1A [1] is a read-write alias of the Secure 921 * GICD_CTLR.EnableGrp1NS 922 * EnableGrp1 [0] RES0 923 */ 924 if ((data & (1 << 4)) == 0) { 925 warn("Gicv3Distributor::write(): " 926 "setting ARE_NS to 0 is not supported!\n"); 927 } 928 929 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 930 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 931 "EnableGrp1NS %d\n", EnableGrp1NS); 932 } 933 } 934 935 update(); 936 937 break; 938 939 case GICD_SGIR: // Error Reporting Status Register 940 // Only if affinity routing is disabled, RES0 941 break; 942 943 default: 944 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 945 break; 946 } 947} 948 949void 950Gicv3Distributor::sendInt(uint32_t int_id) 951{ 952 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 953 panic_if(int_id > itLines, "Invalid SPI!"); 954 irqPending[int_id] = true; 955 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 956 "int_id %d (SPI) pending bit set\n", int_id); 957 update(); 958} 959 960void 961Gicv3Distributor::deassertSPI(uint32_t int_id) 962{ 963 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 964 panic_if(int_id > itLines, "Invalid SPI!"); 965 irqPending[int_id] = false; 966 clearIrqCpuInterface(int_id); 967 968 update(); 969} 970 971Gicv3CPUInterface* 972Gicv3Distributor::route(uint32_t int_id) 973{ 974 IROUTER affinity_routing = irqAffinityRouting[int_id]; 975 Gicv3Redistributor * target_redistributor = nullptr; 976 977 const Gicv3::GroupId int_group = getIntGroup(int_id); 978 979 if (affinity_routing.IRM) { 980 // Interrupts routed to any PE defined as a participating node 981 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 982 Gicv3Redistributor * redistributor_i = 983 gic->getRedistributor(i); 984 985 if (redistributor_i-> 986 canBeSelectedFor1toNInterrupt(int_group)) { 987 target_redistributor = redistributor_i; 988 break; 989 } 990 } 991 } else { 992 uint32_t affinity = (affinity_routing.Aff3 << 24) | 993 (affinity_routing.Aff2 << 16) | 994 (affinity_routing.Aff1 << 8) | 995 (affinity_routing.Aff0 << 0); 996 target_redistributor = 997 gic->getRedistributorByAffinity(affinity); 998 } 999 1000 if (!target_redistributor) { 1001 // Interrrupts targeting not present cpus must remain pending 1002 return nullptr; 1003 } else { 1004 return target_redistributor->getCPUInterface(); 1005 } 1006} 1007 1008void 1009Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) 1010{ 1011 auto cpu_interface = route(int_id); 1012 if (cpu_interface) 1013 cpu_interface->hppi.prio = 0xff; 1014} 1015 1016void 1017Gicv3Distributor::update() 1018{ 1019 // Find the highest priority pending SPI 1020 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 1021 int_id++) { 1022 Gicv3::GroupId int_group = getIntGroup(int_id); 1023 bool group_enabled = groupEnabled(int_group); 1024 1025 if (irqPending[int_id] && irqEnabled[int_id] && 1026 !irqActive[int_id] && group_enabled) { 1027 1028 // Find the cpu interface where to route the interrupt 1029 Gicv3CPUInterface *target_cpu_interface = route(int_id); 1030 1031 // Invalid routing 1032 if (!target_cpu_interface) continue; 1033 1034 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 1035 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1036 int_id < target_cpu_interface->hppi.intid)) { 1037 1038 target_cpu_interface->hppi.intid = int_id; 1039 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1040 target_cpu_interface->hppi.group = int_group; 1041 } 1042 } 1043 } 1044 1045 // Update all redistributors 1046 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1047 gic->getRedistributor(i)->update(); 1048 } 1049} 1050 1051Gicv3::IntStatus 1052Gicv3Distributor::intStatus(uint32_t int_id) const 1053{ 1054 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1055 panic_if(int_id > itLines, "Invalid SPI!"); 1056 1057 if (irqPending[int_id]) { 1058 if (irqActive[int_id]) { 1059 return Gicv3::INT_ACTIVE_PENDING; 1060 } 1061 1062 return Gicv3::INT_PENDING; 1063 } else if (irqActive[int_id]) { 1064 return Gicv3::INT_ACTIVE; 1065 } else { 1066 return Gicv3::INT_INACTIVE; 1067 } 1068} 1069 1070Gicv3::GroupId 1071Gicv3Distributor::getIntGroup(int int_id) const 1072{ 1073 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1074 panic_if(int_id > itLines, "Invalid SPI!"); 1075 1076 if (DS) { 1077 if (irqGroup[int_id] == 1) { 1078 return Gicv3::G1NS; 1079 } else { 1080 return Gicv3::G0S; 1081 } 1082 } else { 1083 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 1084 return Gicv3::G0S; 1085 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 1086 return Gicv3::G1NS; 1087 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 1088 return Gicv3::G1S; 1089 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 1090 return Gicv3::G1NS; 1091 } 1092 } 1093 1094 M5_UNREACHABLE; 1095} 1096 1097void 1098Gicv3Distributor::activateIRQ(uint32_t int_id) 1099{ 1100 irqPending[int_id] = false; 1101 irqActive[int_id] = true; 1102} 1103 1104void 1105Gicv3Distributor::deactivateIRQ(uint32_t int_id) 1106{ 1107 irqActive[int_id] = false; 1108} 1109 1110void 1111Gicv3Distributor::serialize(CheckpointOut & cp) const 1112{ 1113 SERIALIZE_SCALAR(ARE); 1114 SERIALIZE_SCALAR(DS); 1115 SERIALIZE_SCALAR(EnableGrp1S); 1116 SERIALIZE_SCALAR(EnableGrp1NS); 1117 SERIALIZE_SCALAR(EnableGrp0); 1118 SERIALIZE_CONTAINER(irqGroup); 1119 SERIALIZE_CONTAINER(irqEnabled); 1120 SERIALIZE_CONTAINER(irqPending); 1121 SERIALIZE_CONTAINER(irqActive); 1122 SERIALIZE_CONTAINER(irqPriority); 1123 SERIALIZE_CONTAINER(irqConfig); 1124 SERIALIZE_CONTAINER(irqGrpmod); 1125 SERIALIZE_CONTAINER(irqNsacr); 1126 SERIALIZE_CONTAINER(irqAffinityRouting); 1127} 1128 1129void 1130Gicv3Distributor::unserialize(CheckpointIn & cp) 1131{ 1132 UNSERIALIZE_SCALAR(ARE); 1133 UNSERIALIZE_SCALAR(DS); 1134 UNSERIALIZE_SCALAR(EnableGrp1S); 1135 UNSERIALIZE_SCALAR(EnableGrp1NS); 1136 UNSERIALIZE_SCALAR(EnableGrp0); 1137 UNSERIALIZE_CONTAINER(irqGroup); 1138 UNSERIALIZE_CONTAINER(irqEnabled); 1139 UNSERIALIZE_CONTAINER(irqPending); 1140 UNSERIALIZE_CONTAINER(irqActive); 1141 UNSERIALIZE_CONTAINER(irqPriority); 1142 UNSERIALIZE_CONTAINER(irqConfig); 1143 UNSERIALIZE_CONTAINER(irqGrpmod); 1144 UNSERIALIZE_CONTAINER(irqNsacr); 1145 UNSERIALIZE_CONTAINER(irqAffinityRouting); 1146} 1147