gic_v3_cpu_interface.cc revision 13923
112837Sgabeblack@google.com/*
212837Sgabeblack@google.com * Copyright (c) 2018 Metempsy Technology Consulting
312837Sgabeblack@google.com * All rights reserved.
412837Sgabeblack@google.com *
512837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
612837Sgabeblack@google.com * modification, are permitted provided that the following conditions are
712837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
812837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
912837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1012837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
1112837Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
1212837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
1312837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
1412837Sgabeblack@google.com * this software without specific prior written permission.
1512837Sgabeblack@google.com *
1612837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1712837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1812837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1912837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2012837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2112837Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2212837Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2312837Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2412837Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2512837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2612837Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2712837Sgabeblack@google.com *
2812837Sgabeblack@google.com * Authors: Jairo Balart
2912837Sgabeblack@google.com */
3012901Sgabeblack@google.com
3113135Sgabeblack@google.com#include "dev/arm/gic_v3_cpu_interface.hh"
3212901Sgabeblack@google.com
3312901Sgabeblack@google.com#include "arch/arm/isa.hh"
3412837Sgabeblack@google.com#include "debug/GIC.hh"
3512982Sgabeblack@google.com#include "dev/arm/gic_v3.hh"
3612951Sgabeblack@google.com#include "dev/arm/gic_v3_distributor.hh"
3712953Sgabeblack@google.com#include "dev/arm/gic_v3_redistributor.hh"
3813155Sgabeblack@google.com
3912837Sgabeblack@google.comGicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id)
4012951Sgabeblack@google.com    : BaseISADevice(),
4113155Sgabeblack@google.com      gic(gic),
4213135Sgabeblack@google.com      redistributor(nullptr),
4312837Sgabeblack@google.com      distributor(nullptr),
4412952Sgabeblack@google.com      cpuId(cpu_id)
4512952Sgabeblack@google.com{
4612952Sgabeblack@google.com}
4712952Sgabeblack@google.com
4812952Sgabeblack@google.comvoid
4912952Sgabeblack@google.comGicv3CPUInterface::init()
5013135Sgabeblack@google.com{
5113135Sgabeblack@google.com    redistributor = gic->getRedistributor(cpuId);
5213135Sgabeblack@google.com    distributor = gic->getDistributor();
5313135Sgabeblack@google.com}
5413135Sgabeblack@google.com
5513135Sgabeblack@google.comvoid
5613135Sgabeblack@google.comGicv3CPUInterface::initState()
5713135Sgabeblack@google.com{
5812993Sgabeblack@google.com    reset();
5912993Sgabeblack@google.com}
6012952Sgabeblack@google.com
6112952Sgabeblack@google.comvoid
6212952Sgabeblack@google.comGicv3CPUInterface::reset()
6312952Sgabeblack@google.com{
6412952Sgabeblack@google.com    hppi.prio = 0xff;
6513135Sgabeblack@google.com}
6613135Sgabeblack@google.com
6713135Sgabeblack@google.comvoid
6813135Sgabeblack@google.comGicv3CPUInterface::setThreadContext(ThreadContext *tc)
6913135Sgabeblack@google.com{
7013135Sgabeblack@google.com    maintenanceInterrupt = gic->params()->maint_int->get(tc);
7113135Sgabeblack@google.com}
7213135Sgabeblack@google.com
7312993Sgabeblack@google.combool
7412993Sgabeblack@google.comGicv3CPUInterface::getHCREL2FMO() const
7512952Sgabeblack@google.com{
7612952Sgabeblack@google.com    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
7712952Sgabeblack@google.com
7812952Sgabeblack@google.com    if (hcr.tge && hcr.e2h) {
7912952Sgabeblack@google.com        return false;
8013135Sgabeblack@google.com    } else if (hcr.tge) {
8113135Sgabeblack@google.com        return true;
8213135Sgabeblack@google.com    } else {
8313135Sgabeblack@google.com        return hcr.fmo;
8413135Sgabeblack@google.com    }
8513135Sgabeblack@google.com}
8613135Sgabeblack@google.com
8713135Sgabeblack@google.combool
8812993Sgabeblack@google.comGicv3CPUInterface::getHCREL2IMO() const
8913060Sgabeblack@google.com{
9012993Sgabeblack@google.com    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
9112952Sgabeblack@google.com
9212952Sgabeblack@google.com    if (hcr.tge && hcr.e2h) {
9313035Sgabeblack@google.com        return false;
9413035Sgabeblack@google.com    } else if (hcr.tge) {
9512952Sgabeblack@google.com        return true;
9612952Sgabeblack@google.com    } else {
9712837Sgabeblack@google.com        return hcr.imo;
9812837Sgabeblack@google.com    }
9912837Sgabeblack@google.com}
10013091Sgabeblack@google.com
10112951Sgabeblack@google.comRegVal
10212951Sgabeblack@google.comGicv3CPUInterface::readMiscReg(int misc_reg)
10312837Sgabeblack@google.com{
10413091Sgabeblack@google.com    RegVal value = isa->readMiscRegNoEffect(misc_reg);
10512951Sgabeblack@google.com    bool hcr_fmo = getHCREL2FMO();
10612951Sgabeblack@google.com    bool hcr_imo = getHCREL2IMO();
10712837Sgabeblack@google.com
10813091Sgabeblack@google.com    switch (misc_reg) {
10912837Sgabeblack@google.com      // Active Priorities Group 1 Registers
11012982Sgabeblack@google.com      case MISCREG_ICC_AP1R0:
11112837Sgabeblack@google.com      case MISCREG_ICC_AP1R0_EL1: {
11213091Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
11312837Sgabeblack@google.com              return isa->readMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1);
11412837Sgabeblack@google.com          }
11512837Sgabeblack@google.com
11612837Sgabeblack@google.com          break;
11712837Sgabeblack@google.com      }
11812837Sgabeblack@google.com
11912837Sgabeblack@google.com      case MISCREG_ICC_AP1R1:
12012837Sgabeblack@google.com      case MISCREG_ICC_AP1R1_EL1:
12112837Sgabeblack@google.com
12212837Sgabeblack@google.com        // only implemented if supporting 6 or more bits of priority
12312837Sgabeblack@google.com      case MISCREG_ICC_AP1R2:
12412837Sgabeblack@google.com      case MISCREG_ICC_AP1R2_EL1:
12512837Sgabeblack@google.com
12612837Sgabeblack@google.com        // only implemented if supporting 7 or more bits of priority
12712837Sgabeblack@google.com      case MISCREG_ICC_AP1R3:
12812837Sgabeblack@google.com      case MISCREG_ICC_AP1R3_EL1:
12912837Sgabeblack@google.com        // only implemented if supporting 7 or more bits of priority
13012837Sgabeblack@google.com        return 0;
13112837Sgabeblack@google.com
13212837Sgabeblack@google.com      // Active Priorities Group 0 Registers
13312837Sgabeblack@google.com      case MISCREG_ICC_AP0R0:
13412837Sgabeblack@google.com      case MISCREG_ICC_AP0R0_EL1: {
13512837Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
13612837Sgabeblack@google.com              return isa->readMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1);
13712837Sgabeblack@google.com          }
13812837Sgabeblack@google.com
13912837Sgabeblack@google.com          break;
14012837Sgabeblack@google.com      }
14112837Sgabeblack@google.com
14212837Sgabeblack@google.com      case MISCREG_ICC_AP0R1:
14312837Sgabeblack@google.com      case MISCREG_ICC_AP0R1_EL1:
14412837Sgabeblack@google.com
14512837Sgabeblack@google.com        // only implemented if supporting 6 or more bits of priority
14612837Sgabeblack@google.com      case MISCREG_ICC_AP0R2:
14712837Sgabeblack@google.com      case MISCREG_ICC_AP0R2_EL1:
14812837Sgabeblack@google.com
14912837Sgabeblack@google.com        // only implemented if supporting 7 or more bits of priority
15012837Sgabeblack@google.com      case MISCREG_ICC_AP0R3:
15112837Sgabeblack@google.com      case MISCREG_ICC_AP0R3_EL1:
15212837Sgabeblack@google.com        // only implemented if supporting 7 or more bits of priority
15312837Sgabeblack@google.com        return 0;
15412837Sgabeblack@google.com
15512837Sgabeblack@google.com      // Interrupt Group 0 Enable register EL1
15612837Sgabeblack@google.com      case MISCREG_ICC_IGRPEN0:
15712837Sgabeblack@google.com      case MISCREG_ICC_IGRPEN0_EL1: {
15812837Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
15912837Sgabeblack@google.com              return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN0_EL1);
16012837Sgabeblack@google.com          }
16112837Sgabeblack@google.com
16212837Sgabeblack@google.com          break;
16312837Sgabeblack@google.com      }
16412837Sgabeblack@google.com
16512837Sgabeblack@google.com      // Interrupt Group 1 Enable register EL1
16612837Sgabeblack@google.com      case MISCREG_ICC_IGRPEN1:
16712837Sgabeblack@google.com      case MISCREG_ICC_IGRPEN1_EL1: {
16812837Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
16912837Sgabeblack@google.com              return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN1_EL1);
17012837Sgabeblack@google.com          }
17112837Sgabeblack@google.com
17212837Sgabeblack@google.com          break;
17312837Sgabeblack@google.com      }
17412837Sgabeblack@google.com
17512837Sgabeblack@google.com      // Interrupt Group 1 Enable register EL3
17612837Sgabeblack@google.com      case MISCREG_ICC_MGRPEN1:
17712837Sgabeblack@google.com      case MISCREG_ICC_IGRPEN1_EL3:
17812837Sgabeblack@google.com          break;
17912837Sgabeblack@google.com
18013091Sgabeblack@google.com      // Running Priority Register
18113091Sgabeblack@google.com      case MISCREG_ICC_RPR:
18213091Sgabeblack@google.com      case MISCREG_ICC_RPR_EL1: {
18313091Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() &&
18413091Sgabeblack@google.com              (hcr_imo || hcr_fmo)) {
18513091Sgabeblack@google.com              return readMiscReg(MISCREG_ICV_RPR_EL1);
18613091Sgabeblack@google.com          }
18713091Sgabeblack@google.com
18813091Sgabeblack@google.com          uint8_t rprio = highestActivePriority();
18913091Sgabeblack@google.com
19013091Sgabeblack@google.com          if (haveEL(EL3) && !inSecureState() &&
19113091Sgabeblack@google.com              (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
19213091Sgabeblack@google.com              // Spec section 4.8.1
19313091Sgabeblack@google.com              // For Non-secure access to ICC_RPR_EL1 when SCR_EL3.FIQ == 1
19413091Sgabeblack@google.com              if ((rprio & 0x80) == 0) {
19513091Sgabeblack@google.com                  // If the current priority mask value is in the range of
19613091Sgabeblack@google.com                  // 0x00-0x7F a read access returns the value 0x0
19713091Sgabeblack@google.com                  rprio = 0;
19813091Sgabeblack@google.com              } else if (rprio != 0xff) {
19913091Sgabeblack@google.com                  // If the current priority mask value is in the range of
20013091Sgabeblack@google.com                  // 0x80-0xFF a read access returns the Non-secure read of
20113091Sgabeblack@google.com                  // the current value
20213091Sgabeblack@google.com                  rprio = (rprio << 1) & 0xff;
20313091Sgabeblack@google.com              }
20412837Sgabeblack@google.com          }
20512837Sgabeblack@google.com
20612837Sgabeblack@google.com          value = rprio;
20712837Sgabeblack@google.com          break;
20812837Sgabeblack@google.com      }
20912951Sgabeblack@google.com
21012837Sgabeblack@google.com      // Virtual Running Priority Register
21112837Sgabeblack@google.com      case MISCREG_ICV_RPR_EL1: {
21212837Sgabeblack@google.com          value = virtualHighestActivePriority();
21312837Sgabeblack@google.com          break;
21412837Sgabeblack@google.com      }
21512951Sgabeblack@google.com
21612837Sgabeblack@google.com      // Highest Priority Pending Interrupt Register 0
21712837Sgabeblack@google.com      case MISCREG_ICC_HPPIR0:
21812951Sgabeblack@google.com      case MISCREG_ICC_HPPIR0_EL1: {
21913079Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
22012951Sgabeblack@google.com              return readMiscReg(MISCREG_ICV_HPPIR0_EL1);
22112951Sgabeblack@google.com          }
22212837Sgabeblack@google.com
22312951Sgabeblack@google.com          value = getHPPIR0();
22412951Sgabeblack@google.com          break;
22512951Sgabeblack@google.com      }
22612951Sgabeblack@google.com
22712951Sgabeblack@google.com      // Virtual Highest Priority Pending Interrupt Register 0
22812928Sgabeblack@google.com      case MISCREG_ICV_HPPIR0_EL1: {
22912837Sgabeblack@google.com          value = Gicv3::INTID_SPURIOUS;
23012837Sgabeblack@google.com          int lr_idx = getHPPVILR();
23112837Sgabeblack@google.com
23212837Sgabeblack@google.com          if (lr_idx >= 0) {
23312837Sgabeblack@google.com              ICH_LR_EL2 ich_lr_el2 =
23412837Sgabeblack@google.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
23512837Sgabeblack@google.com              Gicv3::GroupId group =
23612837Sgabeblack@google.com                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
23712837Sgabeblack@google.com
23812837Sgabeblack@google.com              if (group == Gicv3::G0S) {
23912837Sgabeblack@google.com                  value = ich_lr_el2.vINTID;
24012837Sgabeblack@google.com              }
24112837Sgabeblack@google.com          }
24212837Sgabeblack@google.com
24312837Sgabeblack@google.com          break;
24412837Sgabeblack@google.com      }
24512837Sgabeblack@google.com
24612837Sgabeblack@google.com      // Highest Priority Pending Interrupt Register 1
24712837Sgabeblack@google.com      case MISCREG_ICC_HPPIR1:
24812837Sgabeblack@google.com      case MISCREG_ICC_HPPIR1_EL1: {
24912837Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
25012837Sgabeblack@google.com              return readMiscReg(MISCREG_ICV_HPPIR1_EL1);
25112837Sgabeblack@google.com          }
25212837Sgabeblack@google.com
25312837Sgabeblack@google.com          value = getHPPIR1();
25412837Sgabeblack@google.com          break;
25512837Sgabeblack@google.com      }
25612837Sgabeblack@google.com
25712837Sgabeblack@google.com      // Virtual Highest Priority Pending Interrupt Register 1
25812837Sgabeblack@google.com      case MISCREG_ICV_HPPIR1_EL1: {
25912837Sgabeblack@google.com          value = Gicv3::INTID_SPURIOUS;
26012837Sgabeblack@google.com          int lr_idx = getHPPVILR();
26112837Sgabeblack@google.com
26212837Sgabeblack@google.com          if (lr_idx >= 0) {
26312837Sgabeblack@google.com              ICH_LR_EL2 ich_lr_el2 =
26412837Sgabeblack@google.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
26512837Sgabeblack@google.com              Gicv3::GroupId group =
26612837Sgabeblack@google.com                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
26712837Sgabeblack@google.com
26812837Sgabeblack@google.com              if (group == Gicv3::G1NS) {
26912837Sgabeblack@google.com                  value = ich_lr_el2.vINTID;
27012837Sgabeblack@google.com              }
27112837Sgabeblack@google.com          }
27212837Sgabeblack@google.com
27312837Sgabeblack@google.com          break;
27412837Sgabeblack@google.com      }
27512837Sgabeblack@google.com
27612837Sgabeblack@google.com      // Binary Point Register 0
27712837Sgabeblack@google.com      case MISCREG_ICC_BPR0:
27812837Sgabeblack@google.com      case MISCREG_ICC_BPR0_EL1:
27912837Sgabeblack@google.com        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
28012837Sgabeblack@google.com            return readMiscReg(MISCREG_ICV_BPR0_EL1);
28112837Sgabeblack@google.com        }
28212953Sgabeblack@google.com
28312837Sgabeblack@google.com        M5_FALLTHROUGH;
28412837Sgabeblack@google.com
28512837Sgabeblack@google.com      // Binary Point Register 1
28612953Sgabeblack@google.com      case MISCREG_ICC_BPR1:
28712837Sgabeblack@google.com      case MISCREG_ICC_BPR1_EL1: {
28812953Sgabeblack@google.com            if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
28912837Sgabeblack@google.com                return readMiscReg(MISCREG_ICV_BPR1_EL1);
29012837Sgabeblack@google.com            }
29112837Sgabeblack@google.com
29212951Sgabeblack@google.com            Gicv3::GroupId group =
29312951Sgabeblack@google.com                misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S;
29412837Sgabeblack@google.com
29512951Sgabeblack@google.com            if (group == Gicv3::G1S && !inSecureState()) {
29612837Sgabeblack@google.com                group = Gicv3::G1NS;
29712951Sgabeblack@google.com            }
29812837Sgabeblack@google.com
29912837Sgabeblack@google.com            ICC_CTLR_EL1 icc_ctlr_el1_s =
30012837Sgabeblack@google.com                isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
30112951Sgabeblack@google.com
30212837Sgabeblack@google.com            if ((group == Gicv3::G1S) && !isEL3OrMon() &&
30312951Sgabeblack@google.com                icc_ctlr_el1_s.CBPR) {
30412837Sgabeblack@google.com                group = Gicv3::G0S;
30512837Sgabeblack@google.com            }
30612837Sgabeblack@google.com
30712951Sgabeblack@google.com            bool sat_inc = false;
30812837Sgabeblack@google.com
30912951Sgabeblack@google.com            ICC_CTLR_EL1 icc_ctlr_el1_ns =
31012837Sgabeblack@google.com                isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
31112837Sgabeblack@google.com
31212837Sgabeblack@google.com            if ((group == Gicv3::G1NS) && (currEL() < EL3) &&
31312951Sgabeblack@google.com                icc_ctlr_el1_ns.CBPR) {
31412837Sgabeblack@google.com                // Reads return BPR0 + 1 saturated to 7, WI
31512951Sgabeblack@google.com                group = Gicv3::G0S;
31612837Sgabeblack@google.com                sat_inc = true;
31712837Sgabeblack@google.com            }
31812837Sgabeblack@google.com
31912951Sgabeblack@google.com            uint8_t bpr;
32012837Sgabeblack@google.com
32112951Sgabeblack@google.com            if (group == Gicv3::G0S) {
32212837Sgabeblack@google.com                bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1);
32312837Sgabeblack@google.com            } else {
32412837Sgabeblack@google.com                bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1);
32512951Sgabeblack@google.com            }
32612837Sgabeblack@google.com
32712951Sgabeblack@google.com            if (sat_inc) {
32812837Sgabeblack@google.com                bpr++;
32912837Sgabeblack@google.com
33012837Sgabeblack@google.com                if (bpr > 7) {
33112951Sgabeblack@google.com                    bpr = 7;
33212837Sgabeblack@google.com                }
33312951Sgabeblack@google.com            }
33412837Sgabeblack@google.com
33512837Sgabeblack@google.com            value = bpr;
33612837Sgabeblack@google.com            break;
33712951Sgabeblack@google.com      }
33812837Sgabeblack@google.com
33912951Sgabeblack@google.com      // Virtual Binary Point Register 1
34012837Sgabeblack@google.com      case MISCREG_ICV_BPR0_EL1:
34112837Sgabeblack@google.com      case MISCREG_ICV_BPR1_EL1: {
34212837Sgabeblack@google.com          Gicv3::GroupId group =
34312951Sgabeblack@google.com              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
34412837Sgabeblack@google.com          ICH_VMCR_EL2 ich_vmcr_el2 =
34512951Sgabeblack@google.com              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
34612837Sgabeblack@google.com          bool sat_inc = false;
34712837Sgabeblack@google.com
34812837Sgabeblack@google.com          if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
34912951Sgabeblack@google.com              // bpr0 + 1 saturated to 7, WI
35012837Sgabeblack@google.com              group = Gicv3::G0S;
35112951Sgabeblack@google.com              sat_inc = true;
35212837Sgabeblack@google.com          }
35312837Sgabeblack@google.com
35412837Sgabeblack@google.com          uint8_t vbpr;
35512951Sgabeblack@google.com
35612837Sgabeblack@google.com          if (group == Gicv3::G0S) {
35712951Sgabeblack@google.com              vbpr = ich_vmcr_el2.VBPR0;
35812837Sgabeblack@google.com          } else {
35912837Sgabeblack@google.com              vbpr = ich_vmcr_el2.VBPR1;
36012837Sgabeblack@google.com          }
36112929Sgabeblack@google.com
36212929Sgabeblack@google.com          if (sat_inc) {
36312929Sgabeblack@google.com              vbpr++;
36413189Sgabeblack@google.com
36512929Sgabeblack@google.com              if (vbpr > 7) {
36612929Sgabeblack@google.com                  vbpr = 7;
36712929Sgabeblack@google.com              }
36812837Sgabeblack@google.com          }
36912837Sgabeblack@google.com
37012837Sgabeblack@google.com          value = vbpr;
37112951Sgabeblack@google.com          break;
37212837Sgabeblack@google.com      }
37312837Sgabeblack@google.com
37412837Sgabeblack@google.com      // Interrupt Priority Mask Register
37512951Sgabeblack@google.com      case MISCREG_ICC_PMR:
37612837Sgabeblack@google.com      case MISCREG_ICC_PMR_EL1:
37712951Sgabeblack@google.com        if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
37812837Sgabeblack@google.com            return isa->readMiscRegNoEffect(MISCREG_ICV_PMR_EL1);
37912837Sgabeblack@google.com        }
38012837Sgabeblack@google.com
38112951Sgabeblack@google.com        if (haveEL(EL3) && !inSecureState() &&
38212837Sgabeblack@google.com            (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
38312951Sgabeblack@google.com            // Spec section 4.8.1
38412837Sgabeblack@google.com            // For Non-secure access to ICC_PMR_EL1 when SCR_EL3.FIQ == 1:
38512837Sgabeblack@google.com            if ((value & 0x80) == 0) {
38612837Sgabeblack@google.com                // If the current priority mask value is in the range of
38712951Sgabeblack@google.com                // 0x00-0x7F a read access returns the value 0x00.
38812837Sgabeblack@google.com                value = 0;
38912951Sgabeblack@google.com            } else if (value != 0xff) {
39012837Sgabeblack@google.com                // If the current priority mask value is in the range of
39112837Sgabeblack@google.com                // 0x80-0xFF a read access returns the Non-secure read of the
39212837Sgabeblack@google.com                // current value.
39312951Sgabeblack@google.com                value = (value << 1) & 0xff;
39412837Sgabeblack@google.com            }
39512951Sgabeblack@google.com        }
39612837Sgabeblack@google.com
39712837Sgabeblack@google.com        break;
39812837Sgabeblack@google.com
39912951Sgabeblack@google.com      // Interrupt Acknowledge Register 0
40012837Sgabeblack@google.com      case MISCREG_ICC_IAR0:
40112951Sgabeblack@google.com      case MISCREG_ICC_IAR0_EL1: {
40212837Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
40312837Sgabeblack@google.com              return readMiscReg(MISCREG_ICV_IAR0_EL1);
40412837Sgabeblack@google.com          }
40512951Sgabeblack@google.com
40612837Sgabeblack@google.com          uint32_t int_id;
40712951Sgabeblack@google.com
40812837Sgabeblack@google.com          if (hppiCanPreempt()) {
40912837Sgabeblack@google.com              int_id = getHPPIR0();
41012837Sgabeblack@google.com
41112951Sgabeblack@google.com              // avoid activation for special interrupts
41212837Sgabeblack@google.com              if (int_id < Gicv3::INTID_SECURE ||
41312951Sgabeblack@google.com                  int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
41412837Sgabeblack@google.com                  activateIRQ(int_id, hppi.group);
41512837Sgabeblack@google.com              }
41612837Sgabeblack@google.com          } else {
41712951Sgabeblack@google.com              int_id = Gicv3::INTID_SPURIOUS;
41812837Sgabeblack@google.com          }
41912951Sgabeblack@google.com
42012837Sgabeblack@google.com          value = int_id;
42112837Sgabeblack@google.com          break;
42212837Sgabeblack@google.com      }
42312951Sgabeblack@google.com
42412837Sgabeblack@google.com      // Virtual Interrupt Acknowledge Register 0
42512951Sgabeblack@google.com      case MISCREG_ICV_IAR0_EL1: {
42612837Sgabeblack@google.com          int lr_idx = getHPPVILR();
42712837Sgabeblack@google.com          uint32_t int_id = Gicv3::INTID_SPURIOUS;
42812837Sgabeblack@google.com
42912951Sgabeblack@google.com          if (lr_idx >= 0) {
43012837Sgabeblack@google.com              ICH_LR_EL2 ich_lr_el2 =
43112951Sgabeblack@google.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
43212837Sgabeblack@google.com
43312837Sgabeblack@google.com              if (!ich_lr_el2.Group && hppviCanPreempt(lr_idx)) {
43412837Sgabeblack@google.com                  int_id = ich_lr_el2.vINTID;
43512951Sgabeblack@google.com
43612837Sgabeblack@google.com                  if (int_id < Gicv3::INTID_SECURE ||
43712951Sgabeblack@google.com                      int_id > Gicv3::INTID_SPURIOUS) {
43812837Sgabeblack@google.com                      virtualActivateIRQ(lr_idx);
43912837Sgabeblack@google.com                  } else {
44012837Sgabeblack@google.com                      // Bogus... Pseudocode says:
44112951Sgabeblack@google.com                      // - Move from pending to invalid...
44212837Sgabeblack@google.com                      // - Return de bogus id...
44312951Sgabeblack@google.com                      ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID;
44412837Sgabeblack@google.com                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
44512837Sgabeblack@google.com                                              ich_lr_el2);
44612837Sgabeblack@google.com                  }
44712837Sgabeblack@google.com              }
44812909Sgabeblack@google.com          }
44912909Sgabeblack@google.com
45012951Sgabeblack@google.com          value = int_id;
45112909Sgabeblack@google.com          virtualUpdate();
45212909Sgabeblack@google.com          break;
45312914Sgabeblack@google.com      }
45412951Sgabeblack@google.com
45512914Sgabeblack@google.com      // Interrupt Acknowledge Register 1
45612951Sgabeblack@google.com      case MISCREG_ICC_IAR1:
45712914Sgabeblack@google.com      case MISCREG_ICC_IAR1_EL1: {
45812914Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
45912914Sgabeblack@google.com              return readMiscReg(MISCREG_ICV_IAR1_EL1);
46012951Sgabeblack@google.com          }
46112914Sgabeblack@google.com
46212951Sgabeblack@google.com          uint32_t int_id;
46312914Sgabeblack@google.com
46412914Sgabeblack@google.com          if (hppiCanPreempt()) {
46512914Sgabeblack@google.com              int_id = getHPPIR1();
46612951Sgabeblack@google.com
46712914Sgabeblack@google.com              // avoid activation for special interrupts
46812951Sgabeblack@google.com              if (int_id < Gicv3::INTID_SECURE ||
46912914Sgabeblack@google.com                  int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
47012914Sgabeblack@google.com                  activateIRQ(int_id, hppi.group);
47112914Sgabeblack@google.com              }
47212951Sgabeblack@google.com          } else {
47312914Sgabeblack@google.com              int_id = Gicv3::INTID_SPURIOUS;
47412951Sgabeblack@google.com          }
47512914Sgabeblack@google.com
47612914Sgabeblack@google.com          value = int_id;
47712909Sgabeblack@google.com          break;
47812909Sgabeblack@google.com      }
47912837Sgabeblack@google.com
48012837Sgabeblack@google.com      // Virtual Interrupt Acknowledge Register 1
48112958Sgabeblack@google.com      case MISCREG_ICV_IAR1_EL1: {
48212958Sgabeblack@google.com          int lr_idx = getHPPVILR();
48312837Sgabeblack@google.com          uint32_t int_id = Gicv3::INTID_SPURIOUS;
48412837Sgabeblack@google.com
48512837Sgabeblack@google.com          if (lr_idx >= 0) {
48612958Sgabeblack@google.com              ICH_LR_EL2 ich_lr_el2 =
48712837Sgabeblack@google.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
48812958Sgabeblack@google.com
48912958Sgabeblack@google.com              if (ich_lr_el2.Group && hppviCanPreempt(lr_idx)) {
49012837Sgabeblack@google.com                  int_id = ich_lr_el2.vINTID;
49112837Sgabeblack@google.com
49212837Sgabeblack@google.com                  if (int_id < Gicv3::INTID_SECURE ||
49312958Sgabeblack@google.com                      int_id > Gicv3::INTID_SPURIOUS) {
49412837Sgabeblack@google.com                      virtualActivateIRQ(lr_idx);
49512958Sgabeblack@google.com                  } else {
49612958Sgabeblack@google.com                      // Bogus... Pseudocode says:
49712837Sgabeblack@google.com                      // - Move from pending to invalid...
49812837Sgabeblack@google.com                      // - Return de bogus id...
49912837Sgabeblack@google.com                      ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID;
50012958Sgabeblack@google.com                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
50112837Sgabeblack@google.com                                              ich_lr_el2);
50212958Sgabeblack@google.com                  }
50312958Sgabeblack@google.com              }
50412837Sgabeblack@google.com          }
50512837Sgabeblack@google.com
50612837Sgabeblack@google.com          value = int_id;
50712958Sgabeblack@google.com          virtualUpdate();
50812837Sgabeblack@google.com          break;
50912958Sgabeblack@google.com      }
51012958Sgabeblack@google.com
51112837Sgabeblack@google.com      // System Register Enable Register EL1
51212837Sgabeblack@google.com      case MISCREG_ICC_SRE:
51312837Sgabeblack@google.com      case MISCREG_ICC_SRE_EL1: {
51412951Sgabeblack@google.com        /*
51512837Sgabeblack@google.com         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
51612951Sgabeblack@google.com         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
51712837Sgabeblack@google.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
51812837Sgabeblack@google.com         */
51912837Sgabeblack@google.com          ICC_SRE_EL1 icc_sre_el1 = 0;
52012958Sgabeblack@google.com          icc_sre_el1.SRE = 1;
52112837Sgabeblack@google.com          icc_sre_el1.DIB = 1;
52212958Sgabeblack@google.com          icc_sre_el1.DFB = 1;
52312958Sgabeblack@google.com          value = icc_sre_el1;
52412837Sgabeblack@google.com          break;
52512837Sgabeblack@google.com      }
52612837Sgabeblack@google.com
52712951Sgabeblack@google.com      // System Register Enable Register EL2
52812837Sgabeblack@google.com      case MISCREG_ICC_HSRE:
52912951Sgabeblack@google.com      case MISCREG_ICC_SRE_EL2: {
53012837Sgabeblack@google.com        /*
53112837Sgabeblack@google.com         * Enable [3] == 1
53212837Sgabeblack@google.com         * (EL1 accesses to ICC_SRE_EL1 do not trap to EL2, RAO/WI)
53312958Sgabeblack@google.com         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
53412837Sgabeblack@google.com         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
53512958Sgabeblack@google.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
53612958Sgabeblack@google.com         */
53712958Sgabeblack@google.com        ICC_SRE_EL2 icc_sre_el2 = 0;
53812837Sgabeblack@google.com        icc_sre_el2.SRE = 1;
53912837Sgabeblack@google.com        icc_sre_el2.DIB = 1;
54012837Sgabeblack@google.com        icc_sre_el2.DFB = 1;
54112951Sgabeblack@google.com        icc_sre_el2.Enable = 1;
54212837Sgabeblack@google.com        value = icc_sre_el2;
54312951Sgabeblack@google.com        break;
54412837Sgabeblack@google.com      }
54512837Sgabeblack@google.com
54612837Sgabeblack@google.com      // System Register Enable Register EL3
54712958Sgabeblack@google.com      case MISCREG_ICC_MSRE:
54812837Sgabeblack@google.com      case MISCREG_ICC_SRE_EL3: {
54912958Sgabeblack@google.com        /*
55012958Sgabeblack@google.com         * Enable [3] == 1
55112958Sgabeblack@google.com         * (EL1 accesses to ICC_SRE_EL1 do not trap to EL3.
55212837Sgabeblack@google.com         *  EL2 accesses to ICC_SRE_EL1 and ICC_SRE_EL2 do not trap to EL3.
55312837Sgabeblack@google.com         *  RAO/WI)
55412837Sgabeblack@google.com         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
55512951Sgabeblack@google.com         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
55612837Sgabeblack@google.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
55712951Sgabeblack@google.com         */
55812837Sgabeblack@google.com        ICC_SRE_EL3 icc_sre_el3 = 0;
55912837Sgabeblack@google.com        icc_sre_el3.SRE = 1;
56012929Sgabeblack@google.com        icc_sre_el3.DIB = 1;
56112929Sgabeblack@google.com        icc_sre_el3.DFB = 1;
56212929Sgabeblack@google.com        icc_sre_el3.Enable = 1;
56313189Sgabeblack@google.com        value = icc_sre_el3;
56413189Sgabeblack@google.com        break;
56513189Sgabeblack@google.com      }
56613189Sgabeblack@google.com
56713189Sgabeblack@google.com      // Control Register
56812929Sgabeblack@google.com      case MISCREG_ICC_CTLR:
56912929Sgabeblack@google.com      case MISCREG_ICC_CTLR_EL1: {
57012837Sgabeblack@google.com          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
57112837Sgabeblack@google.com              return readMiscReg(MISCREG_ICV_CTLR_EL1);
57212837Sgabeblack@google.com          }
57312837Sgabeblack@google.com
57412958Sgabeblack@google.com          // Enforce value for RO bits
57512958Sgabeblack@google.com          // ExtRange [19], INTIDs in the range 1024..8191 not supported
57612958Sgabeblack@google.com          // RSS [18], SGIs with affinity level 0 values of 0-255 are supported
57712837Sgabeblack@google.com          // A3V [15], supports non-zero values of the Aff3 field in SGI
57812837Sgabeblack@google.com          //           generation System registers
57912837Sgabeblack@google.com          // SEIS [14], does not support generation of SEIs (deprecated)
58012958Sgabeblack@google.com          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
58112837Sgabeblack@google.com          // PRIbits [10:8], number of priority bits implemented, minus one
58213146Sgabeblack@google.com          ICC_CTLR_EL1 icc_ctlr_el1 = value;
58313146Sgabeblack@google.com          icc_ctlr_el1.ExtRange = 0;
58413146Sgabeblack@google.com          icc_ctlr_el1.RSS = 1;
58513146Sgabeblack@google.com          icc_ctlr_el1.A3V = 1;
58612958Sgabeblack@google.com          icc_ctlr_el1.SEIS = 0;
58712958Sgabeblack@google.com          icc_ctlr_el1.IDbits = 1;
58812837Sgabeblack@google.com          icc_ctlr_el1.PRIbits = PRIORITY_BITS - 1;
58912837Sgabeblack@google.com          value = icc_ctlr_el1;
59012837Sgabeblack@google.com          break;
59112958Sgabeblack@google.com      }
59212837Sgabeblack@google.com
59312958Sgabeblack@google.com      // Virtual Control Register
59412958Sgabeblack@google.com      case MISCREG_ICV_CTLR_EL1: {
59512958Sgabeblack@google.com          ICV_CTLR_EL1 icv_ctlr_el1 = value;
59612837Sgabeblack@google.com          icv_ctlr_el1.RSS = 0;
59712837Sgabeblack@google.com          icv_ctlr_el1.A3V = 1;
59812837Sgabeblack@google.com          icv_ctlr_el1.SEIS = 0;
59912958Sgabeblack@google.com          icv_ctlr_el1.IDbits = 1;
60012837Sgabeblack@google.com          icv_ctlr_el1.PRIbits = 7;
60112958Sgabeblack@google.com          value = icv_ctlr_el1;
60212958Sgabeblack@google.com          break;
60312958Sgabeblack@google.com      }
60412837Sgabeblack@google.com
60512837Sgabeblack@google.com      // Control Register
60612837Sgabeblack@google.com      case MISCREG_ICC_MCTLR:
60712958Sgabeblack@google.com      case MISCREG_ICC_CTLR_EL3: {
60812837Sgabeblack@google.com          // Enforce value for RO bits
60912958Sgabeblack@google.com          // ExtRange [19], INTIDs in the range 1024..8191 not supported
61012958Sgabeblack@google.com          // RSS [18], SGIs with affinity level 0 values of 0-255 are supported
61112958Sgabeblack@google.com          // nDS [17], supports disabling of security
61212837Sgabeblack@google.com          // A3V [15], supports non-zero values of the Aff3 field in SGI
61312837Sgabeblack@google.com          //           generation System registers
61412837Sgabeblack@google.com          // SEIS [14], does not support generation of SEIs (deprecated)
61512958Sgabeblack@google.com          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
61612837Sgabeblack@google.com          // PRIbits [10:8], number of priority bits implemented, minus one
61712958Sgabeblack@google.com          ICC_CTLR_EL3 icc_ctlr_el3 = value;
61812958Sgabeblack@google.com          icc_ctlr_el3.ExtRange = 0;
61912958Sgabeblack@google.com          icc_ctlr_el3.RSS = 1;
62012837Sgabeblack@google.com          icc_ctlr_el3.nDS = 0;
62112837Sgabeblack@google.com          icc_ctlr_el3.A3V = 1;
62212837Sgabeblack@google.com          icc_ctlr_el3.SEIS = 0;
62312951Sgabeblack@google.com          icc_ctlr_el3.IDbits = 0;
62412837Sgabeblack@google.com          icc_ctlr_el3.PRIbits = PRIORITY_BITS - 1;
62512951Sgabeblack@google.com          value = icc_ctlr_el3;
62612837Sgabeblack@google.com          break;
62712837Sgabeblack@google.com      }
62812837Sgabeblack@google.com
62912958Sgabeblack@google.com      // Hyp Control Register
63012837Sgabeblack@google.com      case MISCREG_ICH_HCR:
63112958Sgabeblack@google.com      case MISCREG_ICH_HCR_EL2:
63212958Sgabeblack@google.com        break;
63312958Sgabeblack@google.com
63412837Sgabeblack@google.com      // Hyp Active Priorities Group 0 Registers
63512837Sgabeblack@google.com      case MISCREG_ICH_AP0R0:
63612837Sgabeblack@google.com      case MISCREG_ICH_AP0R0_EL2:
63712951Sgabeblack@google.com        break;
63812837Sgabeblack@google.com
63912951Sgabeblack@google.com      // Hyp Active Priorities Group 1 Registers
64012837Sgabeblack@google.com      case MISCREG_ICH_AP1R0:
64112837Sgabeblack@google.com      case MISCREG_ICH_AP1R0_EL2:
64212837Sgabeblack@google.com        break;
64312958Sgabeblack@google.com
64412837Sgabeblack@google.com      // Maintenance Interrupt State Register
64512958Sgabeblack@google.com      case MISCREG_ICH_MISR:
64612958Sgabeblack@google.com      case MISCREG_ICH_MISR_EL2:
64712958Sgabeblack@google.com        value = maintenanceInterruptStatus();
64812958Sgabeblack@google.com        break;
64912837Sgabeblack@google.com
65012837Sgabeblack@google.com      // VGIC Type Register
65112837Sgabeblack@google.com      case MISCREG_ICH_VTR:
65212951Sgabeblack@google.com      case MISCREG_ICH_VTR_EL2: {
65312837Sgabeblack@google.com        ICH_VTR_EL2 ich_vtr_el2 = value;
65412951Sgabeblack@google.com
65512837Sgabeblack@google.com        ich_vtr_el2.ListRegs = VIRTUAL_NUM_LIST_REGS - 1;
65612837Sgabeblack@google.com        ich_vtr_el2.A3V = 1;
65712837Sgabeblack@google.com        ich_vtr_el2.IDbits = 1;
65812958Sgabeblack@google.com        ich_vtr_el2.PREbits = VIRTUAL_PREEMPTION_BITS - 1;
65912837Sgabeblack@google.com        ich_vtr_el2.PRIbits = VIRTUAL_PRIORITY_BITS - 1;
66012958Sgabeblack@google.com
66112958Sgabeblack@google.com        value = ich_vtr_el2;
66212958Sgabeblack@google.com        break;
66312958Sgabeblack@google.com      }
66412837Sgabeblack@google.com
66512837Sgabeblack@google.com      // End of Interrupt Status Register
66612837Sgabeblack@google.com      case MISCREG_ICH_EISR:
66712951Sgabeblack@google.com      case MISCREG_ICH_EISR_EL2:
66812837Sgabeblack@google.com        value = eoiMaintenanceInterruptStatus();
66912951Sgabeblack@google.com        break;
67012837Sgabeblack@google.com
67112837Sgabeblack@google.com      // Empty List Register Status Register
67212909Sgabeblack@google.com      case MISCREG_ICH_ELRSR:
67312909Sgabeblack@google.com      case MISCREG_ICH_ELRSR_EL2:
67412909Sgabeblack@google.com        value = 0;
67513175Sgabeblack@google.com
67613175Sgabeblack@google.com        for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
67712909Sgabeblack@google.com            ICH_LR_EL2 ich_lr_el2 =
67812909Sgabeblack@google.com                isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
67912914Sgabeblack@google.com
68013155Sgabeblack@google.com            if ((ich_lr_el2.State  == ICH_LR_EL2_STATE_INVALID) &&
68112914Sgabeblack@google.com                (ich_lr_el2.HW || !ich_lr_el2.EOI)) {
68213155Sgabeblack@google.com                value |= (1 << lr_idx);
68313155Sgabeblack@google.com            }
68413155Sgabeblack@google.com        }
68513155Sgabeblack@google.com
68612914Sgabeblack@google.com        break;
68712914Sgabeblack@google.com
68812914Sgabeblack@google.com      // List Registers
68913155Sgabeblack@google.com      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15:
69012914Sgabeblack@google.com        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
69113155Sgabeblack@google.com        value = value >> 32;
69213155Sgabeblack@google.com        break;
69313155Sgabeblack@google.com
69413155Sgabeblack@google.com      // List Registers
69512914Sgabeblack@google.com      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15:
69612914Sgabeblack@google.com        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
69712914Sgabeblack@google.com        value = value & 0xffffffff;
69813155Sgabeblack@google.com        break;
69912914Sgabeblack@google.com
70013155Sgabeblack@google.com      // List Registers
70113155Sgabeblack@google.com      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2:
70213155Sgabeblack@google.com        break;
70313155Sgabeblack@google.com
70412914Sgabeblack@google.com      // Virtual Machine Control Register
70512914Sgabeblack@google.com      case MISCREG_ICH_VMCR:
70612914Sgabeblack@google.com      case MISCREG_ICH_VMCR_EL2:
70713155Sgabeblack@google.com        break;
70812914Sgabeblack@google.com
70913155Sgabeblack@google.com      default:
71013155Sgabeblack@google.com        panic("Gicv3CPUInterface::readMiscReg(): unknown register %d (%s)",
71113155Sgabeblack@google.com              misc_reg, miscRegName[misc_reg]);
71213155Sgabeblack@google.com    }
71312914Sgabeblack@google.com
71412914Sgabeblack@google.com    DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): register %s value %#x\n",
71512837Sgabeblack@google.com            miscRegName[misc_reg], value);
71613035Sgabeblack@google.com    return value;
71712837Sgabeblack@google.com}
71813035Sgabeblack@google.com
71913035Sgabeblack@google.comvoid
72013035Sgabeblack@google.comGicv3CPUInterface::setMiscReg(int misc_reg, RegVal val)
72112837Sgabeblack@google.com{
72212837Sgabeblack@google.com    bool do_virtual_update = false;
72312837Sgabeblack@google.com    DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): register %s value %#x\n",
72412930Sgabeblack@google.com            miscRegName[misc_reg], val);
72512930Sgabeblack@google.com    bool hcr_fmo = getHCREL2FMO();
72612930Sgabeblack@google.com    bool hcr_imo = getHCREL2IMO();
72712930Sgabeblack@google.com
72812930Sgabeblack@google.com    switch (misc_reg) {
72912930Sgabeblack@google.com      // Active Priorities Group 1 Registers
73012930Sgabeblack@google.com      case MISCREG_ICC_AP1R0:
73112837Sgabeblack@google.com      case MISCREG_ICC_AP1R0_EL1:
73212837Sgabeblack@google.com        if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
73312982Sgabeblack@google.com            return isa->setMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1, val);
73412837Sgabeblack@google.com        }
73512837Sgabeblack@google.com
73612837Sgabeblack@google.com        break;
73712837Sgabeblack@google.com
73812837Sgabeblack@google.com      case MISCREG_ICC_AP1R1:
73912982Sgabeblack@google.com      case MISCREG_ICC_AP1R1_EL1:
74012837Sgabeblack@google.com
74112837Sgabeblack@google.com        // only implemented if supporting 6 or more bits of priority
74212901Sgabeblack@google.com      case MISCREG_ICC_AP1R2:
74312901Sgabeblack@google.com      case MISCREG_ICC_AP1R2_EL1:
74412901Sgabeblack@google.com
74512901Sgabeblack@google.com        // only implemented if supporting 7 or more bits of priority
74612901Sgabeblack@google.com      case MISCREG_ICC_AP1R3:
74712901Sgabeblack@google.com      case MISCREG_ICC_AP1R3_EL1:
74812901Sgabeblack@google.com        // only implemented if supporting 7 or more bits of priority
74912901Sgabeblack@google.com        break;
75012837Sgabeblack@google.com
751      // Active Priorities Group 0 Registers
752      case MISCREG_ICC_AP0R0:
753      case MISCREG_ICC_AP0R0_EL1:
754        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
755            return isa->setMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1, val);
756        }
757
758        break;
759
760      case MISCREG_ICC_AP0R1:
761      case MISCREG_ICC_AP0R1_EL1:
762
763        // only implemented if supporting 6 or more bits of priority
764      case MISCREG_ICC_AP0R2:
765      case MISCREG_ICC_AP0R2_EL1:
766
767        // only implemented if supporting 7 or more bits of priority
768      case MISCREG_ICC_AP0R3:
769      case MISCREG_ICC_AP0R3_EL1:
770        // only implemented if supporting 7 or more bits of priority
771        break;
772
773      // End Of Interrupt Register 0
774      case MISCREG_ICC_EOIR0:
775      case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0
776          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
777              return setMiscReg(MISCREG_ICV_EOIR0_EL1, val);
778          }
779
780          int int_id = val & 0xffffff;
781
782          // avoid activation for special interrupts
783          if (int_id >= Gicv3::INTID_SECURE &&
784              int_id <= Gicv3::INTID_SPURIOUS) {
785              return;
786          }
787
788          Gicv3::GroupId group = Gicv3::G0S;
789
790          if (highestActiveGroup() != group) {
791              return;
792          }
793
794          dropPriority(group);
795
796          if (!isEOISplitMode()) {
797              deactivateIRQ(int_id, group);
798          }
799
800          break;
801      }
802
803      // Virtual End Of Interrupt Register 0
804      case MISCREG_ICV_EOIR0_EL1: {
805          int int_id = val & 0xffffff;
806
807          // avoid deactivation for special interrupts
808          if (int_id >= Gicv3::INTID_SECURE &&
809                  int_id <= Gicv3::INTID_SPURIOUS) {
810              return;
811          }
812
813          uint8_t drop_prio = virtualDropPriority();
814
815          if (drop_prio == 0xff) {
816              return;
817          }
818
819          int lr_idx = virtualFindActive(int_id);
820
821          if (lr_idx < 0) {
822              // No LR found matching
823              virtualIncrementEOICount();
824          } else {
825              ICH_LR_EL2 ich_lr_el2 =
826                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
827              Gicv3::GroupId lr_group =
828                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
829              uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8;
830
831              if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) {
832                  //if (!virtualIsEOISplitMode())
833                  {
834                      virtualDeactivateIRQ(lr_idx);
835                  }
836              }
837          }
838
839          virtualUpdate();
840          break;
841      }
842
843      // End Of Interrupt Register 1
844      case MISCREG_ICC_EOIR1:
845      case MISCREG_ICC_EOIR1_EL1: {
846          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
847              return setMiscReg(MISCREG_ICV_EOIR1_EL1, val);
848          }
849
850          int int_id = val & 0xffffff;
851
852          // avoid deactivation for special interrupts
853          if (int_id >= Gicv3::INTID_SECURE &&
854              int_id <= Gicv3::INTID_SPURIOUS) {
855              return;
856          }
857
858          Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS;
859
860          if (highestActiveGroup() == Gicv3::G0S) {
861              return;
862          }
863
864          if (distributor->DS == 0) {
865              if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) {
866                  return;
867              } else if (highestActiveGroup() == Gicv3::G1NS &&
868                         !(!inSecureState() or (currEL() == EL3))) {
869                  return;
870              }
871          }
872
873          dropPriority(group);
874
875          if (!isEOISplitMode()) {
876              deactivateIRQ(int_id, group);
877          }
878
879          break;
880      }
881
882      // Virtual End Of Interrupt Register 1
883      case MISCREG_ICV_EOIR1_EL1: {
884          int int_id = val & 0xffffff;
885
886          // avoid deactivation for special interrupts
887          if (int_id >= Gicv3::INTID_SECURE &&
888              int_id <= Gicv3::INTID_SPURIOUS) {
889              return;
890          }
891
892          uint8_t drop_prio = virtualDropPriority();
893
894          if (drop_prio == 0xff) {
895              return;
896          }
897
898          int lr_idx = virtualFindActive(int_id);
899
900          if (lr_idx < 0) {
901              // No matching LR found
902              virtualIncrementEOICount();
903          } else {
904              ICH_LR_EL2 ich_lr_el2 =
905                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
906              Gicv3::GroupId lr_group =
907                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
908              uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8;
909
910              if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) {
911                  if (!virtualIsEOISplitMode()) {
912                      virtualDeactivateIRQ(lr_idx);
913                  }
914              }
915          }
916
917          virtualUpdate();
918          break;
919      }
920
921      // Deactivate Interrupt Register
922      case MISCREG_ICC_DIR:
923      case MISCREG_ICC_DIR_EL1: {
924          if ((currEL() == EL1) && !inSecureState() &&
925              (hcr_imo || hcr_fmo)) {
926              return setMiscReg(MISCREG_ICV_DIR_EL1, val);
927          }
928
929          int int_id = val & 0xffffff;
930
931          // The following checks are as per spec pseudocode
932          // aarch64/support/ICC_DIR_EL1
933
934          // Check for spurious ID
935          if (int_id >= Gicv3::INTID_SECURE) {
936              return;
937          }
938
939          // EOI mode is not set, so don't deactivate
940          if (!isEOISplitMode()) {
941              return;
942          }
943
944          Gicv3::GroupId group =
945              int_id >= 32 ? distributor->getIntGroup(int_id) :
946              redistributor->getIntGroup(int_id);
947          bool irq_is_grp0 = group == Gicv3::G0S;
948          bool single_sec_state = distributor->DS;
949          bool irq_is_secure = !single_sec_state && (group != Gicv3::G1NS);
950          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
951          bool route_fiq_to_el3 = scr_el3.fiq;
952          bool route_irq_to_el3 = scr_el3.irq;
953          bool route_fiq_to_el2 = hcr_fmo;
954          bool route_irq_to_el2 = hcr_imo;
955
956          switch (currEL()) {
957            case EL3:
958              break;
959
960            case EL2:
961              if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) {
962                  break;
963              }
964
965              if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) {
966                  break;
967              }
968
969              return;
970
971            case EL1:
972              if (!isSecureBelowEL3()) {
973                  if (single_sec_state && irq_is_grp0 &&
974                      !route_fiq_to_el3 && !route_fiq_to_el2) {
975                      break;
976                  }
977
978                  if (!irq_is_secure && !irq_is_grp0 &&
979                      !route_irq_to_el3 && !route_irq_to_el2) {
980                      break;
981                  }
982              } else {
983                  if (irq_is_grp0 && !route_fiq_to_el3) {
984                      break;
985                  }
986
987                  if (!irq_is_grp0 &&
988                      (!irq_is_secure || !single_sec_state) &&
989                      !route_irq_to_el3) {
990                      break;
991                  }
992              }
993
994              return;
995
996            default:
997              break;
998          }
999
1000          deactivateIRQ(int_id, group);
1001          break;
1002      }
1003
1004      // Deactivate Virtual Interrupt Register
1005      case MISCREG_ICV_DIR_EL1: {
1006          int int_id = val & 0xffffff;
1007
1008          // avoid deactivation for special interrupts
1009          if (int_id >= Gicv3::INTID_SECURE &&
1010              int_id <= Gicv3::INTID_SPURIOUS) {
1011              return;
1012          }
1013
1014          if (!virtualIsEOISplitMode()) {
1015              return;
1016          }
1017
1018          int lr_idx = virtualFindActive(int_id);
1019
1020          if (lr_idx < 0) {
1021              // No matching LR found
1022              virtualIncrementEOICount();
1023          } else {
1024              virtualDeactivateIRQ(lr_idx);
1025          }
1026
1027          virtualUpdate();
1028          break;
1029      }
1030
1031      // Binary Point Register 0
1032      case MISCREG_ICC_BPR0:
1033      case MISCREG_ICC_BPR0_EL1:
1034      // Binary Point Register 1
1035      case MISCREG_ICC_BPR1:
1036      case MISCREG_ICC_BPR1_EL1: {
1037          if ((currEL() == EL1) && !inSecureState()) {
1038              if (misc_reg == MISCREG_ICC_BPR0_EL1 && hcr_fmo) {
1039                  return setMiscReg(MISCREG_ICV_BPR0_EL1, val);
1040              } else if (misc_reg == MISCREG_ICC_BPR1_EL1 && hcr_imo) {
1041                  return setMiscReg(MISCREG_ICV_BPR1_EL1, val);
1042              }
1043          }
1044
1045          Gicv3::GroupId group =
1046              misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S;
1047
1048          if (group == Gicv3::G1S && !inSecureState()) {
1049              group = Gicv3::G1NS;
1050          }
1051
1052          ICC_CTLR_EL1 icc_ctlr_el1_s =
1053              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1054
1055          if ((group == Gicv3::G1S) && !isEL3OrMon() &&
1056              icc_ctlr_el1_s.CBPR) {
1057              group = Gicv3::G0S;
1058          }
1059
1060          ICC_CTLR_EL1 icc_ctlr_el1_ns =
1061              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1062
1063          if ((group == Gicv3::G1NS) && (currEL() < EL3) &&
1064              icc_ctlr_el1_ns.CBPR) {
1065              // BPR0 + 1 saturated to 7, WI
1066              return;
1067          }
1068
1069          uint8_t min_val = (group == Gicv3::G1NS) ?
1070              GIC_MIN_BPR_NS : GIC_MIN_BPR;
1071          val &= 0x7;
1072
1073          if (val < min_val) {
1074              val = min_val;
1075          }
1076
1077          break;
1078      }
1079
1080      // Virtual Binary Point Register 0
1081      case MISCREG_ICV_BPR0_EL1:
1082      // Virtual Binary Point Register 1
1083      case MISCREG_ICV_BPR1_EL1: {
1084          Gicv3::GroupId group =
1085              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
1086          ICH_VMCR_EL2 ich_vmcr_el2 =
1087              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1088
1089          if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
1090              // BPR0 + 1 saturated to 7, WI
1091              return;
1092          }
1093
1094          uint8_t min_VPBR = 7 - VIRTUAL_PREEMPTION_BITS;
1095
1096          if (group != Gicv3::G0S) {
1097              min_VPBR++;
1098          }
1099
1100          if (val < min_VPBR) {
1101              val = min_VPBR;
1102          }
1103
1104          if (group == Gicv3::G0S) {
1105              ich_vmcr_el2.VBPR0 = val;
1106          } else {
1107              ich_vmcr_el2.VBPR1 = val;
1108          }
1109
1110          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1111          do_virtual_update = true;
1112          break;
1113      }
1114
1115      // Control Register EL1
1116      case MISCREG_ICC_CTLR:
1117      case MISCREG_ICC_CTLR_EL1: {
1118          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
1119              return setMiscReg(MISCREG_ICV_CTLR_EL1, val);
1120          }
1121
1122          /*
1123           * ExtRange is RO.
1124           * RSS is RO.
1125           * A3V is RO.
1126           * SEIS is RO.
1127           * IDbits is RO.
1128           * PRIbits is RO.
1129           */
1130          ICC_CTLR_EL1 requested_icc_ctlr_el1 = val;
1131          ICC_CTLR_EL1 icc_ctlr_el1 =
1132              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1);
1133
1134          ICC_CTLR_EL3 icc_ctlr_el3 =
1135              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1136
1137          // The following could be refactored but it is following
1138          // spec description section 9.2.6 point by point.
1139
1140          // PMHE
1141          if (haveEL(EL3)) {
1142              // PMHE is alias of ICC_CTLR_EL3.PMHE
1143
1144              if (distributor->DS == 0) {
1145                  // PMHE is RO
1146              } else if (distributor->DS == 1) {
1147                  // PMHE is RW
1148                  icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE;
1149                  icc_ctlr_el3.PMHE = icc_ctlr_el1.PMHE;
1150              }
1151          } else {
1152              // PMHE is RW (by implementation choice)
1153              icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE;
1154          }
1155
1156          // EOImode
1157          icc_ctlr_el1.EOImode = requested_icc_ctlr_el1.EOImode;
1158
1159          if (inSecureState()) {
1160              // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1S
1161              icc_ctlr_el3.EOImode_EL1S = icc_ctlr_el1.EOImode;
1162          } else {
1163              // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1NS
1164              icc_ctlr_el3.EOImode_EL1NS = icc_ctlr_el1.EOImode;
1165          }
1166
1167          // CBPR
1168          if (haveEL(EL3)) {
1169              // CBPR is alias of ICC_CTLR_EL3.CBPR_EL1{S,NS}
1170
1171              if (distributor->DS == 0) {
1172                  // CBPR is RO
1173              } else {
1174                  // CBPR is RW
1175                  icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR;
1176
1177                  if (inSecureState()) {
1178                      icc_ctlr_el3.CBPR_EL1S = icc_ctlr_el1.CBPR;
1179                  } else {
1180                      icc_ctlr_el3.CBPR_EL1NS = icc_ctlr_el1.CBPR;
1181                  }
1182              }
1183          } else {
1184              // CBPR is RW
1185              icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR;
1186          }
1187
1188          isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL3, icc_ctlr_el3);
1189
1190          val = icc_ctlr_el1;
1191          break;
1192      }
1193
1194      // Virtual Control Register
1195      case MISCREG_ICV_CTLR_EL1: {
1196         ICV_CTLR_EL1 requested_icv_ctlr_el1 = val;
1197         ICV_CTLR_EL1 icv_ctlr_el1 =
1198             isa->readMiscRegNoEffect(MISCREG_ICV_CTLR_EL1);
1199         icv_ctlr_el1.EOImode = requested_icv_ctlr_el1.EOImode;
1200         icv_ctlr_el1.CBPR = requested_icv_ctlr_el1.CBPR;
1201         val = icv_ctlr_el1;
1202
1203         // Aliases
1204         // ICV_CTLR_EL1.CBPR aliases ICH_VMCR_EL2.VCBPR.
1205         // ICV_CTLR_EL1.EOImode aliases ICH_VMCR_EL2.VEOIM.
1206         ICH_VMCR_EL2 ich_vmcr_el2 =
1207             isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1208         ich_vmcr_el2.VCBPR = icv_ctlr_el1.CBPR;
1209         ich_vmcr_el2.VEOIM = icv_ctlr_el1.EOImode;
1210         isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1211         break;
1212      }
1213
1214      // Control Register EL3
1215      case MISCREG_ICC_MCTLR:
1216      case MISCREG_ICC_CTLR_EL3: {
1217          /*
1218           * ExtRange is RO.
1219           * RSS is RO.
1220           * nDS is RO.
1221           * A3V is RO.
1222           * SEIS is RO.
1223           * IDbits is RO.
1224           * PRIbits is RO.
1225           * PMHE is RAO/WI, priority-based routing is always used.
1226           */
1227          ICC_CTLR_EL3 requested_icc_ctlr_el3 = val;
1228
1229          // Aliases
1230          if (haveEL(EL3))
1231          {
1232              ICC_CTLR_EL1 icc_ctlr_el1_s =
1233                  isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1234              ICC_CTLR_EL1 icc_ctlr_el1_ns =
1235                  isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1236
1237              // ICC_CTLR_EL1(NS).EOImode is an alias of
1238              // ICC_CTLR_EL3.EOImode_EL1NS
1239              icc_ctlr_el1_ns.EOImode = requested_icc_ctlr_el3.EOImode_EL1NS;
1240              // ICC_CTLR_EL1(S).EOImode is an alias of
1241              // ICC_CTLR_EL3.EOImode_EL1S
1242              icc_ctlr_el1_s.EOImode = requested_icc_ctlr_el3.EOImode_EL1S;
1243              // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS
1244              icc_ctlr_el1_ns.CBPR = requested_icc_ctlr_el3.CBPR_EL1NS;
1245              // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S
1246              icc_ctlr_el1_s.CBPR = requested_icc_ctlr_el3.CBPR_EL1S;
1247
1248              isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s);
1249              isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS,
1250                                      icc_ctlr_el1_ns);
1251          }
1252
1253          ICC_CTLR_EL3 icc_ctlr_el3 =
1254              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1255
1256          icc_ctlr_el3.RM = requested_icc_ctlr_el3.RM;
1257          icc_ctlr_el3.EOImode_EL1NS = requested_icc_ctlr_el3.EOImode_EL1NS;
1258          icc_ctlr_el3.EOImode_EL1S = requested_icc_ctlr_el3.EOImode_EL1S;
1259          icc_ctlr_el3.EOImode_EL3 = requested_icc_ctlr_el3.EOImode_EL3;
1260          icc_ctlr_el3.CBPR_EL1NS = requested_icc_ctlr_el3.CBPR_EL1NS;
1261          icc_ctlr_el3.CBPR_EL1S = requested_icc_ctlr_el3.CBPR_EL1S;
1262
1263          val = icc_ctlr_el3;
1264          break;
1265      }
1266
1267      // Priority Mask Register
1268      case MISCREG_ICC_PMR:
1269      case MISCREG_ICC_PMR_EL1: {
1270          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
1271              return isa->setMiscRegNoEffect(MISCREG_ICV_PMR_EL1, val);
1272          }
1273
1274          val &= 0xff;
1275          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
1276
1277          if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) {
1278              // Spec section 4.8.1
1279              // For Non-secure access to ICC_PMR_EL1 SCR_EL3.FIQ == 1:
1280              RegVal old_icc_pmr_el1 =
1281                  isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1);
1282
1283              if (!(old_icc_pmr_el1 & 0x80)) {
1284                  // If the current priority mask value is in the range of
1285                  // 0x00-0x7F then WI
1286                  return;
1287              }
1288
1289              // If the current priority mask value is in the range of
1290              // 0x80-0xFF then a write access to ICC_PMR_EL1 succeeds,
1291              // based on the Non-secure read of the priority mask value
1292              // written to the register.
1293
1294              val = (val >> 1) | 0x80;
1295          }
1296
1297          val &= ~0U << (8 - PRIORITY_BITS);
1298          break;
1299      }
1300
1301      // Interrupt Group 0 Enable Register EL1
1302      case MISCREG_ICC_IGRPEN0:
1303      case MISCREG_ICC_IGRPEN0_EL1: {
1304          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1305              return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val);
1306          }
1307
1308          break;
1309      }
1310
1311      // Virtual Interrupt Group 0 Enable register
1312      case MISCREG_ICV_IGRPEN0_EL1: {
1313          bool enable = val & 0x1;
1314          ICH_VMCR_EL2 ich_vmcr_el2 =
1315              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1316          ich_vmcr_el2.VENG0 = enable;
1317          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1318          virtualUpdate();
1319          return;
1320      }
1321
1322      // Interrupt Group 1 Enable register EL1
1323      case MISCREG_ICC_IGRPEN1:
1324      case MISCREG_ICC_IGRPEN1_EL1: {
1325          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1326              return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val);
1327          }
1328
1329          if (haveEL(EL3)) {
1330              ICC_IGRPEN1_EL1 icc_igrpen1_el1 = val;
1331              ICC_IGRPEN1_EL3 icc_igrpen1_el3 =
1332                  isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3);
1333
1334              if (inSecureState()) {
1335                  // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1S
1336                  icc_igrpen1_el3.EnableGrp1S = icc_igrpen1_el1.Enable;
1337              } else {
1338                  // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1NS
1339                  icc_igrpen1_el3.EnableGrp1NS = icc_igrpen1_el1.Enable;
1340              }
1341
1342              isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3,
1343                                      icc_igrpen1_el3);
1344          }
1345
1346          break;
1347      }
1348
1349      // Virtual Interrupt Group 1 Enable register
1350      case MISCREG_ICV_IGRPEN1_EL1: {
1351          bool enable = val & 0x1;
1352          ICH_VMCR_EL2 ich_vmcr_el2 =
1353              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1354          ich_vmcr_el2.VENG1 = enable;
1355          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1356          virtualUpdate();
1357          return;
1358      }
1359
1360      // Interrupt Group 1 Enable register
1361      case MISCREG_ICC_MGRPEN1:
1362      case MISCREG_ICC_IGRPEN1_EL3: {
1363          ICC_IGRPEN1_EL3 icc_igrpen1_el3 = val;
1364          ICC_IGRPEN1_EL1 icc_igrpen1_el1 =
1365              isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1);
1366
1367          if (inSecureState()) {
1368              // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1S
1369              icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1S;
1370          } else {
1371              // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1NS
1372              icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1NS;
1373          }
1374
1375          isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1, icc_igrpen1_el1);
1376          break;
1377      }
1378
1379      // Software Generated Interrupt Group 0 Register
1380      case MISCREG_ICC_SGI0R:
1381      case MISCREG_ICC_SGI0R_EL1:
1382
1383      // Software Generated Interrupt Group 1 Register
1384      case MISCREG_ICC_SGI1R:
1385      case MISCREG_ICC_SGI1R_EL1:
1386
1387      // Alias Software Generated Interrupt Group 1 Register
1388      case MISCREG_ICC_ASGI1R:
1389      case MISCREG_ICC_ASGI1R_EL1: {
1390          bool ns = !inSecureState();
1391          Gicv3::GroupId group;
1392
1393          if (misc_reg == MISCREG_ICC_SGI1R_EL1) {
1394              group = ns ? Gicv3::G1NS : Gicv3::G1S;
1395          } else if (misc_reg == MISCREG_ICC_ASGI1R_EL1) {
1396              group = ns ? Gicv3::G1S : Gicv3::G1NS;
1397          } else {
1398              group = Gicv3::G0S;
1399          }
1400
1401          if (distributor->DS && group == Gicv3::G1S) {
1402              group = Gicv3::G0S;
1403          }
1404
1405          uint8_t aff3 = bits(val, 55, 48);
1406          uint8_t aff2 = bits(val, 39, 32);
1407          uint8_t aff1 = bits(val, 23, 16);;
1408          uint16_t target_list = bits(val, 15, 0);
1409          uint32_t int_id = bits(val, 27, 24);
1410          bool irm = bits(val, 40, 40);
1411          uint8_t rs = bits(val, 47, 44);
1412
1413          for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1414              Gicv3Redistributor * redistributor_i =
1415                  gic->getRedistributor(i);
1416              uint32_t affinity_i = redistributor_i->getAffinity();
1417
1418              if (irm) {
1419                  // Interrupts routed to all PEs in the system,
1420                  // excluding "self"
1421                  if (affinity_i == redistributor->getAffinity()) {
1422                      continue;
1423                  }
1424              } else {
1425                  // Interrupts routed to the PEs specified by
1426                  // Aff3.Aff2.Aff1.<target list>
1427                  if ((affinity_i >> 8) !=
1428                      ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) {
1429                      continue;
1430                  }
1431
1432                  uint8_t aff0_i = bits(affinity_i, 7, 0);
1433
1434                  if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 &&
1435                      ((0x1 << (aff0_i - rs * 16)) & target_list))) {
1436                      continue;
1437                  }
1438              }
1439
1440              redistributor_i->sendSGI(int_id, group, ns);
1441          }
1442
1443          break;
1444      }
1445
1446      // System Register Enable Register EL1
1447      case MISCREG_ICC_SRE:
1448      case MISCREG_ICC_SRE_EL1:
1449      // System Register Enable Register EL2
1450      case MISCREG_ICC_HSRE:
1451      case MISCREG_ICC_SRE_EL2:
1452      // System Register Enable Register EL3
1453      case MISCREG_ICC_MSRE:
1454      case MISCREG_ICC_SRE_EL3:
1455        // All bits are RAO/WI
1456        return;
1457
1458      // Hyp Control Register
1459      case MISCREG_ICH_HCR:
1460      case MISCREG_ICH_HCR_EL2: {
1461        ICH_HCR_EL2 requested_ich_hcr_el2 = val;
1462        ICH_HCR_EL2 ich_hcr_el2 =
1463            isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1464
1465        if (requested_ich_hcr_el2.EOIcount >= ich_hcr_el2.EOIcount)
1466        {
1467            // EOIcount - Permitted behaviors are:
1468            // - Increment EOIcount.
1469            // - Leave EOIcount unchanged.
1470            ich_hcr_el2.EOIcount = requested_ich_hcr_el2.EOIcount;
1471        }
1472
1473        ich_hcr_el2.TDIR = requested_ich_hcr_el2.TDIR;
1474        ich_hcr_el2.TSEI = requested_ich_hcr_el2.TSEI;
1475        ich_hcr_el2.TALL1 = requested_ich_hcr_el2.TALL1;;
1476        ich_hcr_el2.TALL0 = requested_ich_hcr_el2.TALL0;;
1477        ich_hcr_el2.TC = requested_ich_hcr_el2.TC;
1478        ich_hcr_el2.VGrp1DIE = requested_ich_hcr_el2.VGrp1DIE;
1479        ich_hcr_el2.VGrp1EIE = requested_ich_hcr_el2.VGrp1EIE;
1480        ich_hcr_el2.VGrp0DIE = requested_ich_hcr_el2.VGrp0DIE;
1481        ich_hcr_el2.VGrp0EIE = requested_ich_hcr_el2.VGrp0EIE;
1482        ich_hcr_el2.NPIE = requested_ich_hcr_el2.NPIE;
1483        ich_hcr_el2.LRENPIE = requested_ich_hcr_el2.LRENPIE;
1484        ich_hcr_el2.UIE = requested_ich_hcr_el2.UIE;
1485        ich_hcr_el2.En = requested_ich_hcr_el2.En;
1486        val = ich_hcr_el2;
1487        do_virtual_update = true;
1488        break;
1489      }
1490
1491      // List Registers
1492      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: {
1493        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
1494        ICH_LRC requested_ich_lrc = val;
1495        ICH_LRC ich_lrc = isa->readMiscRegNoEffect(misc_reg);
1496
1497        ich_lrc.State = requested_ich_lrc.State;
1498        ich_lrc.HW = requested_ich_lrc.HW;
1499        ich_lrc.Group = requested_ich_lrc.Group;
1500
1501        // Priority, bits [23:16]
1502        // At least five bits must be implemented.
1503        // Unimplemented bits are RES0 and start from bit[16] up to bit[18].
1504        // We implement 5 bits.
1505        ich_lrc.Priority = (requested_ich_lrc.Priority & 0xf8) |
1506                           (ich_lrc.Priority & 0x07);
1507
1508        // pINTID, bits [12:0]
1509        // When ICH_LR<n>.HW is 0 this field has the following meaning:
1510        // - Bits[12:10] : RES0.
1511        // - Bit[9] : EOI.
1512        // - Bits[8:0] : RES0.
1513        // When ICH_LR<n>.HW is 1:
1514        // - This field is only required to implement enough bits to hold a
1515        // valid value for the implemented INTID size. Any unused higher
1516        // order bits are RES0.
1517        if (requested_ich_lrc.HW == 0) {
1518            ich_lrc.EOI = requested_ich_lrc.EOI;
1519        } else {
1520            ich_lrc.pINTID = requested_ich_lrc.pINTID;
1521        }
1522
1523        val = ich_lrc;
1524        do_virtual_update = true;
1525        break;
1526      }
1527
1528      // List Registers
1529      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: {
1530          // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
1531          RegVal old_val = isa->readMiscRegNoEffect(misc_reg);
1532          val = (old_val & 0xffffffff00000000) | (val & 0xffffffff);
1533          do_virtual_update = true;
1534          break;
1535      }
1536
1537      // List Registers
1538      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64
1539          ICH_LR_EL2 requested_ich_lr_el2 = val;
1540          ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(misc_reg);
1541
1542          ich_lr_el2.State = requested_ich_lr_el2.State;
1543          ich_lr_el2.HW = requested_ich_lr_el2.HW;
1544          ich_lr_el2.Group = requested_ich_lr_el2.Group;
1545
1546          // Priority, bits [55:48]
1547          // At least five bits must be implemented.
1548          // Unimplemented bits are RES0 and start from bit[48] up to bit[50].
1549          // We implement 5 bits.
1550          ich_lr_el2.Priority = (requested_ich_lr_el2.Priority & 0xf8) |
1551                                (ich_lr_el2.Priority & 0x07);
1552
1553          // pINTID, bits [44:32]
1554          // When ICH_LR<n>_EL2.HW is 0 this field has the following meaning:
1555          // - Bits[44:42] : RES0.
1556          // - Bit[41] : EOI.
1557          // - Bits[40:32] : RES0.
1558          // When ICH_LR<n>_EL2.HW is 1:
1559          // - This field is only required to implement enough bits to hold a
1560          // valid value for the implemented INTID size. Any unused higher
1561          // order bits are RES0.
1562          if (requested_ich_lr_el2.HW == 0) {
1563              ich_lr_el2.EOI = requested_ich_lr_el2.EOI;
1564          } else {
1565              ich_lr_el2.pINTID = requested_ich_lr_el2.pINTID;
1566          }
1567
1568          // vINTID, bits [31:0]
1569          // It is IMPLEMENTATION DEFINED how many bits are implemented,
1570          // though at least 16 bits must be implemented.
1571          // Unimplemented bits are RES0.
1572          ich_lr_el2.vINTID = requested_ich_lr_el2.vINTID;
1573
1574          val = ich_lr_el2;
1575          do_virtual_update = true;
1576          break;
1577      }
1578
1579      // Virtual Machine Control Register
1580      case MISCREG_ICH_VMCR:
1581      case MISCREG_ICH_VMCR_EL2: {
1582          ICH_VMCR_EL2 requested_ich_vmcr_el2 = val;
1583          ICH_VMCR_EL2 ich_vmcr_el2 =
1584              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1585          ich_vmcr_el2.VPMR = requested_ich_vmcr_el2.VPMR;
1586          uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS;
1587
1588          if (requested_ich_vmcr_el2.VBPR0 < min_vpr0) {
1589              ich_vmcr_el2.VBPR0 = min_vpr0;
1590          } else {
1591              ich_vmcr_el2.VBPR0 = requested_ich_vmcr_el2.VBPR0;
1592          }
1593
1594          uint8_t min_vpr1 = min_vpr0 + 1;
1595
1596          if (requested_ich_vmcr_el2.VBPR1 < min_vpr1) {
1597              ich_vmcr_el2.VBPR1 = min_vpr1;
1598          } else {
1599              ich_vmcr_el2.VBPR1 = requested_ich_vmcr_el2.VBPR1;
1600          }
1601
1602          ich_vmcr_el2.VEOIM = requested_ich_vmcr_el2.VEOIM;
1603          ich_vmcr_el2.VCBPR = requested_ich_vmcr_el2.VCBPR;
1604          ich_vmcr_el2.VENG1 = requested_ich_vmcr_el2.VENG1;
1605          ich_vmcr_el2.VENG0 = requested_ich_vmcr_el2.VENG0;
1606          val = ich_vmcr_el2;
1607          break;
1608      }
1609
1610      // Hyp Active Priorities Group 0 Registers
1611      case MISCREG_ICH_AP0R0 ... MISCREG_ICH_AP0R3:
1612      case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_AP0R3_EL2:
1613      // Hyp Active Priorities Group 1 Registers
1614      case MISCREG_ICH_AP1R0 ... MISCREG_ICH_AP1R3:
1615      case MISCREG_ICH_AP1R0_EL2 ... MISCREG_ICH_AP1R3_EL2:
1616        break;
1617
1618      default:
1619        panic("Gicv3CPUInterface::setMiscReg(): unknown register %d (%s)",
1620              misc_reg, miscRegName[misc_reg]);
1621    }
1622
1623    isa->setMiscRegNoEffect(misc_reg, val);
1624
1625    if (do_virtual_update) {
1626        virtualUpdate();
1627    }
1628}
1629
1630int
1631Gicv3CPUInterface::virtualFindActive(uint32_t int_id) const
1632{
1633    for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
1634        ICH_LR_EL2 ich_lr_el2 =
1635            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1636
1637        if (((ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE) ||
1638             (ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE_PENDING)) &&
1639            (ich_lr_el2.vINTID == int_id)) {
1640            return lr_idx;
1641        }
1642    }
1643
1644    return -1;
1645}
1646
1647uint32_t
1648Gicv3CPUInterface::getHPPIR0() const
1649{
1650    if (hppi.prio == 0xff) {
1651        return Gicv3::INTID_SPURIOUS;
1652    }
1653
1654    bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS;
1655
1656    if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) {
1657        // interrupt for the other state pending
1658        return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE;
1659    }
1660
1661    if ((hppi.group != Gicv3::G0S)) { // && !isEL3OrMon())
1662        return Gicv3::INTID_SPURIOUS;
1663    }
1664
1665    if (irq_is_secure && !inSecureState()) {
1666        // Secure interrupts not visible in Non-secure
1667        return Gicv3::INTID_SPURIOUS;
1668    }
1669
1670    return hppi.intid;
1671}
1672
1673uint32_t
1674Gicv3CPUInterface::getHPPIR1() const
1675{
1676    if (hppi.prio == 0xff) {
1677        return Gicv3::INTID_SPURIOUS;
1678    }
1679
1680    ICC_CTLR_EL3 icc_ctlr_el3 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1681    if ((currEL() == EL3) && icc_ctlr_el3.RM) {
1682        if (hppi.group == Gicv3::G0S) {
1683            return Gicv3::INTID_SECURE;
1684        } else if (hppi.group == Gicv3::G1NS) {
1685            return Gicv3::INTID_NONSECURE;
1686        }
1687    }
1688
1689    if (hppi.group == Gicv3::G0S) {
1690        return Gicv3::INTID_SPURIOUS;
1691    }
1692
1693    bool irq_is_secure = (distributor->DS == 0) && (hppi.group != Gicv3::G1NS);
1694
1695    if (irq_is_secure) {
1696        if (!inSecureState()) {
1697            // Secure interrupts not visible in Non-secure
1698            return Gicv3::INTID_SPURIOUS;
1699        }
1700    } else if (!isEL3OrMon() && inSecureState()) {
1701        // Group 1 non-secure interrupts not visible in Secure EL1
1702        return Gicv3::INTID_SPURIOUS;
1703    }
1704
1705    return hppi.intid;
1706}
1707
1708void
1709Gicv3CPUInterface::dropPriority(Gicv3::GroupId group)
1710{
1711    int apr_misc_reg;
1712    RegVal apr;
1713    apr_misc_reg = group == Gicv3::G0S ?
1714                   MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1715    apr = isa->readMiscRegNoEffect(apr_misc_reg);
1716
1717    if (apr) {
1718        apr &= apr - 1;
1719        isa->setMiscRegNoEffect(apr_misc_reg, apr);
1720    }
1721
1722    update();
1723}
1724
1725uint8_t
1726Gicv3CPUInterface::virtualDropPriority()
1727{
1728    int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5);
1729
1730    for (int i = 0; i < apr_max; i++) {
1731        RegVal vapr0 = isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i);
1732        RegVal vapr1 = isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
1733
1734        if (!vapr0 && !vapr1) {
1735            continue;
1736        }
1737
1738        int vapr0_count = ctz32(vapr0);
1739        int vapr1_count = ctz32(vapr1);
1740
1741        if (vapr0_count <= vapr1_count) {
1742            vapr0 &= vapr0 - 1;
1743            isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0);
1744            return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1);
1745        } else {
1746            vapr1 &= vapr1 - 1;
1747            isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1);
1748            return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1);
1749        }
1750    }
1751
1752    return 0xff;
1753}
1754
1755void
1756Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
1757{
1758    // Update active priority registers.
1759    uint32_t prio = hppi.prio & 0xf8;
1760    int apr_bit = prio >> (8 - PRIORITY_BITS);
1761    int reg_bit = apr_bit % 32;
1762    int apr_idx = group == Gicv3::G0S ?
1763                 MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1764    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1765    apr |= (1 << reg_bit);
1766    isa->setMiscRegNoEffect(apr_idx, apr);
1767
1768    // Move interrupt state from pending to active.
1769    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1770        // SGI or PPI, redistributor
1771        redistributor->activateIRQ(int_id);
1772        redistributor->updateAndInformCPUInterface();
1773    } else if (int_id < Gicv3::INTID_SECURE) {
1774        // SPI, distributor
1775        distributor->activateIRQ(int_id);
1776        distributor->updateAndInformCPUInterfaces();
1777    } else if (int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
1778        // LPI, Redistributor
1779        redistributor->setClrLPI(int_id, false);
1780    }
1781}
1782
1783void
1784Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx)
1785{
1786    // Update active priority registers.
1787    ICH_LR_EL2 ich_lr_el = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1788            lr_idx);
1789    Gicv3::GroupId group = ich_lr_el.Group ? Gicv3::G1NS : Gicv3::G0S;
1790    uint8_t prio = ich_lr_el.Priority & 0xf8;
1791    int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS);
1792    int reg_no = apr_bit / 32;
1793    int reg_bit = apr_bit % 32;
1794    int apr_idx = group == Gicv3::G0S ?
1795        MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no;
1796    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1797    apr |= (1 << reg_bit);
1798    isa->setMiscRegNoEffect(apr_idx, apr);
1799    // Move interrupt state from pending to active.
1800    ich_lr_el.State = ICH_LR_EL2_STATE_ACTIVE;
1801    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el);
1802}
1803
1804void
1805Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group)
1806{
1807    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1808        // SGI or PPI, redistributor
1809        redistributor->deactivateIRQ(int_id);
1810        redistributor->updateAndInformCPUInterface();
1811    } else if (int_id < Gicv3::INTID_SECURE) {
1812        // SPI, distributor
1813        distributor->deactivateIRQ(int_id);
1814        distributor->updateAndInformCPUInterfaces();
1815    } else {
1816        // LPI, redistributor, shouldn't deactivate
1817        redistributor->updateAndInformCPUInterface();
1818    }
1819}
1820
1821void
1822Gicv3CPUInterface::virtualDeactivateIRQ(int lr_idx)
1823{
1824    ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1825            lr_idx);
1826
1827    if (ich_lr_el2.HW) {
1828        // Deactivate the associated physical interrupt
1829        if (ich_lr_el2.pINTID < Gicv3::INTID_SECURE) {
1830            Gicv3::GroupId group = ich_lr_el2.pINTID >= 32 ?
1831                distributor->getIntGroup(ich_lr_el2.pINTID) :
1832                redistributor->getIntGroup(ich_lr_el2.pINTID);
1833            deactivateIRQ(ich_lr_el2.pINTID, group);
1834        }
1835    }
1836
1837    //  Remove the active bit
1838    ich_lr_el2.State = ich_lr_el2.State & ~ICH_LR_EL2_STATE_ACTIVE;
1839    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el2);
1840}
1841
1842/*
1843 * Returns the priority group field for the current BPR value for the group.
1844 * GroupBits() Pseudocode from spec.
1845 */
1846uint32_t
1847Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) const
1848{
1849    ICC_CTLR_EL1 icc_ctlr_el1_s =
1850        isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1851    ICC_CTLR_EL1 icc_ctlr_el1_ns =
1852        isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1853
1854    if ((group == Gicv3::G1S && icc_ctlr_el1_s.CBPR) ||
1855        (group == Gicv3::G1NS && icc_ctlr_el1_ns.CBPR)) {
1856        group = Gicv3::G0S;
1857    }
1858
1859    int bpr;
1860
1861    if (group == Gicv3::G0S) {
1862        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) & 0x7;
1863    } else {
1864        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1) & 0x7;
1865    }
1866
1867    if (group == Gicv3::G1NS) {
1868        assert(bpr > 0);
1869        bpr--;
1870    }
1871
1872    return ~0U << (bpr + 1);
1873}
1874
1875uint32_t
1876Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) const
1877{
1878    ICH_VMCR_EL2 ich_vmcr_el2 =
1879        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1880
1881    if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
1882        group = Gicv3::G0S;
1883    }
1884
1885    int bpr;
1886
1887    if (group == Gicv3::G0S) {
1888        bpr = ich_vmcr_el2.VBPR0;
1889    } else {
1890        bpr = ich_vmcr_el2.VBPR1;
1891    }
1892
1893    if (group == Gicv3::G1NS) {
1894        assert(bpr > 0);
1895        bpr--;
1896    }
1897
1898    return ~0U << (bpr + 1);
1899}
1900
1901bool
1902Gicv3CPUInterface::isEOISplitMode() const
1903{
1904    if (isEL3OrMon()) {
1905        ICC_CTLR_EL3 icc_ctlr_el3 =
1906            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1907        return icc_ctlr_el3.EOImode_EL3;
1908    } else {
1909        ICC_CTLR_EL1 icc_ctlr_el1 =
1910            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1);
1911        return icc_ctlr_el1.EOImode;
1912    }
1913}
1914
1915bool
1916Gicv3CPUInterface::virtualIsEOISplitMode() const
1917{
1918    ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1919    return ich_vmcr_el2.VEOIM;
1920}
1921
1922int
1923Gicv3CPUInterface::highestActiveGroup() const
1924{
1925    int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1));
1926    int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S));
1927    int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS));
1928
1929    if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) {
1930        return Gicv3::G1NS;
1931    }
1932
1933    if (gq_ctz < g0_ctz) {
1934        return Gicv3::G1S;
1935    }
1936
1937    if (g0_ctz < 32) {
1938        return Gicv3::G0S;
1939    }
1940
1941    return -1;
1942}
1943
1944void
1945Gicv3CPUInterface::update()
1946{
1947    bool signal_IRQ = false;
1948    bool signal_FIQ = false;
1949
1950    if (hppi.group == Gicv3::G1S && !haveEL(EL3)) {
1951        /*
1952         * Secure enabled GIC sending a G1S IRQ to a secure disabled
1953         * CPU -> send G0 IRQ
1954         */
1955        hppi.group = Gicv3::G0S;
1956    }
1957
1958    if (hppiCanPreempt()) {
1959        ArmISA::InterruptTypes int_type = intSignalType(hppi.group);
1960        DPRINTF(GIC, "Gicv3CPUInterface::update(): "
1961                "posting int as %d!\n", int_type);
1962        int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true;
1963    }
1964
1965    if (signal_IRQ) {
1966        gic->postInt(cpuId, ArmISA::INT_IRQ);
1967    } else {
1968        gic->deassertInt(cpuId, ArmISA::INT_IRQ);
1969    }
1970
1971    if (signal_FIQ) {
1972        gic->postInt(cpuId, ArmISA::INT_FIQ);
1973    } else {
1974        gic->deassertInt(cpuId, ArmISA::INT_FIQ);
1975    }
1976}
1977
1978void
1979Gicv3CPUInterface::virtualUpdate()
1980{
1981    bool signal_IRQ = false;
1982    bool signal_FIQ = false;
1983    int lr_idx = getHPPVILR();
1984
1985    if (lr_idx >= 0) {
1986        ICH_LR_EL2 ich_lr_el2 =
1987            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1988
1989        if (hppviCanPreempt(lr_idx)) {
1990            if (ich_lr_el2.Group) {
1991                signal_IRQ = true;
1992            } else {
1993                signal_FIQ = true;
1994            }
1995        }
1996    }
1997
1998    ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1999
2000    if (ich_hcr_el2.En) {
2001        if (maintenanceInterruptStatus()) {
2002            maintenanceInterrupt->raise();
2003        }
2004    }
2005
2006    if (signal_IRQ) {
2007        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
2008                "posting int as %d!\n", ArmISA::INT_VIRT_IRQ);
2009        gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ);
2010    } else {
2011        gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ);
2012    }
2013
2014    if (signal_FIQ) {
2015        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
2016                "posting int as %d!\n", ArmISA::INT_VIRT_FIQ);
2017        gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ);
2018    } else {
2019        gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ);
2020    }
2021}
2022
2023// Returns the index of the LR with the HPPI
2024int
2025Gicv3CPUInterface::getHPPVILR() const
2026{
2027    int idx = -1;
2028    ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2029
2030    if (!ich_vmcr_el2.VENG0 && !ich_vmcr_el2.VENG1) {
2031        // VG0 and VG1 disabled...
2032        return idx;
2033    }
2034
2035    uint8_t highest_prio = 0xff;
2036
2037    for (int i = 0; i < 16; i++) {
2038        ICH_LR_EL2 ich_lr_el2 =
2039            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i);
2040
2041        if (ich_lr_el2.State != Gicv3::INT_PENDING) {
2042            continue;
2043        }
2044
2045        if (ich_lr_el2.Group) {
2046            // VG1
2047            if (!ich_vmcr_el2.VENG1) {
2048                continue;
2049            }
2050        } else {
2051            // VG0
2052            if (!ich_vmcr_el2.VENG0) {
2053                continue;
2054            }
2055        }
2056
2057        uint8_t prio = ich_lr_el2.Priority;
2058
2059        if (prio < highest_prio) {
2060            highest_prio = prio;
2061            idx = i;
2062        }
2063    }
2064
2065    return idx;
2066}
2067
2068bool
2069Gicv3CPUInterface::hppviCanPreempt(int lr_idx) const
2070{
2071    ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2072    if (!ich_hcr_el2.En) {
2073        // virtual interface is disabled
2074        return false;
2075    }
2076
2077    ICH_LR_EL2 ich_lr_el2 =
2078        isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2079    uint8_t prio = ich_lr_el2.Priority;
2080    uint8_t vpmr =
2081        bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24);
2082
2083    if (prio >= vpmr) {
2084        // prioriry masked
2085        return false;
2086    }
2087
2088    uint8_t rprio = virtualHighestActivePriority();
2089
2090    if (rprio == 0xff) {
2091        return true;
2092    }
2093
2094    Gicv3::GroupId group = ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2095    uint32_t prio_mask = virtualGroupPriorityMask(group);
2096
2097    if ((prio & prio_mask) < (rprio & prio_mask)) {
2098        return true;
2099    }
2100
2101    return false;
2102}
2103
2104uint8_t
2105Gicv3CPUInterface::virtualHighestActivePriority() const
2106{
2107    uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5);
2108
2109    for (int i = 0; i < num_aprs; i++) {
2110        RegVal vapr =
2111            isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) |
2112            isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
2113
2114        if (!vapr) {
2115            continue;
2116        }
2117
2118        return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1);
2119    }
2120
2121    // no active interrups, return idle priority
2122    return 0xff;
2123}
2124
2125void
2126Gicv3CPUInterface::virtualIncrementEOICount()
2127{
2128    // Increment the EOICOUNT field in ICH_HCR_EL2
2129    RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2130    uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27);
2131    EOI_cout++;
2132    ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout);
2133    isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2);
2134}
2135
2136// spec section 4.6.2
2137ArmISA::InterruptTypes
2138Gicv3CPUInterface::intSignalType(Gicv3::GroupId group) const
2139{
2140    bool is_fiq = false;
2141
2142    switch (group) {
2143      case Gicv3::G0S:
2144        is_fiq = true;
2145        break;
2146
2147      case Gicv3::G1S:
2148        is_fiq = (distributor->DS == 0) &&
2149            (!inSecureState() || ((currEL() == EL3) && isAA64()));
2150        break;
2151
2152      case Gicv3::G1NS:
2153        is_fiq = (distributor->DS == 0) && inSecureState();
2154        break;
2155
2156      default:
2157        panic("Gicv3CPUInterface::intSignalType(): invalid group!");
2158    }
2159
2160    if (is_fiq) {
2161        return ArmISA::INT_FIQ;
2162    } else {
2163        return ArmISA::INT_IRQ;
2164    }
2165}
2166
2167bool
2168Gicv3CPUInterface::hppiCanPreempt() const
2169{
2170    if (hppi.prio == 0xff) {
2171        // there is no pending interrupt
2172        return false;
2173    }
2174
2175    if (!groupEnabled(hppi.group)) {
2176        // group disabled at CPU interface
2177        return false;
2178    }
2179
2180    if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) {
2181        // priority masked
2182        return false;
2183    }
2184
2185    uint8_t rprio = highestActivePriority();
2186
2187    if (rprio == 0xff) {
2188        return true;
2189    }
2190
2191    uint32_t prio_mask = groupPriorityMask(hppi.group);
2192
2193    if ((hppi.prio & prio_mask) < (rprio & prio_mask)) {
2194        return true;
2195    }
2196
2197    return false;
2198}
2199
2200uint8_t
2201Gicv3CPUInterface::highestActivePriority() const
2202{
2203    uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) |
2204                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) |
2205                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S);
2206
2207    if (apr) {
2208        return ctz32(apr) << (GIC_MIN_BPR + 1);
2209    }
2210
2211    // no active interrups, return idle priority
2212    return 0xff;
2213}
2214
2215bool
2216Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) const
2217{
2218    switch (group) {
2219      case Gicv3::G0S: {
2220        ICC_IGRPEN0_EL1 icc_igrpen0_el1 =
2221            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1);
2222        return icc_igrpen0_el1.Enable;
2223      }
2224
2225      case Gicv3::G1S: {
2226        ICC_IGRPEN1_EL1 icc_igrpen1_el1_s =
2227            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S);
2228        return icc_igrpen1_el1_s.Enable;
2229      }
2230
2231      case Gicv3::G1NS: {
2232        ICC_IGRPEN1_EL1 icc_igrpen1_el1_ns =
2233            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS);
2234        return icc_igrpen1_el1_ns.Enable;
2235      }
2236
2237      default:
2238        panic("Gicv3CPUInterface::groupEnable(): invalid group!\n");
2239    }
2240}
2241
2242bool
2243Gicv3CPUInterface::inSecureState() const
2244{
2245    if (!gic->getSystem()->haveSecurity()) {
2246        return false;
2247    }
2248
2249    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2250    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR);
2251    return ArmISA::inSecureState(scr, cpsr);
2252}
2253
2254int
2255Gicv3CPUInterface::currEL() const
2256{
2257    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2258    bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2259
2260    if (is_64) {
2261        return (ExceptionLevel)(uint8_t) cpsr.el;
2262    } else {
2263        switch (cpsr.mode) {
2264          case MODE_USER:
2265            return 0;
2266
2267          case MODE_HYP:
2268            return 2;
2269
2270          case MODE_MON:
2271            return 3;
2272
2273          default:
2274            return 1;
2275        }
2276    }
2277}
2278
2279bool
2280Gicv3CPUInterface::haveEL(ExceptionLevel el) const
2281{
2282    switch (el) {
2283      case EL0:
2284      case EL1:
2285        return true;
2286
2287      case EL2:
2288        return gic->getSystem()->haveVirtualization();
2289
2290      case EL3:
2291        return gic->getSystem()->haveSecurity();
2292
2293      default:
2294        warn("Unimplemented Exception Level\n");
2295        return false;
2296    }
2297}
2298
2299bool
2300Gicv3CPUInterface::isSecureBelowEL3() const
2301{
2302    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
2303    return haveEL(EL3) && scr.ns == 0;
2304}
2305
2306bool
2307Gicv3CPUInterface::isAA64() const
2308{
2309    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2310    return opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2311}
2312
2313bool
2314Gicv3CPUInterface::isEL3OrMon() const
2315{
2316    if (haveEL(EL3)) {
2317        CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2318        bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2319
2320        if (is_64 && (cpsr.el == EL3)) {
2321            return true;
2322        } else if (!is_64 && (cpsr.mode == MODE_MON)) {
2323            return true;
2324        }
2325    }
2326
2327    return false;
2328}
2329
2330// Computes ICH_EISR_EL2
2331uint64_t
2332Gicv3CPUInterface::eoiMaintenanceInterruptStatus() const
2333{
2334    // ICH_EISR_EL2
2335    // Bits [63:16] - RES0
2336    // Status<n>, bit [n], for n = 0 to 15
2337    //   EOI maintenance interrupt status bit for List register <n>:
2338    //     0 if List register <n>, ICH_LR<n>_EL2, does not have an EOI
2339    //     maintenance interrupt.
2340    //     1 if List register <n>, ICH_LR<n>_EL2, has an EOI maintenance
2341    //     interrupt that has not been handled.
2342    //
2343    // For any ICH_LR<n>_EL2, the corresponding status bit is set to 1 if all
2344    // of the following are true:
2345    // - ICH_LR<n>_EL2.State is 0b00 (ICH_LR_EL2_STATE_INVALID).
2346    // - ICH_LR<n>_EL2.HW is 0.
2347    // - ICH_LR<n>_EL2.EOI (bit [41]) is 1.
2348
2349    uint64_t value = 0;
2350
2351    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2352        ICH_LR_EL2 ich_lr_el2 =
2353            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2354
2355        if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) &&
2356            !ich_lr_el2.HW && ich_lr_el2.EOI) {
2357            value |= (1 << lr_idx);
2358        }
2359    }
2360
2361    return value;
2362}
2363
2364Gicv3CPUInterface::ICH_MISR_EL2
2365Gicv3CPUInterface::maintenanceInterruptStatus() const
2366{
2367    // Comments are copied from SPEC section 9.4.7 (ID012119)
2368    ICH_MISR_EL2 ich_misr_el2 = 0;
2369    ICH_HCR_EL2 ich_hcr_el2 =
2370        isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2371    ICH_VMCR_EL2 ich_vmcr_el2 =
2372        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2373
2374    // End Of Interrupt. [bit 0]
2375    // This maintenance interrupt is asserted when at least one bit in
2376    // ICH_EISR_EL2 is 1.
2377
2378    if (eoiMaintenanceInterruptStatus()) {
2379        ich_misr_el2.EOI = 1;
2380    }
2381
2382    // Underflow. [bit 1]
2383    // This maintenance interrupt is asserted when ICH_HCR_EL2.UIE==1 and
2384    // zero or one of the List register entries are marked as a valid
2385    // interrupt, that is, if the corresponding ICH_LR<n>_EL2.State bits
2386    // do not equal 0x0.
2387    uint32_t num_valid_interrupts = 0;
2388    uint32_t num_pending_interrupts = 0;
2389
2390    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2391        ICH_LR_EL2 ich_lr_el2 =
2392            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2393
2394        if (ich_lr_el2.State != ICH_LR_EL2_STATE_INVALID) {
2395            num_valid_interrupts++;
2396        }
2397
2398        if (ich_lr_el2.State == ICH_LR_EL2_STATE_PENDING) {
2399            num_pending_interrupts++;
2400        }
2401    }
2402
2403    if (ich_hcr_el2.UIE && (num_valid_interrupts < 2)) {
2404        ich_misr_el2.U = 1;
2405    }
2406
2407    // List Register Entry Not Present. [bit 2]
2408    // This maintenance interrupt is asserted when ICH_HCR_EL2.LRENPIE==1
2409    // and ICH_HCR_EL2.EOIcount is non-zero.
2410    if (ich_hcr_el2.LRENPIE && ich_hcr_el2.EOIcount) {
2411        ich_misr_el2.LRENP = 1;
2412    }
2413
2414    // No Pending. [bit 3]
2415    // This maintenance interrupt is asserted when ICH_HCR_EL2.NPIE==1 and
2416    // no List register is in pending state.
2417    if (ich_hcr_el2.NPIE && (num_pending_interrupts == 0)) {
2418        ich_misr_el2.NP = 1;
2419    }
2420
2421    // vPE Group 0 Enabled. [bit 4]
2422    // This maintenance interrupt is asserted when
2423    // ICH_HCR_EL2.VGrp0EIE==1 and ICH_VMCR_EL2.VENG0==1.
2424    if (ich_hcr_el2.VGrp0EIE && ich_vmcr_el2.VENG0) {
2425        ich_misr_el2.VGrp0E = 1;
2426    }
2427
2428    // vPE Group 0 Disabled. [bit 5]
2429    // This maintenance interrupt is asserted when
2430    // ICH_HCR_EL2.VGrp0DIE==1 and ICH_VMCR_EL2.VENG0==0.
2431    if (ich_hcr_el2.VGrp0DIE && !ich_vmcr_el2.VENG0) {
2432        ich_misr_el2.VGrp0D = 1;
2433    }
2434
2435    // vPE Group 1 Enabled. [bit 6]
2436    // This maintenance interrupt is asserted when
2437    // ICH_HCR_EL2.VGrp1EIE==1 and ICH_VMCR_EL2.VENG1==is 1.
2438    if (ich_hcr_el2.VGrp1EIE && ich_vmcr_el2.VENG1) {
2439        ich_misr_el2.VGrp1E = 1;
2440    }
2441
2442    // vPE Group 1 Disabled. [bit 7]
2443    // This maintenance interrupt is asserted when
2444    // ICH_HCR_EL2.VGrp1DIE==1 and ICH_VMCR_EL2.VENG1==is 0.
2445    if (ich_hcr_el2.VGrp1DIE && !ich_vmcr_el2.VENG1) {
2446        ich_misr_el2.VGrp1D = 1;
2447    }
2448
2449    return ich_misr_el2;
2450}
2451
2452void
2453Gicv3CPUInterface::serialize(CheckpointOut & cp) const
2454{
2455    SERIALIZE_SCALAR(hppi.intid);
2456    SERIALIZE_SCALAR(hppi.prio);
2457    SERIALIZE_ENUM(hppi.group);
2458}
2459
2460void
2461Gicv3CPUInterface::unserialize(CheckpointIn & cp)
2462{
2463    UNSERIALIZE_SCALAR(hppi.intid);
2464    UNSERIALIZE_SCALAR(hppi.prio);
2465    UNSERIALIZE_ENUM(hppi.group);
2466}
2467