gic_v3_distributor.cc revision 14231
11689SN/A/* 22329SN/A * Copyright (c) 2019 ARM Limited 31689SN/A * All rights reserved 41689SN/A * 51689SN/A * The license below extends only to copyright in the software and shall 61689SN/A * not be construed as granting a license to any other intellectual 71689SN/A * property including but not limited to intellectual property relating 81689SN/A * to a hardware implementation of the functionality of the software 91689SN/A * licensed hereunder. You may use the software subject to the license 101689SN/A * terms below provided that you ensure that this notice is replicated 111689SN/A * unmodified and in its entirety in all distributions of the software, 121689SN/A * modified or unmodified, in source code or in binary form. 131689SN/A * 141689SN/A * Copyright (c) 2018 Metempsy Technology Consulting 151689SN/A * All rights reserved. 161689SN/A * 171689SN/A * Redistribution and use in source and binary forms, with or without 181689SN/A * modification, are permitted provided that the following conditions are 191689SN/A * met: redistributions of source code must retain the above copyright 201689SN/A * notice, this list of conditions and the following disclaimer; 211689SN/A * redistributions in binary form must reproduce the above copyright 221689SN/A * notice, this list of conditions and the following disclaimer in the 231689SN/A * documentation and/or other materials provided with the distribution; 241689SN/A * neither the name of the copyright holders nor the names of its 251689SN/A * contributors may be used to endorse or promote products derived from 261689SN/A * this software without specific prior written permission. 272665Ssaidi@eecs.umich.edu * 282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 291689SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 301061SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312292SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322292SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 331061SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342292SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 351061SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 361061SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372292SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382292SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 391684SN/A * 401061SN/A * Authors: Jairo Balart 411061SN/A */ 422292SN/A 432292SN/A#include "dev/arm/gic_v3_distributor.hh" 442292SN/A 452292SN/A#include <algorithm> 462292SN/A 472292SN/A#include "debug/GIC.hh" 482292SN/A#include "dev/arm/gic_v3.hh" 492292SN/A#include "dev/arm/gic_v3_cpu_interface.hh" 502292SN/A#include "dev/arm/gic_v3_redistributor.hh" 515529Snate@binkert.org 525529Snate@binkert.orgconst AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff); 532292SN/Aconst AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f); 542292SN/Aconst AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff); 552292SN/Aconst AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f); 561061SN/Aconst AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff); 571061SN/Aconst AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f); 581061SN/Aconst AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff); 591061SN/Aconst AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff); 601061SN/Aconst AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff); 611061SN/Aconst AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff); 621061SN/Aconst AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f); 631061SN/Aconst AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff); 641061SN/Aconst AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f); 651061SN/Aconst AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f); 661061SN/Aconst AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0); 671061SN/A 681061SN/AGicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) 691061SN/A : gic(gic), 701061SN/A itLines(it_lines), 711061SN/A irqGroup(it_lines), 722292SN/A irqEnabled(it_lines), 733500Sktlim@umich.edu irqPending(it_lines), 741061SN/A irqActive(it_lines), 752292SN/A irqPriority(it_lines), 765529Snate@binkert.org irqConfig(it_lines), 772292SN/A irqGrpmod(it_lines), 782292SN/A irqNsacr(it_lines), 792292SN/A irqAffinityRouting(it_lines), 802292SN/A gicdPidr0(0x92), 812292SN/A gicdPidr1(0xb4), 822292SN/A gicdPidr2(0x3b), 832292SN/A gicdPidr3(0), 842292SN/A gicdPidr4(0x44) 855529Snate@binkert.org{ 862292SN/A panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!"); 872292SN/A} 881062SN/A 891061SN/Avoid 902348SN/AGicv3Distributor::init() 912307SN/A{ 922307SN/A} 932348SN/A 942307SN/Avoid 952307SN/AGicv3Distributor::initState() 962292SN/A{ 972292SN/A reset(); 982292SN/A} 992292SN/A 1001061SN/Avoid 1011061SN/AGicv3Distributor::reset() 1022292SN/A{ 1031062SN/A std::fill(irqGroup.begin(), irqGroup.end(), 0); 1041062SN/A // Imp. defined reset value 1052292SN/A std::fill(irqEnabled.begin(), irqEnabled.end(), false); 1062292SN/A std::fill(irqPending.begin(), irqPending.end(), false); 1071684SN/A std::fill(irqActive.begin(), irqActive.end(), false); 1082292SN/A // Imp. defined reset value 1091062SN/A std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA); 1101062SN/A std::fill(irqConfig.begin(), irqConfig.end(), 1112292SN/A Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value 1121062SN/A std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 1131061SN/A std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 1142292SN/A /* 1152292SN/A * For our implementation affinity routing is always enabled, 1162292SN/A * no GICv2 legacy 1172292SN/A */ 1182292SN/A ARE = true; 1192292SN/A 1202292SN/A if (gic->getSystem()->haveSecurity()) { 1212292SN/A DS = false; 1222292SN/A } else { 1232292SN/A DS = true; 1242292SN/A } 1252292SN/A 1262292SN/A EnableGrp0 = 0; 1272292SN/A EnableGrp1NS = 0; 1282292SN/A EnableGrp1S = 0; 1292292SN/A} 1302292SN/A 1312292SN/Auint64_t 1322292SN/AGicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) 1332292SN/A{ 1342292SN/A if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 1352292SN/A uint64_t val = 0x0; 1362292SN/A 1372292SN/A if (!DS && !is_secure_access) { 1382292SN/A // RAZ/WI for non-secure accesses 1392292SN/A return 0; 1401061SN/A } 1411061SN/A 1422292SN/A int first_intid = (addr - GICD_IGROUPR.start()) * 8; 1432292SN/A 1441062SN/A if (isNotSPI(first_intid)) { 1451062SN/A return 0; 1462292SN/A } 1471062SN/A 1482292SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1491062SN/A i++, int_id++) { 1502292SN/A val |= irqGroup[int_id] << i; 1511062SN/A } 1522292SN/A 1532292SN/A return val; 1542292SN/A } else if (GICD_ISENABLER.contains(addr)) { 1552292SN/A // Interrupt Set-Enable Registers 1562292SN/A uint64_t val = 0x0; 1572292SN/A int first_intid = (addr - GICD_ISENABLER.start()) * 8; 1582292SN/A 1592292SN/A if (isNotSPI(first_intid)) { 1602292SN/A return 0; 1612292SN/A } 1622292SN/A 1632348SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1642292SN/A i++, int_id++) { 1651062SN/A 1662292SN/A if (nsAccessToSecInt(int_id, is_secure_access)) 1672292SN/A { 1682348SN/A continue; 1692292SN/A } 1701062SN/A 1712292SN/A val |= irqEnabled[int_id] << i; 1722292SN/A } 1732292SN/A 1742292SN/A return val; 1752292SN/A } else if (GICD_ICENABLER.contains(addr)) { 1762292SN/A // Interrupt Clear-Enable Registers 1772348SN/A uint64_t val = 0x0; 1782292SN/A int first_intid = (addr - GICD_ICENABLER.start()) * 8; 1792292SN/A 1802292SN/A if (isNotSPI(first_intid)) { 1812292SN/A return 0; 1822348SN/A } 1832292SN/A 1842292SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1852292SN/A i++, int_id++) { 1862292SN/A 1872292SN/A if (nsAccessToSecInt(int_id, is_secure_access)) 1882292SN/A { 1892292SN/A continue; 1902292SN/A } 1912292SN/A 1922292SN/A val |= (irqEnabled[int_id] << i); 1932292SN/A } 1942292SN/A 1952292SN/A return val; 1962292SN/A } else if (GICD_ISPENDR.contains(addr)) { 1972292SN/A // Interrupt Set-Pending Registers 1982292SN/A uint64_t val = 0x0; 1992292SN/A int first_intid = (addr - GICD_ISPENDR.start()) * 8; 2002292SN/A 2012292SN/A if (isNotSPI(first_intid)) { 2022292SN/A return 0; 2032292SN/A } 2042292SN/A 2052292SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 2062292SN/A i++, int_id++) { 2072348SN/A 2082292SN/A if (nsAccessToSecInt(int_id, is_secure_access)) 2092292SN/A { 2102292SN/A if (irqNsacr[int_id] == 0) { 2112348SN/A // Group 0 or Secure Group 1 interrupts are RAZ/WI 2121062SN/A continue; 2131062SN/A } 2142292SN/A } 2152292SN/A 2161062SN/A val |= (irqPending[int_id] << i); 2172292SN/A } 2182292SN/A 2191062SN/A return val; 2202292SN/A } else if (GICD_ICPENDR.contains(addr)) { 2211061SN/A // Interrupt Clear-Pending Registers 2222292SN/A uint64_t val = 0x0; 2231061SN/A int first_intid = (addr - GICD_ICPENDR.start()) * 8; 2242292SN/A 2252292SN/A if (isNotSPI(first_intid)) { 2261062SN/A return 0; 2272292SN/A } 2282292SN/A 2291062SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 2302292SN/A i++, int_id++) { 2312292SN/A 2321061SN/A if (nsAccessToSecInt(int_id, is_secure_access)) 2331061SN/A { 2341061SN/A if (irqNsacr[int_id] < 2) { 2351061SN/A // Group 0 or Secure Group 1 interrupts are RAZ/WI 2361061SN/A continue; 2371061SN/A } 2381061SN/A } 2391061SN/A 2402348SN/A val |= (irqPending[int_id] << i); 2412292SN/A } 2422348SN/A 2432292SN/A return val; 2442348SN/A } else if (GICD_ISACTIVER.contains(addr)) { 2452292SN/A // Interrupt Set-Active Registers 2462348SN/A int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 2472292SN/A 2482292SN/A if (isNotSPI(first_intid)) { 2492292SN/A return 0; 2502292SN/A } 2512292SN/A 2522292SN/A uint64_t val = 0x0; 2532292SN/A 2542292SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 2552292SN/A i++, int_id++) { 2561062SN/A 2572292SN/A if (nsAccessToSecInt(int_id, is_secure_access)) 2581062SN/A { 2592292SN/A // Group 0 or Secure Group 1 interrupts are RAZ/WI 2601062SN/A if (irqNsacr[int_id] < 2) { 2612292SN/A continue; 2621062SN/A } 2631061SN/A } 2641061SN/A 2652292SN/A val |= (irqActive[int_id] << i); 266 } 267 268 return val; 269 } else if (GICD_ICACTIVER.contains(addr)) { 270 // Interrupt Clear-Active Registers 271 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 272 273 if (isNotSPI(first_intid)) { 274 return 0; 275 } 276 277 uint64_t val = 0x0; 278 279 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 280 i++, int_id++) { 281 282 if (nsAccessToSecInt(int_id, is_secure_access)) 283 { 284 if (irqNsacr[int_id] < 2) { 285 continue; 286 } 287 } 288 289 val |= (irqActive[int_id] << i); 290 } 291 292 return val; 293 } else if (GICD_IPRIORITYR.contains(addr)) { 294 // Interrupt Priority Registers 295 uint64_t val = 0x0; 296 int first_intid = addr - GICD_IPRIORITYR.start(); 297 298 if (isNotSPI(first_intid)) { 299 return 0; 300 } 301 302 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 303 i++, int_id++) { 304 305 uint8_t prio = irqPriority[int_id]; 306 307 if (!DS && !is_secure_access) { 308 if (getIntGroup(int_id) != Gicv3::G1NS) { 309 // RAZ/WI for non-secure accesses for secure interrupts 310 continue; 311 } else { 312 // NS view 313 prio = (prio << 1) & 0xff; 314 } 315 } 316 317 val |= prio << (i * 8); 318 } 319 320 return val; 321 } else if (GICD_ITARGETSR.contains(addr)) { 322 // Interrupt Processor Targets Registers 323 // ARE always on, RAZ/WI 324 warn("Gicv3Distributor::read(): " 325 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 326 return 0; 327 } else if (GICD_ICFGR.contains(addr)) { 328 // Interrupt Configuration Registers 329 int first_intid = (addr - GICD_ICFGR.start()) * 4; 330 331 if (isNotSPI(first_intid)) { 332 return 0; 333 } 334 335 uint64_t val = 0x0; 336 337 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 338 i = i + 2, int_id++) { 339 340 if (nsAccessToSecInt(int_id, is_secure_access)) 341 { 342 continue; 343 } 344 345 if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 346 val |= (0x2 << i); 347 } 348 } 349 350 return val; 351 } else if (GICD_IGRPMODR.contains(addr)) { 352 // Interrupt Group Modifier Registers 353 if (DS) { 354 // RAZ/WI if security disabled 355 return 0; 356 } else { 357 if (!is_secure_access) { 358 // RAZ/WI for non-secure accesses 359 return 0; 360 } else { 361 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 362 363 if (isNotSPI(first_intid)) { 364 return 0; 365 } 366 367 uint64_t val = 0x0; 368 369 for (int i = 0, int_id = first_intid; 370 i < 8 * size && int_id < itLines; i++, int_id++) { 371 val |= irqGrpmod[int_id] << i; 372 } 373 374 return val; 375 } 376 } 377 } else if (GICD_NSACR.contains(addr)) { 378 // Non-secure Access Control Registers 379 // 2 bits per interrupt 380 int first_intid = (addr - GICD_NSACR.start()) * 4; 381 382 if (isNotSPI(first_intid)) { 383 return 0; 384 } 385 386 if (DS || (!DS && !is_secure_access)) { 387 return 0; 388 } 389 390 uint64_t val = 0x0; 391 392 for (int i = 0, int_id = first_intid; 393 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 394 val |= irqNsacr[int_id] << i; 395 } 396 397 return val; 398 } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers 399 // ARE always on, RAZ/WI 400 warn("Gicv3Distributor::read(): " 401 "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n"); 402 return 0x0; 403 } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers 404 // ARE always on, RAZ/WI 405 warn("Gicv3Distributor::read(): " 406 "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n"); 407 return 0x0; 408 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 409 // 64 bit registers. 2 or 1 access. 410 int int_id = (addr - GICD_IROUTER.start()) / 8; 411 412 if (isNotSPI(int_id)) { 413 return 0; 414 } 415 416 if (nsAccessToSecInt(int_id, is_secure_access)) 417 { 418 if (irqNsacr[int_id] < 3) { 419 return 0; 420 } 421 } 422 423 if (size == 4) { 424 if (addr & 7) { // high half of 64 bit register 425 return irqAffinityRouting[int_id] >> 32; 426 } else { // high low of 64 bit register 427 return irqAffinityRouting[int_id] & 0xFFFFFFFF; 428 } 429 } else { 430 return irqAffinityRouting[int_id]; 431 } 432 } 433 434 switch (addr) { 435 case GICD_CTLR: // Control Register 436 if (!DS) { 437 if (is_secure_access) { 438 // E1NWF [7] RAZ/WI 439 // DS [6] - Disable Security 440 // ARE_NS [5] RAO/WI 441 // ARE_S [4] RAO/WI 442 // EnableGrp1S [2] 443 // EnableGrp1NS [1] 444 // EnableGrp0 [0] 445 return (EnableGrp0 << 0) | 446 (EnableGrp1NS << 1) | 447 (EnableGrp1S << 2) | 448 (1 << 4) | 449 (1 << 5) | 450 (DS << 6); 451 } else { 452 // ARE_NS [4] RAO/WI; 453 // EnableGrp1A [1] is a read-write alias of the Secure 454 // GICD_CTLR.EnableGrp1NS 455 // EnableGrp1 [0] RES0 456 return (1 << 4) | (EnableGrp1NS << 1); 457 } 458 } else { 459 return (DS << 6) | (ARE << 4) | 460 (EnableGrp1NS << 1) | (EnableGrp0 << 0); 461 } 462 463 case GICD_TYPER: // Interrupt Controller Type Register 464 /* 465 * RSS [26] == 1 466 * (The implementation does supports targeted SGIs with affinity 467 * level 0 values of 0 - 255) 468 * No1N [25] == 1 469 * (1 of N SPI interrupts are not supported) 470 * A3V [24] == 1 471 * (Supports nonzero values of Affinity level 3) 472 * IDbits [23:19] == 0xf 473 * (The number of interrupt identifier bits supported, minus one) 474 * DVIS [18] == 0 475 * (The implementation does not support Direct Virtual LPI 476 * injection) 477 * LPIS [17] == 1 478 * (The implementation does not support LPIs) 479 * MBIS [16] == 0 480 * (The implementation does not support message-based interrupts 481 * by writing to Distributor registers) 482 * SecurityExtn [10] == X 483 * (The GIC implementation supports two Security states) 484 * CPUNumber [7:5] == 0 485 * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy]) 486 * ITLinesNumber [4:0] == N 487 * (MaxSPIIntId = 32 (N + 1) - 1) 488 */ 489 { 490 int max_spi_int_id = itLines - 1; 491 int it_lines_number = ceil((max_spi_int_id + 1) / 32.0) - 1; 492 return (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) | 493 (1 << 17) | (gic->getSystem()->haveSecurity() << 10) | 494 (it_lines_number << 0); 495 } 496 497 case GICD_IIDR: // Implementer Identification Register 498 //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 499 return 0; 500 501 case GICD_STATUSR: // Error Reporting Status Register 502 // Optional register, RAZ/WI 503 return 0x0; 504 505 case GICD_PIDR0: // Peripheral ID0 Register 506 return gicdPidr0; 507 508 case GICD_PIDR1: // Peripheral ID1 Register 509 return gicdPidr1; 510 511 case GICD_PIDR2: // Peripheral ID2 Register 512 return gicdPidr2; 513 514 case GICD_PIDR3: // Peripheral ID3 Register 515 return gicdPidr3; 516 517 case GICD_PIDR4: // Peripheral ID4 Register 518 return gicdPidr4; 519 520 case GICD_PIDR5: // Peripheral ID5 Register 521 case GICD_PIDR6: // Peripheral ID6 Register 522 case GICD_PIDR7: // Peripheral ID7 Register 523 return 0; // RES0 524 525 default: 526 panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); 527 break; 528 } 529} 530 531void 532Gicv3Distributor::write(Addr addr, uint64_t data, size_t size, 533 bool is_secure_access) 534{ 535 if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 536 if (!DS && !is_secure_access) { 537 // RAZ/WI for non-secure accesses 538 return; 539 } 540 541 int first_intid = (addr - GICD_IGROUPR.start()) * 8; 542 543 if (isNotSPI(first_intid)) { 544 return; 545 } 546 547 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 548 i++, int_id++) { 549 irqGroup[int_id] = data & (1 << i) ? 1 : 0; 550 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n", 551 int_id, irqGroup[int_id]); 552 } 553 554 return; 555 } else if (GICD_ISENABLER.contains(addr)) { 556 // Interrupt Set-Enable Registers 557 int first_intid = (addr - GICD_ISENABLER.start()) * 8; 558 559 if (isNotSPI(first_intid)) { 560 return; 561 } 562 563 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 564 i++, int_id++) { 565 566 if (nsAccessToSecInt(int_id, is_secure_access)) 567 { 568 continue; 569 } 570 571 bool enable = data & (1 << i) ? 1 : 0; 572 573 if (enable) { 574 if (!irqEnabled[int_id]) { 575 DPRINTF(GIC, "Gicv3Distributor::write(): " 576 "int_id %d enabled\n", int_id); 577 } 578 579 irqEnabled[int_id] = true; 580 } 581 } 582 583 return; 584 } else if (GICD_ICENABLER.contains(addr)) { 585 // Interrupt Clear-Enable Registers 586 int first_intid = (addr - GICD_ICENABLER.start()) * 8; 587 588 if (isNotSPI(first_intid)) { 589 return; 590 } 591 592 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 593 i++, int_id++) { 594 595 if (nsAccessToSecInt(int_id, is_secure_access)) 596 { 597 continue; 598 } 599 600 bool disable = data & (1 << i) ? 1 : 0; 601 602 if (disable) { 603 if (irqEnabled[int_id]) { 604 DPRINTF(GIC, "Gicv3Distributor::write(): " 605 "int_id %d disabled\n", int_id); 606 } 607 608 irqEnabled[int_id] = false; 609 } 610 } 611 612 return; 613 } else if (GICD_ISPENDR.contains(addr)) { 614 // Interrupt Set-Pending Registers 615 int first_intid = (addr - GICD_ISPENDR.start()) * 8; 616 617 if (isNotSPI(first_intid)) { 618 return; 619 } 620 621 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 622 i++, int_id++) { 623 624 if (nsAccessToSecInt(int_id, is_secure_access)) 625 { 626 if (irqNsacr[int_id] == 0) { 627 // Group 0 or Secure Group 1 interrupts are RAZ/WI 628 continue; 629 } 630 } 631 632 bool pending = data & (1 << i) ? 1 : 0; 633 634 if (pending) { 635 DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 636 "int_id %d (SPI) pending bit set\n", int_id); 637 irqPending[int_id] = true; 638 } 639 } 640 641 update(); 642 return; 643 } else if (GICD_ICPENDR.contains(addr)) { 644 // Interrupt Clear-Pending Registers 645 int first_intid = (addr - GICD_ICPENDR.start()) * 8; 646 647 if (isNotSPI(first_intid)) { 648 return; 649 } 650 651 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 652 i++, int_id++) { 653 654 if (nsAccessToSecInt(int_id, is_secure_access)) 655 { 656 if (irqNsacr[int_id] < 2) { 657 // Group 0 or Secure Group 1 interrupts are RAZ/WI 658 continue; 659 } 660 } 661 662 bool clear = data & (1 << i) ? 1 : 0; 663 664 if (clear) { 665 irqPending[int_id] = false; 666 clearIrqCpuInterface(int_id); 667 } 668 } 669 670 update(); 671 return; 672 } else if (GICD_ISACTIVER.contains(addr)) { 673 // Interrupt Set-Active Registers 674 int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 675 676 if (isNotSPI(first_intid)) { 677 return; 678 } 679 680 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 681 i++, int_id++) { 682 683 if (nsAccessToSecInt(int_id, is_secure_access)) 684 { 685 continue; 686 } 687 688 bool active = data & (1 << i) ? 1 : 0; 689 690 if (active) { 691 irqActive[int_id] = 1; 692 } 693 } 694 695 return; 696 } else if (GICD_ICACTIVER.contains(addr)) { 697 // Interrupt Clear-Active Registers 698 int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 699 700 if (isNotSPI(first_intid)) { 701 return; 702 } 703 704 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 705 i++, int_id++) { 706 707 if (nsAccessToSecInt(int_id, is_secure_access)) 708 { 709 continue; 710 } 711 712 bool clear = data & (1 << i) ? 1 : 0; 713 714 if (clear) { 715 if (irqActive[int_id]) { 716 DPRINTF(GIC, "Gicv3Distributor::write(): " 717 "int_id %d active cleared\n", int_id); 718 } 719 720 irqActive[int_id] = false; 721 } 722 } 723 724 return; 725 } else if (GICD_IPRIORITYR.contains(addr)) { 726 // Interrupt Priority Registers 727 int first_intid = addr - GICD_IPRIORITYR.start(); 728 729 if (isNotSPI(first_intid)) { 730 return; 731 } 732 733 for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 734 i++, int_id++) { 735 uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 736 737 if (!DS && !is_secure_access) { 738 if (getIntGroup(int_id) != Gicv3::G1NS) { 739 // RAZ/WI for non-secure accesses to secure interrupts 740 continue; 741 } else { 742 prio = 0x80 | (prio >> 1); 743 } 744 } 745 746 irqPriority[int_id] = prio; 747 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 748 int_id, irqPriority[int_id]); 749 } 750 751 return; 752 } else if (GICD_ITARGETSR.contains(addr)) { 753 // Interrupt Processor Targets Registers 754 // ARE always on, RAZ/WI 755 warn("Gicv3Distributor::write(): " 756 "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 757 return; 758 } else if (GICD_ICFGR.contains(addr)) { 759 // Interrupt Configuration Registers 760 // for x = 0 to 15: 761 // GICD_ICFGR[2x] = RES0 762 // GICD_ICFGR[2x + 1] = 763 // 0 level-sensitive 764 // 1 edge-triggered 765 int first_intid = (addr - GICD_ICFGR.start()) * 4; 766 767 if (isNotSPI(first_intid)) { 768 return; 769 } 770 771 for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 772 i = i + 2, int_id++) { 773 irqConfig[int_id] = data & (0x2 << i) ? 774 Gicv3::INT_EDGE_TRIGGERED : 775 Gicv3::INT_LEVEL_SENSITIVE; 776 DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 777 int_id, irqConfig[int_id]); 778 } 779 780 return; 781 } else if (GICD_IGRPMODR.contains(addr)) { 782 // Interrupt Group Modifier Registers 783 if (DS) { 784 return; 785 } else { 786 if (!is_secure_access) { 787 // RAZ/WI for non-secure accesses 788 return; 789 } else { 790 int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 791 792 if (isNotSPI(first_intid)) { 793 return; 794 } 795 796 for (int i = 0, int_id = first_intid; 797 i < 8 * size && int_id < itLines; i++, int_id++) { 798 irqGrpmod[int_id] = bits(data, i); 799 } 800 801 return ; 802 } 803 } 804 805 } else if (GICD_NSACR.contains(addr)) { 806 // Non-secure Access Control Registers 807 // 2 bits per interrupt 808 int first_intid = (addr - GICD_NSACR.start()) * 4; 809 810 if (isNotSPI(first_intid)) { 811 return; 812 } 813 814 if (DS || (!DS && !is_secure_access)) { 815 return; 816 } 817 818 for (int i = 0, int_id = first_intid; 819 i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 820 irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 821 } 822 823 return; 824 } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 825 // 64 bit registers. 2 accesses. 826 int int_id = (addr - GICD_IROUTER.start()) / 8; 827 828 if (isNotSPI(int_id)) { 829 return; 830 } 831 832 if (nsAccessToSecInt(int_id, is_secure_access)) 833 { 834 if (irqNsacr[int_id] < 3) { 835 // Group 0 or Secure Group 1 interrupts are RAZ/WI 836 return; 837 } 838 } 839 840 if (size == 4) { 841 if (addr & 7) { // high half of 64 bit register 842 irqAffinityRouting[int_id] = 843 (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 844 } else { // low half of 64 bit register 845 irqAffinityRouting[int_id] = 846 (irqAffinityRouting[int_id] & 0xffffffff00000000) | 847 (data & 0xffffffff); 848 } 849 } else { 850 irqAffinityRouting[int_id] = data; 851 } 852 853 DPRINTF(GIC, "Gicv3Distributor::write(): " 854 "int_id %d GICD_IROUTER %#llx\n", 855 int_id, irqAffinityRouting[int_id]); 856 return; 857 } 858 859 switch (addr) { 860 case GICD_CTLR: // Control Register 861 if (DS) { 862 /* 863 * E1NWF [7] 864 * 1 of N wakeup functionality not supported, RAZ/WI 865 * DS [6] - RAO/WI 866 * ARE [4] 867 * affinity routing always on, no GICv2 legacy, RAO/WI 868 * EnableGrp1 [1] 869 * EnableGrp0 [0] 870 */ 871 if ((data & (1 << 4)) == 0) { 872 warn("Gicv3Distributor::write(): " 873 "setting ARE to 0 is not supported!\n"); 874 } 875 876 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 877 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 878 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 879 "EnableGrp1NS %d EnableGrp0 %d\n", 880 EnableGrp1NS, EnableGrp0); 881 } else { 882 if (is_secure_access) { 883 /* 884 * E1NWF [7] 885 * 1 of N wakeup functionality not supported, RAZ/WI 886 * DS [6] 887 * ARE_NS [5] 888 * affinity routing always on, no GICv2 legacy, RAO/WI 889 * ARE_S [4] 890 * affinity routing always on, no GICv2 legacy, RAO/WI 891 * EnableGrp1S [2] 892 * EnableGrp1NS [1] 893 * EnableGrp0 [0] 894 */ 895 if ((data & (1 << 5)) == 0) { 896 warn("Gicv3Distributor::write(): " 897 "setting ARE_NS to 0 is not supported!\n"); 898 } 899 900 if ((data & (1 << 4)) == 0) { 901 warn("Gicv3Distributor::write(): " 902 "setting ARE_S to 0 is not supported!\n"); 903 } 904 905 DS = data & GICD_CTLR_DS; 906 EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 907 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 908 EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 909 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 910 "DS %d " 911 "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 912 DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 913 914 if (data & GICD_CTLR_DS) { 915 EnableGrp1S = 0; 916 } 917 } else { 918 /* 919 * ARE_NS [4] RAO/WI; 920 * EnableGrp1A [1] is a read-write alias of the Secure 921 * GICD_CTLR.EnableGrp1NS 922 * EnableGrp1 [0] RES0 923 */ 924 if ((data & (1 << 4)) == 0) { 925 warn("Gicv3Distributor::write(): " 926 "setting ARE_NS to 0 is not supported!\n"); 927 } 928 929 EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 930 DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 931 "EnableGrp1NS %d\n", EnableGrp1NS); 932 } 933 } 934 935 break; 936 937 default: 938 panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 939 break; 940 } 941} 942 943void 944Gicv3Distributor::sendInt(uint32_t int_id) 945{ 946 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 947 panic_if(int_id > itLines, "Invalid SPI!"); 948 irqPending[int_id] = true; 949 DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 950 "int_id %d (SPI) pending bit set\n", int_id); 951 update(); 952} 953 954void 955Gicv3Distributor::deassertSPI(uint32_t int_id) 956{ 957 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 958 panic_if(int_id > itLines, "Invalid SPI!"); 959 irqPending[int_id] = false; 960 clearIrqCpuInterface(int_id); 961 962 update(); 963} 964 965Gicv3CPUInterface* 966Gicv3Distributor::route(uint32_t int_id) 967{ 968 IROUTER affinity_routing = irqAffinityRouting[int_id]; 969 Gicv3Redistributor * target_redistributor = nullptr; 970 971 const Gicv3::GroupId int_group = getIntGroup(int_id); 972 973 if (affinity_routing.IRM) { 974 // Interrupts routed to any PE defined as a participating node 975 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 976 Gicv3Redistributor * redistributor_i = 977 gic->getRedistributor(i); 978 979 if (redistributor_i-> 980 canBeSelectedFor1toNInterrupt(int_group)) { 981 target_redistributor = redistributor_i; 982 break; 983 } 984 } 985 } else { 986 uint32_t affinity = (affinity_routing.Aff3 << 24) | 987 (affinity_routing.Aff2 << 16) | 988 (affinity_routing.Aff1 << 8) | 989 (affinity_routing.Aff0 << 0); 990 target_redistributor = 991 gic->getRedistributorByAffinity(affinity); 992 } 993 994 if (!target_redistributor) { 995 // Interrrupts targeting not present cpus must remain pending 996 return nullptr; 997 } else { 998 return target_redistributor->getCPUInterface(); 999 } 1000} 1001 1002void 1003Gicv3Distributor::clearIrqCpuInterface(uint32_t int_id) 1004{ 1005 auto cpu_interface = route(int_id); 1006 if (cpu_interface) 1007 cpu_interface->hppi.prio = 0xff; 1008} 1009 1010void 1011Gicv3Distributor::update() 1012{ 1013 // Find the highest priority pending SPI 1014 for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 1015 int_id++) { 1016 Gicv3::GroupId int_group = getIntGroup(int_id); 1017 bool group_enabled = groupEnabled(int_group); 1018 1019 if (irqPending[int_id] && irqEnabled[int_id] && 1020 !irqActive[int_id] && group_enabled) { 1021 1022 // Find the cpu interface where to route the interrupt 1023 Gicv3CPUInterface *target_cpu_interface = route(int_id); 1024 1025 // Invalid routing 1026 if (!target_cpu_interface) continue; 1027 1028 if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 1029 (irqPriority[int_id] == target_cpu_interface->hppi.prio && 1030 int_id < target_cpu_interface->hppi.intid)) { 1031 1032 target_cpu_interface->hppi.intid = int_id; 1033 target_cpu_interface->hppi.prio = irqPriority[int_id]; 1034 target_cpu_interface->hppi.group = int_group; 1035 } 1036 } 1037 } 1038 1039 // Update all redistributors 1040 for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 1041 gic->getRedistributor(i)->update(); 1042 } 1043} 1044 1045Gicv3::IntStatus 1046Gicv3Distributor::intStatus(uint32_t int_id) const 1047{ 1048 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1049 panic_if(int_id > itLines, "Invalid SPI!"); 1050 1051 if (irqPending[int_id]) { 1052 if (irqActive[int_id]) { 1053 return Gicv3::INT_ACTIVE_PENDING; 1054 } 1055 1056 return Gicv3::INT_PENDING; 1057 } else if (irqActive[int_id]) { 1058 return Gicv3::INT_ACTIVE; 1059 } else { 1060 return Gicv3::INT_INACTIVE; 1061 } 1062} 1063 1064Gicv3::GroupId 1065Gicv3Distributor::getIntGroup(int int_id) const 1066{ 1067 panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 1068 panic_if(int_id > itLines, "Invalid SPI!"); 1069 1070 if (DS) { 1071 if (irqGroup[int_id] == 1) { 1072 return Gicv3::G1NS; 1073 } else { 1074 return Gicv3::G0S; 1075 } 1076 } else { 1077 if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 1078 return Gicv3::G0S; 1079 } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 1080 return Gicv3::G1NS; 1081 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 1082 return Gicv3::G1S; 1083 } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 1084 return Gicv3::G1NS; 1085 } 1086 } 1087 1088 M5_UNREACHABLE; 1089} 1090 1091void 1092Gicv3Distributor::activateIRQ(uint32_t int_id) 1093{ 1094 irqPending[int_id] = false; 1095 irqActive[int_id] = true; 1096} 1097 1098void 1099Gicv3Distributor::deactivateIRQ(uint32_t int_id) 1100{ 1101 irqActive[int_id] = false; 1102} 1103 1104void 1105Gicv3Distributor::serialize(CheckpointOut & cp) const 1106{ 1107 SERIALIZE_SCALAR(ARE); 1108 SERIALIZE_SCALAR(DS); 1109 SERIALIZE_SCALAR(EnableGrp1S); 1110 SERIALIZE_SCALAR(EnableGrp1NS); 1111 SERIALIZE_SCALAR(EnableGrp0); 1112 SERIALIZE_CONTAINER(irqGroup); 1113 SERIALIZE_CONTAINER(irqEnabled); 1114 SERIALIZE_CONTAINER(irqPending); 1115 SERIALIZE_CONTAINER(irqActive); 1116 SERIALIZE_CONTAINER(irqPriority); 1117 SERIALIZE_CONTAINER(irqConfig); 1118 SERIALIZE_CONTAINER(irqGrpmod); 1119 SERIALIZE_CONTAINER(irqNsacr); 1120 SERIALIZE_CONTAINER(irqAffinityRouting); 1121} 1122 1123void 1124Gicv3Distributor::unserialize(CheckpointIn & cp) 1125{ 1126 UNSERIALIZE_SCALAR(ARE); 1127 UNSERIALIZE_SCALAR(DS); 1128 UNSERIALIZE_SCALAR(EnableGrp1S); 1129 UNSERIALIZE_SCALAR(EnableGrp1NS); 1130 UNSERIALIZE_SCALAR(EnableGrp0); 1131 UNSERIALIZE_CONTAINER(irqGroup); 1132 UNSERIALIZE_CONTAINER(irqEnabled); 1133 UNSERIALIZE_CONTAINER(irqPending); 1134 UNSERIALIZE_CONTAINER(irqActive); 1135 UNSERIALIZE_CONTAINER(irqPriority); 1136 UNSERIALIZE_CONTAINER(irqConfig); 1137 UNSERIALIZE_CONTAINER(irqGrpmod); 1138 UNSERIALIZE_CONTAINER(irqNsacr); 1139 UNSERIALIZE_CONTAINER(irqAffinityRouting); 1140} 1141