gic_v3_cpu_interface.cc revision 14236
110515SN/A/* 210515SN/A * Copyright (c) 2019 ARM Limited 311502SCurtis.Dunham@arm.com * All rights reserved 411502SCurtis.Dunham@arm.com * 511502SCurtis.Dunham@arm.com * The license below extends only to copyright in the software and shall 610515SN/A * not be construed as granting a license to any other intellectual 711502SCurtis.Dunham@arm.com * property including but not limited to intellectual property relating 811502SCurtis.Dunham@arm.com * to a hardware implementation of the functionality of the software 911502SCurtis.Dunham@arm.com * licensed hereunder. You may use the software subject to the license 1011502SCurtis.Dunham@arm.com * terms below provided that you ensure that this notice is replicated 1111502SCurtis.Dunham@arm.com * unmodified and in its entirety in all distributions of the software, 1211502SCurtis.Dunham@arm.com * modified or unmodified, in source code or in binary form. 1311502SCurtis.Dunham@arm.com * 1410515SN/A * Copyright (c) 2018 Metempsy Technology Consulting 1510515SN/A * All rights reserved. 1611502SCurtis.Dunham@arm.com * 1711502SCurtis.Dunham@arm.com * Redistribution and use in source and binary forms, with or without 1811502SCurtis.Dunham@arm.com * modification, are permitted provided that the following conditions are 1911502SCurtis.Dunham@arm.com * met: redistributions of source code must retain the above copyright 2011502SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer; 2111502SCurtis.Dunham@arm.com * redistributions in binary form must reproduce the above copyright 2211502SCurtis.Dunham@arm.com * notice, this list of conditions and the following disclaimer in the 2311502SCurtis.Dunham@arm.com * documentation and/or other materials provided with the distribution; 2411502SCurtis.Dunham@arm.com * neither the name of the copyright holders nor the names of its 2511502SCurtis.Dunham@arm.com * contributors may be used to endorse or promote products derived from 2611502SCurtis.Dunham@arm.com * this software without specific prior written permission. 2711502SCurtis.Dunham@arm.com * 2811502SCurtis.Dunham@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2911502SCurtis.Dunham@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3011502SCurtis.Dunham@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 3111502SCurtis.Dunham@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3210827Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3310585SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3411502SCurtis.Dunham@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3511502SCurtis.Dunham@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3611502SCurtis.Dunham@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3711502SCurtis.Dunham@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3811502SCurtis.Dunham@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3911502SCurtis.Dunham@arm.com * 4011502SCurtis.Dunham@arm.com * Authors: Jairo Balart 4111502SCurtis.Dunham@arm.com */ 4211502SCurtis.Dunham@arm.com 4311502SCurtis.Dunham@arm.com#include "dev/arm/gic_v3_cpu_interface.hh" 4411502SCurtis.Dunham@arm.com 4511502SCurtis.Dunham@arm.com#include "arch/arm/isa.hh" 4611502SCurtis.Dunham@arm.com#include "debug/GIC.hh" 4711502SCurtis.Dunham@arm.com#include "dev/arm/gic_v3.hh" 4810827Sandreas.hansson@arm.com#include "dev/arm/gic_v3_distributor.hh" 4910585SN/A#include "dev/arm/gic_v3_redistributor.hh" 5011502SCurtis.Dunham@arm.com 5111502SCurtis.Dunham@arm.comconst uint8_t Gicv3CPUInterface::GIC_MIN_BPR; 5211502SCurtis.Dunham@arm.comconst uint8_t Gicv3CPUInterface::GIC_MIN_BPR_NS; 5311502SCurtis.Dunham@arm.com 5411502SCurtis.Dunham@arm.comGicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id) 5511502SCurtis.Dunham@arm.com : BaseISADevice(), 5611502SCurtis.Dunham@arm.com gic(gic), 5711502SCurtis.Dunham@arm.com redistributor(nullptr), 5811502SCurtis.Dunham@arm.com distributor(nullptr), 5911502SCurtis.Dunham@arm.com cpuId(cpu_id) 6011502SCurtis.Dunham@arm.com{ 6111502SCurtis.Dunham@arm.com} 6211502SCurtis.Dunham@arm.com 6311502SCurtis.Dunham@arm.comvoid 6411502SCurtis.Dunham@arm.comGicv3CPUInterface::init() 6511502SCurtis.Dunham@arm.com{ 6611502SCurtis.Dunham@arm.com redistributor = gic->getRedistributor(cpuId); 6711502SCurtis.Dunham@arm.com distributor = gic->getDistributor(); 6810585SN/A} 6911502SCurtis.Dunham@arm.com 7011502SCurtis.Dunham@arm.comvoid 7111502SCurtis.Dunham@arm.comGicv3CPUInterface::initState() 7211502SCurtis.Dunham@arm.com{ 7311502SCurtis.Dunham@arm.com reset(); 7411502SCurtis.Dunham@arm.com} 7511502SCurtis.Dunham@arm.com 7611502SCurtis.Dunham@arm.comvoid 7711502SCurtis.Dunham@arm.comGicv3CPUInterface::reset() 7811502SCurtis.Dunham@arm.com{ 7911502SCurtis.Dunham@arm.com hppi.prio = 0xff; 8011502SCurtis.Dunham@arm.com} 8111502SCurtis.Dunham@arm.com 8211502SCurtis.Dunham@arm.comvoid 8311502SCurtis.Dunham@arm.comGicv3CPUInterface::setThreadContext(ThreadContext *tc) 8411502SCurtis.Dunham@arm.com{ 8511502SCurtis.Dunham@arm.com maintenanceInterrupt = gic->params()->maint_int->get(tc); 8611502SCurtis.Dunham@arm.com} 8711502SCurtis.Dunham@arm.com 8811502SCurtis.Dunham@arm.combool 8911502SCurtis.Dunham@arm.comGicv3CPUInterface::getHCREL2FMO() const 9011502SCurtis.Dunham@arm.com{ 9111502SCurtis.Dunham@arm.com HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2); 9211502SCurtis.Dunham@arm.com 9311502SCurtis.Dunham@arm.com if (hcr.tge && hcr.e2h) { 9411336Sandreas.hansson@arm.com return false; 9511502SCurtis.Dunham@arm.com } else if (hcr.tge) { 9611502SCurtis.Dunham@arm.com return true; 9711502SCurtis.Dunham@arm.com } else { 9811502SCurtis.Dunham@arm.com return hcr.fmo; 9911502SCurtis.Dunham@arm.com } 10011502SCurtis.Dunham@arm.com} 10111502SCurtis.Dunham@arm.com 10211502SCurtis.Dunham@arm.combool 10311502SCurtis.Dunham@arm.comGicv3CPUInterface::getHCREL2IMO() const 10411502SCurtis.Dunham@arm.com{ 10511502SCurtis.Dunham@arm.com HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2); 10611502SCurtis.Dunham@arm.com 10711502SCurtis.Dunham@arm.com if (hcr.tge && hcr.e2h) { 10811502SCurtis.Dunham@arm.com return false; 10911502SCurtis.Dunham@arm.com } else if (hcr.tge) { 11011502SCurtis.Dunham@arm.com return true; 11111502SCurtis.Dunham@arm.com } else { 11211502SCurtis.Dunham@arm.com return hcr.imo; 11311502SCurtis.Dunham@arm.com } 11411502SCurtis.Dunham@arm.com} 11511502SCurtis.Dunham@arm.com 11611502SCurtis.Dunham@arm.comRegVal 11711502SCurtis.Dunham@arm.comGicv3CPUInterface::readMiscReg(int misc_reg) 11811502SCurtis.Dunham@arm.com{ 11911502SCurtis.Dunham@arm.com RegVal value = isa->readMiscRegNoEffect(misc_reg); 12011502SCurtis.Dunham@arm.com bool hcr_fmo = getHCREL2FMO(); 12111502SCurtis.Dunham@arm.com bool hcr_imo = getHCREL2IMO(); 12211502SCurtis.Dunham@arm.com 12311502SCurtis.Dunham@arm.com switch (misc_reg) { 12411502SCurtis.Dunham@arm.com // Active Priorities Group 1 Registers 12511502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R0: 12611502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R0_EL1: { 12710515SN/A if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 12811502SCurtis.Dunham@arm.com return isa->readMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1); 12911502SCurtis.Dunham@arm.com } 13010515SN/A 13110515SN/A break; 13210515SN/A } 13310827Sandreas.hansson@arm.com 13410515SN/A case MISCREG_ICC_AP1R1: 13510515SN/A case MISCREG_ICC_AP1R1_EL1: 13611502SCurtis.Dunham@arm.com 13710515SN/A // only implemented if supporting 6 or more bits of priority 13810515SN/A case MISCREG_ICC_AP1R2: 13910515SN/A case MISCREG_ICC_AP1R2_EL1: 14010827Sandreas.hansson@arm.com 14110515SN/A // only implemented if supporting 7 or more bits of priority 14210515SN/A case MISCREG_ICC_AP1R3: 14311502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R3_EL1: 14411502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 14511502SCurtis.Dunham@arm.com return 0; 14611502SCurtis.Dunham@arm.com 14711502SCurtis.Dunham@arm.com // Active Priorities Group 0 Registers 14811502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R0: 14911502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R0_EL1: { 15011502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 15111502SCurtis.Dunham@arm.com return isa->readMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1); 15211502SCurtis.Dunham@arm.com } 15311502SCurtis.Dunham@arm.com 15411502SCurtis.Dunham@arm.com break; 15511502SCurtis.Dunham@arm.com } 15611502SCurtis.Dunham@arm.com 15711502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R1: 15811502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R1_EL1: 15911502SCurtis.Dunham@arm.com 16011502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 16111502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R2: 16211502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R2_EL1: 16311502SCurtis.Dunham@arm.com 16411502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 16511502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R3: 16611201Sandreas.hansson@arm.com case MISCREG_ICC_AP0R3_EL1: 16711201Sandreas.hansson@arm.com // only implemented if supporting 7 or more bits of priority 16810628SN/A return 0; 16910628SN/A 17010515SN/A // Interrupt Group 0 Enable register EL1 17110515SN/A case MISCREG_ICC_IGRPEN0: 17210515SN/A case MISCREG_ICC_IGRPEN0_EL1: { 17310515SN/A if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 17410515SN/A return readMiscReg(MISCREG_ICV_IGRPEN0_EL1); 17510515SN/A } 17610515SN/A 17710515SN/A break; 17810515SN/A } 17910515SN/A 18010515SN/A case MISCREG_ICV_IGRPEN0_EL1: { 18110515SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 18210515SN/A isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 18310515SN/A value = ich_vmcr_el2.VENG0; 18410515SN/A break; 18510515SN/A } 18610515SN/A 18710515SN/A // Interrupt Group 1 Enable register EL1 18810515SN/A case MISCREG_ICC_IGRPEN1: 18910515SN/A case MISCREG_ICC_IGRPEN1_EL1: { 19010515SN/A if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 19111502SCurtis.Dunham@arm.com return readMiscReg(MISCREG_ICV_IGRPEN1_EL1); 19211502SCurtis.Dunham@arm.com } 19311502SCurtis.Dunham@arm.com 19411502SCurtis.Dunham@arm.com break; 19511502SCurtis.Dunham@arm.com } 19611502SCurtis.Dunham@arm.com 19711502SCurtis.Dunham@arm.com case MISCREG_ICV_IGRPEN1_EL1: { 19811502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = 19911502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 20011502SCurtis.Dunham@arm.com value = ich_vmcr_el2.VENG1; 20111502SCurtis.Dunham@arm.com break; 20211502SCurtis.Dunham@arm.com } 20311502SCurtis.Dunham@arm.com 20411502SCurtis.Dunham@arm.com // Interrupt Group 1 Enable register EL3 20511502SCurtis.Dunham@arm.com case MISCREG_ICC_MGRPEN1: 20611502SCurtis.Dunham@arm.com case MISCREG_ICC_IGRPEN1_EL3: 20711502SCurtis.Dunham@arm.com break; 20811502SCurtis.Dunham@arm.com 20911502SCurtis.Dunham@arm.com // Running Priority Register 21011502SCurtis.Dunham@arm.com case MISCREG_ICC_RPR: 21111502SCurtis.Dunham@arm.com case MISCREG_ICC_RPR_EL1: { 21211502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && 21311502SCurtis.Dunham@arm.com (hcr_imo || hcr_fmo)) { 21411502SCurtis.Dunham@arm.com return readMiscReg(MISCREG_ICV_RPR_EL1); 21511502SCurtis.Dunham@arm.com } 21611502SCurtis.Dunham@arm.com 21711502SCurtis.Dunham@arm.com uint8_t rprio = highestActivePriority(); 21811502SCurtis.Dunham@arm.com 21911502SCurtis.Dunham@arm.com if (haveEL(EL3) && !inSecureState() && 22011502SCurtis.Dunham@arm.com (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { 22111502SCurtis.Dunham@arm.com // Spec section 4.8.1 22211502SCurtis.Dunham@arm.com // For Non-secure access to ICC_RPR_EL1 when SCR_EL3.FIQ == 1 22311502SCurtis.Dunham@arm.com if ((rprio & 0x80) == 0) { 22411502SCurtis.Dunham@arm.com // If the current priority mask value is in the range of 22511502SCurtis.Dunham@arm.com // 0x00-0x7F a read access returns the value 0x0 22611502SCurtis.Dunham@arm.com rprio = 0; 22711502SCurtis.Dunham@arm.com } else if (rprio != 0xff) { 22811502SCurtis.Dunham@arm.com // If the current priority mask value is in the range of 22911502SCurtis.Dunham@arm.com // 0x80-0xFF a read access returns the Non-secure read of 23011502SCurtis.Dunham@arm.com // the current value 23111502SCurtis.Dunham@arm.com rprio = (rprio << 1) & 0xff; 23211502SCurtis.Dunham@arm.com } 23311502SCurtis.Dunham@arm.com } 23411502SCurtis.Dunham@arm.com 23511502SCurtis.Dunham@arm.com value = rprio; 23611502SCurtis.Dunham@arm.com break; 23711502SCurtis.Dunham@arm.com } 23811502SCurtis.Dunham@arm.com 23911502SCurtis.Dunham@arm.com // Virtual Running Priority Register 24011502SCurtis.Dunham@arm.com case MISCREG_ICV_RPR_EL1: { 24111502SCurtis.Dunham@arm.com value = virtualHighestActivePriority(); 24211502SCurtis.Dunham@arm.com break; 24311502SCurtis.Dunham@arm.com } 24411502SCurtis.Dunham@arm.com 24511502SCurtis.Dunham@arm.com // Highest Priority Pending Interrupt Register 0 24611502SCurtis.Dunham@arm.com case MISCREG_ICC_HPPIR0: 24711502SCurtis.Dunham@arm.com case MISCREG_ICC_HPPIR0_EL1: { 24811502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 24911502SCurtis.Dunham@arm.com return readMiscReg(MISCREG_ICV_HPPIR0_EL1); 25011502SCurtis.Dunham@arm.com } 25111502SCurtis.Dunham@arm.com 25211502SCurtis.Dunham@arm.com value = getHPPIR0(); 25311502SCurtis.Dunham@arm.com break; 25411502SCurtis.Dunham@arm.com } 25511502SCurtis.Dunham@arm.com 25611502SCurtis.Dunham@arm.com // Virtual Highest Priority Pending Interrupt Register 0 25711502SCurtis.Dunham@arm.com case MISCREG_ICV_HPPIR0_EL1: { 25811374Ssteve.reinhardt@amd.com value = Gicv3::INTID_SPURIOUS; 25911353Sandreas.hansson@arm.com int lr_idx = getHPPVILR(); 26011353Sandreas.hansson@arm.com 26111502SCurtis.Dunham@arm.com if (lr_idx >= 0) { 26211502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 26311502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 26411502SCurtis.Dunham@arm.com Gicv3::GroupId group = 26511502SCurtis.Dunham@arm.com ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; 26611502SCurtis.Dunham@arm.com 26711502SCurtis.Dunham@arm.com if (group == Gicv3::G0S) { 26811502SCurtis.Dunham@arm.com value = ich_lr_el2.vINTID; 26911502SCurtis.Dunham@arm.com } 27011502SCurtis.Dunham@arm.com } 27111502SCurtis.Dunham@arm.com 27211502SCurtis.Dunham@arm.com break; 27311502SCurtis.Dunham@arm.com } 27411502SCurtis.Dunham@arm.com 27511502SCurtis.Dunham@arm.com // Highest Priority Pending Interrupt Register 1 27611502SCurtis.Dunham@arm.com case MISCREG_ICC_HPPIR1: 27711502SCurtis.Dunham@arm.com case MISCREG_ICC_HPPIR1_EL1: { 27811502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 27911502SCurtis.Dunham@arm.com return readMiscReg(MISCREG_ICV_HPPIR1_EL1); 28011502SCurtis.Dunham@arm.com } 28111502SCurtis.Dunham@arm.com 28211502SCurtis.Dunham@arm.com value = getHPPIR1(); 28311502SCurtis.Dunham@arm.com break; 28411502SCurtis.Dunham@arm.com } 28511502SCurtis.Dunham@arm.com 28611502SCurtis.Dunham@arm.com // Virtual Highest Priority Pending Interrupt Register 1 28711502SCurtis.Dunham@arm.com case MISCREG_ICV_HPPIR1_EL1: { 28811502SCurtis.Dunham@arm.com value = Gicv3::INTID_SPURIOUS; 28911502SCurtis.Dunham@arm.com int lr_idx = getHPPVILR(); 29011502SCurtis.Dunham@arm.com 29111502SCurtis.Dunham@arm.com if (lr_idx >= 0) { 29211502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 29311502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 29411502SCurtis.Dunham@arm.com Gicv3::GroupId group = 29511502SCurtis.Dunham@arm.com ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; 29611502SCurtis.Dunham@arm.com 29711502SCurtis.Dunham@arm.com if (group == Gicv3::G1NS) { 29811502SCurtis.Dunham@arm.com value = ich_lr_el2.vINTID; 29911502SCurtis.Dunham@arm.com } 30011502SCurtis.Dunham@arm.com } 30111502SCurtis.Dunham@arm.com 30211502SCurtis.Dunham@arm.com break; 30311502SCurtis.Dunham@arm.com } 30411502SCurtis.Dunham@arm.com 30511502SCurtis.Dunham@arm.com // Binary Point Register 0 30611502SCurtis.Dunham@arm.com case MISCREG_ICC_BPR0: 30711502SCurtis.Dunham@arm.com case MISCREG_ICC_BPR0_EL1: 30811502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 30910515SN/A return readMiscReg(MISCREG_ICV_BPR0_EL1); 31011502SCurtis.Dunham@arm.com } 31111502SCurtis.Dunham@arm.com 31211502SCurtis.Dunham@arm.com M5_FALLTHROUGH; 31311502SCurtis.Dunham@arm.com 31411502SCurtis.Dunham@arm.com // Binary Point Register 1 31510515SN/A case MISCREG_ICC_BPR1: 31611374Ssteve.reinhardt@amd.com case MISCREG_ICC_BPR1_EL1: { 31711201Sandreas.hansson@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 31810892Sandreas.hansson@arm.com return readMiscReg(MISCREG_ICV_BPR1_EL1); 31911502SCurtis.Dunham@arm.com } 32011502SCurtis.Dunham@arm.com 32111502SCurtis.Dunham@arm.com Gicv3::GroupId group = 32211502SCurtis.Dunham@arm.com misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; 32311502SCurtis.Dunham@arm.com 32411502SCurtis.Dunham@arm.com if (group == Gicv3::G1S && !inSecureState()) { 32511502SCurtis.Dunham@arm.com group = Gicv3::G1NS; 32611502SCurtis.Dunham@arm.com } 32711502SCurtis.Dunham@arm.com 32811502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_s = 32911502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); 33011502SCurtis.Dunham@arm.com 33111502SCurtis.Dunham@arm.com if ((group == Gicv3::G1S) && !isEL3OrMon() && 33211502SCurtis.Dunham@arm.com icc_ctlr_el1_s.CBPR) { 33311502SCurtis.Dunham@arm.com group = Gicv3::G0S; 33411502SCurtis.Dunham@arm.com } 33511502SCurtis.Dunham@arm.com 33611502SCurtis.Dunham@arm.com bool sat_inc = false; 33711502SCurtis.Dunham@arm.com 33810628SN/A ICC_CTLR_EL1 icc_ctlr_el1_ns = 33911502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); 34010628SN/A 34111502SCurtis.Dunham@arm.com if ((group == Gicv3::G1NS) && (currEL() < EL3) && 34211502SCurtis.Dunham@arm.com icc_ctlr_el1_ns.CBPR) { 34311502SCurtis.Dunham@arm.com // Reads return BPR0 + 1 saturated to 7, WI 34411502SCurtis.Dunham@arm.com group = Gicv3::G0S; 34511502SCurtis.Dunham@arm.com sat_inc = true; 34611502SCurtis.Dunham@arm.com } 34711502SCurtis.Dunham@arm.com 34811502SCurtis.Dunham@arm.com uint8_t bpr; 34911502SCurtis.Dunham@arm.com 35011502SCurtis.Dunham@arm.com if (group == Gicv3::G0S) { 35111502SCurtis.Dunham@arm.com bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1); 35210628SN/A } else { 35311502SCurtis.Dunham@arm.com bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1); 35410628SN/A bpr = std::max(bpr, group == Gicv3::G1S ? 35510515SN/A GIC_MIN_BPR : GIC_MIN_BPR_NS); 35610515SN/A } 35710515SN/A 35810515SN/A if (sat_inc) { 35910515SN/A bpr++; 36010515SN/A 36110515SN/A if (bpr > 7) { 36210515SN/A bpr = 7; 36310515SN/A } 36410515SN/A } 36510515SN/A 36610515SN/A value = bpr; 36710515SN/A break; 36810515SN/A } 36910515SN/A 37010515SN/A // Virtual Binary Point Register 1 37110515SN/A case MISCREG_ICV_BPR0_EL1: 37210515SN/A case MISCREG_ICV_BPR1_EL1: { 37310515SN/A Gicv3::GroupId group = 37410515SN/A misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS; 37510515SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 37610515SN/A isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 37710515SN/A bool sat_inc = false; 37810515SN/A 37910515SN/A if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { 38010515SN/A // bpr0 + 1 saturated to 7, WI 38110535SN/A group = Gicv3::G0S; 38210535SN/A sat_inc = true; 38310535SN/A } 38411353Sandreas.hansson@arm.com 38511353Sandreas.hansson@arm.com uint8_t vbpr; 38611353Sandreas.hansson@arm.com 38710515SN/A if (group == Gicv3::G0S) { 38810628SN/A vbpr = ich_vmcr_el2.VBPR0; 38910628SN/A } else { 39010628SN/A vbpr = ich_vmcr_el2.VBPR1; 39110628SN/A } 39210628SN/A 39310628SN/A if (sat_inc) { 39410628SN/A vbpr++; 39510628SN/A 39610535SN/A if (vbpr > 7) { 39710535SN/A vbpr = 7; 39810535SN/A } 39910535SN/A } 40010535SN/A 40110535SN/A value = vbpr; 40210535SN/A break; 40310535SN/A } 40410535SN/A 40510535SN/A // Interrupt Priority Mask Register 40610535SN/A case MISCREG_ICC_PMR: 40710535SN/A case MISCREG_ICC_PMR_EL1: 40810535SN/A if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { 40910535SN/A return readMiscReg(MISCREG_ICV_PMR_EL1); 41010535SN/A } 41110535SN/A 41210535SN/A if (haveEL(EL3) && !inSecureState() && 41310535SN/A (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { 41410535SN/A // Spec section 4.8.1 41510535SN/A // For Non-secure access to ICC_PMR_EL1 when SCR_EL3.FIQ == 1: 41610535SN/A if ((value & 0x80) == 0) { 41711502SCurtis.Dunham@arm.com // If the current priority mask value is in the range of 41811502SCurtis.Dunham@arm.com // 0x00-0x7F a read access returns the value 0x00. 41911502SCurtis.Dunham@arm.com value = 0; 42011502SCurtis.Dunham@arm.com } else if (value != 0xff) { 42111502SCurtis.Dunham@arm.com // If the current priority mask value is in the range of 42211502SCurtis.Dunham@arm.com // 0x80-0xFF a read access returns the Non-secure read of the 42311502SCurtis.Dunham@arm.com // current value. 42411502SCurtis.Dunham@arm.com value = (value << 1) & 0xff; 42511502SCurtis.Dunham@arm.com } 42611201Sandreas.hansson@arm.com } 42711502SCurtis.Dunham@arm.com 42811502SCurtis.Dunham@arm.com break; 42911502SCurtis.Dunham@arm.com 43011502SCurtis.Dunham@arm.com case MISCREG_ICV_PMR_EL1: { // Priority Mask Register 43111502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = 43211502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 43311502SCurtis.Dunham@arm.com 43411502SCurtis.Dunham@arm.com value = ich_vmcr_el2.VPMR; 43511502SCurtis.Dunham@arm.com break; 43611502SCurtis.Dunham@arm.com } 43711502SCurtis.Dunham@arm.com 43811502SCurtis.Dunham@arm.com // Interrupt Acknowledge Register 0 43911502SCurtis.Dunham@arm.com case MISCREG_ICC_IAR0: 44011502SCurtis.Dunham@arm.com case MISCREG_ICC_IAR0_EL1: { 44111502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 44211502SCurtis.Dunham@arm.com return readMiscReg(MISCREG_ICV_IAR0_EL1); 44311502SCurtis.Dunham@arm.com } 44411502SCurtis.Dunham@arm.com 44511502SCurtis.Dunham@arm.com uint32_t int_id; 44611502SCurtis.Dunham@arm.com 44711502SCurtis.Dunham@arm.com if (hppiCanPreempt()) { 44811502SCurtis.Dunham@arm.com int_id = getHPPIR0(); 44911502SCurtis.Dunham@arm.com 45011502SCurtis.Dunham@arm.com // avoid activation for special interrupts 45111502SCurtis.Dunham@arm.com if (int_id < Gicv3::INTID_SECURE || 45211502SCurtis.Dunham@arm.com int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) { 45311502SCurtis.Dunham@arm.com activateIRQ(int_id, hppi.group); 45411502SCurtis.Dunham@arm.com } 45511502SCurtis.Dunham@arm.com } else { 45611502SCurtis.Dunham@arm.com int_id = Gicv3::INTID_SPURIOUS; 45710628SN/A } 45811502SCurtis.Dunham@arm.com 45911502SCurtis.Dunham@arm.com value = int_id; 46010628SN/A break; 46111502SCurtis.Dunham@arm.com } 46211502SCurtis.Dunham@arm.com 46310535SN/A // Virtual Interrupt Acknowledge Register 0 46410535SN/A case MISCREG_ICV_IAR0_EL1: { 46511502SCurtis.Dunham@arm.com int lr_idx = getHPPVILR(); 46611502SCurtis.Dunham@arm.com uint32_t int_id = Gicv3::INTID_SPURIOUS; 46711502SCurtis.Dunham@arm.com 46811502SCurtis.Dunham@arm.com if (lr_idx >= 0) { 46910535SN/A ICH_LR_EL2 ich_lr_el2 = 47010535SN/A isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 47111502SCurtis.Dunham@arm.com 47211502SCurtis.Dunham@arm.com if (!ich_lr_el2.Group && hppviCanPreempt(lr_idx)) { 47311502SCurtis.Dunham@arm.com int_id = ich_lr_el2.vINTID; 47410535SN/A 47511502SCurtis.Dunham@arm.com if (int_id < Gicv3::INTID_SECURE || 47610535SN/A int_id > Gicv3::INTID_SPURIOUS) { 47711502SCurtis.Dunham@arm.com virtualActivateIRQ(lr_idx); 47811502SCurtis.Dunham@arm.com } else { 47911502SCurtis.Dunham@arm.com // Bogus... Pseudocode says: 48010535SN/A // - Move from pending to invalid... 48111502SCurtis.Dunham@arm.com // - Return de bogus id... 48211502SCurtis.Dunham@arm.com ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID; 48311502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, 48410628SN/A ich_lr_el2); 48510628SN/A } 48610628SN/A } 48710628SN/A } 48810628SN/A 48910628SN/A value = int_id; 49010628SN/A virtualUpdate(); 49110628SN/A break; 49210535SN/A } 49310535SN/A 49410535SN/A // Interrupt Acknowledge Register 1 49510535SN/A case MISCREG_ICC_IAR1: 49610535SN/A case MISCREG_ICC_IAR1_EL1: { 49710535SN/A if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 49810535SN/A return readMiscReg(MISCREG_ICV_IAR1_EL1); 49910535SN/A } 50010535SN/A 50110535SN/A uint32_t int_id; 50210535SN/A 50310535SN/A if (hppiCanPreempt()) { 50410535SN/A int_id = getHPPIR1(); 50510535SN/A 50610535SN/A // avoid activation for special interrupts 50710535SN/A if (int_id < Gicv3::INTID_SECURE || 50810535SN/A int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) { 50910535SN/A activateIRQ(int_id, hppi.group); 51010535SN/A } 51110535SN/A } else { 51210535SN/A int_id = Gicv3::INTID_SPURIOUS; 51311502SCurtis.Dunham@arm.com } 51411502SCurtis.Dunham@arm.com 51511502SCurtis.Dunham@arm.com value = int_id; 51611502SCurtis.Dunham@arm.com break; 51711502SCurtis.Dunham@arm.com } 51811502SCurtis.Dunham@arm.com 51911502SCurtis.Dunham@arm.com // Virtual Interrupt Acknowledge Register 1 52011502SCurtis.Dunham@arm.com case MISCREG_ICV_IAR1_EL1: { 52111502SCurtis.Dunham@arm.com int lr_idx = getHPPVILR(); 52211502SCurtis.Dunham@arm.com uint32_t int_id = Gicv3::INTID_SPURIOUS; 52311502SCurtis.Dunham@arm.com 52411502SCurtis.Dunham@arm.com if (lr_idx >= 0) { 52511502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 52611502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 52711502SCurtis.Dunham@arm.com 52811502SCurtis.Dunham@arm.com if (ich_lr_el2.Group && hppviCanPreempt(lr_idx)) { 52911502SCurtis.Dunham@arm.com int_id = ich_lr_el2.vINTID; 53011502SCurtis.Dunham@arm.com 53111502SCurtis.Dunham@arm.com if (int_id < Gicv3::INTID_SECURE || 53211374Ssteve.reinhardt@amd.com int_id > Gicv3::INTID_SPURIOUS) { 53311502SCurtis.Dunham@arm.com virtualActivateIRQ(lr_idx); 53411502SCurtis.Dunham@arm.com } else { 53511502SCurtis.Dunham@arm.com // Bogus... Pseudocode says: 53611502SCurtis.Dunham@arm.com // - Move from pending to invalid... 53711502SCurtis.Dunham@arm.com // - Return de bogus id... 53811502SCurtis.Dunham@arm.com ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID; 53911502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, 54010628SN/A ich_lr_el2); 54111502SCurtis.Dunham@arm.com } 54211502SCurtis.Dunham@arm.com } 54310628SN/A } 54411502SCurtis.Dunham@arm.com 54511502SCurtis.Dunham@arm.com value = int_id; 54611502SCurtis.Dunham@arm.com virtualUpdate(); 54711502SCurtis.Dunham@arm.com break; 54811502SCurtis.Dunham@arm.com } 54910535SN/A 55010535SN/A // System Register Enable Register EL1 55110535SN/A case MISCREG_ICC_SRE: 55210535SN/A case MISCREG_ICC_SRE_EL1: { 55310535SN/A /* 55410535SN/A * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) 55511502SCurtis.Dunham@arm.com * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) 55611502SCurtis.Dunham@arm.com * SRE [0] == 1 (Only system register interface supported, RAO/WI) 55711502SCurtis.Dunham@arm.com */ 55810535SN/A ICC_SRE_EL1 icc_sre_el1 = 0; 55910535SN/A icc_sre_el1.SRE = 1; 56010535SN/A icc_sre_el1.DIB = 1; 56110535SN/A icc_sre_el1.DFB = 1; 56210535SN/A value = icc_sre_el1; 56310535SN/A break; 56411502SCurtis.Dunham@arm.com } 56511502SCurtis.Dunham@arm.com 56611502SCurtis.Dunham@arm.com // System Register Enable Register EL2 56711502SCurtis.Dunham@arm.com case MISCREG_ICC_HSRE: 56811502SCurtis.Dunham@arm.com case MISCREG_ICC_SRE_EL2: { 56910535SN/A /* 57010535SN/A * Enable [3] == 1 57111167Sjthestness@gmail.com * (EL1 accesses to ICC_SRE_EL1 do not trap to EL2, RAO/WI) 57211502SCurtis.Dunham@arm.com * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) 57311502SCurtis.Dunham@arm.com * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) 57411502SCurtis.Dunham@arm.com * SRE [0] == 1 (Only system register interface supported, RAO/WI) 57511502SCurtis.Dunham@arm.com */ 57611502SCurtis.Dunham@arm.com ICC_SRE_EL2 icc_sre_el2 = 0; 57711502SCurtis.Dunham@arm.com icc_sre_el2.SRE = 1; 57811502SCurtis.Dunham@arm.com icc_sre_el2.DIB = 1; 57911502SCurtis.Dunham@arm.com icc_sre_el2.DFB = 1; 58011502SCurtis.Dunham@arm.com icc_sre_el2.Enable = 1; 58111502SCurtis.Dunham@arm.com value = icc_sre_el2; 58211502SCurtis.Dunham@arm.com break; 58311502SCurtis.Dunham@arm.com } 58411502SCurtis.Dunham@arm.com 58511502SCurtis.Dunham@arm.com // System Register Enable Register EL3 58611502SCurtis.Dunham@arm.com case MISCREG_ICC_MSRE: 58711502SCurtis.Dunham@arm.com case MISCREG_ICC_SRE_EL3: { 58811502SCurtis.Dunham@arm.com /* 58911502SCurtis.Dunham@arm.com * Enable [3] == 1 59011502SCurtis.Dunham@arm.com * (EL1 accesses to ICC_SRE_EL1 do not trap to EL3. 59111502SCurtis.Dunham@arm.com * EL2 accesses to ICC_SRE_EL1 and ICC_SRE_EL2 do not trap to EL3. 59211502SCurtis.Dunham@arm.com * RAO/WI) 59311502SCurtis.Dunham@arm.com * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) 59411502SCurtis.Dunham@arm.com * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) 59511374Ssteve.reinhardt@amd.com * SRE [0] == 1 (Only system register interface supported, RAO/WI) 59611502SCurtis.Dunham@arm.com */ 59711502SCurtis.Dunham@arm.com ICC_SRE_EL3 icc_sre_el3 = 0; 59811502SCurtis.Dunham@arm.com icc_sre_el3.SRE = 1; 59911502SCurtis.Dunham@arm.com icc_sre_el3.DIB = 1; 60011502SCurtis.Dunham@arm.com icc_sre_el3.DFB = 1; 60111502SCurtis.Dunham@arm.com icc_sre_el3.Enable = 1; 60211502SCurtis.Dunham@arm.com value = icc_sre_el3; 60311502SCurtis.Dunham@arm.com break; 60411502SCurtis.Dunham@arm.com } 60511502SCurtis.Dunham@arm.com 60611502SCurtis.Dunham@arm.com // Control Register 60711502SCurtis.Dunham@arm.com case MISCREG_ICC_CTLR: 60811502SCurtis.Dunham@arm.com case MISCREG_ICC_CTLR_EL1: { 60911502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { 61011502SCurtis.Dunham@arm.com return readMiscReg(MISCREG_ICV_CTLR_EL1); 61111502SCurtis.Dunham@arm.com } 61211502SCurtis.Dunham@arm.com 61311502SCurtis.Dunham@arm.com // Enforce value for RO bits 61411502SCurtis.Dunham@arm.com // ExtRange [19], INTIDs in the range 1024..8191 not supported 61511502SCurtis.Dunham@arm.com // RSS [18], SGIs with affinity level 0 values of 0-255 are supported 61611502SCurtis.Dunham@arm.com // A3V [15], supports non-zero values of the Aff3 field in SGI 61711502SCurtis.Dunham@arm.com // generation System registers 61811502SCurtis.Dunham@arm.com // SEIS [14], does not support generation of SEIs (deprecated) 61911502SCurtis.Dunham@arm.com // IDbits [13:11], 001 = 24 bits | 000 = 16 bits 62011502SCurtis.Dunham@arm.com // PRIbits [10:8], number of priority bits implemented, minus one 62111502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1 = value; 62211502SCurtis.Dunham@arm.com icc_ctlr_el1.ExtRange = 0; 62311502SCurtis.Dunham@arm.com icc_ctlr_el1.RSS = 1; 62411502SCurtis.Dunham@arm.com icc_ctlr_el1.A3V = 1; 62511502SCurtis.Dunham@arm.com icc_ctlr_el1.SEIS = 0; 62611502SCurtis.Dunham@arm.com icc_ctlr_el1.IDbits = 1; 62710535SN/A icc_ctlr_el1.PRIbits = PRIORITY_BITS - 1; 62810535SN/A value = icc_ctlr_el1; 62911502SCurtis.Dunham@arm.com break; 63011502SCurtis.Dunham@arm.com } 63111502SCurtis.Dunham@arm.com 63211502SCurtis.Dunham@arm.com // Virtual Control Register 63311502SCurtis.Dunham@arm.com case MISCREG_ICV_CTLR_EL1: { 63411502SCurtis.Dunham@arm.com ICV_CTLR_EL1 icv_ctlr_el1 = value; 63511502SCurtis.Dunham@arm.com icv_ctlr_el1.RSS = 0; 63611502SCurtis.Dunham@arm.com icv_ctlr_el1.A3V = 1; 63711502SCurtis.Dunham@arm.com icv_ctlr_el1.SEIS = 0; 63811502SCurtis.Dunham@arm.com icv_ctlr_el1.IDbits = 1; 63911374Ssteve.reinhardt@amd.com icv_ctlr_el1.PRIbits = 7; 64011502SCurtis.Dunham@arm.com value = icv_ctlr_el1; 64111502SCurtis.Dunham@arm.com break; 64211502SCurtis.Dunham@arm.com } 64311374Ssteve.reinhardt@amd.com 64411502SCurtis.Dunham@arm.com // Control Register 64511502SCurtis.Dunham@arm.com case MISCREG_ICC_MCTLR: 64611502SCurtis.Dunham@arm.com case MISCREG_ICC_CTLR_EL3: { 64711502SCurtis.Dunham@arm.com // Enforce value for RO bits 64811502SCurtis.Dunham@arm.com // ExtRange [19], INTIDs in the range 1024..8191 not supported 64911502SCurtis.Dunham@arm.com // RSS [18], SGIs with affinity level 0 values of 0-255 are supported 65011502SCurtis.Dunham@arm.com // nDS [17], supports disabling of security 65111502SCurtis.Dunham@arm.com // A3V [15], supports non-zero values of the Aff3 field in SGI 65211502SCurtis.Dunham@arm.com // generation System registers 65311502SCurtis.Dunham@arm.com // SEIS [14], does not support generation of SEIs (deprecated) 65411502SCurtis.Dunham@arm.com // IDbits [13:11], 001 = 24 bits | 000 = 16 bits 65511502SCurtis.Dunham@arm.com // PRIbits [10:8], number of priority bits implemented, minus one 65611502SCurtis.Dunham@arm.com ICC_CTLR_EL3 icc_ctlr_el3 = value; 65711502SCurtis.Dunham@arm.com icc_ctlr_el3.ExtRange = 0; 65811502SCurtis.Dunham@arm.com icc_ctlr_el3.RSS = 1; 65911502SCurtis.Dunham@arm.com icc_ctlr_el3.nDS = 0; 66011502SCurtis.Dunham@arm.com icc_ctlr_el3.A3V = 1; 66111502SCurtis.Dunham@arm.com icc_ctlr_el3.SEIS = 0; 66211502SCurtis.Dunham@arm.com icc_ctlr_el3.IDbits = 0; 66311502SCurtis.Dunham@arm.com icc_ctlr_el3.PRIbits = PRIORITY_BITS - 1; 66411502SCurtis.Dunham@arm.com value = icc_ctlr_el3; 66511502SCurtis.Dunham@arm.com break; 66611502SCurtis.Dunham@arm.com } 66711502SCurtis.Dunham@arm.com 66811502SCurtis.Dunham@arm.com // Hyp Control Register 66911502SCurtis.Dunham@arm.com case MISCREG_ICH_HCR: 67011502SCurtis.Dunham@arm.com case MISCREG_ICH_HCR_EL2: 67111502SCurtis.Dunham@arm.com break; 67211502SCurtis.Dunham@arm.com 67311502SCurtis.Dunham@arm.com // Hyp Active Priorities Group 0 Registers 67411502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R0: 67511502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R0_EL2: 67611502SCurtis.Dunham@arm.com break; 67711502SCurtis.Dunham@arm.com 67811502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 67911502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R1: 68011502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R1_EL2: 68111502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 68211502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R2: 68311502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R2_EL2: 68411502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 68511502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R3: 68611502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R3_EL2: 68711502SCurtis.Dunham@arm.com // Unimplemented registers are RAZ/WI 68811502SCurtis.Dunham@arm.com return 0; 68911502SCurtis.Dunham@arm.com 69011502SCurtis.Dunham@arm.com // Hyp Active Priorities Group 1 Registers 69111502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R0: 69211502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R0_EL2: 69311502SCurtis.Dunham@arm.com break; 69411502SCurtis.Dunham@arm.com 69511502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 69611502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R1: 69711502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R1_EL2: 69811502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 69911502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R2: 70011502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R2_EL2: 70111502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 70211502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R3: 70311502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R3_EL2: 70411502SCurtis.Dunham@arm.com // Unimplemented registers are RAZ/WI 70511502SCurtis.Dunham@arm.com return 0; 70611502SCurtis.Dunham@arm.com 70711502SCurtis.Dunham@arm.com // Maintenance Interrupt State Register 70811502SCurtis.Dunham@arm.com case MISCREG_ICH_MISR: 70911502SCurtis.Dunham@arm.com case MISCREG_ICH_MISR_EL2: 71011502SCurtis.Dunham@arm.com value = maintenanceInterruptStatus(); 71111502SCurtis.Dunham@arm.com break; 71211502SCurtis.Dunham@arm.com 71311502SCurtis.Dunham@arm.com // VGIC Type Register 71411502SCurtis.Dunham@arm.com case MISCREG_ICH_VTR: 71511502SCurtis.Dunham@arm.com case MISCREG_ICH_VTR_EL2: { 71611502SCurtis.Dunham@arm.com ICH_VTR_EL2 ich_vtr_el2 = value; 71711502SCurtis.Dunham@arm.com 71811502SCurtis.Dunham@arm.com ich_vtr_el2.ListRegs = VIRTUAL_NUM_LIST_REGS - 1; 71911502SCurtis.Dunham@arm.com ich_vtr_el2.A3V = 1; 72011502SCurtis.Dunham@arm.com ich_vtr_el2.IDbits = 1; 72111502SCurtis.Dunham@arm.com ich_vtr_el2.PREbits = VIRTUAL_PREEMPTION_BITS - 1; 72211502SCurtis.Dunham@arm.com ich_vtr_el2.PRIbits = VIRTUAL_PRIORITY_BITS - 1; 72311502SCurtis.Dunham@arm.com 72411502SCurtis.Dunham@arm.com value = ich_vtr_el2; 72511502SCurtis.Dunham@arm.com break; 72611502SCurtis.Dunham@arm.com } 72711502SCurtis.Dunham@arm.com 72811502SCurtis.Dunham@arm.com // End of Interrupt Status Register 72911502SCurtis.Dunham@arm.com case MISCREG_ICH_EISR: 73011502SCurtis.Dunham@arm.com case MISCREG_ICH_EISR_EL2: 73111502SCurtis.Dunham@arm.com value = eoiMaintenanceInterruptStatus(); 73211502SCurtis.Dunham@arm.com break; 73311502SCurtis.Dunham@arm.com 73411502SCurtis.Dunham@arm.com // Empty List Register Status Register 73511502SCurtis.Dunham@arm.com case MISCREG_ICH_ELRSR: 73610535SN/A case MISCREG_ICH_ELRSR_EL2: 73710535SN/A value = 0; 73811502SCurtis.Dunham@arm.com 73911502SCurtis.Dunham@arm.com for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 74011502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 74111502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 74210535SN/A 74310535SN/A if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) && 74410535SN/A (ich_lr_el2.HW || !ich_lr_el2.EOI)) { 74510535SN/A value |= (1 << lr_idx); 74610535SN/A } 74710535SN/A } 74811502SCurtis.Dunham@arm.com 74911502SCurtis.Dunham@arm.com break; 75011502SCurtis.Dunham@arm.com 75111502SCurtis.Dunham@arm.com // List Registers 75211502SCurtis.Dunham@arm.com case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: 75311502SCurtis.Dunham@arm.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part) 75411502SCurtis.Dunham@arm.com value = value >> 32; 75511502SCurtis.Dunham@arm.com break; 75611502SCurtis.Dunham@arm.com 75711502SCurtis.Dunham@arm.com // List Registers 75811502SCurtis.Dunham@arm.com case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: 75911502SCurtis.Dunham@arm.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part) 76011502SCurtis.Dunham@arm.com value = value & 0xffffffff; 76111502SCurtis.Dunham@arm.com break; 76211502SCurtis.Dunham@arm.com 76311502SCurtis.Dunham@arm.com // List Registers 76411502SCurtis.Dunham@arm.com case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: 76511502SCurtis.Dunham@arm.com break; 76611502SCurtis.Dunham@arm.com 76711502SCurtis.Dunham@arm.com // Virtual Machine Control Register 76811502SCurtis.Dunham@arm.com case MISCREG_ICH_VMCR: 76911502SCurtis.Dunham@arm.com case MISCREG_ICH_VMCR_EL2: 77011502SCurtis.Dunham@arm.com break; 77111502SCurtis.Dunham@arm.com 77211502SCurtis.Dunham@arm.com default: 77311502SCurtis.Dunham@arm.com panic("Gicv3CPUInterface::readMiscReg(): unknown register %d (%s)", 77411502SCurtis.Dunham@arm.com misc_reg, miscRegName[misc_reg]); 77511502SCurtis.Dunham@arm.com } 77611502SCurtis.Dunham@arm.com 77711502SCurtis.Dunham@arm.com DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): register %s value %#x\n", 77811502SCurtis.Dunham@arm.com miscRegName[misc_reg], value); 77911502SCurtis.Dunham@arm.com return value; 78011502SCurtis.Dunham@arm.com} 78111502SCurtis.Dunham@arm.com 78211502SCurtis.Dunham@arm.comvoid 78311502SCurtis.Dunham@arm.comGicv3CPUInterface::setMiscReg(int misc_reg, RegVal val) 78411502SCurtis.Dunham@arm.com{ 78511502SCurtis.Dunham@arm.com bool do_virtual_update = false; 78611502SCurtis.Dunham@arm.com DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): register %s value %#x\n", 78711502SCurtis.Dunham@arm.com miscRegName[misc_reg], val); 78811502SCurtis.Dunham@arm.com bool hcr_fmo = getHCREL2FMO(); 78911502SCurtis.Dunham@arm.com bool hcr_imo = getHCREL2IMO(); 79011502SCurtis.Dunham@arm.com 79111502SCurtis.Dunham@arm.com switch (misc_reg) { 79211502SCurtis.Dunham@arm.com // Active Priorities Group 1 Registers 79311502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R0: 79411502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R0_EL1: 79511502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 79611502SCurtis.Dunham@arm.com return isa->setMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1, val); 79711502SCurtis.Dunham@arm.com } 79811502SCurtis.Dunham@arm.com 79911502SCurtis.Dunham@arm.com break; 80011502SCurtis.Dunham@arm.com 80111502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R1: 80211502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R1_EL1: 80311502SCurtis.Dunham@arm.com 80411502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 80511502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R2: 80611502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R2_EL1: 80711502SCurtis.Dunham@arm.com 80811502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 80911502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R3: 81011502SCurtis.Dunham@arm.com case MISCREG_ICC_AP1R3_EL1: 81111502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 81211502SCurtis.Dunham@arm.com break; 81311502SCurtis.Dunham@arm.com 81411502SCurtis.Dunham@arm.com // Active Priorities Group 0 Registers 81511502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R0: 81611502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R0_EL1: 81711502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 81811502SCurtis.Dunham@arm.com return isa->setMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1, val); 81911502SCurtis.Dunham@arm.com } 82011502SCurtis.Dunham@arm.com 82111502SCurtis.Dunham@arm.com break; 82211502SCurtis.Dunham@arm.com 82311502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R1: 82411502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R1_EL1: 82511502SCurtis.Dunham@arm.com 82611502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 82711502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R2: 82811502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R2_EL1: 82911502SCurtis.Dunham@arm.com 83011502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 83111502SCurtis.Dunham@arm.com case MISCREG_ICC_AP0R3: 83210535SN/A case MISCREG_ICC_AP0R3_EL1: 83310535SN/A // only implemented if supporting 7 or more bits of priority 83411502SCurtis.Dunham@arm.com break; 83511502SCurtis.Dunham@arm.com 83611502SCurtis.Dunham@arm.com // End Of Interrupt Register 0 83711502SCurtis.Dunham@arm.com case MISCREG_ICC_EOIR0: 83811502SCurtis.Dunham@arm.com case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0 83911502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 84011502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_EOIR0_EL1, val); 84111502SCurtis.Dunham@arm.com } 84211502SCurtis.Dunham@arm.com 84311502SCurtis.Dunham@arm.com int int_id = val & 0xffffff; 84411502SCurtis.Dunham@arm.com 84511502SCurtis.Dunham@arm.com // avoid activation for special interrupts 84611502SCurtis.Dunham@arm.com if (int_id >= Gicv3::INTID_SECURE && 84711502SCurtis.Dunham@arm.com int_id <= Gicv3::INTID_SPURIOUS) { 84811502SCurtis.Dunham@arm.com return; 84911502SCurtis.Dunham@arm.com } 85011502SCurtis.Dunham@arm.com 85110535SN/A Gicv3::GroupId group = Gicv3::G0S; 85211502SCurtis.Dunham@arm.com 85311502SCurtis.Dunham@arm.com if (highestActiveGroup() != group) { 85411502SCurtis.Dunham@arm.com return; 85511502SCurtis.Dunham@arm.com } 85610535SN/A 85711502SCurtis.Dunham@arm.com dropPriority(group); 85811502SCurtis.Dunham@arm.com 85911502SCurtis.Dunham@arm.com if (!isEOISplitMode()) { 86011502SCurtis.Dunham@arm.com deactivateIRQ(int_id, group); 86111502SCurtis.Dunham@arm.com } 86211502SCurtis.Dunham@arm.com 86311502SCurtis.Dunham@arm.com break; 86411502SCurtis.Dunham@arm.com } 86511502SCurtis.Dunham@arm.com 86611502SCurtis.Dunham@arm.com // Virtual End Of Interrupt Register 0 86711502SCurtis.Dunham@arm.com case MISCREG_ICV_EOIR0_EL1: { 86811502SCurtis.Dunham@arm.com int int_id = val & 0xffffff; 86911502SCurtis.Dunham@arm.com 87011502SCurtis.Dunham@arm.com // avoid deactivation for special interrupts 87111502SCurtis.Dunham@arm.com if (int_id >= Gicv3::INTID_SECURE && 87211502SCurtis.Dunham@arm.com int_id <= Gicv3::INTID_SPURIOUS) { 87311502SCurtis.Dunham@arm.com return; 87411502SCurtis.Dunham@arm.com } 87511502SCurtis.Dunham@arm.com 87611502SCurtis.Dunham@arm.com uint8_t drop_prio = virtualDropPriority(); 87711502SCurtis.Dunham@arm.com 87811502SCurtis.Dunham@arm.com if (drop_prio == 0xff) { 87911502SCurtis.Dunham@arm.com return; 88011502SCurtis.Dunham@arm.com } 88111502SCurtis.Dunham@arm.com 88211502SCurtis.Dunham@arm.com int lr_idx = virtualFindActive(int_id); 88311502SCurtis.Dunham@arm.com 88411502SCurtis.Dunham@arm.com if (lr_idx < 0) { 88511502SCurtis.Dunham@arm.com // No LR found matching 88611502SCurtis.Dunham@arm.com virtualIncrementEOICount(); 88711502SCurtis.Dunham@arm.com } else { 88811502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 88911502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 89011502SCurtis.Dunham@arm.com Gicv3::GroupId lr_group = 89111502SCurtis.Dunham@arm.com ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; 89211502SCurtis.Dunham@arm.com uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8; 89311502SCurtis.Dunham@arm.com 89411502SCurtis.Dunham@arm.com if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) { 89510535SN/A //if (!virtualIsEOISplitMode()) 89610535SN/A { 89710535SN/A virtualDeactivateIRQ(lr_idx); 89810535SN/A } 89910535SN/A } 90010535SN/A } 90111502SCurtis.Dunham@arm.com 90211502SCurtis.Dunham@arm.com virtualUpdate(); 90311502SCurtis.Dunham@arm.com break; 90411502SCurtis.Dunham@arm.com } 90511502SCurtis.Dunham@arm.com 90611502SCurtis.Dunham@arm.com // End Of Interrupt Register 1 90711502SCurtis.Dunham@arm.com case MISCREG_ICC_EOIR1: 90811502SCurtis.Dunham@arm.com case MISCREG_ICC_EOIR1_EL1: { 90910827Sandreas.hansson@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 91010827Sandreas.hansson@arm.com return setMiscReg(MISCREG_ICV_EOIR1_EL1, val); 91110827Sandreas.hansson@arm.com } 91210827Sandreas.hansson@arm.com 91311502SCurtis.Dunham@arm.com int int_id = val & 0xffffff; 91411502SCurtis.Dunham@arm.com 91511502SCurtis.Dunham@arm.com // avoid deactivation for special interrupts 91611502SCurtis.Dunham@arm.com if (int_id >= Gicv3::INTID_SECURE && 91711502SCurtis.Dunham@arm.com int_id <= Gicv3::INTID_SPURIOUS) { 91811502SCurtis.Dunham@arm.com return; 91911502SCurtis.Dunham@arm.com } 92011502SCurtis.Dunham@arm.com 92111502SCurtis.Dunham@arm.com Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS; 92211502SCurtis.Dunham@arm.com 92311502SCurtis.Dunham@arm.com if (highestActiveGroup() == Gicv3::G0S) { 92411502SCurtis.Dunham@arm.com return; 92511502SCurtis.Dunham@arm.com } 92611502SCurtis.Dunham@arm.com 92711502SCurtis.Dunham@arm.com if (distributor->DS == 0) { 92811502SCurtis.Dunham@arm.com if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) { 92911502SCurtis.Dunham@arm.com return; 93011502SCurtis.Dunham@arm.com } else if (highestActiveGroup() == Gicv3::G1NS && 93111502SCurtis.Dunham@arm.com !(!inSecureState() or (currEL() == EL3))) { 93211502SCurtis.Dunham@arm.com return; 93311502SCurtis.Dunham@arm.com } 93411502SCurtis.Dunham@arm.com } 93511502SCurtis.Dunham@arm.com 93611502SCurtis.Dunham@arm.com dropPriority(group); 93711502SCurtis.Dunham@arm.com 93811502SCurtis.Dunham@arm.com if (!isEOISplitMode()) { 93911502SCurtis.Dunham@arm.com deactivateIRQ(int_id, group); 94011502SCurtis.Dunham@arm.com } 94111502SCurtis.Dunham@arm.com 94210628SN/A break; 94310628SN/A } 94411502SCurtis.Dunham@arm.com 94511502SCurtis.Dunham@arm.com // Virtual End Of Interrupt Register 1 94611502SCurtis.Dunham@arm.com case MISCREG_ICV_EOIR1_EL1: { 94711502SCurtis.Dunham@arm.com int int_id = val & 0xffffff; 94811502SCurtis.Dunham@arm.com 94911502SCurtis.Dunham@arm.com // avoid deactivation for special interrupts 95011502SCurtis.Dunham@arm.com if (int_id >= Gicv3::INTID_SECURE && 95111502SCurtis.Dunham@arm.com int_id <= Gicv3::INTID_SPURIOUS) { 95211502SCurtis.Dunham@arm.com return; 95311502SCurtis.Dunham@arm.com } 95411502SCurtis.Dunham@arm.com 95511502SCurtis.Dunham@arm.com uint8_t drop_prio = virtualDropPriority(); 95611502SCurtis.Dunham@arm.com 95711502SCurtis.Dunham@arm.com if (drop_prio == 0xff) { 95811502SCurtis.Dunham@arm.com return; 95911502SCurtis.Dunham@arm.com } 96011502SCurtis.Dunham@arm.com 96111502SCurtis.Dunham@arm.com int lr_idx = virtualFindActive(int_id); 96211502SCurtis.Dunham@arm.com 96311502SCurtis.Dunham@arm.com if (lr_idx < 0) { 96411502SCurtis.Dunham@arm.com // No matching LR found 96511502SCurtis.Dunham@arm.com virtualIncrementEOICount(); 96611502SCurtis.Dunham@arm.com } else { 96711502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 96811502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 96911502SCurtis.Dunham@arm.com Gicv3::GroupId lr_group = 97011502SCurtis.Dunham@arm.com ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; 97111502SCurtis.Dunham@arm.com uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8; 97211502SCurtis.Dunham@arm.com 97311502SCurtis.Dunham@arm.com if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) { 97411502SCurtis.Dunham@arm.com if (!virtualIsEOISplitMode()) { 97511502SCurtis.Dunham@arm.com virtualDeactivateIRQ(lr_idx); 97611502SCurtis.Dunham@arm.com } 97711502SCurtis.Dunham@arm.com } 97811502SCurtis.Dunham@arm.com } 97911502SCurtis.Dunham@arm.com 98011502SCurtis.Dunham@arm.com virtualUpdate(); 98111502SCurtis.Dunham@arm.com break; 98211502SCurtis.Dunham@arm.com } 98311502SCurtis.Dunham@arm.com 98411502SCurtis.Dunham@arm.com // Deactivate Interrupt Register 98511502SCurtis.Dunham@arm.com case MISCREG_ICC_DIR: 98611502SCurtis.Dunham@arm.com case MISCREG_ICC_DIR_EL1: { 98711502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && 98811502SCurtis.Dunham@arm.com (hcr_imo || hcr_fmo)) { 98911502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_DIR_EL1, val); 99011502SCurtis.Dunham@arm.com } 99111502SCurtis.Dunham@arm.com 99211502SCurtis.Dunham@arm.com int int_id = val & 0xffffff; 99311502SCurtis.Dunham@arm.com 99411502SCurtis.Dunham@arm.com // The following checks are as per spec pseudocode 99511502SCurtis.Dunham@arm.com // aarch64/support/ICC_DIR_EL1 99611502SCurtis.Dunham@arm.com 99711502SCurtis.Dunham@arm.com // Check for spurious ID 99811502SCurtis.Dunham@arm.com if (int_id >= Gicv3::INTID_SECURE) { 99911502SCurtis.Dunham@arm.com return; 100011502SCurtis.Dunham@arm.com } 100111502SCurtis.Dunham@arm.com 100211502SCurtis.Dunham@arm.com // EOI mode is not set, so don't deactivate 100311502SCurtis.Dunham@arm.com if (!isEOISplitMode()) { 100411502SCurtis.Dunham@arm.com return; 100511502SCurtis.Dunham@arm.com } 100611502SCurtis.Dunham@arm.com 100711502SCurtis.Dunham@arm.com Gicv3::GroupId group = 100811502SCurtis.Dunham@arm.com int_id >= 32 ? distributor->getIntGroup(int_id) : 100911502SCurtis.Dunham@arm.com redistributor->getIntGroup(int_id); 101011502SCurtis.Dunham@arm.com bool irq_is_grp0 = group == Gicv3::G0S; 101111502SCurtis.Dunham@arm.com bool single_sec_state = distributor->DS; 101211502SCurtis.Dunham@arm.com bool irq_is_secure = !single_sec_state && (group != Gicv3::G1NS); 101311502SCurtis.Dunham@arm.com SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); 101411502SCurtis.Dunham@arm.com bool route_fiq_to_el3 = scr_el3.fiq; 101511502SCurtis.Dunham@arm.com bool route_irq_to_el3 = scr_el3.irq; 101611502SCurtis.Dunham@arm.com bool route_fiq_to_el2 = hcr_fmo; 101711502SCurtis.Dunham@arm.com bool route_irq_to_el2 = hcr_imo; 101811502SCurtis.Dunham@arm.com 101911502SCurtis.Dunham@arm.com switch (currEL()) { 102011502SCurtis.Dunham@arm.com case EL3: 102111502SCurtis.Dunham@arm.com break; 102211502SCurtis.Dunham@arm.com 102311502SCurtis.Dunham@arm.com case EL2: 102411502SCurtis.Dunham@arm.com if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) { 102511502SCurtis.Dunham@arm.com break; 102611502SCurtis.Dunham@arm.com } 102711502SCurtis.Dunham@arm.com 102811502SCurtis.Dunham@arm.com if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) { 102911502SCurtis.Dunham@arm.com break; 103011502SCurtis.Dunham@arm.com } 103111502SCurtis.Dunham@arm.com 103211502SCurtis.Dunham@arm.com return; 103311502SCurtis.Dunham@arm.com 103411502SCurtis.Dunham@arm.com case EL1: 103511502SCurtis.Dunham@arm.com if (!isSecureBelowEL3()) { 103611502SCurtis.Dunham@arm.com if (single_sec_state && irq_is_grp0 && 103711502SCurtis.Dunham@arm.com !route_fiq_to_el3 && !route_fiq_to_el2) { 103811502SCurtis.Dunham@arm.com break; 103911502SCurtis.Dunham@arm.com } 104011502SCurtis.Dunham@arm.com 104111502SCurtis.Dunham@arm.com if (!irq_is_secure && !irq_is_grp0 && 104211502SCurtis.Dunham@arm.com !route_irq_to_el3 && !route_irq_to_el2) { 104311502SCurtis.Dunham@arm.com break; 104411502SCurtis.Dunham@arm.com } 104511502SCurtis.Dunham@arm.com } else { 104611502SCurtis.Dunham@arm.com if (irq_is_grp0 && !route_fiq_to_el3) { 104711502SCurtis.Dunham@arm.com break; 104811502SCurtis.Dunham@arm.com } 104911502SCurtis.Dunham@arm.com 105011502SCurtis.Dunham@arm.com if (!irq_is_grp0 && 105111502SCurtis.Dunham@arm.com (!irq_is_secure || !single_sec_state) && 105211502SCurtis.Dunham@arm.com !route_irq_to_el3) { 105311502SCurtis.Dunham@arm.com break; 105411502SCurtis.Dunham@arm.com } 105511502SCurtis.Dunham@arm.com } 105611502SCurtis.Dunham@arm.com 105711502SCurtis.Dunham@arm.com return; 105811502SCurtis.Dunham@arm.com 105911502SCurtis.Dunham@arm.com default: 106011502SCurtis.Dunham@arm.com break; 106111502SCurtis.Dunham@arm.com } 106211502SCurtis.Dunham@arm.com 106311502SCurtis.Dunham@arm.com deactivateIRQ(int_id, group); 106411502SCurtis.Dunham@arm.com break; 106511502SCurtis.Dunham@arm.com } 106611502SCurtis.Dunham@arm.com 106711502SCurtis.Dunham@arm.com // Deactivate Virtual Interrupt Register 106811502SCurtis.Dunham@arm.com case MISCREG_ICV_DIR_EL1: { 106911502SCurtis.Dunham@arm.com int int_id = val & 0xffffff; 107011502SCurtis.Dunham@arm.com 107111502SCurtis.Dunham@arm.com // avoid deactivation for special interrupts 107211502SCurtis.Dunham@arm.com if (int_id >= Gicv3::INTID_SECURE && 107311502SCurtis.Dunham@arm.com int_id <= Gicv3::INTID_SPURIOUS) { 107411502SCurtis.Dunham@arm.com return; 107511502SCurtis.Dunham@arm.com } 107611502SCurtis.Dunham@arm.com 107711502SCurtis.Dunham@arm.com if (!virtualIsEOISplitMode()) { 107811502SCurtis.Dunham@arm.com return; 107911502SCurtis.Dunham@arm.com } 108011502SCurtis.Dunham@arm.com 108111502SCurtis.Dunham@arm.com int lr_idx = virtualFindActive(int_id); 108211502SCurtis.Dunham@arm.com 108311502SCurtis.Dunham@arm.com if (lr_idx < 0) { 108411502SCurtis.Dunham@arm.com // No matching LR found 108511502SCurtis.Dunham@arm.com virtualIncrementEOICount(); 108611502SCurtis.Dunham@arm.com } else { 108711502SCurtis.Dunham@arm.com virtualDeactivateIRQ(lr_idx); 108811502SCurtis.Dunham@arm.com } 108911502SCurtis.Dunham@arm.com 109011502SCurtis.Dunham@arm.com virtualUpdate(); 109111502SCurtis.Dunham@arm.com break; 109211502SCurtis.Dunham@arm.com } 109311502SCurtis.Dunham@arm.com 109411502SCurtis.Dunham@arm.com // Binary Point Register 0 109511502SCurtis.Dunham@arm.com case MISCREG_ICC_BPR0: 109611502SCurtis.Dunham@arm.com case MISCREG_ICC_BPR0_EL1: 109711201Sandreas.hansson@arm.com // Binary Point Register 1 109811201Sandreas.hansson@arm.com case MISCREG_ICC_BPR1: 109910535SN/A case MISCREG_ICC_BPR1_EL1: { 110010535SN/A if ((currEL() == EL1) && !inSecureState()) { 110111502SCurtis.Dunham@arm.com if (misc_reg == MISCREG_ICC_BPR0_EL1 && hcr_fmo) { 110211502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_BPR0_EL1, val); 110311502SCurtis.Dunham@arm.com } else if (misc_reg == MISCREG_ICC_BPR1_EL1 && hcr_imo) { 110411502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_BPR1_EL1, val); 110511502SCurtis.Dunham@arm.com } 110611502SCurtis.Dunham@arm.com } 110711502SCurtis.Dunham@arm.com 110811502SCurtis.Dunham@arm.com Gicv3::GroupId group = 110911502SCurtis.Dunham@arm.com misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; 111011502SCurtis.Dunham@arm.com 111111502SCurtis.Dunham@arm.com if (group == Gicv3::G1S && !inSecureState()) { 111211502SCurtis.Dunham@arm.com group = Gicv3::G1NS; 111311502SCurtis.Dunham@arm.com } 111411502SCurtis.Dunham@arm.com 111511502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_s = 111611502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); 111711502SCurtis.Dunham@arm.com 111811502SCurtis.Dunham@arm.com if ((group == Gicv3::G1S) && !isEL3OrMon() && 111911502SCurtis.Dunham@arm.com icc_ctlr_el1_s.CBPR) { 112011502SCurtis.Dunham@arm.com group = Gicv3::G0S; 112111502SCurtis.Dunham@arm.com } 112211502SCurtis.Dunham@arm.com 112311502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_ns = 112411502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); 112511502SCurtis.Dunham@arm.com 112611502SCurtis.Dunham@arm.com if ((group == Gicv3::G1NS) && (currEL() < EL3) && 112711502SCurtis.Dunham@arm.com icc_ctlr_el1_ns.CBPR) { 112811502SCurtis.Dunham@arm.com // BPR0 + 1 saturated to 7, WI 112911502SCurtis.Dunham@arm.com return; 113011502SCurtis.Dunham@arm.com } 113111502SCurtis.Dunham@arm.com 113211502SCurtis.Dunham@arm.com uint8_t min_val = (group == Gicv3::G1NS) ? 113311502SCurtis.Dunham@arm.com GIC_MIN_BPR_NS : GIC_MIN_BPR; 113411502SCurtis.Dunham@arm.com val &= 0x7; 113511502SCurtis.Dunham@arm.com 113611502SCurtis.Dunham@arm.com if (val < min_val) { 113711502SCurtis.Dunham@arm.com val = min_val; 113811502SCurtis.Dunham@arm.com } 113911502SCurtis.Dunham@arm.com 114011502SCurtis.Dunham@arm.com break; 114111502SCurtis.Dunham@arm.com } 114211502SCurtis.Dunham@arm.com 114311502SCurtis.Dunham@arm.com // Virtual Binary Point Register 0 114411502SCurtis.Dunham@arm.com case MISCREG_ICV_BPR0_EL1: 114511502SCurtis.Dunham@arm.com // Virtual Binary Point Register 1 114610628SN/A case MISCREG_ICV_BPR1_EL1: { 114710535SN/A Gicv3::GroupId group = 114810628SN/A misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS; 114910535SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 115010628SN/A isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 115110535SN/A 115211502SCurtis.Dunham@arm.com if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { 115311502SCurtis.Dunham@arm.com // BPR0 + 1 saturated to 7, WI 115411502SCurtis.Dunham@arm.com return; 115511502SCurtis.Dunham@arm.com } 115611502SCurtis.Dunham@arm.com 115711502SCurtis.Dunham@arm.com uint8_t min_VPBR = 7 - VIRTUAL_PREEMPTION_BITS; 115811502SCurtis.Dunham@arm.com 115911502SCurtis.Dunham@arm.com if (group != Gicv3::G0S) { 116011502SCurtis.Dunham@arm.com min_VPBR++; 116111502SCurtis.Dunham@arm.com } 116211502SCurtis.Dunham@arm.com 116311502SCurtis.Dunham@arm.com if (val < min_VPBR) { 116411502SCurtis.Dunham@arm.com val = min_VPBR; 116511502SCurtis.Dunham@arm.com } 116611502SCurtis.Dunham@arm.com 116711502SCurtis.Dunham@arm.com if (group == Gicv3::G0S) { 116811502SCurtis.Dunham@arm.com ich_vmcr_el2.VBPR0 = val; 116911502SCurtis.Dunham@arm.com } else { 117011502SCurtis.Dunham@arm.com ich_vmcr_el2.VBPR1 = val; 117111502SCurtis.Dunham@arm.com } 117211502SCurtis.Dunham@arm.com 117311502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 117411502SCurtis.Dunham@arm.com do_virtual_update = true; 117511502SCurtis.Dunham@arm.com break; 117611502SCurtis.Dunham@arm.com } 117711502SCurtis.Dunham@arm.com 117811502SCurtis.Dunham@arm.com // Control Register EL1 117911502SCurtis.Dunham@arm.com case MISCREG_ICC_CTLR: 118011502SCurtis.Dunham@arm.com case MISCREG_ICC_CTLR_EL1: { 118111502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { 118211502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_CTLR_EL1, val); 118311502SCurtis.Dunham@arm.com } 118411502SCurtis.Dunham@arm.com 118511502SCurtis.Dunham@arm.com /* 118611502SCurtis.Dunham@arm.com * ExtRange is RO. 118711502SCurtis.Dunham@arm.com * RSS is RO. 118811502SCurtis.Dunham@arm.com * A3V is RO. 118911502SCurtis.Dunham@arm.com * SEIS is RO. 119011502SCurtis.Dunham@arm.com * IDbits is RO. 119111502SCurtis.Dunham@arm.com * PRIbits is RO. 119211502SCurtis.Dunham@arm.com */ 119310827Sandreas.hansson@arm.com ICC_CTLR_EL1 requested_icc_ctlr_el1 = val; 119411502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1 = 119511502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1); 119611502SCurtis.Dunham@arm.com 119711502SCurtis.Dunham@arm.com ICC_CTLR_EL3 icc_ctlr_el3 = 119810827Sandreas.hansson@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); 119911502SCurtis.Dunham@arm.com 120011502SCurtis.Dunham@arm.com // The following could be refactored but it is following 120111502SCurtis.Dunham@arm.com // spec description section 9.2.6 point by point. 120211502SCurtis.Dunham@arm.com 120311502SCurtis.Dunham@arm.com // PMHE 120411502SCurtis.Dunham@arm.com if (haveEL(EL3)) { 120511502SCurtis.Dunham@arm.com // PMHE is alias of ICC_CTLR_EL3.PMHE 120611502SCurtis.Dunham@arm.com 120711502SCurtis.Dunham@arm.com if (distributor->DS == 0) { 120811502SCurtis.Dunham@arm.com // PMHE is RO 120911502SCurtis.Dunham@arm.com } else if (distributor->DS == 1) { 121011502SCurtis.Dunham@arm.com // PMHE is RW 121111502SCurtis.Dunham@arm.com icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE; 121211502SCurtis.Dunham@arm.com icc_ctlr_el3.PMHE = icc_ctlr_el1.PMHE; 121311502SCurtis.Dunham@arm.com } 121411502SCurtis.Dunham@arm.com } else { 121511502SCurtis.Dunham@arm.com // PMHE is RW (by implementation choice) 121611502SCurtis.Dunham@arm.com icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE; 121711502SCurtis.Dunham@arm.com } 121811502SCurtis.Dunham@arm.com 121911502SCurtis.Dunham@arm.com // EOImode 122011502SCurtis.Dunham@arm.com icc_ctlr_el1.EOImode = requested_icc_ctlr_el1.EOImode; 122111502SCurtis.Dunham@arm.com 122211502SCurtis.Dunham@arm.com if (inSecureState()) { 122311502SCurtis.Dunham@arm.com // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1S 122411502SCurtis.Dunham@arm.com icc_ctlr_el3.EOImode_EL1S = icc_ctlr_el1.EOImode; 122511502SCurtis.Dunham@arm.com } else { 122611502SCurtis.Dunham@arm.com // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1NS 122711502SCurtis.Dunham@arm.com icc_ctlr_el3.EOImode_EL1NS = icc_ctlr_el1.EOImode; 122811502SCurtis.Dunham@arm.com } 122911502SCurtis.Dunham@arm.com 123011502SCurtis.Dunham@arm.com // CBPR 123111502SCurtis.Dunham@arm.com if (haveEL(EL3)) { 123211502SCurtis.Dunham@arm.com // CBPR is alias of ICC_CTLR_EL3.CBPR_EL1{S,NS} 123311502SCurtis.Dunham@arm.com 123411502SCurtis.Dunham@arm.com if (distributor->DS == 0) { 123511502SCurtis.Dunham@arm.com // CBPR is RO 123611502SCurtis.Dunham@arm.com } else { 123711502SCurtis.Dunham@arm.com // CBPR is RW 123811502SCurtis.Dunham@arm.com icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR; 123911502SCurtis.Dunham@arm.com 124010535SN/A if (inSecureState()) { 124110535SN/A icc_ctlr_el3.CBPR_EL1S = icc_ctlr_el1.CBPR; 124211502SCurtis.Dunham@arm.com } else { 124311502SCurtis.Dunham@arm.com icc_ctlr_el3.CBPR_EL1NS = icc_ctlr_el1.CBPR; 124411201Sandreas.hansson@arm.com } 124511201Sandreas.hansson@arm.com } 124610535SN/A } else { 124710535SN/A // CBPR is RW 124811502SCurtis.Dunham@arm.com icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR; 124911502SCurtis.Dunham@arm.com } 125011502SCurtis.Dunham@arm.com 125111502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL3, icc_ctlr_el3); 125211502SCurtis.Dunham@arm.com 125311502SCurtis.Dunham@arm.com val = icc_ctlr_el1; 125411502SCurtis.Dunham@arm.com break; 125511502SCurtis.Dunham@arm.com } 125611502SCurtis.Dunham@arm.com 125711502SCurtis.Dunham@arm.com // Virtual Control Register 125811502SCurtis.Dunham@arm.com case MISCREG_ICV_CTLR_EL1: { 125911502SCurtis.Dunham@arm.com ICV_CTLR_EL1 requested_icv_ctlr_el1 = val; 126011502SCurtis.Dunham@arm.com ICV_CTLR_EL1 icv_ctlr_el1 = 126111502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICV_CTLR_EL1); 126211502SCurtis.Dunham@arm.com icv_ctlr_el1.EOImode = requested_icv_ctlr_el1.EOImode; 126311502SCurtis.Dunham@arm.com icv_ctlr_el1.CBPR = requested_icv_ctlr_el1.CBPR; 126411502SCurtis.Dunham@arm.com val = icv_ctlr_el1; 126510535SN/A 126611502SCurtis.Dunham@arm.com // Aliases 126711502SCurtis.Dunham@arm.com // ICV_CTLR_EL1.CBPR aliases ICH_VMCR_EL2.VCBPR. 126811502SCurtis.Dunham@arm.com // ICV_CTLR_EL1.EOImode aliases ICH_VMCR_EL2.VEOIM. 126911502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = 127011502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 127111502SCurtis.Dunham@arm.com ich_vmcr_el2.VCBPR = icv_ctlr_el1.CBPR; 127211502SCurtis.Dunham@arm.com ich_vmcr_el2.VEOIM = icv_ctlr_el1.EOImode; 127311502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 127411502SCurtis.Dunham@arm.com break; 127511502SCurtis.Dunham@arm.com } 127611502SCurtis.Dunham@arm.com 127711502SCurtis.Dunham@arm.com // Control Register EL3 127811502SCurtis.Dunham@arm.com case MISCREG_ICC_MCTLR: 127911502SCurtis.Dunham@arm.com case MISCREG_ICC_CTLR_EL3: { 128011502SCurtis.Dunham@arm.com /* 128111502SCurtis.Dunham@arm.com * ExtRange is RO. 128211502SCurtis.Dunham@arm.com * RSS is RO. 128311502SCurtis.Dunham@arm.com * nDS is RO. 128411502SCurtis.Dunham@arm.com * A3V is RO. 128511502SCurtis.Dunham@arm.com * SEIS is RO. 128611502SCurtis.Dunham@arm.com * IDbits is RO. 128711502SCurtis.Dunham@arm.com * PRIbits is RO. 128811502SCurtis.Dunham@arm.com * PMHE is RAO/WI, priority-based routing is always used. 128911502SCurtis.Dunham@arm.com */ 129011502SCurtis.Dunham@arm.com ICC_CTLR_EL3 requested_icc_ctlr_el3 = val; 129111502SCurtis.Dunham@arm.com 129211502SCurtis.Dunham@arm.com // Aliases 129311502SCurtis.Dunham@arm.com if (haveEL(EL3)) 129411502SCurtis.Dunham@arm.com { 129511502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_s = 129611502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); 129711502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_ns = 129811502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); 129911502SCurtis.Dunham@arm.com 130011502SCurtis.Dunham@arm.com // ICC_CTLR_EL1(NS).EOImode is an alias of 130111502SCurtis.Dunham@arm.com // ICC_CTLR_EL3.EOImode_EL1NS 130211502SCurtis.Dunham@arm.com icc_ctlr_el1_ns.EOImode = requested_icc_ctlr_el3.EOImode_EL1NS; 130311502SCurtis.Dunham@arm.com // ICC_CTLR_EL1(S).EOImode is an alias of 130411502SCurtis.Dunham@arm.com // ICC_CTLR_EL3.EOImode_EL1S 130511502SCurtis.Dunham@arm.com icc_ctlr_el1_s.EOImode = requested_icc_ctlr_el3.EOImode_EL1S; 130611502SCurtis.Dunham@arm.com // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS 130711502SCurtis.Dunham@arm.com icc_ctlr_el1_ns.CBPR = requested_icc_ctlr_el3.CBPR_EL1NS; 130811502SCurtis.Dunham@arm.com // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S 130911502SCurtis.Dunham@arm.com icc_ctlr_el1_s.CBPR = requested_icc_ctlr_el3.CBPR_EL1S; 131011502SCurtis.Dunham@arm.com 131111502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s); 131211502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS, 131311502SCurtis.Dunham@arm.com icc_ctlr_el1_ns); 131411502SCurtis.Dunham@arm.com } 131511502SCurtis.Dunham@arm.com 131611502SCurtis.Dunham@arm.com ICC_CTLR_EL3 icc_ctlr_el3 = 131711502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); 131811502SCurtis.Dunham@arm.com 131911502SCurtis.Dunham@arm.com icc_ctlr_el3.RM = requested_icc_ctlr_el3.RM; 132011502SCurtis.Dunham@arm.com icc_ctlr_el3.EOImode_EL1NS = requested_icc_ctlr_el3.EOImode_EL1NS; 132111502SCurtis.Dunham@arm.com icc_ctlr_el3.EOImode_EL1S = requested_icc_ctlr_el3.EOImode_EL1S; 132211502SCurtis.Dunham@arm.com icc_ctlr_el3.EOImode_EL3 = requested_icc_ctlr_el3.EOImode_EL3; 132311502SCurtis.Dunham@arm.com icc_ctlr_el3.CBPR_EL1NS = requested_icc_ctlr_el3.CBPR_EL1NS; 132411502SCurtis.Dunham@arm.com icc_ctlr_el3.CBPR_EL1S = requested_icc_ctlr_el3.CBPR_EL1S; 132511502SCurtis.Dunham@arm.com 132611502SCurtis.Dunham@arm.com val = icc_ctlr_el3; 132711502SCurtis.Dunham@arm.com break; 132811502SCurtis.Dunham@arm.com } 132911502SCurtis.Dunham@arm.com 133011502SCurtis.Dunham@arm.com // Priority Mask Register 133111502SCurtis.Dunham@arm.com case MISCREG_ICC_PMR: 133211502SCurtis.Dunham@arm.com case MISCREG_ICC_PMR_EL1: { 133311502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) { 133411502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_PMR_EL1, val); 133511502SCurtis.Dunham@arm.com } 133611502SCurtis.Dunham@arm.com 133711502SCurtis.Dunham@arm.com val &= 0xff; 133811502SCurtis.Dunham@arm.com SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); 133911502SCurtis.Dunham@arm.com 134011502SCurtis.Dunham@arm.com if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) { 134111502SCurtis.Dunham@arm.com // Spec section 4.8.1 134210535SN/A // For Non-secure access to ICC_PMR_EL1 SCR_EL3.FIQ == 1: 134311502SCurtis.Dunham@arm.com RegVal old_icc_pmr_el1 = 134411502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1); 134511502SCurtis.Dunham@arm.com 134610535SN/A if (!(old_icc_pmr_el1 & 0x80)) { 134711138Sandreas.hansson@arm.com // If the current priority mask value is in the range of 134810827Sandreas.hansson@arm.com // 0x00-0x7F then WI 134911502SCurtis.Dunham@arm.com return; 135011502SCurtis.Dunham@arm.com } 135110535SN/A 135211502SCurtis.Dunham@arm.com // If the current priority mask value is in the range of 135310535SN/A // 0x80-0xFF then a write access to ICC_PMR_EL1 succeeds, 135411502SCurtis.Dunham@arm.com // based on the Non-secure read of the priority mask value 135510535SN/A // written to the register. 135611502SCurtis.Dunham@arm.com 135710535SN/A val = (val >> 1) | 0x80; 135811502SCurtis.Dunham@arm.com } 135910535SN/A 136011502SCurtis.Dunham@arm.com val &= ~0U << (8 - PRIORITY_BITS); 136110535SN/A break; 136210628SN/A } 136310628SN/A 136410628SN/A case MISCREG_ICV_PMR_EL1: { // Priority Mask Register 136510628SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 136610628SN/A isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 136710628SN/A ich_vmcr_el2.VPMR = val & 0xff; 136810628SN/A 136910628SN/A isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 137010535SN/A virtualUpdate(); 137110535SN/A return; 137210535SN/A } 137310535SN/A 137410535SN/A // Interrupt Group 0 Enable Register EL1 137510535SN/A case MISCREG_ICC_IGRPEN0: 137610535SN/A case MISCREG_ICC_IGRPEN0_EL1: { 137710535SN/A if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 137810535SN/A return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val); 137910535SN/A } 138010535SN/A 138110535SN/A break; 138210535SN/A } 138310535SN/A 138410535SN/A // Virtual Interrupt Group 0 Enable register 138510535SN/A case MISCREG_ICV_IGRPEN0_EL1: { 138610535SN/A bool enable = val & 0x1; 138710535SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 138810535SN/A isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 138910535SN/A ich_vmcr_el2.VENG0 = enable; 139010535SN/A isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 139111502SCurtis.Dunham@arm.com virtualUpdate(); 139211502SCurtis.Dunham@arm.com return; 139311502SCurtis.Dunham@arm.com } 139411502SCurtis.Dunham@arm.com 139511502SCurtis.Dunham@arm.com // Interrupt Group 1 Enable register EL1 139611502SCurtis.Dunham@arm.com case MISCREG_ICC_IGRPEN1: 139711502SCurtis.Dunham@arm.com case MISCREG_ICC_IGRPEN1_EL1: { 139811502SCurtis.Dunham@arm.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 139911502SCurtis.Dunham@arm.com return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val); 140011353Sandreas.hansson@arm.com } 140111502SCurtis.Dunham@arm.com 140211502SCurtis.Dunham@arm.com if (haveEL(EL3)) { 140311502SCurtis.Dunham@arm.com ICC_IGRPEN1_EL1 icc_igrpen1_el1 = val; 140411502SCurtis.Dunham@arm.com ICC_IGRPEN1_EL3 icc_igrpen1_el3 = 140511502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3); 140611502SCurtis.Dunham@arm.com 140711502SCurtis.Dunham@arm.com if (inSecureState()) { 140811502SCurtis.Dunham@arm.com // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1S 140911502SCurtis.Dunham@arm.com icc_igrpen1_el3.EnableGrp1S = icc_igrpen1_el1.Enable; 141011502SCurtis.Dunham@arm.com } else { 141111502SCurtis.Dunham@arm.com // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1NS 141211502SCurtis.Dunham@arm.com icc_igrpen1_el3.EnableGrp1NS = icc_igrpen1_el1.Enable; 141311502SCurtis.Dunham@arm.com } 141411502SCurtis.Dunham@arm.com 141511502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3, 141611502SCurtis.Dunham@arm.com icc_igrpen1_el3); 141711502SCurtis.Dunham@arm.com } 141811502SCurtis.Dunham@arm.com 141911502SCurtis.Dunham@arm.com break; 142011502SCurtis.Dunham@arm.com } 142111502SCurtis.Dunham@arm.com 142211502SCurtis.Dunham@arm.com // Virtual Interrupt Group 1 Enable register 142311502SCurtis.Dunham@arm.com case MISCREG_ICV_IGRPEN1_EL1: { 142411502SCurtis.Dunham@arm.com bool enable = val & 0x1; 142510628SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 142611502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 142711502SCurtis.Dunham@arm.com ich_vmcr_el2.VENG1 = enable; 142810628SN/A isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 142911502SCurtis.Dunham@arm.com virtualUpdate(); 143011502SCurtis.Dunham@arm.com return; 143110535SN/A } 143210535SN/A 143311502SCurtis.Dunham@arm.com // Interrupt Group 1 Enable register 143411502SCurtis.Dunham@arm.com case MISCREG_ICC_MGRPEN1: 143511502SCurtis.Dunham@arm.com case MISCREG_ICC_IGRPEN1_EL3: { 143611502SCurtis.Dunham@arm.com ICC_IGRPEN1_EL3 icc_igrpen1_el3 = val; 143710535SN/A ICC_IGRPEN1_EL1 icc_igrpen1_el1 = 143810535SN/A isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1); 143911502SCurtis.Dunham@arm.com 144011502SCurtis.Dunham@arm.com if (inSecureState()) { 144111502SCurtis.Dunham@arm.com // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1S 144210535SN/A icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1S; 144311502SCurtis.Dunham@arm.com } else { 144410535SN/A // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1NS 144511502SCurtis.Dunham@arm.com icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1NS; 144611502SCurtis.Dunham@arm.com } 144711502SCurtis.Dunham@arm.com 144810535SN/A isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1, icc_igrpen1_el1); 144911502SCurtis.Dunham@arm.com break; 145011502SCurtis.Dunham@arm.com } 145111502SCurtis.Dunham@arm.com 145210628SN/A // Software Generated Interrupt Group 0 Register 145310628SN/A case MISCREG_ICC_SGI0R: 145410628SN/A case MISCREG_ICC_SGI0R_EL1: 145510628SN/A generateSGI(val, Gicv3::G0S); 145610628SN/A break; 145710628SN/A 145810628SN/A // Software Generated Interrupt Group 1 Register 145910628SN/A case MISCREG_ICC_SGI1R: 146010535SN/A case MISCREG_ICC_SGI1R_EL1: { 146110535SN/A Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS; 146210535SN/A 146310535SN/A generateSGI(val, group); 146410535SN/A break; 146510535SN/A } 146610535SN/A 146710535SN/A // Alias Software Generated Interrupt Group 1 Register 146810535SN/A case MISCREG_ICC_ASGI1R: 146910535SN/A case MISCREG_ICC_ASGI1R_EL1: { 147010535SN/A Gicv3::GroupId group = inSecureState() ? Gicv3::G1NS : Gicv3::G1S; 147110535SN/A 147210535SN/A generateSGI(val, group); 147310535SN/A break; 147410535SN/A } 147510535SN/A 147610535SN/A // System Register Enable Register EL1 147710535SN/A case MISCREG_ICC_SRE: 147810535SN/A case MISCREG_ICC_SRE_EL1: 147910535SN/A // System Register Enable Register EL2 148010535SN/A case MISCREG_ICC_HSRE: 148111502SCurtis.Dunham@arm.com case MISCREG_ICC_SRE_EL2: 148211502SCurtis.Dunham@arm.com // System Register Enable Register EL3 148311502SCurtis.Dunham@arm.com case MISCREG_ICC_MSRE: 148411502SCurtis.Dunham@arm.com case MISCREG_ICC_SRE_EL3: 148511502SCurtis.Dunham@arm.com // All bits are RAO/WI 148611502SCurtis.Dunham@arm.com return; 148711502SCurtis.Dunham@arm.com 148811502SCurtis.Dunham@arm.com // Hyp Control Register 148911502SCurtis.Dunham@arm.com case MISCREG_ICH_HCR: 149011502SCurtis.Dunham@arm.com case MISCREG_ICH_HCR_EL2: { 149111502SCurtis.Dunham@arm.com ICH_HCR_EL2 requested_ich_hcr_el2 = val; 149211502SCurtis.Dunham@arm.com ICH_HCR_EL2 ich_hcr_el2 = 149311502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 149411502SCurtis.Dunham@arm.com 149511502SCurtis.Dunham@arm.com if (requested_ich_hcr_el2.EOIcount >= ich_hcr_el2.EOIcount) 149611502SCurtis.Dunham@arm.com { 149711502SCurtis.Dunham@arm.com // EOIcount - Permitted behaviors are: 149811502SCurtis.Dunham@arm.com // - Increment EOIcount. 149911502SCurtis.Dunham@arm.com // - Leave EOIcount unchanged. 150011502SCurtis.Dunham@arm.com ich_hcr_el2.EOIcount = requested_ich_hcr_el2.EOIcount; 150111502SCurtis.Dunham@arm.com } 150211502SCurtis.Dunham@arm.com 150311502SCurtis.Dunham@arm.com ich_hcr_el2.TDIR = requested_ich_hcr_el2.TDIR; 150411502SCurtis.Dunham@arm.com ich_hcr_el2.TSEI = requested_ich_hcr_el2.TSEI; 150511502SCurtis.Dunham@arm.com ich_hcr_el2.TALL1 = requested_ich_hcr_el2.TALL1;; 150611502SCurtis.Dunham@arm.com ich_hcr_el2.TALL0 = requested_ich_hcr_el2.TALL0;; 150711502SCurtis.Dunham@arm.com ich_hcr_el2.TC = requested_ich_hcr_el2.TC; 150811502SCurtis.Dunham@arm.com ich_hcr_el2.VGrp1DIE = requested_ich_hcr_el2.VGrp1DIE; 150911502SCurtis.Dunham@arm.com ich_hcr_el2.VGrp1EIE = requested_ich_hcr_el2.VGrp1EIE; 151011502SCurtis.Dunham@arm.com ich_hcr_el2.VGrp0DIE = requested_ich_hcr_el2.VGrp0DIE; 151111502SCurtis.Dunham@arm.com ich_hcr_el2.VGrp0EIE = requested_ich_hcr_el2.VGrp0EIE; 151211502SCurtis.Dunham@arm.com ich_hcr_el2.NPIE = requested_ich_hcr_el2.NPIE; 151311502SCurtis.Dunham@arm.com ich_hcr_el2.LRENPIE = requested_ich_hcr_el2.LRENPIE; 151410628SN/A ich_hcr_el2.UIE = requested_ich_hcr_el2.UIE; 151511502SCurtis.Dunham@arm.com ich_hcr_el2.En = requested_ich_hcr_el2.En; 151611502SCurtis.Dunham@arm.com val = ich_hcr_el2; 151710628SN/A do_virtual_update = true; 151811502SCurtis.Dunham@arm.com break; 151911502SCurtis.Dunham@arm.com } 152011502SCurtis.Dunham@arm.com 152111502SCurtis.Dunham@arm.com // List Registers 152211502SCurtis.Dunham@arm.com case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: { 152310535SN/A // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part) 152410535SN/A ICH_LRC requested_ich_lrc = val; 152510535SN/A ICH_LRC ich_lrc = isa->readMiscRegNoEffect(misc_reg); 152610535SN/A 152710535SN/A ich_lrc.State = requested_ich_lrc.State; 152810535SN/A ich_lrc.HW = requested_ich_lrc.HW; 152911502SCurtis.Dunham@arm.com ich_lrc.Group = requested_ich_lrc.Group; 153011502SCurtis.Dunham@arm.com 153111502SCurtis.Dunham@arm.com // Priority, bits [23:16] 153210535SN/A // At least five bits must be implemented. 153310535SN/A // Unimplemented bits are RES0 and start from bit[16] up to bit[18]. 153410535SN/A // We implement 5 bits. 153510535SN/A ich_lrc.Priority = (requested_ich_lrc.Priority & 0xf8) | 153610535SN/A (ich_lrc.Priority & 0x07); 153710535SN/A 153811502SCurtis.Dunham@arm.com // pINTID, bits [12:0] 153911502SCurtis.Dunham@arm.com // When ICH_LR<n>.HW is 0 this field has the following meaning: 154011502SCurtis.Dunham@arm.com // - Bits[12:10] : RES0. 154111502SCurtis.Dunham@arm.com // - Bit[9] : EOI. 154211502SCurtis.Dunham@arm.com // - Bits[8:0] : RES0. 154310535SN/A // When ICH_LR<n>.HW is 1: 154410535SN/A // - This field is only required to implement enough bits to hold a 154511167Sjthestness@gmail.com // valid value for the implemented INTID size. Any unused higher 154611502SCurtis.Dunham@arm.com // order bits are RES0. 154711502SCurtis.Dunham@arm.com if (requested_ich_lrc.HW == 0) { 154811502SCurtis.Dunham@arm.com ich_lrc.EOI = requested_ich_lrc.EOI; 154911502SCurtis.Dunham@arm.com } else { 155011502SCurtis.Dunham@arm.com ich_lrc.pINTID = requested_ich_lrc.pINTID; 155111502SCurtis.Dunham@arm.com } 155211502SCurtis.Dunham@arm.com 155311502SCurtis.Dunham@arm.com val = ich_lrc; 155411502SCurtis.Dunham@arm.com do_virtual_update = true; 155511502SCurtis.Dunham@arm.com break; 155611502SCurtis.Dunham@arm.com } 155711502SCurtis.Dunham@arm.com 155811502SCurtis.Dunham@arm.com // List Registers 155911502SCurtis.Dunham@arm.com case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: { 156011502SCurtis.Dunham@arm.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part) 156111502SCurtis.Dunham@arm.com RegVal old_val = isa->readMiscRegNoEffect(misc_reg); 156211502SCurtis.Dunham@arm.com val = (old_val & 0xffffffff00000000) | (val & 0xffffffff); 156311502SCurtis.Dunham@arm.com do_virtual_update = true; 156411502SCurtis.Dunham@arm.com break; 156511502SCurtis.Dunham@arm.com } 156611502SCurtis.Dunham@arm.com 156711502SCurtis.Dunham@arm.com // List Registers 156811502SCurtis.Dunham@arm.com case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64 156911374Ssteve.reinhardt@amd.com ICH_LR_EL2 requested_ich_lr_el2 = val; 157011502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(misc_reg); 157111502SCurtis.Dunham@arm.com 157211502SCurtis.Dunham@arm.com ich_lr_el2.State = requested_ich_lr_el2.State; 157311502SCurtis.Dunham@arm.com ich_lr_el2.HW = requested_ich_lr_el2.HW; 157411502SCurtis.Dunham@arm.com ich_lr_el2.Group = requested_ich_lr_el2.Group; 157511502SCurtis.Dunham@arm.com 157611502SCurtis.Dunham@arm.com // Priority, bits [55:48] 157711502SCurtis.Dunham@arm.com // At least five bits must be implemented. 157811502SCurtis.Dunham@arm.com // Unimplemented bits are RES0 and start from bit[48] up to bit[50]. 157911502SCurtis.Dunham@arm.com // We implement 5 bits. 158011502SCurtis.Dunham@arm.com ich_lr_el2.Priority = (requested_ich_lr_el2.Priority & 0xf8) | 158111502SCurtis.Dunham@arm.com (ich_lr_el2.Priority & 0x07); 158211502SCurtis.Dunham@arm.com 158311502SCurtis.Dunham@arm.com // pINTID, bits [44:32] 158411502SCurtis.Dunham@arm.com // When ICH_LR<n>_EL2.HW is 0 this field has the following meaning: 158511502SCurtis.Dunham@arm.com // - Bits[44:42] : RES0. 158611502SCurtis.Dunham@arm.com // - Bit[41] : EOI. 158711502SCurtis.Dunham@arm.com // - Bits[40:32] : RES0. 158811502SCurtis.Dunham@arm.com // When ICH_LR<n>_EL2.HW is 1: 158911502SCurtis.Dunham@arm.com // - This field is only required to implement enough bits to hold a 159011502SCurtis.Dunham@arm.com // valid value for the implemented INTID size. Any unused higher 159111502SCurtis.Dunham@arm.com // order bits are RES0. 159211502SCurtis.Dunham@arm.com if (requested_ich_lr_el2.HW == 0) { 159311502SCurtis.Dunham@arm.com ich_lr_el2.EOI = requested_ich_lr_el2.EOI; 159411502SCurtis.Dunham@arm.com } else { 159511502SCurtis.Dunham@arm.com ich_lr_el2.pINTID = requested_ich_lr_el2.pINTID; 159611502SCurtis.Dunham@arm.com } 159711502SCurtis.Dunham@arm.com 159811502SCurtis.Dunham@arm.com // vINTID, bits [31:0] 159911502SCurtis.Dunham@arm.com // It is IMPLEMENTATION DEFINED how many bits are implemented, 160011502SCurtis.Dunham@arm.com // though at least 16 bits must be implemented. 160110535SN/A // Unimplemented bits are RES0. 160210535SN/A ich_lr_el2.vINTID = requested_ich_lr_el2.vINTID; 160311502SCurtis.Dunham@arm.com 160411502SCurtis.Dunham@arm.com val = ich_lr_el2; 160511502SCurtis.Dunham@arm.com do_virtual_update = true; 160611502SCurtis.Dunham@arm.com break; 160711502SCurtis.Dunham@arm.com } 160811502SCurtis.Dunham@arm.com 160911502SCurtis.Dunham@arm.com // Virtual Machine Control Register 161011502SCurtis.Dunham@arm.com case MISCREG_ICH_VMCR: 161111502SCurtis.Dunham@arm.com case MISCREG_ICH_VMCR_EL2: { 161211502SCurtis.Dunham@arm.com ICH_VMCR_EL2 requested_ich_vmcr_el2 = val; 161311502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = 161411502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 161511502SCurtis.Dunham@arm.com ich_vmcr_el2.VPMR = requested_ich_vmcr_el2.VPMR; 161611502SCurtis.Dunham@arm.com uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS; 161711502SCurtis.Dunham@arm.com 161811502SCurtis.Dunham@arm.com if (requested_ich_vmcr_el2.VBPR0 < min_vpr0) { 161911502SCurtis.Dunham@arm.com ich_vmcr_el2.VBPR0 = min_vpr0; 162011502SCurtis.Dunham@arm.com } else { 162111502SCurtis.Dunham@arm.com ich_vmcr_el2.VBPR0 = requested_ich_vmcr_el2.VBPR0; 162211502SCurtis.Dunham@arm.com } 162311502SCurtis.Dunham@arm.com 162411502SCurtis.Dunham@arm.com uint8_t min_vpr1 = min_vpr0 + 1; 162511502SCurtis.Dunham@arm.com 162611502SCurtis.Dunham@arm.com if (requested_ich_vmcr_el2.VBPR1 < min_vpr1) { 162711502SCurtis.Dunham@arm.com ich_vmcr_el2.VBPR1 = min_vpr1; 162811502SCurtis.Dunham@arm.com } else { 162911502SCurtis.Dunham@arm.com ich_vmcr_el2.VBPR1 = requested_ich_vmcr_el2.VBPR1; 163011502SCurtis.Dunham@arm.com } 163111502SCurtis.Dunham@arm.com 163211502SCurtis.Dunham@arm.com ich_vmcr_el2.VEOIM = requested_ich_vmcr_el2.VEOIM; 163311502SCurtis.Dunham@arm.com ich_vmcr_el2.VCBPR = requested_ich_vmcr_el2.VCBPR; 163411502SCurtis.Dunham@arm.com ich_vmcr_el2.VENG1 = requested_ich_vmcr_el2.VENG1; 163511502SCurtis.Dunham@arm.com ich_vmcr_el2.VENG0 = requested_ich_vmcr_el2.VENG0; 163611502SCurtis.Dunham@arm.com val = ich_vmcr_el2; 163711502SCurtis.Dunham@arm.com break; 163811502SCurtis.Dunham@arm.com } 163911502SCurtis.Dunham@arm.com 164011502SCurtis.Dunham@arm.com // Hyp Active Priorities Group 0 Registers 164111502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R0: 164211502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R0_EL2: 164311502SCurtis.Dunham@arm.com break; 164411502SCurtis.Dunham@arm.com 164511502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 164611502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R1: 164711502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R1_EL2: 164811502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 164911502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R2: 165011502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R2_EL2: 165111502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 165211502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R3: 165311502SCurtis.Dunham@arm.com case MISCREG_ICH_AP0R3_EL2: 165411502SCurtis.Dunham@arm.com // Unimplemented registers are RAZ/WI 165511502SCurtis.Dunham@arm.com return; 165611502SCurtis.Dunham@arm.com 165711502SCurtis.Dunham@arm.com // Hyp Active Priorities Group 1 Registers 165811502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R0: 165911502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R0_EL2: 166011502SCurtis.Dunham@arm.com break; 166111502SCurtis.Dunham@arm.com 166211502SCurtis.Dunham@arm.com // only implemented if supporting 6 or more bits of priority 166311502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R1: 166411502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R1_EL2: 166511502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 166611502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R2: 166711502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R2_EL2: 166811502SCurtis.Dunham@arm.com // only implemented if supporting 7 or more bits of priority 166911502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R3: 167011502SCurtis.Dunham@arm.com case MISCREG_ICH_AP1R3_EL2: 167111502SCurtis.Dunham@arm.com // Unimplemented registers are RAZ/WI 167211502SCurtis.Dunham@arm.com return; 167311502SCurtis.Dunham@arm.com 167411502SCurtis.Dunham@arm.com default: 167511502SCurtis.Dunham@arm.com panic("Gicv3CPUInterface::setMiscReg(): unknown register %d (%s)", 167611502SCurtis.Dunham@arm.com misc_reg, miscRegName[misc_reg]); 167711502SCurtis.Dunham@arm.com } 167811502SCurtis.Dunham@arm.com 167911502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(misc_reg, val); 168011502SCurtis.Dunham@arm.com 168111502SCurtis.Dunham@arm.com if (do_virtual_update) { 168211502SCurtis.Dunham@arm.com virtualUpdate(); 168311502SCurtis.Dunham@arm.com } 168411502SCurtis.Dunham@arm.com} 168511502SCurtis.Dunham@arm.com 168611502SCurtis.Dunham@arm.comint 168711502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualFindActive(uint32_t int_id) const 168811502SCurtis.Dunham@arm.com{ 168911502SCurtis.Dunham@arm.com for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 169011502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 169111502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 169211502SCurtis.Dunham@arm.com 169311502SCurtis.Dunham@arm.com if (((ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE) || 169411502SCurtis.Dunham@arm.com (ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE_PENDING)) && 169511502SCurtis.Dunham@arm.com (ich_lr_el2.vINTID == int_id)) { 169611502SCurtis.Dunham@arm.com return lr_idx; 169711502SCurtis.Dunham@arm.com } 169811502SCurtis.Dunham@arm.com } 169911502SCurtis.Dunham@arm.com 170011502SCurtis.Dunham@arm.com return -1; 170111502SCurtis.Dunham@arm.com} 170211502SCurtis.Dunham@arm.com 170311502SCurtis.Dunham@arm.comuint32_t 170411502SCurtis.Dunham@arm.comGicv3CPUInterface::getHPPIR0() const 170511502SCurtis.Dunham@arm.com{ 170611502SCurtis.Dunham@arm.com if (hppi.prio == 0xff || !groupEnabled(hppi.group)) { 170711502SCurtis.Dunham@arm.com return Gicv3::INTID_SPURIOUS; 170811502SCurtis.Dunham@arm.com } 170911502SCurtis.Dunham@arm.com 171011502SCurtis.Dunham@arm.com bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS; 171110535SN/A 171210535SN/A if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) { 171311502SCurtis.Dunham@arm.com // interrupt for the other state pending 171411502SCurtis.Dunham@arm.com return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE; 171511502SCurtis.Dunham@arm.com } 171611502SCurtis.Dunham@arm.com 171710535SN/A if ((hppi.group != Gicv3::G0S)) { // && !isEL3OrMon()) 171810535SN/A return Gicv3::INTID_SPURIOUS; 171910535SN/A } 172010535SN/A 172110535SN/A if (irq_is_secure && !inSecureState()) { 172210535SN/A // Secure interrupts not visible in Non-secure 172311502SCurtis.Dunham@arm.com return Gicv3::INTID_SPURIOUS; 172411502SCurtis.Dunham@arm.com } 172511502SCurtis.Dunham@arm.com 172611502SCurtis.Dunham@arm.com return hppi.intid; 172711502SCurtis.Dunham@arm.com} 172811502SCurtis.Dunham@arm.com 172911502SCurtis.Dunham@arm.comuint32_t 173011502SCurtis.Dunham@arm.comGicv3CPUInterface::getHPPIR1() const 173111502SCurtis.Dunham@arm.com{ 173211502SCurtis.Dunham@arm.com if (hppi.prio == 0xff || !groupEnabled(hppi.group)) { 173311502SCurtis.Dunham@arm.com return Gicv3::INTID_SPURIOUS; 173411502SCurtis.Dunham@arm.com } 173511502SCurtis.Dunham@arm.com 173611502SCurtis.Dunham@arm.com ICC_CTLR_EL3 icc_ctlr_el3 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); 173711502SCurtis.Dunham@arm.com if ((currEL() == EL3) && icc_ctlr_el3.RM) { 173811502SCurtis.Dunham@arm.com if (hppi.group == Gicv3::G0S) { 173911502SCurtis.Dunham@arm.com return Gicv3::INTID_SECURE; 174011502SCurtis.Dunham@arm.com } else if (hppi.group == Gicv3::G1NS) { 174111502SCurtis.Dunham@arm.com return Gicv3::INTID_NONSECURE; 174211502SCurtis.Dunham@arm.com } 174311374Ssteve.reinhardt@amd.com } 174411374Ssteve.reinhardt@amd.com 174511502SCurtis.Dunham@arm.com if (hppi.group == Gicv3::G0S) { 174611502SCurtis.Dunham@arm.com return Gicv3::INTID_SPURIOUS; 174711502SCurtis.Dunham@arm.com } 174811502SCurtis.Dunham@arm.com 174911502SCurtis.Dunham@arm.com bool irq_is_secure = (distributor->DS == 0) && (hppi.group != Gicv3::G1NS); 175011502SCurtis.Dunham@arm.com 175111502SCurtis.Dunham@arm.com if (irq_is_secure) { 175211502SCurtis.Dunham@arm.com if (!inSecureState()) { 175311502SCurtis.Dunham@arm.com // Secure interrupts not visible in Non-secure 175411502SCurtis.Dunham@arm.com return Gicv3::INTID_SPURIOUS; 175511502SCurtis.Dunham@arm.com } 175611502SCurtis.Dunham@arm.com } else if (!isEL3OrMon() && inSecureState()) { 175711502SCurtis.Dunham@arm.com // Group 1 non-secure interrupts not visible in Secure EL1 175811502SCurtis.Dunham@arm.com return Gicv3::INTID_SPURIOUS; 175911502SCurtis.Dunham@arm.com } 176011502SCurtis.Dunham@arm.com 176111502SCurtis.Dunham@arm.com return hppi.intid; 176211502SCurtis.Dunham@arm.com} 176311502SCurtis.Dunham@arm.com 176411502SCurtis.Dunham@arm.comvoid 176511502SCurtis.Dunham@arm.comGicv3CPUInterface::dropPriority(Gicv3::GroupId group) 176611502SCurtis.Dunham@arm.com{ 176711502SCurtis.Dunham@arm.com int apr_misc_reg; 176811502SCurtis.Dunham@arm.com RegVal apr; 176911502SCurtis.Dunham@arm.com apr_misc_reg = group == Gicv3::G0S ? 177011502SCurtis.Dunham@arm.com MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1; 177111502SCurtis.Dunham@arm.com apr = isa->readMiscRegNoEffect(apr_misc_reg); 177211502SCurtis.Dunham@arm.com 177311502SCurtis.Dunham@arm.com if (apr) { 177411502SCurtis.Dunham@arm.com apr &= apr - 1; 177511502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(apr_misc_reg, apr); 177611502SCurtis.Dunham@arm.com } 177711502SCurtis.Dunham@arm.com 177811502SCurtis.Dunham@arm.com update(); 177911502SCurtis.Dunham@arm.com} 178011502SCurtis.Dunham@arm.com 178111502SCurtis.Dunham@arm.comuint8_t 178211502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualDropPriority() 178311502SCurtis.Dunham@arm.com{ 178411502SCurtis.Dunham@arm.com int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5); 178511502SCurtis.Dunham@arm.com 178611502SCurtis.Dunham@arm.com for (int i = 0; i < apr_max; i++) { 178711502SCurtis.Dunham@arm.com RegVal vapr0 = isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i); 178811502SCurtis.Dunham@arm.com RegVal vapr1 = isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i); 178911502SCurtis.Dunham@arm.com 179011502SCurtis.Dunham@arm.com if (!vapr0 && !vapr1) { 179111502SCurtis.Dunham@arm.com continue; 179211502SCurtis.Dunham@arm.com } 179311502SCurtis.Dunham@arm.com 179411502SCurtis.Dunham@arm.com int vapr0_count = ctz32(vapr0); 179511502SCurtis.Dunham@arm.com int vapr1_count = ctz32(vapr1); 179611502SCurtis.Dunham@arm.com 179711502SCurtis.Dunham@arm.com if (vapr0_count <= vapr1_count) { 179811502SCurtis.Dunham@arm.com vapr0 &= vapr0 - 1; 179911502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0); 180011502SCurtis.Dunham@arm.com return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1); 180111502SCurtis.Dunham@arm.com } else { 180211502SCurtis.Dunham@arm.com vapr1 &= vapr1 - 1; 180311502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1); 180411502SCurtis.Dunham@arm.com return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1); 180511502SCurtis.Dunham@arm.com } 180611502SCurtis.Dunham@arm.com } 180710535SN/A 180810535SN/A return 0xff; 180911502SCurtis.Dunham@arm.com} 181011502SCurtis.Dunham@arm.com 181111502SCurtis.Dunham@arm.comvoid 181211502SCurtis.Dunham@arm.comGicv3CPUInterface::generateSGI(RegVal val, Gicv3::GroupId group) 181311502SCurtis.Dunham@arm.com{ 181411502SCurtis.Dunham@arm.com uint8_t aff3 = bits(val, 55, 48); 181511502SCurtis.Dunham@arm.com uint8_t aff2 = bits(val, 39, 32); 181611502SCurtis.Dunham@arm.com uint8_t aff1 = bits(val, 23, 16);; 181711502SCurtis.Dunham@arm.com uint16_t target_list = bits(val, 15, 0); 181811502SCurtis.Dunham@arm.com uint32_t int_id = bits(val, 27, 24); 181911502SCurtis.Dunham@arm.com bool irm = bits(val, 40, 40); 182011502SCurtis.Dunham@arm.com uint8_t rs = bits(val, 47, 44); 182111502SCurtis.Dunham@arm.com 182211502SCurtis.Dunham@arm.com bool ns = !inSecureState(); 182311502SCurtis.Dunham@arm.com 182411502SCurtis.Dunham@arm.com for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 182511502SCurtis.Dunham@arm.com Gicv3Redistributor * redistributor_i = 182610535SN/A gic->getRedistributor(i); 182711502SCurtis.Dunham@arm.com uint32_t affinity_i = redistributor_i->getAffinity(); 182811502SCurtis.Dunham@arm.com 182911502SCurtis.Dunham@arm.com if (irm) { 183011502SCurtis.Dunham@arm.com // Interrupts routed to all PEs in the system, 183110535SN/A // excluding "self" 183211502SCurtis.Dunham@arm.com if (affinity_i == redistributor->getAffinity()) { 183311502SCurtis.Dunham@arm.com continue; 183411502SCurtis.Dunham@arm.com } 183511502SCurtis.Dunham@arm.com } else { 183611502SCurtis.Dunham@arm.com // Interrupts routed to the PEs specified by 183711502SCurtis.Dunham@arm.com // Aff3.Aff2.Aff1.<target list> 183811502SCurtis.Dunham@arm.com if ((affinity_i >> 8) != 183911502SCurtis.Dunham@arm.com ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) { 184011502SCurtis.Dunham@arm.com continue; 184111502SCurtis.Dunham@arm.com } 184211502SCurtis.Dunham@arm.com 184311502SCurtis.Dunham@arm.com uint8_t aff0_i = bits(affinity_i, 7, 0); 184411502SCurtis.Dunham@arm.com 184511502SCurtis.Dunham@arm.com if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 && 184611502SCurtis.Dunham@arm.com ((0x1 << (aff0_i - rs * 16)) & target_list))) { 184711502SCurtis.Dunham@arm.com continue; 184811502SCurtis.Dunham@arm.com } 184911502SCurtis.Dunham@arm.com } 185011502SCurtis.Dunham@arm.com 185111502SCurtis.Dunham@arm.com redistributor_i->sendSGI(int_id, group, ns); 185211502SCurtis.Dunham@arm.com } 185311502SCurtis.Dunham@arm.com} 185411502SCurtis.Dunham@arm.com 185511502SCurtis.Dunham@arm.comvoid 185611502SCurtis.Dunham@arm.comGicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group) 185711502SCurtis.Dunham@arm.com{ 185811502SCurtis.Dunham@arm.com // Update active priority registers. 185911502SCurtis.Dunham@arm.com uint32_t prio = hppi.prio & 0xf8; 186011502SCurtis.Dunham@arm.com int apr_bit = prio >> (8 - PRIORITY_BITS); 186111502SCurtis.Dunham@arm.com int reg_bit = apr_bit % 32; 186211502SCurtis.Dunham@arm.com int apr_idx = group == Gicv3::G0S ? 186311502SCurtis.Dunham@arm.com MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1; 186411502SCurtis.Dunham@arm.com RegVal apr = isa->readMiscRegNoEffect(apr_idx); 186511502SCurtis.Dunham@arm.com apr |= (1 << reg_bit); 186611502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(apr_idx, apr); 186711502SCurtis.Dunham@arm.com 186811502SCurtis.Dunham@arm.com // Move interrupt state from pending to active. 186911502SCurtis.Dunham@arm.com if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 187010535SN/A // SGI or PPI, redistributor 187110535SN/A redistributor->activateIRQ(int_id); 187210535SN/A } else if (int_id < Gicv3::INTID_SECURE) { 187310535SN/A // SPI, distributor 187410535SN/A distributor->activateIRQ(int_id); 187510535SN/A } else if (int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) { 187611502SCurtis.Dunham@arm.com // LPI, Redistributor 187711502SCurtis.Dunham@arm.com redistributor->setClrLPI(int_id, false); 187811502SCurtis.Dunham@arm.com } 187911502SCurtis.Dunham@arm.com 188011502SCurtis.Dunham@arm.com // By setting the priority to 0xff we are effectively 188111502SCurtis.Dunham@arm.com // making the int_id not pending anymore at the cpu 188211502SCurtis.Dunham@arm.com // interface. 188311502SCurtis.Dunham@arm.com hppi.prio = 0xff; 188410827Sandreas.hansson@arm.com updateDistributor(); 188510827Sandreas.hansson@arm.com} 188610827Sandreas.hansson@arm.com 188710827Sandreas.hansson@arm.comvoid 188811502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx) 188911502SCurtis.Dunham@arm.com{ 189011502SCurtis.Dunham@arm.com // Update active priority registers. 189111502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + 189211502SCurtis.Dunham@arm.com lr_idx); 189311502SCurtis.Dunham@arm.com Gicv3::GroupId group = ich_lr_el.Group ? Gicv3::G1NS : Gicv3::G0S; 189411502SCurtis.Dunham@arm.com uint8_t prio = ich_lr_el.Priority & 0xf8; 189511502SCurtis.Dunham@arm.com int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS); 189611502SCurtis.Dunham@arm.com int reg_no = apr_bit / 32; 189711502SCurtis.Dunham@arm.com int reg_bit = apr_bit % 32; 189811502SCurtis.Dunham@arm.com int apr_idx = group == Gicv3::G0S ? 189911502SCurtis.Dunham@arm.com MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no; 190011502SCurtis.Dunham@arm.com RegVal apr = isa->readMiscRegNoEffect(apr_idx); 190111502SCurtis.Dunham@arm.com apr |= (1 << reg_bit); 190211502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(apr_idx, apr); 190311502SCurtis.Dunham@arm.com // Move interrupt state from pending to active. 190411502SCurtis.Dunham@arm.com ich_lr_el.State = ICH_LR_EL2_STATE_ACTIVE; 190511502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el); 190611502SCurtis.Dunham@arm.com} 190711502SCurtis.Dunham@arm.com 190811502SCurtis.Dunham@arm.comvoid 190911502SCurtis.Dunham@arm.comGicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group) 191011502SCurtis.Dunham@arm.com{ 191111502SCurtis.Dunham@arm.com if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 191211502SCurtis.Dunham@arm.com // SGI or PPI, redistributor 191311502SCurtis.Dunham@arm.com redistributor->deactivateIRQ(int_id); 191411502SCurtis.Dunham@arm.com } else if (int_id < Gicv3::INTID_SECURE) { 191511502SCurtis.Dunham@arm.com // SPI, distributor 191611502SCurtis.Dunham@arm.com distributor->deactivateIRQ(int_id); 191710628SN/A } 191810628SN/A 191911502SCurtis.Dunham@arm.com updateDistributor(); 192011502SCurtis.Dunham@arm.com} 192111502SCurtis.Dunham@arm.com 192211502SCurtis.Dunham@arm.comvoid 192311502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualDeactivateIRQ(int lr_idx) 192411502SCurtis.Dunham@arm.com{ 192511502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + 192611502SCurtis.Dunham@arm.com lr_idx); 192711502SCurtis.Dunham@arm.com 192811502SCurtis.Dunham@arm.com if (ich_lr_el2.HW) { 192911502SCurtis.Dunham@arm.com // Deactivate the associated physical interrupt 193011502SCurtis.Dunham@arm.com if (ich_lr_el2.pINTID < Gicv3::INTID_SECURE) { 193111502SCurtis.Dunham@arm.com Gicv3::GroupId group = ich_lr_el2.pINTID >= 32 ? 193211502SCurtis.Dunham@arm.com distributor->getIntGroup(ich_lr_el2.pINTID) : 193311502SCurtis.Dunham@arm.com redistributor->getIntGroup(ich_lr_el2.pINTID); 193411502SCurtis.Dunham@arm.com deactivateIRQ(ich_lr_el2.pINTID, group); 193511502SCurtis.Dunham@arm.com } 193611502SCurtis.Dunham@arm.com } 193711502SCurtis.Dunham@arm.com 193811502SCurtis.Dunham@arm.com // Remove the active bit 193911502SCurtis.Dunham@arm.com ich_lr_el2.State = ich_lr_el2.State & ~ICH_LR_EL2_STATE_ACTIVE; 194011502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el2); 194111502SCurtis.Dunham@arm.com} 194211502SCurtis.Dunham@arm.com 194311502SCurtis.Dunham@arm.com/* 194411502SCurtis.Dunham@arm.com * Returns the priority group field for the current BPR value for the group. 194511502SCurtis.Dunham@arm.com * GroupBits() Pseudocode from spec. 194611502SCurtis.Dunham@arm.com */ 194711502SCurtis.Dunham@arm.comuint32_t 194811502SCurtis.Dunham@arm.comGicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) 194911502SCurtis.Dunham@arm.com{ 195011502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_s = 195111502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); 195211502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1_ns = 195311502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); 195411502SCurtis.Dunham@arm.com 195511502SCurtis.Dunham@arm.com if ((group == Gicv3::G1S && icc_ctlr_el1_s.CBPR) || 195611502SCurtis.Dunham@arm.com (group == Gicv3::G1NS && icc_ctlr_el1_ns.CBPR)) { 195711502SCurtis.Dunham@arm.com group = Gicv3::G0S; 195811502SCurtis.Dunham@arm.com } 195911502SCurtis.Dunham@arm.com 196011502SCurtis.Dunham@arm.com int bpr; 196111502SCurtis.Dunham@arm.com 196211502SCurtis.Dunham@arm.com if (group == Gicv3::G0S) { 196311502SCurtis.Dunham@arm.com bpr = readMiscReg(MISCREG_ICC_BPR0_EL1) & 0x7; 196411502SCurtis.Dunham@arm.com } else { 196511502SCurtis.Dunham@arm.com bpr = readMiscReg(MISCREG_ICC_BPR1_EL1) & 0x7; 196611502SCurtis.Dunham@arm.com } 196711502SCurtis.Dunham@arm.com 196811502SCurtis.Dunham@arm.com if (group == Gicv3::G1NS) { 196911502SCurtis.Dunham@arm.com assert(bpr > 0); 197011502SCurtis.Dunham@arm.com bpr--; 197111502SCurtis.Dunham@arm.com } 197211502SCurtis.Dunham@arm.com 197311502SCurtis.Dunham@arm.com return ~0U << (bpr + 1); 197411502SCurtis.Dunham@arm.com} 197511502SCurtis.Dunham@arm.com 197611502SCurtis.Dunham@arm.comuint32_t 197711502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) const 197811502SCurtis.Dunham@arm.com{ 197911502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = 198011502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 198111502SCurtis.Dunham@arm.com 198211502SCurtis.Dunham@arm.com if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) { 198311502SCurtis.Dunham@arm.com group = Gicv3::G0S; 198411502SCurtis.Dunham@arm.com } 198511502SCurtis.Dunham@arm.com 198611502SCurtis.Dunham@arm.com int bpr; 198711502SCurtis.Dunham@arm.com 198811502SCurtis.Dunham@arm.com if (group == Gicv3::G0S) { 198911502SCurtis.Dunham@arm.com bpr = ich_vmcr_el2.VBPR0; 199011502SCurtis.Dunham@arm.com } else { 199111502SCurtis.Dunham@arm.com bpr = ich_vmcr_el2.VBPR1; 199211502SCurtis.Dunham@arm.com } 199311502SCurtis.Dunham@arm.com 199411502SCurtis.Dunham@arm.com if (group == Gicv3::G1NS) { 199511502SCurtis.Dunham@arm.com assert(bpr > 0); 199611502SCurtis.Dunham@arm.com bpr--; 199711502SCurtis.Dunham@arm.com } 199811502SCurtis.Dunham@arm.com 199911502SCurtis.Dunham@arm.com return ~0U << (bpr + 1); 200011502SCurtis.Dunham@arm.com} 200111502SCurtis.Dunham@arm.com 200211502SCurtis.Dunham@arm.combool 200311502SCurtis.Dunham@arm.comGicv3CPUInterface::isEOISplitMode() const 200411502SCurtis.Dunham@arm.com{ 200511502SCurtis.Dunham@arm.com if (isEL3OrMon()) { 200611502SCurtis.Dunham@arm.com ICC_CTLR_EL3 icc_ctlr_el3 = 200711502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); 200811502SCurtis.Dunham@arm.com return icc_ctlr_el3.EOImode_EL3; 200911502SCurtis.Dunham@arm.com } else { 201011502SCurtis.Dunham@arm.com ICC_CTLR_EL1 icc_ctlr_el1 = 201111502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1); 201211502SCurtis.Dunham@arm.com return icc_ctlr_el1.EOImode; 201311502SCurtis.Dunham@arm.com } 201411502SCurtis.Dunham@arm.com} 201511502SCurtis.Dunham@arm.com 201611502SCurtis.Dunham@arm.combool 201711502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualIsEOISplitMode() const 201811502SCurtis.Dunham@arm.com{ 201911502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 202011502SCurtis.Dunham@arm.com return ich_vmcr_el2.VEOIM; 202111502SCurtis.Dunham@arm.com} 202211502SCurtis.Dunham@arm.com 202311502SCurtis.Dunham@arm.comint 202411502SCurtis.Dunham@arm.comGicv3CPUInterface::highestActiveGroup() const 202511502SCurtis.Dunham@arm.com{ 202611502SCurtis.Dunham@arm.com int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1)); 202711502SCurtis.Dunham@arm.com int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S)); 202811502SCurtis.Dunham@arm.com int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS)); 202911502SCurtis.Dunham@arm.com 203011502SCurtis.Dunham@arm.com if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) { 203111502SCurtis.Dunham@arm.com return Gicv3::G1NS; 203211502SCurtis.Dunham@arm.com } 203311502SCurtis.Dunham@arm.com 203411502SCurtis.Dunham@arm.com if (gq_ctz < g0_ctz) { 203511502SCurtis.Dunham@arm.com return Gicv3::G1S; 203611502SCurtis.Dunham@arm.com } 203711502SCurtis.Dunham@arm.com 203811502SCurtis.Dunham@arm.com if (g0_ctz < 32) { 203911502SCurtis.Dunham@arm.com return Gicv3::G0S; 204011502SCurtis.Dunham@arm.com } 204111502SCurtis.Dunham@arm.com 204211502SCurtis.Dunham@arm.com return -1; 204311502SCurtis.Dunham@arm.com} 204411502SCurtis.Dunham@arm.com 204511502SCurtis.Dunham@arm.comvoid 204611502SCurtis.Dunham@arm.comGicv3CPUInterface::updateDistributor() 204711502SCurtis.Dunham@arm.com{ 204811502SCurtis.Dunham@arm.com distributor->update(); 204911502SCurtis.Dunham@arm.com} 205011502SCurtis.Dunham@arm.com 205111502SCurtis.Dunham@arm.comvoid 205211502SCurtis.Dunham@arm.comGicv3CPUInterface::update() 205311502SCurtis.Dunham@arm.com{ 205411502SCurtis.Dunham@arm.com bool signal_IRQ = false; 205511502SCurtis.Dunham@arm.com bool signal_FIQ = false; 205611502SCurtis.Dunham@arm.com 205711502SCurtis.Dunham@arm.com if (hppi.group == Gicv3::G1S && !haveEL(EL3)) { 205811502SCurtis.Dunham@arm.com /* 205911502SCurtis.Dunham@arm.com * Secure enabled GIC sending a G1S IRQ to a secure disabled 206011502SCurtis.Dunham@arm.com * CPU -> send G0 IRQ 206111502SCurtis.Dunham@arm.com */ 206211502SCurtis.Dunham@arm.com hppi.group = Gicv3::G0S; 206311502SCurtis.Dunham@arm.com } 206411502SCurtis.Dunham@arm.com 206511502SCurtis.Dunham@arm.com if (hppiCanPreempt()) { 206611502SCurtis.Dunham@arm.com ArmISA::InterruptTypes int_type = intSignalType(hppi.group); 206711502SCurtis.Dunham@arm.com DPRINTF(GIC, "Gicv3CPUInterface::update(): " 206811502SCurtis.Dunham@arm.com "posting int as %d!\n", int_type); 206911502SCurtis.Dunham@arm.com int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true; 207011502SCurtis.Dunham@arm.com } 207111201Sandreas.hansson@arm.com 207211201Sandreas.hansson@arm.com if (signal_IRQ) { 207310535SN/A gic->postInt(cpuId, ArmISA::INT_IRQ); 207410535SN/A } else { 207511502SCurtis.Dunham@arm.com gic->deassertInt(cpuId, ArmISA::INT_IRQ); 207611502SCurtis.Dunham@arm.com } 207711502SCurtis.Dunham@arm.com 207811502SCurtis.Dunham@arm.com if (signal_FIQ) { 207911502SCurtis.Dunham@arm.com gic->postInt(cpuId, ArmISA::INT_FIQ); 208011502SCurtis.Dunham@arm.com } else { 208111502SCurtis.Dunham@arm.com gic->deassertInt(cpuId, ArmISA::INT_FIQ); 208211502SCurtis.Dunham@arm.com } 208311502SCurtis.Dunham@arm.com} 208411502SCurtis.Dunham@arm.com 208511502SCurtis.Dunham@arm.comvoid 208611502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualUpdate() 208711502SCurtis.Dunham@arm.com{ 208811502SCurtis.Dunham@arm.com bool signal_IRQ = false; 208911502SCurtis.Dunham@arm.com bool signal_FIQ = false; 209011502SCurtis.Dunham@arm.com int lr_idx = getHPPVILR(); 209111502SCurtis.Dunham@arm.com 209211502SCurtis.Dunham@arm.com if (lr_idx >= 0) { 209311502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 209411502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 209511502SCurtis.Dunham@arm.com 209611502SCurtis.Dunham@arm.com if (hppviCanPreempt(lr_idx)) { 209711502SCurtis.Dunham@arm.com if (ich_lr_el2.Group) { 209811502SCurtis.Dunham@arm.com signal_IRQ = true; 209911502SCurtis.Dunham@arm.com } else { 210011502SCurtis.Dunham@arm.com signal_FIQ = true; 210111502SCurtis.Dunham@arm.com } 210211502SCurtis.Dunham@arm.com } 210311502SCurtis.Dunham@arm.com } 210411502SCurtis.Dunham@arm.com 210511502SCurtis.Dunham@arm.com ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 210611502SCurtis.Dunham@arm.com 210711502SCurtis.Dunham@arm.com if (ich_hcr_el2.En) { 210811502SCurtis.Dunham@arm.com if (maintenanceInterruptStatus()) { 210911502SCurtis.Dunham@arm.com maintenanceInterrupt->raise(); 211011502SCurtis.Dunham@arm.com } 211111502SCurtis.Dunham@arm.com } 211211502SCurtis.Dunham@arm.com 211311502SCurtis.Dunham@arm.com if (signal_IRQ) { 211411502SCurtis.Dunham@arm.com DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): " 211511502SCurtis.Dunham@arm.com "posting int as %d!\n", ArmISA::INT_VIRT_IRQ); 211611502SCurtis.Dunham@arm.com gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ); 211711502SCurtis.Dunham@arm.com } else { 211811502SCurtis.Dunham@arm.com gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ); 211911502SCurtis.Dunham@arm.com } 212010628SN/A 212110535SN/A if (signal_FIQ) { 212210628SN/A DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): " 212310535SN/A "posting int as %d!\n", ArmISA::INT_VIRT_FIQ); 212410628SN/A gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ); 212510535SN/A } else { 212611502SCurtis.Dunham@arm.com gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ); 212711502SCurtis.Dunham@arm.com } 212811502SCurtis.Dunham@arm.com} 212911502SCurtis.Dunham@arm.com 213011502SCurtis.Dunham@arm.com// Returns the index of the LR with the HPPI 213111502SCurtis.Dunham@arm.comint 213211502SCurtis.Dunham@arm.comGicv3CPUInterface::getHPPVILR() const 213311502SCurtis.Dunham@arm.com{ 213411502SCurtis.Dunham@arm.com int idx = -1; 213511502SCurtis.Dunham@arm.com ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 213611502SCurtis.Dunham@arm.com 213711502SCurtis.Dunham@arm.com if (!ich_vmcr_el2.VENG0 && !ich_vmcr_el2.VENG1) { 213811502SCurtis.Dunham@arm.com // VG0 and VG1 disabled... 213911502SCurtis.Dunham@arm.com return idx; 214011502SCurtis.Dunham@arm.com } 214111502SCurtis.Dunham@arm.com 214211502SCurtis.Dunham@arm.com uint8_t highest_prio = 0xff; 214311502SCurtis.Dunham@arm.com 214411502SCurtis.Dunham@arm.com for (int i = 0; i < 16; i++) { 214511502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 214611502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i); 214711502SCurtis.Dunham@arm.com 214811502SCurtis.Dunham@arm.com if (ich_lr_el2.State != Gicv3::INT_PENDING) { 214911502SCurtis.Dunham@arm.com continue; 215011502SCurtis.Dunham@arm.com } 215111502SCurtis.Dunham@arm.com 215211502SCurtis.Dunham@arm.com if (ich_lr_el2.Group) { 215311502SCurtis.Dunham@arm.com // VG1 215411502SCurtis.Dunham@arm.com if (!ich_vmcr_el2.VENG1) { 215511502SCurtis.Dunham@arm.com continue; 215611502SCurtis.Dunham@arm.com } 215711502SCurtis.Dunham@arm.com } else { 215811502SCurtis.Dunham@arm.com // VG0 215911502SCurtis.Dunham@arm.com if (!ich_vmcr_el2.VENG0) { 216011502SCurtis.Dunham@arm.com continue; 216111502SCurtis.Dunham@arm.com } 216211502SCurtis.Dunham@arm.com } 216311502SCurtis.Dunham@arm.com 216411502SCurtis.Dunham@arm.com uint8_t prio = ich_lr_el2.Priority; 216511502SCurtis.Dunham@arm.com 216611502SCurtis.Dunham@arm.com if (prio < highest_prio) { 216711502SCurtis.Dunham@arm.com highest_prio = prio; 216811502SCurtis.Dunham@arm.com idx = i; 216910827Sandreas.hansson@arm.com } 217011502SCurtis.Dunham@arm.com } 217111502SCurtis.Dunham@arm.com 217211502SCurtis.Dunham@arm.com return idx; 217311502SCurtis.Dunham@arm.com} 217410827Sandreas.hansson@arm.com 217511502SCurtis.Dunham@arm.combool 217611502SCurtis.Dunham@arm.comGicv3CPUInterface::hppviCanPreempt(int lr_idx) const 217711502SCurtis.Dunham@arm.com{ 217811502SCurtis.Dunham@arm.com ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 217911502SCurtis.Dunham@arm.com if (!ich_hcr_el2.En) { 218011502SCurtis.Dunham@arm.com // virtual interface is disabled 218111502SCurtis.Dunham@arm.com return false; 218211502SCurtis.Dunham@arm.com } 218311502SCurtis.Dunham@arm.com 218411502SCurtis.Dunham@arm.com ICH_LR_EL2 ich_lr_el2 = 218511502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 218611502SCurtis.Dunham@arm.com uint8_t prio = ich_lr_el2.Priority; 218711502SCurtis.Dunham@arm.com uint8_t vpmr = 218811502SCurtis.Dunham@arm.com bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24); 218911502SCurtis.Dunham@arm.com 219011502SCurtis.Dunham@arm.com if (prio >= vpmr) { 219111502SCurtis.Dunham@arm.com // prioriry masked 219211502SCurtis.Dunham@arm.com return false; 219311502SCurtis.Dunham@arm.com } 219411502SCurtis.Dunham@arm.com 219511502SCurtis.Dunham@arm.com uint8_t rprio = virtualHighestActivePriority(); 219611502SCurtis.Dunham@arm.com 219711502SCurtis.Dunham@arm.com if (rprio == 0xff) { 219811502SCurtis.Dunham@arm.com return true; 219911502SCurtis.Dunham@arm.com } 220011502SCurtis.Dunham@arm.com 220111502SCurtis.Dunham@arm.com Gicv3::GroupId group = ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S; 220211502SCurtis.Dunham@arm.com uint32_t prio_mask = virtualGroupPriorityMask(group); 220311502SCurtis.Dunham@arm.com 220411502SCurtis.Dunham@arm.com if ((prio & prio_mask) < (rprio & prio_mask)) { 220511502SCurtis.Dunham@arm.com return true; 220611502SCurtis.Dunham@arm.com } 220711502SCurtis.Dunham@arm.com 220811502SCurtis.Dunham@arm.com return false; 220911502SCurtis.Dunham@arm.com} 221011502SCurtis.Dunham@arm.com 221111502SCurtis.Dunham@arm.comuint8_t 221211502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualHighestActivePriority() const 221311502SCurtis.Dunham@arm.com{ 221411502SCurtis.Dunham@arm.com uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5); 221511502SCurtis.Dunham@arm.com 221610535SN/A for (int i = 0; i < num_aprs; i++) { 221710535SN/A RegVal vapr = 221811502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) | 221911502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i); 222011201Sandreas.hansson@arm.com 222111201Sandreas.hansson@arm.com if (!vapr) { 222210535SN/A continue; 222310535SN/A } 222411502SCurtis.Dunham@arm.com 222511502SCurtis.Dunham@arm.com return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1); 222611502SCurtis.Dunham@arm.com } 222711502SCurtis.Dunham@arm.com 222811502SCurtis.Dunham@arm.com // no active interrups, return idle priority 222911502SCurtis.Dunham@arm.com return 0xff; 223011502SCurtis.Dunham@arm.com} 223111502SCurtis.Dunham@arm.com 223211502SCurtis.Dunham@arm.comvoid 223311502SCurtis.Dunham@arm.comGicv3CPUInterface::virtualIncrementEOICount() 223411502SCurtis.Dunham@arm.com{ 223511502SCurtis.Dunham@arm.com // Increment the EOICOUNT field in ICH_HCR_EL2 223611502SCurtis.Dunham@arm.com RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 223711502SCurtis.Dunham@arm.com uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27); 223811502SCurtis.Dunham@arm.com EOI_cout++; 223911502SCurtis.Dunham@arm.com ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout); 224011502SCurtis.Dunham@arm.com isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2); 224110535SN/A} 224211502SCurtis.Dunham@arm.com 224311502SCurtis.Dunham@arm.com// spec section 4.6.2 224411502SCurtis.Dunham@arm.comArmISA::InterruptTypes 224511502SCurtis.Dunham@arm.comGicv3CPUInterface::intSignalType(Gicv3::GroupId group) const 224611502SCurtis.Dunham@arm.com{ 224711502SCurtis.Dunham@arm.com bool is_fiq = false; 224811502SCurtis.Dunham@arm.com 224911502SCurtis.Dunham@arm.com switch (group) { 225011502SCurtis.Dunham@arm.com case Gicv3::G0S: 225111502SCurtis.Dunham@arm.com is_fiq = true; 225211502SCurtis.Dunham@arm.com break; 225311502SCurtis.Dunham@arm.com 225411502SCurtis.Dunham@arm.com case Gicv3::G1S: 225511502SCurtis.Dunham@arm.com is_fiq = (distributor->DS == 0) && 225611502SCurtis.Dunham@arm.com (!inSecureState() || ((currEL() == EL3) && isAA64())); 225711502SCurtis.Dunham@arm.com break; 225811502SCurtis.Dunham@arm.com 225911502SCurtis.Dunham@arm.com case Gicv3::G1NS: 226011502SCurtis.Dunham@arm.com is_fiq = (distributor->DS == 0) && inSecureState(); 226111502SCurtis.Dunham@arm.com break; 226211502SCurtis.Dunham@arm.com 226311502SCurtis.Dunham@arm.com default: 226411502SCurtis.Dunham@arm.com panic("Gicv3CPUInterface::intSignalType(): invalid group!"); 226511502SCurtis.Dunham@arm.com } 226611502SCurtis.Dunham@arm.com 226711502SCurtis.Dunham@arm.com if (is_fiq) { 226811502SCurtis.Dunham@arm.com return ArmISA::INT_FIQ; 226911502SCurtis.Dunham@arm.com } else { 227011502SCurtis.Dunham@arm.com return ArmISA::INT_IRQ; 227111502SCurtis.Dunham@arm.com } 227211502SCurtis.Dunham@arm.com} 227311502SCurtis.Dunham@arm.com 227411502SCurtis.Dunham@arm.combool 227511502SCurtis.Dunham@arm.comGicv3CPUInterface::hppiCanPreempt() 227611502SCurtis.Dunham@arm.com{ 227711502SCurtis.Dunham@arm.com if (hppi.prio == 0xff) { 227811502SCurtis.Dunham@arm.com // there is no pending interrupt 227911502SCurtis.Dunham@arm.com return false; 228011502SCurtis.Dunham@arm.com } 228111502SCurtis.Dunham@arm.com 228211502SCurtis.Dunham@arm.com if (!groupEnabled(hppi.group)) { 228311502SCurtis.Dunham@arm.com // group disabled at CPU interface 228411502SCurtis.Dunham@arm.com return false; 228511502SCurtis.Dunham@arm.com } 228611502SCurtis.Dunham@arm.com 228711502SCurtis.Dunham@arm.com if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) { 228811502SCurtis.Dunham@arm.com // priority masked 228911502SCurtis.Dunham@arm.com return false; 229011502SCurtis.Dunham@arm.com } 229111502SCurtis.Dunham@arm.com 229211502SCurtis.Dunham@arm.com uint8_t rprio = highestActivePriority(); 229311502SCurtis.Dunham@arm.com 229411502SCurtis.Dunham@arm.com if (rprio == 0xff) { 229511502SCurtis.Dunham@arm.com return true; 229611502SCurtis.Dunham@arm.com } 229711502SCurtis.Dunham@arm.com 229811502SCurtis.Dunham@arm.com uint32_t prio_mask = groupPriorityMask(hppi.group); 229911502SCurtis.Dunham@arm.com 230011502SCurtis.Dunham@arm.com if ((hppi.prio & prio_mask) < (rprio & prio_mask)) { 230111502SCurtis.Dunham@arm.com return true; 230211502SCurtis.Dunham@arm.com } 230311502SCurtis.Dunham@arm.com 230411502SCurtis.Dunham@arm.com return false; 230511502SCurtis.Dunham@arm.com} 230611502SCurtis.Dunham@arm.com 230711502SCurtis.Dunham@arm.comuint8_t 230811502SCurtis.Dunham@arm.comGicv3CPUInterface::highestActivePriority() const 230911502SCurtis.Dunham@arm.com{ 231011502SCurtis.Dunham@arm.com uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) | 231111502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) | 231211502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S); 231311502SCurtis.Dunham@arm.com 231411502SCurtis.Dunham@arm.com if (apr) { 231511502SCurtis.Dunham@arm.com return ctz32(apr) << (GIC_MIN_BPR + 1); 231611502SCurtis.Dunham@arm.com } 231711502SCurtis.Dunham@arm.com 231810535SN/A // no active interrups, return idle priority 231911502SCurtis.Dunham@arm.com return 0xff; 232011502SCurtis.Dunham@arm.com} 232111502SCurtis.Dunham@arm.com 232210535SN/Abool 232311138Sandreas.hansson@arm.comGicv3CPUInterface::groupEnabled(Gicv3::GroupId group) const 232410827Sandreas.hansson@arm.com{ 232511502SCurtis.Dunham@arm.com switch (group) { 232611502SCurtis.Dunham@arm.com case Gicv3::G0S: { 232710535SN/A ICC_IGRPEN0_EL1 icc_igrpen0_el1 = 232811502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1); 232910535SN/A return icc_igrpen0_el1.Enable && distributor->EnableGrp0; 233011502SCurtis.Dunham@arm.com } 233110535SN/A 233211502SCurtis.Dunham@arm.com case Gicv3::G1S: { 233310535SN/A ICC_IGRPEN1_EL1 icc_igrpen1_el1_s = 233411502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S); 233510535SN/A return icc_igrpen1_el1_s.Enable && distributor->EnableGrp1S; 233611502SCurtis.Dunham@arm.com } 233710535SN/A 233811502SCurtis.Dunham@arm.com case Gicv3::G1NS: { 233911502SCurtis.Dunham@arm.com ICC_IGRPEN1_EL1 icc_igrpen1_el1_ns = 234011502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS); 234111502SCurtis.Dunham@arm.com return icc_igrpen1_el1_ns.Enable && distributor->EnableGrp1NS; 234211502SCurtis.Dunham@arm.com } 234310535SN/A 234411245Sandreas.sandberg@arm.com default: 234510535SN/A panic("Gicv3CPUInterface::groupEnable(): invalid group!\n"); 234610535SN/A } 234710535SN/A} 234810535SN/A 234910535SN/Abool 235010535SN/AGicv3CPUInterface::inSecureState() const 235110535SN/A{ 235210535SN/A if (!gic->getSystem()->haveSecurity()) { 235311374Ssteve.reinhardt@amd.com return false; 235410535SN/A } 235511502SCurtis.Dunham@arm.com 235611502SCurtis.Dunham@arm.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 235711502SCurtis.Dunham@arm.com SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR); 235810535SN/A return ArmISA::inSecureState(scr, cpsr); 235910535SN/A} 236011502SCurtis.Dunham@arm.com 236111502SCurtis.Dunham@arm.comint 236210535SN/AGicv3CPUInterface::currEL() const 236311245Sandreas.sandberg@arm.com{ 236410535SN/A CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 236510535SN/A bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode); 236610535SN/A 236710535SN/A if (is_64) { 236810535SN/A return (ExceptionLevel)(uint8_t) cpsr.el; 236910535SN/A } else { 237010535SN/A switch (cpsr.mode) { 237110535SN/A case MODE_USER: 237211374Ssteve.reinhardt@amd.com return 0; 237310535SN/A 237411502SCurtis.Dunham@arm.com case MODE_HYP: 237511502SCurtis.Dunham@arm.com return 2; 237611502SCurtis.Dunham@arm.com 237710535SN/A case MODE_MON: 237810535SN/A return 3; 237911502SCurtis.Dunham@arm.com 238011502SCurtis.Dunham@arm.com default: 238110535SN/A return 1; 238211502SCurtis.Dunham@arm.com } 238310535SN/A } 238411502SCurtis.Dunham@arm.com} 238510535SN/A 238611201Sandreas.hansson@arm.combool 238710535SN/AGicv3CPUInterface::haveEL(ExceptionLevel el) const 238811336Sandreas.hansson@arm.com{ 238911245Sandreas.sandberg@arm.com switch (el) { 239010535SN/A case EL0: 239110535SN/A case EL1: 239211353Sandreas.hansson@arm.com return true; 239310535SN/A 239411502SCurtis.Dunham@arm.com case EL2: 239510535SN/A return gic->getSystem()->haveVirtualization(); 239611201Sandreas.hansson@arm.com 239710535SN/A case EL3: 239811502SCurtis.Dunham@arm.com return gic->getSystem()->haveSecurity(); 239910535SN/A 240011353Sandreas.hansson@arm.com default: 240110535SN/A warn("Unimplemented Exception Level\n"); 240211502SCurtis.Dunham@arm.com return false; 240310535SN/A } 240411502SCurtis.Dunham@arm.com} 240510535SN/A 240611502SCurtis.Dunham@arm.combool 240710535SN/AGicv3CPUInterface::isSecureBelowEL3() const 240811502SCurtis.Dunham@arm.com{ 240910535SN/A SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); 241011502SCurtis.Dunham@arm.com return haveEL(EL3) && scr.ns == 0; 241110535SN/A} 241210892Sandreas.hansson@arm.com 241310535SN/Abool 241411502SCurtis.Dunham@arm.comGicv3CPUInterface::isAA64() const 241511502SCurtis.Dunham@arm.com{ 241611336Sandreas.hansson@arm.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 241711502SCurtis.Dunham@arm.com return opModeIs64((OperatingMode)(uint8_t) cpsr.mode); 241811336Sandreas.hansson@arm.com} 241911502SCurtis.Dunham@arm.com 242011502SCurtis.Dunham@arm.combool 242111502SCurtis.Dunham@arm.comGicv3CPUInterface::isEL3OrMon() const 242211502SCurtis.Dunham@arm.com{ 242311502SCurtis.Dunham@arm.com if (haveEL(EL3)) { 242411502SCurtis.Dunham@arm.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 242510535SN/A bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode); 242610535SN/A 242710535SN/A if (is_64 && (cpsr.el == EL3)) { 242811502SCurtis.Dunham@arm.com return true; 242911502SCurtis.Dunham@arm.com } else if (!is_64 && (cpsr.mode == MODE_MON)) { 243010535SN/A return true; 243111502SCurtis.Dunham@arm.com } 243211502SCurtis.Dunham@arm.com } 243310535SN/A 243410535SN/A return false; 243511353Sandreas.hansson@arm.com} 243611353Sandreas.hansson@arm.com 243710535SN/A// Computes ICH_EISR_EL2 243811502SCurtis.Dunham@arm.comuint64_t 243911502SCurtis.Dunham@arm.comGicv3CPUInterface::eoiMaintenanceInterruptStatus() const 244010535SN/A{ 244111502SCurtis.Dunham@arm.com // ICH_EISR_EL2 244211502SCurtis.Dunham@arm.com // Bits [63:16] - RES0 244311502SCurtis.Dunham@arm.com // Status<n>, bit [n], for n = 0 to 15 244411502SCurtis.Dunham@arm.com // EOI maintenance interrupt status bit for List register <n>: 244511502SCurtis.Dunham@arm.com // 0 if List register <n>, ICH_LR<n>_EL2, does not have an EOI 244610726SN/A // maintenance interrupt. 244710726SN/A // 1 if List register <n>, ICH_LR<n>_EL2, has an EOI maintenance 244811502SCurtis.Dunham@arm.com // interrupt that has not been handled. 244911502SCurtis.Dunham@arm.com // 245011502SCurtis.Dunham@arm.com // For any ICH_LR<n>_EL2, the corresponding status bit is set to 1 if all 245111502SCurtis.Dunham@arm.com // of the following are true: 245211502SCurtis.Dunham@arm.com // - ICH_LR<n>_EL2.State is 0b00 (ICH_LR_EL2_STATE_INVALID). 245311502SCurtis.Dunham@arm.com // - ICH_LR<n>_EL2.HW is 0. 245411502SCurtis.Dunham@arm.com // - ICH_LR<n>_EL2.EOI (bit [41]) is 1. 245511502SCurtis.Dunham@arm.com 245610535SN/A uint64_t value = 0; 245711502SCurtis.Dunham@arm.com 245811502SCurtis.Dunham@arm.com for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 245910535SN/A ICH_LR_EL2 ich_lr_el2 = 246010535SN/A isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 246111353Sandreas.hansson@arm.com 246211353Sandreas.hansson@arm.com if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) && 246310535SN/A !ich_lr_el2.HW && ich_lr_el2.EOI) { 246411502SCurtis.Dunham@arm.com value |= (1 << lr_idx); 246511502SCurtis.Dunham@arm.com } 246610535SN/A } 246711502SCurtis.Dunham@arm.com 246811502SCurtis.Dunham@arm.com return value; 246910535SN/A} 247010535SN/A 247110535SN/AGicv3CPUInterface::ICH_MISR_EL2 247210535SN/AGicv3CPUInterface::maintenanceInterruptStatus() const 247310535SN/A{ 247411336Sandreas.hansson@arm.com // Comments are copied from SPEC section 9.4.7 (ID012119) 247511336Sandreas.hansson@arm.com ICH_MISR_EL2 ich_misr_el2 = 0; 247610535SN/A ICH_HCR_EL2 ich_hcr_el2 = 247710535SN/A isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 247810535SN/A ICH_VMCR_EL2 ich_vmcr_el2 = 247910535SN/A isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 248010535SN/A 248110535SN/A // End Of Interrupt. [bit 0] 248211502SCurtis.Dunham@arm.com // This maintenance interrupt is asserted when at least one bit in 248311502SCurtis.Dunham@arm.com // ICH_EISR_EL2 is 1. 248411502SCurtis.Dunham@arm.com 248510726SN/A if (eoiMaintenanceInterruptStatus()) { 248610726SN/A ich_misr_el2.EOI = 1; 248711502SCurtis.Dunham@arm.com } 248811502SCurtis.Dunham@arm.com 248911502SCurtis.Dunham@arm.com // Underflow. [bit 1] 249011502SCurtis.Dunham@arm.com // This maintenance interrupt is asserted when ICH_HCR_EL2.UIE==1 and 249111502SCurtis.Dunham@arm.com // zero or one of the List register entries are marked as a valid 249211502SCurtis.Dunham@arm.com // interrupt, that is, if the corresponding ICH_LR<n>_EL2.State bits 249311502SCurtis.Dunham@arm.com // do not equal 0x0. 249411502SCurtis.Dunham@arm.com uint32_t num_valid_interrupts = 0; 249511502SCurtis.Dunham@arm.com uint32_t num_pending_interrupts = 0; 249610535SN/A 249711502SCurtis.Dunham@arm.com for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 249810535SN/A ICH_LR_EL2 ich_lr_el2 = 249911502SCurtis.Dunham@arm.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 250010535SN/A 250111502SCurtis.Dunham@arm.com if (ich_lr_el2.State != ICH_LR_EL2_STATE_INVALID) { 250211502SCurtis.Dunham@arm.com num_valid_interrupts++; 250310535SN/A } 250411502SCurtis.Dunham@arm.com 250511502SCurtis.Dunham@arm.com if (ich_lr_el2.State == ICH_LR_EL2_STATE_PENDING) { 250610535SN/A num_pending_interrupts++; 250710535SN/A } 250811353Sandreas.hansson@arm.com } 250911353Sandreas.hansson@arm.com 251010535SN/A if (ich_hcr_el2.UIE && (num_valid_interrupts < 2)) { 251111502SCurtis.Dunham@arm.com ich_misr_el2.U = 1; 251211502SCurtis.Dunham@arm.com } 251310535SN/A 251411502SCurtis.Dunham@arm.com // List Register Entry Not Present. [bit 2] 251511502SCurtis.Dunham@arm.com // This maintenance interrupt is asserted when ICH_HCR_EL2.LRENPIE==1 251611502SCurtis.Dunham@arm.com // and ICH_HCR_EL2.EOIcount is non-zero. 251711502SCurtis.Dunham@arm.com if (ich_hcr_el2.LRENPIE && ich_hcr_el2.EOIcount) { 251811502SCurtis.Dunham@arm.com ich_misr_el2.LRENP = 1; 251910892Sandreas.hansson@arm.com } 252010892Sandreas.hansson@arm.com 252111502SCurtis.Dunham@arm.com // No Pending. [bit 3] 252211502SCurtis.Dunham@arm.com // This maintenance interrupt is asserted when ICH_HCR_EL2.NPIE==1 and 252311502SCurtis.Dunham@arm.com // no List register is in pending state. 252411502SCurtis.Dunham@arm.com if (ich_hcr_el2.NPIE && (num_pending_interrupts == 0)) { 252511502SCurtis.Dunham@arm.com ich_misr_el2.NP = 1; 252611502SCurtis.Dunham@arm.com } 252711502SCurtis.Dunham@arm.com 252811502SCurtis.Dunham@arm.com // vPE Group 0 Enabled. [bit 4] 252910535SN/A // This maintenance interrupt is asserted when 253010535SN/A // ICH_HCR_EL2.VGrp0EIE==1 and ICH_VMCR_EL2.VENG0==1. 253110535SN/A if (ich_hcr_el2.VGrp0EIE && ich_vmcr_el2.VENG0) { 253210535SN/A ich_misr_el2.VGrp0E = 1; 253310535SN/A } 253411336Sandreas.hansson@arm.com 253511336Sandreas.hansson@arm.com // vPE Group 0 Disabled. [bit 5] 253610535SN/A // This maintenance interrupt is asserted when 253710535SN/A // ICH_HCR_EL2.VGrp0DIE==1 and ICH_VMCR_EL2.VENG0==0. 253810535SN/A if (ich_hcr_el2.VGrp0DIE && !ich_vmcr_el2.VENG0) { 253910535SN/A ich_misr_el2.VGrp0D = 1; 254010535SN/A } 254110535SN/A 254211502SCurtis.Dunham@arm.com // vPE Group 1 Enabled. [bit 6] 254311502SCurtis.Dunham@arm.com // This maintenance interrupt is asserted when 254411502SCurtis.Dunham@arm.com // ICH_HCR_EL2.VGrp1EIE==1 and ICH_VMCR_EL2.VENG1==is 1. 254510892Sandreas.hansson@arm.com if (ich_hcr_el2.VGrp1EIE && ich_vmcr_el2.VENG1) { 254610892Sandreas.hansson@arm.com ich_misr_el2.VGrp1E = 1; 254711502SCurtis.Dunham@arm.com } 254811502SCurtis.Dunham@arm.com 254911502SCurtis.Dunham@arm.com // vPE Group 1 Disabled. [bit 7] 255011502SCurtis.Dunham@arm.com // This maintenance interrupt is asserted when 255111502SCurtis.Dunham@arm.com // ICH_HCR_EL2.VGrp1DIE==1 and ICH_VMCR_EL2.VENG1==is 0. 255211502SCurtis.Dunham@arm.com if (ich_hcr_el2.VGrp1DIE && !ich_vmcr_el2.VENG1) { 255311502SCurtis.Dunham@arm.com ich_misr_el2.VGrp1D = 1; 255411502SCurtis.Dunham@arm.com } 255511502SCurtis.Dunham@arm.com 255611502SCurtis.Dunham@arm.com return ich_misr_el2; 255711502SCurtis.Dunham@arm.com} 255811502SCurtis.Dunham@arm.com 255911502SCurtis.Dunham@arm.comvoid 256011502SCurtis.Dunham@arm.comGicv3CPUInterface::serialize(CheckpointOut & cp) const 256111502SCurtis.Dunham@arm.com{ 256211502SCurtis.Dunham@arm.com SERIALIZE_SCALAR(hppi.intid); 256311502SCurtis.Dunham@arm.com SERIALIZE_SCALAR(hppi.prio); 256411502SCurtis.Dunham@arm.com SERIALIZE_ENUM(hppi.group); 256511502SCurtis.Dunham@arm.com} 256611502SCurtis.Dunham@arm.com 256711502SCurtis.Dunham@arm.comvoid 256811502SCurtis.Dunham@arm.comGicv3CPUInterface::unserialize(CheckpointIn & cp) 256911502SCurtis.Dunham@arm.com{ 257011502SCurtis.Dunham@arm.com UNSERIALIZE_SCALAR(hppi.intid); 257111502SCurtis.Dunham@arm.com UNSERIALIZE_SCALAR(hppi.prio); 257211502SCurtis.Dunham@arm.com UNSERIALIZE_ENUM(hppi.group); 257311502SCurtis.Dunham@arm.com} 257411502SCurtis.Dunham@arm.com