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