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