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