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