gic_v3_distributor.cc revision 14232
12810SN/A/* 212724Snikos.nikoleris@arm.com * Copyright (c) 2019 ARM Limited 38856Sandreas.hansson@arm.com * All rights reserved 48856Sandreas.hansson@arm.com * 58856Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 68856Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 78856Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 88856Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 98856Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 108856Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 118856Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 128856Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 138856Sandreas.hansson@arm.com * 142810SN/A * Copyright (c) 2018 Metempsy Technology Consulting 152810SN/A * All rights reserved. 162810SN/A * 172810SN/A * Redistribution and use in source and binary forms, with or without 182810SN/A * modification, are permitted provided that the following conditions are 192810SN/A * met: redistributions of source code must retain the above copyright 202810SN/A * notice, this list of conditions and the following disclaimer; 212810SN/A * redistributions in binary form must reproduce the above copyright 222810SN/A * notice, this list of conditions and the following disclaimer in the 232810SN/A * documentation and/or other materials provided with the distribution; 242810SN/A * neither the name of the copyright holders nor the names of its 252810SN/A * contributors may be used to endorse or promote products derived from 262810SN/A * this software without specific prior written permission. 272810SN/A * 282810SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 292810SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 302810SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 312810SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 322810SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 332810SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 342810SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 352810SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 362810SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 372810SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 382810SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 392810SN/A * 402810SN/A * Authors: Jairo Balart 4112724Snikos.nikoleris@arm.com */ 422810SN/A 432810SN/A#include "dev/arm/gic_v3_distributor.hh" 442810SN/A 452810SN/A#include <algorithm> 462810SN/A 472810SN/A#include "debug/GIC.hh" 482810SN/A#include "dev/arm/gic_v3.hh" 4911486Snikos.nikoleris@arm.com#include "dev/arm/gic_v3_cpu_interface.hh" 5011486Snikos.nikoleris@arm.com#include "dev/arm/gic_v3_redistributor.hh" 5112724Snikos.nikoleris@arm.com 5212724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x00ff); 538232Snate@binkert.orgconst AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f); 5412724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff); 5513222Sodanrc@yahoo.com.brconst AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x027f); 5612724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x02ff); 5711486Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f); 5812724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff); 5912724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff); 6012724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff); 6113352Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0cff); 6212724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d7f); 6312724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0eff); 6412724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f); 6512724Snikos.nikoleris@arm.comconst AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f); 662810SN/Aconst AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0); 672810SN/A 682810SN/AGicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines) 698856Sandreas.hansson@arm.com : gic(gic), 708856Sandreas.hansson@arm.com itLines(it_lines), 718856Sandreas.hansson@arm.com irqGroup(it_lines), 728922Swilliam.wang@arm.com irqEnabled(it_lines), 7312084Sspwilson2@wisc.edu irqPending(it_lines), 7412084Sspwilson2@wisc.edu irqActive(it_lines), 758856Sandreas.hansson@arm.com irqPriority(it_lines), 768856Sandreas.hansson@arm.com irqConfig(it_lines), 774475SN/A irqGrpmod(it_lines), 7811053Sandreas.hansson@arm.com irqNsacr(it_lines), 795034SN/A irqAffinityRouting(it_lines), 8012724Snikos.nikoleris@arm.com gicdPidr0(0x92), 8112724Snikos.nikoleris@arm.com gicdPidr1(0xb4), 8211377Sandreas.hansson@arm.com gicdPidr2(0x3b), 8311377Sandreas.hansson@arm.com gicdPidr3(0), 8412724Snikos.nikoleris@arm.com gicdPidr4(0x44) 8512724Snikos.nikoleris@arm.com{ 8613352Snikos.nikoleris@arm.com panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!"); 8712724Snikos.nikoleris@arm.com} 8812724Snikos.nikoleris@arm.com 8912724Snikos.nikoleris@arm.comvoid 9012724Snikos.nikoleris@arm.comGicv3Distributor::init() 9112724Snikos.nikoleris@arm.com{ 9211053Sandreas.hansson@arm.com} 9311722Ssophiane.senni@gmail.com 9411722Ssophiane.senni@gmail.comvoid 9511722Ssophiane.senni@gmail.comGicv3Distributor::initState() 9611722Ssophiane.senni@gmail.com{ 979263Smrinmoy.ghosh@arm.com reset(); 9813418Sodanrc@yahoo.com.br} 995034SN/A 10011331Sandreas.hansson@arm.comvoid 10112724Snikos.nikoleris@arm.comGicv3Distributor::reset() 10210884Sandreas.hansson@arm.com{ 1034626SN/A std::fill(irqGroup.begin(), irqGroup.end(), 0); 10410360Sandreas.hansson@arm.com // Imp. defined reset value 10511484Snikos.nikoleris@arm.com std::fill(irqEnabled.begin(), irqEnabled.end(), false); 1065034SN/A std::fill(irqPending.begin(), irqPending.end(), false); 1078883SAli.Saidi@ARM.com std::fill(irqActive.begin(), irqActive.end(), false); 1088833Sdam.sunwoo@arm.com // Imp. defined reset value 1094458SN/A std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA); 11011377Sandreas.hansson@arm.com std::fill(irqConfig.begin(), irqConfig.end(), 11111377Sandreas.hansson@arm.com Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value 11211377Sandreas.hansson@arm.com std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0); 11311377Sandreas.hansson@arm.com std::fill(irqNsacr.begin(), irqNsacr.end(), 0); 11411377Sandreas.hansson@arm.com /* 11511377Sandreas.hansson@arm.com * For our implementation affinity routing is always enabled, 11611331Sandreas.hansson@arm.com * no GICv2 legacy 11711331Sandreas.hansson@arm.com */ 11812724Snikos.nikoleris@arm.com ARE = true; 11912843Srmk35@cl.cam.ac.uk 12012724Snikos.nikoleris@arm.com if (gic->getSystem()->haveSecurity()) { 12113419Sodanrc@yahoo.com.br DS = false; 12212724Snikos.nikoleris@arm.com } else { 12312724Snikos.nikoleris@arm.com DS = true; 12412724Snikos.nikoleris@arm.com } 12512724Snikos.nikoleris@arm.com 12612724Snikos.nikoleris@arm.com EnableGrp0 = 0; 12712724Snikos.nikoleris@arm.com EnableGrp1NS = 0; 12812724Snikos.nikoleris@arm.com EnableGrp1S = 0; 1292810SN/A} 1302810SN/A 1313013SN/Auint64_t 1328856Sandreas.hansson@arm.comGicv3Distributor::read(Addr addr, size_t size, bool is_secure_access) 1332810SN/A{ 1343013SN/A if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 13510714Sandreas.hansson@arm.com uint64_t val = 0x0; 1362810SN/A 1379614Srene.dejong@arm.com if (!DS && !is_secure_access) { 1389614Srene.dejong@arm.com // RAZ/WI for non-secure accesses 1399614Srene.dejong@arm.com return 0; 14010345SCurtis.Dunham@arm.com } 14110714Sandreas.hansson@arm.com 14210345SCurtis.Dunham@arm.com int first_intid = (addr - GICD_IGROUPR.start()) * 8; 1439614Srene.dejong@arm.com 1442810SN/A if (isNotSPI(first_intid)) { 1452810SN/A return 0; 1462810SN/A } 1478856Sandreas.hansson@arm.com 1482810SN/A for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1493013SN/A i++, int_id++) { 15010714Sandreas.hansson@arm.com val |= irqGroup[int_id] << i; 1513013SN/A } 1528856Sandreas.hansson@arm.com 15310714Sandreas.hansson@arm.com return val; 1548922Swilliam.wang@arm.com } else if (GICD_ISENABLER.contains(addr)) { 1552897SN/A // Interrupt Set-Enable Registers 1562810SN/A uint64_t val = 0x0; 1572810SN/A int first_intid = (addr - GICD_ISENABLER.start()) * 8; 15810344Sandreas.hansson@arm.com 15910344Sandreas.hansson@arm.com if (isNotSPI(first_intid)) { 16010344Sandreas.hansson@arm.com return 0; 16110714Sandreas.hansson@arm.com } 16210344Sandreas.hansson@arm.com 16310344Sandreas.hansson@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 16410344Sandreas.hansson@arm.com i++, int_id++) { 16510713Sandreas.hansson@arm.com 16610344Sandreas.hansson@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 1672844SN/A { 16812730Sodanrc@yahoo.com.br continue; 16912730Sodanrc@yahoo.com.br } 17012730Sodanrc@yahoo.com.br 17112730Sodanrc@yahoo.com.br val |= irqEnabled[int_id] << i; 17212730Sodanrc@yahoo.com.br } 17312730Sodanrc@yahoo.com.br 17412730Sodanrc@yahoo.com.br return val; 17512730Sodanrc@yahoo.com.br } else if (GICD_ICENABLER.contains(addr)) { 17612730Sodanrc@yahoo.com.br // Interrupt Clear-Enable Registers 17712730Sodanrc@yahoo.com.br uint64_t val = 0x0; 1782810SN/A int first_intid = (addr - GICD_ICENABLER.start()) * 8; 1792858SN/A 1802858SN/A if (isNotSPI(first_intid)) { 18112724Snikos.nikoleris@arm.com return 0; 1828922Swilliam.wang@arm.com } 18312724Snikos.nikoleris@arm.com 18412724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 1852858SN/A i++, int_id++) { 1862858SN/A 1879294Sandreas.hansson@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 1889294Sandreas.hansson@arm.com { 1898922Swilliam.wang@arm.com continue; 1908922Swilliam.wang@arm.com } 19112724Snikos.nikoleris@arm.com 1928922Swilliam.wang@arm.com val |= (irqEnabled[int_id] << i); 1938922Swilliam.wang@arm.com } 1948922Swilliam.wang@arm.com 1958922Swilliam.wang@arm.com return val; 1968922Swilliam.wang@arm.com } else if (GICD_ISPENDR.contains(addr)) { 1979294Sandreas.hansson@arm.com // Interrupt Set-Pending Registers 1989294Sandreas.hansson@arm.com uint64_t val = 0x0; 1998922Swilliam.wang@arm.com int first_intid = (addr - GICD_ISPENDR.start()) * 8; 2008922Swilliam.wang@arm.com 20112724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 2028922Swilliam.wang@arm.com return 0; 2038922Swilliam.wang@arm.com } 2048922Swilliam.wang@arm.com 2058922Swilliam.wang@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 2064628SN/A i++, int_id++) { 20710821Sandreas.hansson@arm.com 20810821Sandreas.hansson@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 20910821Sandreas.hansson@arm.com { 21010821Sandreas.hansson@arm.com if (irqNsacr[int_id] == 0) { 21110821Sandreas.hansson@arm.com // Group 0 or Secure Group 1 interrupts are RAZ/WI 21210821Sandreas.hansson@arm.com continue; 21310821Sandreas.hansson@arm.com } 21410821Sandreas.hansson@arm.com } 21510821Sandreas.hansson@arm.com 21610821Sandreas.hansson@arm.com val |= (irqPending[int_id] << i); 21710821Sandreas.hansson@arm.com } 2182858SN/A 21912724Snikos.nikoleris@arm.com return val; 22012724Snikos.nikoleris@arm.com } else if (GICD_ICPENDR.contains(addr)) { 22112724Snikos.nikoleris@arm.com // Interrupt Clear-Pending Registers 22212724Snikos.nikoleris@arm.com uint64_t val = 0x0; 22312724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ICPENDR.start()) * 8; 22412724Snikos.nikoleris@arm.com 22512724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 22612724Snikos.nikoleris@arm.com return 0; 22712724Snikos.nikoleris@arm.com } 22812724Snikos.nikoleris@arm.com 22913418Sodanrc@yahoo.com.br for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 23013418Sodanrc@yahoo.com.br i++, int_id++) { 23112724Snikos.nikoleris@arm.com 23212724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 23312724Snikos.nikoleris@arm.com { 23412724Snikos.nikoleris@arm.com if (irqNsacr[int_id] < 2) { 23512724Snikos.nikoleris@arm.com // Group 0 or Secure Group 1 interrupts are RAZ/WI 23612724Snikos.nikoleris@arm.com continue; 23712724Snikos.nikoleris@arm.com } 23812724Snikos.nikoleris@arm.com } 23912724Snikos.nikoleris@arm.com 24012724Snikos.nikoleris@arm.com val |= (irqPending[int_id] << i); 24112724Snikos.nikoleris@arm.com } 24212724Snikos.nikoleris@arm.com 24312724Snikos.nikoleris@arm.com return val; 24412724Snikos.nikoleris@arm.com } else if (GICD_ISACTIVER.contains(addr)) { 24512724Snikos.nikoleris@arm.com // Interrupt Set-Active Registers 24612724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 24712724Snikos.nikoleris@arm.com 24813352Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 24913352Snikos.nikoleris@arm.com return 0; 25013352Snikos.nikoleris@arm.com } 25113352Snikos.nikoleris@arm.com 25213352Snikos.nikoleris@arm.com uint64_t val = 0x0; 25313352Snikos.nikoleris@arm.com 25412724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 25512724Snikos.nikoleris@arm.com i++, int_id++) { 25612724Snikos.nikoleris@arm.com 25712724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 25812724Snikos.nikoleris@arm.com { 25912724Snikos.nikoleris@arm.com // Group 0 or Secure Group 1 interrupts are RAZ/WI 26012724Snikos.nikoleris@arm.com if (irqNsacr[int_id] < 2) { 26112724Snikos.nikoleris@arm.com continue; 26212724Snikos.nikoleris@arm.com } 26312724Snikos.nikoleris@arm.com } 26412724Snikos.nikoleris@arm.com 26512724Snikos.nikoleris@arm.com val |= (irqActive[int_id] << i); 26612724Snikos.nikoleris@arm.com } 26712724Snikos.nikoleris@arm.com 26812724Snikos.nikoleris@arm.com return val; 26912724Snikos.nikoleris@arm.com } else if (GICD_ICACTIVER.contains(addr)) { 27012724Snikos.nikoleris@arm.com // Interrupt Clear-Active Registers 27112724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 27212724Snikos.nikoleris@arm.com 27312724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 27412724Snikos.nikoleris@arm.com return 0; 27512724Snikos.nikoleris@arm.com } 27612724Snikos.nikoleris@arm.com 27712724Snikos.nikoleris@arm.com uint64_t val = 0x0; 27812724Snikos.nikoleris@arm.com 27912724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 28012724Snikos.nikoleris@arm.com i++, int_id++) { 28112724Snikos.nikoleris@arm.com 28212724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 28312724Snikos.nikoleris@arm.com { 28412724Snikos.nikoleris@arm.com if (irqNsacr[int_id] < 2) { 28512724Snikos.nikoleris@arm.com continue; 28612724Snikos.nikoleris@arm.com } 28712724Snikos.nikoleris@arm.com } 28812724Snikos.nikoleris@arm.com 28912724Snikos.nikoleris@arm.com val |= (irqActive[int_id] << i); 29012724Snikos.nikoleris@arm.com } 29112724Snikos.nikoleris@arm.com 29212724Snikos.nikoleris@arm.com return val; 29312724Snikos.nikoleris@arm.com } else if (GICD_IPRIORITYR.contains(addr)) { 29412724Snikos.nikoleris@arm.com // Interrupt Priority Registers 29512724Snikos.nikoleris@arm.com uint64_t val = 0x0; 29612724Snikos.nikoleris@arm.com int first_intid = addr - GICD_IPRIORITYR.start(); 29712724Snikos.nikoleris@arm.com 29812724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 29912724Snikos.nikoleris@arm.com return 0; 30012724Snikos.nikoleris@arm.com } 30112724Snikos.nikoleris@arm.com 30212724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 30312724Snikos.nikoleris@arm.com i++, int_id++) { 30412724Snikos.nikoleris@arm.com 30512724Snikos.nikoleris@arm.com uint8_t prio = irqPriority[int_id]; 30612724Snikos.nikoleris@arm.com 30712724Snikos.nikoleris@arm.com if (!DS && !is_secure_access) { 30812724Snikos.nikoleris@arm.com if (getIntGroup(int_id) != Gicv3::G1NS) { 30912724Snikos.nikoleris@arm.com // RAZ/WI for non-secure accesses for secure interrupts 31012724Snikos.nikoleris@arm.com continue; 31112724Snikos.nikoleris@arm.com } else { 31212724Snikos.nikoleris@arm.com // NS view 31312724Snikos.nikoleris@arm.com prio = (prio << 1) & 0xff; 31412724Snikos.nikoleris@arm.com } 31512724Snikos.nikoleris@arm.com } 31612724Snikos.nikoleris@arm.com 31712724Snikos.nikoleris@arm.com val |= prio << (i * 8); 31812724Snikos.nikoleris@arm.com } 31912724Snikos.nikoleris@arm.com 32012724Snikos.nikoleris@arm.com return val; 32112724Snikos.nikoleris@arm.com } else if (GICD_ITARGETSR.contains(addr)) { 32212724Snikos.nikoleris@arm.com // Interrupt Processor Targets Registers 32312724Snikos.nikoleris@arm.com // ARE always on, RAZ/WI 32412724Snikos.nikoleris@arm.com warn("Gicv3Distributor::read(): " 32512724Snikos.nikoleris@arm.com "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 32612724Snikos.nikoleris@arm.com return 0; 32712724Snikos.nikoleris@arm.com } else if (GICD_ICFGR.contains(addr)) { 32812724Snikos.nikoleris@arm.com // Interrupt Configuration Registers 32912724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ICFGR.start()) * 4; 33012724Snikos.nikoleris@arm.com 33112724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 33212724Snikos.nikoleris@arm.com return 0; 33312724Snikos.nikoleris@arm.com } 33412724Snikos.nikoleris@arm.com 33512724Snikos.nikoleris@arm.com uint64_t val = 0x0; 33612724Snikos.nikoleris@arm.com 33712724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 33812724Snikos.nikoleris@arm.com i = i + 2, int_id++) { 33912724Snikos.nikoleris@arm.com 34012724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 34112724Snikos.nikoleris@arm.com { 34212724Snikos.nikoleris@arm.com continue; 34312724Snikos.nikoleris@arm.com } 34412724Snikos.nikoleris@arm.com 34512724Snikos.nikoleris@arm.com if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) { 34613418Sodanrc@yahoo.com.br val |= (0x2 << i); 34712724Snikos.nikoleris@arm.com } 34812724Snikos.nikoleris@arm.com } 34912724Snikos.nikoleris@arm.com 35012724Snikos.nikoleris@arm.com return val; 35112724Snikos.nikoleris@arm.com } else if (GICD_IGRPMODR.contains(addr)) { 35213418Sodanrc@yahoo.com.br // Interrupt Group Modifier Registers 35312724Snikos.nikoleris@arm.com if (DS) { 35412724Snikos.nikoleris@arm.com // RAZ/WI if security disabled 35512724Snikos.nikoleris@arm.com return 0; 35612820Srmk35@cl.cam.ac.uk } else { 35712724Snikos.nikoleris@arm.com if (!is_secure_access) { 35812724Snikos.nikoleris@arm.com // RAZ/WI for non-secure accesses 35912724Snikos.nikoleris@arm.com return 0; 36012724Snikos.nikoleris@arm.com } else { 36112724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 36213418Sodanrc@yahoo.com.br 36312724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 36412724Snikos.nikoleris@arm.com return 0; 36512724Snikos.nikoleris@arm.com } 36612724Snikos.nikoleris@arm.com 36712724Snikos.nikoleris@arm.com uint64_t val = 0x0; 36812724Snikos.nikoleris@arm.com 36912724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; 37013416Sjavier.bueno@metempsy.com i < 8 * size && int_id < itLines; i++, int_id++) { 37113416Sjavier.bueno@metempsy.com val |= irqGrpmod[int_id] << i; 37213416Sjavier.bueno@metempsy.com } 37312724Snikos.nikoleris@arm.com 37413416Sjavier.bueno@metempsy.com return val; 37513416Sjavier.bueno@metempsy.com } 37612724Snikos.nikoleris@arm.com } 37712724Snikos.nikoleris@arm.com } else if (GICD_NSACR.contains(addr)) { 37812724Snikos.nikoleris@arm.com // Non-secure Access Control Registers 37912724Snikos.nikoleris@arm.com // 2 bits per interrupt 38012724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_NSACR.start()) * 4; 38112724Snikos.nikoleris@arm.com 38213416Sjavier.bueno@metempsy.com if (isNotSPI(first_intid)) { 38312724Snikos.nikoleris@arm.com return 0; 38412724Snikos.nikoleris@arm.com } 38513416Sjavier.bueno@metempsy.com 38613416Sjavier.bueno@metempsy.com if (DS || (!DS && !is_secure_access)) { 38713416Sjavier.bueno@metempsy.com return 0; 38813416Sjavier.bueno@metempsy.com } 38913416Sjavier.bueno@metempsy.com 39013416Sjavier.bueno@metempsy.com uint64_t val = 0x0; 39112724Snikos.nikoleris@arm.com 39212724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; 39312724Snikos.nikoleris@arm.com i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 39412724Snikos.nikoleris@arm.com val |= irqNsacr[int_id] << i; 39512724Snikos.nikoleris@arm.com } 39612724Snikos.nikoleris@arm.com 39712724Snikos.nikoleris@arm.com return val; 39812724Snikos.nikoleris@arm.com } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers 39912724Snikos.nikoleris@arm.com // ARE always on, RAZ/WI 40012724Snikos.nikoleris@arm.com warn("Gicv3Distributor::read(): " 40112724Snikos.nikoleris@arm.com "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n"); 40212724Snikos.nikoleris@arm.com return 0x0; 40312724Snikos.nikoleris@arm.com } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers 40412724Snikos.nikoleris@arm.com // ARE always on, RAZ/WI 40512724Snikos.nikoleris@arm.com warn("Gicv3Distributor::read(): " 40612724Snikos.nikoleris@arm.com "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n"); 40712724Snikos.nikoleris@arm.com return 0x0; 40812724Snikos.nikoleris@arm.com } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 40912724Snikos.nikoleris@arm.com // 64 bit registers. 2 or 1 access. 41012724Snikos.nikoleris@arm.com int int_id = (addr - GICD_IROUTER.start()) / 8; 41112724Snikos.nikoleris@arm.com 41212724Snikos.nikoleris@arm.com if (isNotSPI(int_id)) { 41312724Snikos.nikoleris@arm.com return 0; 41412724Snikos.nikoleris@arm.com } 41512724Snikos.nikoleris@arm.com 41612724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 41712724Snikos.nikoleris@arm.com { 41812724Snikos.nikoleris@arm.com if (irqNsacr[int_id] < 3) { 41912724Snikos.nikoleris@arm.com return 0; 42012724Snikos.nikoleris@arm.com } 42112724Snikos.nikoleris@arm.com } 42212724Snikos.nikoleris@arm.com 42312724Snikos.nikoleris@arm.com if (size == 4) { 42412724Snikos.nikoleris@arm.com if (addr & 7) { // high half of 64 bit register 42512724Snikos.nikoleris@arm.com return irqAffinityRouting[int_id] >> 32; 42612724Snikos.nikoleris@arm.com } else { // high low of 64 bit register 42712724Snikos.nikoleris@arm.com return irqAffinityRouting[int_id] & 0xFFFFFFFF; 42812724Snikos.nikoleris@arm.com } 42912724Snikos.nikoleris@arm.com } else { 43012724Snikos.nikoleris@arm.com return irqAffinityRouting[int_id]; 43112724Snikos.nikoleris@arm.com } 43212724Snikos.nikoleris@arm.com } 43312724Snikos.nikoleris@arm.com 43412724Snikos.nikoleris@arm.com switch (addr) { 43512724Snikos.nikoleris@arm.com case GICD_CTLR: // Control Register 43612724Snikos.nikoleris@arm.com if (!DS) { 43712724Snikos.nikoleris@arm.com if (is_secure_access) { 43812724Snikos.nikoleris@arm.com // E1NWF [7] RAZ/WI 43912724Snikos.nikoleris@arm.com // DS [6] - Disable Security 44012724Snikos.nikoleris@arm.com // ARE_NS [5] RAO/WI 44112724Snikos.nikoleris@arm.com // ARE_S [4] RAO/WI 44212724Snikos.nikoleris@arm.com // EnableGrp1S [2] 44312724Snikos.nikoleris@arm.com // EnableGrp1NS [1] 44412724Snikos.nikoleris@arm.com // EnableGrp0 [0] 44512724Snikos.nikoleris@arm.com return (EnableGrp0 << 0) | 44612724Snikos.nikoleris@arm.com (EnableGrp1NS << 1) | 44712724Snikos.nikoleris@arm.com (EnableGrp1S << 2) | 44812724Snikos.nikoleris@arm.com (1 << 4) | 44912724Snikos.nikoleris@arm.com (1 << 5) | 45012724Snikos.nikoleris@arm.com (DS << 6); 45112724Snikos.nikoleris@arm.com } else { 45212724Snikos.nikoleris@arm.com // ARE_NS [4] RAO/WI; 45312724Snikos.nikoleris@arm.com // EnableGrp1A [1] is a read-write alias of the Secure 45412724Snikos.nikoleris@arm.com // GICD_CTLR.EnableGrp1NS 45512724Snikos.nikoleris@arm.com // EnableGrp1 [0] RES0 45612724Snikos.nikoleris@arm.com return (1 << 4) | (EnableGrp1NS << 1); 45712724Snikos.nikoleris@arm.com } 45812724Snikos.nikoleris@arm.com } else { 45912724Snikos.nikoleris@arm.com return (DS << 6) | (ARE << 4) | 46012724Snikos.nikoleris@arm.com (EnableGrp1NS << 1) | (EnableGrp0 << 0); 46112724Snikos.nikoleris@arm.com } 46212724Snikos.nikoleris@arm.com 46313350Snikos.nikoleris@arm.com case GICD_TYPER: // Interrupt Controller Type Register 46413350Snikos.nikoleris@arm.com /* 46513350Snikos.nikoleris@arm.com * RSS [26] == 1 46613350Snikos.nikoleris@arm.com * (The implementation does supports targeted SGIs with affinity 46713350Snikos.nikoleris@arm.com * level 0 values of 0 - 255) 46813350Snikos.nikoleris@arm.com * No1N [25] == 1 46912724Snikos.nikoleris@arm.com * (1 of N SPI interrupts are not supported) 47012724Snikos.nikoleris@arm.com * A3V [24] == 1 47112724Snikos.nikoleris@arm.com * (Supports nonzero values of Affinity level 3) 47212724Snikos.nikoleris@arm.com * IDbits [23:19] == 0xf 47312724Snikos.nikoleris@arm.com * (The number of interrupt identifier bits supported, minus one) 47412724Snikos.nikoleris@arm.com * DVIS [18] == 0 47512724Snikos.nikoleris@arm.com * (The implementation does not support Direct Virtual LPI 47613352Snikos.nikoleris@arm.com * injection) 47713352Snikos.nikoleris@arm.com * LPIS [17] == 1 47813352Snikos.nikoleris@arm.com * (The implementation does not support LPIs) 47912724Snikos.nikoleris@arm.com * MBIS [16] == 0 48012724Snikos.nikoleris@arm.com * (The implementation does not support message-based interrupts 48112724Snikos.nikoleris@arm.com * by writing to Distributor registers) 48212724Snikos.nikoleris@arm.com * SecurityExtn [10] == X 48312724Snikos.nikoleris@arm.com * (The GIC implementation supports two Security states) 48412724Snikos.nikoleris@arm.com * CPUNumber [7:5] == 0 48512724Snikos.nikoleris@arm.com * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy]) 48612794Snikos.nikoleris@arm.com * ITLinesNumber [4:0] == N 48712794Snikos.nikoleris@arm.com * (MaxSPIIntId = 32 (N + 1) - 1) 48812794Snikos.nikoleris@arm.com */ 48912794Snikos.nikoleris@arm.com { 49012794Snikos.nikoleris@arm.com int max_spi_int_id = itLines - 1; 49112794Snikos.nikoleris@arm.com int it_lines_number = ceil((max_spi_int_id + 1) / 32.0) - 1; 49212724Snikos.nikoleris@arm.com return (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) | 49312724Snikos.nikoleris@arm.com (1 << 17) | (gic->getSystem()->haveSecurity() << 10) | 49412724Snikos.nikoleris@arm.com (it_lines_number << 0); 49512724Snikos.nikoleris@arm.com } 49612724Snikos.nikoleris@arm.com 49712724Snikos.nikoleris@arm.com case GICD_IIDR: // Implementer Identification Register 49812724Snikos.nikoleris@arm.com //return 0x43b; // ARM JEP106 code (r0p0 GIC-500) 49912724Snikos.nikoleris@arm.com return 0; 50012724Snikos.nikoleris@arm.com 50113478Sodanrc@yahoo.com.br case GICD_STATUSR: // Error Reporting Status Register 50212724Snikos.nikoleris@arm.com // Optional register, RAZ/WI 50312724Snikos.nikoleris@arm.com return 0x0; 50412724Snikos.nikoleris@arm.com 50512724Snikos.nikoleris@arm.com case GICD_PIDR0: // Peripheral ID0 Register 50612724Snikos.nikoleris@arm.com return gicdPidr0; 50712724Snikos.nikoleris@arm.com 50812724Snikos.nikoleris@arm.com case GICD_PIDR1: // Peripheral ID1 Register 50912724Snikos.nikoleris@arm.com return gicdPidr1; 51012724Snikos.nikoleris@arm.com 51112724Snikos.nikoleris@arm.com case GICD_PIDR2: // Peripheral ID2 Register 51212724Snikos.nikoleris@arm.com return gicdPidr2; 51312724Snikos.nikoleris@arm.com 51412724Snikos.nikoleris@arm.com case GICD_PIDR3: // Peripheral ID3 Register 51512724Snikos.nikoleris@arm.com return gicdPidr3; 51612724Snikos.nikoleris@arm.com 51712724Snikos.nikoleris@arm.com case GICD_PIDR4: // Peripheral ID4 Register 51812724Snikos.nikoleris@arm.com return gicdPidr4; 51912724Snikos.nikoleris@arm.com 52012724Snikos.nikoleris@arm.com case GICD_PIDR5: // Peripheral ID5 Register 52112724Snikos.nikoleris@arm.com case GICD_PIDR6: // Peripheral ID6 Register 52212724Snikos.nikoleris@arm.com case GICD_PIDR7: // Peripheral ID7 Register 52312724Snikos.nikoleris@arm.com return 0; // RES0 52412724Snikos.nikoleris@arm.com 52512724Snikos.nikoleris@arm.com default: 52612724Snikos.nikoleris@arm.com panic("Gicv3Distributor::read(): invalid offset %#x\n", addr); 52712724Snikos.nikoleris@arm.com break; 52812724Snikos.nikoleris@arm.com } 52912724Snikos.nikoleris@arm.com} 53012724Snikos.nikoleris@arm.com 53112724Snikos.nikoleris@arm.comvoid 53212724Snikos.nikoleris@arm.comGicv3Distributor::write(Addr addr, uint64_t data, size_t size, 53312724Snikos.nikoleris@arm.com bool is_secure_access) 53412724Snikos.nikoleris@arm.com{ 53512724Snikos.nikoleris@arm.com if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers 53612724Snikos.nikoleris@arm.com if (!DS && !is_secure_access) { 53712724Snikos.nikoleris@arm.com // RAZ/WI for non-secure accesses 53812724Snikos.nikoleris@arm.com return; 53912724Snikos.nikoleris@arm.com } 54012724Snikos.nikoleris@arm.com 54112724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_IGROUPR.start()) * 8; 54212724Snikos.nikoleris@arm.com 54312724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 54412724Snikos.nikoleris@arm.com return; 54512724Snikos.nikoleris@arm.com } 54612724Snikos.nikoleris@arm.com 54712724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 54812724Snikos.nikoleris@arm.com i++, int_id++) { 54912724Snikos.nikoleris@arm.com irqGroup[int_id] = data & (1 << i) ? 1 : 0; 55012724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n", 55112724Snikos.nikoleris@arm.com int_id, irqGroup[int_id]); 55213412Snikos.nikoleris@arm.com } 55313412Snikos.nikoleris@arm.com 55413412Snikos.nikoleris@arm.com return; 55513412Snikos.nikoleris@arm.com } else if (GICD_ISENABLER.contains(addr)) { 55612724Snikos.nikoleris@arm.com // Interrupt Set-Enable Registers 55712724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ISENABLER.start()) * 8; 55812724Snikos.nikoleris@arm.com 55912724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 56012724Snikos.nikoleris@arm.com return; 56112724Snikos.nikoleris@arm.com } 56212724Snikos.nikoleris@arm.com 56312724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 56412724Snikos.nikoleris@arm.com i++, int_id++) { 56512724Snikos.nikoleris@arm.com 56612724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 56712724Snikos.nikoleris@arm.com { 56812724Snikos.nikoleris@arm.com continue; 56912724Snikos.nikoleris@arm.com } 57012724Snikos.nikoleris@arm.com 57112724Snikos.nikoleris@arm.com bool enable = data & (1 << i) ? 1 : 0; 57212724Snikos.nikoleris@arm.com 57312820Srmk35@cl.cam.ac.uk if (enable) { 57412724Snikos.nikoleris@arm.com if (!irqEnabled[int_id]) { 57512724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): " 57612724Snikos.nikoleris@arm.com "int_id %d enabled\n", int_id); 57712724Snikos.nikoleris@arm.com } 57812724Snikos.nikoleris@arm.com 57912724Snikos.nikoleris@arm.com irqEnabled[int_id] = true; 58012724Snikos.nikoleris@arm.com } 58112724Snikos.nikoleris@arm.com } 58212724Snikos.nikoleris@arm.com 58312724Snikos.nikoleris@arm.com return; 58412724Snikos.nikoleris@arm.com } else if (GICD_ICENABLER.contains(addr)) { 58512724Snikos.nikoleris@arm.com // Interrupt Clear-Enable Registers 58612724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ICENABLER.start()) * 8; 58712724Snikos.nikoleris@arm.com 58812724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 58912724Snikos.nikoleris@arm.com return; 59012724Snikos.nikoleris@arm.com } 59112724Snikos.nikoleris@arm.com 59212724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 59312724Snikos.nikoleris@arm.com i++, int_id++) { 59412724Snikos.nikoleris@arm.com 59512724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 59612724Snikos.nikoleris@arm.com { 59712724Snikos.nikoleris@arm.com continue; 59812724Snikos.nikoleris@arm.com } 59912724Snikos.nikoleris@arm.com 60012724Snikos.nikoleris@arm.com bool disable = data & (1 << i) ? 1 : 0; 60112724Snikos.nikoleris@arm.com 60212724Snikos.nikoleris@arm.com if (disable) { 60312724Snikos.nikoleris@arm.com if (irqEnabled[int_id]) { 60412724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): " 60512724Snikos.nikoleris@arm.com "int_id %d disabled\n", int_id); 60612724Snikos.nikoleris@arm.com } 60712724Snikos.nikoleris@arm.com 60812724Snikos.nikoleris@arm.com irqEnabled[int_id] = false; 60912724Snikos.nikoleris@arm.com } 61012724Snikos.nikoleris@arm.com } 61112724Snikos.nikoleris@arm.com 61212724Snikos.nikoleris@arm.com return; 61312724Snikos.nikoleris@arm.com } else if (GICD_ISPENDR.contains(addr)) { 61412724Snikos.nikoleris@arm.com // Interrupt Set-Pending Registers 61512724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ISPENDR.start()) * 8; 61612724Snikos.nikoleris@arm.com 61712724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 61812724Snikos.nikoleris@arm.com return; 61912724Snikos.nikoleris@arm.com } 62012724Snikos.nikoleris@arm.com 62112724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 62212724Snikos.nikoleris@arm.com i++, int_id++) { 62312724Snikos.nikoleris@arm.com 62412724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 62512724Snikos.nikoleris@arm.com { 62612724Snikos.nikoleris@arm.com if (irqNsacr[int_id] == 0) { 62712724Snikos.nikoleris@arm.com // Group 0 or Secure Group 1 interrupts are RAZ/WI 62812724Snikos.nikoleris@arm.com continue; 62912724Snikos.nikoleris@arm.com } 63012724Snikos.nikoleris@arm.com } 63112724Snikos.nikoleris@arm.com 63212724Snikos.nikoleris@arm.com bool pending = data & (1 << i) ? 1 : 0; 63312724Snikos.nikoleris@arm.com 63412724Snikos.nikoleris@arm.com if (pending) { 63512724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): " 63612724Snikos.nikoleris@arm.com "int_id %d (SPI) pending bit set\n", int_id); 63712724Snikos.nikoleris@arm.com irqPending[int_id] = true; 63812724Snikos.nikoleris@arm.com } 63912724Snikos.nikoleris@arm.com } 64012724Snikos.nikoleris@arm.com 64112724Snikos.nikoleris@arm.com update(); 64212724Snikos.nikoleris@arm.com return; 64312724Snikos.nikoleris@arm.com } else if (GICD_ICPENDR.contains(addr)) { 64412823Srmk35@cl.cam.ac.uk // Interrupt Clear-Pending Registers 64512823Srmk35@cl.cam.ac.uk int first_intid = (addr - GICD_ICPENDR.start()) * 8; 64612724Snikos.nikoleris@arm.com 64712724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 64812724Snikos.nikoleris@arm.com return; 64912724Snikos.nikoleris@arm.com } 65012724Snikos.nikoleris@arm.com 65112724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 65212724Snikos.nikoleris@arm.com i++, int_id++) { 65312724Snikos.nikoleris@arm.com 65412823Srmk35@cl.cam.ac.uk if (nsAccessToSecInt(int_id, is_secure_access)) 65512823Srmk35@cl.cam.ac.uk { 65612823Srmk35@cl.cam.ac.uk if (irqNsacr[int_id] < 2) { 65712823Srmk35@cl.cam.ac.uk // Group 0 or Secure Group 1 interrupts are RAZ/WI 65812724Snikos.nikoleris@arm.com continue; 65912724Snikos.nikoleris@arm.com } 66012724Snikos.nikoleris@arm.com } 66112724Snikos.nikoleris@arm.com 66212724Snikos.nikoleris@arm.com bool clear = data & (1 << i) ? 1 : 0; 66312724Snikos.nikoleris@arm.com 66412724Snikos.nikoleris@arm.com if (clear) { 66512724Snikos.nikoleris@arm.com irqPending[int_id] = false; 66612724Snikos.nikoleris@arm.com clearIrqCpuInterface(int_id); 66712724Snikos.nikoleris@arm.com } 66812724Snikos.nikoleris@arm.com } 66912724Snikos.nikoleris@arm.com 67012724Snikos.nikoleris@arm.com update(); 67112724Snikos.nikoleris@arm.com return; 67212724Snikos.nikoleris@arm.com } else if (GICD_ISACTIVER.contains(addr)) { 67312724Snikos.nikoleris@arm.com // Interrupt Set-Active Registers 67412724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ISACTIVER.start()) * 8; 67512724Snikos.nikoleris@arm.com 67612724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 67712724Snikos.nikoleris@arm.com return; 67812724Snikos.nikoleris@arm.com } 67912724Snikos.nikoleris@arm.com 68012724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 68112724Snikos.nikoleris@arm.com i++, int_id++) { 68212724Snikos.nikoleris@arm.com 68312724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 68412724Snikos.nikoleris@arm.com { 68512724Snikos.nikoleris@arm.com continue; 68612724Snikos.nikoleris@arm.com } 68712724Snikos.nikoleris@arm.com 68812724Snikos.nikoleris@arm.com bool active = data & (1 << i) ? 1 : 0; 68912724Snikos.nikoleris@arm.com 69012724Snikos.nikoleris@arm.com if (active) { 69112724Snikos.nikoleris@arm.com irqActive[int_id] = 1; 69212724Snikos.nikoleris@arm.com } 69312724Snikos.nikoleris@arm.com } 69412724Snikos.nikoleris@arm.com 69512724Snikos.nikoleris@arm.com return; 69612724Snikos.nikoleris@arm.com } else if (GICD_ICACTIVER.contains(addr)) { 69712724Snikos.nikoleris@arm.com // Interrupt Clear-Active Registers 69812724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ICACTIVER.start()) * 8; 69912724Snikos.nikoleris@arm.com 70012724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 70112724Snikos.nikoleris@arm.com return; 70212724Snikos.nikoleris@arm.com } 70312724Snikos.nikoleris@arm.com 70412724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 70512724Snikos.nikoleris@arm.com i++, int_id++) { 70612724Snikos.nikoleris@arm.com 70712724Snikos.nikoleris@arm.com if (nsAccessToSecInt(int_id, is_secure_access)) 70812724Snikos.nikoleris@arm.com { 70912724Snikos.nikoleris@arm.com continue; 71012724Snikos.nikoleris@arm.com } 71112724Snikos.nikoleris@arm.com 71212724Snikos.nikoleris@arm.com bool clear = data & (1 << i) ? 1 : 0; 71312724Snikos.nikoleris@arm.com 71412724Snikos.nikoleris@arm.com if (clear) { 71512724Snikos.nikoleris@arm.com if (irqActive[int_id]) { 71612724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): " 71712724Snikos.nikoleris@arm.com "int_id %d active cleared\n", int_id); 71812724Snikos.nikoleris@arm.com } 71912724Snikos.nikoleris@arm.com 72012724Snikos.nikoleris@arm.com irqActive[int_id] = false; 72112724Snikos.nikoleris@arm.com } 72212724Snikos.nikoleris@arm.com } 72312724Snikos.nikoleris@arm.com 72412724Snikos.nikoleris@arm.com return; 72512724Snikos.nikoleris@arm.com } else if (GICD_IPRIORITYR.contains(addr)) { 72612724Snikos.nikoleris@arm.com // Interrupt Priority Registers 72712724Snikos.nikoleris@arm.com int first_intid = addr - GICD_IPRIORITYR.start(); 72812724Snikos.nikoleris@arm.com 72912724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 73012724Snikos.nikoleris@arm.com return; 73112724Snikos.nikoleris@arm.com } 73212724Snikos.nikoleris@arm.com 73312724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < size && int_id < itLines; 73412724Snikos.nikoleris@arm.com i++, int_id++) { 73512724Snikos.nikoleris@arm.com uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8)); 73612724Snikos.nikoleris@arm.com 73712724Snikos.nikoleris@arm.com if (!DS && !is_secure_access) { 73812724Snikos.nikoleris@arm.com if (getIntGroup(int_id) != Gicv3::G1NS) { 73912724Snikos.nikoleris@arm.com // RAZ/WI for non-secure accesses to secure interrupts 74012724Snikos.nikoleris@arm.com continue; 74112724Snikos.nikoleris@arm.com } else { 74212724Snikos.nikoleris@arm.com prio = 0x80 | (prio >> 1); 74312724Snikos.nikoleris@arm.com } 74412724Snikos.nikoleris@arm.com } 74512724Snikos.nikoleris@arm.com 74612724Snikos.nikoleris@arm.com irqPriority[int_id] = prio; 74712724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n", 74812724Snikos.nikoleris@arm.com int_id, irqPriority[int_id]); 74912724Snikos.nikoleris@arm.com } 75012724Snikos.nikoleris@arm.com 75112724Snikos.nikoleris@arm.com return; 75212724Snikos.nikoleris@arm.com } else if (GICD_ITARGETSR.contains(addr)) { 75312724Snikos.nikoleris@arm.com // Interrupt Processor Targets Registers 75412724Snikos.nikoleris@arm.com // ARE always on, RAZ/WI 75512724Snikos.nikoleris@arm.com warn("Gicv3Distributor::write(): " 75612724Snikos.nikoleris@arm.com "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n"); 75712724Snikos.nikoleris@arm.com return; 75812724Snikos.nikoleris@arm.com } else if (GICD_ICFGR.contains(addr)) { 75912724Snikos.nikoleris@arm.com // Interrupt Configuration Registers 76012724Snikos.nikoleris@arm.com // for x = 0 to 15: 76112724Snikos.nikoleris@arm.com // GICD_ICFGR[2x] = RES0 76212724Snikos.nikoleris@arm.com // GICD_ICFGR[2x + 1] = 76312724Snikos.nikoleris@arm.com // 0 level-sensitive 76412724Snikos.nikoleris@arm.com // 1 edge-triggered 76512724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_ICFGR.start()) * 4; 76612724Snikos.nikoleris@arm.com 76712724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 76812724Snikos.nikoleris@arm.com return; 76912724Snikos.nikoleris@arm.com } 77012724Snikos.nikoleris@arm.com 77112724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines; 77212724Snikos.nikoleris@arm.com i = i + 2, int_id++) { 77312724Snikos.nikoleris@arm.com irqConfig[int_id] = data & (0x2 << i) ? 77412724Snikos.nikoleris@arm.com Gicv3::INT_EDGE_TRIGGERED : 77512724Snikos.nikoleris@arm.com Gicv3::INT_LEVEL_SENSITIVE; 77612724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n", 77712724Snikos.nikoleris@arm.com int_id, irqConfig[int_id]); 77812724Snikos.nikoleris@arm.com } 77912724Snikos.nikoleris@arm.com 78012724Snikos.nikoleris@arm.com return; 78112724Snikos.nikoleris@arm.com } else if (GICD_IGRPMODR.contains(addr)) { 78212724Snikos.nikoleris@arm.com // Interrupt Group Modifier Registers 78312724Snikos.nikoleris@arm.com if (DS) { 78412724Snikos.nikoleris@arm.com return; 78512724Snikos.nikoleris@arm.com } else { 78612724Snikos.nikoleris@arm.com if (!is_secure_access) { 78712724Snikos.nikoleris@arm.com // RAZ/WI for non-secure accesses 78812724Snikos.nikoleris@arm.com return; 78912724Snikos.nikoleris@arm.com } else { 79012724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_IGRPMODR.start()) * 8; 79112724Snikos.nikoleris@arm.com 79212724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 79312724Snikos.nikoleris@arm.com return; 79412724Snikos.nikoleris@arm.com } 79512724Snikos.nikoleris@arm.com 79612724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; 79712724Snikos.nikoleris@arm.com i < 8 * size && int_id < itLines; i++, int_id++) { 79812724Snikos.nikoleris@arm.com irqGrpmod[int_id] = bits(data, i); 79912724Snikos.nikoleris@arm.com } 80012724Snikos.nikoleris@arm.com 80112724Snikos.nikoleris@arm.com return ; 80212724Snikos.nikoleris@arm.com } 80312724Snikos.nikoleris@arm.com } 80412724Snikos.nikoleris@arm.com 80512724Snikos.nikoleris@arm.com } else if (GICD_NSACR.contains(addr)) { 80612724Snikos.nikoleris@arm.com // Non-secure Access Control Registers 80712724Snikos.nikoleris@arm.com // 2 bits per interrupt 80812724Snikos.nikoleris@arm.com int first_intid = (addr - GICD_NSACR.start()) * 4; 80912724Snikos.nikoleris@arm.com 81012724Snikos.nikoleris@arm.com if (isNotSPI(first_intid)) { 81112724Snikos.nikoleris@arm.com return; 81212724Snikos.nikoleris@arm.com } 81312724Snikos.nikoleris@arm.com 81412724Snikos.nikoleris@arm.com if (DS || (!DS && !is_secure_access)) { 81512724Snikos.nikoleris@arm.com return; 81612724Snikos.nikoleris@arm.com } 81712724Snikos.nikoleris@arm.com 81812724Snikos.nikoleris@arm.com for (int i = 0, int_id = first_intid; 81912724Snikos.nikoleris@arm.com i < 8 * size && int_id < itLines; i = i + 2, int_id++) { 82012724Snikos.nikoleris@arm.com irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3; 82112724Snikos.nikoleris@arm.com } 82212766Sqtt2@cornell.edu 82312766Sqtt2@cornell.edu return; 82412766Sqtt2@cornell.edu } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers 82512766Sqtt2@cornell.edu // 64 bit registers. 2 accesses. 82612766Sqtt2@cornell.edu int int_id = (addr - GICD_IROUTER.start()) / 8; 82713377Sodanrc@yahoo.com.br 82812766Sqtt2@cornell.edu if (isNotSPI(int_id)) { 82912766Sqtt2@cornell.edu return; 83012766Sqtt2@cornell.edu } 83112766Sqtt2@cornell.edu 83212766Sqtt2@cornell.edu if (nsAccessToSecInt(int_id, is_secure_access)) 83312766Sqtt2@cornell.edu { 83412766Sqtt2@cornell.edu if (irqNsacr[int_id] < 3) { 83512766Sqtt2@cornell.edu // Group 0 or Secure Group 1 interrupts are RAZ/WI 83612766Sqtt2@cornell.edu return; 83712724Snikos.nikoleris@arm.com } 83812724Snikos.nikoleris@arm.com } 83912724Snikos.nikoleris@arm.com 84012724Snikos.nikoleris@arm.com if (size == 4) { 84112724Snikos.nikoleris@arm.com if (addr & 7) { // high half of 64 bit register 84212724Snikos.nikoleris@arm.com irqAffinityRouting[int_id] = 84312724Snikos.nikoleris@arm.com (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32); 84412724Snikos.nikoleris@arm.com } else { // low half of 64 bit register 84512724Snikos.nikoleris@arm.com irqAffinityRouting[int_id] = 84612724Snikos.nikoleris@arm.com (irqAffinityRouting[int_id] & 0xffffffff00000000) | 84712724Snikos.nikoleris@arm.com (data & 0xffffffff); 84812724Snikos.nikoleris@arm.com } 84912724Snikos.nikoleris@arm.com } else { 85012724Snikos.nikoleris@arm.com irqAffinityRouting[int_id] = data; 85112724Snikos.nikoleris@arm.com } 85212724Snikos.nikoleris@arm.com 85312724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): " 85412724Snikos.nikoleris@arm.com "int_id %d GICD_IROUTER %#llx\n", 85512724Snikos.nikoleris@arm.com int_id, irqAffinityRouting[int_id]); 85612724Snikos.nikoleris@arm.com return; 85712724Snikos.nikoleris@arm.com } 85812724Snikos.nikoleris@arm.com 85912724Snikos.nikoleris@arm.com switch (addr) { 86012724Snikos.nikoleris@arm.com case GICD_CTLR: // Control Register 86112724Snikos.nikoleris@arm.com if (DS) { 86212724Snikos.nikoleris@arm.com /* 86312724Snikos.nikoleris@arm.com * E1NWF [7] 86412724Snikos.nikoleris@arm.com * 1 of N wakeup functionality not supported, RAZ/WI 86512724Snikos.nikoleris@arm.com * DS [6] - RAO/WI 86612724Snikos.nikoleris@arm.com * ARE [4] 86712724Snikos.nikoleris@arm.com * affinity routing always on, no GICv2 legacy, RAO/WI 86812724Snikos.nikoleris@arm.com * EnableGrp1 [1] 86912724Snikos.nikoleris@arm.com * EnableGrp0 [0] 87012724Snikos.nikoleris@arm.com */ 87112724Snikos.nikoleris@arm.com if ((data & (1 << 4)) == 0) { 87212794Snikos.nikoleris@arm.com warn("Gicv3Distributor::write(): " 87312794Snikos.nikoleris@arm.com "setting ARE to 0 is not supported!\n"); 87412724Snikos.nikoleris@arm.com } 87512724Snikos.nikoleris@arm.com 87612724Snikos.nikoleris@arm.com EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 87712724Snikos.nikoleris@arm.com EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 87812724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)" 87912724Snikos.nikoleris@arm.com "EnableGrp1NS %d EnableGrp0 %d\n", 88012724Snikos.nikoleris@arm.com EnableGrp1NS, EnableGrp0); 88112724Snikos.nikoleris@arm.com } else { 88212724Snikos.nikoleris@arm.com if (is_secure_access) { 88312724Snikos.nikoleris@arm.com /* 88412724Snikos.nikoleris@arm.com * E1NWF [7] 88512724Snikos.nikoleris@arm.com * 1 of N wakeup functionality not supported, RAZ/WI 88612724Snikos.nikoleris@arm.com * DS [6] 88713418Sodanrc@yahoo.com.br * ARE_NS [5] 88813418Sodanrc@yahoo.com.br * affinity routing always on, no GICv2 legacy, RAO/WI 88913418Sodanrc@yahoo.com.br * ARE_S [4] 89013418Sodanrc@yahoo.com.br * affinity routing always on, no GICv2 legacy, RAO/WI 89113418Sodanrc@yahoo.com.br * EnableGrp1S [2] 89213418Sodanrc@yahoo.com.br * EnableGrp1NS [1] 89313418Sodanrc@yahoo.com.br * EnableGrp0 [0] 89413418Sodanrc@yahoo.com.br */ 89513418Sodanrc@yahoo.com.br if ((data & (1 << 5)) == 0) { 89613418Sodanrc@yahoo.com.br warn("Gicv3Distributor::write(): " 89713418Sodanrc@yahoo.com.br "setting ARE_NS to 0 is not supported!\n"); 89813418Sodanrc@yahoo.com.br } 89913418Sodanrc@yahoo.com.br 90013418Sodanrc@yahoo.com.br if ((data & (1 << 4)) == 0) { 90113418Sodanrc@yahoo.com.br warn("Gicv3Distributor::write(): " 90213418Sodanrc@yahoo.com.br "setting ARE_S to 0 is not supported!\n"); 90313477Sodanrc@yahoo.com.br } 90413477Sodanrc@yahoo.com.br 90513477Sodanrc@yahoo.com.br DS = data & GICD_CTLR_DS; 90613477Sodanrc@yahoo.com.br EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S; 90713477Sodanrc@yahoo.com.br EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS; 90813418Sodanrc@yahoo.com.br EnableGrp0 = data & GICD_CTLR_ENABLEGRP0; 90913418Sodanrc@yahoo.com.br DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)" 91013418Sodanrc@yahoo.com.br "DS %d " 91113418Sodanrc@yahoo.com.br "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n", 91213418Sodanrc@yahoo.com.br DS, EnableGrp1S, EnableGrp1NS, EnableGrp0); 91312724Snikos.nikoleris@arm.com 91412724Snikos.nikoleris@arm.com if (data & GICD_CTLR_DS) { 91512724Snikos.nikoleris@arm.com EnableGrp1S = 0; 91612724Snikos.nikoleris@arm.com } 91712724Snikos.nikoleris@arm.com } else { 91812724Snikos.nikoleris@arm.com /* 91912724Snikos.nikoleris@arm.com * ARE_NS [4] RAO/WI; 92012724Snikos.nikoleris@arm.com * EnableGrp1A [1] is a read-write alias of the Secure 92112724Snikos.nikoleris@arm.com * GICD_CTLR.EnableGrp1NS 92212724Snikos.nikoleris@arm.com * EnableGrp1 [0] RES0 92312724Snikos.nikoleris@arm.com */ 92412724Snikos.nikoleris@arm.com if ((data & (1 << 4)) == 0) { 92513418Sodanrc@yahoo.com.br warn("Gicv3Distributor::write(): " 92613418Sodanrc@yahoo.com.br "setting ARE_NS to 0 is not supported!\n"); 92713418Sodanrc@yahoo.com.br } 92813418Sodanrc@yahoo.com.br 92913418Sodanrc@yahoo.com.br EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A; 93013418Sodanrc@yahoo.com.br DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)" 93112724Snikos.nikoleris@arm.com "EnableGrp1NS %d\n", EnableGrp1NS); 93212724Snikos.nikoleris@arm.com } 93312724Snikos.nikoleris@arm.com } 93412724Snikos.nikoleris@arm.com 93512724Snikos.nikoleris@arm.com update(); 93612724Snikos.nikoleris@arm.com 93712724Snikos.nikoleris@arm.com break; 93812724Snikos.nikoleris@arm.com 93912724Snikos.nikoleris@arm.com default: 94012724Snikos.nikoleris@arm.com panic("Gicv3Distributor::write(): invalid offset %#x\n", addr); 94112724Snikos.nikoleris@arm.com break; 94212724Snikos.nikoleris@arm.com } 94312724Snikos.nikoleris@arm.com} 94412724Snikos.nikoleris@arm.com 94512724Snikos.nikoleris@arm.comvoid 94612724Snikos.nikoleris@arm.comGicv3Distributor::sendInt(uint32_t int_id) 94712724Snikos.nikoleris@arm.com{ 94812724Snikos.nikoleris@arm.com panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 94912724Snikos.nikoleris@arm.com panic_if(int_id > itLines, "Invalid SPI!"); 95012724Snikos.nikoleris@arm.com irqPending[int_id] = true; 95112724Snikos.nikoleris@arm.com DPRINTF(GIC, "Gicv3Distributor::sendInt(): " 95212724Snikos.nikoleris@arm.com "int_id %d (SPI) pending bit set\n", int_id); 95312724Snikos.nikoleris@arm.com update(); 95412724Snikos.nikoleris@arm.com} 95512724Snikos.nikoleris@arm.com 95612724Snikos.nikoleris@arm.comvoid 95712724Snikos.nikoleris@arm.comGicv3Distributor::deassertSPI(uint32_t int_id) 95812724Snikos.nikoleris@arm.com{ 95912724Snikos.nikoleris@arm.com panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 96012724Snikos.nikoleris@arm.com panic_if(int_id > itLines, "Invalid SPI!"); 96112724Snikos.nikoleris@arm.com irqPending[int_id] = false; 96212724Snikos.nikoleris@arm.com clearIrqCpuInterface(int_id); 96312724Snikos.nikoleris@arm.com 96412724Snikos.nikoleris@arm.com update(); 96512724Snikos.nikoleris@arm.com} 96612724Snikos.nikoleris@arm.com 96712724Snikos.nikoleris@arm.comGicv3CPUInterface* 96812724Snikos.nikoleris@arm.comGicv3Distributor::route(uint32_t int_id) 96912724Snikos.nikoleris@arm.com{ 97012724Snikos.nikoleris@arm.com IROUTER affinity_routing = irqAffinityRouting[int_id]; 97112724Snikos.nikoleris@arm.com Gicv3Redistributor * target_redistributor = nullptr; 97212724Snikos.nikoleris@arm.com 97312724Snikos.nikoleris@arm.com const Gicv3::GroupId int_group = getIntGroup(int_id); 97412724Snikos.nikoleris@arm.com 97512724Snikos.nikoleris@arm.com if (affinity_routing.IRM) { 97612724Snikos.nikoleris@arm.com // Interrupts routed to any PE defined as a participating node 97712724Snikos.nikoleris@arm.com for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 97812724Snikos.nikoleris@arm.com Gicv3Redistributor * redistributor_i = 97912724Snikos.nikoleris@arm.com gic->getRedistributor(i); 98012724Snikos.nikoleris@arm.com 98112724Snikos.nikoleris@arm.com if (redistributor_i-> 98212724Snikos.nikoleris@arm.com canBeSelectedFor1toNInterrupt(int_group)) { 98312724Snikos.nikoleris@arm.com target_redistributor = redistributor_i; 98412724Snikos.nikoleris@arm.com break; 98512724Snikos.nikoleris@arm.com } 98612724Snikos.nikoleris@arm.com } 98712724Snikos.nikoleris@arm.com } else { 98812724Snikos.nikoleris@arm.com uint32_t affinity = (affinity_routing.Aff3 << 24) | 98912724Snikos.nikoleris@arm.com (affinity_routing.Aff2 << 16) | 99012724Snikos.nikoleris@arm.com (affinity_routing.Aff1 << 8) | 99112724Snikos.nikoleris@arm.com (affinity_routing.Aff0 << 0); 99212724Snikos.nikoleris@arm.com target_redistributor = 99312724Snikos.nikoleris@arm.com gic->getRedistributorByAffinity(affinity); 99412724Snikos.nikoleris@arm.com } 99512724Snikos.nikoleris@arm.com 99612724Snikos.nikoleris@arm.com if (!target_redistributor) { 99712724Snikos.nikoleris@arm.com // Interrrupts targeting not present cpus must remain pending 99812724Snikos.nikoleris@arm.com return nullptr; 99912724Snikos.nikoleris@arm.com } else { 100012724Snikos.nikoleris@arm.com return target_redistributor->getCPUInterface(); 100112754Sodanrc@yahoo.com.br } 100212724Snikos.nikoleris@arm.com} 100312724Snikos.nikoleris@arm.com 100412724Snikos.nikoleris@arm.comvoid 100512724Snikos.nikoleris@arm.comGicv3Distributor::clearIrqCpuInterface(uint32_t int_id) 100612724Snikos.nikoleris@arm.com{ 100712724Snikos.nikoleris@arm.com auto cpu_interface = route(int_id); 100813445Sodanrc@yahoo.com.br if (cpu_interface) 100912724Snikos.nikoleris@arm.com cpu_interface->hppi.prio = 0xff; 101012724Snikos.nikoleris@arm.com} 101112724Snikos.nikoleris@arm.com 101212724Snikos.nikoleris@arm.comvoid 101312724Snikos.nikoleris@arm.comGicv3Distributor::update() 101412724Snikos.nikoleris@arm.com{ 101512724Snikos.nikoleris@arm.com // Find the highest priority pending SPI 101612724Snikos.nikoleris@arm.com for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines; 101712724Snikos.nikoleris@arm.com int_id++) { 101812724Snikos.nikoleris@arm.com Gicv3::GroupId int_group = getIntGroup(int_id); 101912724Snikos.nikoleris@arm.com bool group_enabled = groupEnabled(int_group); 102012724Snikos.nikoleris@arm.com 102112724Snikos.nikoleris@arm.com if (irqPending[int_id] && irqEnabled[int_id] && 102212724Snikos.nikoleris@arm.com !irqActive[int_id] && group_enabled) { 102312724Snikos.nikoleris@arm.com 102412724Snikos.nikoleris@arm.com // Find the cpu interface where to route the interrupt 102512724Snikos.nikoleris@arm.com Gicv3CPUInterface *target_cpu_interface = route(int_id); 102612724Snikos.nikoleris@arm.com 102712724Snikos.nikoleris@arm.com // Invalid routing 102813477Sodanrc@yahoo.com.br if (!target_cpu_interface) continue; 102913477Sodanrc@yahoo.com.br 103012724Snikos.nikoleris@arm.com if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) || 103112724Snikos.nikoleris@arm.com (irqPriority[int_id] == target_cpu_interface->hppi.prio && 103212724Snikos.nikoleris@arm.com int_id < target_cpu_interface->hppi.intid)) { 103312724Snikos.nikoleris@arm.com 103412724Snikos.nikoleris@arm.com target_cpu_interface->hppi.intid = int_id; 103512724Snikos.nikoleris@arm.com target_cpu_interface->hppi.prio = irqPriority[int_id]; 103612724Snikos.nikoleris@arm.com target_cpu_interface->hppi.group = int_group; 103712724Snikos.nikoleris@arm.com } 103812724Snikos.nikoleris@arm.com } 103912724Snikos.nikoleris@arm.com } 104012724Snikos.nikoleris@arm.com 104112724Snikos.nikoleris@arm.com // Update all redistributors 104212724Snikos.nikoleris@arm.com for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 104312724Snikos.nikoleris@arm.com gic->getRedistributor(i)->update(); 104412724Snikos.nikoleris@arm.com } 104512724Snikos.nikoleris@arm.com} 104612724Snikos.nikoleris@arm.com 104712724Snikos.nikoleris@arm.comGicv3::IntStatus 104812724Snikos.nikoleris@arm.comGicv3Distributor::intStatus(uint32_t int_id) const 104912724Snikos.nikoleris@arm.com{ 105012724Snikos.nikoleris@arm.com panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 105112724Snikos.nikoleris@arm.com panic_if(int_id > itLines, "Invalid SPI!"); 105212724Snikos.nikoleris@arm.com 105312724Snikos.nikoleris@arm.com if (irqPending[int_id]) { 105412724Snikos.nikoleris@arm.com if (irqActive[int_id]) { 105512724Snikos.nikoleris@arm.com return Gicv3::INT_ACTIVE_PENDING; 105612724Snikos.nikoleris@arm.com } 105712724Snikos.nikoleris@arm.com 105812754Sodanrc@yahoo.com.br return Gicv3::INT_PENDING; 105912724Snikos.nikoleris@arm.com } else if (irqActive[int_id]) { 106012724Snikos.nikoleris@arm.com return Gicv3::INT_ACTIVE; 106112724Snikos.nikoleris@arm.com } else { 106212724Snikos.nikoleris@arm.com return Gicv3::INT_INACTIVE; 106312724Snikos.nikoleris@arm.com } 106412724Snikos.nikoleris@arm.com} 106512724Snikos.nikoleris@arm.com 106613445Sodanrc@yahoo.com.brGicv3::GroupId 106712724Snikos.nikoleris@arm.comGicv3Distributor::getIntGroup(int int_id) const 106812724Snikos.nikoleris@arm.com{ 106912724Snikos.nikoleris@arm.com panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!"); 107012724Snikos.nikoleris@arm.com panic_if(int_id > itLines, "Invalid SPI!"); 107112724Snikos.nikoleris@arm.com 107212724Snikos.nikoleris@arm.com if (DS) { 107312724Snikos.nikoleris@arm.com if (irqGroup[int_id] == 1) { 107412724Snikos.nikoleris@arm.com return Gicv3::G1NS; 107512724Snikos.nikoleris@arm.com } else { 107612724Snikos.nikoleris@arm.com return Gicv3::G0S; 107712724Snikos.nikoleris@arm.com } 107812724Snikos.nikoleris@arm.com } else { 107912724Snikos.nikoleris@arm.com if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) { 108012724Snikos.nikoleris@arm.com return Gicv3::G0S; 108112724Snikos.nikoleris@arm.com } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) { 108212724Snikos.nikoleris@arm.com return Gicv3::G1NS; 108312724Snikos.nikoleris@arm.com } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) { 108412724Snikos.nikoleris@arm.com return Gicv3::G1S; 108513477Sodanrc@yahoo.com.br } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) { 108613477Sodanrc@yahoo.com.br return Gicv3::G1NS; 108712724Snikos.nikoleris@arm.com } 108812724Snikos.nikoleris@arm.com } 108912724Snikos.nikoleris@arm.com 109012724Snikos.nikoleris@arm.com M5_UNREACHABLE; 109112724Snikos.nikoleris@arm.com} 109212724Snikos.nikoleris@arm.com 109312724Snikos.nikoleris@arm.comvoid 109412724Snikos.nikoleris@arm.comGicv3Distributor::activateIRQ(uint32_t int_id) 109512724Snikos.nikoleris@arm.com{ 109612724Snikos.nikoleris@arm.com irqPending[int_id] = false; 109712724Snikos.nikoleris@arm.com irqActive[int_id] = true; 109812724Snikos.nikoleris@arm.com} 109912724Snikos.nikoleris@arm.com 110012724Snikos.nikoleris@arm.comvoid 110112724Snikos.nikoleris@arm.comGicv3Distributor::deactivateIRQ(uint32_t int_id) 110212724Snikos.nikoleris@arm.com{ 110312724Snikos.nikoleris@arm.com irqActive[int_id] = false; 110412724Snikos.nikoleris@arm.com} 110512724Snikos.nikoleris@arm.com 110612724Snikos.nikoleris@arm.comvoid 110712724Snikos.nikoleris@arm.comGicv3Distributor::serialize(CheckpointOut & cp) const 110812724Snikos.nikoleris@arm.com{ 110912724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(ARE); 111012724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(DS); 111112724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(EnableGrp1S); 111212724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(EnableGrp1NS); 111312724Snikos.nikoleris@arm.com SERIALIZE_SCALAR(EnableGrp0); 111412724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqGroup); 111512724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqEnabled); 111612724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqPending); 111712724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqActive); 111812724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqPriority); 111912724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqConfig); 112012724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqGrpmod); 112112724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqNsacr); 112212724Snikos.nikoleris@arm.com SERIALIZE_CONTAINER(irqAffinityRouting); 112312724Snikos.nikoleris@arm.com} 112412724Snikos.nikoleris@arm.com 112512724Snikos.nikoleris@arm.comvoid 112612724Snikos.nikoleris@arm.comGicv3Distributor::unserialize(CheckpointIn & cp) 112712724Snikos.nikoleris@arm.com{ 112812724Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(ARE); 112912724Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(DS); 113013350Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(EnableGrp1S); 113112724Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(EnableGrp1NS); 113212724Snikos.nikoleris@arm.com UNSERIALIZE_SCALAR(EnableGrp0); 113312724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqGroup); 113412724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqEnabled); 113512724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqPending); 113612724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqActive); 113712724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqPriority); 113812724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqConfig); 113912724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqGrpmod); 114012724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqNsacr); 114112724Snikos.nikoleris@arm.com UNSERIALIZE_CONTAINER(irqAffinityRouting); 114212724Snikos.nikoleris@arm.com} 114313350Snikos.nikoleris@arm.com