gic_v3_redistributor.cc revision 13921
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_redistributor.hh" 32 33#include "arch/arm/utility.hh" 34#include "debug/GIC.hh" 35#include "dev/arm/gic_v3_cpu_interface.hh" 36#include "dev/arm/gic_v3_distributor.hh" 37#include "mem/fs_translating_port_proxy.hh" 38 39const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400, 40 SGI_base + 0x041f); 41 42Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id) 43 : gic(gic), 44 distributor(nullptr), 45 cpuInterface(nullptr), 46 cpuId(cpu_id), 47 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 48 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 49 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 50 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 51 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 52 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 53 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 54 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 55 addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000) 56{ 57} 58 59void 60Gicv3Redistributor::init() 61{ 62 distributor = gic->getDistributor(); 63 cpuInterface = gic->getCPUInterface(cpuId); 64} 65 66void 67Gicv3Redistributor::initState() 68{ 69 reset(); 70} 71 72void 73Gicv3Redistributor::reset() 74{ 75 peInLowPowerState = true; 76 std::fill(irqGroup.begin(), irqGroup.end(), 0); 77 std::fill(irqEnabled.begin(), irqEnabled.end(), false); 78 std::fill(irqPending.begin(), irqPending.end(), false); 79 std::fill(irqActive.begin(), irqActive.end(), false); 80 std::fill(irqPriority.begin(), irqPriority.end(), 0); 81 82 // SGIs have edge-triggered behavior 83 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) { 84 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED; 85 } 86 87 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 88 std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 89 DPG1S = false; 90 DPG1NS = false; 91 DPG0 = false; 92 EnableLPIs = false; 93 lpiConfigurationTablePtr = 0; 94 lpiIDBits = 0; 95 lpiPendingTablePtr = 0; 96} 97 98uint64_t 99Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) 100{ 101 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 102 uint64_t value = 0; 103 int first_intid = addr - GICR_IPRIORITYR.start(); 104 105 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 106 uint8_t prio = irqPriority[int_id]; 107 108 if (!distributor->DS && !is_secure_access) { 109 if (getIntGroup(int_id) != Gicv3::G1NS) { 110 // RAZ/WI for non-secure accesses for secure interrupts 111 continue; 112 } else { 113 // NS view 114 prio = (prio << 1) & 0xff; 115 } 116 } 117 118 value |= prio << (i * 8); 119 } 120 121 return value; 122 } 123 124 switch (addr) { 125 case GICR_CTLR: { // Control Register 126 uint64_t value = 0; 127 128 if (DPG1S) { 129 value |= GICR_CTLR_DPG1S; 130 } 131 132 if (DPG1NS) { 133 value |= GICR_CTLR_DPG1NS; 134 } 135 136 if (DPG0) { 137 value |= GICR_CTLR_DPG0; 138 } 139 140 if (EnableLPIs) { 141 value |= GICR_CTLR_ENABLE_LPIS; 142 } 143 144 return value; 145 } 146 147 case GICR_IIDR: // Implementer Identification Register 148 //return 0x43b; // r0p0 GIC-500 149 return 0; 150 151 case GICR_TYPER: { // Type Register 152 /* 153 * Affinity_Value [63:32] == X 154 * (The identity of the PE associated with this Redistributor) 155 * CommonLPIAff [25:24] == 01 156 * (All Redistributors with the same Aff3 value must share an 157 * LPI Configuration table) 158 * Processor_Number [23:8] == X 159 * (A unique identifier for the PE) 160 * DPGS [5] == 1 161 * (GICR_CTLR.DPG* bits are supported) 162 * Last [4] == X 163 * (This Redistributor is the highest-numbered Redistributor in 164 * a series of contiguous Redistributor pages) 165 * DirectLPI [3] == 1 166 * (direct injection of LPIs supported) 167 * VLPIS [1] == 0 168 * (virtual LPIs not supported) 169 * PLPIS [0] == 1 170 * (physical LPIs supported) 171 */ 172 uint64_t affinity = getAffinity(); 173 int last = cpuId == (gic->getSystem()->numContexts() - 1); 174 return (affinity << 32) | (1 << 24) | (cpuId << 8) | 175 (1 << 5) | (last << 4) | (1 << 3) | (1 << 0); 176 } 177 178 case GICR_WAKER: // Wake Register 179 if (!distributor->DS && !is_secure_access) { 180 // RAZ/WI for non-secure accesses 181 return 0; 182 } 183 184 if (peInLowPowerState) { 185 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep; 186 } else { 187 return 0; 188 } 189 190 case GICR_PIDR0: { // Peripheral ID0 Register 191 return 0x92; // Part number, bits[7:0] 192 } 193 194 case GICR_PIDR1: { // Peripheral ID1 Register 195 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0] 196 uint8_t part_1 = 0x4; // Part number, bits[11:8] 197 return (des_0 << 4) | (part_1 << 0); 198 } 199 200 case GICR_PIDR2: { // Peripheral ID2 Register 201 uint8_t arch_rev = 0x3; // 0x3 GICv3 202 uint8_t jedec = 0x1; // JEP code 203 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4] 204 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0); 205 } 206 207 case GICR_PIDR3: // Peripheral ID3 Register 208 return 0x0; // Implementation defined 209 210 case GICR_PIDR4: { // Peripheral ID4 Register 211 uint8_t size = 0x4; // 64 KB software visible page 212 uint8_t des_2 = 0x4; // ARM implementation 213 return (size << 4) | (des_2 << 0); 214 } 215 216 case GICR_PIDR5: // Peripheral ID5 Register 217 case GICR_PIDR6: // Peripheral ID6 Register 218 case GICR_PIDR7: // Peripheral ID7 Register 219 return 0; // RES0 220 221 case GICR_IGROUPR0: { // Interrupt Group Register 0 222 uint64_t value = 0; 223 224 if (!distributor->DS && !is_secure_access) { 225 // RAZ/WI for non-secure accesses 226 return 0; 227 } 228 229 for (int int_id = 0; int_id < 8 * size; int_id++) { 230 value |= (irqGroup[int_id] << int_id); 231 } 232 233 return value; 234 } 235 236 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 237 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0 238 uint64_t value = 0; 239 240 for (int int_id = 0; int_id < 8 * size; int_id++) { 241 if (!distributor->DS && !is_secure_access) { 242 // RAZ/WI for non-secure accesses for secure interrupts 243 if (getIntGroup(int_id) != Gicv3::G1NS) { 244 continue; 245 } 246 } 247 248 if (irqEnabled[int_id]) { 249 value |= (1 << int_id); 250 } 251 } 252 253 return value; 254 } 255 256 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 257 case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0 258 uint64_t value = 0; 259 260 for (int int_id = 0; int_id < 8 * size; int_id++) { 261 if (!distributor->DS && !is_secure_access) { 262 // RAZ/WI for non-secure accesses for secure interrupts 263 if (getIntGroup(int_id) != Gicv3::G1NS) { 264 continue; 265 } 266 } 267 268 value |= (irqPending[int_id] << int_id); 269 } 270 271 return value; 272 } 273 274 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 275 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0 276 uint64_t value = 0; 277 278 for (int int_id = 0; int_id < 8 * size; int_id++) { 279 if (!distributor->DS && !is_secure_access) { 280 // RAZ/WI for non-secure accesses for secure interrupts 281 if (getIntGroup(int_id) != Gicv3::G1NS) { 282 continue; 283 } 284 } 285 286 value |= irqActive[int_id] << int_id; 287 } 288 289 return value; 290 } 291 292 case GICR_ICFGR0: // SGI Configuration Register 293 case GICR_ICFGR1: { // PPI Configuration Register 294 uint64_t value = 0; 295 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX; 296 297 for (int i = 0, int_id = first_int_id; i < 32; 298 i = i + 2, int_id++) { 299 if (!distributor->DS && !is_secure_access) { 300 // RAZ/WI for non-secure accesses for secure interrupts 301 if (getIntGroup(int_id) != Gicv3::G1NS) { 302 continue; 303 } 304 } 305 306 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 307 value |= (0x2) << i; 308 } 309 } 310 311 return value; 312 } 313 314 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 315 uint64_t value = 0; 316 317 if (distributor->DS) { 318 value = 0; 319 } else { 320 if (!is_secure_access) { 321 // RAZ/WI for non-secure accesses 322 value = 0; 323 } else { 324 for (int int_id = 0; int_id < 8 * size; int_id++) { 325 value |= irqGrpmod[int_id] << int_id; 326 } 327 } 328 } 329 330 return value; 331 } 332 333 case GICR_NSACR: { // Non-secure Access Control Register 334 uint64_t value = 0; 335 336 if (distributor->DS) { 337 // RAZ/WI 338 value = 0; 339 } else { 340 if (!is_secure_access) { 341 // RAZ/WI 342 value = 0; 343 } else { 344 for (int i = 0, int_id = 0; i < 8 * size; 345 i = i + 2, int_id++) { 346 value |= irqNsacr[int_id] << i; 347 } 348 } 349 } 350 351 return value; 352 } 353 354 case GICR_PROPBASER: // Redistributor Properties Base Address Register 355 // OuterCache, bits [58:56] 356 // 000 Memory type defined in InnerCache field 357 // Physical_Address, bits [51:12] 358 // Bits [51:12] of the physical address containing the LPI 359 // Configuration table 360 // Shareability, bits [11:10] 361 // 00 Non-shareable 362 // InnerCache, bits [9:7] 363 // 000 Device-nGnRnE 364 // IDbits, bits [4:0] 365 // limited by GICD_TYPER.IDbits 366 return lpiConfigurationTablePtr | lpiIDBits; 367 368 // Redistributor LPI Pending Table Base Address Register 369 case GICR_PENDBASER: 370 // PTZ, bit [62] 371 // Pending Table Zero 372 // OuterCache, bits [58:56] 373 // 000 Memory type defined in InnerCache field 374 // Physical_Address, bits [51:16] 375 // Bits [51:16] of the physical address containing the LPI Pending 376 // table 377 // Shareability, bits [11:10] 378 // 00 Non-shareable 379 // InnerCache, bits [9:7] 380 // 000 Device-nGnRnE 381 return lpiPendingTablePtr; 382 383 // Redistributor Synchronize Register 384 case GICR_SYNCR: 385 return 0; 386 387 default: 388 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr); 389 break; 390 } 391} 392 393void 394Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size, 395 bool is_secure_access) 396{ 397 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 398 int first_intid = addr - GICR_IPRIORITYR.start(); 399 400 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 401 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 402 403 if (!distributor->DS && !is_secure_access) { 404 if (getIntGroup(int_id) != Gicv3::G1NS) { 405 // RAZ/WI for non-secure accesses for secure interrupts 406 continue; 407 } else { 408 // NS view 409 prio = 0x80 | (prio >> 1); 410 } 411 } 412 413 irqPriority[int_id] = prio; 414 DPRINTF(GIC, "Gicv3Redistributor::write(): " 415 "int_id %d priority %d\n", int_id, irqPriority[int_id]); 416 } 417 418 return; 419 } 420 421 switch (addr) { 422 case GICR_CTLR: { 423 // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0 424 EnableLPIs = data & GICR_CTLR_ENABLE_LPIS; 425 DPG1S = data & GICR_CTLR_DPG1S; 426 DPG1NS = data & GICR_CTLR_DPG1NS; 427 DPG0 = data & GICR_CTLR_DPG0; 428 break; 429 } 430 431 case GICR_WAKER: // Wake Register 432 if (!distributor->DS && !is_secure_access) { 433 // RAZ/WI for non-secure accesses 434 return; 435 } 436 437 if (not peInLowPowerState and 438 (data & GICR_WAKER_ProcessorSleep)) { 439 DPRINTF(GIC, "Gicv3Redistributor::write(): " 440 "PE entering in low power state\n"); 441 } else if (peInLowPowerState and 442 not(data & GICR_WAKER_ProcessorSleep)) { 443 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n"); 444 } 445 446 peInLowPowerState = data & GICR_WAKER_ProcessorSleep; 447 break; 448 449 case GICR_IGROUPR0: // Interrupt Group Register 0 450 if (!distributor->DS && !is_secure_access) { 451 // RAZ/WI for non-secure accesses 452 return; 453 } 454 455 for (int int_id = 0; int_id < 8 * size; int_id++) { 456 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0; 457 DPRINTF(GIC, "Gicv3Redistributor::write(): " 458 "int_id %d group %d\n", int_id, irqGroup[int_id]); 459 } 460 461 break; 462 463 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 464 for (int int_id = 0; int_id < 8 * size; int_id++) { 465 if (!distributor->DS && !is_secure_access) { 466 // RAZ/WI for non-secure accesses for secure interrupts 467 if (getIntGroup(int_id) != Gicv3::G1NS) { 468 continue; 469 } 470 } 471 472 bool enable = data & (1 << int_id) ? 1 : 0; 473 474 if (enable) { 475 irqEnabled[int_id] = true; 476 } 477 478 DPRINTF(GIC, "Gicv3Redistributor::write(): " 479 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 480 } 481 482 break; 483 484 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0 485 for (int int_id = 0; int_id < 8 * size; int_id++) { 486 if (!distributor->DS && !is_secure_access) { 487 // RAZ/WI for non-secure accesses for secure interrupts 488 if (getIntGroup(int_id) != Gicv3::G1NS) { 489 continue; 490 } 491 } 492 493 bool disable = data & (1 << int_id) ? 1 : 0; 494 495 if (disable) { 496 irqEnabled[int_id] = false; 497 } 498 499 DPRINTF(GIC, "Gicv3Redistributor::write(): " 500 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 501 } 502 503 break; 504 505 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 506 for (int int_id = 0; int_id < 8 * size; int_id++) { 507 if (!distributor->DS && !is_secure_access) { 508 // RAZ/WI for non-secure accesses for secure interrupts 509 if (getIntGroup(int_id) != Gicv3::G1NS) { 510 continue; 511 } 512 } 513 514 bool pending = data & (1 << int_id) ? 1 : 0; 515 516 if (pending) { 517 DPRINTF(GIC, "Gicv3Redistributor::write() " 518 "(GICR_ISPENDR0): int_id %d (PPI) " 519 "pending bit set\n", int_id); 520 irqPending[int_id] = true; 521 } 522 } 523 524 updateAndInformCPUInterface(); 525 break; 526 527 case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0 528 for (int int_id = 0; int_id < 8 * size; int_id++) { 529 if (!distributor->DS && !is_secure_access) { 530 // RAZ/WI for non-secure accesses for secure interrupts 531 if (getIntGroup(int_id) != Gicv3::G1NS) { 532 continue; 533 } 534 } 535 536 bool clear = data & (1 << int_id) ? 1 : 0; 537 538 if (clear) { 539 irqPending[int_id] = false; 540 } 541 } 542 543 break; 544 545 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 546 for (int int_id = 0; int_id < 8 * size; int_id++) { 547 if (!distributor->DS && !is_secure_access) { 548 // RAZ/WI for non-secure accesses for secure interrupts 549 if (getIntGroup(int_id) != Gicv3::G1NS) { 550 continue; 551 } 552 } 553 554 bool activate = data & (1 << int_id) ? 1 : 0; 555 556 if (activate) { 557 if (!irqActive[int_id]) { 558 DPRINTF(GIC, "Gicv3Redistributor::write(): " 559 "int_id %d active set\n", int_id); 560 } 561 562 irqActive[int_id] = true; 563 } 564 } 565 566 break; 567 568 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0 569 for (int int_id = 0; int_id < 8 * size; int_id++) { 570 if (!distributor->DS && !is_secure_access) { 571 // RAZ/WI for non-secure accesses for secure interrupts 572 if (getIntGroup(int_id) != Gicv3::G1NS) { 573 continue; 574 } 575 } 576 577 bool clear = data & (1 << int_id) ? 1 : 0; 578 579 if (clear) { 580 if (irqActive[int_id]) { 581 DPRINTF(GIC, "Gicv3Redistributor::write(): " 582 "int_id %d active cleared\n", int_id); 583 } 584 585 irqActive[int_id] = false; 586 } 587 } 588 589 break; 590 591 case GICR_ICFGR1: { // PPI Configuration Register 592 int first_intid = Gicv3::SGI_MAX; 593 594 for (int i = 0, int_id = first_intid; i < 8 * size; 595 i = i + 2, int_id++) { 596 if (!distributor->DS && !is_secure_access) { 597 // RAZ/WI for non-secure accesses for secure interrupts 598 if (getIntGroup(int_id) != Gicv3::G1NS) { 599 continue; 600 } 601 } 602 603 irqConfig[int_id] = data & (0x2 << i) ? 604 Gicv3::INT_EDGE_TRIGGERED : 605 Gicv3::INT_LEVEL_SENSITIVE; 606 DPRINTF(GIC, "Gicv3Redistributor::write(): " 607 "int_id %d (PPI) config %d\n", 608 int_id, irqConfig[int_id]); 609 } 610 611 break; 612 } 613 614 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 615 if (distributor->DS) { 616 // RAZ/WI if secutiry disabled 617 } else { 618 for (int int_id = 0; int_id < 8 * size; int_id++) { 619 if (!is_secure_access) { 620 // RAZ/WI for non-secure accesses 621 continue; 622 } 623 624 irqGrpmod[int_id] = data & (1 << int_id); 625 } 626 } 627 628 break; 629 } 630 631 case GICR_NSACR: { // Non-secure Access Control Register 632 if (distributor->DS) { 633 // RAZ/WI 634 } else { 635 if (!is_secure_access) { 636 // RAZ/WI 637 } else { 638 for (int i = 0, int_id = 0; i < 8 * size; 639 i = i + 2, int_id++) { 640 irqNsacr[int_id] = (data >> i) & 0x3; 641 } 642 } 643 } 644 645 break; 646 } 647 648 case GICR_SETLPIR: // Set LPI Pending Register 649 setClrLPI(data, true); 650 break; 651 652 case GICR_CLRLPIR: // Clear LPI Pending Register 653 setClrLPI(data, false); 654 break; 655 656 case GICR_PROPBASER: { // Redistributor Properties Base Address Register 657 // OuterCache, bits [58:56] 658 // 000 Memory type defined in InnerCache field 659 // Physical_Address, bits [51:12] 660 // Bits [51:12] of the physical address containing the LPI 661 // Configuration table 662 // Shareability, bits [11:10] 663 // 00 Non-shareable 664 // InnerCache, bits [9:7] 665 // 000 Device-nGnRnE 666 // IDbits, bits [4:0] 667 // limited by GICD_TYPER.IDbits (= 0xf) 668 lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000; 669 lpiIDBits = data & 0x1f; 670 671 // 0xf here matches the value of GICD_TYPER.IDbits. 672 // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded 673 // value 674 if (lpiIDBits > 0xf) { 675 lpiIDBits = 0xf; 676 } 677 678 break; 679 } 680 681 // Redistributor LPI Pending Table Base Address Register 682 case GICR_PENDBASER: 683 // PTZ, bit [62] 684 // Pending Table Zero 685 // OuterCache, bits [58:56] 686 // 000 Memory type defined in InnerCache field 687 // Physical_Address, bits [51:16] 688 // Bits [51:16] of the physical address containing the LPI Pending 689 // table 690 // Shareability, bits [11:10] 691 // 00 Non-shareable 692 // InnerCache, bits [9:7] 693 // 000 Device-nGnRnE 694 lpiPendingTablePtr = data & 0xFFFFFFFFF0000; 695 break; 696 697 case GICR_INVLPIR: { // Redistributor Invalidate LPI Register 698 // Do nothing: no caching supported 699 break; 700 } 701 702 case GICR_INVALLR: { // Redistributor Invalidate All Register 703 // Do nothing: no caching supported 704 break; 705 } 706 707 default: 708 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr); 709 break; 710 } 711} 712 713void 714Gicv3Redistributor::sendPPInt(uint32_t int_id) 715{ 716 assert((int_id >= Gicv3::SGI_MAX) && 717 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 718 irqPending[int_id] = true; 719 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): " 720 "int_id %d (PPI) pending bit set\n", int_id); 721 updateAndInformCPUInterface(); 722} 723 724void 725Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns) 726{ 727 assert(int_id < Gicv3::SGI_MAX); 728 Gicv3::GroupId int_group = getIntGroup(int_id); 729 730 // asked for secure group 1 731 // configured as group 0 732 // send group 0 733 if (int_group == Gicv3::G0S && group == Gicv3::G1S) { 734 group = Gicv3::G0S; 735 } 736 737 if (group == Gicv3::G0S and int_group != Gicv3::G0S) { 738 return; 739 } 740 741 if (ns && distributor->DS == 0) { 742 int nsaccess = irqNsacr[int_id]; 743 744 if ((int_group == Gicv3::G0S && nsaccess < 1) || 745 (int_group == Gicv3::G1S && nsaccess < 2)) { 746 return; 747 } 748 } 749 750 irqPending[int_id] = true; 751 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): " 752 "int_id %d (SGI) pending bit set\n", int_id); 753 updateAndInformCPUInterface(); 754} 755 756Gicv3::IntStatus 757Gicv3Redistributor::intStatus(uint32_t int_id) const 758{ 759 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX); 760 761 if (irqPending[int_id]) { 762 if (irqActive[int_id]) { 763 return Gicv3::INT_ACTIVE_PENDING; 764 } 765 766 return Gicv3::INT_PENDING; 767 } else if (irqActive[int_id]) { 768 return Gicv3::INT_ACTIVE; 769 } else { 770 return Gicv3::INT_INACTIVE; 771 } 772} 773 774/* 775 * Recalculate the highest priority pending interrupt after a 776 * change to redistributor state. 777 */ 778void 779Gicv3Redistributor::update() 780{ 781 bool new_hppi = false; 782 783 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) { 784 Gicv3::GroupId int_group = getIntGroup(int_id); 785 bool group_enabled = distributor->groupEnabled(int_group); 786 787 if (irqPending[int_id] && irqEnabled[int_id] && 788 !irqActive[int_id] && group_enabled) { 789 if ((irqPriority[int_id] < cpuInterface->hppi.prio) || 790 /* 791 * Multiple pending ints with same priority. 792 * Implementation choice which one to signal. 793 * Our implementation selects the one with the lower id. 794 */ 795 (irqPriority[int_id] == cpuInterface->hppi.prio && 796 int_id < cpuInterface->hppi.intid)) { 797 cpuInterface->hppi.intid = int_id; 798 cpuInterface->hppi.prio = irqPriority[int_id]; 799 cpuInterface->hppi.group = int_group; 800 new_hppi = true; 801 } 802 } 803 } 804 805 // Check LPIs 806 if (EnableLPIs) { 807 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 808 809 const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1); 810 const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1; 811 812 uint8_t lpi_pending_table[largest_lpi_id / 8]; 813 uint8_t lpi_config_table[number_lpis]; 814 815 tc->getPhysProxy().readBlob(lpiPendingTablePtr, 816 (uint8_t *) lpi_pending_table, 817 sizeof(lpi_pending_table)); 818 819 tc->getPhysProxy().readBlob(lpiConfigurationTablePtr, 820 (uint8_t*) lpi_config_table, 821 sizeof(lpi_config_table)); 822 823 for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id; 824 lpi_id++) { 825 uint32_t lpi_pending_entry_byte = lpi_id / 8; 826 uint8_t lpi_pending_entry_bit_position = lpi_id % 8; 827 bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] & 828 1 << lpi_pending_entry_bit_position; 829 uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID; 830 831 LPIConfigurationTableEntry config_entry = 832 lpi_config_table[lpi_configuration_entry_index]; 833 834 bool lpi_is_enable = config_entry.enable; 835 836 // LPIs are always Non-secure Group 1 interrupts, 837 // in a system where two Security states are enabled. 838 Gicv3::GroupId lpi_group = Gicv3::G1NS; 839 bool group_enabled = distributor->groupEnabled(lpi_group); 840 841 if (lpi_is_pending && lpi_is_enable && group_enabled) { 842 uint8_t lpi_priority =config_entry.priority; 843 844 if ((lpi_priority < cpuInterface->hppi.prio) || 845 (lpi_priority == cpuInterface->hppi.prio && 846 lpi_id < cpuInterface->hppi.intid)) { 847 cpuInterface->hppi.intid = lpi_id; 848 cpuInterface->hppi.prio = lpi_priority; 849 cpuInterface->hppi.group = lpi_group; 850 new_hppi = true; 851 } 852 } 853 } 854 } 855 856 if (!new_hppi && cpuInterface->hppi.prio != 0xff && 857 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 858 distributor->fullUpdate(); 859 } 860} 861 862void 863Gicv3Redistributor::setClrLPI(uint64_t data, bool set) 864{ 865 if (!EnableLPIs) { 866 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if 867 // GICR_CTLR.EnableLPIs == 0. 868 return; 869 } 870 871 uint32_t lpi_id = data & 0xffffffff; 872 uint32_t largest_lpi_id = 1 << (lpiIDBits + 1); 873 874 if (lpi_id > largest_lpi_id) { 875 // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if 876 // pINTID value specifies an unimplemented LPI. 877 return; 878 } 879 880 Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8); 881 uint8_t lpi_pending_entry; 882 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 883 tc->getPhysProxy().readBlob(lpi_pending_entry_ptr, 884 (uint8_t*) &lpi_pending_entry, 885 sizeof(lpi_pending_entry)); 886 uint8_t lpi_pending_entry_bit_position = lpi_id % 8; 887 bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position); 888 889 if (set) { 890 if (is_set) { 891 // Writes to GICR_SETLPIR have not effect if the pINTID field 892 // corresponds to an LPI that is already pending. 893 return; 894 } 895 896 lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position); 897 } else { 898 if (!is_set) { 899 // Writes to GICR_SETLPIR have not effect if the pINTID field 900 // corresponds to an LPI that is not pending. 901 return; 902 } 903 904 lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position)); 905 } 906 907 tc->getPhysProxy().writeBlob(lpi_pending_entry_ptr, 908 (uint8_t*) &lpi_pending_entry, 909 sizeof(lpi_pending_entry)); 910 updateAndInformCPUInterface(); 911} 912 913void 914Gicv3Redistributor::updateAndInformCPUInterface() 915{ 916 update(); 917 cpuInterface->update(); 918} 919 920Gicv3::GroupId 921Gicv3Redistributor::getIntGroup(int int_id) const 922{ 923 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 924 925 if (distributor->DS) { 926 if (irqGroup[int_id] == 0) { 927 return Gicv3::G0S; 928 } else { 929 return Gicv3::G1NS; 930 } 931 } else { 932 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 933 return Gicv3::G0S; 934 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 935 return Gicv3::G1NS; 936 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 937 return Gicv3::G1S; 938 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 939 return Gicv3::G1NS; 940 } 941 } 942 943 M5_UNREACHABLE; 944} 945 946void 947Gicv3Redistributor::activateIRQ(uint32_t int_id) 948{ 949 irqPending[int_id] = false; 950 irqActive[int_id] = true; 951} 952 953void 954Gicv3Redistributor::deactivateIRQ(uint32_t int_id) 955{ 956 irqActive[int_id] = false; 957} 958 959uint32_t 960Gicv3Redistributor::getAffinity() const 961{ 962 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 963 uint64_t mpidr = getMPIDR(gic->getSystem(), tc); 964 /* 965 * Aff3 = MPIDR[39:32] 966 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...) 967 * Aff2 = MPIDR[23:16] 968 * Aff1 = MPIDR[15:8] 969 * Aff0 = MPIDR[7:0] 970 * affinity = Aff3.Aff2.Aff1.Aff0 971 */ 972 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff)); 973 return affinity; 974} 975 976bool 977Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const 978{ 979 if (peInLowPowerState) { 980 return false; 981 } 982 983 if (!distributor->groupEnabled(group)) { 984 return false; 985 } 986 987 if ((group == Gicv3::G1S) && DPG1S) { 988 return false; 989 } 990 991 if ((group == Gicv3::G1NS) && DPG1NS) { 992 return false; 993 } 994 995 if ((group == Gicv3::G0S) && DPG0) { 996 return false; 997 } 998 999 return true; 1000} 1001 1002void 1003Gicv3Redistributor::serialize(CheckpointOut & cp) const 1004{ 1005 SERIALIZE_SCALAR(peInLowPowerState); 1006 SERIALIZE_CONTAINER(irqGroup); 1007 SERIALIZE_CONTAINER(irqEnabled); 1008 SERIALIZE_CONTAINER(irqPending); 1009 SERIALIZE_CONTAINER(irqActive); 1010 SERIALIZE_CONTAINER(irqPriority); 1011 SERIALIZE_CONTAINER(irqConfig); 1012 SERIALIZE_CONTAINER(irqGrpmod); 1013 SERIALIZE_CONTAINER(irqNsacr); 1014 SERIALIZE_SCALAR(DPG1S); 1015 SERIALIZE_SCALAR(DPG1NS); 1016 SERIALIZE_SCALAR(DPG0); 1017 SERIALIZE_SCALAR(EnableLPIs); 1018 SERIALIZE_SCALAR(lpiConfigurationTablePtr); 1019 SERIALIZE_SCALAR(lpiIDBits); 1020 SERIALIZE_SCALAR(lpiPendingTablePtr); 1021} 1022 1023void 1024Gicv3Redistributor::unserialize(CheckpointIn & cp) 1025{ 1026 UNSERIALIZE_SCALAR(peInLowPowerState); 1027 UNSERIALIZE_CONTAINER(irqGroup); 1028 UNSERIALIZE_CONTAINER(irqEnabled); 1029 UNSERIALIZE_CONTAINER(irqPending); 1030 UNSERIALIZE_CONTAINER(irqActive); 1031 UNSERIALIZE_CONTAINER(irqPriority); 1032 UNSERIALIZE_CONTAINER(irqConfig); 1033 UNSERIALIZE_CONTAINER(irqGrpmod); 1034 UNSERIALIZE_CONTAINER(irqNsacr); 1035 UNSERIALIZE_SCALAR(DPG1S); 1036 UNSERIALIZE_SCALAR(DPG1NS); 1037 UNSERIALIZE_SCALAR(DPG0); 1038 UNSERIALIZE_SCALAR(EnableLPIs); 1039 UNSERIALIZE_SCALAR(lpiConfigurationTablePtr); 1040 UNSERIALIZE_SCALAR(lpiIDBits); 1041 UNSERIALIZE_SCALAR(lpiPendingTablePtr); 1042} 1043