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