gic_v3_cpu_interface.cc revision 14246:033f20c96440
12SN/A/*
21762SN/A * Copyright (c) 2019 ARM Limited
32SN/A * All rights reserved
42SN/A *
52SN/A * The license below extends only to copyright in the software and shall
62SN/A * not be construed as granting a license to any other intellectual
72SN/A * property including but not limited to intellectual property relating
82SN/A * to a hardware implementation of the functionality of the software
92SN/A * licensed hereunder.  You may use the software subject to the license
102SN/A * terms below provided that you ensure that this notice is replicated
112SN/A * unmodified and in its entirety in all distributions of the software,
122SN/A * modified or unmodified, in source code or in binary form.
132SN/A *
142SN/A * Copyright (c) 2018 Metempsy Technology Consulting
152SN/A * All rights reserved.
162SN/A *
172SN/A * Redistribution and use in source and binary forms, with or without
182SN/A * modification, are permitted provided that the following conditions are
192SN/A * met: redistributions of source code must retain the above copyright
202SN/A * notice, this list of conditions and the following disclaimer;
212SN/A * redistributions in binary form must reproduce the above copyright
222SN/A * notice, this list of conditions and the following disclaimer in the
232SN/A * documentation and/or other materials provided with the distribution;
242SN/A * neither the name of the copyright holders nor the names of its
252SN/A * contributors may be used to endorse or promote products derived from
262SN/A * this software without specific prior written permission.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
292665Ssaidi@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
302665Ssaidi@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
312SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
322SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3310905Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3410905Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3510905Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3610474Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
372SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
382SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
392SN/A *
408229Snate@binkert.org * Authors: Jairo Balart
412984Sgblack@eecs.umich.edu */
428591Sgblack@eecs.umich.edu
43146SN/A#include "dev/arm/gic_v3_cpu_interface.hh"
44146SN/A
45146SN/A#include "arch/arm/isa.hh"
462680Sktlim@umich.edu#include "debug/GIC.hh"
478232Snate@binkert.org#include "dev/arm/gic_v3.hh"
488738Sgblack@eecs.umich.edu#include "dev/arm/gic_v3_distributor.hh"
492SN/A#include "dev/arm/gic_v3_redistributor.hh"
502SN/A
512SN/Aconst uint8_t Gicv3CPUInterface::GIC_MIN_BPR;
524088Sbinkertn@umich.educonst uint8_t Gicv3CPUInterface::GIC_MIN_BPR_NS;
535569Snate@binkert.org
543838Shsul@eecs.umich.eduGicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id)
553838Shsul@eecs.umich.edu    : BaseISADevice(),
563838Shsul@eecs.umich.edu      gic(gic),
573838Shsul@eecs.umich.edu      redistributor(nullptr),
585569Snate@binkert.org      distributor(nullptr),
59860SN/A      cpuId(cpu_id)
603838Shsul@eecs.umich.edu{
613838Shsul@eecs.umich.edu}
62860SN/A
63860SN/Avoid
645569Snate@binkert.orgGicv3CPUInterface::init()
651147SN/A{
665034Smilesck@eecs.umich.edu    redistributor = gic->getRedistributor(cpuId);
6710905Sandreas.sandberg@arm.com    distributor = gic->getDistributor();
683838Shsul@eecs.umich.edu}
694957Sacolyte@umich.edu
703838Shsul@eecs.umich.eduvoid
712SN/AGicv3CPUInterface::initState()
723838Shsul@eecs.umich.edu{
733838Shsul@eecs.umich.edu    reset();
743838Shsul@eecs.umich.edu}
752SN/A
766022Sgblack@eecs.umich.eduvoid
776022Sgblack@eecs.umich.eduGicv3CPUInterface::reset()
786022Sgblack@eecs.umich.edu{
7911523Sdavid.guillen@arm.com    hppi.prio = 0xff;
8011523Sdavid.guillen@arm.com}
816022Sgblack@eecs.umich.edu
826022Sgblack@eecs.umich.eduvoid
836022Sgblack@eecs.umich.eduGicv3CPUInterface::setThreadContext(ThreadContext *tc)
846022Sgblack@eecs.umich.edu{
856022Sgblack@eecs.umich.edu    maintenanceInterrupt = gic->params()->maint_int->get(tc);
866022Sgblack@eecs.umich.edu}
876022Sgblack@eecs.umich.edu
886022Sgblack@eecs.umich.edubool
896022Sgblack@eecs.umich.eduGicv3CPUInterface::getHCREL2FMO() const
906022Sgblack@eecs.umich.edu{
916022Sgblack@eecs.umich.edu    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
926022Sgblack@eecs.umich.edu
936022Sgblack@eecs.umich.edu    if (hcr.tge && hcr.e2h) {
946022Sgblack@eecs.umich.edu        return false;
956022Sgblack@eecs.umich.edu    } else if (hcr.tge) {
966022Sgblack@eecs.umich.edu        return true;
976022Sgblack@eecs.umich.edu    } else {
986022Sgblack@eecs.umich.edu        return hcr.fmo;
996022Sgblack@eecs.umich.edu    }
1006022Sgblack@eecs.umich.edu}
1016022Sgblack@eecs.umich.edu
1026022Sgblack@eecs.umich.edubool
1036022Sgblack@eecs.umich.eduGicv3CPUInterface::getHCREL2IMO() const
1046022Sgblack@eecs.umich.edu{
1056022Sgblack@eecs.umich.edu    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
1066022Sgblack@eecs.umich.edu
1076022Sgblack@eecs.umich.edu    if (hcr.tge && hcr.e2h) {
1086022Sgblack@eecs.umich.edu        return false;
1096022Sgblack@eecs.umich.edu    } else if (hcr.tge) {
1106022Sgblack@eecs.umich.edu        return true;
1116022Sgblack@eecs.umich.edu    } else {
1126022Sgblack@eecs.umich.edu        return hcr.imo;
1136022Sgblack@eecs.umich.edu    }
1146022Sgblack@eecs.umich.edu}
1156022Sgblack@eecs.umich.edu
1166022Sgblack@eecs.umich.eduRegVal
1176022Sgblack@eecs.umich.eduGicv3CPUInterface::readMiscReg(int misc_reg)
1186022Sgblack@eecs.umich.edu{
1196022Sgblack@eecs.umich.edu    RegVal value = isa->readMiscRegNoEffect(misc_reg);
1206022Sgblack@eecs.umich.edu    bool hcr_fmo = getHCREL2FMO();
1216022Sgblack@eecs.umich.edu    bool hcr_imo = getHCREL2IMO();
1226022Sgblack@eecs.umich.edu
1236022Sgblack@eecs.umich.edu    switch (misc_reg) {
1246022Sgblack@eecs.umich.edu      // Active Priorities Group 1 Registers
1256022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R0:
1266022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R0_EL1: {
1276022Sgblack@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1286022Sgblack@eecs.umich.edu              return isa->readMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1);
1296022Sgblack@eecs.umich.edu          }
1306022Sgblack@eecs.umich.edu
1316022Sgblack@eecs.umich.edu          return readBankedMiscReg(MISCREG_ICC_AP1R0_EL1);
1326022Sgblack@eecs.umich.edu      }
1336022Sgblack@eecs.umich.edu
1346022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R1:
1356022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R1_EL1:
1366022Sgblack@eecs.umich.edu
1376022Sgblack@eecs.umich.edu        // only implemented if supporting 6 or more bits of priority
1386022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R2:
1396022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R2_EL1:
1406022Sgblack@eecs.umich.edu
1416022Sgblack@eecs.umich.edu        // only implemented if supporting 7 or more bits of priority
1426022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R3:
1436022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP1R3_EL1:
1446022Sgblack@eecs.umich.edu        // only implemented if supporting 7 or more bits of priority
1456022Sgblack@eecs.umich.edu        return 0;
1466022Sgblack@eecs.umich.edu
1476022Sgblack@eecs.umich.edu      // Active Priorities Group 0 Registers
1486022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP0R0:
1496022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP0R0_EL1: {
1506022Sgblack@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1516022Sgblack@eecs.umich.edu              return isa->readMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1);
1526022Sgblack@eecs.umich.edu          }
1536022Sgblack@eecs.umich.edu
1546022Sgblack@eecs.umich.edu          break;
1556022Sgblack@eecs.umich.edu      }
1566022Sgblack@eecs.umich.edu
1576022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP0R1:
1586022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP0R1_EL1:
1596022Sgblack@eecs.umich.edu
1606022Sgblack@eecs.umich.edu        // only implemented if supporting 6 or more bits of priority
1616022Sgblack@eecs.umich.edu      case MISCREG_ICC_AP0R2:
1623838Shsul@eecs.umich.edu      case MISCREG_ICC_AP0R2_EL1:
1635004Sgblack@eecs.umich.edu
1644967Sacolyte@umich.edu        // only implemented if supporting 7 or more bits of priority
1653838Shsul@eecs.umich.edu      case MISCREG_ICC_AP0R3:
1663838Shsul@eecs.umich.edu      case MISCREG_ICC_AP0R3_EL1:
1675004Sgblack@eecs.umich.edu        // only implemented if supporting 7 or more bits of priority
1682SN/A        return 0;
1695004Sgblack@eecs.umich.edu
1705004Sgblack@eecs.umich.edu      // Interrupt Group 0 Enable register EL1
1715004Sgblack@eecs.umich.edu      case MISCREG_ICC_IGRPEN0:
1725004Sgblack@eecs.umich.edu      case MISCREG_ICC_IGRPEN0_EL1: {
1735004Sgblack@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1745004Sgblack@eecs.umich.edu              return readMiscReg(MISCREG_ICV_IGRPEN0_EL1);
1755004Sgblack@eecs.umich.edu          }
1765004Sgblack@eecs.umich.edu
1775004Sgblack@eecs.umich.edu          break;
1785004Sgblack@eecs.umich.edu      }
1795004Sgblack@eecs.umich.edu
1804962Sacolyte@umich.edu      case MISCREG_ICV_IGRPEN0_EL1: {
1814962Sacolyte@umich.edu          ICH_VMCR_EL2 ich_vmcr_el2 =
1824962Sacolyte@umich.edu              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1834967Sacolyte@umich.edu          value = ich_vmcr_el2.VENG0;
1844957Sacolyte@umich.edu          break;
1854957Sacolyte@umich.edu      }
1864957Sacolyte@umich.edu
1874957Sacolyte@umich.edu      // Interrupt Group 1 Enable register EL1
1885004Sgblack@eecs.umich.edu      case MISCREG_ICC_IGRPEN1:
1895004Sgblack@eecs.umich.edu      case MISCREG_ICC_IGRPEN1_EL1: {
1905004Sgblack@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1915004Sgblack@eecs.umich.edu              return readMiscReg(MISCREG_ICV_IGRPEN1_EL1);
1924957Sacolyte@umich.edu          }
1934957Sacolyte@umich.edu
1944957Sacolyte@umich.edu          break;
1954957Sacolyte@umich.edu      }
1961413SN/A
1971413SN/A      case MISCREG_ICV_IGRPEN1_EL1: {
1982SN/A          ICH_VMCR_EL2 ich_vmcr_el2 =
1992SN/A              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2003838Shsul@eecs.umich.edu          value = ich_vmcr_el2.VENG1;
2013838Shsul@eecs.umich.edu          break;
2023838Shsul@eecs.umich.edu      }
2033838Shsul@eecs.umich.edu
2042SN/A      // Interrupt Group 1 Enable register EL3
2053838Shsul@eecs.umich.edu      case MISCREG_ICC_MGRPEN1:
20612749Sgiacomo.travaglini@arm.com      case MISCREG_ICC_IGRPEN1_EL3:
2073838Shsul@eecs.umich.edu          break;
2085569Snate@binkert.org
2095569Snate@binkert.org      // Running Priority Register
2103838Shsul@eecs.umich.edu      case MISCREG_ICC_RPR:
2115569Snate@binkert.org      case MISCREG_ICC_RPR_EL1: {
2125569Snate@binkert.org          if ((currEL() == EL1) && !inSecureState() &&
2135569Snate@binkert.org              (hcr_imo || hcr_fmo)) {
2145569Snate@binkert.org              return readMiscReg(MISCREG_ICV_RPR_EL1);
2155569Snate@binkert.org          }
2165569Snate@binkert.org
2175569Snate@binkert.org          uint8_t rprio = highestActivePriority();
2185569Snate@binkert.org
2193838Shsul@eecs.umich.edu          if (haveEL(EL3) && !inSecureState() &&
2203838Shsul@eecs.umich.edu              (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
2216025Snate@binkert.org              // Spec section 4.8.1
2223838Shsul@eecs.umich.edu              // For Non-secure access to ICC_RPR_EL1 when SCR_EL3.FIQ == 1
2233838Shsul@eecs.umich.edu              if ((rprio & 0x80) == 0) {
22410474Sandreas.hansson@arm.com                  // If the current priority mask value is in the range of
22510474Sandreas.hansson@arm.com                  // 0x00-0x7F a read access returns the value 0x0
2263838Shsul@eecs.umich.edu                  rprio = 0;
2273838Shsul@eecs.umich.edu              } else if (rprio != 0xff) {
22810824SAndreas.Sandberg@ARM.com                  // If the current priority mask value is in the range of
2293838Shsul@eecs.umich.edu                  // 0x80-0xFF a read access returns the Non-secure read of
2305569Snate@binkert.org                  // the current value
2315569Snate@binkert.org                  rprio = (rprio << 1) & 0xff;
2323838Shsul@eecs.umich.edu              }
233924SN/A          }
2345532Ssaidi@eecs.umich.edu
23511320Ssteve.reinhardt@amd.com          value = rprio;
23611320Ssteve.reinhardt@amd.com          break;
23711320Ssteve.reinhardt@amd.com      }
23810474Sandreas.hansson@arm.com
23910474Sandreas.hansson@arm.com      // Virtual Running Priority Register
2405532Ssaidi@eecs.umich.edu      case MISCREG_ICV_RPR_EL1: {
2412SN/A          value = virtualHighestActivePriority();
2423838Shsul@eecs.umich.edu          break;
2433838Shsul@eecs.umich.edu      }
2442SN/A
2452SN/A      // Highest Priority Pending Interrupt Register 0
2463838Shsul@eecs.umich.edu      case MISCREG_ICC_HPPIR0:
2473838Shsul@eecs.umich.edu      case MISCREG_ICC_HPPIR0_EL1: {
2485004Sgblack@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
2493838Shsul@eecs.umich.edu              return readMiscReg(MISCREG_ICV_HPPIR0_EL1);
2504957Sacolyte@umich.edu          }
2513838Shsul@eecs.umich.edu
2523838Shsul@eecs.umich.edu          value = getHPPIR0();
2533838Shsul@eecs.umich.edu          break;
2543838Shsul@eecs.umich.edu      }
2553838Shsul@eecs.umich.edu
2563838Shsul@eecs.umich.edu      // Virtual Highest Priority Pending Interrupt Register 0
2573838Shsul@eecs.umich.edu      case MISCREG_ICV_HPPIR0_EL1: {
2583838Shsul@eecs.umich.edu          value = Gicv3::INTID_SPURIOUS;
2593838Shsul@eecs.umich.edu          int lr_idx = getHPPVILR();
2603838Shsul@eecs.umich.edu
2613838Shsul@eecs.umich.edu          if (lr_idx >= 0) {
2623838Shsul@eecs.umich.edu              ICH_LR_EL2 ich_lr_el2 =
2633838Shsul@eecs.umich.edu                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2643838Shsul@eecs.umich.edu              Gicv3::GroupId group =
2653838Shsul@eecs.umich.edu                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2663838Shsul@eecs.umich.edu
2673838Shsul@eecs.umich.edu              if (group == Gicv3::G0S) {
2683838Shsul@eecs.umich.edu                  value = ich_lr_el2.vINTID;
2693838Shsul@eecs.umich.edu              }
2703838Shsul@eecs.umich.edu          }
2713838Shsul@eecs.umich.edu
2725004Sgblack@eecs.umich.edu          break;
2733838Shsul@eecs.umich.edu      }
2745004Sgblack@eecs.umich.edu
2753838Shsul@eecs.umich.edu      // Highest Priority Pending Interrupt Register 1
2763838Shsul@eecs.umich.edu      case MISCREG_ICC_HPPIR1:
2773838Shsul@eecs.umich.edu      case MISCREG_ICC_HPPIR1_EL1: {
2783838Shsul@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
2793838Shsul@eecs.umich.edu              return readMiscReg(MISCREG_ICV_HPPIR1_EL1);
2803838Shsul@eecs.umich.edu          }
2813838Shsul@eecs.umich.edu
2823838Shsul@eecs.umich.edu          value = getHPPIR1();
2833838Shsul@eecs.umich.edu          break;
2843838Shsul@eecs.umich.edu      }
2853838Shsul@eecs.umich.edu
28610905Sandreas.sandberg@arm.com      // Virtual Highest Priority Pending Interrupt Register 1
2874957Sacolyte@umich.edu      case MISCREG_ICV_HPPIR1_EL1: {
2883838Shsul@eecs.umich.edu          value = Gicv3::INTID_SPURIOUS;
2893838Shsul@eecs.umich.edu          int lr_idx = getHPPVILR();
2903838Shsul@eecs.umich.edu
2913838Shsul@eecs.umich.edu          if (lr_idx >= 0) {
2923838Shsul@eecs.umich.edu              ICH_LR_EL2 ich_lr_el2 =
2933838Shsul@eecs.umich.edu                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2943838Shsul@eecs.umich.edu              Gicv3::GroupId group =
2954957Sacolyte@umich.edu                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2963838Shsul@eecs.umich.edu
2973838Shsul@eecs.umich.edu              if (group == Gicv3::G1NS) {
2983838Shsul@eecs.umich.edu                  value = ich_lr_el2.vINTID;
2993838Shsul@eecs.umich.edu              }
3005004Sgblack@eecs.umich.edu          }
3015004Sgblack@eecs.umich.edu
3023838Shsul@eecs.umich.edu          break;
3033838Shsul@eecs.umich.edu      }
3043838Shsul@eecs.umich.edu
3053838Shsul@eecs.umich.edu      // Binary Point Register 0
3063838Shsul@eecs.umich.edu      case MISCREG_ICC_BPR0:
3073838Shsul@eecs.umich.edu      case MISCREG_ICC_BPR0_EL1: {
3085004Sgblack@eecs.umich.edu        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
3095569Snate@binkert.org            return readMiscReg(MISCREG_ICV_BPR0_EL1);
3105569Snate@binkert.org        }
3115004Sgblack@eecs.umich.edu
3123838Shsul@eecs.umich.edu        value = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1);
3133453Sgblack@eecs.umich.edu        break;
3143453Sgblack@eecs.umich.edu      }
3153838Shsul@eecs.umich.edu
3162SN/A      // Binary Point Register 1
3173838Shsul@eecs.umich.edu      case MISCREG_ICC_BPR1:
3183838Shsul@eecs.umich.edu      case MISCREG_ICC_BPR1_EL1: {
3193838Shsul@eecs.umich.edu        value = bpr1(isSecureBelowEL3() ? Gicv3::G1S : Gicv3::G1NS);
3204957Sacolyte@umich.edu        break;
3213838Shsul@eecs.umich.edu      }
3222SN/A
3233838Shsul@eecs.umich.edu      // Virtual Binary Point Register 0
3243838Shsul@eecs.umich.edu      case MISCREG_ICV_BPR0_EL1: {
3253838Shsul@eecs.umich.edu        ICH_VMCR_EL2 ich_vmcr_el2 =
3262SN/A            isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
3274428Ssaidi@eecs.umich.edu
3283838Shsul@eecs.umich.edu        value = ich_vmcr_el2.VBPR0;
3295004Sgblack@eecs.umich.edu        break;
3305004Sgblack@eecs.umich.edu      }
3313453Sgblack@eecs.umich.edu
3325004Sgblack@eecs.umich.edu      // Virtual Binary Point Register 1
3333838Shsul@eecs.umich.edu      case MISCREG_ICV_BPR1_EL1: {
3345004Sgblack@eecs.umich.edu        ICH_VMCR_EL2 ich_vmcr_el2 =
3353453Sgblack@eecs.umich.edu            isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
3363838Shsul@eecs.umich.edu
3375004Sgblack@eecs.umich.edu        if (ich_vmcr_el2.VCBPR) {
3383838Shsul@eecs.umich.edu            // bpr0 + 1 saturated to 7, WI
3394428Ssaidi@eecs.umich.edu            value = ich_vmcr_el2.VBPR0 + 1;
3404428Ssaidi@eecs.umich.edu            value = value < 7 ? value : 7;
3414428Ssaidi@eecs.umich.edu        } else {
3423838Shsul@eecs.umich.edu            value = ich_vmcr_el2.VBPR1;
3433838Shsul@eecs.umich.edu        }
3443838Shsul@eecs.umich.edu
3453838Shsul@eecs.umich.edu        break;
3463838Shsul@eecs.umich.edu      }
3473838Shsul@eecs.umich.edu
34810905Sandreas.sandberg@arm.com      // Interrupt Priority Mask Register
3493838Shsul@eecs.umich.edu      case MISCREG_ICC_PMR:
35010905Sandreas.sandberg@arm.com      case MISCREG_ICC_PMR_EL1:
3513838Shsul@eecs.umich.edu        if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
3523838Shsul@eecs.umich.edu            return readMiscReg(MISCREG_ICV_PMR_EL1);
3533838Shsul@eecs.umich.edu        }
35410905Sandreas.sandberg@arm.com
35510905Sandreas.sandberg@arm.com        if (haveEL(EL3) && !inSecureState() &&
3563838Shsul@eecs.umich.edu            (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
3573838Shsul@eecs.umich.edu            // Spec section 4.8.1
3583838Shsul@eecs.umich.edu            // For Non-secure access to ICC_PMR_EL1 when SCR_EL3.FIQ == 1:
35910905Sandreas.sandberg@arm.com            if ((value & 0x80) == 0) {
3603838Shsul@eecs.umich.edu                // If the current priority mask value is in the range of
36110905Sandreas.sandberg@arm.com                // 0x00-0x7F a read access returns the value 0x00.
3623838Shsul@eecs.umich.edu                value = 0;
3633838Shsul@eecs.umich.edu            } else if (value != 0xff) {
3643838Shsul@eecs.umich.edu                // If the current priority mask value is in the range of
36510905Sandreas.sandberg@arm.com                // 0x80-0xFF a read access returns the Non-secure read of the
3663838Shsul@eecs.umich.edu                // current value.
36710905Sandreas.sandberg@arm.com                value = (value << 1) & 0xff;
3683838Shsul@eecs.umich.edu            }
3693838Shsul@eecs.umich.edu        }
3703838Shsul@eecs.umich.edu
3713838Shsul@eecs.umich.edu        break;
3723838Shsul@eecs.umich.edu
3733838Shsul@eecs.umich.edu      case MISCREG_ICV_PMR_EL1: { // Priority Mask Register
3743838Shsul@eecs.umich.edu          ICH_VMCR_EL2 ich_vmcr_el2 =
37512749Sgiacomo.travaglini@arm.com              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
3763838Shsul@eecs.umich.edu
3774375Sgblack@eecs.umich.edu          value = ich_vmcr_el2.VPMR;
3788738Sgblack@eecs.umich.edu          break;
3795736Snate@binkert.org      }
3804375Sgblack@eecs.umich.edu
3813838Shsul@eecs.umich.edu      // Interrupt Acknowledge Register 0
3823838Shsul@eecs.umich.edu      case MISCREG_ICC_IAR0:
3833838Shsul@eecs.umich.edu      case MISCREG_ICC_IAR0_EL1: {
3846022Sgblack@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
3853838Shsul@eecs.umich.edu              return readMiscReg(MISCREG_ICV_IAR0_EL1);
3863453Sgblack@eecs.umich.edu          }
3873453Sgblack@eecs.umich.edu
3885736Snate@binkert.org          uint32_t int_id;
3893838Shsul@eecs.umich.edu
3903838Shsul@eecs.umich.edu          if (hppiCanPreempt()) {
3913838Shsul@eecs.umich.edu              int_id = getHPPIR0();
3923838Shsul@eecs.umich.edu
3936022Sgblack@eecs.umich.edu              // avoid activation for special interrupts
39410474Sandreas.hansson@arm.com              if (int_id < Gicv3::INTID_SECURE ||
3952SN/A                  int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
3962SN/A                  activateIRQ(int_id, hppi.group);
3973838Shsul@eecs.umich.edu              }
3983838Shsul@eecs.umich.edu          } else {
3993838Shsul@eecs.umich.edu              int_id = Gicv3::INTID_SPURIOUS;
4006025Snate@binkert.org          }
4013838Shsul@eecs.umich.edu
4024172Ssaidi@eecs.umich.edu          value = int_id;
4033838Shsul@eecs.umich.edu          break;
4046022Sgblack@eecs.umich.edu      }
40510474Sandreas.hansson@arm.com
406555SN/A      // Virtual Interrupt Acknowledge Register 0
4072SN/A      case MISCREG_ICV_IAR0_EL1: {
4083838Shsul@eecs.umich.edu          int lr_idx = getHPPVILR();
409551SN/A          uint32_t int_id = Gicv3::INTID_SPURIOUS;
4103838Shsul@eecs.umich.edu
4113838Shsul@eecs.umich.edu          if (lr_idx >= 0) {
4123838Shsul@eecs.umich.edu              ICH_LR_EL2 ich_lr_el2 =
4133838Shsul@eecs.umich.edu                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
4143838Shsul@eecs.umich.edu
4153838Shsul@eecs.umich.edu              if (!ich_lr_el2.Group && hppviCanPreempt(lr_idx)) {
4163838Shsul@eecs.umich.edu                  int_id = ich_lr_el2.vINTID;
4174172Ssaidi@eecs.umich.edu
4185004Sgblack@eecs.umich.edu                  if (int_id < Gicv3::INTID_SECURE ||
4193838Shsul@eecs.umich.edu                      int_id > Gicv3::INTID_SPURIOUS) {
4203838Shsul@eecs.umich.edu                      virtualActivateIRQ(lr_idx);
4215004Sgblack@eecs.umich.edu                  } else {
4226022Sgblack@eecs.umich.edu                      // Bogus... Pseudocode says:
42310474Sandreas.hansson@arm.com                      // - Move from pending to invalid...
4243838Shsul@eecs.umich.edu                      // - Return de bogus id...
4253838Shsul@eecs.umich.edu                      ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID;
4265004Sgblack@eecs.umich.edu                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
4273838Shsul@eecs.umich.edu                                              ich_lr_el2);
4283838Shsul@eecs.umich.edu                  }
4293838Shsul@eecs.umich.edu              }
4303838Shsul@eecs.umich.edu          }
4315004Sgblack@eecs.umich.edu
4324172Ssaidi@eecs.umich.edu          value = int_id;
4333838Shsul@eecs.umich.edu          virtualUpdate();
4346022Sgblack@eecs.umich.edu          break;
43510474Sandreas.hansson@arm.com      }
4363838Shsul@eecs.umich.edu
4373838Shsul@eecs.umich.edu      // Interrupt Acknowledge Register 1
4386022Sgblack@eecs.umich.edu      case MISCREG_ICC_IAR1:
4393838Shsul@eecs.umich.edu      case MISCREG_ICC_IAR1_EL1: {
4403838Shsul@eecs.umich.edu          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
4413838Shsul@eecs.umich.edu              return readMiscReg(MISCREG_ICV_IAR1_EL1);
4423838Shsul@eecs.umich.edu          }
4438591Sgblack@eecs.umich.edu
44410474Sandreas.hansson@arm.com          uint32_t int_id;
4458591Sgblack@eecs.umich.edu
4463838Shsul@eecs.umich.edu          if (hppiCanPreempt()) {
4475532Ssaidi@eecs.umich.edu              int_id = getHPPIR1();
4483838Shsul@eecs.umich.edu
4493838Shsul@eecs.umich.edu              // avoid activation for special interrupts
4503838Shsul@eecs.umich.edu              if (int_id < Gicv3::INTID_SECURE ||
4513838Shsul@eecs.umich.edu                  int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
45212749Sgiacomo.travaglini@arm.com                  activateIRQ(int_id, hppi.group);
4533838Shsul@eecs.umich.edu              }
4543838Shsul@eecs.umich.edu          } else {
4554172Ssaidi@eecs.umich.edu              int_id = Gicv3::INTID_SPURIOUS;
4563838Shsul@eecs.umich.edu          }
4573838Shsul@eecs.umich.edu
4583838Shsul@eecs.umich.edu          value = int_id;
4593838Shsul@eecs.umich.edu          break;
4603838Shsul@eecs.umich.edu      }
4616185Sksewell@umich.edu
4623838Shsul@eecs.umich.edu      // Virtual Interrupt Acknowledge Register 1
4633838Shsul@eecs.umich.edu      case MISCREG_ICV_IAR1_EL1: {
46410474Sandreas.hansson@arm.com          int lr_idx = getHPPVILR();
46510474Sandreas.hansson@arm.com          uint32_t int_id = Gicv3::INTID_SPURIOUS;
46610474Sandreas.hansson@arm.com
4673838Shsul@eecs.umich.edu          if (lr_idx >= 0) {
4683838Shsul@eecs.umich.edu              ICH_LR_EL2 ich_lr_el2 =
4698408Sksewell@umich.edu                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
47010823SAndreas.Sandberg@ARM.com
4713838Shsul@eecs.umich.edu              if (ich_lr_el2.Group && hppviCanPreempt(lr_idx)) {
4724172Ssaidi@eecs.umich.edu                  int_id = ich_lr_el2.vINTID;
4733838Shsul@eecs.umich.edu
4743838Shsul@eecs.umich.edu                  if (int_id < Gicv3::INTID_SECURE ||
4753838Shsul@eecs.umich.edu                      int_id > Gicv3::INTID_SPURIOUS) {
4765736Snate@binkert.org                      virtualActivateIRQ(lr_idx);
4773838Shsul@eecs.umich.edu                  } else {
4783838Shsul@eecs.umich.edu                      // Bogus... Pseudocode says:
4793838Shsul@eecs.umich.edu                      // - Move from pending to invalid...
4803838Shsul@eecs.umich.edu                      // - Return de bogus id...
4813838Shsul@eecs.umich.edu                      ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID;
4823838Shsul@eecs.umich.edu                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
4833838Shsul@eecs.umich.edu                                              ich_lr_el2);
4843838Shsul@eecs.umich.edu                  }
48510474Sandreas.hansson@arm.com              }
48610474Sandreas.hansson@arm.com          }
48710474Sandreas.hansson@arm.com
4883838Shsul@eecs.umich.edu          value = int_id;
4893838Shsul@eecs.umich.edu          virtualUpdate();
4903838Shsul@eecs.umich.edu          break;
4916025Snate@binkert.org      }
4923838Shsul@eecs.umich.edu
4934172Ssaidi@eecs.umich.edu      // System Register Enable Register EL1
4943838Shsul@eecs.umich.edu      case MISCREG_ICC_SRE:
4953838Shsul@eecs.umich.edu      case MISCREG_ICC_SRE_EL1: {
4963838Shsul@eecs.umich.edu        /*
4973838Shsul@eecs.umich.edu         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
4985569Snate@binkert.org         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
49910474Sandreas.hansson@arm.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
50010474Sandreas.hansson@arm.com         */
50110474Sandreas.hansson@arm.com          ICC_SRE_EL1 icc_sre_el1 = 0;
5023838Shsul@eecs.umich.edu          icc_sre_el1.SRE = 1;
5033838Shsul@eecs.umich.edu          icc_sre_el1.DIB = 1;
5043838Shsul@eecs.umich.edu          icc_sre_el1.DFB = 1;
5053838Shsul@eecs.umich.edu          value = icc_sre_el1;
5063838Shsul@eecs.umich.edu          break;
5073838Shsul@eecs.umich.edu      }
5083838Shsul@eecs.umich.edu
5093838Shsul@eecs.umich.edu      // System Register Enable Register EL2
5103838Shsul@eecs.umich.edu      case MISCREG_ICC_HSRE:
5113838Shsul@eecs.umich.edu      case MISCREG_ICC_SRE_EL2: {
5123838Shsul@eecs.umich.edu        /*
5133838Shsul@eecs.umich.edu         * Enable [3] == 1
5143838Shsul@eecs.umich.edu         * (EL1 accesses to ICC_SRE_EL1 do not trap to EL2, RAO/WI)
5153838Shsul@eecs.umich.edu         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
5163838Shsul@eecs.umich.edu         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
5174172Ssaidi@eecs.umich.edu         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
5183838Shsul@eecs.umich.edu         */
5193838Shsul@eecs.umich.edu        ICC_SRE_EL2 icc_sre_el2 = 0;
5205004Sgblack@eecs.umich.edu        icc_sre_el2.SRE = 1;
5213838Shsul@eecs.umich.edu        icc_sre_el2.DIB = 1;
5225004Sgblack@eecs.umich.edu        icc_sre_el2.DFB = 1;
5233838Shsul@eecs.umich.edu        icc_sre_el2.Enable = 1;
5243838Shsul@eecs.umich.edu        value = icc_sre_el2;
5253838Shsul@eecs.umich.edu        break;
5263838Shsul@eecs.umich.edu      }
52710823SAndreas.Sandberg@ARM.com
52810474Sandreas.hansson@arm.com      // System Register Enable Register EL3
52910474Sandreas.hansson@arm.com      case MISCREG_ICC_MSRE:
53010474Sandreas.hansson@arm.com      case MISCREG_ICC_SRE_EL3: {
53110474Sandreas.hansson@arm.com        /*
53210474Sandreas.hansson@arm.com         * Enable [3] == 1
53310474Sandreas.hansson@arm.com         * (EL1 accesses to ICC_SRE_EL1 do not trap to EL3.
5343838Shsul@eecs.umich.edu         *  EL2 accesses to ICC_SRE_EL1 and ICC_SRE_EL2 do not trap to EL3.
5353838Shsul@eecs.umich.edu         *  RAO/WI)
5365004Sgblack@eecs.umich.edu         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
5373838Shsul@eecs.umich.edu         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
5383838Shsul@eecs.umich.edu         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
5393838Shsul@eecs.umich.edu         */
5405004Sgblack@eecs.umich.edu        ICC_SRE_EL3 icc_sre_el3 = 0;
5413838Shsul@eecs.umich.edu        icc_sre_el3.SRE = 1;
5423838Shsul@eecs.umich.edu        icc_sre_el3.DIB = 1;
5433838Shsul@eecs.umich.edu        icc_sre_el3.DFB = 1;
5443838Shsul@eecs.umich.edu        icc_sre_el3.Enable = 1;
5455004Sgblack@eecs.umich.edu        value = icc_sre_el3;
54610474Sandreas.hansson@arm.com        break;
54710474Sandreas.hansson@arm.com      }
54810474Sandreas.hansson@arm.com
5493838Shsul@eecs.umich.edu      // Control Register
5505004Sgblack@eecs.umich.edu      case MISCREG_ICC_CTLR:
5513838Shsul@eecs.umich.edu      case MISCREG_ICC_CTLR_EL1: {
5525569Snate@binkert.org          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
55310474Sandreas.hansson@arm.com              return readMiscReg(MISCREG_ICV_CTLR_EL1);
55410474Sandreas.hansson@arm.com          }
55510474Sandreas.hansson@arm.com
5563838Shsul@eecs.umich.edu          value = readBankedMiscReg(MISCREG_ICC_CTLR_EL1);
5573453Sgblack@eecs.umich.edu          // Enforce value for RO bits
5585004Sgblack@eecs.umich.edu          // ExtRange [19], INTIDs in the range 1024..8191 not supported
5593838Shsul@eecs.umich.edu          // RSS [18], SGIs with affinity level 0 values of 0-255 are supported
5603838Shsul@eecs.umich.edu          // A3V [15], supports non-zero values of the Aff3 field in SGI
5615004Sgblack@eecs.umich.edu          //           generation System registers
56210474Sandreas.hansson@arm.com          // SEIS [14], does not support generation of SEIs (deprecated)
56310474Sandreas.hansson@arm.com          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
56410474Sandreas.hansson@arm.com          // PRIbits [10:8], number of priority bits implemented, minus one
5653453Sgblack@eecs.umich.edu          ICC_CTLR_EL1 icc_ctlr_el1 = value;
5665004Sgblack@eecs.umich.edu          icc_ctlr_el1.ExtRange = 0;
5673838Shsul@eecs.umich.edu          icc_ctlr_el1.RSS = 1;
5683838Shsul@eecs.umich.edu          icc_ctlr_el1.A3V = 1;
56910474Sandreas.hansson@arm.com          icc_ctlr_el1.SEIS = 0;
57010474Sandreas.hansson@arm.com          icc_ctlr_el1.IDbits = 1;
57110474Sandreas.hansson@arm.com          icc_ctlr_el1.PRIbits = PRIORITY_BITS - 1;
5723453Sgblack@eecs.umich.edu          value = icc_ctlr_el1;
5732SN/A          break;
5742SN/A      }
575551SN/A
5763838Shsul@eecs.umich.edu      // Virtual Control Register
5773838Shsul@eecs.umich.edu      case MISCREG_ICV_CTLR_EL1: {
5783838Shsul@eecs.umich.edu          ICV_CTLR_EL1 icv_ctlr_el1 = value;
5793838Shsul@eecs.umich.edu          icv_ctlr_el1.RSS = 0;
5802SN/A          icv_ctlr_el1.A3V = 1;
5812SN/A          icv_ctlr_el1.SEIS = 0;
5823838Shsul@eecs.umich.edu          icv_ctlr_el1.IDbits = 1;
5838591Sgblack@eecs.umich.edu          icv_ctlr_el1.PRIbits = 7;
58410474Sandreas.hansson@arm.com          value = icv_ctlr_el1;
5858591Sgblack@eecs.umich.edu          break;
586551SN/A      }
5873838Shsul@eecs.umich.edu
5883838Shsul@eecs.umich.edu      // Control Register
5893453Sgblack@eecs.umich.edu      case MISCREG_ICC_MCTLR:
5905004Sgblack@eecs.umich.edu      case MISCREG_ICC_CTLR_EL3: {
5913838Shsul@eecs.umich.edu          // Enforce value for RO bits
5923838Shsul@eecs.umich.edu          // ExtRange [19], INTIDs in the range 1024..8191 not supported
5935004Sgblack@eecs.umich.edu          // RSS [18], SGIs with affinity level 0 values of 0-255 are supported
5943453Sgblack@eecs.umich.edu          // nDS [17], supports disabling of security
5953838Shsul@eecs.umich.edu          // A3V [15], supports non-zero values of the Aff3 field in SGI
5963838Shsul@eecs.umich.edu          //           generation System registers
5973453Sgblack@eecs.umich.edu          // SEIS [14], does not support generation of SEIs (deprecated)
5985004Sgblack@eecs.umich.edu          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
5993838Shsul@eecs.umich.edu          // PRIbits [10:8], number of priority bits implemented, minus one
6003453Sgblack@eecs.umich.edu          ICC_CTLR_EL3 icc_ctlr_el3 = value;
6016022Sgblack@eecs.umich.edu          icc_ctlr_el3.ExtRange = 0;
60212749Sgiacomo.travaglini@arm.com          icc_ctlr_el3.RSS = 1;
6036022Sgblack@eecs.umich.edu          icc_ctlr_el3.nDS = 0;
6046023Snate@binkert.org          icc_ctlr_el3.A3V = 1;
6056022Sgblack@eecs.umich.edu          icc_ctlr_el3.SEIS = 0;
6066022Sgblack@eecs.umich.edu          icc_ctlr_el3.IDbits = 0;
6076023Snate@binkert.org          icc_ctlr_el3.PRIbits = PRIORITY_BITS - 1;
6086022Sgblack@eecs.umich.edu          value = icc_ctlr_el3;
6096022Sgblack@eecs.umich.edu          break;
6106022Sgblack@eecs.umich.edu      }
61112749Sgiacomo.travaglini@arm.com
6126023Snate@binkert.org      // Hyp Control Register
6136022Sgblack@eecs.umich.edu      case MISCREG_ICH_HCR:
6146022Sgblack@eecs.umich.edu      case MISCREG_ICH_HCR_EL2:
6156023Snate@binkert.org        break;
6166022Sgblack@eecs.umich.edu
6176022Sgblack@eecs.umich.edu      // Hyp Active Priorities Group 0 Registers
6188888Sgeoffrey.blake@arm.com      case MISCREG_ICH_AP0R0:
61912749Sgiacomo.travaglini@arm.com      case MISCREG_ICH_AP0R0_EL2:
62012749Sgiacomo.travaglini@arm.com        break;
6219738Sandreas@sandberg.pp.se
6229738Sandreas@sandberg.pp.se      // only implemented if supporting 6 or more bits of priority
6239738Sandreas@sandberg.pp.se      case MISCREG_ICH_AP0R1:
6249738Sandreas@sandberg.pp.se      case MISCREG_ICH_AP0R1_EL2:
6257811Ssteve.reinhardt@amd.com      // only implemented if supporting 7 or more bits of priority
6264088Sbinkertn@umich.edu      case MISCREG_ICH_AP0R2:
6276022Sgblack@eecs.umich.edu      case MISCREG_ICH_AP0R2_EL2:
6286022Sgblack@eecs.umich.edu      // only implemented if supporting 7 or more bits of priority
6293838Shsul@eecs.umich.edu      case MISCREG_ICH_AP0R3:
6306022Sgblack@eecs.umich.edu      case MISCREG_ICH_AP0R3_EL2:
6313838Shsul@eecs.umich.edu        // Unimplemented registers are RAZ/WI
632        return 0;
633
634      // Hyp Active Priorities Group 1 Registers
635      case MISCREG_ICH_AP1R0:
636      case MISCREG_ICH_AP1R0_EL2:
637        break;
638
639      // only implemented if supporting 6 or more bits of priority
640      case MISCREG_ICH_AP1R1:
641      case MISCREG_ICH_AP1R1_EL2:
642      // only implemented if supporting 7 or more bits of priority
643      case MISCREG_ICH_AP1R2:
644      case MISCREG_ICH_AP1R2_EL2:
645      // only implemented if supporting 7 or more bits of priority
646      case MISCREG_ICH_AP1R3:
647      case MISCREG_ICH_AP1R3_EL2:
648        // Unimplemented registers are RAZ/WI
649        return 0;
650
651      // Maintenance Interrupt State Register
652      case MISCREG_ICH_MISR:
653      case MISCREG_ICH_MISR_EL2:
654        value = maintenanceInterruptStatus();
655        break;
656
657      // VGIC Type Register
658      case MISCREG_ICH_VTR:
659      case MISCREG_ICH_VTR_EL2: {
660        ICH_VTR_EL2 ich_vtr_el2 = value;
661
662        ich_vtr_el2.ListRegs = VIRTUAL_NUM_LIST_REGS - 1;
663        ich_vtr_el2.A3V = 1;
664        ich_vtr_el2.IDbits = 1;
665        ich_vtr_el2.PREbits = VIRTUAL_PREEMPTION_BITS - 1;
666        ich_vtr_el2.PRIbits = VIRTUAL_PRIORITY_BITS - 1;
667
668        value = ich_vtr_el2;
669        break;
670      }
671
672      // End of Interrupt Status Register
673      case MISCREG_ICH_EISR:
674      case MISCREG_ICH_EISR_EL2:
675        value = eoiMaintenanceInterruptStatus();
676        break;
677
678      // Empty List Register Status Register
679      case MISCREG_ICH_ELRSR:
680      case MISCREG_ICH_ELRSR_EL2:
681        value = 0;
682
683        for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
684            ICH_LR_EL2 ich_lr_el2 =
685                isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
686
687            if ((ich_lr_el2.State  == ICH_LR_EL2_STATE_INVALID) &&
688                (ich_lr_el2.HW || !ich_lr_el2.EOI)) {
689                value |= (1 << lr_idx);
690            }
691        }
692
693        break;
694
695      // List Registers
696      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15:
697        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
698        value = value >> 32;
699        break;
700
701      // List Registers
702      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15:
703        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
704        value = value & 0xffffffff;
705        break;
706
707      // List Registers
708      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2:
709        break;
710
711      // Virtual Machine Control Register
712      case MISCREG_ICH_VMCR:
713      case MISCREG_ICH_VMCR_EL2:
714        break;
715
716      default:
717        panic("Gicv3CPUInterface::readMiscReg(): unknown register %d (%s)",
718              misc_reg, miscRegName[misc_reg]);
719    }
720
721    DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): register %s value %#x\n",
722            miscRegName[misc_reg], value);
723    return value;
724}
725
726void
727Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val)
728{
729    bool do_virtual_update = false;
730    DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): register %s value %#x\n",
731            miscRegName[misc_reg], val);
732    bool hcr_fmo = getHCREL2FMO();
733    bool hcr_imo = getHCREL2IMO();
734
735    switch (misc_reg) {
736      // Active Priorities Group 1 Registers
737      case MISCREG_ICC_AP1R0:
738      case MISCREG_ICC_AP1R0_EL1:
739        if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
740            return isa->setMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1, val);
741        }
742
743        setBankedMiscReg(MISCREG_ICC_AP1R0_EL1, val);
744        return;
745
746      case MISCREG_ICC_AP1R1:
747      case MISCREG_ICC_AP1R1_EL1:
748
749        // only implemented if supporting 6 or more bits of priority
750      case MISCREG_ICC_AP1R2:
751      case MISCREG_ICC_AP1R2_EL1:
752
753        // only implemented if supporting 7 or more bits of priority
754      case MISCREG_ICC_AP1R3:
755      case MISCREG_ICC_AP1R3_EL1:
756        // only implemented if supporting 7 or more bits of priority
757        break;
758
759      // Active Priorities Group 0 Registers
760      case MISCREG_ICC_AP0R0:
761      case MISCREG_ICC_AP0R0_EL1:
762        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
763            return isa->setMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1, val);
764        }
765
766        break;
767
768      case MISCREG_ICC_AP0R1:
769      case MISCREG_ICC_AP0R1_EL1:
770
771        // only implemented if supporting 6 or more bits of priority
772      case MISCREG_ICC_AP0R2:
773      case MISCREG_ICC_AP0R2_EL1:
774
775        // only implemented if supporting 7 or more bits of priority
776      case MISCREG_ICC_AP0R3:
777      case MISCREG_ICC_AP0R3_EL1:
778        // only implemented if supporting 7 or more bits of priority
779        break;
780
781      // End Of Interrupt Register 0
782      case MISCREG_ICC_EOIR0:
783      case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0
784          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
785              return setMiscReg(MISCREG_ICV_EOIR0_EL1, val);
786          }
787
788          int int_id = val & 0xffffff;
789
790          // avoid activation for special interrupts
791          if (int_id >= Gicv3::INTID_SECURE &&
792              int_id <= Gicv3::INTID_SPURIOUS) {
793              return;
794          }
795
796          Gicv3::GroupId group = Gicv3::G0S;
797
798          if (highestActiveGroup() != group) {
799              return;
800          }
801
802          dropPriority(group);
803
804          if (!isEOISplitMode()) {
805              deactivateIRQ(int_id, group);
806          }
807
808          break;
809      }
810
811      // Virtual End Of Interrupt Register 0
812      case MISCREG_ICV_EOIR0_EL1: {
813          int int_id = val & 0xffffff;
814
815          // avoid deactivation for special interrupts
816          if (int_id >= Gicv3::INTID_SECURE &&
817                  int_id <= Gicv3::INTID_SPURIOUS) {
818              return;
819          }
820
821          uint8_t drop_prio = virtualDropPriority();
822
823          if (drop_prio == 0xff) {
824              return;
825          }
826
827          int lr_idx = virtualFindActive(int_id);
828
829          if (lr_idx < 0) {
830              // No LR found matching
831              virtualIncrementEOICount();
832          } else {
833              ICH_LR_EL2 ich_lr_el2 =
834                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
835              Gicv3::GroupId lr_group =
836                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
837              uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8;
838
839              if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) {
840                  //if (!virtualIsEOISplitMode())
841                  {
842                      virtualDeactivateIRQ(lr_idx);
843                  }
844              }
845          }
846
847          virtualUpdate();
848          break;
849      }
850
851      // End Of Interrupt Register 1
852      case MISCREG_ICC_EOIR1:
853      case MISCREG_ICC_EOIR1_EL1: {
854          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
855              return setMiscReg(MISCREG_ICV_EOIR1_EL1, val);
856          }
857
858          int int_id = val & 0xffffff;
859
860          // avoid deactivation for special interrupts
861          if (int_id >= Gicv3::INTID_SECURE &&
862              int_id <= Gicv3::INTID_SPURIOUS) {
863              return;
864          }
865
866          Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS;
867
868          if (highestActiveGroup() == Gicv3::G0S) {
869              return;
870          }
871
872          if (distributor->DS == 0) {
873              if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) {
874                  return;
875              } else if (highestActiveGroup() == Gicv3::G1NS &&
876                         !(!inSecureState() or (currEL() == EL3))) {
877                  return;
878              }
879          }
880
881          dropPriority(group);
882
883          if (!isEOISplitMode()) {
884              deactivateIRQ(int_id, group);
885          }
886
887          break;
888      }
889
890      // Virtual End Of Interrupt Register 1
891      case MISCREG_ICV_EOIR1_EL1: {
892          int int_id = val & 0xffffff;
893
894          // avoid deactivation for special interrupts
895          if (int_id >= Gicv3::INTID_SECURE &&
896              int_id <= Gicv3::INTID_SPURIOUS) {
897              return;
898          }
899
900          uint8_t drop_prio = virtualDropPriority();
901
902          if (drop_prio == 0xff) {
903              return;
904          }
905
906          int lr_idx = virtualFindActive(int_id);
907
908          if (lr_idx < 0) {
909              // No matching LR found
910              virtualIncrementEOICount();
911          } else {
912              ICH_LR_EL2 ich_lr_el2 =
913                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
914              Gicv3::GroupId lr_group =
915                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
916              uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8;
917
918              if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) {
919                  if (!virtualIsEOISplitMode()) {
920                      virtualDeactivateIRQ(lr_idx);
921                  }
922              }
923          }
924
925          virtualUpdate();
926          break;
927      }
928
929      // Deactivate Interrupt Register
930      case MISCREG_ICC_DIR:
931      case MISCREG_ICC_DIR_EL1: {
932          if ((currEL() == EL1) && !inSecureState() &&
933              (hcr_imo || hcr_fmo)) {
934              return setMiscReg(MISCREG_ICV_DIR_EL1, val);
935          }
936
937          int int_id = val & 0xffffff;
938
939          // The following checks are as per spec pseudocode
940          // aarch64/support/ICC_DIR_EL1
941
942          // Check for spurious ID
943          if (int_id >= Gicv3::INTID_SECURE) {
944              return;
945          }
946
947          // EOI mode is not set, so don't deactivate
948          if (!isEOISplitMode()) {
949              return;
950          }
951
952          Gicv3::GroupId group =
953              int_id >= 32 ? distributor->getIntGroup(int_id) :
954              redistributor->getIntGroup(int_id);
955          bool irq_is_grp0 = group == Gicv3::G0S;
956          bool single_sec_state = distributor->DS;
957          bool irq_is_secure = !single_sec_state && (group != Gicv3::G1NS);
958          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
959          bool route_fiq_to_el3 = scr_el3.fiq;
960          bool route_irq_to_el3 = scr_el3.irq;
961          bool route_fiq_to_el2 = hcr_fmo;
962          bool route_irq_to_el2 = hcr_imo;
963
964          switch (currEL()) {
965            case EL3:
966              break;
967
968            case EL2:
969              if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) {
970                  break;
971              }
972
973              if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) {
974                  break;
975              }
976
977              return;
978
979            case EL1:
980              if (!isSecureBelowEL3()) {
981                  if (single_sec_state && irq_is_grp0 &&
982                      !route_fiq_to_el3 && !route_fiq_to_el2) {
983                      break;
984                  }
985
986                  if (!irq_is_secure && !irq_is_grp0 &&
987                      !route_irq_to_el3 && !route_irq_to_el2) {
988                      break;
989                  }
990              } else {
991                  if (irq_is_grp0 && !route_fiq_to_el3) {
992                      break;
993                  }
994
995                  if (!irq_is_grp0 &&
996                      (!irq_is_secure || !single_sec_state) &&
997                      !route_irq_to_el3) {
998                      break;
999                  }
1000              }
1001
1002              return;
1003
1004            default:
1005              break;
1006          }
1007
1008          deactivateIRQ(int_id, group);
1009          break;
1010      }
1011
1012      // Deactivate Virtual Interrupt Register
1013      case MISCREG_ICV_DIR_EL1: {
1014          int int_id = val & 0xffffff;
1015
1016          // avoid deactivation for special interrupts
1017          if (int_id >= Gicv3::INTID_SECURE &&
1018              int_id <= Gicv3::INTID_SPURIOUS) {
1019              return;
1020          }
1021
1022          if (!virtualIsEOISplitMode()) {
1023              return;
1024          }
1025
1026          int lr_idx = virtualFindActive(int_id);
1027
1028          if (lr_idx < 0) {
1029              // No matching LR found
1030              virtualIncrementEOICount();
1031          } else {
1032              virtualDeactivateIRQ(lr_idx);
1033          }
1034
1035          virtualUpdate();
1036          break;
1037      }
1038
1039      // Binary Point Register 0
1040      case MISCREG_ICC_BPR0:
1041      case MISCREG_ICC_BPR0_EL1: {
1042        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1043            return setMiscReg(MISCREG_ICV_BPR0_EL1, val);
1044        }
1045        break;
1046      }
1047      // Binary Point Register 1
1048      case MISCREG_ICC_BPR1:
1049      case MISCREG_ICC_BPR1_EL1: {
1050        if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1051            return setMiscReg(MISCREG_ICV_BPR1_EL1, val);
1052        }
1053
1054        val &= 0x7;
1055
1056        if (isSecureBelowEL3()) {
1057            // group == Gicv3::G1S
1058            ICC_CTLR_EL1 icc_ctlr_el1_s =
1059                isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1060
1061            val = val > GIC_MIN_BPR ? val : GIC_MIN_BPR;
1062            if (haveEL(EL3) && !isEL3OrMon() && icc_ctlr_el1_s.CBPR) {
1063                isa->setMiscRegNoEffect(MISCREG_ICC_BPR0_EL1, val);
1064            } else {
1065                isa->setMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_S, val);
1066            }
1067            return;
1068        } else {
1069            // group == Gicv3::G1NS
1070            ICC_CTLR_EL1 icc_ctlr_el1_ns =
1071                isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1072
1073            val = val > GIC_MIN_BPR_NS ? val : GIC_MIN_BPR_NS;
1074            if (haveEL(EL3) && !isEL3OrMon() && icc_ctlr_el1_ns.CBPR) {
1075                // Non secure writes from EL1 and EL2 are ignored
1076            } else {
1077                isa->setMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_NS, val);
1078            }
1079            return;
1080        }
1081
1082        break;
1083      }
1084
1085      // Virtual Binary Point Register 0
1086      case MISCREG_ICV_BPR0_EL1:
1087      // Virtual Binary Point Register 1
1088      case MISCREG_ICV_BPR1_EL1: {
1089          Gicv3::GroupId group =
1090              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
1091          ICH_VMCR_EL2 ich_vmcr_el2 =
1092              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1093
1094          if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
1095              // BPR0 + 1 saturated to 7, WI
1096              return;
1097          }
1098
1099          uint8_t min_VPBR = 7 - VIRTUAL_PREEMPTION_BITS;
1100
1101          if (group != Gicv3::G0S) {
1102              min_VPBR++;
1103          }
1104
1105          if (val < min_VPBR) {
1106              val = min_VPBR;
1107          }
1108
1109          if (group == Gicv3::G0S) {
1110              ich_vmcr_el2.VBPR0 = val;
1111          } else {
1112              ich_vmcr_el2.VBPR1 = val;
1113          }
1114
1115          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1116          do_virtual_update = true;
1117          break;
1118      }
1119
1120      // Control Register EL1
1121      case MISCREG_ICC_CTLR:
1122      case MISCREG_ICC_CTLR_EL1: {
1123          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
1124              return setMiscReg(MISCREG_ICV_CTLR_EL1, val);
1125          }
1126
1127          /*
1128           * ExtRange is RO.
1129           * RSS is RO.
1130           * A3V is RO.
1131           * SEIS is RO.
1132           * IDbits is RO.
1133           * PRIbits is RO.
1134           */
1135          ICC_CTLR_EL1 requested_icc_ctlr_el1 = val;
1136          ICC_CTLR_EL1 icc_ctlr_el1 =
1137              readBankedMiscReg(MISCREG_ICC_CTLR_EL1);
1138
1139          ICC_CTLR_EL3 icc_ctlr_el3 =
1140              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1141
1142          // The following could be refactored but it is following
1143          // spec description section 9.2.6 point by point.
1144
1145          // PMHE
1146          if (haveEL(EL3)) {
1147              // PMHE is alias of ICC_CTLR_EL3.PMHE
1148
1149              if (distributor->DS == 0) {
1150                  // PMHE is RO
1151              } else if (distributor->DS == 1) {
1152                  // PMHE is RW
1153                  icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE;
1154                  icc_ctlr_el3.PMHE = icc_ctlr_el1.PMHE;
1155              }
1156          } else {
1157              // PMHE is RW (by implementation choice)
1158              icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE;
1159          }
1160
1161          // EOImode
1162          icc_ctlr_el1.EOImode = requested_icc_ctlr_el1.EOImode;
1163
1164          if (inSecureState()) {
1165              // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1S
1166              icc_ctlr_el3.EOImode_EL1S = icc_ctlr_el1.EOImode;
1167          } else {
1168              // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1NS
1169              icc_ctlr_el3.EOImode_EL1NS = icc_ctlr_el1.EOImode;
1170          }
1171
1172          // CBPR
1173          if (haveEL(EL3)) {
1174              // CBPR is alias of ICC_CTLR_EL3.CBPR_EL1{S,NS}
1175
1176              if (distributor->DS == 0) {
1177                  // CBPR is RO
1178              } else {
1179                  // CBPR is RW
1180                  icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR;
1181
1182                  if (inSecureState()) {
1183                      icc_ctlr_el3.CBPR_EL1S = icc_ctlr_el1.CBPR;
1184                  } else {
1185                      icc_ctlr_el3.CBPR_EL1NS = icc_ctlr_el1.CBPR;
1186                  }
1187              }
1188          } else {
1189              // CBPR is RW
1190              icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR;
1191          }
1192
1193          isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL3, icc_ctlr_el3);
1194
1195          setBankedMiscReg(MISCREG_ICC_CTLR_EL1, icc_ctlr_el1);
1196          return;
1197      }
1198
1199      // Virtual Control Register
1200      case MISCREG_ICV_CTLR_EL1: {
1201         ICV_CTLR_EL1 requested_icv_ctlr_el1 = val;
1202         ICV_CTLR_EL1 icv_ctlr_el1 =
1203             isa->readMiscRegNoEffect(MISCREG_ICV_CTLR_EL1);
1204         icv_ctlr_el1.EOImode = requested_icv_ctlr_el1.EOImode;
1205         icv_ctlr_el1.CBPR = requested_icv_ctlr_el1.CBPR;
1206         val = icv_ctlr_el1;
1207
1208         // Aliases
1209         // ICV_CTLR_EL1.CBPR aliases ICH_VMCR_EL2.VCBPR.
1210         // ICV_CTLR_EL1.EOImode aliases ICH_VMCR_EL2.VEOIM.
1211         ICH_VMCR_EL2 ich_vmcr_el2 =
1212             isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1213         ich_vmcr_el2.VCBPR = icv_ctlr_el1.CBPR;
1214         ich_vmcr_el2.VEOIM = icv_ctlr_el1.EOImode;
1215         isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1216         break;
1217      }
1218
1219      // Control Register EL3
1220      case MISCREG_ICC_MCTLR:
1221      case MISCREG_ICC_CTLR_EL3: {
1222          /*
1223           * ExtRange is RO.
1224           * RSS is RO.
1225           * nDS is RO.
1226           * A3V is RO.
1227           * SEIS is RO.
1228           * IDbits is RO.
1229           * PRIbits is RO.
1230           * PMHE is RAO/WI, priority-based routing is always used.
1231           */
1232          ICC_CTLR_EL3 requested_icc_ctlr_el3 = val;
1233
1234          // Aliases
1235          if (haveEL(EL3))
1236          {
1237              ICC_CTLR_EL1 icc_ctlr_el1_s =
1238                  isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1239              ICC_CTLR_EL1 icc_ctlr_el1_ns =
1240                  isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1241
1242              // ICC_CTLR_EL1(NS).EOImode is an alias of
1243              // ICC_CTLR_EL3.EOImode_EL1NS
1244              icc_ctlr_el1_ns.EOImode = requested_icc_ctlr_el3.EOImode_EL1NS;
1245              // ICC_CTLR_EL1(S).EOImode is an alias of
1246              // ICC_CTLR_EL3.EOImode_EL1S
1247              icc_ctlr_el1_s.EOImode = requested_icc_ctlr_el3.EOImode_EL1S;
1248              // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS
1249              icc_ctlr_el1_ns.CBPR = requested_icc_ctlr_el3.CBPR_EL1NS;
1250              // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S
1251              icc_ctlr_el1_s.CBPR = requested_icc_ctlr_el3.CBPR_EL1S;
1252
1253              isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s);
1254              isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS,
1255                                      icc_ctlr_el1_ns);
1256          }
1257
1258          ICC_CTLR_EL3 icc_ctlr_el3 =
1259              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1260
1261          icc_ctlr_el3.RM = requested_icc_ctlr_el3.RM;
1262          icc_ctlr_el3.EOImode_EL1NS = requested_icc_ctlr_el3.EOImode_EL1NS;
1263          icc_ctlr_el3.EOImode_EL1S = requested_icc_ctlr_el3.EOImode_EL1S;
1264          icc_ctlr_el3.EOImode_EL3 = requested_icc_ctlr_el3.EOImode_EL3;
1265          icc_ctlr_el3.CBPR_EL1NS = requested_icc_ctlr_el3.CBPR_EL1NS;
1266          icc_ctlr_el3.CBPR_EL1S = requested_icc_ctlr_el3.CBPR_EL1S;
1267
1268          val = icc_ctlr_el3;
1269          break;
1270      }
1271
1272      // Priority Mask Register
1273      case MISCREG_ICC_PMR:
1274      case MISCREG_ICC_PMR_EL1: {
1275          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
1276              return setMiscReg(MISCREG_ICV_PMR_EL1, val);
1277          }
1278
1279          val &= 0xff;
1280          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
1281
1282          if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) {
1283              // Spec section 4.8.1
1284              // For Non-secure access to ICC_PMR_EL1 SCR_EL3.FIQ == 1:
1285              RegVal old_icc_pmr_el1 =
1286                  isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1);
1287
1288              if (!(old_icc_pmr_el1 & 0x80)) {
1289                  // If the current priority mask value is in the range of
1290                  // 0x00-0x7F then WI
1291                  return;
1292              }
1293
1294              // If the current priority mask value is in the range of
1295              // 0x80-0xFF then a write access to ICC_PMR_EL1 succeeds,
1296              // based on the Non-secure read of the priority mask value
1297              // written to the register.
1298
1299              val = (val >> 1) | 0x80;
1300          }
1301
1302          val &= ~0U << (8 - PRIORITY_BITS);
1303          break;
1304      }
1305
1306      case MISCREG_ICV_PMR_EL1: { // Priority Mask Register
1307          ICH_VMCR_EL2 ich_vmcr_el2 =
1308             isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1309          ich_vmcr_el2.VPMR = val & 0xff;
1310
1311          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1312          virtualUpdate();
1313          return;
1314      }
1315
1316      // Interrupt Group 0 Enable Register EL1
1317      case MISCREG_ICC_IGRPEN0:
1318      case MISCREG_ICC_IGRPEN0_EL1: {
1319          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1320              return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val);
1321          }
1322
1323          break;
1324      }
1325
1326      // Virtual Interrupt Group 0 Enable register
1327      case MISCREG_ICV_IGRPEN0_EL1: {
1328          bool enable = val & 0x1;
1329          ICH_VMCR_EL2 ich_vmcr_el2 =
1330              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1331          ich_vmcr_el2.VENG0 = enable;
1332          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1333          virtualUpdate();
1334          return;
1335      }
1336
1337      // Interrupt Group 1 Enable register EL1
1338      case MISCREG_ICC_IGRPEN1:
1339      case MISCREG_ICC_IGRPEN1_EL1: {
1340          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1341              return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val);
1342          }
1343
1344          if (haveEL(EL3)) {
1345              ICC_IGRPEN1_EL1 icc_igrpen1_el1 = val;
1346              ICC_IGRPEN1_EL3 icc_igrpen1_el3 =
1347                  isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3);
1348
1349              if (inSecureState()) {
1350                  // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1S
1351                  icc_igrpen1_el3.EnableGrp1S = icc_igrpen1_el1.Enable;
1352              } else {
1353                  // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1NS
1354                  icc_igrpen1_el3.EnableGrp1NS = icc_igrpen1_el1.Enable;
1355              }
1356
1357              isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3,
1358                                      icc_igrpen1_el3);
1359          }
1360
1361          break;
1362      }
1363
1364      // Virtual Interrupt Group 1 Enable register
1365      case MISCREG_ICV_IGRPEN1_EL1: {
1366          bool enable = val & 0x1;
1367          ICH_VMCR_EL2 ich_vmcr_el2 =
1368              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1369          ich_vmcr_el2.VENG1 = enable;
1370          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1371          virtualUpdate();
1372          return;
1373      }
1374
1375      // Interrupt Group 1 Enable register
1376      case MISCREG_ICC_MGRPEN1:
1377      case MISCREG_ICC_IGRPEN1_EL3: {
1378          ICC_IGRPEN1_EL3 icc_igrpen1_el3 = val;
1379          ICC_IGRPEN1_EL1 icc_igrpen1_el1 =
1380              isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1);
1381
1382          if (inSecureState()) {
1383              // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1S
1384              icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1S;
1385          } else {
1386              // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1NS
1387              icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1NS;
1388          }
1389
1390          isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1, icc_igrpen1_el1);
1391          break;
1392      }
1393
1394      // Software Generated Interrupt Group 0 Register
1395      case MISCREG_ICC_SGI0R:
1396      case MISCREG_ICC_SGI0R_EL1:
1397        generateSGI(val, Gicv3::G0S);
1398        break;
1399
1400      // Software Generated Interrupt Group 1 Register
1401      case MISCREG_ICC_SGI1R:
1402      case MISCREG_ICC_SGI1R_EL1: {
1403        Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS;
1404
1405        generateSGI(val, group);
1406        break;
1407      }
1408
1409      // Alias Software Generated Interrupt Group 1 Register
1410      case MISCREG_ICC_ASGI1R:
1411      case MISCREG_ICC_ASGI1R_EL1: {
1412        Gicv3::GroupId group = inSecureState() ? Gicv3::G1NS : Gicv3::G1S;
1413
1414        generateSGI(val, group);
1415        break;
1416      }
1417
1418      // System Register Enable Register EL1
1419      case MISCREG_ICC_SRE:
1420      case MISCREG_ICC_SRE_EL1:
1421      // System Register Enable Register EL2
1422      case MISCREG_ICC_HSRE:
1423      case MISCREG_ICC_SRE_EL2:
1424      // System Register Enable Register EL3
1425      case MISCREG_ICC_MSRE:
1426      case MISCREG_ICC_SRE_EL3:
1427        // All bits are RAO/WI
1428        return;
1429
1430      // Hyp Control Register
1431      case MISCREG_ICH_HCR:
1432      case MISCREG_ICH_HCR_EL2: {
1433        ICH_HCR_EL2 requested_ich_hcr_el2 = val;
1434        ICH_HCR_EL2 ich_hcr_el2 =
1435            isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1436
1437        if (requested_ich_hcr_el2.EOIcount >= ich_hcr_el2.EOIcount)
1438        {
1439            // EOIcount - Permitted behaviors are:
1440            // - Increment EOIcount.
1441            // - Leave EOIcount unchanged.
1442            ich_hcr_el2.EOIcount = requested_ich_hcr_el2.EOIcount;
1443        }
1444
1445        ich_hcr_el2.TDIR = requested_ich_hcr_el2.TDIR;
1446        ich_hcr_el2.TSEI = requested_ich_hcr_el2.TSEI;
1447        ich_hcr_el2.TALL1 = requested_ich_hcr_el2.TALL1;;
1448        ich_hcr_el2.TALL0 = requested_ich_hcr_el2.TALL0;;
1449        ich_hcr_el2.TC = requested_ich_hcr_el2.TC;
1450        ich_hcr_el2.VGrp1DIE = requested_ich_hcr_el2.VGrp1DIE;
1451        ich_hcr_el2.VGrp1EIE = requested_ich_hcr_el2.VGrp1EIE;
1452        ich_hcr_el2.VGrp0DIE = requested_ich_hcr_el2.VGrp0DIE;
1453        ich_hcr_el2.VGrp0EIE = requested_ich_hcr_el2.VGrp0EIE;
1454        ich_hcr_el2.NPIE = requested_ich_hcr_el2.NPIE;
1455        ich_hcr_el2.LRENPIE = requested_ich_hcr_el2.LRENPIE;
1456        ich_hcr_el2.UIE = requested_ich_hcr_el2.UIE;
1457        ich_hcr_el2.En = requested_ich_hcr_el2.En;
1458        val = ich_hcr_el2;
1459        do_virtual_update = true;
1460        break;
1461      }
1462
1463      // List Registers
1464      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: {
1465        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
1466        ICH_LRC requested_ich_lrc = val;
1467        ICH_LRC ich_lrc = isa->readMiscRegNoEffect(misc_reg);
1468
1469        ich_lrc.State = requested_ich_lrc.State;
1470        ich_lrc.HW = requested_ich_lrc.HW;
1471        ich_lrc.Group = requested_ich_lrc.Group;
1472
1473        // Priority, bits [23:16]
1474        // At least five bits must be implemented.
1475        // Unimplemented bits are RES0 and start from bit[16] up to bit[18].
1476        // We implement 5 bits.
1477        ich_lrc.Priority = (requested_ich_lrc.Priority & 0xf8) |
1478                           (ich_lrc.Priority & 0x07);
1479
1480        // pINTID, bits [12:0]
1481        // When ICH_LR<n>.HW is 0 this field has the following meaning:
1482        // - Bits[12:10] : RES0.
1483        // - Bit[9] : EOI.
1484        // - Bits[8:0] : RES0.
1485        // When ICH_LR<n>.HW is 1:
1486        // - This field is only required to implement enough bits to hold a
1487        // valid value for the implemented INTID size. Any unused higher
1488        // order bits are RES0.
1489        if (requested_ich_lrc.HW == 0) {
1490            ich_lrc.EOI = requested_ich_lrc.EOI;
1491        } else {
1492            ich_lrc.pINTID = requested_ich_lrc.pINTID;
1493        }
1494
1495        val = ich_lrc;
1496        do_virtual_update = true;
1497        break;
1498      }
1499
1500      // List Registers
1501      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: {
1502          // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
1503          RegVal old_val = isa->readMiscRegNoEffect(misc_reg);
1504          val = (old_val & 0xffffffff00000000) | (val & 0xffffffff);
1505          do_virtual_update = true;
1506          break;
1507      }
1508
1509      // List Registers
1510      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64
1511          ICH_LR_EL2 requested_ich_lr_el2 = val;
1512          ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(misc_reg);
1513
1514          ich_lr_el2.State = requested_ich_lr_el2.State;
1515          ich_lr_el2.HW = requested_ich_lr_el2.HW;
1516          ich_lr_el2.Group = requested_ich_lr_el2.Group;
1517
1518          // Priority, bits [55:48]
1519          // At least five bits must be implemented.
1520          // Unimplemented bits are RES0 and start from bit[48] up to bit[50].
1521          // We implement 5 bits.
1522          ich_lr_el2.Priority = (requested_ich_lr_el2.Priority & 0xf8) |
1523                                (ich_lr_el2.Priority & 0x07);
1524
1525          // pINTID, bits [44:32]
1526          // When ICH_LR<n>_EL2.HW is 0 this field has the following meaning:
1527          // - Bits[44:42] : RES0.
1528          // - Bit[41] : EOI.
1529          // - Bits[40:32] : RES0.
1530          // When ICH_LR<n>_EL2.HW is 1:
1531          // - This field is only required to implement enough bits to hold a
1532          // valid value for the implemented INTID size. Any unused higher
1533          // order bits are RES0.
1534          if (requested_ich_lr_el2.HW == 0) {
1535              ich_lr_el2.EOI = requested_ich_lr_el2.EOI;
1536          } else {
1537              ich_lr_el2.pINTID = requested_ich_lr_el2.pINTID;
1538          }
1539
1540          // vINTID, bits [31:0]
1541          // It is IMPLEMENTATION DEFINED how many bits are implemented,
1542          // though at least 16 bits must be implemented.
1543          // Unimplemented bits are RES0.
1544          ich_lr_el2.vINTID = requested_ich_lr_el2.vINTID;
1545
1546          val = ich_lr_el2;
1547          do_virtual_update = true;
1548          break;
1549      }
1550
1551      // Virtual Machine Control Register
1552      case MISCREG_ICH_VMCR:
1553      case MISCREG_ICH_VMCR_EL2: {
1554          ICH_VMCR_EL2 requested_ich_vmcr_el2 = val;
1555          ICH_VMCR_EL2 ich_vmcr_el2 =
1556              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1557          ich_vmcr_el2.VPMR = requested_ich_vmcr_el2.VPMR;
1558          uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS;
1559
1560          if (requested_ich_vmcr_el2.VBPR0 < min_vpr0) {
1561              ich_vmcr_el2.VBPR0 = min_vpr0;
1562          } else {
1563              ich_vmcr_el2.VBPR0 = requested_ich_vmcr_el2.VBPR0;
1564          }
1565
1566          uint8_t min_vpr1 = min_vpr0 + 1;
1567
1568          if (requested_ich_vmcr_el2.VBPR1 < min_vpr1) {
1569              ich_vmcr_el2.VBPR1 = min_vpr1;
1570          } else {
1571              ich_vmcr_el2.VBPR1 = requested_ich_vmcr_el2.VBPR1;
1572          }
1573
1574          ich_vmcr_el2.VEOIM = requested_ich_vmcr_el2.VEOIM;
1575          ich_vmcr_el2.VCBPR = requested_ich_vmcr_el2.VCBPR;
1576          ich_vmcr_el2.VENG1 = requested_ich_vmcr_el2.VENG1;
1577          ich_vmcr_el2.VENG0 = requested_ich_vmcr_el2.VENG0;
1578          val = ich_vmcr_el2;
1579          break;
1580      }
1581
1582      // Hyp Active Priorities Group 0 Registers
1583      case MISCREG_ICH_AP0R0:
1584      case MISCREG_ICH_AP0R0_EL2:
1585        break;
1586
1587      // only implemented if supporting 6 or more bits of priority
1588      case MISCREG_ICH_AP0R1:
1589      case MISCREG_ICH_AP0R1_EL2:
1590      // only implemented if supporting 7 or more bits of priority
1591      case MISCREG_ICH_AP0R2:
1592      case MISCREG_ICH_AP0R2_EL2:
1593      // only implemented if supporting 7 or more bits of priority
1594      case MISCREG_ICH_AP0R3:
1595      case MISCREG_ICH_AP0R3_EL2:
1596        // Unimplemented registers are RAZ/WI
1597        return;
1598
1599      // Hyp Active Priorities Group 1 Registers
1600      case MISCREG_ICH_AP1R0:
1601      case MISCREG_ICH_AP1R0_EL2:
1602        break;
1603
1604      // only implemented if supporting 6 or more bits of priority
1605      case MISCREG_ICH_AP1R1:
1606      case MISCREG_ICH_AP1R1_EL2:
1607      // only implemented if supporting 7 or more bits of priority
1608      case MISCREG_ICH_AP1R2:
1609      case MISCREG_ICH_AP1R2_EL2:
1610      // only implemented if supporting 7 or more bits of priority
1611      case MISCREG_ICH_AP1R3:
1612      case MISCREG_ICH_AP1R3_EL2:
1613        // Unimplemented registers are RAZ/WI
1614        return;
1615
1616      default:
1617        panic("Gicv3CPUInterface::setMiscReg(): unknown register %d (%s)",
1618              misc_reg, miscRegName[misc_reg]);
1619    }
1620
1621    isa->setMiscRegNoEffect(misc_reg, val);
1622
1623    if (do_virtual_update) {
1624        virtualUpdate();
1625    }
1626}
1627
1628RegVal
1629Gicv3CPUInterface::readBankedMiscReg(MiscRegIndex misc_reg) const
1630{
1631    return isa->readMiscRegNoEffect(
1632        isa->snsBankedIndex64(misc_reg, !isSecureBelowEL3()));
1633}
1634
1635void
1636Gicv3CPUInterface::setBankedMiscReg(MiscRegIndex misc_reg, RegVal val) const
1637{
1638    isa->setMiscRegNoEffect(
1639        isa->snsBankedIndex64(misc_reg, !isSecureBelowEL3()), val);
1640}
1641
1642int
1643Gicv3CPUInterface::virtualFindActive(uint32_t int_id) const
1644{
1645    for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
1646        ICH_LR_EL2 ich_lr_el2 =
1647            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1648
1649        if (((ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE) ||
1650             (ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE_PENDING)) &&
1651            (ich_lr_el2.vINTID == int_id)) {
1652            return lr_idx;
1653        }
1654    }
1655
1656    return -1;
1657}
1658
1659uint32_t
1660Gicv3CPUInterface::getHPPIR0() const
1661{
1662    if (hppi.prio == 0xff || !groupEnabled(hppi.group)) {
1663        return Gicv3::INTID_SPURIOUS;
1664    }
1665
1666    bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS;
1667
1668    if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) {
1669        // interrupt for the other state pending
1670        return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE;
1671    }
1672
1673    if ((hppi.group != Gicv3::G0S)) { // && !isEL3OrMon())
1674        return Gicv3::INTID_SPURIOUS;
1675    }
1676
1677    if (irq_is_secure && !inSecureState()) {
1678        // Secure interrupts not visible in Non-secure
1679        return Gicv3::INTID_SPURIOUS;
1680    }
1681
1682    return hppi.intid;
1683}
1684
1685uint32_t
1686Gicv3CPUInterface::getHPPIR1() const
1687{
1688    if (hppi.prio == 0xff || !groupEnabled(hppi.group)) {
1689        return Gicv3::INTID_SPURIOUS;
1690    }
1691
1692    ICC_CTLR_EL3 icc_ctlr_el3 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1693    if ((currEL() == EL3) && icc_ctlr_el3.RM) {
1694        if (hppi.group == Gicv3::G0S) {
1695            return Gicv3::INTID_SECURE;
1696        } else if (hppi.group == Gicv3::G1NS) {
1697            return Gicv3::INTID_NONSECURE;
1698        }
1699    }
1700
1701    if (hppi.group == Gicv3::G0S) {
1702        return Gicv3::INTID_SPURIOUS;
1703    }
1704
1705    bool irq_is_secure = (distributor->DS == 0) && (hppi.group != Gicv3::G1NS);
1706
1707    if (irq_is_secure) {
1708        if (!inSecureState()) {
1709            // Secure interrupts not visible in Non-secure
1710            return Gicv3::INTID_SPURIOUS;
1711        }
1712    } else if (!isEL3OrMon() && inSecureState()) {
1713        // Group 1 non-secure interrupts not visible in Secure EL1
1714        return Gicv3::INTID_SPURIOUS;
1715    }
1716
1717    return hppi.intid;
1718}
1719
1720void
1721Gicv3CPUInterface::dropPriority(Gicv3::GroupId group)
1722{
1723    int apr_misc_reg = 0;
1724
1725    switch (group) {
1726      case Gicv3::G0S:
1727        apr_misc_reg = MISCREG_ICC_AP0R0_EL1;
1728        break;
1729      case Gicv3::G1S:
1730        apr_misc_reg = MISCREG_ICC_AP1R0_EL1_S;
1731        break;
1732      case Gicv3::G1NS:
1733        apr_misc_reg = MISCREG_ICC_AP1R0_EL1_NS;
1734        break;
1735      default:
1736        panic("Invalid Gicv3::GroupId");
1737    }
1738
1739    RegVal apr = isa->readMiscRegNoEffect(apr_misc_reg);
1740
1741    if (apr) {
1742        apr &= apr - 1;
1743        isa->setMiscRegNoEffect(apr_misc_reg, apr);
1744    }
1745
1746    update();
1747}
1748
1749uint8_t
1750Gicv3CPUInterface::virtualDropPriority()
1751{
1752    int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5);
1753
1754    for (int i = 0; i < apr_max; i++) {
1755        RegVal vapr0 = isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i);
1756        RegVal vapr1 = isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
1757
1758        if (!vapr0 && !vapr1) {
1759            continue;
1760        }
1761
1762        int vapr0_count = ctz32(vapr0);
1763        int vapr1_count = ctz32(vapr1);
1764
1765        if (vapr0_count <= vapr1_count) {
1766            vapr0 &= vapr0 - 1;
1767            isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0);
1768            return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1);
1769        } else {
1770            vapr1 &= vapr1 - 1;
1771            isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1);
1772            return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1);
1773        }
1774    }
1775
1776    return 0xff;
1777}
1778
1779void
1780Gicv3CPUInterface::generateSGI(RegVal val, Gicv3::GroupId group)
1781{
1782    uint8_t aff3 = bits(val, 55, 48);
1783    uint8_t aff2 = bits(val, 39, 32);
1784    uint8_t aff1 = bits(val, 23, 16);;
1785    uint16_t target_list = bits(val, 15, 0);
1786    uint32_t int_id = bits(val, 27, 24);
1787    bool irm = bits(val, 40, 40);
1788    uint8_t rs = bits(val, 47, 44);
1789
1790    bool ns = !inSecureState();
1791
1792    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1793        Gicv3Redistributor * redistributor_i =
1794            gic->getRedistributor(i);
1795        uint32_t affinity_i = redistributor_i->getAffinity();
1796
1797        if (irm) {
1798            // Interrupts routed to all PEs in the system,
1799            // excluding "self"
1800            if (affinity_i == redistributor->getAffinity()) {
1801                continue;
1802            }
1803        } else {
1804            // Interrupts routed to the PEs specified by
1805            // Aff3.Aff2.Aff1.<target list>
1806            if ((affinity_i >> 8) !=
1807                ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) {
1808                continue;
1809            }
1810
1811            uint8_t aff0_i = bits(affinity_i, 7, 0);
1812
1813            if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 &&
1814                ((0x1 << (aff0_i - rs * 16)) & target_list))) {
1815                continue;
1816            }
1817        }
1818
1819        redistributor_i->sendSGI(int_id, group, ns);
1820    }
1821}
1822
1823void
1824Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
1825{
1826    // Update active priority registers.
1827    uint32_t prio = hppi.prio & 0xf8;
1828    int apr_bit = prio >> (8 - PRIORITY_BITS);
1829    int reg_bit = apr_bit % 32;
1830
1831    int apr_idx = 0;
1832    switch (group) {
1833      case Gicv3::G0S:
1834        apr_idx = MISCREG_ICC_AP0R0_EL1;
1835        break;
1836      case Gicv3::G1S:
1837        apr_idx = MISCREG_ICC_AP1R0_EL1_S;
1838        break;
1839      case Gicv3::G1NS:
1840        apr_idx = MISCREG_ICC_AP1R0_EL1_NS;
1841        break;
1842      default:
1843        panic("Invalid Gicv3::GroupId");
1844    }
1845
1846    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1847    apr |= (1 << reg_bit);
1848    isa->setMiscRegNoEffect(apr_idx, apr);
1849
1850    // Move interrupt state from pending to active.
1851    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1852        // SGI or PPI, redistributor
1853        redistributor->activateIRQ(int_id);
1854    } else if (int_id < Gicv3::INTID_SECURE) {
1855        // SPI, distributor
1856        distributor->activateIRQ(int_id);
1857    } else if (int_id >= Gicv3Redistributor::SMALLEST_LPI_ID) {
1858        // LPI, Redistributor
1859        redistributor->setClrLPI(int_id, false);
1860    }
1861
1862    // By setting the priority to 0xff we are effectively
1863    // making the int_id not pending anymore at the cpu
1864    // interface.
1865    hppi.prio = 0xff;
1866    updateDistributor();
1867}
1868
1869void
1870Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx)
1871{
1872    // Update active priority registers.
1873    ICH_LR_EL2 ich_lr_el = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1874            lr_idx);
1875    Gicv3::GroupId group = ich_lr_el.Group ? Gicv3::G1NS : Gicv3::G0S;
1876    uint8_t prio = ich_lr_el.Priority & 0xf8;
1877    int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS);
1878    int reg_no = apr_bit / 32;
1879    int reg_bit = apr_bit % 32;
1880    int apr_idx = group == Gicv3::G0S ?
1881        MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no;
1882    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1883    apr |= (1 << reg_bit);
1884    isa->setMiscRegNoEffect(apr_idx, apr);
1885    // Move interrupt state from pending to active.
1886    ich_lr_el.State = ICH_LR_EL2_STATE_ACTIVE;
1887    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el);
1888}
1889
1890void
1891Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group)
1892{
1893    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1894        // SGI or PPI, redistributor
1895        redistributor->deactivateIRQ(int_id);
1896    } else if (int_id < Gicv3::INTID_SECURE) {
1897        // SPI, distributor
1898        distributor->deactivateIRQ(int_id);
1899    }
1900
1901    updateDistributor();
1902}
1903
1904void
1905Gicv3CPUInterface::virtualDeactivateIRQ(int lr_idx)
1906{
1907    ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1908            lr_idx);
1909
1910    if (ich_lr_el2.HW) {
1911        // Deactivate the associated physical interrupt
1912        if (ich_lr_el2.pINTID < Gicv3::INTID_SECURE) {
1913            Gicv3::GroupId group = ich_lr_el2.pINTID >= 32 ?
1914                distributor->getIntGroup(ich_lr_el2.pINTID) :
1915                redistributor->getIntGroup(ich_lr_el2.pINTID);
1916            deactivateIRQ(ich_lr_el2.pINTID, group);
1917        }
1918    }
1919
1920    //  Remove the active bit
1921    ich_lr_el2.State = ich_lr_el2.State & ~ICH_LR_EL2_STATE_ACTIVE;
1922    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el2);
1923}
1924
1925/*
1926 * Returns the priority group field for the current BPR value for the group.
1927 * GroupBits() Pseudocode from spec.
1928 */
1929uint32_t
1930Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group)
1931{
1932    ICC_CTLR_EL1 icc_ctlr_el1_s =
1933        isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1934    ICC_CTLR_EL1 icc_ctlr_el1_ns =
1935        isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1936
1937    if ((group == Gicv3::G1S && icc_ctlr_el1_s.CBPR) ||
1938        (group == Gicv3::G1NS && icc_ctlr_el1_ns.CBPR)) {
1939        group = Gicv3::G0S;
1940    }
1941
1942    int bpr;
1943
1944    if (group == Gicv3::G0S) {
1945        bpr = readMiscReg(MISCREG_ICC_BPR0_EL1) & 0x7;
1946    } else if (group == Gicv3::G1S) {
1947        bpr = bpr1(Gicv3::G1S) & 0x7;
1948    } else {
1949        bpr = bpr1(Gicv3::G1NS) & 0x7;
1950    }
1951
1952    if (group == Gicv3::G1NS) {
1953        assert(bpr > 0);
1954        bpr--;
1955    }
1956
1957    return ~0U << (bpr + 1);
1958}
1959
1960uint32_t
1961Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) const
1962{
1963    ICH_VMCR_EL2 ich_vmcr_el2 =
1964        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1965
1966    if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
1967        group = Gicv3::G0S;
1968    }
1969
1970    int bpr;
1971
1972    if (group == Gicv3::G0S) {
1973        bpr = ich_vmcr_el2.VBPR0;
1974    } else {
1975        bpr = ich_vmcr_el2.VBPR1;
1976    }
1977
1978    if (group == Gicv3::G1NS) {
1979        assert(bpr > 0);
1980        bpr--;
1981    }
1982
1983    return ~0U << (bpr + 1);
1984}
1985
1986bool
1987Gicv3CPUInterface::isEOISplitMode() const
1988{
1989    if (isEL3OrMon()) {
1990        ICC_CTLR_EL3 icc_ctlr_el3 =
1991            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1992        return icc_ctlr_el3.EOImode_EL3;
1993    } else {
1994        ICC_CTLR_EL1 icc_ctlr_el1 = 0;
1995        if (inSecureState())
1996            icc_ctlr_el1 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1997        else
1998            icc_ctlr_el1 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1999        return icc_ctlr_el1.EOImode;
2000    }
2001}
2002
2003bool
2004Gicv3CPUInterface::virtualIsEOISplitMode() const
2005{
2006    ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2007    return ich_vmcr_el2.VEOIM;
2008}
2009
2010int
2011Gicv3CPUInterface::highestActiveGroup() const
2012{
2013    int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1));
2014    int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S));
2015    int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS));
2016
2017    if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) {
2018        return Gicv3::G1NS;
2019    }
2020
2021    if (gq_ctz < g0_ctz) {
2022        return Gicv3::G1S;
2023    }
2024
2025    if (g0_ctz < 32) {
2026        return Gicv3::G0S;
2027    }
2028
2029    return -1;
2030}
2031
2032void
2033Gicv3CPUInterface::updateDistributor()
2034{
2035    distributor->update();
2036}
2037
2038void
2039Gicv3CPUInterface::update()
2040{
2041    bool signal_IRQ = false;
2042    bool signal_FIQ = false;
2043
2044    if (hppi.group == Gicv3::G1S && !haveEL(EL3)) {
2045        /*
2046         * Secure enabled GIC sending a G1S IRQ to a secure disabled
2047         * CPU -> send G0 IRQ
2048         */
2049        hppi.group = Gicv3::G0S;
2050    }
2051
2052    if (hppiCanPreempt()) {
2053        ArmISA::InterruptTypes int_type = intSignalType(hppi.group);
2054        DPRINTF(GIC, "Gicv3CPUInterface::update(): "
2055                "posting int as %d!\n", int_type);
2056        int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true;
2057    }
2058
2059    if (signal_IRQ) {
2060        gic->postInt(cpuId, ArmISA::INT_IRQ);
2061    } else {
2062        gic->deassertInt(cpuId, ArmISA::INT_IRQ);
2063    }
2064
2065    if (signal_FIQ) {
2066        gic->postInt(cpuId, ArmISA::INT_FIQ);
2067    } else {
2068        gic->deassertInt(cpuId, ArmISA::INT_FIQ);
2069    }
2070}
2071
2072void
2073Gicv3CPUInterface::virtualUpdate()
2074{
2075    bool signal_IRQ = false;
2076    bool signal_FIQ = false;
2077    int lr_idx = getHPPVILR();
2078
2079    if (lr_idx >= 0) {
2080        ICH_LR_EL2 ich_lr_el2 =
2081            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2082
2083        if (hppviCanPreempt(lr_idx)) {
2084            if (ich_lr_el2.Group) {
2085                signal_IRQ = true;
2086            } else {
2087                signal_FIQ = true;
2088            }
2089        }
2090    }
2091
2092    ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2093
2094    if (ich_hcr_el2.En) {
2095        if (maintenanceInterruptStatus()) {
2096            maintenanceInterrupt->raise();
2097        }
2098    }
2099
2100    if (signal_IRQ) {
2101        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
2102                "posting int as %d!\n", ArmISA::INT_VIRT_IRQ);
2103        gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ);
2104    } else {
2105        gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ);
2106    }
2107
2108    if (signal_FIQ) {
2109        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
2110                "posting int as %d!\n", ArmISA::INT_VIRT_FIQ);
2111        gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ);
2112    } else {
2113        gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ);
2114    }
2115}
2116
2117// Returns the index of the LR with the HPPI
2118int
2119Gicv3CPUInterface::getHPPVILR() const
2120{
2121    int idx = -1;
2122    ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2123
2124    if (!ich_vmcr_el2.VENG0 && !ich_vmcr_el2.VENG1) {
2125        // VG0 and VG1 disabled...
2126        return idx;
2127    }
2128
2129    uint8_t highest_prio = 0xff;
2130
2131    for (int i = 0; i < 16; i++) {
2132        ICH_LR_EL2 ich_lr_el2 =
2133            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i);
2134
2135        if (ich_lr_el2.State != Gicv3::INT_PENDING) {
2136            continue;
2137        }
2138
2139        if (ich_lr_el2.Group) {
2140            // VG1
2141            if (!ich_vmcr_el2.VENG1) {
2142                continue;
2143            }
2144        } else {
2145            // VG0
2146            if (!ich_vmcr_el2.VENG0) {
2147                continue;
2148            }
2149        }
2150
2151        uint8_t prio = ich_lr_el2.Priority;
2152
2153        if (prio < highest_prio) {
2154            highest_prio = prio;
2155            idx = i;
2156        }
2157    }
2158
2159    return idx;
2160}
2161
2162bool
2163Gicv3CPUInterface::hppviCanPreempt(int lr_idx) const
2164{
2165    ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2166    if (!ich_hcr_el2.En) {
2167        // virtual interface is disabled
2168        return false;
2169    }
2170
2171    ICH_LR_EL2 ich_lr_el2 =
2172        isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2173    uint8_t prio = ich_lr_el2.Priority;
2174    uint8_t vpmr =
2175        bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24);
2176
2177    if (prio >= vpmr) {
2178        // prioriry masked
2179        return false;
2180    }
2181
2182    uint8_t rprio = virtualHighestActivePriority();
2183
2184    if (rprio == 0xff) {
2185        return true;
2186    }
2187
2188    Gicv3::GroupId group = ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2189    uint32_t prio_mask = virtualGroupPriorityMask(group);
2190
2191    if ((prio & prio_mask) < (rprio & prio_mask)) {
2192        return true;
2193    }
2194
2195    return false;
2196}
2197
2198uint8_t
2199Gicv3CPUInterface::virtualHighestActivePriority() const
2200{
2201    uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5);
2202
2203    for (int i = 0; i < num_aprs; i++) {
2204        RegVal vapr =
2205            isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) |
2206            isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
2207
2208        if (!vapr) {
2209            continue;
2210        }
2211
2212        return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1);
2213    }
2214
2215    // no active interrups, return idle priority
2216    return 0xff;
2217}
2218
2219void
2220Gicv3CPUInterface::virtualIncrementEOICount()
2221{
2222    // Increment the EOICOUNT field in ICH_HCR_EL2
2223    RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2224    uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27);
2225    EOI_cout++;
2226    ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout);
2227    isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2);
2228}
2229
2230// spec section 4.6.2
2231ArmISA::InterruptTypes
2232Gicv3CPUInterface::intSignalType(Gicv3::GroupId group) const
2233{
2234    bool is_fiq = false;
2235
2236    switch (group) {
2237      case Gicv3::G0S:
2238        is_fiq = true;
2239        break;
2240
2241      case Gicv3::G1S:
2242        is_fiq = (distributor->DS == 0) &&
2243            (!inSecureState() || ((currEL() == EL3) && isAA64()));
2244        break;
2245
2246      case Gicv3::G1NS:
2247        is_fiq = (distributor->DS == 0) && inSecureState();
2248        break;
2249
2250      default:
2251        panic("Gicv3CPUInterface::intSignalType(): invalid group!");
2252    }
2253
2254    if (is_fiq) {
2255        return ArmISA::INT_FIQ;
2256    } else {
2257        return ArmISA::INT_IRQ;
2258    }
2259}
2260
2261bool
2262Gicv3CPUInterface::hppiCanPreempt()
2263{
2264    if (hppi.prio == 0xff) {
2265        // there is no pending interrupt
2266        return false;
2267    }
2268
2269    if (!groupEnabled(hppi.group)) {
2270        // group disabled at CPU interface
2271        return false;
2272    }
2273
2274    if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) {
2275        // priority masked
2276        return false;
2277    }
2278
2279    uint8_t rprio = highestActivePriority();
2280
2281    if (rprio == 0xff) {
2282        return true;
2283    }
2284
2285    uint32_t prio_mask = groupPriorityMask(hppi.group);
2286
2287    if ((hppi.prio & prio_mask) < (rprio & prio_mask)) {
2288        return true;
2289    }
2290
2291    return false;
2292}
2293
2294uint8_t
2295Gicv3CPUInterface::highestActivePriority() const
2296{
2297    uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) |
2298                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) |
2299                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S);
2300
2301    if (apr) {
2302        return ctz32(apr) << (GIC_MIN_BPR + 1);
2303    }
2304
2305    // no active interrups, return idle priority
2306    return 0xff;
2307}
2308
2309bool
2310Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) const
2311{
2312    switch (group) {
2313      case Gicv3::G0S: {
2314        ICC_IGRPEN0_EL1 icc_igrpen0_el1 =
2315            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1);
2316        return icc_igrpen0_el1.Enable && distributor->EnableGrp0;
2317      }
2318
2319      case Gicv3::G1S: {
2320        ICC_IGRPEN1_EL1 icc_igrpen1_el1_s =
2321            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S);
2322        return icc_igrpen1_el1_s.Enable && distributor->EnableGrp1S;
2323      }
2324
2325      case Gicv3::G1NS: {
2326        ICC_IGRPEN1_EL1 icc_igrpen1_el1_ns =
2327            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS);
2328        return icc_igrpen1_el1_ns.Enable && distributor->EnableGrp1NS;
2329      }
2330
2331      default:
2332        panic("Gicv3CPUInterface::groupEnable(): invalid group!\n");
2333    }
2334}
2335
2336bool
2337Gicv3CPUInterface::inSecureState() const
2338{
2339    if (!gic->getSystem()->haveSecurity()) {
2340        return false;
2341    }
2342
2343    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2344    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR);
2345    return ArmISA::inSecureState(scr, cpsr);
2346}
2347
2348int
2349Gicv3CPUInterface::currEL() const
2350{
2351    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2352    bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2353
2354    if (is_64) {
2355        return (ExceptionLevel)(uint8_t) cpsr.el;
2356    } else {
2357        switch (cpsr.mode) {
2358          case MODE_USER:
2359            return 0;
2360
2361          case MODE_HYP:
2362            return 2;
2363
2364          case MODE_MON:
2365            return 3;
2366
2367          default:
2368            return 1;
2369        }
2370    }
2371}
2372
2373bool
2374Gicv3CPUInterface::haveEL(ExceptionLevel el) const
2375{
2376    switch (el) {
2377      case EL0:
2378      case EL1:
2379        return true;
2380
2381      case EL2:
2382        return gic->getSystem()->haveVirtualization();
2383
2384      case EL3:
2385        return gic->getSystem()->haveSecurity();
2386
2387      default:
2388        warn("Unimplemented Exception Level\n");
2389        return false;
2390    }
2391}
2392
2393bool
2394Gicv3CPUInterface::isSecureBelowEL3() const
2395{
2396    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
2397    return haveEL(EL3) && scr.ns == 0;
2398}
2399
2400bool
2401Gicv3CPUInterface::isAA64() const
2402{
2403    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2404    return opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2405}
2406
2407bool
2408Gicv3CPUInterface::isEL3OrMon() const
2409{
2410    if (haveEL(EL3)) {
2411        CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2412        bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2413
2414        if (is_64 && (cpsr.el == EL3)) {
2415            return true;
2416        } else if (!is_64 && (cpsr.mode == MODE_MON)) {
2417            return true;
2418        }
2419    }
2420
2421    return false;
2422}
2423
2424// Computes ICH_EISR_EL2
2425uint64_t
2426Gicv3CPUInterface::eoiMaintenanceInterruptStatus() const
2427{
2428    // ICH_EISR_EL2
2429    // Bits [63:16] - RES0
2430    // Status<n>, bit [n], for n = 0 to 15
2431    //   EOI maintenance interrupt status bit for List register <n>:
2432    //     0 if List register <n>, ICH_LR<n>_EL2, does not have an EOI
2433    //     maintenance interrupt.
2434    //     1 if List register <n>, ICH_LR<n>_EL2, has an EOI maintenance
2435    //     interrupt that has not been handled.
2436    //
2437    // For any ICH_LR<n>_EL2, the corresponding status bit is set to 1 if all
2438    // of the following are true:
2439    // - ICH_LR<n>_EL2.State is 0b00 (ICH_LR_EL2_STATE_INVALID).
2440    // - ICH_LR<n>_EL2.HW is 0.
2441    // - ICH_LR<n>_EL2.EOI (bit [41]) is 1.
2442
2443    uint64_t value = 0;
2444
2445    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2446        ICH_LR_EL2 ich_lr_el2 =
2447            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2448
2449        if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) &&
2450            !ich_lr_el2.HW && ich_lr_el2.EOI) {
2451            value |= (1 << lr_idx);
2452        }
2453    }
2454
2455    return value;
2456}
2457
2458Gicv3CPUInterface::ICH_MISR_EL2
2459Gicv3CPUInterface::maintenanceInterruptStatus() const
2460{
2461    // Comments are copied from SPEC section 9.4.7 (ID012119)
2462    ICH_MISR_EL2 ich_misr_el2 = 0;
2463    ICH_HCR_EL2 ich_hcr_el2 =
2464        isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2465    ICH_VMCR_EL2 ich_vmcr_el2 =
2466        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2467
2468    // End Of Interrupt. [bit 0]
2469    // This maintenance interrupt is asserted when at least one bit in
2470    // ICH_EISR_EL2 is 1.
2471
2472    if (eoiMaintenanceInterruptStatus()) {
2473        ich_misr_el2.EOI = 1;
2474    }
2475
2476    // Underflow. [bit 1]
2477    // This maintenance interrupt is asserted when ICH_HCR_EL2.UIE==1 and
2478    // zero or one of the List register entries are marked as a valid
2479    // interrupt, that is, if the corresponding ICH_LR<n>_EL2.State bits
2480    // do not equal 0x0.
2481    uint32_t num_valid_interrupts = 0;
2482    uint32_t num_pending_interrupts = 0;
2483
2484    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2485        ICH_LR_EL2 ich_lr_el2 =
2486            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2487
2488        if (ich_lr_el2.State != ICH_LR_EL2_STATE_INVALID) {
2489            num_valid_interrupts++;
2490        }
2491
2492        if (ich_lr_el2.State == ICH_LR_EL2_STATE_PENDING) {
2493            num_pending_interrupts++;
2494        }
2495    }
2496
2497    if (ich_hcr_el2.UIE && (num_valid_interrupts < 2)) {
2498        ich_misr_el2.U = 1;
2499    }
2500
2501    // List Register Entry Not Present. [bit 2]
2502    // This maintenance interrupt is asserted when ICH_HCR_EL2.LRENPIE==1
2503    // and ICH_HCR_EL2.EOIcount is non-zero.
2504    if (ich_hcr_el2.LRENPIE && ich_hcr_el2.EOIcount) {
2505        ich_misr_el2.LRENP = 1;
2506    }
2507
2508    // No Pending. [bit 3]
2509    // This maintenance interrupt is asserted when ICH_HCR_EL2.NPIE==1 and
2510    // no List register is in pending state.
2511    if (ich_hcr_el2.NPIE && (num_pending_interrupts == 0)) {
2512        ich_misr_el2.NP = 1;
2513    }
2514
2515    // vPE Group 0 Enabled. [bit 4]
2516    // This maintenance interrupt is asserted when
2517    // ICH_HCR_EL2.VGrp0EIE==1 and ICH_VMCR_EL2.VENG0==1.
2518    if (ich_hcr_el2.VGrp0EIE && ich_vmcr_el2.VENG0) {
2519        ich_misr_el2.VGrp0E = 1;
2520    }
2521
2522    // vPE Group 0 Disabled. [bit 5]
2523    // This maintenance interrupt is asserted when
2524    // ICH_HCR_EL2.VGrp0DIE==1 and ICH_VMCR_EL2.VENG0==0.
2525    if (ich_hcr_el2.VGrp0DIE && !ich_vmcr_el2.VENG0) {
2526        ich_misr_el2.VGrp0D = 1;
2527    }
2528
2529    // vPE Group 1 Enabled. [bit 6]
2530    // This maintenance interrupt is asserted when
2531    // ICH_HCR_EL2.VGrp1EIE==1 and ICH_VMCR_EL2.VENG1==is 1.
2532    if (ich_hcr_el2.VGrp1EIE && ich_vmcr_el2.VENG1) {
2533        ich_misr_el2.VGrp1E = 1;
2534    }
2535
2536    // vPE Group 1 Disabled. [bit 7]
2537    // This maintenance interrupt is asserted when
2538    // ICH_HCR_EL2.VGrp1DIE==1 and ICH_VMCR_EL2.VENG1==is 0.
2539    if (ich_hcr_el2.VGrp1DIE && !ich_vmcr_el2.VENG1) {
2540        ich_misr_el2.VGrp1D = 1;
2541    }
2542
2543    return ich_misr_el2;
2544}
2545
2546RegVal
2547Gicv3CPUInterface::bpr1(Gicv3::GroupId group)
2548{
2549    bool hcr_imo = getHCREL2IMO();
2550    if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
2551        return readMiscReg(MISCREG_ICV_BPR1_EL1);
2552    }
2553
2554    RegVal bpr = 0;
2555
2556    if (group == Gicv3::G1S) {
2557        ICC_CTLR_EL1 icc_ctlr_el1_s =
2558            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
2559
2560        if (!isEL3OrMon() && icc_ctlr_el1_s.CBPR) {
2561            bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1);
2562        } else {
2563            bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_S);
2564            bpr = bpr > GIC_MIN_BPR ? bpr : GIC_MIN_BPR;
2565        }
2566    } else if (group == Gicv3::G1NS) {
2567        ICC_CTLR_EL1 icc_ctlr_el1_ns =
2568            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
2569
2570        // Check if EL3 is implemented and this is a non secure accesses at
2571        // EL1 and EL2
2572        if (haveEL(EL3) && !isEL3OrMon() && icc_ctlr_el1_ns.CBPR) {
2573            // Reads return BPR0 + 1 saturated to 7, WI
2574            bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) + 1;
2575            bpr = bpr < 7 ? bpr : 7;
2576        } else {
2577            bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1_NS);
2578            bpr = bpr > GIC_MIN_BPR_NS ? bpr : GIC_MIN_BPR_NS;
2579        }
2580    } else {
2581        panic("Should be used with G1S and G1NS only\n");
2582    }
2583
2584    return bpr;
2585}
2586
2587void
2588Gicv3CPUInterface::serialize(CheckpointOut & cp) const
2589{
2590    SERIALIZE_SCALAR(hppi.intid);
2591    SERIALIZE_SCALAR(hppi.prio);
2592    SERIALIZE_ENUM(hppi.group);
2593}
2594
2595void
2596Gicv3CPUInterface::unserialize(CheckpointIn & cp)
2597{
2598    UNSERIALIZE_SCALAR(hppi.intid);
2599    UNSERIALIZE_SCALAR(hppi.prio);
2600    UNSERIALIZE_ENUM(hppi.group);
2601}
2602