gic_v3_redistributor.cc revision 13531:e6f1bf55d038
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 38const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400, 39 SGI_base + 0x041f); 40 41Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id) 42 : gic(gic), 43 distributor(nullptr), 44 cpuInterface(nullptr), 45 cpuId(cpu_id), 46 irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 47 irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 48 irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 49 irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 50 irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 51 irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 52 irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX), 53 irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX) 54{ 55} 56 57Gicv3Redistributor::~Gicv3Redistributor() 58{ 59} 60 61void 62Gicv3Redistributor::init() 63{ 64 distributor = gic->getDistributor(); 65 cpuInterface = gic->getCPUInterface(cpuId); 66} 67 68void 69Gicv3Redistributor::initState() 70{ 71 reset(); 72} 73 74void 75Gicv3Redistributor::reset() 76{ 77 peInLowPowerState = true; 78 std::fill(irqGroup.begin(), irqGroup.end(), 0); 79 std::fill(irqEnabled.begin(), irqEnabled.end(), false); 80 std::fill(irqPending.begin(), irqPending.end(), false); 81 std::fill(irqActive.begin(), irqActive.end(), false); 82 std::fill(irqPriority.begin(), irqPriority.end(), 0); 83 84 // SGIs have edge-triggered behavior 85 for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) { 86 irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED; 87 } 88 89 std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 90 std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 91 DPG1S = false; 92 DPG1NS = false; 93 DPG0 = false; 94} 95 96uint64_t 97Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access) 98{ 99 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 100 uint64_t value = 0; 101 int first_intid = addr - GICR_IPRIORITYR.start(); 102 103 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 104 uint8_t prio = irqPriority[int_id]; 105 106 if (!distributor->DS && !is_secure_access) { 107 if (getIntGroup(int_id) != Gicv3::G1NS) { 108 // RAZ/WI for non-secure accesses for secure interrupts 109 continue; 110 } else { 111 // NS view 112 prio = (prio << 1) & 0xff; 113 } 114 } 115 116 value |= prio << (i * 8); 117 } 118 119 return value; 120 } 121 122 switch (addr) { 123 case GICR_CTLR: { // Control Register 124 uint64_t value = 0; 125 126 if (DPG1S) { 127 value |= GICR_CTLR_DPG1S; 128 } 129 130 if (DPG1NS) { 131 value |= GICR_CTLR_DPG1NS; 132 } 133 134 if (DPG0) { 135 value |= GICR_CTLR_DPG0; 136 } 137 138 return value; 139 } 140 141 case GICR_IIDR: // Implementer Identification Register 142 //return 0x43b; // r0p0 GIC-500 143 return 0; 144 145 case GICR_TYPER: { // Type Register 146 /* 147 * Affinity_Value [63:32] == X 148 * (The identity of the PE associated with this Redistributor) 149 * CommonLPIAff [25:24] == 01 150 * (All Redistributors with the same Aff3 value must share an 151 * LPI Configuration table) 152 * Processor_Number [23:8] == X 153 * (A unique identifier for the PE) 154 * DPGS [5] == 1 155 * (GICR_CTLR.DPG* bits are supported) 156 * Last [4] == X 157 * (This Redistributor is the highest-numbered Redistributor in 158 * a series of contiguous Redistributor pages) 159 * DirectLPI [3] == 0 160 * (direct injection of LPIs not supported) 161 * VLPIS [1] == 0 162 * (virtual LPIs not supported) 163 * PLPIS [0] == 0 164 * (physical LPIs not supported) 165 */ 166 uint64_t affinity = getAffinity(); 167 int last = cpuId == (gic->getSystem()->numContexts() - 1); 168 return (affinity << 32) | (1 << 24) | (cpuId << 8) | 169 (1 << 5) | (last << 4); 170 } 171 172 case GICR_WAKER: // Wake Register 173 if (!distributor->DS && !is_secure_access) { 174 // RAZ/WI for non-secure accesses 175 return 0; 176 } 177 178 if (peInLowPowerState) { 179 return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep; 180 } else { 181 return 0; 182 } 183 184 case GICR_PIDR0: { // Peripheral ID0 Register 185 uint8_t part_0 = 0x92; // Part number, bits[7:0] 186 return part_0; 187 } 188 189 case GICR_PIDR1: { // Peripheral ID1 Register 190 uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0] 191 uint8_t part_1 = 0x4; // Part number, bits[11:8] 192 return (des_0 << 4) | (part_1 << 0); 193 } 194 195 case GICR_PIDR2: { // Peripheral ID2 Register 196 uint8_t arch_rev = 0x3; // 0x3 GICv3 197 uint8_t jedec = 0x1; // JEP code 198 uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4] 199 return (arch_rev << 4) | (jedec << 3) | (des_1 << 0); 200 } 201 202 case GICR_PIDR3: // Peripheral ID3 Register 203 return 0x0; // Implementation defined 204 205 case GICR_PIDR4: { // Peripheral ID4 Register 206 uint8_t size = 0x4; // 64 KB software visible page 207 uint8_t des_2 = 0x4; // ARM implementation 208 return (size << 4) | (des_2 << 0); 209 } 210 211 case GICR_PIDR5: // Peripheral ID5 Register 212 case GICR_PIDR6: // Peripheral ID6 Register 213 case GICR_PIDR7: // Peripheral ID7 Register 214 return 0; // RES0 215 216 case GICR_IGROUPR0: { // Interrupt Group Register 0 217 uint64_t value = 0; 218 219 if (!distributor->DS && !is_secure_access) { 220 // RAZ/WI for non-secure accesses 221 return 0; 222 } 223 224 for (int int_id = 0; int_id < 8 * size; int_id++) { 225 value |= (irqGroup[int_id] << int_id); 226 } 227 228 return value; 229 } 230 231 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 232 case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0 233 uint64_t value = 0; 234 235 for (int int_id = 0; int_id < 8 * size; int_id++) { 236 if (!distributor->DS && !is_secure_access) { 237 // RAZ/WI for non-secure accesses for secure interrupts 238 if (getIntGroup(int_id) != Gicv3::G1NS) { 239 continue; 240 } 241 } 242 243 if (irqEnabled[int_id]) { 244 value |= (1 << int_id); 245 } 246 } 247 248 return value; 249 } 250 251 case GICR_ISPENDR0: // Interrupt Set-Pending Register 0 252 case GICR_ICPENDR0: { // Interrupt Clear-Pending 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 value |= (irqPending[int_id] << int_id); 264 } 265 266 return value; 267 } 268 269 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 270 case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0 271 uint64_t value = 0; 272 273 for (int int_id = 0; int_id < 8 * size; int_id++) { 274 if (!distributor->DS && !is_secure_access) { 275 // RAZ/WI for non-secure accesses for secure interrupts 276 if (getIntGroup(int_id) != Gicv3::G1NS) { 277 continue; 278 } 279 } 280 281 value |= irqActive[int_id] << int_id; 282 } 283 284 return value; 285 } 286 287 case GICR_ICFGR0: // SGI Configuration Register 288 case GICR_ICFGR1: { // PPI Configuration Register 289 uint64_t value = 0; 290 uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX; 291 292 for (int i = 0, int_id = first_int_id; i < 32; 293 i = i + 2, 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 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 302 value |= (0x2) << i; 303 } 304 } 305 306 return value; 307 } 308 309 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 310 uint64_t value = 0; 311 312 if (distributor->DS) { 313 value = 0; 314 } else { 315 if (!is_secure_access) { 316 // RAZ/WI for non-secure accesses 317 value = 0; 318 } else { 319 for (int int_id = 0; int_id < 8 * size; int_id++) { 320 value |= irqGrpmod[int_id] << int_id; 321 } 322 } 323 } 324 325 return value; 326 } 327 328 case GICR_NSACR: { // Non-secure Access Control Register 329 uint64_t value = 0; 330 331 if (distributor->DS) { 332 // RAZ/WI 333 value = 0; 334 } else { 335 if (!is_secure_access) { 336 // RAZ/WI 337 value = 0; 338 } else { 339 for (int i = 0, int_id = 0; i < 8 * size; 340 i = i + 2, int_id++) { 341 value |= irqNsacr[int_id] << i; 342 } 343 } 344 } 345 346 return value; 347 } 348 349 default: 350 panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr); 351 break; 352 } 353} 354 355void 356Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size, 357 bool is_secure_access) 358{ 359 if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers 360 int first_intid = addr - GICR_IPRIORITYR.start(); 361 362 for (int i = 0, int_id = first_intid; i < size; i++, int_id++) { 363 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 364 365 if (!distributor->DS && !is_secure_access) { 366 if (getIntGroup(int_id) != Gicv3::G1NS) { 367 // RAZ/WI for non-secure accesses for secure interrupts 368 continue; 369 } else { 370 // NS view 371 prio = 0x80 | (prio >> 1); 372 } 373 } 374 375 irqPriority[int_id] = prio; 376 DPRINTF(GIC, "Gicv3Redistributor::write(): " 377 "int_id %d priority %d\n", int_id, irqPriority[int_id]); 378 } 379 380 return; 381 } 382 383 switch (addr) { 384 case GICR_CTLR: { 385 // GICR_TYPER.LPIS is 0 so Enable_LPIs is RES0 386 DPG1S = data & GICR_CTLR_DPG1S; 387 DPG1NS = data & GICR_CTLR_DPG1NS; 388 DPG0 = data & GICR_CTLR_DPG0; 389 break; 390 } 391 392 case GICR_WAKER: // Wake Register 393 if (!distributor->DS && !is_secure_access) { 394 // RAZ/WI for non-secure accesses 395 return; 396 } 397 398 if (not peInLowPowerState and 399 (data & GICR_WAKER_ProcessorSleep)) { 400 DPRINTF(GIC, "Gicv3Redistributor::write(): " 401 "PE entering in low power state\n"); 402 } else if (peInLowPowerState and 403 not(data & GICR_WAKER_ProcessorSleep)) { 404 DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n"); 405 } 406 407 peInLowPowerState = data & GICR_WAKER_ProcessorSleep; 408 break; 409 410 case GICR_IGROUPR0: // Interrupt Group Register 0 411 if (!distributor->DS && !is_secure_access) { 412 // RAZ/WI for non-secure accesses 413 return; 414 } 415 416 for (int int_id = 0; int_id < 8 * size; int_id++) { 417 irqGroup[int_id] = data & (1 << int_id) ? 1 : 0; 418 DPRINTF(GIC, "Gicv3Redistributor::write(): " 419 "int_id %d group %d\n", int_id, irqGroup[int_id]); 420 } 421 422 break; 423 424 case GICR_ISENABLER0: // Interrupt Set-Enable Register 0 425 for (int int_id = 0; int_id < 8 * size; int_id++) { 426 if (!distributor->DS && !is_secure_access) { 427 // RAZ/WI for non-secure accesses for secure interrupts 428 if (getIntGroup(int_id) != Gicv3::G1NS) { 429 continue; 430 } 431 } 432 433 bool enable = data & (1 << int_id) ? 1 : 0; 434 435 if (enable) { 436 irqEnabled[int_id] = true; 437 } 438 439 DPRINTF(GIC, "Gicv3Redistributor::write(): " 440 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 441 } 442 443 break; 444 445 case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0 446 for (int int_id = 0; int_id < 8 * size; int_id++) { 447 if (!distributor->DS && !is_secure_access) { 448 // RAZ/WI for non-secure accesses for secure interrupts 449 if (getIntGroup(int_id) != Gicv3::G1NS) { 450 continue; 451 } 452 } 453 454 bool disable = data & (1 << int_id) ? 1 : 0; 455 456 if (disable) { 457 irqEnabled[int_id] = false; 458 } 459 460 DPRINTF(GIC, "Gicv3Redistributor::write(): " 461 "int_id %d enable %i\n", int_id, irqEnabled[int_id]); 462 } 463 464 break; 465 466 case GICR_ISPENDR0: // Interrupt Set-Pending 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 pending = data & (1 << int_id) ? 1 : 0; 476 477 if (pending) { 478 DPRINTF(GIC, "Gicv3Redistributor::write() " 479 "(GICR_ISPENDR0): int_id %d (PPI) " 480 "pending bit set\n", int_id); 481 irqPending[int_id] = true; 482 } 483 } 484 485 updateAndInformCPUInterface(); 486 break; 487 488 case GICR_ICPENDR0:// Interrupt Clear-Pending 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 clear = data & (1 << int_id) ? 1 : 0; 498 499 if (clear) { 500 irqPending[int_id] = false; 501 } 502 } 503 504 break; 505 506 case GICR_ISACTIVER0: // Interrupt Set-Active Register 0 507 for (int int_id = 0; int_id < 8 * size; int_id++) { 508 if (!distributor->DS && !is_secure_access) { 509 // RAZ/WI for non-secure accesses for secure interrupts 510 if (getIntGroup(int_id) != Gicv3::G1NS) { 511 continue; 512 } 513 } 514 515 bool activate = data & (1 << int_id) ? 1 : 0; 516 517 if (activate) { 518 if (!irqActive[int_id]) { 519 DPRINTF(GIC, "Gicv3Redistributor::write(): " 520 "int_id %d active set\n", int_id); 521 } 522 523 irqActive[int_id] = true; 524 } 525 } 526 527 break; 528 529 case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0 530 for (int int_id = 0; int_id < 8 * size; int_id++) { 531 if (!distributor->DS && !is_secure_access) { 532 // RAZ/WI for non-secure accesses for secure interrupts 533 if (getIntGroup(int_id) != Gicv3::G1NS) { 534 continue; 535 } 536 } 537 538 bool clear = data & (1 << int_id) ? 1 : 0; 539 540 if (clear) { 541 if (irqActive[int_id]) { 542 DPRINTF(GIC, "Gicv3Redistributor::write(): " 543 "int_id %d active cleared\n", int_id); 544 } 545 546 irqActive[int_id] = false; 547 } 548 } 549 550 break; 551 552 case GICR_ICFGR1: { // PPI Configuration Register 553 int first_intid = Gicv3::SGI_MAX; 554 555 for (int i = 0, int_id = first_intid; i < 8 * size; 556 i = i + 2, int_id++) { 557 if (!distributor->DS && !is_secure_access) { 558 // RAZ/WI for non-secure accesses for secure interrupts 559 if (getIntGroup(int_id) != Gicv3::G1NS) { 560 continue; 561 } 562 } 563 564 irqConfig[int_id] = data & (0x2 << i) 565 ? Gicv3::INT_EDGE_TRIGGERED : 566 Gicv3::INT_LEVEL_SENSITIVE; 567 DPRINTF(GIC, "Gicv3Redistributor::write(): " 568 "int_id %d (PPI) config %d\n", 569 int_id, irqConfig[int_id]); 570 } 571 572 break; 573 } 574 575 case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0 576 if (distributor->DS) { 577 // RAZ/WI if secutiry disabled 578 } else { 579 for (int int_id = 0; int_id < 8 * size; int_id++) { 580 if (!is_secure_access) { 581 // RAZ/WI for non-secure accesses 582 continue; 583 } 584 585 irqGrpmod[int_id] = data & (1 << int_id); 586 } 587 } 588 589 break; 590 } 591 592 case GICR_NSACR: { // Non-secure Access Control Register 593 if (distributor->DS) { 594 // RAZ/WI 595 } else { 596 if (!is_secure_access) { 597 // RAZ/WI 598 } else { 599 for (int i = 0, int_id = 0; i < 8 * size; 600 i = i + 2, int_id++) { 601 irqNsacr[int_id] = (data >> i) & 0x3; 602 } 603 } 604 } 605 606 break; 607 } 608 609 default: 610 panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr); 611 break; 612 } 613} 614 615void 616Gicv3Redistributor::sendPPInt(uint32_t int_id) 617{ 618 assert((int_id >= Gicv3::SGI_MAX) && 619 (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 620 irqPending[int_id] = true; 621 DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): " 622 "int_id %d (PPI) pending bit set\n", int_id); 623 updateAndInformCPUInterface(); 624} 625 626void 627Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns) 628{ 629 assert(int_id < Gicv3::SGI_MAX); 630 Gicv3::GroupId int_group = getIntGroup(int_id); 631 632 // asked for secure group 1 633 // configured as group 0 634 // send group 0 635 if (int_group == Gicv3::G0S && group == Gicv3::G1S) { 636 group = Gicv3::G0S; 637 } 638 639 if (group == Gicv3::G0S and int_group != Gicv3::G0S) { 640 return; 641 } 642 643 if (ns && distributor->DS == 0) { 644 int nsaccess = irqNsacr[int_id]; 645 646 if ((int_group == Gicv3::G0S && nsaccess < 1) || 647 (int_group == Gicv3::G1S && nsaccess < 2)) { 648 return; 649 } 650 } 651 652 irqPending[int_id] = true; 653 DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): " 654 "int_id %d (SGI) pending bit set\n", int_id); 655 updateAndInformCPUInterface(); 656} 657 658Gicv3::IntStatus 659Gicv3Redistributor::intStatus(uint32_t int_id) 660{ 661 assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX); 662 663 if (irqPending[int_id]) { 664 if (irqActive[int_id]) { 665 return Gicv3::INT_ACTIVE_PENDING; 666 } 667 668 return Gicv3::INT_PENDING; 669 } else if (irqActive[int_id]) { 670 return Gicv3::INT_ACTIVE; 671 } else { 672 return Gicv3::INT_INACTIVE; 673 } 674} 675 676/* 677 * Recalculate the highest priority pending interrupt after a 678 * change to redistributor state. 679 */ 680void 681Gicv3Redistributor::update() 682{ 683 bool new_hppi = false; 684 685 for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) { 686 Gicv3::GroupId int_group = getIntGroup(int_id); 687 bool group_enabled = distributor->groupEnabled(int_group); 688 689 if (irqPending[int_id] && irqEnabled[int_id] && 690 !irqActive[int_id] && group_enabled) { 691 if ((irqPriority[int_id] < cpuInterface->hppi.prio) || 692 /* 693 * Multiple pending ints with same priority. 694 * Implementation choice which one to signal. 695 * Our implementation selects the one with the lower id. 696 */ 697 (irqPriority[int_id] == cpuInterface->hppi.prio && 698 int_id < cpuInterface->hppi.intid)) { 699 cpuInterface->hppi.intid = int_id; 700 cpuInterface->hppi.prio = irqPriority[int_id]; 701 cpuInterface->hppi.group = int_group; 702 new_hppi = true; 703 } 704 } 705 } 706 707 if (!new_hppi && cpuInterface->hppi.prio != 0xff && 708 cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 709 distributor->fullUpdate(); 710 } 711} 712 713void 714Gicv3Redistributor::updateAndInformCPUInterface() 715{ 716 update(); 717 cpuInterface->update(); 718} 719 720Gicv3::GroupId 721Gicv3Redistributor::getIntGroup(int int_id) 722{ 723 assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX)); 724 725 if (distributor->DS) { 726 if (irqGroup[int_id] == 0) { 727 return Gicv3::G0S; 728 } else { 729 return Gicv3::G1NS; 730 } 731 } else { 732 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 733 return Gicv3::G0S; 734 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 735 return Gicv3::G1NS; 736 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 737 return Gicv3::G1S; 738 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 739 return Gicv3::G1NS; 740 } 741 } 742 743 M5_UNREACHABLE; 744} 745 746void 747Gicv3Redistributor::activateIRQ(uint32_t int_id) 748{ 749 irqPending[int_id] = false; 750 irqActive[int_id] = true; 751} 752 753void 754Gicv3Redistributor::deactivateIRQ(uint32_t int_id) 755{ 756 irqActive[int_id] = false; 757} 758 759uint32_t 760Gicv3Redistributor::getAffinity() 761{ 762 ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId); 763 uint64_t mpidr = getMPIDR(gic->getSystem(), tc); 764 /* 765 * Aff3 = MPIDR[39:32] 766 * (Note getMPIDR() returns uint32_t so Aff3 is always 0...) 767 * Aff2 = MPIDR[23:16] 768 * Aff1 = MPIDR[15:8] 769 * Aff0 = MPIDR[7:0] 770 * affinity = Aff3.Aff2.Aff1.Aff0 771 */ 772 uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff)); 773 return affinity; 774} 775 776bool 777Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) 778{ 779 if (peInLowPowerState) { 780 return false; 781 } 782 783 if (!distributor->groupEnabled(group)) { 784 return false; 785 } 786 787 if ((group == Gicv3::G1S) && DPG1S) { 788 return false; 789 } 790 791 if ((group == Gicv3::G1NS) && DPG1NS) { 792 return false; 793 } 794 795 if ((group == Gicv3::G0S) && DPG0) { 796 return false; 797 } 798 799 return true; 800} 801 802void 803Gicv3Redistributor::serialize(CheckpointOut & cp) const 804{ 805 SERIALIZE_SCALAR(peInLowPowerState); 806 SERIALIZE_CONTAINER(irqGroup); 807 SERIALIZE_CONTAINER(irqEnabled); 808 SERIALIZE_CONTAINER(irqPending); 809 SERIALIZE_CONTAINER(irqActive); 810 SERIALIZE_CONTAINER(irqPriority); 811 SERIALIZE_CONTAINER(irqConfig); 812 SERIALIZE_CONTAINER(irqGrpmod); 813 SERIALIZE_CONTAINER(irqNsacr); 814 SERIALIZE_SCALAR(DPG1S); 815 SERIALIZE_SCALAR(DPG1NS); 816 SERIALIZE_SCALAR(DPG0); 817} 818 819void 820Gicv3Redistributor::unserialize(CheckpointIn & cp) 821{ 822 UNSERIALIZE_SCALAR(peInLowPowerState); 823 UNSERIALIZE_CONTAINER(irqGroup); 824 UNSERIALIZE_CONTAINER(irqEnabled); 825 UNSERIALIZE_CONTAINER(irqPending); 826 UNSERIALIZE_CONTAINER(irqActive); 827 UNSERIALIZE_CONTAINER(irqPriority); 828 UNSERIALIZE_CONTAINER(irqConfig); 829 UNSERIALIZE_CONTAINER(irqGrpmod); 830 UNSERIALIZE_CONTAINER(irqNsacr); 831 UNSERIALIZE_SCALAR(DPG1S); 832 UNSERIALIZE_SCALAR(DPG1NS); 833 UNSERIALIZE_SCALAR(DPG0); 834} 835