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