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