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