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