gic_v3_distributor.cc revision 14259
16019Shines@cs.fsu.edu/* 213374Sanouk.vanlaer@arm.com * Copyright (c) 2019 ARM Limited 37399SAli.Saidi@ARM.com * All rights reserved 47399SAli.Saidi@ARM.com * 57399SAli.Saidi@ARM.com * The license below extends only to copyright in the software and shall 67399SAli.Saidi@ARM.com * not be construed as granting a license to any other intellectual 77399SAli.Saidi@ARM.com * property including but not limited to intellectual property relating 87399SAli.Saidi@ARM.com * to a hardware implementation of the functionality of the software 97399SAli.Saidi@ARM.com * licensed hereunder. You may use the software subject to the license 107399SAli.Saidi@ARM.com * terms below provided that you ensure that this notice is replicated 117399SAli.Saidi@ARM.com * unmodified and in its entirety in all distributions of the software, 127399SAli.Saidi@ARM.com * modified or unmodified, in source code or in binary form. 137399SAli.Saidi@ARM.com * 146019Shines@cs.fsu.edu * Copyright (c) 2018 Metempsy Technology Consulting 156019Shines@cs.fsu.edu * All rights reserved. 166019Shines@cs.fsu.edu * 176019Shines@cs.fsu.edu * Redistribution and use in source and binary forms, with or without 186019Shines@cs.fsu.edu * modification, are permitted provided that the following conditions are 196019Shines@cs.fsu.edu * met: redistributions of source code must retain the above copyright 206019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer; 216019Shines@cs.fsu.edu * redistributions in binary form must reproduce the above copyright 226019Shines@cs.fsu.edu * notice, this list of conditions and the following disclaimer in the 236019Shines@cs.fsu.edu * documentation and/or other materials provided with the distribution; 246019Shines@cs.fsu.edu * neither the name of the copyright holders nor the names of its 256019Shines@cs.fsu.edu * contributors may be used to endorse or promote products derived from 266019Shines@cs.fsu.edu * this software without specific prior written permission. 276019Shines@cs.fsu.edu * 286019Shines@cs.fsu.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 296019Shines@cs.fsu.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 306019Shines@cs.fsu.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 316019Shines@cs.fsu.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 326019Shines@cs.fsu.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 336019Shines@cs.fsu.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 346019Shines@cs.fsu.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 356019Shines@cs.fsu.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 366019Shines@cs.fsu.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 376019Shines@cs.fsu.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 386019Shines@cs.fsu.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 396019Shines@cs.fsu.edu * 407399SAli.Saidi@ARM.com * Authors: Jairo Balart 416019Shines@cs.fsu.edu */ 426019Shines@cs.fsu.edu 436019Shines@cs.fsu.edu#include "dev/arm/gic_v3_distributor.hh" 446019Shines@cs.fsu.edu 456019Shines@cs.fsu.edu#include <algorithm> 466019Shines@cs.fsu.edu 476019Shines@cs.fsu.edu#include "base/intmath.hh" 488229Snate@binkert.org#include "debug/GIC.hh" 496019Shines@cs.fsu.edu#include "dev/arm/gic_v3.hh" 506019Shines@cs.fsu.edu#include "dev/arm/gic_v3_cpu_interface.hh" 5110687SAndreas.Sandberg@ARM.com#include "dev/arm/gic_v3_redistributor.hh" 526019Shines@cs.fsu.edu 536019Shines@cs.fsu.educonst AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff); 546116Snate@binkert.orgconst AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f); 5510463SAndreas.Sandberg@ARM.comconst AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff); 566019Shines@cs.fsu.educonst AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f); 576019Shines@cs.fsu.educonst AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff); 586019Shines@cs.fsu.educonst AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f); 596019Shines@cs.fsu.educonst AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff); 606019Shines@cs.fsu.educonst AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff); 617404SAli.Saidi@ARM.comconst AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff); 6210037SARM gem5 Developersconst AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff); 6310037SARM gem5 Developersconst AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f); 6411395Sandreas.sandberg@arm.comconst AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff); 6511395Sandreas.sandberg@arm.comconst AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f); 6611395Sandreas.sandberg@arm.comconst AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f); 6711395Sandreas.sandberg@arm.comconst AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0); 6811395Sandreas.sandberg@arm.com 6911395Sandreas.sandberg@arm.comGicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) 7011395Sandreas.sandberg@arm.com : gic(gic), 7111395Sandreas.sandberg@arm.com itLines(it_lines), 7211395Sandreas.sandberg@arm.com ARE(true), 7311395Sandreas.sandberg@arm.com EnableGrp1S(0), 7411395Sandreas.sandberg@arm.com EnableGrp1NS(0), 7511395Sandreas.sandberg@arm.com EnableGrp0(0), 7611395Sandreas.sandberg@arm.com irqGroup(it_lines, 0), 7711395Sandreas.sandberg@arm.com irqEnabled(it_lines, false), 7811395Sandreas.sandberg@arm.com irqPending(it_lines, false), 7911395Sandreas.sandberg@arm.com irqActive(it_lines, false), 8012749Sgiacomo.travaglini@arm.com irqPriority(it_lines, 0xAA), 8111395Sandreas.sandberg@arm.com irqConfig(it_lines, Gicv3::INT_LEVEL_SENSITIVE), 8211395Sandreas.sandberg@arm.com irqGrpmod(it_lines, 0), 8311395Sandreas.sandberg@arm.com irqNsacr(it_lines, 0), 8411395Sandreas.sandberg@arm.com irqAffinityRouting(it_lines, 0), 8511395Sandreas.sandberg@arm.com gicdTyper(0), 8611395Sandreas.sandberg@arm.com gicdPidr0(0x92), 8711395Sandreas.sandberg@arm.com gicdPidr1(0xb4), 8811395Sandreas.sandberg@arm.com gicdPidr2(0x3b), 8911395Sandreas.sandberg@arm.com gicdPidr3(0), 9011395Sandreas.sandberg@arm.com gicdPidr4(0x44) 9111395Sandreas.sandberg@arm.com{ 9211395Sandreas.sandberg@arm.com panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!"); 9311395Sandreas.sandberg@arm.com /* 9411395Sandreas.sandberg@arm.com * RSS [26] == 1 9511395Sandreas.sandberg@arm.com * (The implementation does supports targeted SGIs with affinity 9611395Sandreas.sandberg@arm.com * level 0 values of 0 - 255) 9711395Sandreas.sandberg@arm.com * No1N [25] == 1 9811395Sandreas.sandberg@arm.com * (1 of N SPI interrupts are not supported) 9911395Sandreas.sandberg@arm.com * A3V [24] == 1 10011395Sandreas.sandberg@arm.com * (Supports nonzero values of Affinity level 3) 1017404SAli.Saidi@ARM.com * IDbits [23:19] == 0xf 1026019Shines@cs.fsu.edu * (The number of interrupt identifier bits supported, minus one) 1036019Shines@cs.fsu.edu * DVIS [18] == 0 1047294Sgblack@eecs.umich.edu * (The implementation does not support Direct Virtual LPI 1057294Sgblack@eecs.umich.edu * injection) 10610037SARM gem5 Developers * LPIS [17] == 1 1077294Sgblack@eecs.umich.edu * (The implementation does not support LPIs) 1087294Sgblack@eecs.umich.edu * MBIS [16] == 1 1097294Sgblack@eecs.umich.edu * (The implementation supports message-based interrupts 11010037SARM gem5 Developers * by writing to Distributor registers) 11110037SARM gem5 Developers * SecurityExtn [10] == X 11210037SARM gem5 Developers * (The GIC implementation supports two Security states) 11310037SARM gem5 Developers * CPUNumber [7:5] == 0 1147294Sgblack@eecs.umich.edu * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy]) 11510037SARM gem5 Developers * ITLinesNumber [4:0] == N 1167404SAli.Saidi@ARM.com * (MaxSPIIntId = 32 (N + 1) - 1) 11710037SARM gem5 Developers */ 1187294Sgblack@eecs.umich.edu int max_spi_int_id = itLines - 1; 1197294Sgblack@eecs.umich.edu int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1; 1207294Sgblack@eecs.umich.edu gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) | 12110037SARM gem5 Developers (1 << 17) | (1 << 16) | 12210037SARM gem5 Developers ((gic->getSystem()->haveSecurity() ? 1 : 0) << 10) | 12310037SARM gem5 Developers (it_lines_number << 0); 12410037SARM gem5 Developers 12510037SARM gem5 Developers if (gic->getSystem()->haveSecurity()) { 12610037SARM gem5 Developers DS = false; 12710037SARM gem5 Developers } else { 12810037SARM gem5 Developers DS = true; 12910037SARM gem5 Developers } 13011577SDylan.Johnson@ARM.com} 13111577SDylan.Johnson@ARM.com 13211577SDylan.Johnson@ARM.comvoid 13311577SDylan.Johnson@ARM.comGicv3Distributor::init() 13411577SDylan.Johnson@ARM.com{ 13511577SDylan.Johnson@ARM.com} 13611577SDylan.Johnson@ARM.com 13711577SDylan.Johnson@ARM.comuint64_t 13811577SDylan.Johnson@ARM.comGicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) 13911577SDylan.Johnson@ARM.com{ 14011577SDylan.Johnson@ARM.com if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 1417294Sgblack@eecs.umich.edu uint64_t val = 0x0; 14212735Sandreas.sandberg@arm.com 14312735Sandreas.sandberg@arm.com if (!DS && !is_secure_access) { 14412735Sandreas.sandberg@arm.com // RAZ/WI for non-secure accesses 14512735Sandreas.sandberg@arm.com return 0; 14612735Sandreas.sandberg@arm.com } 14712735Sandreas.sandberg@arm.com 14812735Sandreas.sandberg@arm.com int first_intid = (addr - GICD_IGROUPR.start()) * 8; 14912735Sandreas.sandberg@arm.com 1506019Shines@cs.fsu.edu if (isNotSPI(first_intid)) { 15110037SARM gem5 Developers return 0; 15210037SARM gem5 Developers } 15310037SARM gem5 Developers 15410037SARM gem5 Developers for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 15513374Sanouk.vanlaer@arm.com i++, int_id++) { 15613374Sanouk.vanlaer@arm.com val |= irqGroup[int_id] << i; 15713374Sanouk.vanlaer@arm.com } 15813374Sanouk.vanlaer@arm.com 15910037SARM gem5 Developers return val; 16010037SARM gem5 Developers } else if (GICD_ISENABLER.contains(addr)) { 16110037SARM gem5 Developers // Interrupt Set-Enable Registers 1627436Sdam.sunwoo@arm.com uint64_t val = 0x0; 1637404SAli.Saidi@ARM.com int first_intid = (addr - GICD_ISENABLER.start()) * 8; 16410037SARM gem5 Developers 16510037SARM gem5 Developers if (isNotSPI(first_intid)) { 1666019Shines@cs.fsu.edu return 0; 16711395Sandreas.sandberg@arm.com } 16811395Sandreas.sandberg@arm.com 1697399SAli.Saidi@ARM.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1707734SAli.Saidi@ARM.com i++, int_id++) { 1717734SAli.Saidi@ARM.com 1727734SAli.Saidi@ARM.com if (nsAccessToSecInt(int_id, is_secure_access)) 1737734SAli.Saidi@ARM.com { 1747734SAli.Saidi@ARM.com continue; 1757734SAli.Saidi@ARM.com } 1767734SAli.Saidi@ARM.com 1777734SAli.Saidi@ARM.com val |= irqEnabled[int_id] << i; 1787734SAli.Saidi@ARM.com } 1797734SAli.Saidi@ARM.com 1807734SAli.Saidi@ARM.com return val; 1817734SAli.Saidi@ARM.com } else if (GICD_ICENABLER.contains(addr)) { 1827734SAli.Saidi@ARM.com // Interrupt Clear-Enable Registers 1837734SAli.Saidi@ARM.com uint64_t val = 0x0; 1847734SAli.Saidi@ARM.com int first_intid = (addr - GICD_ICENABLER.start()) * 8; 1857734SAli.Saidi@ARM.com 1867734SAli.Saidi@ARM.com if (isNotSPI(first_intid)) { 1877734SAli.Saidi@ARM.com return 0; 1887734SAli.Saidi@ARM.com } 1897734SAli.Saidi@ARM.com 1906019Shines@cs.fsu.edu for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1916019Shines@cs.fsu.edu i++, int_id++) { 1926019Shines@cs.fsu.edu 1936019Shines@cs.fsu.edu if (nsAccessToSecInt(int_id, is_secure_access)) 19410463SAndreas.Sandberg@ARM.com { 19510463SAndreas.Sandberg@ARM.com continue; 19610463SAndreas.Sandberg@ARM.com } 1977697SAli.Saidi@ARM.com 1987404SAli.Saidi@ARM.com val |= (irqEnabled[int_id] << i); 1996019Shines@cs.fsu.edu } 20010037SARM gem5 Developers 20110037SARM gem5 Developers return val; 2026019Shines@cs.fsu.edu } else if (GICD_ISPENDR.contains(addr)) { 2039535Smrinmoy.ghosh@arm.com // Interrupt Set-Pending Registers 2049535Smrinmoy.ghosh@arm.com uint64_t val = 0x0; 2059535Smrinmoy.ghosh@arm.com int first_intid = (addr - GICD_ISPENDR.start()) * 8; 20610037SARM gem5 Developers 20710037SARM gem5 Developers if (isNotSPI(first_intid)) { 20810037SARM gem5 Developers return 0; 2099535Smrinmoy.ghosh@arm.com } 21010037SARM gem5 Developers 21110037SARM gem5 Developers for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 2129535Smrinmoy.ghosh@arm.com i++, int_id++) { 21310037SARM gem5 Developers 21410037SARM gem5 Developers if (nsAccessToSecInt(int_id, is_secure_access)) 21510037SARM gem5 Developers { 2169535Smrinmoy.ghosh@arm.com if (irqNsacr[int_id] == 0) { 2176019Shines@cs.fsu.edu // Group 0 or Secure Group 1 interrupts are RAZ/WI 21810037SARM gem5 Developers continue; 21911169Sandreas.hansson@arm.com } 22010194SGeoffrey.Blake@arm.com } 22110037SARM gem5 Developers 22211169Sandreas.hansson@arm.com val |= (irqPending[int_id] << i); 22310037SARM gem5 Developers } 22411395Sandreas.sandberg@arm.com 22511395Sandreas.sandberg@arm.com return val; 22610717Sandreas.hansson@arm.com } else if (GICD_ICPENDR.contains(addr)) { 22710717Sandreas.hansson@arm.com // Interrupt Clear-Pending Registers 22810717Sandreas.hansson@arm.com uint64_t val = 0x0; 22910037SARM gem5 Developers int first_intid = (addr - GICD_ICPENDR.start()) * 8; 2306019Shines@cs.fsu.edu 2316019Shines@cs.fsu.edu if (isNotSPI(first_intid)) { 2327404SAli.Saidi@ARM.com return 0; 2337404SAli.Saidi@ARM.com } 23412749Sgiacomo.travaglini@arm.com 23512749Sgiacomo.travaglini@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 23610037SARM gem5 Developers i++, int_id++) { 23710037SARM gem5 Developers 23810037SARM gem5 Developers if (nsAccessToSecInt(int_id, is_secure_access)) 23912749Sgiacomo.travaglini@arm.com { 24012749Sgiacomo.travaglini@arm.com if (irqNsacr[int_id] < 2) { 24112749Sgiacomo.travaglini@arm.com // Group 0 or Secure Group 1 interrupts are RAZ/WI 24210037SARM gem5 Developers continue; 24310037SARM gem5 Developers } 24412749Sgiacomo.travaglini@arm.com } 24512749Sgiacomo.travaglini@arm.com 24610037SARM gem5 Developers val |= (irqPending[int_id] << i); 24710037SARM gem5 Developers } 24810037SARM gem5 Developers 24910037SARM gem5 Developers return val; 25010037SARM gem5 Developers } else if (GICD_ISACTIVER.contains(addr)) { 25110037SARM gem5 Developers // Interrupt Set-Active Registers 25210037SARM gem5 Developers int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 25310037SARM gem5 Developers 25410037SARM gem5 Developers if (isNotSPI(first_intid)) { 25510037SARM gem5 Developers return 0; 25610037SARM gem5 Developers } 25710037SARM gem5 Developers 25810037SARM gem5 Developers uint64_t val = 0x0; 25910037SARM gem5 Developers 26010037SARM gem5 Developers for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 26110037SARM gem5 Developers i++, int_id++) { 26210037SARM gem5 Developers 26310037SARM gem5 Developers if (nsAccessToSecInt(int_id, is_secure_access)) 26410037SARM gem5 Developers { 26511169Sandreas.hansson@arm.com // Group 0 or Secure Group 1 interrupts are RAZ/WI 26610037SARM gem5 Developers if (irqNsacr[int_id] < 2) { 26710037SARM gem5 Developers continue; 26810037SARM gem5 Developers } 26910037SARM gem5 Developers } 2707404SAli.Saidi@ARM.com 2717404SAli.Saidi@ARM.com val |= (irqActive[int_id] << i); 2727404SAli.Saidi@ARM.com } 2737404SAli.Saidi@ARM.com 27410037SARM gem5 Developers return val; 2757404SAli.Saidi@ARM.com } else if (GICD_ICACTIVER.contains(addr)) { 27610037SARM gem5 Developers // Interrupt Clear-Active Registers 27710037SARM gem5 Developers int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 2787404SAli.Saidi@ARM.com 2797404SAli.Saidi@ARM.com if (isNotSPI(first_intid)) { 2807404SAli.Saidi@ARM.com return 0; 28110037SARM gem5 Developers } 2827404SAli.Saidi@ARM.com 28310037SARM gem5 Developers uint64_t val = 0x0; 2847404SAli.Saidi@ARM.com 2857404SAli.Saidi@ARM.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 2867404SAli.Saidi@ARM.com i++, int_id++) { 28710037SARM gem5 Developers 28810037SARM gem5 Developers if (nsAccessToSecInt(int_id, is_secure_access)) 2897404SAli.Saidi@ARM.com { 29010037SARM gem5 Developers if (irqNsacr[int_id] < 2) { 2917404SAli.Saidi@ARM.com continue; 29211584SDylan.Johnson@ARM.com } 29311584SDylan.Johnson@ARM.com } 29411584SDylan.Johnson@ARM.com 29511584SDylan.Johnson@ARM.com val |= (irqActive[int_id] << i); 29611584SDylan.Johnson@ARM.com } 29711584SDylan.Johnson@ARM.com 29811584SDylan.Johnson@ARM.com return val; 29911584SDylan.Johnson@ARM.com } else if (GICD_IPRIORITYR.contains(addr)) { 30011584SDylan.Johnson@ARM.com // Interrupt Priority Registers 30112749Sgiacomo.travaglini@arm.com uint64_t val = 0x0; 30212749Sgiacomo.travaglini@arm.com int first_intid = addr - GICD_IPRIORITYR.start(); 30312749Sgiacomo.travaglini@arm.com 30412749Sgiacomo.travaglini@arm.com if (isNotSPI(first_intid)) { 30512749Sgiacomo.travaglini@arm.com return 0; 30612749Sgiacomo.travaglini@arm.com } 30712749Sgiacomo.travaglini@arm.com 30811584SDylan.Johnson@ARM.com for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 30910037SARM gem5 Developers i++, int_id++) { 3107404SAli.Saidi@ARM.com 31111169Sandreas.hansson@arm.com uint8_t prio = irqPriority[int_id]; 3126019Shines@cs.fsu.edu 31310037SARM gem5 Developers if (!DS && !is_secure_access) { 31410037SARM gem5 Developers if (getIntGroup(int_id) != Gicv3::G1NS) { 3156019Shines@cs.fsu.edu // RAZ/WI for non-secure accesses for secure interrupts 3166019Shines@cs.fsu.edu continue; 3177694SAli.Saidi@ARM.com } else { 3187694SAli.Saidi@ARM.com // NS view 3197694SAli.Saidi@ARM.com prio = (prio << 1) & 0xff; 3207694SAli.Saidi@ARM.com } 3217694SAli.Saidi@ARM.com } 3227694SAli.Saidi@ARM.com 3237694SAli.Saidi@ARM.com val |= prio << (i * 8); 3247694SAli.Saidi@ARM.com } 3257694SAli.Saidi@ARM.com 3267694SAli.Saidi@ARM.com return val; 3278733Sgeoffrey.blake@arm.com } else if (GICD_ITARGETSR.contains(addr)) { 3288733Sgeoffrey.blake@arm.com // Interrupt Processor Targets Registers 3298733Sgeoffrey.blake@arm.com // ARE always on, RAZ/WI 3308733Sgeoffrey.blake@arm.com warn("Gicv3Distributor::read(): " 33112749Sgiacomo.travaglini@arm.com "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 33212749Sgiacomo.travaglini@arm.com return 0; 33312419Sgabeblack@google.com } else if (GICD_ICFGR.contains(addr)) { 33412749Sgiacomo.travaglini@arm.com // Interrupt Configuration Registers 33512749Sgiacomo.travaglini@arm.com int first_intid = (addr - GICD_ICFGR.start()) * 4; 33612419Sgabeblack@google.com 33712419Sgabeblack@google.com if (isNotSPI(first_intid)) { 33812419Sgabeblack@google.com return 0; 3398733Sgeoffrey.blake@arm.com } 3407436Sdam.sunwoo@arm.com 3417436Sdam.sunwoo@arm.com uint64_t val = 0x0; 3427436Sdam.sunwoo@arm.com 34310037SARM gem5 Developers for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 3447436Sdam.sunwoo@arm.com i = i + 2, int_id++) { 3457436Sdam.sunwoo@arm.com 3467436Sdam.sunwoo@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 34710037SARM gem5 Developers { 34810037SARM gem5 Developers continue; 3497436Sdam.sunwoo@arm.com } 3507436Sdam.sunwoo@arm.com 3517436Sdam.sunwoo@arm.com if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 3527436Sdam.sunwoo@arm.com val |= (0x2 << i); 3537436Sdam.sunwoo@arm.com } 35412749Sgiacomo.travaglini@arm.com } 3558733Sgeoffrey.blake@arm.com 35610037SARM gem5 Developers return val; 35712749Sgiacomo.travaglini@arm.com } else if (GICD_IGRPMODR.contains(addr)) { 3587404SAli.Saidi@ARM.com // Interrupt Group Modifier Registers 35912749Sgiacomo.travaglini@arm.com if (DS) { 36012406Sgabeblack@google.com // RAZ/WI if security disabled 36112406Sgabeblack@google.com return 0; 36212749Sgiacomo.travaglini@arm.com } else { 36312749Sgiacomo.travaglini@arm.com if (!is_secure_access) { 36412406Sgabeblack@google.com // RAZ/WI for non-secure accesses 36512406Sgabeblack@google.com return 0; 36612406Sgabeblack@google.com } else { 36712406Sgabeblack@google.com int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 36812749Sgiacomo.travaglini@arm.com 36910037SARM gem5 Developers if (isNotSPI(first_intid)) { 37012406Sgabeblack@google.com return 0; 37112406Sgabeblack@google.com } 37212749Sgiacomo.travaglini@arm.com 37312406Sgabeblack@google.com uint64_t val = 0x0; 37412406Sgabeblack@google.com 37512406Sgabeblack@google.com for (int i = 0, int_id = first_intid; 37612406Sgabeblack@google.com i < 8 * size && int_id < itLines; i++, int_id++) { 37712749Sgiacomo.travaglini@arm.com val |= irqGrpmod[int_id] << i; 37810037SARM gem5 Developers } 37910037SARM gem5 Developers 38012406Sgabeblack@google.com return val; 38112749Sgiacomo.travaglini@arm.com } 38212749Sgiacomo.travaglini@arm.com } 3836116Snate@binkert.org } else if (GICD_NSACR.contains(addr)) { 38411168Sandreas.hansson@arm.com // Non-secure Access Control Registers 3859439SAndreas.Sandberg@ARM.com // 2 bits per interrupt 3866019Shines@cs.fsu.edu int first_intid = (addr - GICD_NSACR.start()) * 4; 38711168Sandreas.hansson@arm.com 38811168Sandreas.hansson@arm.com if (isNotSPI(first_intid)) { 3896019Shines@cs.fsu.edu return 0; 39011169Sandreas.hansson@arm.com } 3917749SAli.Saidi@ARM.com 39211168Sandreas.hansson@arm.com if (DS || (!DS && !is_secure_access)) { 39310463SAndreas.Sandberg@ARM.com return 0; 3948922Swilliam.wang@arm.com } 3958922Swilliam.wang@arm.com 3968922Swilliam.wang@arm.com uint64_t val = 0x0; 3978922Swilliam.wang@arm.com 3988922Swilliam.wang@arm.com for (int i = 0, int_id = first_intid; 3998922Swilliam.wang@arm.com i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 4008922Swilliam.wang@arm.com val |= irqNsacr[int_id] << i; 4018922Swilliam.wang@arm.com } 4028922Swilliam.wang@arm.com 4038922Swilliam.wang@arm.com return val; 40411169Sandreas.hansson@arm.com } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers 4057781SAli.Saidi@ARM.com // ARE always on, RAZ/WI 4067749SAli.Saidi@ARM.com warn("Gicv3Distributor::read(): " 4077749SAli.Saidi@ARM.com "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n"); 4087749SAli.Saidi@ARM.com return 0x0; 4097749SAli.Saidi@ARM.com } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers 4107749SAli.Saidi@ARM.com // ARE always on, RAZ/WI 41110854SNathanael.Premillieu@arm.com warn("Gicv3Distributor::read(): " 41210037SARM gem5 Developers "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n"); 41310037SARM gem5 Developers return 0x0; 4147749SAli.Saidi@ARM.com } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 41510037SARM gem5 Developers // 64 bit registers. 2 or 1 access. 4167749SAli.Saidi@ARM.com int int_id = (addr - GICD_IROUTER.start()) / 8; 41710037SARM gem5 Developers 41810037SARM gem5 Developers if (isNotSPI(int_id)) { 41910037SARM gem5 Developers return 0; 42010037SARM gem5 Developers } 42110037SARM gem5 Developers 4227749SAli.Saidi@ARM.com if (nsAccessToSecInt(int_id, is_secure_access)) 4237749SAli.Saidi@ARM.com { 42410037SARM gem5 Developers if (irqNsacr[int_id] < 3) { 4257749SAli.Saidi@ARM.com return 0; 4267749SAli.Saidi@ARM.com } 42711152Smitch.hayenga@arm.com } 42810037SARM gem5 Developers 42910037SARM gem5 Developers if (size == 4) { 43010037SARM gem5 Developers if (addr & 7) { // high half of 64 bit register 43110037SARM gem5 Developers return irqAffinityRouting[int_id] >> 32; 43210037SARM gem5 Developers } else { // high low of 64 bit register 43310037SARM gem5 Developers return irqAffinityRouting[int_id] & 0xFFFFFFFF; 43410037SARM gem5 Developers } 43512005Sandreas.sandberg@arm.com } else { 43612005Sandreas.sandberg@arm.com return irqAffinityRouting[int_id]; 43710037SARM gem5 Developers } 43810037SARM gem5 Developers } 43910037SARM gem5 Developers 4407749SAli.Saidi@ARM.com switch (addr) { 4418299Schander.sudanthi@arm.com case GICD_CTLR: // Control Register 4428299Schander.sudanthi@arm.com if (!DS) { 4438299Schander.sudanthi@arm.com if (is_secure_access) { 4448299Schander.sudanthi@arm.com // E1NWF [7] RAZ/WI 4458299Schander.sudanthi@arm.com // DS [6] - Disable Security 4467749SAli.Saidi@ARM.com // ARE_NS [5] RAO/WI 44710037SARM gem5 Developers // ARE_S [4] RAO/WI 44810037SARM gem5 Developers // EnableGrp1S [2] 44910037SARM gem5 Developers // EnableGrp1NS [1] 45010037SARM gem5 Developers // EnableGrp0 [0] 45110037SARM gem5 Developers return (EnableGrp0 << 0) | 45210037SARM gem5 Developers (EnableGrp1NS << 1) | 45310037SARM gem5 Developers (EnableGrp1S << 2) | 45410037SARM gem5 Developers (1 << 4) | 45510037SARM gem5 Developers (1 << 5) | 45610037SARM gem5 Developers (DS << 6); 45710037SARM gem5 Developers } else { 45810037SARM gem5 Developers // ARE_NS [4] RAO/WI; 45910037SARM gem5 Developers // EnableGrp1A [1] is a read-write alias of the Secure 46011395Sandreas.sandberg@arm.com // GICD_CTLR.EnableGrp1NS 46111395Sandreas.sandberg@arm.com // EnableGrp1 [0] RES0 46212749Sgiacomo.travaglini@arm.com return (1 << 4) | (EnableGrp1NS << 1); 46311395Sandreas.sandberg@arm.com } 46411395Sandreas.sandberg@arm.com } else { 46511395Sandreas.sandberg@arm.com return (DS << 6) | (ARE << 4) | 46611395Sandreas.sandberg@arm.com (EnableGrp1NS << 1) | (EnableGrp0 << 0); 4676019Shines@cs.fsu.edu } 4686019Shines@cs.fsu.edu 46912605Sgiacomo.travaglini@arm.com case GICD_TYPER: // Interrupt Controller Type Register 47012605Sgiacomo.travaglini@arm.com return gicdTyper; 47112605Sgiacomo.travaglini@arm.com 47212605Sgiacomo.travaglini@arm.com case GICD_IIDR: // Implementer Identification Register 47312605Sgiacomo.travaglini@arm.com //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 47412605Sgiacomo.travaglini@arm.com return 0; 47512605Sgiacomo.travaglini@arm.com 47612605Sgiacomo.travaglini@arm.com case GICD_STATUSR: // Error Reporting Status Register 47712605Sgiacomo.travaglini@arm.com // Optional register, RAZ/WI 47812605Sgiacomo.travaglini@arm.com return 0x0; 47912605Sgiacomo.travaglini@arm.com 48012605Sgiacomo.travaglini@arm.com case GICD_PIDR0: // Peripheral ID0 Register 48112605Sgiacomo.travaglini@arm.com return gicdPidr0; 48212605Sgiacomo.travaglini@arm.com 48312605Sgiacomo.travaglini@arm.com case GICD_PIDR1: // Peripheral ID1 Register 48412605Sgiacomo.travaglini@arm.com return gicdPidr1; 48512605Sgiacomo.travaglini@arm.com 48612605Sgiacomo.travaglini@arm.com case GICD_PIDR2: // Peripheral ID2 Register 4877811Ssteve.reinhardt@amd.com return gicdPidr2; 4886019Shines@cs.fsu.edu 4896019Shines@cs.fsu.edu 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->resetHppi(int_id); 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} 1192