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