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_distributor.hh" 44 45#include <algorithm> 46 47#include "base/intmath.hh" 48#include "debug/GIC.hh" 49#include "dev/arm/gic_v3.hh" 50#include "dev/arm/gic_v3_cpu_interface.hh" 51#include "dev/arm/gic_v3_redistributor.hh" 52 53const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff); 54const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f); 55const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff); 56const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f); 57const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff); 58const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f); 59const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff); 60const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff); 61const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff); 62const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff); 63const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f); 64const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff); 65const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f); 66const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f); 67const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0); 68 69Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) 70 : gic(gic), 71 itLines(it_lines),
| 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_distributor.hh" 44 45#include <algorithm> 46 47#include "base/intmath.hh" 48#include "debug/GIC.hh" 49#include "dev/arm/gic_v3.hh" 50#include "dev/arm/gic_v3_cpu_interface.hh" 51#include "dev/arm/gic_v3_redistributor.hh" 52 53const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff); 54const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f); 55const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff); 56const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f); 57const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff); 58const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f); 59const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff); 60const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff); 61const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff); 62const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff); 63const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f); 64const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff); 65const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f); 66const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f); 67const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0); 68 69Gicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) 70 : gic(gic), 71 itLines(it_lines),
|
162} 163 164uint64_t 165Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) 166{ 167 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 168 uint64_t val = 0x0; 169 170 if (!DS && !is_secure_access) { 171 // RAZ/WI for non-secure accesses 172 return 0; 173 } 174 175 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 176 177 if (isNotSPI(first_intid)) { 178 return 0; 179 } 180 181 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 182 i++, int_id++) { 183 val |= irqGroup[int_id] << i; 184 } 185 186 return val; 187 } else if (GICD_ISENABLER.contains(addr)) { 188 // Interrupt Set-Enable Registers 189 uint64_t val = 0x0; 190 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 191 192 if (isNotSPI(first_intid)) { 193 return 0; 194 } 195 196 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 197 i++, int_id++) { 198 199 if (nsAccessToSecInt(int_id, is_secure_access)) 200 { 201 continue; 202 } 203 204 val |= irqEnabled[int_id] << i; 205 } 206 207 return val; 208 } else if (GICD_ICENABLER.contains(addr)) { 209 // Interrupt Clear-Enable Registers 210 uint64_t val = 0x0; 211 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 212 213 if (isNotSPI(first_intid)) { 214 return 0; 215 } 216 217 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 218 i++, int_id++) { 219 220 if (nsAccessToSecInt(int_id, is_secure_access)) 221 { 222 continue; 223 } 224 225 val |= (irqEnabled[int_id] << i); 226 } 227 228 return val; 229 } else if (GICD_ISPENDR.contains(addr)) { 230 // Interrupt Set-Pending Registers 231 uint64_t val = 0x0; 232 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 233 234 if (isNotSPI(first_intid)) { 235 return 0; 236 } 237 238 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 239 i++, int_id++) { 240 241 if (nsAccessToSecInt(int_id, is_secure_access)) 242 { 243 if (irqNsacr[int_id] == 0) { 244 // Group 0 or Secure Group 1 interrupts are RAZ/WI 245 continue; 246 } 247 } 248 249 val |= (irqPending[int_id] << i); 250 } 251 252 return val; 253 } else if (GICD_ICPENDR.contains(addr)) { 254 // Interrupt Clear-Pending Registers 255 uint64_t val = 0x0; 256 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 257 258 if (isNotSPI(first_intid)) { 259 return 0; 260 } 261 262 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 263 i++, int_id++) { 264 265 if (nsAccessToSecInt(int_id, is_secure_access)) 266 { 267 if (irqNsacr[int_id] < 2) { 268 // Group 0 or Secure Group 1 interrupts are RAZ/WI 269 continue; 270 } 271 } 272 273 val |= (irqPending[int_id] << i); 274 } 275 276 return val; 277 } else if (GICD_ISACTIVER.contains(addr)) { 278 // Interrupt Set-Active Registers 279 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 280 281 if (isNotSPI(first_intid)) { 282 return 0; 283 } 284 285 uint64_t val = 0x0; 286 287 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 288 i++, int_id++) { 289 290 if (nsAccessToSecInt(int_id, is_secure_access)) 291 { 292 // Group 0 or Secure Group 1 interrupts are RAZ/WI 293 if (irqNsacr[int_id] < 2) { 294 continue; 295 } 296 } 297 298 val |= (irqActive[int_id] << i); 299 } 300 301 return val; 302 } else if (GICD_ICACTIVER.contains(addr)) { 303 // Interrupt Clear-Active Registers 304 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 305 306 if (isNotSPI(first_intid)) { 307 return 0; 308 } 309 310 uint64_t val = 0x0; 311 312 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 313 i++, int_id++) { 314 315 if (nsAccessToSecInt(int_id, is_secure_access)) 316 { 317 if (irqNsacr[int_id] < 2) { 318 continue; 319 } 320 } 321 322 val |= (irqActive[int_id] << i); 323 } 324 325 return val; 326 } else if (GICD_IPRIORITYR.contains(addr)) { 327 // Interrupt Priority Registers 328 uint64_t val = 0x0; 329 int first_intid = addr - GICD_IPRIORITYR.start(); 330 331 if (isNotSPI(first_intid)) { 332 return 0; 333 } 334 335 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 336 i++, int_id++) { 337 338 uint8_t prio = irqPriority[int_id]; 339 340 if (!DS && !is_secure_access) { 341 if (getIntGroup(int_id) != Gicv3::G1NS) { 342 // RAZ/WI for non-secure accesses for secure interrupts 343 continue; 344 } else { 345 // NS view 346 prio = (prio << 1) & 0xff; 347 } 348 } 349 350 val |= prio << (i * 8); 351 } 352 353 return val; 354 } else if (GICD_ITARGETSR.contains(addr)) { 355 // Interrupt Processor Targets Registers 356 // ARE always on, RAZ/WI 357 warn("Gicv3Distributor::read(): " 358 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 359 return 0; 360 } else if (GICD_ICFGR.contains(addr)) { 361 // Interrupt Configuration Registers 362 int first_intid = (addr - GICD_ICFGR.start()) * 4; 363 364 if (isNotSPI(first_intid)) { 365 return 0; 366 } 367 368 uint64_t val = 0x0; 369 370 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 371 i = i + 2, int_id++) { 372 373 if (nsAccessToSecInt(int_id, is_secure_access)) 374 { 375 continue; 376 } 377 378 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 379 val |= (0x2 << i); 380 } 381 } 382 383 return val; 384 } else if (GICD_IGRPMODR.contains(addr)) { 385 // Interrupt Group Modifier Registers 386 if (DS) { 387 // RAZ/WI if security disabled 388 return 0; 389 } else { 390 if (!is_secure_access) { 391 // RAZ/WI for non-secure accesses 392 return 0; 393 } else { 394 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 395 396 if (isNotSPI(first_intid)) { 397 return 0; 398 } 399 400 uint64_t val = 0x0; 401 402 for (int i = 0, int_id = first_intid; 403 i < 8 * size && int_id < itLines; i++, int_id++) { 404 val |= irqGrpmod[int_id] << i; 405 } 406 407 return val; 408 } 409 } 410 } else if (GICD_NSACR.contains(addr)) { 411 // Non-secure Access Control Registers 412 // 2 bits per interrupt 413 int first_intid = (addr - GICD_NSACR.start()) * 4; 414 415 if (isNotSPI(first_intid)) { 416 return 0; 417 } 418 419 if (DS || (!DS && !is_secure_access)) { 420 return 0; 421 } 422 423 uint64_t val = 0x0; 424 425 for (int i = 0, int_id = first_intid; 426 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 427 val |= irqNsacr[int_id] << i; 428 } 429 430 return val; 431 } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers 432 // ARE always on, RAZ/WI 433 warn("Gicv3Distributor::read(): " 434 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n"); 435 return 0x0; 436 } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers 437 // ARE always on, RAZ/WI 438 warn("Gicv3Distributor::read(): " 439 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n"); 440 return 0x0; 441 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 442 // 64 bit registers. 2 or 1 access. 443 int int_id = (addr - GICD_IROUTER.start()) / 8; 444 445 if (isNotSPI(int_id)) { 446 return 0; 447 } 448 449 if (nsAccessToSecInt(int_id, is_secure_access)) 450 { 451 if (irqNsacr[int_id] < 3) { 452 return 0; 453 } 454 } 455 456 if (size == 4) { 457 if (addr & 7) { // high half of 64 bit register 458 return irqAffinityRouting[int_id] >> 32; 459 } else { // high low of 64 bit register 460 return irqAffinityRouting[int_id] & 0xFFFFFFFF; 461 } 462 } else { 463 return irqAffinityRouting[int_id]; 464 } 465 } 466 467 switch (addr) { 468 case GICD_CTLR: // Control Register 469 if (!DS) { 470 if (is_secure_access) { 471 // E1NWF [7] RAZ/WI 472 // DS [6] - Disable Security 473 // ARE_NS [5] RAO/WI 474 // ARE_S [4] RAO/WI 475 // EnableGrp1S [2] 476 // EnableGrp1NS [1] 477 // EnableGrp0 [0] 478 return (EnableGrp0 << 0) | 479 (EnableGrp1NS << 1) | 480 (EnableGrp1S << 2) | 481 (1 << 4) | 482 (1 << 5) | 483 (DS << 6); 484 } else { 485 // ARE_NS [4] RAO/WI; 486 // EnableGrp1A [1] is a read-write alias of the Secure 487 // GICD_CTLR.EnableGrp1NS 488 // EnableGrp1 [0] RES0 489 return (1 << 4) | (EnableGrp1NS << 1); 490 } 491 } else { 492 return (DS << 6) | (ARE << 4) | 493 (EnableGrp1NS << 1) | (EnableGrp0 << 0); 494 } 495 496 case GICD_TYPER: // Interrupt Controller Type Register 497 return gicdTyper; 498 499 case GICD_IIDR: // Implementer Identification Register 500 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 501 return 0; 502 503 case GICD_STATUSR: // Error Reporting Status Register 504 // Optional register, RAZ/WI 505 return 0x0; 506 507 case GICD_PIDR0: // Peripheral ID0 Register 508 return gicdPidr0; 509 510 case GICD_PIDR1: // Peripheral ID1 Register 511 return gicdPidr1; 512 513 case GICD_PIDR2: // Peripheral ID2 Register 514 return gicdPidr2; 515 516 case GICD_PIDR3: // Peripheral ID3 Register 517 return gicdPidr3; 518 519 case GICD_PIDR4: // Peripheral ID4 Register 520 return gicdPidr4; 521 522 case GICD_PIDR5: // Peripheral ID5 Register 523 case GICD_PIDR6: // Peripheral ID6 Register 524 case GICD_PIDR7: // Peripheral ID7 Register 525 return 0; // RES0 526 527 default: 528 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); 529 break; 530 } 531} 532 533void 534Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, 535 bool is_secure_access) 536{ 537 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 538 if (!DS && !is_secure_access) { 539 // RAZ/WI for non-secure accesses 540 return; 541 } 542 543 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 544 545 if (isNotSPI(first_intid)) { 546 return; 547 } 548 549 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 550 i++, int_id++) { 551 irqGroup[int_id] = data & (1 << i) ? 1 : 0; 552 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n", 553 int_id, irqGroup[int_id]); 554 } 555 556 return; 557 } else if (GICD_ISENABLER.contains(addr)) { 558 // Interrupt Set-Enable Registers 559 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 560 561 if (isNotSPI(first_intid)) { 562 return; 563 } 564 565 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 566 i++, int_id++) { 567 568 if (nsAccessToSecInt(int_id, is_secure_access)) 569 { 570 continue; 571 } 572 573 bool enable = data & (1 << i) ? 1 : 0; 574 575 if (enable) { 576 if (!irqEnabled[int_id]) { 577 DPRINTF(GIC, "Gicv3Distributor::write(): " 578 "int_id %d enabled\n", int_id); 579 } 580 581 irqEnabled[int_id] = true; 582 } 583 } 584 585 return; 586 } else if (GICD_ICENABLER.contains(addr)) { 587 // Interrupt Clear-Enable Registers 588 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 589 590 if (isNotSPI(first_intid)) { 591 return; 592 } 593 594 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 595 i++, int_id++) { 596 597 if (nsAccessToSecInt(int_id, is_secure_access)) 598 { 599 continue; 600 } 601 602 bool disable = data & (1 << i) ? 1 : 0; 603 604 if (disable) { 605 if (irqEnabled[int_id]) { 606 DPRINTF(GIC, "Gicv3Distributor::write(): " 607 "int_id %d disabled\n", int_id); 608 } 609 610 irqEnabled[int_id] = false; 611 } 612 } 613 614 return; 615 } else if (GICD_ISPENDR.contains(addr)) { 616 // Interrupt Set-Pending Registers 617 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 618 619 if (isNotSPI(first_intid)) { 620 return; 621 } 622 623 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 624 i++, int_id++) { 625 626 if (nsAccessToSecInt(int_id, is_secure_access)) 627 { 628 if (irqNsacr[int_id] == 0) { 629 // Group 0 or Secure Group 1 interrupts are RAZ/WI 630 continue; 631 } 632 } 633 634 bool pending = data & (1 << i) ? 1 : 0; 635 636 if (pending) { 637 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 638 "int_id %d (SPI) pending bit set\n", int_id); 639 irqPending[int_id] = true; 640 } 641 } 642 643 update(); 644 return; 645 } else if (GICD_ICPENDR.contains(addr)) { 646 // Interrupt Clear-Pending Registers 647 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 648 649 if (isNotSPI(first_intid)) { 650 return; 651 } 652 653 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 654 i++, int_id++) { 655 656 if (nsAccessToSecInt(int_id, is_secure_access)) 657 { 658 if (irqNsacr[int_id] < 2) { 659 // Group 0 or Secure Group 1 interrupts are RAZ/WI 660 continue; 661 } 662 } 663 664 bool clear = data & (1 << i) ? 1 : 0; 665 666 if (clear) { 667 irqPending[int_id] = false; 668 clearIrqCpuInterface(int_id); 669 } 670 } 671 672 update(); 673 return; 674 } else if (GICD_ISACTIVER.contains(addr)) { 675 // Interrupt Set-Active Registers 676 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 677 678 if (isNotSPI(first_intid)) { 679 return; 680 } 681 682 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 683 i++, int_id++) { 684 685 if (nsAccessToSecInt(int_id, is_secure_access)) 686 { 687 continue; 688 } 689 690 bool active = data & (1 << i) ? 1 : 0; 691 692 if (active) { 693 irqActive[int_id] = 1; 694 } 695 } 696 697 return; 698 } else if (GICD_ICACTIVER.contains(addr)) { 699 // Interrupt Clear-Active Registers 700 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 701 702 if (isNotSPI(first_intid)) { 703 return; 704 } 705 706 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 707 i++, int_id++) { 708 709 if (nsAccessToSecInt(int_id, is_secure_access)) 710 { 711 continue; 712 } 713 714 bool clear = data & (1 << i) ? 1 : 0; 715 716 if (clear) { 717 if (irqActive[int_id]) { 718 DPRINTF(GIC, "Gicv3Distributor::write(): " 719 "int_id %d active cleared\n", int_id); 720 } 721 722 irqActive[int_id] = false; 723 } 724 } 725 726 return; 727 } else if (GICD_IPRIORITYR.contains(addr)) { 728 // Interrupt Priority Registers 729 int first_intid = addr - GICD_IPRIORITYR.start(); 730 731 if (isNotSPI(first_intid)) { 732 return; 733 } 734 735 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 736 i++, int_id++) { 737 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 738 739 if (!DS && !is_secure_access) { 740 if (getIntGroup(int_id) != Gicv3::G1NS) { 741 // RAZ/WI for non-secure accesses to secure interrupts 742 continue; 743 } else { 744 prio = 0x80 | (prio >> 1); 745 } 746 } 747 748 irqPriority[int_id] = prio; 749 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 750 int_id, irqPriority[int_id]); 751 } 752 753 return; 754 } else if (GICD_ITARGETSR.contains(addr)) { 755 // Interrupt Processor Targets Registers 756 // ARE always on, RAZ/WI 757 warn("Gicv3Distributor::write(): " 758 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 759 return; 760 } else if (GICD_ICFGR.contains(addr)) { 761 // Interrupt Configuration Registers 762 // for x = 0 to 15: 763 // GICD_ICFGR[2x] = RES0 764 // GICD_ICFGR[2x + 1] = 765 // 0 level-sensitive 766 // 1 edge-triggered 767 int first_intid = (addr - GICD_ICFGR.start()) * 4; 768 769 if (isNotSPI(first_intid)) { 770 return; 771 } 772 773 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 774 i = i + 2, int_id++) { 775 irqConfig[int_id] = data & (0x2 << i) ? 776 Gicv3::INT_EDGE_TRIGGERED : 777 Gicv3::INT_LEVEL_SENSITIVE; 778 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 779 int_id, irqConfig[int_id]); 780 } 781 782 return; 783 } else if (GICD_IGRPMODR.contains(addr)) { 784 // Interrupt Group Modifier Registers 785 if (DS) { 786 return; 787 } else { 788 if (!is_secure_access) { 789 // RAZ/WI for non-secure accesses 790 return; 791 } else { 792 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 793 794 if (isNotSPI(first_intid)) { 795 return; 796 } 797 798 for (int i = 0, int_id = first_intid; 799 i < 8 * size && int_id < itLines; i++, int_id++) { 800 irqGrpmod[int_id] = bits(data, i); 801 } 802 803 return ; 804 } 805 } 806 807 } else if (GICD_NSACR.contains(addr)) { 808 // Non-secure Access Control Registers 809 // 2 bits per interrupt 810 int first_intid = (addr - GICD_NSACR.start()) * 4; 811 812 if (isNotSPI(first_intid)) { 813 return; 814 } 815 816 if (DS || (!DS && !is_secure_access)) { 817 return; 818 } 819 820 for (int i = 0, int_id = first_intid; 821 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 822 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 823 } 824 825 return; 826 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 827 // 64 bit registers. 2 accesses. 828 int int_id = (addr - GICD_IROUTER.start()) / 8; 829 830 if (isNotSPI(int_id)) { 831 return; 832 } 833 834 if (nsAccessToSecInt(int_id, is_secure_access)) 835 { 836 if (irqNsacr[int_id] < 3) { 837 // Group 0 or Secure Group 1 interrupts are RAZ/WI 838 return; 839 } 840 } 841 842 if (size == 4) { 843 if (addr & 7) { // high half of 64 bit register 844 irqAffinityRouting[int_id] = 845 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 846 } else { // low half of 64 bit register 847 irqAffinityRouting[int_id] = 848 (irqAffinityRouting[int_id] & 0xffffffff00000000) | 849 (data & 0xffffffff); 850 } 851 } else { 852 irqAffinityRouting[int_id] = data; 853 } 854 855 DPRINTF(GIC, "Gicv3Distributor::write(): " 856 "int_id %d GICD_IROUTER %#llx\n", 857 int_id, irqAffinityRouting[int_id]); 858 return; 859 } 860 861 switch (addr) { 862 case GICD_CTLR: // Control Register 863 if (DS) { 864 /* 865 * E1NWF [7] 866 * 1 of N wakeup functionality not supported, RAZ/WI 867 * DS [6] - RAO/WI 868 * ARE [4] 869 * affinity routing always on, no GICv2 legacy, RAO/WI 870 * EnableGrp1 [1] 871 * EnableGrp0 [0] 872 */ 873 if ((data & (1 << 4)) == 0) { 874 warn("Gicv3Distributor::write(): " 875 "setting ARE to 0 is not supported!\n"); 876 } 877 878 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 879 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 880 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 881 "EnableGrp1NS %d EnableGrp0 %d\n", 882 EnableGrp1NS, EnableGrp0); 883 } else { 884 if (is_secure_access) { 885 /* 886 * E1NWF [7] 887 * 1 of N wakeup functionality not supported, RAZ/WI 888 * DS [6] 889 * ARE_NS [5] 890 * affinity routing always on, no GICv2 legacy, RAO/WI 891 * ARE_S [4] 892 * affinity routing always on, no GICv2 legacy, RAO/WI 893 * EnableGrp1S [2] 894 * EnableGrp1NS [1] 895 * EnableGrp0 [0] 896 */ 897 if ((data & (1 << 5)) == 0) { 898 warn("Gicv3Distributor::write(): " 899 "setting ARE_NS to 0 is not supported!\n"); 900 } 901 902 if ((data & (1 << 4)) == 0) { 903 warn("Gicv3Distributor::write(): " 904 "setting ARE_S to 0 is not supported!\n"); 905 } 906 907 DS = data & GICD_CTLR_DS; 908 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 909 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 910 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 911 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 912 "DS %d " 913 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 914 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 915 916 if (data & GICD_CTLR_DS) { 917 EnableGrp1S = 0; 918 } 919 } else { 920 /* 921 * ARE_NS [4] RAO/WI; 922 * EnableGrp1A [1] is a read-write alias of the Secure 923 * GICD_CTLR.EnableGrp1NS 924 * EnableGrp1 [0] RES0 925 */ 926 if ((data & (1 << 4)) == 0) { 927 warn("Gicv3Distributor::write(): " 928 "setting ARE_NS to 0 is not supported!\n"); 929 } 930 931 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 932 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 933 "EnableGrp1NS %d\n", EnableGrp1NS); 934 } 935 } 936 937 update(); 938 939 break; 940 941 case GICD_SGIR: // Error Reporting Status Register 942 // Only if affinity routing is disabled, RES0 943 break; 944 945 case GICD_SETSPI_NSR: { 946 // Writes to this register have no effect if: 947 // * The value written specifies an invalid SPI. 948 // * The SPI is already pending. 949 // * The value written specifies a Secure SPI, the value is 950 // written by a Non-secure access, and the value of the 951 // corresponding GICD_NSACR<n> register is 0. 952 const uint32_t intid = bits(data, 9, 0); 953 if (isNotSPI(intid) || irqPending[intid] || 954 (nsAccessToSecInt(intid, is_secure_access) && 955 irqNsacr[intid] == 0)) { 956 return; 957 } else { 958 // Valid SPI, set interrupt pending 959 sendInt(intid); 960 } 961 break; 962 } 963 964 case GICD_CLRSPI_NSR: { 965 // Writes to this register have no effect if: 966 // * The value written specifies an invalid SPI. 967 // * The SPI is not pending. 968 // * The value written specifies a Secure SPI, the value is 969 // written by a Non-secure access, and the value of the 970 // corresponding GICD_NSACR<n> register is less than 0b10. 971 const uint32_t intid = bits(data, 9, 0); 972 if (isNotSPI(intid) || !irqPending[intid] || 973 (nsAccessToSecInt(intid, is_secure_access) && 974 irqNsacr[intid] < 2)) { 975 return; 976 } else { 977 // Valid SPI, clear interrupt pending 978 deassertSPI(intid); 979 } 980 break; 981 } 982 983 case GICD_SETSPI_SR: { 984 // Writes to this register have no effect if: 985 // * GICD_CTLR.DS = 1 (WI) 986 // * The value written specifies an invalid SPI. 987 // * The SPI is already pending. 988 // * The value is written by a Non-secure access. 989 const uint32_t intid = bits(data, 9, 0); 990 if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) { 991 return; 992 } else { 993 // Valid SPI, set interrupt pending 994 sendInt(intid); 995 } 996 break; 997 } 998 999 case GICD_CLRSPI_SR: { 1000 // Writes to this register have no effect if: 1001 // * GICD_CTLR.DS = 1 (WI) 1002 // * The value written specifies an invalid SPI. 1003 // * The SPI is not pending. 1004 // * The value is written by a Non-secure access. 1005 const uint32_t intid = bits(data, 9, 0); 1006 if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) { 1007 return; 1008 } else { 1009 // Valid SPI, clear interrupt pending 1010 deassertSPI(intid); 1011 } 1012 break; 1013 } 1014 1015 default: 1016 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 1017 break; 1018 } 1019} 1020 1021void 1022Gicv3Distributor::sendInt(uint32_t int_id) 1023{ 1024 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1025 panic_if(int_id > itLines, "Invalid SPI!"); 1026 irqPending[int_id] = true; 1027 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 1028 "int_id %d (SPI) pending bit set\n", int_id); 1029 update(); 1030} 1031 1032void 1033Gicv3Distributor::deassertSPI(uint32_t int_id) 1034{ 1035 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1036 panic_if(int_id > itLines, "Invalid SPI!"); 1037 irqPending[int_id] = false; 1038 clearIrqCpuInterface(int_id); 1039 1040 update(); 1041} 1042 1043Gicv3CPUInterface* 1044Gicv3Distributor::route(uint32_t int_id) 1045{ 1046 IROUTER affinity_routing = irqAffinityRouting[int_id]; 1047 Gicv3Redistributor * target_redistributor = nullptr; 1048 1049 const Gicv3::GroupId int_group = getIntGroup(int_id); 1050 1051 if (affinity_routing.IRM) { 1052 // Interrupts routed to any PE defined as a participating node 1053 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1054 Gicv3Redistributor * redistributor_i = 1055 gic->getRedistributor(i); 1056 1057 if (redistributor_i-> 1058 canBeSelectedFor1toNInterrupt(int_group)) { 1059 target_redistributor = redistributor_i; 1060 break; 1061 } 1062 } 1063 } else { 1064 uint32_t affinity = (affinity_routing.Aff3 << 24) | 1065 (affinity_routing.Aff2 << 16) | 1066 (affinity_routing.Aff1 << 8) | 1067 (affinity_routing.Aff0 << 0); 1068 target_redistributor = 1069 gic->getRedistributorByAffinity(affinity); 1070 } 1071 1072 if (!target_redistributor) { 1073 // Interrrupts targeting not present cpus must remain pending 1074 return nullptr; 1075 } else { 1076 return target_redistributor->getCPUInterface(); 1077 } 1078} 1079 1080void 1081Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) 1082{ 1083 auto cpu_interface = route(int_id); 1084 if (cpu_interface) 1085 cpu_interface->hppi.prio = 0xff; 1086} 1087 1088void 1089Gicv3Distributor::update() 1090{ 1091 // Find the highest priority pending SPI 1092 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 1093 int_id++) { 1094 Gicv3::GroupId int_group = getIntGroup(int_id); 1095 bool group_enabled = groupEnabled(int_group); 1096 1097 if (irqPending[int_id] && irqEnabled[int_id] && 1098 !irqActive[int_id] && group_enabled) { 1099 1100 // Find the cpu interface where to route the interrupt 1101 Gicv3CPUInterface *target_cpu_interface = route(int_id); 1102 1103 // Invalid routing 1104 if (!target_cpu_interface) continue; 1105 1106 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 1107 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1108 int_id < target_cpu_interface->hppi.intid)) { 1109 1110 target_cpu_interface->hppi.intid = int_id; 1111 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1112 target_cpu_interface->hppi.group = int_group; 1113 } 1114 } 1115 } 1116 1117 // Update all redistributors 1118 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1119 gic->getRedistributor(i)->update(); 1120 } 1121} 1122 1123Gicv3::IntStatus 1124Gicv3Distributor::intStatus(uint32_t int_id) const 1125{ 1126 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1127 panic_if(int_id > itLines, "Invalid SPI!"); 1128 1129 if (irqPending[int_id]) { 1130 if (irqActive[int_id]) { 1131 return Gicv3::INT_ACTIVE_PENDING; 1132 } 1133 1134 return Gicv3::INT_PENDING; 1135 } else if (irqActive[int_id]) { 1136 return Gicv3::INT_ACTIVE; 1137 } else { 1138 return Gicv3::INT_INACTIVE; 1139 } 1140} 1141 1142Gicv3::GroupId 1143Gicv3Distributor::getIntGroup(int int_id) const 1144{ 1145 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1146 panic_if(int_id > itLines, "Invalid SPI!"); 1147 1148 if (DS) { 1149 if (irqGroup[int_id] == 1) { 1150 return Gicv3::G1NS; 1151 } else { 1152 return Gicv3::G0S; 1153 } 1154 } else { 1155 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 1156 return Gicv3::G0S; 1157 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 1158 return Gicv3::G1NS; 1159 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 1160 return Gicv3::G1S; 1161 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 1162 return Gicv3::G1NS; 1163 } 1164 } 1165 1166 M5_UNREACHABLE; 1167} 1168 1169void 1170Gicv3Distributor::activateIRQ(uint32_t int_id) 1171{ 1172 irqPending[int_id] = false; 1173 irqActive[int_id] = true; 1174} 1175 1176void 1177Gicv3Distributor::deactivateIRQ(uint32_t int_id) 1178{ 1179 irqActive[int_id] = false; 1180} 1181 1182void 1183Gicv3Distributor::serialize(CheckpointOut & cp) const 1184{ 1185 SERIALIZE_SCALAR(ARE); 1186 SERIALIZE_SCALAR(DS); 1187 SERIALIZE_SCALAR(EnableGrp1S); 1188 SERIALIZE_SCALAR(EnableGrp1NS); 1189 SERIALIZE_SCALAR(EnableGrp0); 1190 SERIALIZE_CONTAINER(irqGroup); 1191 SERIALIZE_CONTAINER(irqEnabled); 1192 SERIALIZE_CONTAINER(irqPending); 1193 SERIALIZE_CONTAINER(irqActive); 1194 SERIALIZE_CONTAINER(irqPriority); 1195 SERIALIZE_CONTAINER(irqConfig); 1196 SERIALIZE_CONTAINER(irqGrpmod); 1197 SERIALIZE_CONTAINER(irqNsacr); 1198 SERIALIZE_CONTAINER(irqAffinityRouting); 1199} 1200 1201void 1202Gicv3Distributor::unserialize(CheckpointIn & cp) 1203{ 1204 UNSERIALIZE_SCALAR(ARE); 1205 UNSERIALIZE_SCALAR(DS); 1206 UNSERIALIZE_SCALAR(EnableGrp1S); 1207 UNSERIALIZE_SCALAR(EnableGrp1NS); 1208 UNSERIALIZE_SCALAR(EnableGrp0); 1209 UNSERIALIZE_CONTAINER(irqGroup); 1210 UNSERIALIZE_CONTAINER(irqEnabled); 1211 UNSERIALIZE_CONTAINER(irqPending); 1212 UNSERIALIZE_CONTAINER(irqActive); 1213 UNSERIALIZE_CONTAINER(irqPriority); 1214 UNSERIALIZE_CONTAINER(irqConfig); 1215 UNSERIALIZE_CONTAINER(irqGrpmod); 1216 UNSERIALIZE_CONTAINER(irqNsacr); 1217 UNSERIALIZE_CONTAINER(irqAffinityRouting); 1218}
| 135} 136 137uint64_t 138Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) 139{ 140 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 141 uint64_t val = 0x0; 142 143 if (!DS && !is_secure_access) { 144 // RAZ/WI for non-secure accesses 145 return 0; 146 } 147 148 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 149 150 if (isNotSPI(first_intid)) { 151 return 0; 152 } 153 154 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 155 i++, int_id++) { 156 val |= irqGroup[int_id] << i; 157 } 158 159 return val; 160 } else if (GICD_ISENABLER.contains(addr)) { 161 // Interrupt Set-Enable Registers 162 uint64_t val = 0x0; 163 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 164 165 if (isNotSPI(first_intid)) { 166 return 0; 167 } 168 169 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 170 i++, int_id++) { 171 172 if (nsAccessToSecInt(int_id, is_secure_access)) 173 { 174 continue; 175 } 176 177 val |= irqEnabled[int_id] << i; 178 } 179 180 return val; 181 } else if (GICD_ICENABLER.contains(addr)) { 182 // Interrupt Clear-Enable Registers 183 uint64_t val = 0x0; 184 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 185 186 if (isNotSPI(first_intid)) { 187 return 0; 188 } 189 190 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 191 i++, int_id++) { 192 193 if (nsAccessToSecInt(int_id, is_secure_access)) 194 { 195 continue; 196 } 197 198 val |= (irqEnabled[int_id] << i); 199 } 200 201 return val; 202 } else if (GICD_ISPENDR.contains(addr)) { 203 // Interrupt Set-Pending Registers 204 uint64_t val = 0x0; 205 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 206 207 if (isNotSPI(first_intid)) { 208 return 0; 209 } 210 211 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 212 i++, int_id++) { 213 214 if (nsAccessToSecInt(int_id, is_secure_access)) 215 { 216 if (irqNsacr[int_id] == 0) { 217 // Group 0 or Secure Group 1 interrupts are RAZ/WI 218 continue; 219 } 220 } 221 222 val |= (irqPending[int_id] << i); 223 } 224 225 return val; 226 } else if (GICD_ICPENDR.contains(addr)) { 227 // Interrupt Clear-Pending Registers 228 uint64_t val = 0x0; 229 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 230 231 if (isNotSPI(first_intid)) { 232 return 0; 233 } 234 235 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 236 i++, int_id++) { 237 238 if (nsAccessToSecInt(int_id, is_secure_access)) 239 { 240 if (irqNsacr[int_id] < 2) { 241 // Group 0 or Secure Group 1 interrupts are RAZ/WI 242 continue; 243 } 244 } 245 246 val |= (irqPending[int_id] << i); 247 } 248 249 return val; 250 } else if (GICD_ISACTIVER.contains(addr)) { 251 // Interrupt Set-Active Registers 252 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 253 254 if (isNotSPI(first_intid)) { 255 return 0; 256 } 257 258 uint64_t val = 0x0; 259 260 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 261 i++, int_id++) { 262 263 if (nsAccessToSecInt(int_id, is_secure_access)) 264 { 265 // Group 0 or Secure Group 1 interrupts are RAZ/WI 266 if (irqNsacr[int_id] < 2) { 267 continue; 268 } 269 } 270 271 val |= (irqActive[int_id] << i); 272 } 273 274 return val; 275 } else if (GICD_ICACTIVER.contains(addr)) { 276 // Interrupt Clear-Active Registers 277 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 278 279 if (isNotSPI(first_intid)) { 280 return 0; 281 } 282 283 uint64_t val = 0x0; 284 285 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 286 i++, int_id++) { 287 288 if (nsAccessToSecInt(int_id, is_secure_access)) 289 { 290 if (irqNsacr[int_id] < 2) { 291 continue; 292 } 293 } 294 295 val |= (irqActive[int_id] << i); 296 } 297 298 return val; 299 } else if (GICD_IPRIORITYR.contains(addr)) { 300 // Interrupt Priority Registers 301 uint64_t val = 0x0; 302 int first_intid = addr - GICD_IPRIORITYR.start(); 303 304 if (isNotSPI(first_intid)) { 305 return 0; 306 } 307 308 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 309 i++, int_id++) { 310 311 uint8_t prio = irqPriority[int_id]; 312 313 if (!DS && !is_secure_access) { 314 if (getIntGroup(int_id) != Gicv3::G1NS) { 315 // RAZ/WI for non-secure accesses for secure interrupts 316 continue; 317 } else { 318 // NS view 319 prio = (prio << 1) & 0xff; 320 } 321 } 322 323 val |= prio << (i * 8); 324 } 325 326 return val; 327 } else if (GICD_ITARGETSR.contains(addr)) { 328 // Interrupt Processor Targets Registers 329 // ARE always on, RAZ/WI 330 warn("Gicv3Distributor::read(): " 331 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 332 return 0; 333 } else if (GICD_ICFGR.contains(addr)) { 334 // Interrupt Configuration Registers 335 int first_intid = (addr - GICD_ICFGR.start()) * 4; 336 337 if (isNotSPI(first_intid)) { 338 return 0; 339 } 340 341 uint64_t val = 0x0; 342 343 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 344 i = i + 2, int_id++) { 345 346 if (nsAccessToSecInt(int_id, is_secure_access)) 347 { 348 continue; 349 } 350 351 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 352 val |= (0x2 << i); 353 } 354 } 355 356 return val; 357 } else if (GICD_IGRPMODR.contains(addr)) { 358 // Interrupt Group Modifier Registers 359 if (DS) { 360 // RAZ/WI if security disabled 361 return 0; 362 } else { 363 if (!is_secure_access) { 364 // RAZ/WI for non-secure accesses 365 return 0; 366 } else { 367 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 368 369 if (isNotSPI(first_intid)) { 370 return 0; 371 } 372 373 uint64_t val = 0x0; 374 375 for (int i = 0, int_id = first_intid; 376 i < 8 * size && int_id < itLines; i++, int_id++) { 377 val |= irqGrpmod[int_id] << i; 378 } 379 380 return val; 381 } 382 } 383 } else if (GICD_NSACR.contains(addr)) { 384 // Non-secure Access Control Registers 385 // 2 bits per interrupt 386 int first_intid = (addr - GICD_NSACR.start()) * 4; 387 388 if (isNotSPI(first_intid)) { 389 return 0; 390 } 391 392 if (DS || (!DS && !is_secure_access)) { 393 return 0; 394 } 395 396 uint64_t val = 0x0; 397 398 for (int i = 0, int_id = first_intid; 399 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 400 val |= irqNsacr[int_id] << i; 401 } 402 403 return val; 404 } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers 405 // ARE always on, RAZ/WI 406 warn("Gicv3Distributor::read(): " 407 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n"); 408 return 0x0; 409 } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers 410 // ARE always on, RAZ/WI 411 warn("Gicv3Distributor::read(): " 412 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n"); 413 return 0x0; 414 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 415 // 64 bit registers. 2 or 1 access. 416 int int_id = (addr - GICD_IROUTER.start()) / 8; 417 418 if (isNotSPI(int_id)) { 419 return 0; 420 } 421 422 if (nsAccessToSecInt(int_id, is_secure_access)) 423 { 424 if (irqNsacr[int_id] < 3) { 425 return 0; 426 } 427 } 428 429 if (size == 4) { 430 if (addr & 7) { // high half of 64 bit register 431 return irqAffinityRouting[int_id] >> 32; 432 } else { // high low of 64 bit register 433 return irqAffinityRouting[int_id] & 0xFFFFFFFF; 434 } 435 } else { 436 return irqAffinityRouting[int_id]; 437 } 438 } 439 440 switch (addr) { 441 case GICD_CTLR: // Control Register 442 if (!DS) { 443 if (is_secure_access) { 444 // E1NWF [7] RAZ/WI 445 // DS [6] - Disable Security 446 // ARE_NS [5] RAO/WI 447 // ARE_S [4] RAO/WI 448 // EnableGrp1S [2] 449 // EnableGrp1NS [1] 450 // EnableGrp0 [0] 451 return (EnableGrp0 << 0) | 452 (EnableGrp1NS << 1) | 453 (EnableGrp1S << 2) | 454 (1 << 4) | 455 (1 << 5) | 456 (DS << 6); 457 } else { 458 // ARE_NS [4] RAO/WI; 459 // EnableGrp1A [1] is a read-write alias of the Secure 460 // GICD_CTLR.EnableGrp1NS 461 // EnableGrp1 [0] RES0 462 return (1 << 4) | (EnableGrp1NS << 1); 463 } 464 } else { 465 return (DS << 6) | (ARE << 4) | 466 (EnableGrp1NS << 1) | (EnableGrp0 << 0); 467 } 468 469 case GICD_TYPER: // Interrupt Controller Type Register 470 return gicdTyper; 471 472 case GICD_IIDR: // Implementer Identification Register 473 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 474 return 0; 475 476 case GICD_STATUSR: // Error Reporting Status Register 477 // Optional register, RAZ/WI 478 return 0x0; 479 480 case GICD_PIDR0: // Peripheral ID0 Register 481 return gicdPidr0; 482 483 case GICD_PIDR1: // Peripheral ID1 Register 484 return gicdPidr1; 485 486 case GICD_PIDR2: // Peripheral ID2 Register 487 return gicdPidr2; 488 489 case GICD_PIDR3: // Peripheral ID3 Register 490 return gicdPidr3; 491 492 case GICD_PIDR4: // Peripheral ID4 Register 493 return gicdPidr4; 494 495 case GICD_PIDR5: // Peripheral ID5 Register 496 case GICD_PIDR6: // Peripheral ID6 Register 497 case GICD_PIDR7: // Peripheral ID7 Register 498 return 0; // RES0 499 500 default: 501 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); 502 break; 503 } 504} 505 506void 507Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, 508 bool is_secure_access) 509{ 510 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 511 if (!DS && !is_secure_access) { 512 // RAZ/WI for non-secure accesses 513 return; 514 } 515 516 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 517 518 if (isNotSPI(first_intid)) { 519 return; 520 } 521 522 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 523 i++, int_id++) { 524 irqGroup[int_id] = data & (1 << i) ? 1 : 0; 525 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n", 526 int_id, irqGroup[int_id]); 527 } 528 529 return; 530 } else if (GICD_ISENABLER.contains(addr)) { 531 // Interrupt Set-Enable Registers 532 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 533 534 if (isNotSPI(first_intid)) { 535 return; 536 } 537 538 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 539 i++, int_id++) { 540 541 if (nsAccessToSecInt(int_id, is_secure_access)) 542 { 543 continue; 544 } 545 546 bool enable = data & (1 << i) ? 1 : 0; 547 548 if (enable) { 549 if (!irqEnabled[int_id]) { 550 DPRINTF(GIC, "Gicv3Distributor::write(): " 551 "int_id %d enabled\n", int_id); 552 } 553 554 irqEnabled[int_id] = true; 555 } 556 } 557 558 return; 559 } else if (GICD_ICENABLER.contains(addr)) { 560 // Interrupt Clear-Enable Registers 561 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 562 563 if (isNotSPI(first_intid)) { 564 return; 565 } 566 567 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 568 i++, int_id++) { 569 570 if (nsAccessToSecInt(int_id, is_secure_access)) 571 { 572 continue; 573 } 574 575 bool disable = data & (1 << i) ? 1 : 0; 576 577 if (disable) { 578 if (irqEnabled[int_id]) { 579 DPRINTF(GIC, "Gicv3Distributor::write(): " 580 "int_id %d disabled\n", int_id); 581 } 582 583 irqEnabled[int_id] = false; 584 } 585 } 586 587 return; 588 } else if (GICD_ISPENDR.contains(addr)) { 589 // Interrupt Set-Pending Registers 590 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 591 592 if (isNotSPI(first_intid)) { 593 return; 594 } 595 596 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 597 i++, int_id++) { 598 599 if (nsAccessToSecInt(int_id, is_secure_access)) 600 { 601 if (irqNsacr[int_id] == 0) { 602 // Group 0 or Secure Group 1 interrupts are RAZ/WI 603 continue; 604 } 605 } 606 607 bool pending = data & (1 << i) ? 1 : 0; 608 609 if (pending) { 610 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 611 "int_id %d (SPI) pending bit set\n", int_id); 612 irqPending[int_id] = true; 613 } 614 } 615 616 update(); 617 return; 618 } else if (GICD_ICPENDR.contains(addr)) { 619 // Interrupt Clear-Pending Registers 620 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 621 622 if (isNotSPI(first_intid)) { 623 return; 624 } 625 626 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 627 i++, int_id++) { 628 629 if (nsAccessToSecInt(int_id, is_secure_access)) 630 { 631 if (irqNsacr[int_id] < 2) { 632 // Group 0 or Secure Group 1 interrupts are RAZ/WI 633 continue; 634 } 635 } 636 637 bool clear = data & (1 << i) ? 1 : 0; 638 639 if (clear) { 640 irqPending[int_id] = false; 641 clearIrqCpuInterface(int_id); 642 } 643 } 644 645 update(); 646 return; 647 } else if (GICD_ISACTIVER.contains(addr)) { 648 // Interrupt Set-Active Registers 649 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 650 651 if (isNotSPI(first_intid)) { 652 return; 653 } 654 655 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 656 i++, int_id++) { 657 658 if (nsAccessToSecInt(int_id, is_secure_access)) 659 { 660 continue; 661 } 662 663 bool active = data & (1 << i) ? 1 : 0; 664 665 if (active) { 666 irqActive[int_id] = 1; 667 } 668 } 669 670 return; 671 } else if (GICD_ICACTIVER.contains(addr)) { 672 // Interrupt Clear-Active Registers 673 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 674 675 if (isNotSPI(first_intid)) { 676 return; 677 } 678 679 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 680 i++, int_id++) { 681 682 if (nsAccessToSecInt(int_id, is_secure_access)) 683 { 684 continue; 685 } 686 687 bool clear = data & (1 << i) ? 1 : 0; 688 689 if (clear) { 690 if (irqActive[int_id]) { 691 DPRINTF(GIC, "Gicv3Distributor::write(): " 692 "int_id %d active cleared\n", int_id); 693 } 694 695 irqActive[int_id] = false; 696 } 697 } 698 699 return; 700 } else if (GICD_IPRIORITYR.contains(addr)) { 701 // Interrupt Priority Registers 702 int first_intid = addr - GICD_IPRIORITYR.start(); 703 704 if (isNotSPI(first_intid)) { 705 return; 706 } 707 708 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 709 i++, int_id++) { 710 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 711 712 if (!DS && !is_secure_access) { 713 if (getIntGroup(int_id) != Gicv3::G1NS) { 714 // RAZ/WI for non-secure accesses to secure interrupts 715 continue; 716 } else { 717 prio = 0x80 | (prio >> 1); 718 } 719 } 720 721 irqPriority[int_id] = prio; 722 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 723 int_id, irqPriority[int_id]); 724 } 725 726 return; 727 } else if (GICD_ITARGETSR.contains(addr)) { 728 // Interrupt Processor Targets Registers 729 // ARE always on, RAZ/WI 730 warn("Gicv3Distributor::write(): " 731 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 732 return; 733 } else if (GICD_ICFGR.contains(addr)) { 734 // Interrupt Configuration Registers 735 // for x = 0 to 15: 736 // GICD_ICFGR[2x] = RES0 737 // GICD_ICFGR[2x + 1] = 738 // 0 level-sensitive 739 // 1 edge-triggered 740 int first_intid = (addr - GICD_ICFGR.start()) * 4; 741 742 if (isNotSPI(first_intid)) { 743 return; 744 } 745 746 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 747 i = i + 2, int_id++) { 748 irqConfig[int_id] = data & (0x2 << i) ? 749 Gicv3::INT_EDGE_TRIGGERED : 750 Gicv3::INT_LEVEL_SENSITIVE; 751 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 752 int_id, irqConfig[int_id]); 753 } 754 755 return; 756 } else if (GICD_IGRPMODR.contains(addr)) { 757 // Interrupt Group Modifier Registers 758 if (DS) { 759 return; 760 } else { 761 if (!is_secure_access) { 762 // RAZ/WI for non-secure accesses 763 return; 764 } else { 765 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 766 767 if (isNotSPI(first_intid)) { 768 return; 769 } 770 771 for (int i = 0, int_id = first_intid; 772 i < 8 * size && int_id < itLines; i++, int_id++) { 773 irqGrpmod[int_id] = bits(data, i); 774 } 775 776 return ; 777 } 778 } 779 780 } else if (GICD_NSACR.contains(addr)) { 781 // Non-secure Access Control Registers 782 // 2 bits per interrupt 783 int first_intid = (addr - GICD_NSACR.start()) * 4; 784 785 if (isNotSPI(first_intid)) { 786 return; 787 } 788 789 if (DS || (!DS && !is_secure_access)) { 790 return; 791 } 792 793 for (int i = 0, int_id = first_intid; 794 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 795 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 796 } 797 798 return; 799 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 800 // 64 bit registers. 2 accesses. 801 int int_id = (addr - GICD_IROUTER.start()) / 8; 802 803 if (isNotSPI(int_id)) { 804 return; 805 } 806 807 if (nsAccessToSecInt(int_id, is_secure_access)) 808 { 809 if (irqNsacr[int_id] < 3) { 810 // Group 0 or Secure Group 1 interrupts are RAZ/WI 811 return; 812 } 813 } 814 815 if (size == 4) { 816 if (addr & 7) { // high half of 64 bit register 817 irqAffinityRouting[int_id] = 818 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 819 } else { // low half of 64 bit register 820 irqAffinityRouting[int_id] = 821 (irqAffinityRouting[int_id] & 0xffffffff00000000) | 822 (data & 0xffffffff); 823 } 824 } else { 825 irqAffinityRouting[int_id] = data; 826 } 827 828 DPRINTF(GIC, "Gicv3Distributor::write(): " 829 "int_id %d GICD_IROUTER %#llx\n", 830 int_id, irqAffinityRouting[int_id]); 831 return; 832 } 833 834 switch (addr) { 835 case GICD_CTLR: // Control Register 836 if (DS) { 837 /* 838 * E1NWF [7] 839 * 1 of N wakeup functionality not supported, RAZ/WI 840 * DS [6] - RAO/WI 841 * ARE [4] 842 * affinity routing always on, no GICv2 legacy, RAO/WI 843 * EnableGrp1 [1] 844 * EnableGrp0 [0] 845 */ 846 if ((data & (1 << 4)) == 0) { 847 warn("Gicv3Distributor::write(): " 848 "setting ARE to 0 is not supported!\n"); 849 } 850 851 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 852 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 853 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 854 "EnableGrp1NS %d EnableGrp0 %d\n", 855 EnableGrp1NS, EnableGrp0); 856 } else { 857 if (is_secure_access) { 858 /* 859 * E1NWF [7] 860 * 1 of N wakeup functionality not supported, RAZ/WI 861 * DS [6] 862 * ARE_NS [5] 863 * affinity routing always on, no GICv2 legacy, RAO/WI 864 * ARE_S [4] 865 * affinity routing always on, no GICv2 legacy, RAO/WI 866 * EnableGrp1S [2] 867 * EnableGrp1NS [1] 868 * EnableGrp0 [0] 869 */ 870 if ((data & (1 << 5)) == 0) { 871 warn("Gicv3Distributor::write(): " 872 "setting ARE_NS to 0 is not supported!\n"); 873 } 874 875 if ((data & (1 << 4)) == 0) { 876 warn("Gicv3Distributor::write(): " 877 "setting ARE_S to 0 is not supported!\n"); 878 } 879 880 DS = data & GICD_CTLR_DS; 881 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 882 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 883 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 884 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 885 "DS %d " 886 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 887 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 888 889 if (data & GICD_CTLR_DS) { 890 EnableGrp1S = 0; 891 } 892 } else { 893 /* 894 * ARE_NS [4] RAO/WI; 895 * EnableGrp1A [1] is a read-write alias of the Secure 896 * GICD_CTLR.EnableGrp1NS 897 * EnableGrp1 [0] RES0 898 */ 899 if ((data & (1 << 4)) == 0) { 900 warn("Gicv3Distributor::write(): " 901 "setting ARE_NS to 0 is not supported!\n"); 902 } 903 904 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 905 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 906 "EnableGrp1NS %d\n", EnableGrp1NS); 907 } 908 } 909 910 update(); 911 912 break; 913 914 case GICD_SGIR: // Error Reporting Status Register 915 // Only if affinity routing is disabled, RES0 916 break; 917 918 case GICD_SETSPI_NSR: { 919 // Writes to this register have no effect if: 920 // * The value written specifies an invalid SPI. 921 // * The SPI is already pending. 922 // * The value written specifies a Secure SPI, the value is 923 // written by a Non-secure access, and the value of the 924 // corresponding GICD_NSACR<n> register is 0. 925 const uint32_t intid = bits(data, 9, 0); 926 if (isNotSPI(intid) || irqPending[intid] || 927 (nsAccessToSecInt(intid, is_secure_access) && 928 irqNsacr[intid] == 0)) { 929 return; 930 } else { 931 // Valid SPI, set interrupt pending 932 sendInt(intid); 933 } 934 break; 935 } 936 937 case GICD_CLRSPI_NSR: { 938 // Writes to this register have no effect if: 939 // * The value written specifies an invalid SPI. 940 // * The SPI is not pending. 941 // * The value written specifies a Secure SPI, the value is 942 // written by a Non-secure access, and the value of the 943 // corresponding GICD_NSACR<n> register is less than 0b10. 944 const uint32_t intid = bits(data, 9, 0); 945 if (isNotSPI(intid) || !irqPending[intid] || 946 (nsAccessToSecInt(intid, is_secure_access) && 947 irqNsacr[intid] < 2)) { 948 return; 949 } else { 950 // Valid SPI, clear interrupt pending 951 deassertSPI(intid); 952 } 953 break; 954 } 955 956 case GICD_SETSPI_SR: { 957 // Writes to this register have no effect if: 958 // * GICD_CTLR.DS = 1 (WI) 959 // * The value written specifies an invalid SPI. 960 // * The SPI is already pending. 961 // * The value is written by a Non-secure access. 962 const uint32_t intid = bits(data, 9, 0); 963 if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) { 964 return; 965 } else { 966 // Valid SPI, set interrupt pending 967 sendInt(intid); 968 } 969 break; 970 } 971 972 case GICD_CLRSPI_SR: { 973 // Writes to this register have no effect if: 974 // * GICD_CTLR.DS = 1 (WI) 975 // * The value written specifies an invalid SPI. 976 // * The SPI is not pending. 977 // * The value is written by a Non-secure access. 978 const uint32_t intid = bits(data, 9, 0); 979 if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) { 980 return; 981 } else { 982 // Valid SPI, clear interrupt pending 983 deassertSPI(intid); 984 } 985 break; 986 } 987 988 default: 989 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 990 break; 991 } 992} 993 994void 995Gicv3Distributor::sendInt(uint32_t int_id) 996{ 997 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 998 panic_if(int_id > itLines, "Invalid SPI!"); 999 irqPending[int_id] = true; 1000 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 1001 "int_id %d (SPI) pending bit set\n", int_id); 1002 update(); 1003} 1004 1005void 1006Gicv3Distributor::deassertSPI(uint32_t int_id) 1007{ 1008 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1009 panic_if(int_id > itLines, "Invalid SPI!"); 1010 irqPending[int_id] = false; 1011 clearIrqCpuInterface(int_id); 1012 1013 update(); 1014} 1015 1016Gicv3CPUInterface* 1017Gicv3Distributor::route(uint32_t int_id) 1018{ 1019 IROUTER affinity_routing = irqAffinityRouting[int_id]; 1020 Gicv3Redistributor * target_redistributor = nullptr; 1021 1022 const Gicv3::GroupId int_group = getIntGroup(int_id); 1023 1024 if (affinity_routing.IRM) { 1025 // Interrupts routed to any PE defined as a participating node 1026 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1027 Gicv3Redistributor * redistributor_i = 1028 gic->getRedistributor(i); 1029 1030 if (redistributor_i-> 1031 canBeSelectedFor1toNInterrupt(int_group)) { 1032 target_redistributor = redistributor_i; 1033 break; 1034 } 1035 } 1036 } else { 1037 uint32_t affinity = (affinity_routing.Aff3 << 24) | 1038 (affinity_routing.Aff2 << 16) | 1039 (affinity_routing.Aff1 << 8) | 1040 (affinity_routing.Aff0 << 0); 1041 target_redistributor = 1042 gic->getRedistributorByAffinity(affinity); 1043 } 1044 1045 if (!target_redistributor) { 1046 // Interrrupts targeting not present cpus must remain pending 1047 return nullptr; 1048 } else { 1049 return target_redistributor->getCPUInterface(); 1050 } 1051} 1052 1053void 1054Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) 1055{ 1056 auto cpu_interface = route(int_id); 1057 if (cpu_interface) 1058 cpu_interface->hppi.prio = 0xff; 1059} 1060 1061void 1062Gicv3Distributor::update() 1063{ 1064 // Find the highest priority pending SPI 1065 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 1066 int_id++) { 1067 Gicv3::GroupId int_group = getIntGroup(int_id); 1068 bool group_enabled = groupEnabled(int_group); 1069 1070 if (irqPending[int_id] && irqEnabled[int_id] && 1071 !irqActive[int_id] && group_enabled) { 1072 1073 // Find the cpu interface where to route the interrupt 1074 Gicv3CPUInterface *target_cpu_interface = route(int_id); 1075 1076 // Invalid routing 1077 if (!target_cpu_interface) continue; 1078 1079 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 1080 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1081 int_id < target_cpu_interface->hppi.intid)) { 1082 1083 target_cpu_interface->hppi.intid = int_id; 1084 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1085 target_cpu_interface->hppi.group = int_group; 1086 } 1087 } 1088 } 1089 1090 // Update all redistributors 1091 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1092 gic->getRedistributor(i)->update(); 1093 } 1094} 1095 1096Gicv3::IntStatus 1097Gicv3Distributor::intStatus(uint32_t int_id) const 1098{ 1099 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1100 panic_if(int_id > itLines, "Invalid SPI!"); 1101 1102 if (irqPending[int_id]) { 1103 if (irqActive[int_id]) { 1104 return Gicv3::INT_ACTIVE_PENDING; 1105 } 1106 1107 return Gicv3::INT_PENDING; 1108 } else if (irqActive[int_id]) { 1109 return Gicv3::INT_ACTIVE; 1110 } else { 1111 return Gicv3::INT_INACTIVE; 1112 } 1113} 1114 1115Gicv3::GroupId 1116Gicv3Distributor::getIntGroup(int int_id) const 1117{ 1118 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1119 panic_if(int_id > itLines, "Invalid SPI!"); 1120 1121 if (DS) { 1122 if (irqGroup[int_id] == 1) { 1123 return Gicv3::G1NS; 1124 } else { 1125 return Gicv3::G0S; 1126 } 1127 } else { 1128 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 1129 return Gicv3::G0S; 1130 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 1131 return Gicv3::G1NS; 1132 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 1133 return Gicv3::G1S; 1134 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 1135 return Gicv3::G1NS; 1136 } 1137 } 1138 1139 M5_UNREACHABLE; 1140} 1141 1142void 1143Gicv3Distributor::activateIRQ(uint32_t int_id) 1144{ 1145 irqPending[int_id] = false; 1146 irqActive[int_id] = true; 1147} 1148 1149void 1150Gicv3Distributor::deactivateIRQ(uint32_t int_id) 1151{ 1152 irqActive[int_id] = false; 1153} 1154 1155void 1156Gicv3Distributor::serialize(CheckpointOut & cp) const 1157{ 1158 SERIALIZE_SCALAR(ARE); 1159 SERIALIZE_SCALAR(DS); 1160 SERIALIZE_SCALAR(EnableGrp1S); 1161 SERIALIZE_SCALAR(EnableGrp1NS); 1162 SERIALIZE_SCALAR(EnableGrp0); 1163 SERIALIZE_CONTAINER(irqGroup); 1164 SERIALIZE_CONTAINER(irqEnabled); 1165 SERIALIZE_CONTAINER(irqPending); 1166 SERIALIZE_CONTAINER(irqActive); 1167 SERIALIZE_CONTAINER(irqPriority); 1168 SERIALIZE_CONTAINER(irqConfig); 1169 SERIALIZE_CONTAINER(irqGrpmod); 1170 SERIALIZE_CONTAINER(irqNsacr); 1171 SERIALIZE_CONTAINER(irqAffinityRouting); 1172} 1173 1174void 1175Gicv3Distributor::unserialize(CheckpointIn & cp) 1176{ 1177 UNSERIALIZE_SCALAR(ARE); 1178 UNSERIALIZE_SCALAR(DS); 1179 UNSERIALIZE_SCALAR(EnableGrp1S); 1180 UNSERIALIZE_SCALAR(EnableGrp1NS); 1181 UNSERIALIZE_SCALAR(EnableGrp0); 1182 UNSERIALIZE_CONTAINER(irqGroup); 1183 UNSERIALIZE_CONTAINER(irqEnabled); 1184 UNSERIALIZE_CONTAINER(irqPending); 1185 UNSERIALIZE_CONTAINER(irqActive); 1186 UNSERIALIZE_CONTAINER(irqPriority); 1187 UNSERIALIZE_CONTAINER(irqConfig); 1188 UNSERIALIZE_CONTAINER(irqGrpmod); 1189 UNSERIALIZE_CONTAINER(irqNsacr); 1190 UNSERIALIZE_CONTAINER(irqAffinityRouting); 1191}
|