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