gic_v3_cpu_interface.cc revision 13531
112854Sgabeblack@google.com/* 212854Sgabeblack@google.com * Copyright (c) 2018 Metempsy Technology Consulting 312854Sgabeblack@google.com * All rights reserved. 412854Sgabeblack@google.com * 512854Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612854Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712854Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912854Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012854Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112854Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212854Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312854Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412854Sgabeblack@google.com * this software without specific prior written permission. 1512854Sgabeblack@google.com * 1612854Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712854Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812854Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912854Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012854Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112854Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212854Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312854Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412854Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512854Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612854Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712854Sgabeblack@google.com * 2812854Sgabeblack@google.com * Authors: Jairo Balart 2912854Sgabeblack@google.com */ 3012854Sgabeblack@google.com 3112854Sgabeblack@google.com#include "dev/arm/gic_v3_cpu_interface.hh" 3212854Sgabeblack@google.com 3312854Sgabeblack@google.com#include "arch/arm/isa.hh" 3412854Sgabeblack@google.com#include "debug/GIC.hh" 3512854Sgabeblack@google.com#include "dev/arm/gic_v3.hh" 3612854Sgabeblack@google.com#include "dev/arm/gic_v3_distributor.hh" 3712854Sgabeblack@google.com#include "dev/arm/gic_v3_redistributor.hh" 3812854Sgabeblack@google.com 3912854Sgabeblack@google.comGicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id) 4012854Sgabeblack@google.com : BaseISADevice(), 4112854Sgabeblack@google.com gic(gic), 4212854Sgabeblack@google.com redistributor(nullptr), 4312854Sgabeblack@google.com distributor(nullptr), 4412854Sgabeblack@google.com cpuId(cpu_id) 4512854Sgabeblack@google.com{ 4612854Sgabeblack@google.com} 4712854Sgabeblack@google.com 4812854Sgabeblack@google.comGicv3CPUInterface::~Gicv3CPUInterface() 4912854Sgabeblack@google.com{ 5012854Sgabeblack@google.com} 5112854Sgabeblack@google.com 5212854Sgabeblack@google.comvoid 5312854Sgabeblack@google.comGicv3CPUInterface::init() 5412854Sgabeblack@google.com{ 5512854Sgabeblack@google.com redistributor = gic->getRedistributor(cpuId); 5612854Sgabeblack@google.com distributor = gic->getDistributor(); 5712854Sgabeblack@google.com} 5812854Sgabeblack@google.com 5912854Sgabeblack@google.comvoid 6012854Sgabeblack@google.comGicv3CPUInterface::initState() 6112854Sgabeblack@google.com{ 6212854Sgabeblack@google.com reset(); 6312854Sgabeblack@google.com} 6412854Sgabeblack@google.com 6512854Sgabeblack@google.comvoid 6612854Sgabeblack@google.comGicv3CPUInterface::reset() 6712854Sgabeblack@google.com{ 6812854Sgabeblack@google.com hppi.prio = 0xff; 6912854Sgabeblack@google.com} 7012854Sgabeblack@google.com 7112854Sgabeblack@google.combool 7212854Sgabeblack@google.comGicv3CPUInterface::getHCREL2FMO() 7312854Sgabeblack@google.com{ 7412854Sgabeblack@google.com HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2); 7512854Sgabeblack@google.com 7612854Sgabeblack@google.com if (hcr.tge && hcr.e2h) { 7712854Sgabeblack@google.com return false; 7812854Sgabeblack@google.com } else if (hcr.tge) { 7912854Sgabeblack@google.com return true; 8012854Sgabeblack@google.com } else { 8112854Sgabeblack@google.com return hcr.fmo; 8212854Sgabeblack@google.com } 8312854Sgabeblack@google.com} 8412854Sgabeblack@google.com 8513325Sgabeblack@google.combool 8612854Sgabeblack@google.comGicv3CPUInterface::getHCREL2IMO() 8712854Sgabeblack@google.com{ 8812854Sgabeblack@google.com HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2); 8912854Sgabeblack@google.com 9012854Sgabeblack@google.com if (hcr.tge && hcr.e2h) { 9112854Sgabeblack@google.com return false; 9212854Sgabeblack@google.com } else if (hcr.tge) { 9312854Sgabeblack@google.com return true; 9412854Sgabeblack@google.com } else { 9512854Sgabeblack@google.com return hcr.imo; 9612854Sgabeblack@google.com } 9712854Sgabeblack@google.com} 9812854Sgabeblack@google.com 9912854Sgabeblack@google.comArmISA::MiscReg 10012854Sgabeblack@google.comGicv3CPUInterface::readMiscReg(int misc_reg) 10112854Sgabeblack@google.com{ 10212854Sgabeblack@google.com ArmISA::MiscReg value = isa->readMiscRegNoEffect(misc_reg); 10312854Sgabeblack@google.com bool hcr_fmo = getHCREL2FMO(); 10412854Sgabeblack@google.com bool hcr_imo = getHCREL2IMO(); 10512854Sgabeblack@google.com 10612854Sgabeblack@google.com switch (misc_reg) { 10712854Sgabeblack@google.com case MISCREG_ICC_AP1R0: 10812854Sgabeblack@google.com case MISCREG_ICC_AP1R0_EL1: { 10912854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 11012854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1); 11112854Sgabeblack@google.com } 11212854Sgabeblack@google.com 11312854Sgabeblack@google.com break; 11413325Sgabeblack@google.com } 11512854Sgabeblack@google.com 11612854Sgabeblack@google.com case MISCREG_ICC_AP1R1: 11712854Sgabeblack@google.com case MISCREG_ICC_AP1R1_EL1: 11812854Sgabeblack@google.com 11912854Sgabeblack@google.com // only implemented if supporting 6 or more bits of priority 12012854Sgabeblack@google.com case MISCREG_ICC_AP1R2: 12112854Sgabeblack@google.com case MISCREG_ICC_AP1R2_EL1: 12212854Sgabeblack@google.com 12312854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 12412854Sgabeblack@google.com case MISCREG_ICC_AP1R3: 12512854Sgabeblack@google.com case MISCREG_ICC_AP1R3_EL1: 12612854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 12713322Sgabeblack@google.com return 0; 12812854Sgabeblack@google.com 12912854Sgabeblack@google.com case MISCREG_ICC_AP0R0: 13012854Sgabeblack@google.com case MISCREG_ICC_AP0R0_EL1: { 13112854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 13212854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1); 13312854Sgabeblack@google.com } 13412854Sgabeblack@google.com 13512854Sgabeblack@google.com break; 13613160Sgabeblack@google.com } 13712854Sgabeblack@google.com 13812854Sgabeblack@google.com case MISCREG_ICC_AP0R1: 13913322Sgabeblack@google.com case MISCREG_ICC_AP0R1_EL1: 14012854Sgabeblack@google.com 14112854Sgabeblack@google.com // only implemented if supporting 6 or more bits of priority 14212854Sgabeblack@google.com case MISCREG_ICC_AP0R2: 14312854Sgabeblack@google.com case MISCREG_ICC_AP0R2_EL1: 14412854Sgabeblack@google.com 14512854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 14612854Sgabeblack@google.com case MISCREG_ICC_AP0R3: 14712854Sgabeblack@google.com case MISCREG_ICC_AP0R3_EL1: 14812854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 14912854Sgabeblack@google.com return 0; 15012854Sgabeblack@google.com 15112854Sgabeblack@google.com case MISCREG_ICC_IGRPEN0: 15212854Sgabeblack@google.com case MISCREG_ICC_IGRPEN0_EL1: { 15312854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 15412854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN0_EL1); 15512854Sgabeblack@google.com } 15612854Sgabeblack@google.com 15712854Sgabeblack@google.com break; 15812854Sgabeblack@google.com } 15912854Sgabeblack@google.com 16012854Sgabeblack@google.com case MISCREG_ICC_IGRPEN1: 16112854Sgabeblack@google.com case MISCREG_ICC_IGRPEN1_EL1: { 16212854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 16312854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN1_EL1); 16412854Sgabeblack@google.com } 16512854Sgabeblack@google.com 16612854Sgabeblack@google.com break; 16712854Sgabeblack@google.com } 16812854Sgabeblack@google.com 16912854Sgabeblack@google.com case MISCREG_ICC_MGRPEN1: 17012854Sgabeblack@google.com case MISCREG_ICC_IGRPEN1_EL3: { 17112854Sgabeblack@google.com // EnableGrp1S and EnableGrp1NS are aliased with 17212854Sgabeblack@google.com // ICC_IGRPEN1_EL1_S.Enable and ICC_IGRPEN1_EL1_NS.Enable 17312854Sgabeblack@google.com bool enable_grp_1s = 17412854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) & 17512854Sgabeblack@google.com ICC_IGRPEN1_EL1_ENABLE; 17612854Sgabeblack@google.com bool enable_grp_1ns = 17712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) & 17812854Sgabeblack@google.com ICC_IGRPEN1_EL1_ENABLE; 17912854Sgabeblack@google.com value = 0; 18012854Sgabeblack@google.com 18112854Sgabeblack@google.com if (enable_grp_1s) { 18212854Sgabeblack@google.com value |= ICC_IGRPEN1_EL3_ENABLEGRP1S; 18312854Sgabeblack@google.com } 18412854Sgabeblack@google.com 18512854Sgabeblack@google.com if (enable_grp_1ns) { 18612854Sgabeblack@google.com value |= ICC_IGRPEN1_EL3_ENABLEGRP1NS; 18712854Sgabeblack@google.com } 18812854Sgabeblack@google.com 18912854Sgabeblack@google.com break; 19012854Sgabeblack@google.com } 19112854Sgabeblack@google.com 19212854Sgabeblack@google.com case MISCREG_ICC_RPR: 19312854Sgabeblack@google.com case MISCREG_ICC_RPR_EL1: { 19412854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && 19512854Sgabeblack@google.com (hcr_imo || hcr_fmo)) { 19612854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_RPR_EL1); 19712854Sgabeblack@google.com } 19812854Sgabeblack@google.com 19912854Sgabeblack@google.com uint8_t rprio = highestActivePriority(); 20012854Sgabeblack@google.com 20112854Sgabeblack@google.com if (haveEL(EL3) && !inSecureState() && 20212854Sgabeblack@google.com (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { 20312854Sgabeblack@google.com /* NS GIC access and Group 0 is inaccessible to NS */ 20412854Sgabeblack@google.com if ((rprio & 0x80) == 0) { 20512854Sgabeblack@google.com /* NS should not see priorities in the Secure half of the 20612854Sgabeblack@google.com * range */ 20712854Sgabeblack@google.com rprio = 0; 20812854Sgabeblack@google.com } else if (rprio != 0xff) { 20912854Sgabeblack@google.com /* Non-idle priority: show the Non-secure view of it */ 21012854Sgabeblack@google.com rprio = (rprio << 1) & 0xff; 21112854Sgabeblack@google.com } 21212854Sgabeblack@google.com } 21312854Sgabeblack@google.com 21412854Sgabeblack@google.com value = rprio; 21512854Sgabeblack@google.com break; 21612854Sgabeblack@google.com } 21712854Sgabeblack@google.com 21812854Sgabeblack@google.com case MISCREG_ICV_RPR_EL1: { 21912854Sgabeblack@google.com value = virtualHighestActivePriority(); 22012854Sgabeblack@google.com break; 22112854Sgabeblack@google.com } 22212854Sgabeblack@google.com 22312854Sgabeblack@google.com case MISCREG_ICC_HPPIR0: 22412854Sgabeblack@google.com case MISCREG_ICC_HPPIR0_EL1: { 22512854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 22612854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_HPPIR0_EL1); 22712854Sgabeblack@google.com } 22812854Sgabeblack@google.com 22912854Sgabeblack@google.com value = getHPPIR0(); 23012854Sgabeblack@google.com break; 23112854Sgabeblack@google.com } 23212854Sgabeblack@google.com 23312854Sgabeblack@google.com case MISCREG_ICV_HPPIR0_EL1: { 23412854Sgabeblack@google.com value = Gicv3::INTID_SPURIOUS; 23512854Sgabeblack@google.com int lr_idx = getHPPVILR(); 23612854Sgabeblack@google.com 23712854Sgabeblack@google.com if (lr_idx >= 0) { 23812854Sgabeblack@google.com ArmISA::MiscReg lr = 23912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 24012854Sgabeblack@google.com Gicv3::GroupId group = 24112854Sgabeblack@google.com lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; 24212854Sgabeblack@google.com 24312854Sgabeblack@google.com if (group == Gicv3::G0S) { 24412854Sgabeblack@google.com value = bits(lr, 31, 0); 24512854Sgabeblack@google.com } 24612854Sgabeblack@google.com } 24712854Sgabeblack@google.com 24812854Sgabeblack@google.com break; 24912854Sgabeblack@google.com } 25012854Sgabeblack@google.com 25112854Sgabeblack@google.com case MISCREG_ICC_HPPIR1: 25212854Sgabeblack@google.com case MISCREG_ICC_HPPIR1_EL1: { 25312854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 25412854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_HPPIR1_EL1); 25512854Sgabeblack@google.com } 25612854Sgabeblack@google.com 25712854Sgabeblack@google.com value = getHPPIR1(); 25812854Sgabeblack@google.com break; 25912854Sgabeblack@google.com } 26012854Sgabeblack@google.com 26112854Sgabeblack@google.com case MISCREG_ICV_HPPIR1_EL1: { 26212854Sgabeblack@google.com value = Gicv3::INTID_SPURIOUS; 26312854Sgabeblack@google.com int lr_idx = getHPPVILR(); 26412854Sgabeblack@google.com 26512854Sgabeblack@google.com if (lr_idx >= 0) { 26612854Sgabeblack@google.com ArmISA::MiscReg lr = 26712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 26812854Sgabeblack@google.com Gicv3::GroupId group = 26912854Sgabeblack@google.com lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; 27012854Sgabeblack@google.com 27112854Sgabeblack@google.com if (group == Gicv3::G1NS) { 27212854Sgabeblack@google.com value = bits(lr, 31, 0); 27312854Sgabeblack@google.com } 27412854Sgabeblack@google.com } 27512854Sgabeblack@google.com 27612854Sgabeblack@google.com break; 27712854Sgabeblack@google.com } 27812854Sgabeblack@google.com 27912854Sgabeblack@google.com case MISCREG_ICC_BPR0: 28012854Sgabeblack@google.com case MISCREG_ICC_BPR0_EL1: 28112854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 28212854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_BPR0_EL1); 28312854Sgabeblack@google.com } 28412854Sgabeblack@google.com 28512854Sgabeblack@google.com M5_FALLTHROUGH; 28612854Sgabeblack@google.com 28712854Sgabeblack@google.com case MISCREG_ICC_BPR1: 28812854Sgabeblack@google.com case MISCREG_ICC_BPR1_EL1: 28912854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 29012854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_BPR1_EL1); 29112854Sgabeblack@google.com } 29212854Sgabeblack@google.com 29312854Sgabeblack@google.com { 29412854Sgabeblack@google.com Gicv3::GroupId group = 29512854Sgabeblack@google.com misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; 29612854Sgabeblack@google.com 29712854Sgabeblack@google.com if (group == Gicv3::G1S && !inSecureState()) { 29812854Sgabeblack@google.com group = Gicv3::G1NS; 29912854Sgabeblack@google.com } 30012854Sgabeblack@google.com 30112854Sgabeblack@google.com if ((group == Gicv3::G1S) && 30212854Sgabeblack@google.com !isEL3OrMon() && 30312854Sgabeblack@google.com (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) 30412854Sgabeblack@google.com & ICC_CTLR_EL1_CBPR)) { 30512854Sgabeblack@google.com group = Gicv3::G0S; 30612854Sgabeblack@google.com } 30712854Sgabeblack@google.com 30812854Sgabeblack@google.com bool sat_inc = false; 30912854Sgabeblack@google.com 31012854Sgabeblack@google.com if ((group == Gicv3::G1NS) && 31112854Sgabeblack@google.com (currEL() < EL3) && 31212854Sgabeblack@google.com (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) 31312854Sgabeblack@google.com & ICC_CTLR_EL1_CBPR)) { 31412854Sgabeblack@google.com // Reads return BPR0 + 1 saturated to 7, WI 31512854Sgabeblack@google.com group = Gicv3::G0S; 31612854Sgabeblack@google.com sat_inc = true; 31712854Sgabeblack@google.com } 31812854Sgabeblack@google.com 31912854Sgabeblack@google.com uint8_t bpr; 32012854Sgabeblack@google.com 32112854Sgabeblack@google.com if (group == Gicv3::G0S) { 32212854Sgabeblack@google.com bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1); 32312854Sgabeblack@google.com } else { 32412854Sgabeblack@google.com bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1); 32512854Sgabeblack@google.com } 32612854Sgabeblack@google.com 32712854Sgabeblack@google.com if (sat_inc) { 32812854Sgabeblack@google.com bpr++; 32912854Sgabeblack@google.com 33012854Sgabeblack@google.com if (bpr > 7) { 33112854Sgabeblack@google.com bpr = 7; 33212854Sgabeblack@google.com } 33312854Sgabeblack@google.com } 33412854Sgabeblack@google.com 33512854Sgabeblack@google.com value = bpr; 33612854Sgabeblack@google.com break; 33712854Sgabeblack@google.com } 33812854Sgabeblack@google.com 33912854Sgabeblack@google.com case MISCREG_ICV_BPR0_EL1: 34012854Sgabeblack@google.com case MISCREG_ICV_BPR1_EL1: { 34112854Sgabeblack@google.com Gicv3::GroupId group = 34212854Sgabeblack@google.com misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS; 34312854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 34412854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 34512854Sgabeblack@google.com bool sat_inc = false; 34612854Sgabeblack@google.com 34712854Sgabeblack@google.com if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) { 34812854Sgabeblack@google.com // reads return bpr0 + 1 saturated to 7, writes ignored 34912854Sgabeblack@google.com group = Gicv3::G0S; 35012854Sgabeblack@google.com sat_inc = true; 35112854Sgabeblack@google.com } 35212854Sgabeblack@google.com 35312854Sgabeblack@google.com uint8_t vbpr; 35412854Sgabeblack@google.com 35512854Sgabeblack@google.com if (group == Gicv3::G0S) { 35612854Sgabeblack@google.com vbpr = bits(ich_vmcr_el2, 23, 21); 35712854Sgabeblack@google.com } else { 35812854Sgabeblack@google.com vbpr = bits(ich_vmcr_el2, 20, 18); 35912854Sgabeblack@google.com } 36012854Sgabeblack@google.com 36112854Sgabeblack@google.com if (sat_inc) { 36212854Sgabeblack@google.com vbpr++; 36312854Sgabeblack@google.com 36412854Sgabeblack@google.com if (vbpr > 7) { 36512854Sgabeblack@google.com vbpr = 7; 36612854Sgabeblack@google.com } 36712854Sgabeblack@google.com } 36812854Sgabeblack@google.com 36912854Sgabeblack@google.com value = vbpr; 37012854Sgabeblack@google.com break; 37112854Sgabeblack@google.com } 37212854Sgabeblack@google.com 37312854Sgabeblack@google.com case MISCREG_ICC_PMR: 37412854Sgabeblack@google.com case MISCREG_ICC_PMR_EL1: // Priority Mask Register 37512854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && 37612854Sgabeblack@google.com (hcr_imo || hcr_fmo)) { 37712854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICV_PMR_EL1); 37812854Sgabeblack@google.com } 37912854Sgabeblack@google.com 38012854Sgabeblack@google.com if (haveEL(EL3) && !inSecureState() && 38112854Sgabeblack@google.com (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) { 38212854Sgabeblack@google.com /* NS GIC access and Group 0 is inaccessible to NS */ 38312854Sgabeblack@google.com if ((value & 0x80) == 0) { 38412854Sgabeblack@google.com /* NS should not see priorities in the Secure half of the 38512854Sgabeblack@google.com * range */ 38612854Sgabeblack@google.com value = 0; 38712854Sgabeblack@google.com } else if (value != 0xff) { 38812854Sgabeblack@google.com /* Non-idle priority: show the Non-secure view of it */ 38912854Sgabeblack@google.com value = (value << 1) & 0xff; 39012854Sgabeblack@google.com } 39112854Sgabeblack@google.com } 39212854Sgabeblack@google.com 39312854Sgabeblack@google.com break; 39412854Sgabeblack@google.com 39512854Sgabeblack@google.com case MISCREG_ICC_IAR0: 39612854Sgabeblack@google.com case MISCREG_ICC_IAR0_EL1: { // Interrupt Acknowledge Register 0 39712854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 39812854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_IAR0_EL1); 39912854Sgabeblack@google.com } 40012854Sgabeblack@google.com 40112854Sgabeblack@google.com uint32_t int_id; 40212854Sgabeblack@google.com 40312854Sgabeblack@google.com if (hppiCanPreempt()) { 40412854Sgabeblack@google.com int_id = getHPPIR0(); 40512854Sgabeblack@google.com 40612854Sgabeblack@google.com // avoid activation for special interrupts 40712854Sgabeblack@google.com if (int_id < Gicv3::INTID_SECURE) { 40812854Sgabeblack@google.com activateIRQ(int_id, hppi.group); 40912854Sgabeblack@google.com } 41012854Sgabeblack@google.com } else { 41112854Sgabeblack@google.com int_id = Gicv3::INTID_SPURIOUS; 41212854Sgabeblack@google.com } 41312854Sgabeblack@google.com 41412854Sgabeblack@google.com value = int_id; 41512854Sgabeblack@google.com break; 41612854Sgabeblack@google.com } 41712854Sgabeblack@google.com 41812854Sgabeblack@google.com case MISCREG_ICV_IAR0_EL1: { 41912854Sgabeblack@google.com int lr_idx = getHPPVILR(); 42012854Sgabeblack@google.com uint32_t int_id = Gicv3::INTID_SPURIOUS; 42112854Sgabeblack@google.com 42212854Sgabeblack@google.com if (lr_idx >= 0) { 42312854Sgabeblack@google.com ArmISA::MiscReg lr = 42412854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 42512854Sgabeblack@google.com 42612854Sgabeblack@google.com if (!(lr & ICH_LR_EL2_GROUP) && hppviCanPreempt(lr_idx)) { 42712854Sgabeblack@google.com int_id = value = bits(lr, 31, 0); 42812854Sgabeblack@google.com 42912854Sgabeblack@google.com if (int_id < Gicv3::INTID_SECURE || 43012854Sgabeblack@google.com int_id > Gicv3::INTID_SPURIOUS) { 43112854Sgabeblack@google.com virtualActivateIRQ(lr_idx); 43212854Sgabeblack@google.com } else { 43312854Sgabeblack@google.com // Bogus... Pseudocode says: 43412854Sgabeblack@google.com // - Move from pending to invalid... 43512854Sgabeblack@google.com // - Return de bogus id... 43612854Sgabeblack@google.com lr &= ~ICH_LR_EL2_STATE_PENDING_BIT; 43712854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, 43812854Sgabeblack@google.com lr); 43912854Sgabeblack@google.com } 44012854Sgabeblack@google.com } 44112854Sgabeblack@google.com } 44212854Sgabeblack@google.com 44312854Sgabeblack@google.com value = int_id; 44413325Sgabeblack@google.com virtualUpdate(); 44512854Sgabeblack@google.com break; 44612854Sgabeblack@google.com } 44713325Sgabeblack@google.com 44812854Sgabeblack@google.com case MISCREG_ICC_IAR1: 44912854Sgabeblack@google.com case MISCREG_ICC_IAR1_EL1: { // Interrupt Acknowledge Register 1 45012854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 45112854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_IAR1_EL1); 45212854Sgabeblack@google.com } 45312854Sgabeblack@google.com 45412854Sgabeblack@google.com uint32_t int_id; 45512854Sgabeblack@google.com 45613325Sgabeblack@google.com if (hppiCanPreempt()) { 45712854Sgabeblack@google.com int_id = getHPPIR1(); 45812854Sgabeblack@google.com 45912854Sgabeblack@google.com // avoid activation for special interrupts 46012854Sgabeblack@google.com if (int_id < Gicv3::INTID_SECURE) { 46112854Sgabeblack@google.com activateIRQ(int_id, hppi.group); 46212854Sgabeblack@google.com } 46312854Sgabeblack@google.com } else { 46412854Sgabeblack@google.com int_id = Gicv3::INTID_SPURIOUS; 46512854Sgabeblack@google.com } 46612854Sgabeblack@google.com 46712854Sgabeblack@google.com value = int_id; 46812854Sgabeblack@google.com break; 46912854Sgabeblack@google.com } 47012854Sgabeblack@google.com 47112854Sgabeblack@google.com case MISCREG_ICV_IAR1_EL1: { 47212854Sgabeblack@google.com int lr_idx = getHPPVILR(); 47312854Sgabeblack@google.com uint32_t int_id = Gicv3::INTID_SPURIOUS; 47412854Sgabeblack@google.com 47512854Sgabeblack@google.com if (lr_idx >= 0) { 47612854Sgabeblack@google.com ArmISA::MiscReg lr = 47712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 47812854Sgabeblack@google.com 47912854Sgabeblack@google.com if (lr & ICH_LR_EL2_GROUP && hppviCanPreempt(lr_idx)) { 48012854Sgabeblack@google.com int_id = value = bits(lr, 31, 0); 48112854Sgabeblack@google.com 48212854Sgabeblack@google.com if (int_id < Gicv3::INTID_SECURE || 48312854Sgabeblack@google.com int_id > Gicv3::INTID_SPURIOUS) { 48412854Sgabeblack@google.com virtualActivateIRQ(lr_idx); 48512854Sgabeblack@google.com } else { 48612854Sgabeblack@google.com // Bogus... Pseudocode says: 48712854Sgabeblack@google.com // - Move from pending to invalid... 48812854Sgabeblack@google.com // - Return de bogus id... 48912854Sgabeblack@google.com lr &= ~ICH_LR_EL2_STATE_PENDING_BIT; 49012854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, 49112854Sgabeblack@google.com lr); 49212854Sgabeblack@google.com } 49312854Sgabeblack@google.com } 49412854Sgabeblack@google.com } 49512854Sgabeblack@google.com 49612854Sgabeblack@google.com value = int_id; 49712854Sgabeblack@google.com virtualUpdate(); 49812854Sgabeblack@google.com break; 49912854Sgabeblack@google.com } 50012854Sgabeblack@google.com 50112854Sgabeblack@google.com case MISCREG_ICC_SRE: 50212854Sgabeblack@google.com case MISCREG_ICC_SRE_EL1: { // System Register Enable Register 50312854Sgabeblack@google.com bool dfb; 50412854Sgabeblack@google.com bool dib; 50512854Sgabeblack@google.com 50612854Sgabeblack@google.com if (haveEL(EL3) && !distributor->DS) { 50712854Sgabeblack@google.com // DIB is RO alias of ICC_SRE_EL3.DIB 50812854Sgabeblack@google.com // DFB is RO alias of ICC_SRE_EL3.DFB 50912854Sgabeblack@google.com ArmISA::MiscReg icc_sre_el3 = 51012854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3); 51112854Sgabeblack@google.com dfb = icc_sre_el3 & ICC_SRE_EL3_DFB; 51212854Sgabeblack@google.com dib = icc_sre_el3 & ICC_SRE_EL3_DIB; 51312854Sgabeblack@google.com } else if (haveEL(EL3) && distributor->DS) { 51412854Sgabeblack@google.com // DIB is RW alias of ICC_SRE_EL3.DIB 51512854Sgabeblack@google.com // DFB is RW alias of ICC_SRE_EL3.DFB 51612854Sgabeblack@google.com ArmISA::MiscReg icc_sre_el3 = 51712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3); 51812854Sgabeblack@google.com dfb = icc_sre_el3 & ICC_SRE_EL3_DFB; 51912854Sgabeblack@google.com dib = icc_sre_el3 & ICC_SRE_EL3_DIB; 52012854Sgabeblack@google.com } else if ((!haveEL(EL3) || distributor->DS) and haveEL(EL2)) { 52112854Sgabeblack@google.com // DIB is RO alias of ICC_SRE_EL2.DIB 52212854Sgabeblack@google.com // DFB is RO alias of ICC_SRE_EL2.DFB 52312854Sgabeblack@google.com ArmISA::MiscReg icc_sre_el2 = 52412854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL2); 52512854Sgabeblack@google.com dfb = icc_sre_el2 & ICC_SRE_EL2_DFB; 52612854Sgabeblack@google.com dib = icc_sre_el2 & ICC_SRE_EL2_DIB; 52712854Sgabeblack@google.com } else { 52812854Sgabeblack@google.com dfb = value & ICC_SRE_EL1_DFB; 52912854Sgabeblack@google.com dib = value & ICC_SRE_EL1_DIB; 53012854Sgabeblack@google.com } 53112854Sgabeblack@google.com 53212854Sgabeblack@google.com value = ICC_SRE_EL1_SRE; 53312854Sgabeblack@google.com 53412854Sgabeblack@google.com if (dfb) { 53512854Sgabeblack@google.com value |= ICC_SRE_EL1_DFB; 53612854Sgabeblack@google.com } 53712854Sgabeblack@google.com 53812854Sgabeblack@google.com if (dib) { 53912854Sgabeblack@google.com value |= ICC_SRE_EL1_DIB; 54012854Sgabeblack@google.com } 54112854Sgabeblack@google.com 54212854Sgabeblack@google.com break; 54312854Sgabeblack@google.com } 54412854Sgabeblack@google.com 54512854Sgabeblack@google.com case MISCREG_ICC_HSRE: 54612854Sgabeblack@google.com case MISCREG_ICC_SRE_EL2: // System Register Enable Register 54712854Sgabeblack@google.com /* 54812854Sgabeblack@google.com * Enable [3] == 1 54912854Sgabeblack@google.com * (Secure EL1 accesses to Secure ICC_SRE_EL1 do not trap to EL2, 55012854Sgabeblack@google.com * RAO/WI) 55112854Sgabeblack@google.com * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) 55212854Sgabeblack@google.com * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) 55312854Sgabeblack@google.com * SRE [0] == 1 (Only system register interface supported, RAO/WI) 55412854Sgabeblack@google.com */ 55512854Sgabeblack@google.com value = ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_DIB | ICC_SRE_EL2_DFB | 55612854Sgabeblack@google.com ICC_SRE_EL2_SRE; 55712854Sgabeblack@google.com break; 55812854Sgabeblack@google.com 55912854Sgabeblack@google.com case MISCREG_ICC_MSRE: 56012854Sgabeblack@google.com case MISCREG_ICC_SRE_EL3: // System Register Enable Register 56112854Sgabeblack@google.com /* 56212854Sgabeblack@google.com * Enable [3] == 1 56312854Sgabeblack@google.com * (Secure EL1 accesses to Secure ICC_SRE_EL1 do not trap to EL3, 56412854Sgabeblack@google.com * RAO/WI) 56512854Sgabeblack@google.com * DIB [2] == 1 (IRQ bypass not supported, RAO/WI) 56612854Sgabeblack@google.com * DFB [1] == 1 (FIQ bypass not supported, RAO/WI) 56712854Sgabeblack@google.com * SRE [0] == 1 (Only system register interface supported, RAO/WI) 56812854Sgabeblack@google.com */ 56912854Sgabeblack@google.com value = ICC_SRE_EL3_ENABLE | ICC_SRE_EL3_DIB | ICC_SRE_EL3_DFB | 57012854Sgabeblack@google.com ICC_SRE_EL3_SRE; 57112854Sgabeblack@google.com break; 57212854Sgabeblack@google.com 57312854Sgabeblack@google.com case MISCREG_ICC_CTLR: 57412854Sgabeblack@google.com case MISCREG_ICC_CTLR_EL1: { // Control Register 57512854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && 57612854Sgabeblack@google.com (hcr_imo || hcr_fmo)) { 57712854Sgabeblack@google.com return readMiscReg(MISCREG_ICV_CTLR_EL1); 57812854Sgabeblack@google.com } 57912854Sgabeblack@google.com 58012854Sgabeblack@google.com // Add value for RO bits 58112854Sgabeblack@google.com // IDbits [13:11], 001 = 24 bits | 000 = 16 bits 58212854Sgabeblack@google.com // PRIbits [10:8], number of priority bits implemented, minus one 58312854Sgabeblack@google.com value |= ICC_CTLR_EL1_RSS | ICC_CTLR_EL1_A3V | 58412854Sgabeblack@google.com (1 << 11) | ((PRIORITY_BITS - 1) << 8); 58512854Sgabeblack@google.com break; 58612854Sgabeblack@google.com } 58712854Sgabeblack@google.com 58812854Sgabeblack@google.com case MISCREG_ICV_CTLR_EL1: { 58912854Sgabeblack@google.com value = ICC_CTLR_EL1_A3V | (1 << ICC_CTLR_EL1_IDBITS_SHIFT) | 59012854Sgabeblack@google.com (7 << ICC_CTLR_EL1_PRIBITS_SHIFT); 59112854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 59212854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 59312854Sgabeblack@google.com 59412854Sgabeblack@google.com if (ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM) { 59512854Sgabeblack@google.com value |= ICC_CTLR_EL1_EOIMODE; 59612854Sgabeblack@google.com } 59712854Sgabeblack@google.com 59812854Sgabeblack@google.com if (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) { 59912854Sgabeblack@google.com value |= ICC_CTLR_EL1_CBPR; 60012854Sgabeblack@google.com } 60112854Sgabeblack@google.com 60212854Sgabeblack@google.com break; 60312854Sgabeblack@google.com } 60412854Sgabeblack@google.com 60512854Sgabeblack@google.com case MISCREG_ICC_MCTLR: 60612854Sgabeblack@google.com case MISCREG_ICC_CTLR_EL3: { 60712854Sgabeblack@google.com // Add value for RO bits 60812854Sgabeblack@google.com // RSS [18] 60912854Sgabeblack@google.com // A3V [15] 61012854Sgabeblack@google.com // IDbits [13:11], 001 = 24 bits | 000 = 16 bits 61112854Sgabeblack@google.com // PRIbits [10:8], number of priority bits implemented, minus one 61212854Sgabeblack@google.com value |= ICC_CTLR_EL3_RSS | ICC_CTLR_EL3_A3V | (0 << 11) | 61312854Sgabeblack@google.com ((PRIORITY_BITS - 1) << 8); 61412854Sgabeblack@google.com // Aliased bits... 61512854Sgabeblack@google.com ArmISA::MiscReg icc_ctlr_el1_ns = 61612854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); 61712854Sgabeblack@google.com ArmISA::MiscReg icc_ctlr_el1_s = 61812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); 61912854Sgabeblack@google.com 62012854Sgabeblack@google.com if (icc_ctlr_el1_ns & ICC_CTLR_EL1_EOIMODE) { 62112854Sgabeblack@google.com value |= ICC_CTLR_EL3_EOIMODE_EL1NS; 62212854Sgabeblack@google.com } 62312854Sgabeblack@google.com 62412854Sgabeblack@google.com if (icc_ctlr_el1_ns & ICC_CTLR_EL1_CBPR) { 62512854Sgabeblack@google.com value |= ICC_CTLR_EL3_CBPR_EL1NS; 62612854Sgabeblack@google.com } 62712854Sgabeblack@google.com 62812854Sgabeblack@google.com if (icc_ctlr_el1_s & ICC_CTLR_EL1_EOIMODE) { 62912854Sgabeblack@google.com value |= ICC_CTLR_EL3_EOIMODE_EL1S; 63012854Sgabeblack@google.com } 63112854Sgabeblack@google.com 63212854Sgabeblack@google.com if (icc_ctlr_el1_s & ICC_CTLR_EL1_CBPR) { 63312854Sgabeblack@google.com value |= ICC_CTLR_EL3_CBPR_EL1S; 63412854Sgabeblack@google.com } 63512854Sgabeblack@google.com 63612854Sgabeblack@google.com break; 63712854Sgabeblack@google.com } 63812854Sgabeblack@google.com 63912854Sgabeblack@google.com case MISCREG_ICH_HCR: 64012854Sgabeblack@google.com case MISCREG_ICH_HCR_EL2: 64112854Sgabeblack@google.com break; 64212854Sgabeblack@google.com 64312854Sgabeblack@google.com case MISCREG_ICH_AP0R0: 64412854Sgabeblack@google.com case MISCREG_ICH_AP0R0_EL2: 64512854Sgabeblack@google.com break; 64612854Sgabeblack@google.com 64712854Sgabeblack@google.com case MISCREG_ICH_AP1R0: 64812854Sgabeblack@google.com case MISCREG_ICH_AP1R0_EL2: 64912854Sgabeblack@google.com break; 65012854Sgabeblack@google.com 65112854Sgabeblack@google.com case MISCREG_ICH_MISR: 65212854Sgabeblack@google.com case MISCREG_ICH_MISR_EL2: { 65312854Sgabeblack@google.com value = 0; 65412854Sgabeblack@google.com // Scan list registers and fill in the U, NP and EOI bits 65512854Sgabeblack@google.com eoiMaintenanceInterruptStatus((uint32_t *) &value); 65612854Sgabeblack@google.com ArmISA::MiscReg ich_hcr_el2 = 65712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 65812854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 65912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 66012854Sgabeblack@google.com 66112854Sgabeblack@google.com if (ich_hcr_el2 & 66212854Sgabeblack@google.com (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) { 66312854Sgabeblack@google.com value |= ICH_MISR_EL2_LRENP; 66412854Sgabeblack@google.com } 66512854Sgabeblack@google.com 66612854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) && 66712854Sgabeblack@google.com (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) { 66812854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP0E; 66912854Sgabeblack@google.com } 67012854Sgabeblack@google.com 67112854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) && 67212854Sgabeblack@google.com !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 67312854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP0D; 67412854Sgabeblack@google.com } 67512854Sgabeblack@google.com 67612854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) && 67712854Sgabeblack@google.com (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 67812854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP1E; 67912854Sgabeblack@google.com } 68012854Sgabeblack@google.com 68112854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) && 68212854Sgabeblack@google.com !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 68312854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP1D; 68412854Sgabeblack@google.com } 68512854Sgabeblack@google.com 68612854Sgabeblack@google.com break; 68712854Sgabeblack@google.com } 68812854Sgabeblack@google.com 68912854Sgabeblack@google.com case MISCREG_ICH_VTR: 69012854Sgabeblack@google.com case MISCREG_ICH_VTR_EL2: 69112854Sgabeblack@google.com /* 69212854Sgabeblack@google.com * PRIbits [31:29] 69312854Sgabeblack@google.com * PREbits [28:26] 69412854Sgabeblack@google.com * IDbits [25:23] 69512854Sgabeblack@google.com * SEIS [22] == 0 (SEI Support) 69612854Sgabeblack@google.com * A3V [21] == 1 69712854Sgabeblack@google.com * (Non-zero values supported for Affinity 3 in SGI genearion) 69812854Sgabeblack@google.com * nV4 [20] == 0 69912854Sgabeblack@google.com * (Support for direct injection of virtual interrupts) 70012854Sgabeblack@google.com * TDS [19] == 0 (Implementation supports ICH_HCR_EL2.TDIR) 70112854Sgabeblack@google.com * ListRegs [4:0] 70212854Sgabeblack@google.com */ 70312854Sgabeblack@google.com value = (16 - 1) << 0 | 70412854Sgabeblack@google.com (5 - 1) << 26 | 70512854Sgabeblack@google.com (5 - 1) << 29; 70612854Sgabeblack@google.com value = 70712854Sgabeblack@google.com ((VIRTUAL_NUM_LIST_REGS - 1) << ICH_VTR_EL2_LISTREGS_SHIFT) | 70812854Sgabeblack@google.com // ICH_VTR_EL2_TDS | 70912854Sgabeblack@google.com // ICH_VTR_EL2_NV4 | 71012854Sgabeblack@google.com ICH_VTR_EL2_A3V | 71112854Sgabeblack@google.com (1 << ICH_VTR_EL2_IDBITS_SHIFT) | 71212854Sgabeblack@google.com ((VIRTUAL_PREEMPTION_BITS - 1) << ICH_VTR_EL2_PREBITS_SHIFT) | 71312854Sgabeblack@google.com ((VIRTUAL_PRIORITY_BITS - 1) << ICH_VTR_EL2_PRIBITS_SHIFT); 71412854Sgabeblack@google.com break; 71512854Sgabeblack@google.com 71612854Sgabeblack@google.com case MISCREG_ICH_EISR: 71712854Sgabeblack@google.com case MISCREG_ICH_EISR_EL2: 71812854Sgabeblack@google.com value = eoiMaintenanceInterruptStatus(nullptr); 71912854Sgabeblack@google.com break; 72012854Sgabeblack@google.com 72112854Sgabeblack@google.com case MISCREG_ICH_ELRSR: 72212854Sgabeblack@google.com case MISCREG_ICH_ELRSR_EL2: 72312854Sgabeblack@google.com value = 0; 72412854Sgabeblack@google.com 72512854Sgabeblack@google.com for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 72612854Sgabeblack@google.com ArmISA::MiscReg lr = 72712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 72812854Sgabeblack@google.com 72912854Sgabeblack@google.com if ((lr & ICH_LR_EL2_STATE_MASK) == 0 && 73012854Sgabeblack@google.com ((lr & ICH_LR_EL2_HW) != 0 || 73112854Sgabeblack@google.com (lr & ICH_LR_EL2_EOI) == 0)) { 73212854Sgabeblack@google.com value |= (1 << lr_idx); 73312854Sgabeblack@google.com } 73412854Sgabeblack@google.com } 73512854Sgabeblack@google.com 73612854Sgabeblack@google.com break; 73712854Sgabeblack@google.com 73812854Sgabeblack@google.com case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: 73912854Sgabeblack@google.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part) 74012854Sgabeblack@google.com value = value >> 32; 74112854Sgabeblack@google.com break; 74212854Sgabeblack@google.com 74312854Sgabeblack@google.com case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: 74412854Sgabeblack@google.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part) 74512854Sgabeblack@google.com value = value & 0xffffffff; 74612854Sgabeblack@google.com break; 74712854Sgabeblack@google.com 74812854Sgabeblack@google.com case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: 74912854Sgabeblack@google.com break; 75012854Sgabeblack@google.com 75112854Sgabeblack@google.com case MISCREG_ICH_VMCR: 75212854Sgabeblack@google.com case MISCREG_ICH_VMCR_EL2: 75312854Sgabeblack@google.com break; 75412854Sgabeblack@google.com 75512854Sgabeblack@google.com default: 75612854Sgabeblack@google.com panic("Gicv3CPUInterface::readMiscReg(): " 75712854Sgabeblack@google.com "unknown register %d (%s)", 75812854Sgabeblack@google.com misc_reg, miscRegName[misc_reg]); 75912854Sgabeblack@google.com } 76012854Sgabeblack@google.com 76112854Sgabeblack@google.com DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): " 76212854Sgabeblack@google.com "register %s value %#x\n", miscRegName[misc_reg], value); 76312854Sgabeblack@google.com return value; 76412854Sgabeblack@google.com} 76512854Sgabeblack@google.com 76612854Sgabeblack@google.comvoid 76712854Sgabeblack@google.comGicv3CPUInterface::setMiscReg(int misc_reg, ArmISA::MiscReg val) 76812854Sgabeblack@google.com{ 76912854Sgabeblack@google.com bool do_virtual_update = false; 77012854Sgabeblack@google.com DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): " 77112854Sgabeblack@google.com "register %s value %#x\n", miscRegName[misc_reg], val); 77212854Sgabeblack@google.com bool hcr_fmo = getHCREL2FMO(); 77312854Sgabeblack@google.com bool hcr_imo = getHCREL2IMO(); 77412854Sgabeblack@google.com 77512854Sgabeblack@google.com switch (misc_reg) { 77612854Sgabeblack@google.com case MISCREG_ICC_AP1R0: 77712854Sgabeblack@google.com case MISCREG_ICC_AP1R0_EL1: 77812854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 77912854Sgabeblack@google.com return isa->setMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1, val); 78012854Sgabeblack@google.com } 78112854Sgabeblack@google.com 78212854Sgabeblack@google.com break; 78312854Sgabeblack@google.com 78412854Sgabeblack@google.com case MISCREG_ICC_AP1R1: 78512854Sgabeblack@google.com case MISCREG_ICC_AP1R1_EL1: 78612854Sgabeblack@google.com 78712854Sgabeblack@google.com // only implemented if supporting 6 or more bits of priority 78812854Sgabeblack@google.com case MISCREG_ICC_AP1R2: 78912854Sgabeblack@google.com case MISCREG_ICC_AP1R2_EL1: 79012854Sgabeblack@google.com 79112854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 79212854Sgabeblack@google.com case MISCREG_ICC_AP1R3: 79312854Sgabeblack@google.com case MISCREG_ICC_AP1R3_EL1: 79412854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 79512854Sgabeblack@google.com break; 79612854Sgabeblack@google.com 79712854Sgabeblack@google.com case MISCREG_ICC_AP0R0: 79812854Sgabeblack@google.com case MISCREG_ICC_AP0R0_EL1: 79912854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 80012854Sgabeblack@google.com return isa->setMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1, val); 80112854Sgabeblack@google.com } 80212854Sgabeblack@google.com 80312854Sgabeblack@google.com break; 80412854Sgabeblack@google.com 80512854Sgabeblack@google.com case MISCREG_ICC_AP0R1: 80612854Sgabeblack@google.com case MISCREG_ICC_AP0R1_EL1: 80712854Sgabeblack@google.com 80812854Sgabeblack@google.com // only implemented if supporting 6 or more bits of priority 80912854Sgabeblack@google.com case MISCREG_ICC_AP0R2: 81012854Sgabeblack@google.com case MISCREG_ICC_AP0R2_EL1: 81112854Sgabeblack@google.com 81212854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 81312854Sgabeblack@google.com case MISCREG_ICC_AP0R3: 81412854Sgabeblack@google.com case MISCREG_ICC_AP0R3_EL1: 81512854Sgabeblack@google.com // only implemented if supporting 7 or more bits of priority 81612854Sgabeblack@google.com break; 81712854Sgabeblack@google.com 81812854Sgabeblack@google.com case MISCREG_ICC_EOIR0: 81912854Sgabeblack@google.com case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0 82012854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 82112854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_EOIR0_EL1, val); 82212854Sgabeblack@google.com } 82312854Sgabeblack@google.com 82412854Sgabeblack@google.com int int_id = val & 0xffffff; 82512854Sgabeblack@google.com 82612854Sgabeblack@google.com // avoid activation for special interrupts 82712854Sgabeblack@google.com if (int_id >= Gicv3::INTID_SECURE) { 82812854Sgabeblack@google.com return; 82912854Sgabeblack@google.com } 83012854Sgabeblack@google.com 83112854Sgabeblack@google.com Gicv3::GroupId group = Gicv3::G0S; 83212854Sgabeblack@google.com 83312854Sgabeblack@google.com if (highestActiveGroup() != group) { 83412854Sgabeblack@google.com return; 83512854Sgabeblack@google.com } 83612854Sgabeblack@google.com 83712854Sgabeblack@google.com dropPriority(group); 83812854Sgabeblack@google.com 83912854Sgabeblack@google.com if (!isEOISplitMode()) { 84012854Sgabeblack@google.com deactivateIRQ(int_id, group); 84112854Sgabeblack@google.com } 84212854Sgabeblack@google.com 84312854Sgabeblack@google.com break; 84412854Sgabeblack@google.com } 84512854Sgabeblack@google.com 84612854Sgabeblack@google.com case MISCREG_ICV_EOIR0_EL1: { 84712854Sgabeblack@google.com int int_id = val & 0xffffff; 84812854Sgabeblack@google.com 84912854Sgabeblack@google.com // avoid deactivation for special interrupts 85012854Sgabeblack@google.com if (int_id >= Gicv3::INTID_SECURE && 85112854Sgabeblack@google.com int_id <= Gicv3::INTID_SPURIOUS) { 85212854Sgabeblack@google.com return; 85312854Sgabeblack@google.com } 85412854Sgabeblack@google.com 85512854Sgabeblack@google.com uint8_t drop_prio = virtualDropPriority(); 85612854Sgabeblack@google.com 85712854Sgabeblack@google.com if (drop_prio == 0xff) { 85812854Sgabeblack@google.com return; 85912854Sgabeblack@google.com } 86012854Sgabeblack@google.com 86112854Sgabeblack@google.com int lr_idx = virtualFindActive(int_id); 86212854Sgabeblack@google.com 86312854Sgabeblack@google.com if (lr_idx < 0) { 86412854Sgabeblack@google.com // No LR found matching 86512854Sgabeblack@google.com virtualIncrementEOICount(); 86612854Sgabeblack@google.com } else { 86712854Sgabeblack@google.com ArmISA::MiscReg lr = 86812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 86912854Sgabeblack@google.com Gicv3::GroupId lr_group = 87012854Sgabeblack@google.com lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; 87112854Sgabeblack@google.com uint8_t lr_group_prio = bits(lr, 55, 48) & 0xf8; 87212854Sgabeblack@google.com 87312854Sgabeblack@google.com if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) { 87412854Sgabeblack@google.com //JAIRO if (!virtualIsEOISplitMode()) 87512854Sgabeblack@google.com { 87612854Sgabeblack@google.com virtualDeactivateIRQ(lr_idx); 87712854Sgabeblack@google.com } 87812854Sgabeblack@google.com } 87912854Sgabeblack@google.com } 88012854Sgabeblack@google.com 88112854Sgabeblack@google.com virtualUpdate(); 88212854Sgabeblack@google.com break; 88312854Sgabeblack@google.com } 88412854Sgabeblack@google.com 88512854Sgabeblack@google.com case MISCREG_ICC_EOIR1: 88612854Sgabeblack@google.com case MISCREG_ICC_EOIR1_EL1: { // End Of Interrupt Register 1 88712854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 88812854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_EOIR1_EL1, val); 88912854Sgabeblack@google.com } 89012854Sgabeblack@google.com 89112854Sgabeblack@google.com int int_id = val & 0xffffff; 89212854Sgabeblack@google.com 89312854Sgabeblack@google.com // avoid deactivation for special interrupts 89412854Sgabeblack@google.com if (int_id >= Gicv3::INTID_SECURE) { 89512854Sgabeblack@google.com return; 89612854Sgabeblack@google.com } 89712854Sgabeblack@google.com 89812854Sgabeblack@google.com Gicv3::GroupId group = 89912854Sgabeblack@google.com inSecureState() ? Gicv3::G1S : Gicv3::G1NS; 90012854Sgabeblack@google.com 90112854Sgabeblack@google.com if (highestActiveGroup() == Gicv3::G0S) { 90212854Sgabeblack@google.com return; 90312854Sgabeblack@google.com } 90412854Sgabeblack@google.com 90512854Sgabeblack@google.com if (distributor->DS == 0) { 90612854Sgabeblack@google.com if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) { 90712854Sgabeblack@google.com return; 90812854Sgabeblack@google.com } else if (highestActiveGroup() == Gicv3::G1NS && 90912854Sgabeblack@google.com !(!inSecureState() or (currEL() == EL3))) { 91012854Sgabeblack@google.com return; 91112854Sgabeblack@google.com } 91212854Sgabeblack@google.com } 91312854Sgabeblack@google.com 91412854Sgabeblack@google.com dropPriority(group); 91512854Sgabeblack@google.com 91612854Sgabeblack@google.com if (!isEOISplitMode()) { 91712854Sgabeblack@google.com deactivateIRQ(int_id, group); 91812854Sgabeblack@google.com } 91912854Sgabeblack@google.com 92012854Sgabeblack@google.com break; 92112854Sgabeblack@google.com } 92212854Sgabeblack@google.com 92312854Sgabeblack@google.com case MISCREG_ICV_EOIR1_EL1: { 92412854Sgabeblack@google.com int int_id = val & 0xffffff; 92512854Sgabeblack@google.com 92612854Sgabeblack@google.com // avoid deactivation for special interrupts 92712854Sgabeblack@google.com if (int_id >= Gicv3::INTID_SECURE && 92812854Sgabeblack@google.com int_id <= Gicv3::INTID_SPURIOUS) { 92912854Sgabeblack@google.com return; 93012854Sgabeblack@google.com } 93112854Sgabeblack@google.com 93212854Sgabeblack@google.com uint8_t drop_prio = virtualDropPriority(); 93312854Sgabeblack@google.com 93412854Sgabeblack@google.com if (drop_prio == 0xff) { 93512854Sgabeblack@google.com return; 93612854Sgabeblack@google.com } 93712854Sgabeblack@google.com 93812854Sgabeblack@google.com int lr_idx = virtualFindActive(int_id); 93912854Sgabeblack@google.com 94012854Sgabeblack@google.com if (lr_idx < 0) { 94112854Sgabeblack@google.com // No LR found matching 94212854Sgabeblack@google.com virtualIncrementEOICount(); 94312854Sgabeblack@google.com } else { 94412854Sgabeblack@google.com ArmISA::MiscReg lr = 94512854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 94612854Sgabeblack@google.com Gicv3::GroupId lr_group = 94712854Sgabeblack@google.com lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; 94812854Sgabeblack@google.com uint8_t lr_group_prio = bits(lr, 55, 48) & 0xf8; 94912854Sgabeblack@google.com 95012854Sgabeblack@google.com if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) { 95112854Sgabeblack@google.com if (!virtualIsEOISplitMode()) { 95212854Sgabeblack@google.com virtualDeactivateIRQ(lr_idx); 95312854Sgabeblack@google.com } 95412854Sgabeblack@google.com } 95512854Sgabeblack@google.com } 95612854Sgabeblack@google.com 95712854Sgabeblack@google.com virtualUpdate(); 95812854Sgabeblack@google.com break; 95912854Sgabeblack@google.com } 96012854Sgabeblack@google.com 96112854Sgabeblack@google.com case MISCREG_ICC_DIR: 96212854Sgabeblack@google.com case MISCREG_ICC_DIR_EL1: { // Deactivate Interrupt Register 96312854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && 96412854Sgabeblack@google.com (hcr_imo || hcr_fmo)) { 96512854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_DIR_EL1, val); 96612854Sgabeblack@google.com } 96712854Sgabeblack@google.com 96812854Sgabeblack@google.com int int_id = val & 0xffffff; 96912854Sgabeblack@google.com 97012854Sgabeblack@google.com // avoid deactivation for special interrupts 97112854Sgabeblack@google.com if (int_id >= Gicv3::INTID_SECURE) { 97212854Sgabeblack@google.com return; 97312854Sgabeblack@google.com } 97412854Sgabeblack@google.com 97512854Sgabeblack@google.com if (!isEOISplitMode()) { 97612854Sgabeblack@google.com return; 97712854Sgabeblack@google.com } 97812854Sgabeblack@google.com 97912854Sgabeblack@google.com /* 98012854Sgabeblack@google.com * Check whether we're allowed to deactivate. 98112854Sgabeblack@google.com * These checks are correspond to the spec's pseudocode. 98212854Sgabeblack@google.com */ 98312854Sgabeblack@google.com Gicv3::GroupId group = 98412854Sgabeblack@google.com int_id >= 32 ? distributor->getIntGroup(int_id) : 98512854Sgabeblack@google.com redistributor->getIntGroup(int_id); 98612854Sgabeblack@google.com bool irq_is_grp0 = group == Gicv3::G0S; 98712854Sgabeblack@google.com bool single_sec_state = distributor->DS; 98812854Sgabeblack@google.com bool irq_is_secure = !single_sec_state && (group != Gicv3::G1NS); 98912854Sgabeblack@google.com SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); 99012854Sgabeblack@google.com bool route_fiq_to_el3 = scr_el3.fiq; 99112854Sgabeblack@google.com bool route_irq_to_el3 = scr_el3.irq; 99212854Sgabeblack@google.com bool route_fiq_to_el2 = hcr_fmo; 99312854Sgabeblack@google.com bool route_irq_to_el2 = hcr_imo; 99412854Sgabeblack@google.com 99512854Sgabeblack@google.com switch (currEL()) { 99612854Sgabeblack@google.com case EL3: 99712854Sgabeblack@google.com break; 99812854Sgabeblack@google.com 99912854Sgabeblack@google.com case EL2: 100012854Sgabeblack@google.com if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) { 100112854Sgabeblack@google.com break; 100212854Sgabeblack@google.com } 100312854Sgabeblack@google.com 100412854Sgabeblack@google.com if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) { 100512854Sgabeblack@google.com break; 100612854Sgabeblack@google.com } 100712854Sgabeblack@google.com 100812854Sgabeblack@google.com return; 100912854Sgabeblack@google.com 101012854Sgabeblack@google.com case EL1: 101112854Sgabeblack@google.com if (!isSecureBelowEL3()) { 101212854Sgabeblack@google.com if (single_sec_state && irq_is_grp0 && 101312854Sgabeblack@google.com !route_fiq_to_el3 && !route_fiq_to_el2) { 101412854Sgabeblack@google.com break; 101512854Sgabeblack@google.com } 101612854Sgabeblack@google.com 101712854Sgabeblack@google.com if (!irq_is_secure && !irq_is_grp0 && 101812854Sgabeblack@google.com !route_irq_to_el3 && !route_irq_to_el2) { 101912854Sgabeblack@google.com break; 102012854Sgabeblack@google.com } 102112854Sgabeblack@google.com } else { 102212854Sgabeblack@google.com if (irq_is_grp0 && !route_fiq_to_el3) { 102312854Sgabeblack@google.com break; 102412854Sgabeblack@google.com } 102512854Sgabeblack@google.com 102612854Sgabeblack@google.com if (!irq_is_grp0 && 102712854Sgabeblack@google.com (!irq_is_secure || !single_sec_state) && 102812854Sgabeblack@google.com !route_irq_to_el3) { 102912854Sgabeblack@google.com break; 103012854Sgabeblack@google.com } 103112854Sgabeblack@google.com } 103212854Sgabeblack@google.com 103312854Sgabeblack@google.com return; 103412854Sgabeblack@google.com 103512854Sgabeblack@google.com default: 103612854Sgabeblack@google.com break; 103712854Sgabeblack@google.com } 103812854Sgabeblack@google.com 103912854Sgabeblack@google.com deactivateIRQ(int_id, group); 104012854Sgabeblack@google.com break; 104112854Sgabeblack@google.com } 104212854Sgabeblack@google.com 104312854Sgabeblack@google.com case MISCREG_ICV_DIR_EL1: { 104412854Sgabeblack@google.com int int_id = val & 0xffffff; 104512854Sgabeblack@google.com 104612854Sgabeblack@google.com // avoid deactivation for special interrupts 104712854Sgabeblack@google.com if (int_id >= Gicv3::INTID_SECURE && 104812854Sgabeblack@google.com int_id <= Gicv3::INTID_SPURIOUS) { 104912854Sgabeblack@google.com return; 105012854Sgabeblack@google.com } 105112854Sgabeblack@google.com 105212854Sgabeblack@google.com if (!virtualIsEOISplitMode()) { 105312854Sgabeblack@google.com return; 105412854Sgabeblack@google.com } 105512854Sgabeblack@google.com 105612854Sgabeblack@google.com int lr_idx = virtualFindActive(int_id); 105712854Sgabeblack@google.com 105812854Sgabeblack@google.com if (lr_idx < 0) { 105912854Sgabeblack@google.com // No LR found matching 106012854Sgabeblack@google.com virtualIncrementEOICount(); 106112854Sgabeblack@google.com } else { 106212854Sgabeblack@google.com virtualDeactivateIRQ(lr_idx); 106312854Sgabeblack@google.com } 106412854Sgabeblack@google.com 106512854Sgabeblack@google.com virtualUpdate(); 106612854Sgabeblack@google.com break; 106712854Sgabeblack@google.com } 106812854Sgabeblack@google.com 106912854Sgabeblack@google.com case MISCREG_ICC_BPR0: 107012854Sgabeblack@google.com case MISCREG_ICC_BPR0_EL1: // Binary Point Register 0 107112854Sgabeblack@google.com case MISCREG_ICC_BPR1: 107212854Sgabeblack@google.com case MISCREG_ICC_BPR1_EL1: { // Binary Point Register 1 107312854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState()) { 107412854Sgabeblack@google.com if (misc_reg == MISCREG_ICC_BPR0_EL1 && hcr_fmo) { 107512854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_BPR0_EL1, val); 107612854Sgabeblack@google.com } else if (misc_reg == MISCREG_ICC_BPR1_EL1 && hcr_imo) { 107712854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_BPR1_EL1, val); 107812854Sgabeblack@google.com } 107912854Sgabeblack@google.com } 108012854Sgabeblack@google.com 108112854Sgabeblack@google.com Gicv3::GroupId group = 108212854Sgabeblack@google.com misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S; 108312854Sgabeblack@google.com 108412854Sgabeblack@google.com if (group == Gicv3::G1S && !inSecureState()) { 108512854Sgabeblack@google.com group = Gicv3::G1NS; 108612854Sgabeblack@google.com } 108712854Sgabeblack@google.com 108812854Sgabeblack@google.com if ((group == Gicv3::G1S) && 108912854Sgabeblack@google.com !isEL3OrMon() && 109012854Sgabeblack@google.com (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) & 109112854Sgabeblack@google.com ICC_CTLR_EL1_CBPR)) { 109212854Sgabeblack@google.com group = Gicv3::G0S; 109312854Sgabeblack@google.com } 109412854Sgabeblack@google.com 109512854Sgabeblack@google.com if ((group == Gicv3::G1NS) && 109612854Sgabeblack@google.com (currEL() < EL3) && 109712854Sgabeblack@google.com (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) & 109812854Sgabeblack@google.com ICC_CTLR_EL1_CBPR)) { 109912854Sgabeblack@google.com // Reads return BPR0 + 1 saturated to 7, WI 110012854Sgabeblack@google.com return; 110112854Sgabeblack@google.com } 110212854Sgabeblack@google.com 110312854Sgabeblack@google.com uint8_t min_val = (group == Gicv3::G1NS) ? 110412854Sgabeblack@google.com GIC_MIN_BPR_NS : GIC_MIN_BPR; 110512854Sgabeblack@google.com val &= 0x7; 110612854Sgabeblack@google.com 110712854Sgabeblack@google.com if (val < min_val) { 110812854Sgabeblack@google.com val = min_val; 110912854Sgabeblack@google.com } 111012854Sgabeblack@google.com 111112854Sgabeblack@google.com break; 111212854Sgabeblack@google.com } 111312854Sgabeblack@google.com 111412854Sgabeblack@google.com case MISCREG_ICV_BPR0_EL1: 111512854Sgabeblack@google.com case MISCREG_ICV_BPR1_EL1: { 111612854Sgabeblack@google.com Gicv3::GroupId group = 111712854Sgabeblack@google.com misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS; 111812854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 111912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 112012854Sgabeblack@google.com 112112854Sgabeblack@google.com if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) { 112212854Sgabeblack@google.com // reads return bpr0 + 1 saturated to 7, writes ignored 112312854Sgabeblack@google.com return; 112412854Sgabeblack@google.com } 112512854Sgabeblack@google.com 112612854Sgabeblack@google.com uint8_t min_VPBR = 7 - VIRTUAL_PREEMPTION_BITS; 112712854Sgabeblack@google.com 112812854Sgabeblack@google.com if (group != Gicv3::G0S) { 112912854Sgabeblack@google.com min_VPBR++; 113012854Sgabeblack@google.com } 113112854Sgabeblack@google.com 113212854Sgabeblack@google.com if (val < min_VPBR) { 113312854Sgabeblack@google.com val = min_VPBR; 113412854Sgabeblack@google.com } 113512854Sgabeblack@google.com 113612854Sgabeblack@google.com if (group == Gicv3::G0S) { 113712854Sgabeblack@google.com ich_vmcr_el2 = insertBits(ich_vmcr_el2, 113812854Sgabeblack@google.com ICH_VMCR_EL2_VBPR0_SHIFT + 2, ICH_VMCR_EL2_VBPR0_SHIFT, 113912854Sgabeblack@google.com val); 114012854Sgabeblack@google.com } else { 114112854Sgabeblack@google.com ich_vmcr_el2 = insertBits(ich_vmcr_el2, 114212854Sgabeblack@google.com ICH_VMCR_EL2_VBPR1_SHIFT + 2, ICH_VMCR_EL2_VBPR1_SHIFT, 114312854Sgabeblack@google.com val); 114412854Sgabeblack@google.com } 114512854Sgabeblack@google.com 114612854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 114712854Sgabeblack@google.com do_virtual_update = true; 114812854Sgabeblack@google.com break; 114912854Sgabeblack@google.com } 115012854Sgabeblack@google.com 115112854Sgabeblack@google.com case MISCREG_ICC_CTLR: 115212854Sgabeblack@google.com case MISCREG_ICC_CTLR_EL1: { // Control Register 115312854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && 115412854Sgabeblack@google.com (hcr_imo || hcr_fmo)) { 115512854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_CTLR_EL1, val); 115612854Sgabeblack@google.com } 115712854Sgabeblack@google.com 115812854Sgabeblack@google.com /* 115912854Sgabeblack@google.com * RSS is RO. 116012854Sgabeblack@google.com * A3V is RO. 116112854Sgabeblack@google.com * SEIS is RO. 116212854Sgabeblack@google.com * IDbits is RO. 116312854Sgabeblack@google.com * PRIbits is RO. 116412854Sgabeblack@google.com * If EL3 is implemented and GICD_CTLR.DS == 0, then PMHE is RO. 116512854Sgabeblack@google.com * So, only CBPR[0] and EOIMODE[1] are RW. 116612854Sgabeblack@google.com * If EL3 is implemented and GICD_CTLR.DS == 0, then CBPR is RO. 116712854Sgabeblack@google.com */ 116812854Sgabeblack@google.com uint64_t mask; 116912854Sgabeblack@google.com 117012854Sgabeblack@google.com if (haveEL(EL3) and distributor->DS == 0) { 117112854Sgabeblack@google.com mask = ICC_CTLR_EL1_EOIMODE; 117212854Sgabeblack@google.com } else if (haveEL(EL3) and distributor->DS == 1) { 117312854Sgabeblack@google.com mask = ICC_CTLR_EL1_PMHE | ICC_CTLR_EL1_CBPR | 117412854Sgabeblack@google.com ICC_CTLR_EL1_EOIMODE; 117512854Sgabeblack@google.com } else { 117612854Sgabeblack@google.com mask = ICC_CTLR_EL1_CBPR | ICC_CTLR_EL1_EOIMODE; 117712854Sgabeblack@google.com } 117812854Sgabeblack@google.com 117912854Sgabeblack@google.com ArmISA::MiscReg old_val = 118012854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1); 118112854Sgabeblack@google.com old_val &= ~mask; 118212854Sgabeblack@google.com val = old_val | (val & mask); 118312854Sgabeblack@google.com break; 118412854Sgabeblack@google.com } 118512854Sgabeblack@google.com 118612854Sgabeblack@google.com case MISCREG_ICV_CTLR_EL1: { 118712854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 118812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 118912854Sgabeblack@google.com ich_vmcr_el2 = insertBits(ich_vmcr_el2, ICH_VMCR_EL2_VCBPR_SHIFT, 119012854Sgabeblack@google.com val & ICC_CTLR_EL1_CBPR ? 1 : 0); 119112854Sgabeblack@google.com ich_vmcr_el2 = insertBits(ich_vmcr_el2, ICH_VMCR_EL2_VEOIM_SHIFT, 119212854Sgabeblack@google.com val & ICC_CTLR_EL1_EOIMODE ? 1 : 0); 119312854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 119412854Sgabeblack@google.com do_virtual_update = true; 119512854Sgabeblack@google.com break; 119612854Sgabeblack@google.com } 119712854Sgabeblack@google.com 119812854Sgabeblack@google.com case MISCREG_ICC_MCTLR: 119912854Sgabeblack@google.com case MISCREG_ICC_CTLR_EL3: { 120012854Sgabeblack@google.com ArmISA::MiscReg icc_ctlr_el1_s = 120112854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S); 120212854Sgabeblack@google.com ArmISA::MiscReg icc_ctlr_el1_ns = 120312854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS); 120412854Sgabeblack@google.com 120512854Sgabeblack@google.com // ICC_CTLR_EL1(NS).EOImode is an alias of 120612854Sgabeblack@google.com // ICC_CTLR_EL3.EOImode_EL1NS 120712854Sgabeblack@google.com if (val & ICC_CTLR_EL3_EOIMODE_EL1NS) { 120812854Sgabeblack@google.com icc_ctlr_el1_ns |= ICC_CTLR_EL1_EOIMODE; 120912854Sgabeblack@google.com } else { 121012854Sgabeblack@google.com icc_ctlr_el1_ns &= ~ICC_CTLR_EL1_EOIMODE; 121112854Sgabeblack@google.com } 121212854Sgabeblack@google.com 121312854Sgabeblack@google.com // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS 121412854Sgabeblack@google.com if (val & ICC_CTLR_EL3_CBPR_EL1NS) { 121512854Sgabeblack@google.com icc_ctlr_el1_ns |= ICC_CTLR_EL1_CBPR; 121612854Sgabeblack@google.com } else { 121712854Sgabeblack@google.com icc_ctlr_el1_ns &= ~ICC_CTLR_EL1_CBPR; 121812854Sgabeblack@google.com } 121912854Sgabeblack@google.com 122012854Sgabeblack@google.com // ICC_CTLR_EL1(S).EOImode is an alias of ICC_CTLR_EL3.EOImode_EL1S 122112854Sgabeblack@google.com if (val & ICC_CTLR_EL3_EOIMODE_EL1S) { 122212854Sgabeblack@google.com icc_ctlr_el1_s |= ICC_CTLR_EL1_EOIMODE; 122312854Sgabeblack@google.com } else { 122412854Sgabeblack@google.com icc_ctlr_el1_s &= ~ICC_CTLR_EL1_EOIMODE; 122512854Sgabeblack@google.com } 122612854Sgabeblack@google.com 122712854Sgabeblack@google.com // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S 122812854Sgabeblack@google.com if (val & ICC_CTLR_EL3_CBPR_EL1S) { 122912854Sgabeblack@google.com icc_ctlr_el1_s |= ICC_CTLR_EL1_CBPR; 123012854Sgabeblack@google.com } else { 123112854Sgabeblack@google.com icc_ctlr_el1_s &= ~ICC_CTLR_EL1_CBPR; 123212854Sgabeblack@google.com } 123312854Sgabeblack@google.com 123412854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s); 123512854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS, icc_ctlr_el1_ns); 123612854Sgabeblack@google.com // Only ICC_CTLR_EL3_EOIMODE_EL3 is writable 123712854Sgabeblack@google.com ArmISA::MiscReg old_icc_ctlr_el3 = 123812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3); 123912854Sgabeblack@google.com old_icc_ctlr_el3 &= ~(ICC_CTLR_EL3_EOIMODE_EL3 | ICC_CTLR_EL3_RM); 124012854Sgabeblack@google.com val = old_icc_ctlr_el3 | 124112854Sgabeblack@google.com (val & (ICC_CTLR_EL3_EOIMODE_EL3 | ICC_CTLR_EL3_RM)); 124212854Sgabeblack@google.com break; 124312854Sgabeblack@google.com } 124412854Sgabeblack@google.com 124512854Sgabeblack@google.com case MISCREG_ICC_PMR: 124612854Sgabeblack@google.com case MISCREG_ICC_PMR_EL1: { // Priority Mask Register 124712854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && 124812854Sgabeblack@google.com (hcr_imo || hcr_fmo)) { 124912854Sgabeblack@google.com return isa->setMiscRegNoEffect(MISCREG_ICV_PMR_EL1, val); 125012854Sgabeblack@google.com } 125112854Sgabeblack@google.com 125212854Sgabeblack@google.com val &= 0xff; 125312854Sgabeblack@google.com SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); 125412854Sgabeblack@google.com 125512854Sgabeblack@google.com if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) { 125612854Sgabeblack@google.com /* 125712854Sgabeblack@google.com * NS access and Group 0 is inaccessible to NS: return the 125812854Sgabeblack@google.com * NS view of the current priority 125912854Sgabeblack@google.com */ 126012854Sgabeblack@google.com ArmISA::MiscReg old_icc_pmr_el1 = 126112854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1); 126212854Sgabeblack@google.com 126312854Sgabeblack@google.com if (!(old_icc_pmr_el1 & 0x80)) { 126412854Sgabeblack@google.com /* Current PMR in the secure range, don't allow NS to 126512854Sgabeblack@google.com * change it */ 126612854Sgabeblack@google.com return; 126712854Sgabeblack@google.com } 126812854Sgabeblack@google.com 126912854Sgabeblack@google.com val = (val >> 1) | 0x80; 127012854Sgabeblack@google.com } 127112854Sgabeblack@google.com 127212854Sgabeblack@google.com val &= ~0U << (8 - PRIORITY_BITS); 127312854Sgabeblack@google.com break; 127412854Sgabeblack@google.com } 127512854Sgabeblack@google.com 127612854Sgabeblack@google.com case MISCREG_ICC_IGRPEN0: 127712854Sgabeblack@google.com case MISCREG_ICC_IGRPEN0_EL1: { // Interrupt Group 0 Enable Register 127812854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_fmo) { 127912854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val); 128012854Sgabeblack@google.com } 128112854Sgabeblack@google.com 128212854Sgabeblack@google.com break; 128312854Sgabeblack@google.com } 128412854Sgabeblack@google.com 128512854Sgabeblack@google.com case MISCREG_ICV_IGRPEN0_EL1: { 128612854Sgabeblack@google.com bool enable = val & 0x1; 128712854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 128812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 128912854Sgabeblack@google.com ich_vmcr_el2 = insertBits(ich_vmcr_el2, 129012854Sgabeblack@google.com ICH_VMCR_EL2_VENG0_SHIFT, enable); 129112854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 129212854Sgabeblack@google.com virtualUpdate(); 129312854Sgabeblack@google.com return; 129412854Sgabeblack@google.com } 129512854Sgabeblack@google.com 129612854Sgabeblack@google.com case MISCREG_ICC_IGRPEN1: 129712854Sgabeblack@google.com case MISCREG_ICC_IGRPEN1_EL1: { // Interrupt Group 1 Enable Register 129812854Sgabeblack@google.com if ((currEL() == EL1) && !inSecureState() && hcr_imo) { 129912854Sgabeblack@google.com return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val); 130012854Sgabeblack@google.com } 130112854Sgabeblack@google.com 130212854Sgabeblack@google.com break; 130312854Sgabeblack@google.com } 130412854Sgabeblack@google.com 130512854Sgabeblack@google.com case MISCREG_ICV_IGRPEN1_EL1: { 130612854Sgabeblack@google.com bool enable = val & 0x1; 130712854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 130812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 130912854Sgabeblack@google.com ich_vmcr_el2 = insertBits(ich_vmcr_el2, 131012854Sgabeblack@google.com ICH_VMCR_EL2_VENG1_SHIFT, enable); 131112854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2); 131212854Sgabeblack@google.com virtualUpdate(); 131312854Sgabeblack@google.com return; 131412854Sgabeblack@google.com } 131512854Sgabeblack@google.com 131612854Sgabeblack@google.com case MISCREG_ICC_MGRPEN1: 131712854Sgabeblack@google.com case MISCREG_ICC_IGRPEN1_EL3: { 131812854Sgabeblack@google.com // EnableGrp1S and EnableGrp1NS are aliased with 131912854Sgabeblack@google.com // ICC_IGRPEN1_EL1_S.Enable and ICC_IGRPEN1_EL1_NS.Enable 132012854Sgabeblack@google.com bool enable_grp_1s = val & ICC_IGRPEN1_EL3_ENABLEGRP1S; 132112854Sgabeblack@google.com bool enable_grp_1ns = val & ICC_IGRPEN1_EL3_ENABLEGRP1NS; 132212854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S, enable_grp_1s); 132312854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS, enable_grp_1ns); 132412854Sgabeblack@google.com return; 132512854Sgabeblack@google.com } 132612854Sgabeblack@google.com 132712854Sgabeblack@google.com // Software Generated Interrupt Group 0 Register 132812854Sgabeblack@google.com case MISCREG_ICC_SGI0R: 132912854Sgabeblack@google.com case MISCREG_ICC_SGI0R_EL1: 133012854Sgabeblack@google.com 133112854Sgabeblack@google.com // Software Generated Interrupt Group 1 Register 133212854Sgabeblack@google.com case MISCREG_ICC_SGI1R: 133312854Sgabeblack@google.com case MISCREG_ICC_SGI1R_EL1: 133412854Sgabeblack@google.com 133512854Sgabeblack@google.com // Alias Software Generated Interrupt Group 1 Register 133612854Sgabeblack@google.com case MISCREG_ICC_ASGI1R: 133712854Sgabeblack@google.com case MISCREG_ICC_ASGI1R_EL1: { 133812854Sgabeblack@google.com bool ns = !inSecureState(); 133912854Sgabeblack@google.com Gicv3::GroupId group; 134012854Sgabeblack@google.com 134112854Sgabeblack@google.com if (misc_reg == MISCREG_ICC_SGI1R_EL1) { 134212854Sgabeblack@google.com group = ns ? Gicv3::G1NS : Gicv3::G1S; 134312854Sgabeblack@google.com } else if (misc_reg == MISCREG_ICC_ASGI1R_EL1) { 134412854Sgabeblack@google.com group = ns ? Gicv3::G1S : Gicv3::G1NS; 134512854Sgabeblack@google.com } else { 134612854Sgabeblack@google.com group = Gicv3::G0S; 134712854Sgabeblack@google.com } 134812854Sgabeblack@google.com 134912854Sgabeblack@google.com if (distributor->DS && group == Gicv3::G1S) { 135012854Sgabeblack@google.com group = Gicv3::G0S; 135112854Sgabeblack@google.com } 135212854Sgabeblack@google.com 135312854Sgabeblack@google.com uint8_t aff3 = bits(val, 55, 48); 135412854Sgabeblack@google.com uint8_t aff2 = bits(val, 39, 32); 135512854Sgabeblack@google.com uint8_t aff1 = bits(val, 23, 16);; 135612854Sgabeblack@google.com uint16_t target_list = bits(val, 15, 0); 135712854Sgabeblack@google.com uint32_t int_id = bits(val, 27, 24); 135812854Sgabeblack@google.com bool irm = bits(val, 40, 40); 135912854Sgabeblack@google.com uint8_t rs = bits(val, 47, 44); 136012854Sgabeblack@google.com 136112854Sgabeblack@google.com for (int i = 0; i < gic->getSystem()->numContexts(); i++) { 136212854Sgabeblack@google.com Gicv3Redistributor * redistributor_i = 136312854Sgabeblack@google.com gic->getRedistributor(i); 136412854Sgabeblack@google.com uint32_t affinity_i = redistributor_i->getAffinity(); 136512854Sgabeblack@google.com 136612854Sgabeblack@google.com if (irm) { 136712854Sgabeblack@google.com // Interrupts routed to all PEs in the system, 136812854Sgabeblack@google.com // excluding "self" 136912854Sgabeblack@google.com if (affinity_i == redistributor->getAffinity()) { 137012854Sgabeblack@google.com continue; 137112854Sgabeblack@google.com } 137212854Sgabeblack@google.com } else { 137312854Sgabeblack@google.com // Interrupts routed to the PEs specified by 137412854Sgabeblack@google.com // Aff3.Aff2.Aff1.<target list> 137512854Sgabeblack@google.com if ((affinity_i >> 8) != 137612854Sgabeblack@google.com ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) { 137712854Sgabeblack@google.com continue; 137812854Sgabeblack@google.com } 137912854Sgabeblack@google.com 138012854Sgabeblack@google.com uint8_t aff0_i = bits(affinity_i, 7, 0); 138112854Sgabeblack@google.com 138212854Sgabeblack@google.com if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 && 138312854Sgabeblack@google.com ((0x1 << (aff0_i - rs * 16)) & target_list))) { 138412854Sgabeblack@google.com continue; 138512854Sgabeblack@google.com } 138612854Sgabeblack@google.com } 138712854Sgabeblack@google.com 138812854Sgabeblack@google.com redistributor_i->sendSGI(int_id, group, ns); 138912854Sgabeblack@google.com } 139012854Sgabeblack@google.com 139112854Sgabeblack@google.com break; 139212854Sgabeblack@google.com } 139312854Sgabeblack@google.com 139412854Sgabeblack@google.com case MISCREG_ICC_SRE: 139512854Sgabeblack@google.com case MISCREG_ICC_SRE_EL1: { // System Register Enable Register EL1 139612854Sgabeblack@google.com if (!(val & ICC_SRE_EL1_SRE)) { 139712854Sgabeblack@google.com warn("Gicv3CPUInterface::setMiscReg(): " 139812854Sgabeblack@google.com "ICC_SRE_EL*.SRE is RAO/WI, legacy not supported!\n"); 139912854Sgabeblack@google.com } 140012854Sgabeblack@google.com 140112854Sgabeblack@google.com bool dfb = val & ICC_SRE_EL1_DFB; 140212854Sgabeblack@google.com bool dib = val & ICC_SRE_EL1_DIB; 140312854Sgabeblack@google.com 140412854Sgabeblack@google.com if (haveEL(EL3) && !distributor->DS) { 140512854Sgabeblack@google.com // DIB is RO alias of ICC_SRE_EL3.DIB 140612854Sgabeblack@google.com // DFB is RO alias of ICC_SRE_EL3.DFB 140712854Sgabeblack@google.com } else if (haveEL(EL3) && distributor->DS) { 140812854Sgabeblack@google.com // DIB is RW alias of ICC_SRE_EL3.DIB 140912854Sgabeblack@google.com // DFB is RW alias of ICC_SRE_EL3.DFB 141012854Sgabeblack@google.com ArmISA::MiscReg icc_sre_el3 = 141112854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3); 141212854Sgabeblack@google.com icc_sre_el3 = insertBits(icc_sre_el3, ICC_SRE_EL3_DFB, dfb); 141312854Sgabeblack@google.com icc_sre_el3 = insertBits(icc_sre_el3, ICC_SRE_EL3_DIB, dib); 141412854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICC_SRE_EL3, icc_sre_el3); 141512854Sgabeblack@google.com } else if ((!haveEL(EL3) || distributor->DS) and haveEL(EL2)) { 141612854Sgabeblack@google.com // DIB is RO alias of ICC_SRE_EL2.DIB 141712854Sgabeblack@google.com // DFB is RO alias of ICC_SRE_EL2.DFB 141812854Sgabeblack@google.com } else { 141912854Sgabeblack@google.com isa->setMiscRegNoEffect(misc_reg, val); 142012854Sgabeblack@google.com } 142112854Sgabeblack@google.com 142212854Sgabeblack@google.com return; 142312854Sgabeblack@google.com } 142412854Sgabeblack@google.com 142512854Sgabeblack@google.com case MISCREG_ICC_HSRE: 142612854Sgabeblack@google.com case MISCREG_ICC_SRE_EL2: // System Register Enable Register EL2 142712854Sgabeblack@google.com case MISCREG_ICC_MSRE: 142812854Sgabeblack@google.com case MISCREG_ICC_SRE_EL3: // System Register Enable Register EL3 142912854Sgabeblack@google.com if (!(val & (1 << 0))) { 143012854Sgabeblack@google.com warn("Gicv3CPUInterface::setMiscReg(): " 143112854Sgabeblack@google.com "ICC_SRE_EL*.SRE is RAO/WI, legacy not supported!\n"); 143212854Sgabeblack@google.com } 143312854Sgabeblack@google.com 143412854Sgabeblack@google.com // All bits are RAO/WI 143512854Sgabeblack@google.com break; 143612854Sgabeblack@google.com 143712854Sgabeblack@google.com case MISCREG_ICH_HCR: 143812854Sgabeblack@google.com case MISCREG_ICH_HCR_EL2: 143912854Sgabeblack@google.com val &= ICH_HCR_EL2_EN | ICH_HCR_EL2_UIE | ICH_HCR_EL2_LRENPIE | 144012854Sgabeblack@google.com ICH_HCR_EL2_NPIE | ICH_HCR_EL2_VGRP0EIE | 144112854Sgabeblack@google.com ICH_HCR_EL2_VGRP0DIE | ICH_HCR_EL2_VGRP1EIE | 144212854Sgabeblack@google.com ICH_HCR_EL2_VGRP1DIE | ICH_HCR_EL2_TC | ICH_HCR_EL2_TALL0 | 144312854Sgabeblack@google.com ICH_HCR_EL2_TALL1 | ICH_HCR_EL2_TDIR | 144412854Sgabeblack@google.com ICH_HCR_EL2_EOICOUNT_MASK; 144512854Sgabeblack@google.com do_virtual_update = true; 144612854Sgabeblack@google.com break; 144712854Sgabeblack@google.com 144812854Sgabeblack@google.com case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: 144912854Sgabeblack@google.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part) 145012854Sgabeblack@google.com { 145112854Sgabeblack@google.com // Enforce RES0 bits in priority field, 5 of 8 bits used 145212854Sgabeblack@google.com val = insertBits(val, ICH_LRC_PRIORITY_SHIFT + 2, 145312854Sgabeblack@google.com ICH_LRC_PRIORITY_SHIFT, 0); 145412854Sgabeblack@google.com ArmISA::MiscReg old_val = isa->readMiscRegNoEffect(misc_reg); 145512854Sgabeblack@google.com val = (old_val & 0xffffffff) | (val << 32); 145612854Sgabeblack@google.com do_virtual_update = true; 145712854Sgabeblack@google.com break; 145812854Sgabeblack@google.com } 145912854Sgabeblack@google.com 146012854Sgabeblack@google.com case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: { 146112854Sgabeblack@google.com // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part) 146212854Sgabeblack@google.com ArmISA::MiscReg old_val = isa->readMiscRegNoEffect(misc_reg); 146312854Sgabeblack@google.com val = (old_val & 0xffffffff00000000) | (val & 0xffffffff); 146412854Sgabeblack@google.com do_virtual_update = true; 146512854Sgabeblack@google.com break; 146612854Sgabeblack@google.com } 146712854Sgabeblack@google.com 146812854Sgabeblack@google.com case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64 146912854Sgabeblack@google.com // Enforce RES0 bits in priority field, 5 of 8 bits used 147012854Sgabeblack@google.com val = insertBits(val, ICH_LR_EL2_PRIORITY_SHIFT + 2, 147112854Sgabeblack@google.com ICH_LR_EL2_PRIORITY_SHIFT, 0); 147212854Sgabeblack@google.com do_virtual_update = true; 147312854Sgabeblack@google.com break; 147412854Sgabeblack@google.com } 147512854Sgabeblack@google.com 147612854Sgabeblack@google.com case MISCREG_ICH_VMCR: 147712854Sgabeblack@google.com case MISCREG_ICH_VMCR_EL2: { 147812854Sgabeblack@google.com val &= ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1 | 147912854Sgabeblack@google.com ICH_VMCR_EL2_VCBPR | ICH_VMCR_EL2_VEOIM | 148012854Sgabeblack@google.com ICH_VMCR_EL2_VBPR1_MASK | ICH_VMCR_EL2_VBPR0_MASK | 148112854Sgabeblack@google.com ICH_VMCR_EL2_VPMR_MASK; 148212854Sgabeblack@google.com val |= ICH_VMCR_EL2_VFIQEN; // RES1 148312854Sgabeblack@google.com // Check VBPRs against minimun allowed value 148412854Sgabeblack@google.com uint8_t vbpr0 = bits(val, 23, 21); 148512854Sgabeblack@google.com uint8_t vbpr1 = bits(val, 20, 18); 148612854Sgabeblack@google.com uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS; 148712854Sgabeblack@google.com uint8_t min_vpr1 = min_vpr0 + 1; 148812854Sgabeblack@google.com vbpr0 = vbpr0 < min_vpr0 ? min_vpr0 : vbpr0; 148912854Sgabeblack@google.com vbpr1 = vbpr1 < min_vpr1 ? min_vpr1 : vbpr1; 149012854Sgabeblack@google.com val = insertBits(val, ICH_VMCR_EL2_VBPR0_SHIFT + 2, 149112854Sgabeblack@google.com ICH_VMCR_EL2_VBPR0_SHIFT, vbpr0); 149212854Sgabeblack@google.com val = insertBits(val, ICH_VMCR_EL2_VBPR1_SHIFT + 2, 149312854Sgabeblack@google.com ICH_VMCR_EL2_VBPR1_SHIFT, vbpr1); 149412854Sgabeblack@google.com break; 149512854Sgabeblack@google.com } 149612854Sgabeblack@google.com 149712854Sgabeblack@google.com case MISCREG_ICH_AP0R0 ... MISCREG_ICH_AP0R3: 149812854Sgabeblack@google.com case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_AP0R3_EL2: 149912854Sgabeblack@google.com case MISCREG_ICH_AP1R0 ... MISCREG_ICH_AP1R3: 150012854Sgabeblack@google.com case MISCREG_ICH_AP1R0_EL2 ... MISCREG_ICH_AP1R3_EL2: 150112854Sgabeblack@google.com break; 150212854Sgabeblack@google.com 150312854Sgabeblack@google.com default: 150412854Sgabeblack@google.com panic("Gicv3CPUInterface::setMiscReg(): " 150512854Sgabeblack@google.com "unknown register %d (%s)", 150612854Sgabeblack@google.com misc_reg, miscRegName[misc_reg]); 150712854Sgabeblack@google.com } 150812854Sgabeblack@google.com 150912854Sgabeblack@google.com isa->setMiscRegNoEffect(misc_reg, val); 151012854Sgabeblack@google.com 151112854Sgabeblack@google.com if (do_virtual_update) { 151212854Sgabeblack@google.com virtualUpdate(); 151312854Sgabeblack@google.com } 151412854Sgabeblack@google.com} 151512854Sgabeblack@google.com 151612854Sgabeblack@google.comint 151712854Sgabeblack@google.comGicv3CPUInterface::virtualFindActive(uint32_t int_id) 151812854Sgabeblack@google.com{ 151912854Sgabeblack@google.com for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 152012854Sgabeblack@google.com ArmISA::MiscReg lr = 152112854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 152212854Sgabeblack@google.com uint32_t lr_intid = bits(lr, 31, 0); 152312854Sgabeblack@google.com 152412854Sgabeblack@google.com if ((lr & ICH_LR_EL2_STATE_ACTIVE_BIT) && lr_intid == int_id) { 152512854Sgabeblack@google.com return lr_idx; 152612854Sgabeblack@google.com } 152712854Sgabeblack@google.com } 152812854Sgabeblack@google.com 152912854Sgabeblack@google.com return -1; 153012854Sgabeblack@google.com} 153112854Sgabeblack@google.com 153212854Sgabeblack@google.comuint32_t 153312854Sgabeblack@google.comGicv3CPUInterface::getHPPIR0() 153412854Sgabeblack@google.com{ 153512854Sgabeblack@google.com if (hppi.prio == 0xff) { 153612854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 153712854Sgabeblack@google.com } 153812854Sgabeblack@google.com 153912854Sgabeblack@google.com bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS; 154012854Sgabeblack@google.com 154112854Sgabeblack@google.com if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) { 154212854Sgabeblack@google.com /* Indicate to EL3 that there's a Group 1 interrupt for the 154312854Sgabeblack@google.com * other state pending. 154412854Sgabeblack@google.com */ 154512854Sgabeblack@google.com return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE; 154612854Sgabeblack@google.com } 154712854Sgabeblack@google.com 154812854Sgabeblack@google.com if ((hppi.group != Gicv3::G0S)) { // && !isEL3OrMon()) 154912854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 155012854Sgabeblack@google.com } 155112854Sgabeblack@google.com 155212854Sgabeblack@google.com if (irq_is_secure && !inSecureState()) { 155312854Sgabeblack@google.com // Secure interrupts not visible in Non-secure 155412854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 155512854Sgabeblack@google.com } 155612854Sgabeblack@google.com 155712854Sgabeblack@google.com return hppi.intid; 155812854Sgabeblack@google.com} 155912854Sgabeblack@google.com 156012854Sgabeblack@google.comuint32_t 156112854Sgabeblack@google.comGicv3CPUInterface::getHPPIR1() 156212854Sgabeblack@google.com{ 156312854Sgabeblack@google.com if (hppi.prio == 0xff) { 156412854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 156512854Sgabeblack@google.com } 156612854Sgabeblack@google.com 156712854Sgabeblack@google.com //if ((currEL() == EL3) && ICC_CTLR_EL3_RM) 156812854Sgabeblack@google.com if ((currEL() == EL3) && 156912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) & ICC_CTLR_EL3_RM) { 157012854Sgabeblack@google.com if (hppi.group == Gicv3::G0S) { 157112854Sgabeblack@google.com return Gicv3::INTID_SECURE; 157212854Sgabeblack@google.com } else if (hppi.group == Gicv3::G1NS) { 157312854Sgabeblack@google.com return Gicv3::INTID_NONSECURE; 157412854Sgabeblack@google.com } 157512854Sgabeblack@google.com } 157612854Sgabeblack@google.com 157712854Sgabeblack@google.com if (hppi.group == Gicv3::G0S) { 157812854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 157912854Sgabeblack@google.com } 158012854Sgabeblack@google.com 158112854Sgabeblack@google.com bool irq_is_secure = (distributor->DS == 0) && (hppi.group != Gicv3::G1NS); 158212854Sgabeblack@google.com 158312854Sgabeblack@google.com if (irq_is_secure) { 158412854Sgabeblack@google.com if (!inSecureState()) { 158512854Sgabeblack@google.com // Secure interrupts not visible in Non-secure 158612854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 158712854Sgabeblack@google.com } 158812854Sgabeblack@google.com } else if (!isEL3OrMon() && inSecureState()) { 158912854Sgabeblack@google.com // Group 1 non-secure interrupts not visible in Secure EL1 159012854Sgabeblack@google.com return Gicv3::INTID_SPURIOUS; 159112854Sgabeblack@google.com } 159212854Sgabeblack@google.com 159312854Sgabeblack@google.com return hppi.intid; 159412854Sgabeblack@google.com} 159512854Sgabeblack@google.com 159612854Sgabeblack@google.comvoid 159712854Sgabeblack@google.comGicv3CPUInterface::dropPriority(Gicv3::GroupId group) 159812854Sgabeblack@google.com{ 159912854Sgabeblack@google.com int apr_misc_reg; 160012854Sgabeblack@google.com ArmISA::MiscReg apr; 160112854Sgabeblack@google.com apr_misc_reg = group == Gicv3::G0S ? 160212854Sgabeblack@google.com MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1; 160312854Sgabeblack@google.com apr = isa->readMiscRegNoEffect(apr_misc_reg); 160412854Sgabeblack@google.com 160512854Sgabeblack@google.com if (apr) { 160612854Sgabeblack@google.com /* Clear the lowest set bit */ 160712854Sgabeblack@google.com apr &= apr - 1; 160812854Sgabeblack@google.com isa->setMiscRegNoEffect(apr_misc_reg, apr); 160912854Sgabeblack@google.com } 161012854Sgabeblack@google.com 161112854Sgabeblack@google.com update(); 161212854Sgabeblack@google.com} 161312854Sgabeblack@google.com 161412854Sgabeblack@google.comuint8_t 161512854Sgabeblack@google.comGicv3CPUInterface::virtualDropPriority() 161612854Sgabeblack@google.com{ 161712854Sgabeblack@google.com /* Drop the priority of the currently active virtual interrupt 161812854Sgabeblack@google.com * (favouring group 0 if there is a set active bit at 161912854Sgabeblack@google.com * the same priority for both group 0 and group 1). 162012854Sgabeblack@google.com * Return the priority value for the bit we just cleared, 162112854Sgabeblack@google.com * or 0xff if no bits were set in the AP registers at all. 162212854Sgabeblack@google.com * Note that though the ich_apr[] are uint64_t only the low 162312854Sgabeblack@google.com * 32 bits are actually relevant. 162412854Sgabeblack@google.com */ 162512854Sgabeblack@google.com int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5); 162612854Sgabeblack@google.com 162712854Sgabeblack@google.com for (int i = 0; i < apr_max; i++) { 162812854Sgabeblack@google.com ArmISA::MiscReg vapr0 = 162912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i); 163012854Sgabeblack@google.com ArmISA::MiscReg vapr1 = 163112854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i); 163212854Sgabeblack@google.com 163312854Sgabeblack@google.com if (!vapr0 && !vapr1) { 163412854Sgabeblack@google.com continue; 163512854Sgabeblack@google.com } 163612854Sgabeblack@google.com 163712854Sgabeblack@google.com int vapr0_count = ctz32(vapr0); 163812854Sgabeblack@google.com int vapr1_count = ctz32(vapr1); 163912854Sgabeblack@google.com 164012854Sgabeblack@google.com if (vapr0_count <= vapr1_count) { 164112854Sgabeblack@google.com /* Clear the lowest set bit */ 164212854Sgabeblack@google.com vapr0 &= vapr0 - 1; 164312854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0); 164412854Sgabeblack@google.com return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1); 164512854Sgabeblack@google.com } else { 164612854Sgabeblack@google.com /* Clear the lowest set bit */ 164712854Sgabeblack@google.com vapr1 &= vapr1 - 1; 164812854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1); 164912854Sgabeblack@google.com return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1); 165012854Sgabeblack@google.com } 165112854Sgabeblack@google.com } 165212854Sgabeblack@google.com 165312854Sgabeblack@google.com return 0xff; 165412854Sgabeblack@google.com} 165512854Sgabeblack@google.com 165612854Sgabeblack@google.comvoid 165712854Sgabeblack@google.comGicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group) 165812854Sgabeblack@google.com{ 165912854Sgabeblack@google.com // Update active priority registers. 166012854Sgabeblack@google.com uint32_t prio = hppi.prio & 0xf8; 166112854Sgabeblack@google.com int apr_bit = prio >> (8 - PRIORITY_BITS); 166212854Sgabeblack@google.com int reg_bit = apr_bit % 32; 166312854Sgabeblack@google.com int apr_idx = group == Gicv3::G0S ? 166412854Sgabeblack@google.com MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1; 166512854Sgabeblack@google.com ArmISA::MiscReg apr = isa->readMiscRegNoEffect(apr_idx); 166612854Sgabeblack@google.com apr |= (1 << reg_bit); 166712854Sgabeblack@google.com isa->setMiscRegNoEffect(apr_idx, apr); 166812854Sgabeblack@google.com 166912854Sgabeblack@google.com // Move interrupt state from pending to active. 167012854Sgabeblack@google.com if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 167112854Sgabeblack@google.com // SGI or PPI, redistributor 167212854Sgabeblack@google.com redistributor->activateIRQ(int_id); 167312854Sgabeblack@google.com redistributor->updateAndInformCPUInterface(); 167412854Sgabeblack@google.com } else if (int_id < Gicv3::INTID_SECURE) { 167512854Sgabeblack@google.com // SPI, distributor 167612854Sgabeblack@google.com distributor->activateIRQ(int_id); 167712854Sgabeblack@google.com distributor->updateAndInformCPUInterfaces(); 167812854Sgabeblack@google.com } 167912854Sgabeblack@google.com} 168012854Sgabeblack@google.com 168112854Sgabeblack@google.comvoid 168212854Sgabeblack@google.comGicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx) 168312854Sgabeblack@google.com{ 168412854Sgabeblack@google.com // Update active priority registers. 168512854Sgabeblack@google.com ArmISA::MiscReg lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + 168612854Sgabeblack@google.com lr_idx); 168712854Sgabeblack@google.com Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; 168812854Sgabeblack@google.com uint8_t prio = bits(lr, 55, 48) & 0xf8; 168912854Sgabeblack@google.com int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS); 169012854Sgabeblack@google.com int reg_no = apr_bit / 32; 169112854Sgabeblack@google.com int reg_bit = apr_bit % 32; 169212854Sgabeblack@google.com int apr_idx = group == Gicv3::G0S ? 169312854Sgabeblack@google.com MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no; 169412854Sgabeblack@google.com ArmISA::MiscReg apr = isa->readMiscRegNoEffect(apr_idx); 169512854Sgabeblack@google.com apr |= (1 << reg_bit); 169612854Sgabeblack@google.com isa->setMiscRegNoEffect(apr_idx, apr); 169712854Sgabeblack@google.com // Move interrupt state from pending to active. 169812854Sgabeblack@google.com lr &= ~ICH_LR_EL2_STATE_PENDING_BIT; 169912854Sgabeblack@google.com lr |= ICH_LR_EL2_STATE_ACTIVE_BIT; 170012854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr); 170112854Sgabeblack@google.com} 170212854Sgabeblack@google.com 170312854Sgabeblack@google.comvoid 170412854Sgabeblack@google.comGicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group) 170512854Sgabeblack@google.com{ 170612854Sgabeblack@google.com if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) { 170712854Sgabeblack@google.com // SGI or PPI, redistributor 170812854Sgabeblack@google.com redistributor->deactivateIRQ(int_id); 170912854Sgabeblack@google.com redistributor->updateAndInformCPUInterface(); 171012854Sgabeblack@google.com } else if (int_id < Gicv3::INTID_SECURE) { 171112854Sgabeblack@google.com // SPI, distributor 171212854Sgabeblack@google.com distributor->deactivateIRQ(int_id); 171312854Sgabeblack@google.com distributor->updateAndInformCPUInterfaces(); 171412854Sgabeblack@google.com } else { 171512854Sgabeblack@google.com return; 171612854Sgabeblack@google.com } 171712854Sgabeblack@google.com} 171812854Sgabeblack@google.com 171912854Sgabeblack@google.comvoid 172012854Sgabeblack@google.comGicv3CPUInterface::virtualDeactivateIRQ(int lr_idx) 172112854Sgabeblack@google.com{ 172212854Sgabeblack@google.com ArmISA::MiscReg lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + 172312854Sgabeblack@google.com lr_idx); 172412854Sgabeblack@google.com 172512854Sgabeblack@google.com if (lr & ICH_LR_EL2_HW) { 172612854Sgabeblack@google.com // Deactivate the associated physical interrupt 172712854Sgabeblack@google.com int pintid = bits(lr, 41, 32); 172812854Sgabeblack@google.com 172912854Sgabeblack@google.com if (pintid < Gicv3::INTID_SECURE) { 173012854Sgabeblack@google.com Gicv3::GroupId group = 173112854Sgabeblack@google.com pintid >= 32 ? distributor->getIntGroup(pintid) : 173212854Sgabeblack@google.com redistributor->getIntGroup(pintid); 173312854Sgabeblack@google.com deactivateIRQ(pintid, group); 173412854Sgabeblack@google.com } 173512854Sgabeblack@google.com } 173612854Sgabeblack@google.com 173712854Sgabeblack@google.com // Remove the active bit 173812854Sgabeblack@google.com lr &= ~ICH_LR_EL2_STATE_ACTIVE_BIT; 173912854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr); 174012854Sgabeblack@google.com} 174112854Sgabeblack@google.com 174212854Sgabeblack@google.com/* 174312854Sgabeblack@google.com * Return a mask word which clears the subpriority bits from 174412854Sgabeblack@google.com * a priority value for an interrupt in the specified group. 174512854Sgabeblack@google.com * This depends on the BPR value. For CBPR0 (S or NS): 174612854Sgabeblack@google.com * a BPR of 0 means the group priority bits are [7:1]; 174712854Sgabeblack@google.com * a BPR of 1 means they are [7:2], and so on down to 174812854Sgabeblack@google.com * ... 174912854Sgabeblack@google.com * a BPR of 7 meaning no group priority bits at all. 175012854Sgabeblack@google.com * For CBPR1 NS: 175112854Sgabeblack@google.com * a BPR of 0 is impossible (the minimum value is 1) 175212854Sgabeblack@google.com * a BPR of 1 means the group priority bits are [7:1]; 175312854Sgabeblack@google.com * a BPR of 2 means they are [7:2], and so on down to 175412854Sgabeblack@google.com * ... 175512854Sgabeblack@google.com * a BPR of 7 meaning the group priority is [7]. 175612854Sgabeblack@google.com * 175712854Sgabeblack@google.com * Which BPR to use depends on the group of the interrupt and 175812854Sgabeblack@google.com * the current ICC_CTLR.CBPR settings. 175912854Sgabeblack@google.com * 176012854Sgabeblack@google.com * This corresponds to the GroupBits() pseudocode from 4.8.2. 176112854Sgabeblack@google.com */ 176212854Sgabeblack@google.comuint32_t 176312854Sgabeblack@google.comGicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) 176412854Sgabeblack@google.com{ 176512854Sgabeblack@google.com if ((group == Gicv3::G1S && 176612854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) 176712854Sgabeblack@google.com & ICC_CTLR_EL1_CBPR) || 176812854Sgabeblack@google.com (group == Gicv3::G1NS && 176912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) 177012854Sgabeblack@google.com & ICC_CTLR_EL1_CBPR)) { 177112854Sgabeblack@google.com group = Gicv3::G0S; 177212854Sgabeblack@google.com } 177312854Sgabeblack@google.com 177412854Sgabeblack@google.com int bpr; 177512854Sgabeblack@google.com 177612854Sgabeblack@google.com if (group == Gicv3::G0S) { 177712854Sgabeblack@google.com bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) & 0x7; 177812854Sgabeblack@google.com } else { 177912854Sgabeblack@google.com bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1) & 0x7; 178012854Sgabeblack@google.com } 178112854Sgabeblack@google.com 178212854Sgabeblack@google.com if (group == Gicv3::G1NS) { 178312854Sgabeblack@google.com assert(bpr > 0); 178412854Sgabeblack@google.com bpr--; 178512854Sgabeblack@google.com } 178612854Sgabeblack@google.com 178712854Sgabeblack@google.com return ~0U << (bpr + 1); 178812854Sgabeblack@google.com} 178912854Sgabeblack@google.com 179012854Sgabeblack@google.comuint32_t 179112854Sgabeblack@google.comGicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) 179212854Sgabeblack@google.com{ 179312854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 179412854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 179512854Sgabeblack@google.com 179612854Sgabeblack@google.com if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) { 179712854Sgabeblack@google.com group = Gicv3::G0S; 179812854Sgabeblack@google.com } 179912854Sgabeblack@google.com 180012854Sgabeblack@google.com int bpr; 180112854Sgabeblack@google.com 180212854Sgabeblack@google.com if (group == Gicv3::G0S) { 180312854Sgabeblack@google.com bpr = bits(ich_vmcr_el2, 23, 21); 180412854Sgabeblack@google.com } else { 180512854Sgabeblack@google.com bpr = bits(ich_vmcr_el2, 20, 18); 180612854Sgabeblack@google.com } 180712854Sgabeblack@google.com 180812854Sgabeblack@google.com if (group == Gicv3::G1NS) { 180912854Sgabeblack@google.com assert(bpr > 0); 181012854Sgabeblack@google.com bpr--; 181112854Sgabeblack@google.com } 181212854Sgabeblack@google.com 181312854Sgabeblack@google.com return ~0U << (bpr + 1); 181412854Sgabeblack@google.com} 181512854Sgabeblack@google.com 181612854Sgabeblack@google.combool 181712854Sgabeblack@google.comGicv3CPUInterface::isEOISplitMode() 181812854Sgabeblack@google.com{ 181912854Sgabeblack@google.com if (isEL3OrMon()) { 182012854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) & 182112854Sgabeblack@google.com ICC_CTLR_EL3_EOIMODE_EL3; 182212854Sgabeblack@google.com } else { 182312854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1) & 182412854Sgabeblack@google.com ICC_CTLR_EL1_EOIMODE; 182512854Sgabeblack@google.com } 182612854Sgabeblack@google.com} 182712854Sgabeblack@google.com 182812854Sgabeblack@google.combool 182912854Sgabeblack@google.comGicv3CPUInterface::virtualIsEOISplitMode() 183012854Sgabeblack@google.com{ 183112854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 183212854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 183312854Sgabeblack@google.com return ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM; 183412854Sgabeblack@google.com} 183512854Sgabeblack@google.com 183612854Sgabeblack@google.comint 183712854Sgabeblack@google.comGicv3CPUInterface::highestActiveGroup() 183812854Sgabeblack@google.com{ 183912854Sgabeblack@google.com int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1)); 184012854Sgabeblack@google.com int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S)); 184112854Sgabeblack@google.com int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS)); 184212854Sgabeblack@google.com 184312854Sgabeblack@google.com if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) { 184412854Sgabeblack@google.com return Gicv3::G1NS; 184512854Sgabeblack@google.com } 184612854Sgabeblack@google.com 184712854Sgabeblack@google.com if (gq_ctz < g0_ctz) { 184812854Sgabeblack@google.com return Gicv3::G1S; 184912854Sgabeblack@google.com } 185012854Sgabeblack@google.com 185112854Sgabeblack@google.com if (g0_ctz < 32) { 185212854Sgabeblack@google.com return Gicv3::G0S; 185312854Sgabeblack@google.com } 185412854Sgabeblack@google.com 185512854Sgabeblack@google.com return -1; 185612854Sgabeblack@google.com} 185712854Sgabeblack@google.com 185812854Sgabeblack@google.comvoid 185912854Sgabeblack@google.comGicv3CPUInterface::update() 186012854Sgabeblack@google.com{ 186112854Sgabeblack@google.com bool signal_IRQ = false; 186212854Sgabeblack@google.com bool signal_FIQ = false; 186312854Sgabeblack@google.com 186412854Sgabeblack@google.com if (hppi.group == Gicv3::G1S && !haveEL(EL3)) { 186512854Sgabeblack@google.com /* 186612854Sgabeblack@google.com * Secure enabled GIC sending a G1S IRQ to a secure disabled 186712854Sgabeblack@google.com * CPU -> send G0 IRQ 186812854Sgabeblack@google.com */ 186912854Sgabeblack@google.com hppi.group = Gicv3::G0S; 187012854Sgabeblack@google.com } 187112854Sgabeblack@google.com 187212854Sgabeblack@google.com if (hppiCanPreempt()) { 187312854Sgabeblack@google.com ArmISA::InterruptTypes int_type = intSignalType(hppi.group); 187412854Sgabeblack@google.com DPRINTF(GIC, "Gicv3CPUInterface::update(): " 187512854Sgabeblack@google.com "posting int as %d!\n", int_type); 187612854Sgabeblack@google.com int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true; 187712854Sgabeblack@google.com } 187812854Sgabeblack@google.com 187912854Sgabeblack@google.com if (signal_IRQ) { 188012854Sgabeblack@google.com gic->postInt(cpuId, ArmISA::INT_IRQ); 188112854Sgabeblack@google.com } else { 188212854Sgabeblack@google.com gic->deassertInt(cpuId, ArmISA::INT_IRQ); 188312854Sgabeblack@google.com } 188412854Sgabeblack@google.com 188512854Sgabeblack@google.com if (signal_FIQ) { 188612854Sgabeblack@google.com gic->postInt(cpuId, ArmISA::INT_FIQ); 188712854Sgabeblack@google.com } else { 188812854Sgabeblack@google.com gic->deassertInt(cpuId, ArmISA::INT_FIQ); 188912854Sgabeblack@google.com } 189012854Sgabeblack@google.com} 189112854Sgabeblack@google.com 189212854Sgabeblack@google.comvoid 189312854Sgabeblack@google.comGicv3CPUInterface::virtualUpdate() 189412854Sgabeblack@google.com{ 189512854Sgabeblack@google.com bool signal_IRQ = false; 189612854Sgabeblack@google.com bool signal_FIQ = false; 189712854Sgabeblack@google.com int lr_idx = getHPPVILR(); 189812854Sgabeblack@google.com 189912854Sgabeblack@google.com if (lr_idx >= 0) { 190012854Sgabeblack@google.com ArmISA::MiscReg ich_lr_el2 = 190112854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 190212854Sgabeblack@google.com 190312854Sgabeblack@google.com if (hppviCanPreempt(lr_idx)) { 190412854Sgabeblack@google.com if (ich_lr_el2 & ICH_LR_EL2_GROUP) { 190512854Sgabeblack@google.com signal_IRQ = true; 190612854Sgabeblack@google.com } else { 190712854Sgabeblack@google.com signal_FIQ = true; 190812854Sgabeblack@google.com } 190912854Sgabeblack@google.com } 191012854Sgabeblack@google.com } 191112854Sgabeblack@google.com 191212854Sgabeblack@google.com ArmISA::MiscReg ich_hcr_el2 = 191312854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 191412854Sgabeblack@google.com 191512854Sgabeblack@google.com if (ich_hcr_el2 & ICH_HCR_EL2_EN) { 191612854Sgabeblack@google.com if (maintenanceInterruptStatus()) { 191712854Sgabeblack@google.com redistributor->sendPPInt(25); 191812854Sgabeblack@google.com } 191912854Sgabeblack@google.com } 192012854Sgabeblack@google.com 192112854Sgabeblack@google.com if (signal_IRQ) { 192212854Sgabeblack@google.com DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): " 192312854Sgabeblack@google.com "posting int as %d!\n", ArmISA::INT_VIRT_IRQ); 192412854Sgabeblack@google.com gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ); 192512854Sgabeblack@google.com } else { 192612854Sgabeblack@google.com gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ); 192712854Sgabeblack@google.com } 192812854Sgabeblack@google.com 192912854Sgabeblack@google.com if (signal_FIQ) { 193012854Sgabeblack@google.com DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): " 193112854Sgabeblack@google.com "posting int as %d!\n", ArmISA::INT_VIRT_FIQ); 193212854Sgabeblack@google.com gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ); 193312854Sgabeblack@google.com } else { 193412854Sgabeblack@google.com gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ); 193512854Sgabeblack@google.com } 193612854Sgabeblack@google.com} 193712854Sgabeblack@google.com 193812854Sgabeblack@google.com// Returns the intex of the LR with the HPPI 193912854Sgabeblack@google.comint 194012854Sgabeblack@google.comGicv3CPUInterface::getHPPVILR() 194112854Sgabeblack@google.com{ 194212854Sgabeblack@google.com int idx = -1; 194312854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 194412854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 194512854Sgabeblack@google.com 194612854Sgabeblack@google.com if (!(ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) { 194712854Sgabeblack@google.com // VG0 and VG1 disabled... 194812854Sgabeblack@google.com return idx; 194912854Sgabeblack@google.com } 195012854Sgabeblack@google.com 195112854Sgabeblack@google.com uint8_t highest_prio = 0xff; 195212854Sgabeblack@google.com 195312854Sgabeblack@google.com for (int i = 0; i < 16; i++) { 195412854Sgabeblack@google.com ArmISA::MiscReg ich_lri_el2 = 195512854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i); 195612854Sgabeblack@google.com uint8_t state = bits(ich_lri_el2, 63, 62); 195712854Sgabeblack@google.com 195812854Sgabeblack@google.com if (state != Gicv3::INT_PENDING) { 195912854Sgabeblack@google.com continue; 196012854Sgabeblack@google.com } 196112854Sgabeblack@google.com 196212854Sgabeblack@google.com if (ich_lri_el2 & ICH_LR_EL2_GROUP) { 196312854Sgabeblack@google.com // VG1 196412854Sgabeblack@google.com if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 196512854Sgabeblack@google.com continue; 196612854Sgabeblack@google.com } 196712854Sgabeblack@google.com } else { 196812854Sgabeblack@google.com // VG0 196912854Sgabeblack@google.com if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) { 197012854Sgabeblack@google.com continue; 197112854Sgabeblack@google.com } 197212854Sgabeblack@google.com } 197312854Sgabeblack@google.com 197412854Sgabeblack@google.com uint8_t prio = bits(ich_lri_el2, 55, 48); 197512854Sgabeblack@google.com 197612854Sgabeblack@google.com if (prio < highest_prio) { 197712854Sgabeblack@google.com highest_prio = prio; 197812854Sgabeblack@google.com idx = i; 197912854Sgabeblack@google.com } 198012854Sgabeblack@google.com } 198112854Sgabeblack@google.com 198212854Sgabeblack@google.com return idx; 198312854Sgabeblack@google.com} 198412854Sgabeblack@google.com 198512854Sgabeblack@google.combool 198612854Sgabeblack@google.comGicv3CPUInterface::hppviCanPreempt(int lr_idx) 198712854Sgabeblack@google.com{ 198812854Sgabeblack@google.com ArmISA::MiscReg lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + 198912854Sgabeblack@google.com lr_idx); 199012854Sgabeblack@google.com 199112854Sgabeblack@google.com if (!(isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2) & ICH_HCR_EL2_EN)) { 199212854Sgabeblack@google.com // virtual interface is disabled 199312854Sgabeblack@google.com return false; 199412854Sgabeblack@google.com } 199512854Sgabeblack@google.com 199612854Sgabeblack@google.com uint8_t prio = bits(lr, 55, 48); 199712854Sgabeblack@google.com uint8_t vpmr = 199812854Sgabeblack@google.com bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24); 199912854Sgabeblack@google.com 200012854Sgabeblack@google.com if (prio >= vpmr) { 200112854Sgabeblack@google.com // prioriry masked 200212854Sgabeblack@google.com return false; 200312854Sgabeblack@google.com } 200412854Sgabeblack@google.com 200512854Sgabeblack@google.com uint8_t rprio = virtualHighestActivePriority(); 200612854Sgabeblack@google.com 200712854Sgabeblack@google.com if (rprio == 0xff) { 200812854Sgabeblack@google.com return true; 200912854Sgabeblack@google.com } 201012854Sgabeblack@google.com 201112854Sgabeblack@google.com Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S; 201212854Sgabeblack@google.com uint32_t prio_mask = virtualGroupPriorityMask(group); 201312854Sgabeblack@google.com 201412854Sgabeblack@google.com if ((prio & prio_mask) < (rprio & prio_mask)) { 201512854Sgabeblack@google.com return true; 201612854Sgabeblack@google.com } 201712854Sgabeblack@google.com 201812854Sgabeblack@google.com return false; 201912854Sgabeblack@google.com} 202012854Sgabeblack@google.com 202112854Sgabeblack@google.comuint8_t 202212854Sgabeblack@google.comGicv3CPUInterface::virtualHighestActivePriority() 202312854Sgabeblack@google.com{ 202412854Sgabeblack@google.com uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5); 202512854Sgabeblack@google.com 202612854Sgabeblack@google.com for (int i = 0; i < num_aprs; i++) { 202712854Sgabeblack@google.com ArmISA::MiscReg vapr = 202812854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) | 202912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i); 203012854Sgabeblack@google.com 203112854Sgabeblack@google.com if (!vapr) { 203212854Sgabeblack@google.com continue; 203312854Sgabeblack@google.com } 203412854Sgabeblack@google.com 203512854Sgabeblack@google.com return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1); 203612854Sgabeblack@google.com } 203712854Sgabeblack@google.com 203812854Sgabeblack@google.com // no active interrups, return idle priority 203912854Sgabeblack@google.com return 0xff; 204012854Sgabeblack@google.com} 204112854Sgabeblack@google.com 204212854Sgabeblack@google.comvoid 204312854Sgabeblack@google.comGicv3CPUInterface::virtualIncrementEOICount() 204412854Sgabeblack@google.com{ 204512854Sgabeblack@google.com // Increment the EOICOUNT field in ICH_HCR_EL2 204612854Sgabeblack@google.com ArmISA::MiscReg ich_hcr_el2 = 204712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 204812854Sgabeblack@google.com uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27); 204912854Sgabeblack@google.com EOI_cout++; 205012854Sgabeblack@google.com ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout); 205112854Sgabeblack@google.com isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2); 205212854Sgabeblack@google.com} 205312854Sgabeblack@google.com 205412854Sgabeblack@google.com/* 205512854Sgabeblack@google.com * Should we signal the interrupt as IRQ or FIQ? 205612854Sgabeblack@google.com * see spec section 4.6.2 205712854Sgabeblack@google.com */ 205812854Sgabeblack@google.comArmISA::InterruptTypes 205912854Sgabeblack@google.comGicv3CPUInterface::intSignalType(Gicv3::GroupId group) 206012854Sgabeblack@google.com{ 206112854Sgabeblack@google.com bool is_fiq = false; 206212854Sgabeblack@google.com 206312854Sgabeblack@google.com switch (group) { 206412854Sgabeblack@google.com case Gicv3::G0S: 206512854Sgabeblack@google.com is_fiq = true; 206612854Sgabeblack@google.com break; 206712854Sgabeblack@google.com 206812854Sgabeblack@google.com case Gicv3::G1S: 206912854Sgabeblack@google.com is_fiq = (distributor->DS == 0) && 207012854Sgabeblack@google.com (!inSecureState() || ((currEL() == EL3) && isAA64())); 207112854Sgabeblack@google.com break; 207212854Sgabeblack@google.com 207312854Sgabeblack@google.com case Gicv3::G1NS: 207412854Sgabeblack@google.com is_fiq = (distributor->DS == 0) && inSecureState(); 207512854Sgabeblack@google.com break; 207612854Sgabeblack@google.com 207712854Sgabeblack@google.com default: 207812854Sgabeblack@google.com panic("Gicv3CPUInterface::intSignalType(): invalid group!"); 207912854Sgabeblack@google.com } 208012854Sgabeblack@google.com 208112854Sgabeblack@google.com if (is_fiq) { 208212854Sgabeblack@google.com return ArmISA::INT_FIQ; 208312854Sgabeblack@google.com } else { 208412854Sgabeblack@google.com return ArmISA::INT_IRQ; 208512854Sgabeblack@google.com } 208612854Sgabeblack@google.com} 208712854Sgabeblack@google.com 208812854Sgabeblack@google.combool 208912854Sgabeblack@google.comGicv3CPUInterface::hppiCanPreempt() 209012854Sgabeblack@google.com{ 209112854Sgabeblack@google.com if (hppi.prio == 0xff) { 209212854Sgabeblack@google.com // there is no pending interrupt 209312854Sgabeblack@google.com return false; 209412854Sgabeblack@google.com } 209512854Sgabeblack@google.com 209612854Sgabeblack@google.com if (!groupEnabled(hppi.group)) { 209712854Sgabeblack@google.com // group disabled at CPU interface 209812854Sgabeblack@google.com return false; 209912854Sgabeblack@google.com } 210012854Sgabeblack@google.com 210112854Sgabeblack@google.com if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) { 210212854Sgabeblack@google.com // priority masked 210312854Sgabeblack@google.com return false; 210412854Sgabeblack@google.com } 210512854Sgabeblack@google.com 210612854Sgabeblack@google.com uint8_t rprio = highestActivePriority(); 210712854Sgabeblack@google.com 210812854Sgabeblack@google.com if (rprio == 0xff) { 210912854Sgabeblack@google.com return true; 211012854Sgabeblack@google.com } 211112854Sgabeblack@google.com 211212854Sgabeblack@google.com uint32_t prio_mask = groupPriorityMask(hppi.group); 211312854Sgabeblack@google.com 211412854Sgabeblack@google.com if ((hppi.prio & prio_mask) < (rprio & prio_mask)) { 211512854Sgabeblack@google.com return true; 211612854Sgabeblack@google.com } 211712854Sgabeblack@google.com 211812854Sgabeblack@google.com return false; 211912854Sgabeblack@google.com} 212012854Sgabeblack@google.com 212112854Sgabeblack@google.comuint8_t 212212854Sgabeblack@google.comGicv3CPUInterface::highestActivePriority() 212312854Sgabeblack@google.com{ 212412854Sgabeblack@google.com uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) | 212512854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) | 212612854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S); 212712854Sgabeblack@google.com 212812854Sgabeblack@google.com if (apr) { 212912854Sgabeblack@google.com return ctz32(apr) << (GIC_MIN_BPR + 1); 213012854Sgabeblack@google.com } 213112854Sgabeblack@google.com 213212854Sgabeblack@google.com // no active interrups, return idle priority 213312854Sgabeblack@google.com return 0xff; 213412854Sgabeblack@google.com} 213512854Sgabeblack@google.com 213612854Sgabeblack@google.combool 213712854Sgabeblack@google.comGicv3CPUInterface::groupEnabled(Gicv3::GroupId group) 213812854Sgabeblack@google.com{ 213912854Sgabeblack@google.com switch (group) { 214012854Sgabeblack@google.com case Gicv3::G0S: 214112854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1) & 214212854Sgabeblack@google.com ICC_IGRPEN0_EL1_ENABLE; 214312854Sgabeblack@google.com 214412854Sgabeblack@google.com case Gicv3::G1S: 214512854Sgabeblack@google.com //if (distributor->DS) 214612854Sgabeblack@google.com //{ 214712854Sgabeblack@google.com // return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) & 214812854Sgabeblack@google.com // ICC_IGRPEN1_EL1_ENABLE; 214912854Sgabeblack@google.com //} 215012854Sgabeblack@google.com //else 215112854Sgabeblack@google.com //{ 215212854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) & 215312854Sgabeblack@google.com ICC_IGRPEN1_EL1_ENABLE; 215412854Sgabeblack@google.com 215512854Sgabeblack@google.com //} 215612854Sgabeblack@google.com 215712854Sgabeblack@google.com case Gicv3::G1NS: 215812854Sgabeblack@google.com return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) & 215912854Sgabeblack@google.com ICC_IGRPEN1_EL1_ENABLE; 216012854Sgabeblack@google.com 216112854Sgabeblack@google.com default: 216212854Sgabeblack@google.com panic("Gicv3CPUInterface::groupEnable(): invalid group!\n"); 216312854Sgabeblack@google.com } 216412854Sgabeblack@google.com} 216512854Sgabeblack@google.com 216612854Sgabeblack@google.combool 216712854Sgabeblack@google.comGicv3CPUInterface::inSecureState() 216812854Sgabeblack@google.com{ 216912854Sgabeblack@google.com if (!gic->getSystem()->haveSecurity()) { 217012854Sgabeblack@google.com return false; 217112854Sgabeblack@google.com } 217212854Sgabeblack@google.com 217312854Sgabeblack@google.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 217412854Sgabeblack@google.com SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR); 217512854Sgabeblack@google.com return ArmISA::inSecureState(scr, cpsr); 217612854Sgabeblack@google.com} 217712854Sgabeblack@google.com 217812854Sgabeblack@google.comint 217912854Sgabeblack@google.comGicv3CPUInterface::currEL() 218012854Sgabeblack@google.com{ 218112854Sgabeblack@google.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 218212854Sgabeblack@google.com bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode); 218312854Sgabeblack@google.com 218412854Sgabeblack@google.com if (is_64) { 218512854Sgabeblack@google.com return (ExceptionLevel)(uint8_t) cpsr.el; 218612854Sgabeblack@google.com } else { 218712854Sgabeblack@google.com switch (cpsr.mode) { 218812854Sgabeblack@google.com case MODE_USER: 218912854Sgabeblack@google.com return 0; 219012854Sgabeblack@google.com 219112854Sgabeblack@google.com case MODE_HYP: 219212854Sgabeblack@google.com return 2; 219312854Sgabeblack@google.com 219412854Sgabeblack@google.com case MODE_MON: 219512854Sgabeblack@google.com return 3; 219612854Sgabeblack@google.com 219712854Sgabeblack@google.com default: 219812854Sgabeblack@google.com return 1; 219912854Sgabeblack@google.com } 220012854Sgabeblack@google.com } 220112854Sgabeblack@google.com} 220212854Sgabeblack@google.com 220312854Sgabeblack@google.combool 220412854Sgabeblack@google.comGicv3CPUInterface::haveEL(ExceptionLevel el) 220512854Sgabeblack@google.com{ 220612854Sgabeblack@google.com switch (el) { 220712854Sgabeblack@google.com case EL0: 220812854Sgabeblack@google.com case EL1: 220912854Sgabeblack@google.com return true; 221012854Sgabeblack@google.com 221112854Sgabeblack@google.com case EL2: 221212854Sgabeblack@google.com return gic->getSystem()->haveVirtualization(); 221312854Sgabeblack@google.com 221412854Sgabeblack@google.com case EL3: 221512854Sgabeblack@google.com return gic->getSystem()->haveSecurity(); 221612854Sgabeblack@google.com 221712854Sgabeblack@google.com default: 221812854Sgabeblack@google.com warn("Unimplemented Exception Level\n"); 221912854Sgabeblack@google.com return false; 222012854Sgabeblack@google.com } 222112854Sgabeblack@google.com} 222212854Sgabeblack@google.com 222312854Sgabeblack@google.combool 222412854Sgabeblack@google.comGicv3CPUInterface::isSecureBelowEL3() 222512854Sgabeblack@google.com{ 222612854Sgabeblack@google.com SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3); 222712854Sgabeblack@google.com return haveEL(EL3) && scr.ns == 0; 222812854Sgabeblack@google.com} 222912854Sgabeblack@google.com 223012854Sgabeblack@google.combool 223112854Sgabeblack@google.comGicv3CPUInterface::isAA64() 223212854Sgabeblack@google.com{ 223312854Sgabeblack@google.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 223412854Sgabeblack@google.com return opModeIs64((OperatingMode)(uint8_t) cpsr.mode); 223512854Sgabeblack@google.com} 223612854Sgabeblack@google.com 223712854Sgabeblack@google.combool 223812854Sgabeblack@google.comGicv3CPUInterface::isEL3OrMon() 223912854Sgabeblack@google.com{ 224012854Sgabeblack@google.com if (haveEL(EL3)) { 224112854Sgabeblack@google.com CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR); 224212854Sgabeblack@google.com bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode); 224312854Sgabeblack@google.com 224412854Sgabeblack@google.com if (is_64 && (cpsr.el == EL3)) { 224512854Sgabeblack@google.com return true; 224612854Sgabeblack@google.com } else if (!is_64 && (cpsr.mode == MODE_MON)) { 224712854Sgabeblack@google.com return true; 224812854Sgabeblack@google.com } 224912854Sgabeblack@google.com } 225012854Sgabeblack@google.com 225112854Sgabeblack@google.com return false; 225212854Sgabeblack@google.com} 225312854Sgabeblack@google.com 225412854Sgabeblack@google.comuint32_t 225512854Sgabeblack@google.comGicv3CPUInterface::eoiMaintenanceInterruptStatus(uint32_t * misr) 225612854Sgabeblack@google.com{ 225712854Sgabeblack@google.com /* Return a set of bits indicating the EOI maintenance interrupt status 225812854Sgabeblack@google.com * for each list register. The EOI maintenance interrupt status is 225912854Sgabeblack@google.com * 1 if LR.State == 0 && LR.HW == 0 && LR.EOI == 1 226012854Sgabeblack@google.com * (see the GICv3 spec for the ICH_EISR_EL2 register). 226112854Sgabeblack@google.com * If misr is not NULL then we should also collect the information 226212854Sgabeblack@google.com * about the MISR.EOI, MISR.NP and MISR.U bits. 226312854Sgabeblack@google.com */ 226412854Sgabeblack@google.com uint32_t value = 0; 226512854Sgabeblack@google.com int valid_count = 0; 226612854Sgabeblack@google.com bool seen_pending = false; 226712854Sgabeblack@google.com 226812854Sgabeblack@google.com for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) { 226912854Sgabeblack@google.com ArmISA::MiscReg lr = 227012854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx); 227112854Sgabeblack@google.com 227212854Sgabeblack@google.com if ((lr & (ICH_LR_EL2_STATE_MASK | ICH_LR_EL2_HW | ICH_LR_EL2_EOI)) == 227312854Sgabeblack@google.com ICH_LR_EL2_EOI) { 227412854Sgabeblack@google.com value |= (1 << lr_idx); 227512854Sgabeblack@google.com } 227612854Sgabeblack@google.com 227712854Sgabeblack@google.com if ((lr & ICH_LR_EL2_STATE_MASK)) { 227812854Sgabeblack@google.com valid_count++; 227912854Sgabeblack@google.com } 228012854Sgabeblack@google.com 228112854Sgabeblack@google.com if (bits(lr, ICH_LR_EL2_STATE_SHIFT + ICH_LR_EL2_STATE_LENGTH, 228212854Sgabeblack@google.com ICH_LR_EL2_STATE_SHIFT) == ICH_LR_EL2_STATE_PENDING) { 228312854Sgabeblack@google.com seen_pending = true; 228412854Sgabeblack@google.com } 228512854Sgabeblack@google.com } 228612854Sgabeblack@google.com 228712854Sgabeblack@google.com if (misr) { 228812854Sgabeblack@google.com ArmISA::MiscReg ich_hcr_el2 = 228912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 229012854Sgabeblack@google.com 229112854Sgabeblack@google.com if (valid_count < 2 && (ich_hcr_el2 & ICH_HCR_EL2_UIE)) { 229212854Sgabeblack@google.com *misr |= ICH_MISR_EL2_U; 229312854Sgabeblack@google.com } 229412854Sgabeblack@google.com 229512854Sgabeblack@google.com if (!seen_pending && (ich_hcr_el2 & ICH_HCR_EL2_NPIE)) { 229612854Sgabeblack@google.com *misr |= ICH_MISR_EL2_NP; 229712854Sgabeblack@google.com } 229812854Sgabeblack@google.com 229912854Sgabeblack@google.com if (value) { 230012854Sgabeblack@google.com *misr |= ICH_MISR_EL2_EOI; 230112854Sgabeblack@google.com } 230212854Sgabeblack@google.com } 230312854Sgabeblack@google.com 230412854Sgabeblack@google.com return value; 230512854Sgabeblack@google.com} 230612854Sgabeblack@google.com 230712854Sgabeblack@google.comuint32_t 230812854Sgabeblack@google.comGicv3CPUInterface::maintenanceInterruptStatus() 230912854Sgabeblack@google.com{ 231012854Sgabeblack@google.com /* Return a set of bits indicating the maintenance interrupt status 231112854Sgabeblack@google.com * (as seen in the ICH_MISR_EL2 register). 231212854Sgabeblack@google.com */ 231312854Sgabeblack@google.com uint32_t value = 0; 231412854Sgabeblack@google.com /* Scan list registers and fill in the U, NP and EOI bits */ 231512854Sgabeblack@google.com eoiMaintenanceInterruptStatus(&value); 231612854Sgabeblack@google.com ArmISA::MiscReg ich_hcr_el2 = 231712854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2); 231812854Sgabeblack@google.com ArmISA::MiscReg ich_vmcr_el2 = 231912854Sgabeblack@google.com isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2); 232012854Sgabeblack@google.com 232112854Sgabeblack@google.com if (ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) { 232212854Sgabeblack@google.com value |= ICH_MISR_EL2_LRENP; 232312854Sgabeblack@google.com } 232412854Sgabeblack@google.com 232512854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) && 232612854Sgabeblack@google.com (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) { 232712854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP0E; 232812854Sgabeblack@google.com } 232912854Sgabeblack@google.com 233012854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) && 233112854Sgabeblack@google.com !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 233212854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP0D; 233312854Sgabeblack@google.com } 233412854Sgabeblack@google.com 233512854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) && 233612854Sgabeblack@google.com (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 233712854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP1E; 233812854Sgabeblack@google.com } 233912854Sgabeblack@google.com 234012854Sgabeblack@google.com if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) && 234112854Sgabeblack@google.com !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) { 234212854Sgabeblack@google.com value |= ICH_MISR_EL2_VGRP1D; 234312854Sgabeblack@google.com } 234412854Sgabeblack@google.com 234512854Sgabeblack@google.com return value; 234612854Sgabeblack@google.com} 234712854Sgabeblack@google.com 234812854Sgabeblack@google.comvoid 234912854Sgabeblack@google.comGicv3CPUInterface::serialize(CheckpointOut & cp) const 235012854Sgabeblack@google.com{ 235112854Sgabeblack@google.com SERIALIZE_SCALAR(hppi.intid); 235212854Sgabeblack@google.com SERIALIZE_SCALAR(hppi.prio); 235312854Sgabeblack@google.com SERIALIZE_ENUM(hppi.group); 235412854Sgabeblack@google.com} 235512854Sgabeblack@google.com 235612854Sgabeblack@google.comvoid 235712854Sgabeblack@google.comGicv3CPUInterface::unserialize(CheckpointIn & cp) 235812854Sgabeblack@google.com{ 235912854Sgabeblack@google.com UNSERIALIZE_SCALAR(hppi.intid); 236012854Sgabeblack@google.com UNSERIALIZE_SCALAR(hppi.prio); 236112854Sgabeblack@google.com UNSERIALIZE_ENUM(hppi.group); 236212854Sgabeblack@google.com} 236312854Sgabeblack@google.com