gic_v3_distributor.cc revision 14167
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 updateAndInformCPUInterfaces(); 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 } 667 } 668 669 updateAndInformCPUInterfaces(); 670 return; 671 } else if (GICD_ISACTIVER.contains(addr)) { 672 // Interrupt Set-Active Registers 673 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 674 675 if (isNotSPI(first_intid)) { 676 return; 677 } 678 679 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 680 i++, int_id++) { 681 682 if (nsAccessToSecInt(int_id, is_secure_access)) 683 { 684 continue; 685 } 686 687 bool active = data & (1 << i) ? 1 : 0; 688 689 if (active) { 690 irqActive[int_id] = 1; 691 } 692 } 693 694 return; 695 } else if (GICD_ICACTIVER.contains(addr)) { 696 // Interrupt Clear-Active Registers 697 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 698 699 if (isNotSPI(first_intid)) { 700 return; 701 } 702 703 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 704 i++, int_id++) { 705 706 if (nsAccessToSecInt(int_id, is_secure_access)) 707 { 708 continue; 709 } 710 711 bool clear = data & (1 << i) ? 1 : 0; 712 713 if (clear) { 714 if (irqActive[int_id]) { 715 DPRINTF(GIC, "Gicv3Distributor::write(): " 716 "int_id %d active cleared\n", int_id); 717 } 718 719 irqActive[int_id] = false; 720 } 721 } 722 723 return; 724 } else if (GICD_IPRIORITYR.contains(addr)) { 725 // Interrupt Priority Registers 726 int first_intid = addr - GICD_IPRIORITYR.start(); 727 728 if (isNotSPI(first_intid)) { 729 return; 730 } 731 732 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 733 i++, int_id++) { 734 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 735 736 if (!DS && !is_secure_access) { 737 if (getIntGroup(int_id) != Gicv3::G1NS) { 738 // RAZ/WI for non-secure accesses to secure interrupts 739 continue; 740 } else { 741 prio = 0x80 | (prio >> 1); 742 } 743 } 744 745 irqPriority[int_id] = prio; 746 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 747 int_id, irqPriority[int_id]); 748 } 749 750 return; 751 } else if (GICD_ITARGETSR.contains(addr)) { 752 // Interrupt Processor Targets Registers 753 // ARE always on, RAZ/WI 754 warn("Gicv3Distributor::write(): " 755 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 756 return; 757 } else if (GICD_ICFGR.contains(addr)) { 758 // Interrupt Configuration Registers 759 // for x = 0 to 15: 760 // GICD_ICFGR[2x] = RES0 761 // GICD_ICFGR[2x + 1] = 762 // 0 level-sensitive 763 // 1 edge-triggered 764 int first_intid = (addr - GICD_ICFGR.start()) * 4; 765 766 if (isNotSPI(first_intid)) { 767 return; 768 } 769 770 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 771 i = i + 2, int_id++) { 772 irqConfig[int_id] = data & (0x2 << i) ? 773 Gicv3::INT_EDGE_TRIGGERED : 774 Gicv3::INT_LEVEL_SENSITIVE; 775 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 776 int_id, irqConfig[int_id]); 777 } 778 779 return; 780 } else if (GICD_IGRPMODR.contains(addr)) { 781 // Interrupt Group Modifier Registers 782 if (DS) { 783 return; 784 } else { 785 if (!is_secure_access) { 786 // RAZ/WI for non-secure accesses 787 return; 788 } else { 789 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 790 791 if (isNotSPI(first_intid)) { 792 return; 793 } 794 795 for (int i = 0, int_id = first_intid; 796 i < 8 * size && int_id < itLines; i++, int_id++) { 797 irqGrpmod[int_id] = data & (0x1 << i); 798 } 799 800 return ; 801 } 802 } 803 804 } else if (GICD_NSACR.contains(addr)) { 805 // Non-secure Access Control Registers 806 // 2 bits per interrupt 807 int first_intid = (addr - GICD_NSACR.start()) * 4; 808 809 if (isNotSPI(first_intid)) { 810 return; 811 } 812 813 if (DS || (!DS && !is_secure_access)) { 814 return; 815 } 816 817 for (int i = 0, int_id = first_intid; 818 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 819 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 820 } 821 822 return; 823 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 824 // 64 bit registers. 2 accesses. 825 int int_id = (addr - GICD_IROUTER.start()) / 8; 826 827 if (isNotSPI(int_id)) { 828 return; 829 } 830 831 if (nsAccessToSecInt(int_id, is_secure_access)) 832 { 833 if (irqNsacr[int_id] < 3) { 834 // Group 0 or Secure Group 1 interrupts are RAZ/WI 835 return; 836 } 837 } 838 839 if (size == 4) { 840 if (addr & 7) { // high half of 64 bit register 841 irqAffinityRouting[int_id] = 842 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 843 } else { // low half of 64 bit register 844 irqAffinityRouting[int_id] = 845 (irqAffinityRouting[int_id] & 0xffffffff00000000) | 846 (data & 0xffffffff); 847 } 848 } else { 849 irqAffinityRouting[int_id] = data; 850 } 851 852 DPRINTF(GIC, "Gicv3Distributor::write(): " 853 "int_id %d GICD_IROUTER %#llx\n", 854 int_id, irqAffinityRouting[int_id]); 855 return; 856 } 857 858 switch (addr) { 859 case GICD_CTLR: // Control Register 860 if (DS) { 861 /* 862 * E1NWF [7] 863 * 1 of N wakeup functionality not supported, RAZ/WI 864 * DS [6] - RAO/WI 865 * ARE [4] 866 * affinity routing always on, no GICv2 legacy, RAO/WI 867 * EnableGrp1 [1] 868 * EnableGrp0 [0] 869 */ 870 if ((data & (1 << 4)) == 0) { 871 warn("Gicv3Distributor::write(): " 872 "setting ARE to 0 is not supported!\n"); 873 } 874 875 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 876 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 877 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 878 "EnableGrp1NS %d EnableGrp0 %d\n", 879 EnableGrp1NS, EnableGrp0); 880 } else { 881 if (is_secure_access) { 882 /* 883 * E1NWF [7] 884 * 1 of N wakeup functionality not supported, RAZ/WI 885 * DS [6] 886 * ARE_NS [5] 887 * affinity routing always on, no GICv2 legacy, RAO/WI 888 * ARE_S [4] 889 * affinity routing always on, no GICv2 legacy, RAO/WI 890 * EnableGrp1S [2] 891 * EnableGrp1NS [1] 892 * EnableGrp0 [0] 893 */ 894 if ((data & (1 << 5)) == 0) { 895 warn("Gicv3Distributor::write(): " 896 "setting ARE_NS to 0 is not supported!\n"); 897 } 898 899 if ((data & (1 << 4)) == 0) { 900 warn("Gicv3Distributor::write(): " 901 "setting ARE_S to 0 is not supported!\n"); 902 } 903 904 DS = data & GICD_CTLR_DS; 905 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 906 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 907 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 908 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 909 "DS %d " 910 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 911 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 912 913 if (data & GICD_CTLR_DS) { 914 EnableGrp1S = 0; 915 } 916 } else { 917 /* 918 * ARE_NS [4] RAO/WI; 919 * EnableGrp1A [1] is a read-write alias of the Secure 920 * GICD_CTLR.EnableGrp1NS 921 * EnableGrp1 [0] RES0 922 */ 923 if ((data & (1 << 4)) == 0) { 924 warn("Gicv3Distributor::write(): " 925 "setting ARE_NS to 0 is not supported!\n"); 926 } 927 928 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 929 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 930 "EnableGrp1NS %d\n", EnableGrp1NS); 931 } 932 } 933 934 break; 935 936 default: 937 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 938 break; 939 } 940} 941 942void 943Gicv3Distributor::sendInt(uint32_t int_id) 944{ 945 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 946 panic_if(int_id > itLines, "Invalid SPI!"); 947 irqPending[int_id] = true; 948 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 949 "int_id %d (SPI) pending bit set\n", int_id); 950 updateAndInformCPUInterfaces(); 951} 952 953void 954Gicv3Distributor::deassertSPI(uint32_t int_id) 955{ 956 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 957 panic_if(int_id > itLines, "Invalid SPI!"); 958 irqPending[int_id] = false; 959 updateAndInformCPUInterfaces(); 960} 961 962void 963Gicv3Distributor::updateAndInformCPUInterfaces() 964{ 965 update(); 966 967 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 968 gic->getCPUInterface(i)->update(); 969 } 970} 971 972void 973Gicv3Distributor::fullUpdate() 974{ 975 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 976 Gicv3CPUInterface * cpu_interface_i = gic->getCPUInterface(i); 977 cpu_interface_i->hppi.prio = 0xff; 978 } 979 980 update(); 981 982 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 983 Gicv3Redistributor * redistributor_i = gic->getRedistributor(i); 984 redistributor_i->update(); 985 } 986} 987 988void 989Gicv3Distributor::update() 990{ 991 std::vector<bool> new_hppi(gic->getSystem()->numContexts(), false); 992 993 // Find the highest priority pending SPI 994 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 995 int_id++) { 996 Gicv3::GroupId int_group = getIntGroup(int_id); 997 bool group_enabled = groupEnabled(int_group); 998 999 if (irqPending[int_id] && irqEnabled[int_id] && 1000 !irqActive[int_id] && group_enabled) { 1001 IROUTER affinity_routing = irqAffinityRouting[int_id]; 1002 Gicv3Redistributor * target_redistributor = nullptr; 1003 1004 if (affinity_routing.IRM) { 1005 // Interrupts routed to any PE defined as a participating node 1006 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1007 Gicv3Redistributor * redistributor_i = 1008 gic->getRedistributor(i); 1009 1010 if (redistributor_i-> 1011 canBeSelectedFor1toNInterrupt(int_group)) { 1012 target_redistributor = redistributor_i; 1013 break; 1014 } 1015 } 1016 } else { 1017 uint32_t affinity = (affinity_routing.Aff3 << 24) | 1018 (affinity_routing.Aff3 << 16) | 1019 (affinity_routing.Aff1 << 8) | 1020 (affinity_routing.Aff0 << 0); 1021 target_redistributor = 1022 gic->getRedistributorByAffinity(affinity); 1023 } 1024 1025 if (!target_redistributor) { 1026 // Interrrupts targeting not present cpus must remain pending 1027 return; 1028 } 1029 1030 Gicv3CPUInterface * target_cpu_interface = 1031 target_redistributor->getCPUInterface(); 1032 uint32_t target_cpu = target_redistributor->cpuId; 1033 1034 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 1035 /* 1036 * Multiple pending ints with same priority. 1037 * Implementation choice which one to signal. 1038 * Our implementation selects the one with the lower id. 1039 */ 1040 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1041 int_id < target_cpu_interface->hppi.intid)) { 1042 target_cpu_interface->hppi.intid = int_id; 1043 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1044 target_cpu_interface->hppi.group = int_group; 1045 new_hppi[target_cpu] = true; 1046 } 1047 } 1048 } 1049 1050 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1051 Gicv3Redistributor * redistributor_i = gic->getRedistributor(i); 1052 Gicv3CPUInterface * cpu_interface_i = 1053 redistributor_i->getCPUInterface(); 1054 1055 if (!new_hppi[i] && cpu_interface_i->hppi.prio != 0xff && 1056 cpu_interface_i->hppi.intid >= (Gicv3::SGI_MAX + Gicv3::PPI_MAX) && 1057 cpu_interface_i->hppi.intid < Gicv3::INTID_SECURE) { 1058 fullUpdate(); 1059 } 1060 } 1061} 1062 1063Gicv3::IntStatus 1064Gicv3Distributor::intStatus(uint32_t int_id) const 1065{ 1066 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1067 panic_if(int_id > itLines, "Invalid SPI!"); 1068 1069 if (irqPending[int_id]) { 1070 if (irqActive[int_id]) { 1071 return Gicv3::INT_ACTIVE_PENDING; 1072 } 1073 1074 return Gicv3::INT_PENDING; 1075 } else if (irqActive[int_id]) { 1076 return Gicv3::INT_ACTIVE; 1077 } else { 1078 return Gicv3::INT_INACTIVE; 1079 } 1080} 1081 1082Gicv3::GroupId 1083Gicv3Distributor::getIntGroup(int int_id) const 1084{ 1085 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1086 panic_if(int_id > itLines, "Invalid SPI!"); 1087 1088 if (DS) { 1089 if (irqGroup[int_id] == 1) { 1090 return Gicv3::G1NS; 1091 } else { 1092 return Gicv3::G0S; 1093 } 1094 } else { 1095 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 1096 return Gicv3::G0S; 1097 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 1098 return Gicv3::G1NS; 1099 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 1100 return Gicv3::G1S; 1101 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 1102 return Gicv3::G1NS; 1103 } 1104 } 1105 1106 M5_UNREACHABLE; 1107} 1108 1109void 1110Gicv3Distributor::activateIRQ(uint32_t int_id) 1111{ 1112 irqPending[int_id] = false; 1113 irqActive[int_id] = true; 1114} 1115 1116void 1117Gicv3Distributor::deactivateIRQ(uint32_t int_id) 1118{ 1119 irqActive[int_id] = false; 1120} 1121 1122void 1123Gicv3Distributor::serialize(CheckpointOut & cp) const 1124{ 1125 SERIALIZE_SCALAR(ARE); 1126 SERIALIZE_SCALAR(DS); 1127 SERIALIZE_SCALAR(EnableGrp1S); 1128 SERIALIZE_SCALAR(EnableGrp1NS); 1129 SERIALIZE_SCALAR(EnableGrp0); 1130 SERIALIZE_CONTAINER(irqGroup); 1131 SERIALIZE_CONTAINER(irqEnabled); 1132 SERIALIZE_CONTAINER(irqPending); 1133 SERIALIZE_CONTAINER(irqActive); 1134 SERIALIZE_CONTAINER(irqPriority); 1135 SERIALIZE_CONTAINER(irqConfig); 1136 SERIALIZE_CONTAINER(irqGrpmod); 1137 SERIALIZE_CONTAINER(irqNsacr); 1138 SERIALIZE_CONTAINER(irqAffinityRouting); 1139} 1140 1141void 1142Gicv3Distributor::unserialize(CheckpointIn & cp) 1143{ 1144 UNSERIALIZE_SCALAR(ARE); 1145 UNSERIALIZE_SCALAR(DS); 1146 UNSERIALIZE_SCALAR(EnableGrp1S); 1147 UNSERIALIZE_SCALAR(EnableGrp1NS); 1148 UNSERIALIZE_SCALAR(EnableGrp0); 1149 UNSERIALIZE_CONTAINER(irqGroup); 1150 UNSERIALIZE_CONTAINER(irqEnabled); 1151 UNSERIALIZE_CONTAINER(irqPending); 1152 UNSERIALIZE_CONTAINER(irqActive); 1153 UNSERIALIZE_CONTAINER(irqPriority); 1154 UNSERIALIZE_CONTAINER(irqConfig); 1155 UNSERIALIZE_CONTAINER(irqGrpmod); 1156 UNSERIALIZE_CONTAINER(irqNsacr); 1157 UNSERIALIZE_CONTAINER(irqAffinityRouting); 1158} 1159