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