gic_v3_cpu_interface.cc revision 13760
16876Ssteve.reinhardt@amd.com/*
26876Ssteve.reinhardt@amd.com * Copyright (c) 2018 Metempsy Technology Consulting
36876Ssteve.reinhardt@amd.com * All rights reserved.
46876Ssteve.reinhardt@amd.com *
56876Ssteve.reinhardt@amd.com * Redistribution and use in source and binary forms, with or without
66876Ssteve.reinhardt@amd.com * modification, are permitted provided that the following conditions are
76876Ssteve.reinhardt@amd.com * met: redistributions of source code must retain the above copyright
86876Ssteve.reinhardt@amd.com * notice, this list of conditions and the following disclaimer;
96876Ssteve.reinhardt@amd.com * redistributions in binary form must reproduce the above copyright
106876Ssteve.reinhardt@amd.com * notice, this list of conditions and the following disclaimer in the
116876Ssteve.reinhardt@amd.com * documentation and/or other materials provided with the distribution;
126876Ssteve.reinhardt@amd.com * neither the name of the copyright holders nor the names of its
136876Ssteve.reinhardt@amd.com * contributors may be used to endorse or promote products derived from
146876Ssteve.reinhardt@amd.com * this software without specific prior written permission.
156876Ssteve.reinhardt@amd.com *
166876Ssteve.reinhardt@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
176876Ssteve.reinhardt@amd.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
186876Ssteve.reinhardt@amd.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
196876Ssteve.reinhardt@amd.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
206876Ssteve.reinhardt@amd.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
216876Ssteve.reinhardt@amd.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
226876Ssteve.reinhardt@amd.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
236876Ssteve.reinhardt@amd.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
246876Ssteve.reinhardt@amd.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
256876Ssteve.reinhardt@amd.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
266876Ssteve.reinhardt@amd.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
276876Ssteve.reinhardt@amd.com *
286876Ssteve.reinhardt@amd.com * Authors: Jairo Balart
297908Shestness@cs.utexas.edu */
307908Shestness@cs.utexas.edu
317908Shestness@cs.utexas.edu#include "dev/arm/gic_v3_cpu_interface.hh"
327908Shestness@cs.utexas.edu
337632SBrad.Beckmann@amd.com#include "arch/arm/isa.hh"
348232Snate@binkert.org#include "debug/GIC.hh"
358436SBrad.Beckmann@amd.com#include "dev/arm/gic_v3.hh"
367039Snate@binkert.org#include "dev/arm/gic_v3_distributor.hh"
376285Snate@binkert.org#include "dev/arm/gic_v3_redistributor.hh"
388229Snate@binkert.org
396285Snate@binkert.orgGicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id)
406876Ssteve.reinhardt@amd.com    : BaseISADevice(),
416893SBrad.Beckmann@amd.com      gic(gic),
426876Ssteve.reinhardt@amd.com      redistributor(nullptr),
436876Ssteve.reinhardt@amd.com      distributor(nullptr),
446876Ssteve.reinhardt@amd.com      cpuId(cpu_id)
456876Ssteve.reinhardt@amd.com{
466893SBrad.Beckmann@amd.com}
477039Snate@binkert.org
486882SBrad.Beckmann@amd.comvoid
496882SBrad.Beckmann@amd.comGicv3CPUInterface::init()
506876Ssteve.reinhardt@amd.com{
516876Ssteve.reinhardt@amd.com    redistributor = gic->getRedistributor(cpuId);
526882SBrad.Beckmann@amd.com    distributor = gic->getDistributor();
536893SBrad.Beckmann@amd.com}
547910SBrad.Beckmann@amd.com
557910SBrad.Beckmann@amd.comvoid
567915SBrad.Beckmann@amd.comGicv3CPUInterface::initState()
578436SBrad.Beckmann@amd.com{
588436SBrad.Beckmann@amd.com    reset();
596876Ssteve.reinhardt@amd.com}
606876Ssteve.reinhardt@amd.com
617039Snate@binkert.orgvoid
627039Snate@binkert.orgGicv3CPUInterface::reset()
636882SBrad.Beckmann@amd.com{
646882SBrad.Beckmann@amd.com    hppi.prio = 0xff;
656882SBrad.Beckmann@amd.com}
666882SBrad.Beckmann@amd.com
676882SBrad.Beckmann@amd.combool
686876Ssteve.reinhardt@amd.comGicv3CPUInterface::getHCREL2FMO() const
696876Ssteve.reinhardt@amd.com{
706876Ssteve.reinhardt@amd.com    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
716882SBrad.Beckmann@amd.com
727915SBrad.Beckmann@amd.com    if (hcr.tge && hcr.e2h) {
738436SBrad.Beckmann@amd.com        return false;
747039Snate@binkert.org    } else if (hcr.tge) {
757039Snate@binkert.org        return true;
767039Snate@binkert.org    } else {
776882SBrad.Beckmann@amd.com        return hcr.fmo;
786882SBrad.Beckmann@amd.com    }
796882SBrad.Beckmann@amd.com}
807039Snate@binkert.org
816882SBrad.Beckmann@amd.combool
826882SBrad.Beckmann@amd.comGicv3CPUInterface::getHCREL2IMO() const
837039Snate@binkert.org{
847039Snate@binkert.org    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
857039Snate@binkert.org
866893SBrad.Beckmann@amd.com    if (hcr.tge && hcr.e2h) {
876893SBrad.Beckmann@amd.com        return false;
886893SBrad.Beckmann@amd.com    } else if (hcr.tge) {
897915SBrad.Beckmann@amd.com        return true;
908436SBrad.Beckmann@amd.com    } else {
917039Snate@binkert.org        return hcr.imo;
926893SBrad.Beckmann@amd.com    }
937039Snate@binkert.org}
947039Snate@binkert.org
957039Snate@binkert.orgRegVal
967039Snate@binkert.orgGicv3CPUInterface::readMiscReg(int misc_reg)
977039Snate@binkert.org{
987039Snate@binkert.org    RegVal value = isa->readMiscRegNoEffect(misc_reg);
996893SBrad.Beckmann@amd.com    bool hcr_fmo = getHCREL2FMO();
1006893SBrad.Beckmann@amd.com    bool hcr_imo = getHCREL2IMO();
1016882SBrad.Beckmann@amd.com
1027039Snate@binkert.org    switch (misc_reg) {
1036876Ssteve.reinhardt@amd.com      // Active Priorities Group 1 Registers
1046876Ssteve.reinhardt@amd.com      case MISCREG_ICC_AP1R0:
1056882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R0_EL1: {
1067039Snate@binkert.org          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1076882SBrad.Beckmann@amd.com              return isa->readMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1);
1086882SBrad.Beckmann@amd.com          }
1096882SBrad.Beckmann@amd.com
1108161SBrad.Beckmann@amd.com          break;
1116882SBrad.Beckmann@amd.com      }
1126882SBrad.Beckmann@amd.com
1136882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R1:
1148436SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R1_EL1:
1158436SBrad.Beckmann@amd.com
1166882SBrad.Beckmann@amd.com        // only implemented if supporting 6 or more bits of priority
1176882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R2:
1188161SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R2_EL1:
1196882SBrad.Beckmann@amd.com
1208436SBrad.Beckmann@amd.com        // only implemented if supporting 7 or more bits of priority
1217910SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R3:
1227915SBrad.Beckmann@amd.com      case MISCREG_ICC_AP1R3_EL1:
1236882SBrad.Beckmann@amd.com        // only implemented if supporting 7 or more bits of priority
1246882SBrad.Beckmann@amd.com        return 0;
1256882SBrad.Beckmann@amd.com
1266882SBrad.Beckmann@amd.com      // Active Priorities Group 0 Registers
1276882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R0:
1286882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R0_EL1: {
1296882SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1306882SBrad.Beckmann@amd.com              return isa->readMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1);
1316882SBrad.Beckmann@amd.com          }
1326882SBrad.Beckmann@amd.com
1336882SBrad.Beckmann@amd.com          break;
1346882SBrad.Beckmann@amd.com      }
1356882SBrad.Beckmann@amd.com
1366882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R1:
1376882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R1_EL1:
1386882SBrad.Beckmann@amd.com
1396882SBrad.Beckmann@amd.com        // only implemented if supporting 6 or more bits of priority
1406882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R2:
1416882SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R2_EL1:
1426882SBrad.Beckmann@amd.com
1437039Snate@binkert.org        // only implemented if supporting 7 or more bits of priority
1447039Snate@binkert.org      case MISCREG_ICC_AP0R3:
1458161SBrad.Beckmann@amd.com      case MISCREG_ICC_AP0R3_EL1:
1466882SBrad.Beckmann@amd.com        // only implemented if supporting 7 or more bits of priority
1476882SBrad.Beckmann@amd.com        return 0;
1486882SBrad.Beckmann@amd.com
1496882SBrad.Beckmann@amd.com      // Interrupt Group 0 Enable register EL1
1507039Snate@binkert.org      case MISCREG_ICC_IGRPEN0:
1516882SBrad.Beckmann@amd.com      case MISCREG_ICC_IGRPEN0_EL1: {
1526882SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1536882SBrad.Beckmann@amd.com              return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN0_EL1);
1547039Snate@binkert.org          }
1556882SBrad.Beckmann@amd.com
1566882SBrad.Beckmann@amd.com          break;
1576882SBrad.Beckmann@amd.com      }
1587039Snate@binkert.org
1596882SBrad.Beckmann@amd.com      // Interrupt Group 1 Enable register EL1
1607039Snate@binkert.org      case MISCREG_ICC_IGRPEN1:
1616882SBrad.Beckmann@amd.com      case MISCREG_ICC_IGRPEN1_EL1: {
1626882SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1636882SBrad.Beckmann@amd.com              return isa->readMiscRegNoEffect(MISCREG_ICV_IGRPEN1_EL1);
1646882SBrad.Beckmann@amd.com          }
1656882SBrad.Beckmann@amd.com
1666882SBrad.Beckmann@amd.com          break;
1678161SBrad.Beckmann@amd.com      }
1687039Snate@binkert.org
1696882SBrad.Beckmann@amd.com      // Interrupt Group 1 Enable register EL3
1706882SBrad.Beckmann@amd.com      case MISCREG_ICC_MGRPEN1:
1716882SBrad.Beckmann@amd.com      case MISCREG_ICC_IGRPEN1_EL3:
1727039Snate@binkert.org          break;
1737039Snate@binkert.org
1747039Snate@binkert.org      // Running Priority Register
1756882SBrad.Beckmann@amd.com      case MISCREG_ICC_RPR:
1766882SBrad.Beckmann@amd.com      case MISCREG_ICC_RPR_EL1: {
1776882SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() &&
1786882SBrad.Beckmann@amd.com              (hcr_imo || hcr_fmo)) {
1796882SBrad.Beckmann@amd.com              return readMiscReg(MISCREG_ICV_RPR_EL1);
1806882SBrad.Beckmann@amd.com          }
1816882SBrad.Beckmann@amd.com
1826882SBrad.Beckmann@amd.com          uint8_t rprio = highestActivePriority();
1836882SBrad.Beckmann@amd.com
1846882SBrad.Beckmann@amd.com          if (haveEL(EL3) && !inSecureState() &&
1856882SBrad.Beckmann@amd.com              (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
1866922SBrad.Beckmann@amd.com              // Spec section 4.8.1
1876922SBrad.Beckmann@amd.com              // For Non-secure access to ICC_RPR_EL1 when SCR_EL3.FIQ == 1
1886922SBrad.Beckmann@amd.com              if ((rprio & 0x80) == 0) {
1896922SBrad.Beckmann@amd.com                  // If the current priority mask value is in the range of
1906882SBrad.Beckmann@amd.com                  // 0x00-0x7F a read access returns the value 0x0
1916882SBrad.Beckmann@amd.com                  rprio = 0;
1926882SBrad.Beckmann@amd.com              } else if (rprio != 0xff) {
1936882SBrad.Beckmann@amd.com                  // If the current priority mask value is in the range of
1948161SBrad.Beckmann@amd.com                  // 0x80-0xFF a read access returns the Non-secure read of
1956922SBrad.Beckmann@amd.com                  // the current value
1966922SBrad.Beckmann@amd.com                  rprio = (rprio << 1) & 0xff;
1976882SBrad.Beckmann@amd.com              }
1986882SBrad.Beckmann@amd.com          }
1996882SBrad.Beckmann@amd.com
2006882SBrad.Beckmann@amd.com          value = rprio;
2016882SBrad.Beckmann@amd.com          break;
2026882SBrad.Beckmann@amd.com      }
2036882SBrad.Beckmann@amd.com
2046899SBrad.Beckmann@amd.com      // Virtual Running Priority Register
2056899SBrad.Beckmann@amd.com      case MISCREG_ICV_RPR_EL1: {
2066882SBrad.Beckmann@amd.com          value = virtualHighestActivePriority();
2076899SBrad.Beckmann@amd.com          break;
2086899SBrad.Beckmann@amd.com      }
2096899SBrad.Beckmann@amd.com
2106899SBrad.Beckmann@amd.com      // Highest Priority Pending Interrupt Register 0
2117023SBrad.Beckmann@amd.com      case MISCREG_ICC_HPPIR0:
2127023SBrad.Beckmann@amd.com      case MISCREG_ICC_HPPIR0_EL1: {
2138161SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
2147907Shestness@cs.utexas.edu              return readMiscReg(MISCREG_ICV_HPPIR0_EL1);
2156882SBrad.Beckmann@amd.com          }
2168161SBrad.Beckmann@amd.com
2177023SBrad.Beckmann@amd.com          value = getHPPIR0();
2187907Shestness@cs.utexas.edu          break;
2196882SBrad.Beckmann@amd.com      }
2207908Shestness@cs.utexas.edu
2217908Shestness@cs.utexas.edu      // Virtual Highest Priority Pending Interrupt Register 0
2228161SBrad.Beckmann@amd.com      case MISCREG_ICV_HPPIR0_EL1: {
2237908Shestness@cs.utexas.edu          value = Gicv3::INTID_SPURIOUS;
2247908Shestness@cs.utexas.edu          int lr_idx = getHPPVILR();
2258161SBrad.Beckmann@amd.com
2267908Shestness@cs.utexas.edu          if (lr_idx >= 0) {
2277908Shestness@cs.utexas.edu              ICH_LR_EL2 ich_lr_el2 =
2287908Shestness@cs.utexas.edu                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2296922SBrad.Beckmann@amd.com              Gicv3::GroupId group =
2307023SBrad.Beckmann@amd.com                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2317023SBrad.Beckmann@amd.com
2327023SBrad.Beckmann@amd.com              if (group == Gicv3::G0S) {
2337023SBrad.Beckmann@amd.com                  value = ich_lr_el2.vINTID;
2347908Shestness@cs.utexas.edu              }
2357908Shestness@cs.utexas.edu          }
2367908Shestness@cs.utexas.edu
2377908Shestness@cs.utexas.edu          break;
2387908Shestness@cs.utexas.edu      }
2397908Shestness@cs.utexas.edu
2407908Shestness@cs.utexas.edu      // Highest Priority Pending Interrupt Register 1
2417908Shestness@cs.utexas.edu      case MISCREG_ICC_HPPIR1:
2427908Shestness@cs.utexas.edu      case MISCREG_ICC_HPPIR1_EL1: {
2437908Shestness@cs.utexas.edu          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
2447908Shestness@cs.utexas.edu              return readMiscReg(MISCREG_ICV_HPPIR1_EL1);
2457908Shestness@cs.utexas.edu          }
2467023SBrad.Beckmann@amd.com
2477023SBrad.Beckmann@amd.com          value = getHPPIR1();
2487908Shestness@cs.utexas.edu          break;
2497908Shestness@cs.utexas.edu      }
2507908Shestness@cs.utexas.edu
2517023SBrad.Beckmann@amd.com      // Virtual Highest Priority Pending Interrupt Register 1
2528184Ssomayeh@cs.wisc.edu      case MISCREG_ICV_HPPIR1_EL1: {
2538184Ssomayeh@cs.wisc.edu          value = Gicv3::INTID_SPURIOUS;
2547023SBrad.Beckmann@amd.com          int lr_idx = getHPPVILR();
2557023SBrad.Beckmann@amd.com
2567023SBrad.Beckmann@amd.com          if (lr_idx >= 0) {
2576882SBrad.Beckmann@amd.com              ICH_LR_EL2 ich_lr_el2 =
2586882SBrad.Beckmann@amd.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2597915SBrad.Beckmann@amd.com              Gicv3::GroupId group =
2607039Snate@binkert.org                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2617039Snate@binkert.org
2626882SBrad.Beckmann@amd.com              if (group == Gicv3::G1NS) {
2638174Snilay@cs.wisc.edu                  value = ich_lr_el2.vINTID;
2647906SBrad.Beckmann@amd.com              }
2657906SBrad.Beckmann@amd.com          }
2666882SBrad.Beckmann@amd.com
2676922SBrad.Beckmann@amd.com          break;
2687023SBrad.Beckmann@amd.com      }
2697550SBrad.Beckmann@amd.com
2707023SBrad.Beckmann@amd.com      // Binary Point Register 0
2717023SBrad.Beckmann@amd.com      case MISCREG_ICC_BPR0:
2727550SBrad.Beckmann@amd.com      case MISCREG_ICC_BPR0_EL1:
2738161SBrad.Beckmann@amd.com        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
2746922SBrad.Beckmann@amd.com            return readMiscReg(MISCREG_ICV_BPR0_EL1);
2756882SBrad.Beckmann@amd.com        }
2767023SBrad.Beckmann@amd.com
2777910SBrad.Beckmann@amd.com        M5_FALLTHROUGH;
2787910SBrad.Beckmann@amd.com
2797910SBrad.Beckmann@amd.com      // Binary Point Register 1
2807910SBrad.Beckmann@amd.com      case MISCREG_ICC_BPR1:
2817910SBrad.Beckmann@amd.com      case MISCREG_ICC_BPR1_EL1: {
2827910SBrad.Beckmann@amd.com            if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
2837910SBrad.Beckmann@amd.com                return readMiscReg(MISCREG_ICV_BPR1_EL1);
2847910SBrad.Beckmann@amd.com            }
2858161SBrad.Beckmann@amd.com
2867906SBrad.Beckmann@amd.com            Gicv3::GroupId group =
2877039Snate@binkert.org                misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S;
2887039Snate@binkert.org
2896922SBrad.Beckmann@amd.com            if (group == Gicv3::G1S && !inSecureState()) {
2906922SBrad.Beckmann@amd.com                group = Gicv3::G1NS;
2916922SBrad.Beckmann@amd.com            }
2926922SBrad.Beckmann@amd.com
2936882SBrad.Beckmann@amd.com            ICC_CTLR_EL1 icc_ctlr_el1_s =
2946882SBrad.Beckmann@amd.com                isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
2958436SBrad.Beckmann@amd.com
2968436SBrad.Beckmann@amd.com            if ((group == Gicv3::G1S) && !isEL3OrMon() &&
2978436SBrad.Beckmann@amd.com                icc_ctlr_el1_s.CBPR) {
2988436SBrad.Beckmann@amd.com                group = Gicv3::G0S;
2998436SBrad.Beckmann@amd.com            }
3008436SBrad.Beckmann@amd.com
3018436SBrad.Beckmann@amd.com            bool sat_inc = false;
3028436SBrad.Beckmann@amd.com
3038436SBrad.Beckmann@amd.com            ICC_CTLR_EL1 icc_ctlr_el1_ns =
3048436SBrad.Beckmann@amd.com                isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
3058436SBrad.Beckmann@amd.com
3068436SBrad.Beckmann@amd.com            if ((group == Gicv3::G1NS) && (currEL() < EL3) &&
3078436SBrad.Beckmann@amd.com                icc_ctlr_el1_ns.CBPR) {
3088436SBrad.Beckmann@amd.com                // Reads return BPR0 + 1 saturated to 7, WI
3098436SBrad.Beckmann@amd.com                group = Gicv3::G0S;
3108436SBrad.Beckmann@amd.com                sat_inc = true;
3118436SBrad.Beckmann@amd.com            }
3128436SBrad.Beckmann@amd.com
3138436SBrad.Beckmann@amd.com            uint8_t bpr;
3148436SBrad.Beckmann@amd.com
3158436SBrad.Beckmann@amd.com            if (group == Gicv3::G0S) {
3168436SBrad.Beckmann@amd.com                bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1);
3178436SBrad.Beckmann@amd.com            } else {
3188436SBrad.Beckmann@amd.com                bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1);
3198436SBrad.Beckmann@amd.com            }
3208436SBrad.Beckmann@amd.com
3218436SBrad.Beckmann@amd.com            if (sat_inc) {
3228436SBrad.Beckmann@amd.com                bpr++;
3238436SBrad.Beckmann@amd.com
3248436SBrad.Beckmann@amd.com                if (bpr > 7) {
3258436SBrad.Beckmann@amd.com                    bpr = 7;
3268436SBrad.Beckmann@amd.com                }
3278436SBrad.Beckmann@amd.com            }
3288436SBrad.Beckmann@amd.com
3298436SBrad.Beckmann@amd.com            value = bpr;
3308436SBrad.Beckmann@amd.com            break;
3318436SBrad.Beckmann@amd.com      }
3328436SBrad.Beckmann@amd.com
3338436SBrad.Beckmann@amd.com      // Virtual Binary Point Register 1
3348436SBrad.Beckmann@amd.com      case MISCREG_ICV_BPR0_EL1:
3358436SBrad.Beckmann@amd.com      case MISCREG_ICV_BPR1_EL1: {
3368436SBrad.Beckmann@amd.com          Gicv3::GroupId group =
3378436SBrad.Beckmann@amd.com              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
3388436SBrad.Beckmann@amd.com          ICH_VMCR_EL2 ich_vmcr_el2 =
3398436SBrad.Beckmann@amd.com              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
3408436SBrad.Beckmann@amd.com          bool sat_inc = false;
3418436SBrad.Beckmann@amd.com
3428436SBrad.Beckmann@amd.com          if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
3438436SBrad.Beckmann@amd.com              // bpr0 + 1 saturated to 7, WI
3448436SBrad.Beckmann@amd.com              group = Gicv3::G0S;
3458436SBrad.Beckmann@amd.com              sat_inc = true;
3468436SBrad.Beckmann@amd.com          }
3478436SBrad.Beckmann@amd.com
3488436SBrad.Beckmann@amd.com          uint8_t vbpr;
3498436SBrad.Beckmann@amd.com
3508436SBrad.Beckmann@amd.com          if (group == Gicv3::G0S) {
3518436SBrad.Beckmann@amd.com              vbpr = ich_vmcr_el2.VBPR0;
3528436SBrad.Beckmann@amd.com          } else {
3538436SBrad.Beckmann@amd.com              vbpr = ich_vmcr_el2.VBPR1;
3548436SBrad.Beckmann@amd.com          }
3558436SBrad.Beckmann@amd.com
3568436SBrad.Beckmann@amd.com          if (sat_inc) {
3578436SBrad.Beckmann@amd.com              vbpr++;
3588436SBrad.Beckmann@amd.com
3598436SBrad.Beckmann@amd.com              if (vbpr > 7) {
3608436SBrad.Beckmann@amd.com                  vbpr = 7;
3618436SBrad.Beckmann@amd.com              }
3628436SBrad.Beckmann@amd.com          }
3638436SBrad.Beckmann@amd.com
3648436SBrad.Beckmann@amd.com          value = vbpr;
3658436SBrad.Beckmann@amd.com          break;
3668436SBrad.Beckmann@amd.com      }
3678436SBrad.Beckmann@amd.com
3688436SBrad.Beckmann@amd.com      // Interrupt Priority Mask Register
3698436SBrad.Beckmann@amd.com      case MISCREG_ICC_PMR:
3708436SBrad.Beckmann@amd.com      case MISCREG_ICC_PMR_EL1:
3718436SBrad.Beckmann@amd.com        if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
3728436SBrad.Beckmann@amd.com            return isa->readMiscRegNoEffect(MISCREG_ICV_PMR_EL1);
3738436SBrad.Beckmann@amd.com        }
3748436SBrad.Beckmann@amd.com
3758436SBrad.Beckmann@amd.com        if (haveEL(EL3) && !inSecureState() &&
3768436SBrad.Beckmann@amd.com            (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
3778436SBrad.Beckmann@amd.com            // Spec section 4.8.1
3788436SBrad.Beckmann@amd.com            // For Non-secure access to ICC_PMR_EL1 when SCR_EL3.FIQ == 1:
3798436SBrad.Beckmann@amd.com            if ((value & 0x80) == 0) {
3808436SBrad.Beckmann@amd.com                // If the current priority mask value is in the range of
3818436SBrad.Beckmann@amd.com                // 0x00-0x7F a read access returns the value 0x00.
3828436SBrad.Beckmann@amd.com                value = 0;
3838436SBrad.Beckmann@amd.com            } else if (value != 0xff) {
3848436SBrad.Beckmann@amd.com                // If the current priority mask value is in the range of
3858436SBrad.Beckmann@amd.com                // 0x80-0xFF a read access returns the Non-secure read of the
3868436SBrad.Beckmann@amd.com                // current value.
3878436SBrad.Beckmann@amd.com                value = (value << 1) & 0xff;
3888436SBrad.Beckmann@amd.com            }
3898436SBrad.Beckmann@amd.com        }
3908436SBrad.Beckmann@amd.com
3918436SBrad.Beckmann@amd.com        break;
3928436SBrad.Beckmann@amd.com
3938436SBrad.Beckmann@amd.com      // Interrupt Acknowledge Register 0
3948436SBrad.Beckmann@amd.com      case MISCREG_ICC_IAR0:
3958436SBrad.Beckmann@amd.com      case MISCREG_ICC_IAR0_EL1: {
3968436SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
3978436SBrad.Beckmann@amd.com              return readMiscReg(MISCREG_ICV_IAR0_EL1);
3988436SBrad.Beckmann@amd.com          }
3998436SBrad.Beckmann@amd.com
4008436SBrad.Beckmann@amd.com          uint32_t int_id;
4018436SBrad.Beckmann@amd.com
4028436SBrad.Beckmann@amd.com          if (hppiCanPreempt()) {
4038436SBrad.Beckmann@amd.com              int_id = getHPPIR0();
4048436SBrad.Beckmann@amd.com
4058436SBrad.Beckmann@amd.com              // avoid activation for special interrupts
4068436SBrad.Beckmann@amd.com              if (int_id < Gicv3::INTID_SECURE) {
4078436SBrad.Beckmann@amd.com                  activateIRQ(int_id, hppi.group);
4088436SBrad.Beckmann@amd.com              }
4098436SBrad.Beckmann@amd.com          } else {
4108436SBrad.Beckmann@amd.com              int_id = Gicv3::INTID_SPURIOUS;
4118436SBrad.Beckmann@amd.com          }
4128436SBrad.Beckmann@amd.com
4138436SBrad.Beckmann@amd.com          value = int_id;
4148436SBrad.Beckmann@amd.com          break;
4158436SBrad.Beckmann@amd.com      }
4168436SBrad.Beckmann@amd.com
4178436SBrad.Beckmann@amd.com      // Virtual Interrupt Acknowledge Register 0
4188436SBrad.Beckmann@amd.com      case MISCREG_ICV_IAR0_EL1: {
4198436SBrad.Beckmann@amd.com          int lr_idx = getHPPVILR();
4208436SBrad.Beckmann@amd.com          uint32_t int_id = Gicv3::INTID_SPURIOUS;
4218436SBrad.Beckmann@amd.com
4228436SBrad.Beckmann@amd.com          if (lr_idx >= 0) {
4238436SBrad.Beckmann@amd.com              ICH_LR_EL2 ich_lr_el2 =
4248436SBrad.Beckmann@amd.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
4258436SBrad.Beckmann@amd.com
4268436SBrad.Beckmann@amd.com              if (!ich_lr_el2.Group && hppviCanPreempt(lr_idx)) {
4278436SBrad.Beckmann@amd.com                  int_id = ich_lr_el2.vINTID;
4288436SBrad.Beckmann@amd.com
4298436SBrad.Beckmann@amd.com                  if (int_id < Gicv3::INTID_SECURE ||
4308436SBrad.Beckmann@amd.com                      int_id > Gicv3::INTID_SPURIOUS) {
4318436SBrad.Beckmann@amd.com                      virtualActivateIRQ(lr_idx);
4328436SBrad.Beckmann@amd.com                  } else {
4338436SBrad.Beckmann@amd.com                      // Bogus... Pseudocode says:
4348436SBrad.Beckmann@amd.com                      // - Move from pending to invalid...
4358436SBrad.Beckmann@amd.com                      // - Return de bogus id...
4368436SBrad.Beckmann@amd.com                      ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID;
4378436SBrad.Beckmann@amd.com                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
4388436SBrad.Beckmann@amd.com                                              ich_lr_el2);
4398436SBrad.Beckmann@amd.com                  }
4408436SBrad.Beckmann@amd.com              }
4418436SBrad.Beckmann@amd.com          }
4428436SBrad.Beckmann@amd.com
4438436SBrad.Beckmann@amd.com          value = int_id;
4448436SBrad.Beckmann@amd.com          virtualUpdate();
4458436SBrad.Beckmann@amd.com          break;
4468436SBrad.Beckmann@amd.com      }
4478436SBrad.Beckmann@amd.com
4488436SBrad.Beckmann@amd.com      // Interrupt Acknowledge Register 1
4498436SBrad.Beckmann@amd.com      case MISCREG_ICC_IAR1:
4508436SBrad.Beckmann@amd.com      case MISCREG_ICC_IAR1_EL1: {
4518436SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
4528436SBrad.Beckmann@amd.com              return readMiscReg(MISCREG_ICV_IAR1_EL1);
4538436SBrad.Beckmann@amd.com          }
4548436SBrad.Beckmann@amd.com
4558436SBrad.Beckmann@amd.com          uint32_t int_id;
4568436SBrad.Beckmann@amd.com
4576882SBrad.Beckmann@amd.com          if (hppiCanPreempt()) {
4586922SBrad.Beckmann@amd.com              int_id = getHPPIR1();
4596882SBrad.Beckmann@amd.com
4606922SBrad.Beckmann@amd.com              // avoid activation for special interrupts
4617039Snate@binkert.org              if (int_id < Gicv3::INTID_SECURE) {
4626922SBrad.Beckmann@amd.com                  activateIRQ(int_id, hppi.group);
4636922SBrad.Beckmann@amd.com              }
4646922SBrad.Beckmann@amd.com          } else {
4657039Snate@binkert.org              int_id = Gicv3::INTID_SPURIOUS;
4666922SBrad.Beckmann@amd.com          }
4676922SBrad.Beckmann@amd.com
4686922SBrad.Beckmann@amd.com          value = int_id;
4696882SBrad.Beckmann@amd.com          break;
4706882SBrad.Beckmann@amd.com      }
4717910SBrad.Beckmann@amd.com
4727910SBrad.Beckmann@amd.com      // Virtual Interrupt Acknowledge Register 1
4737910SBrad.Beckmann@amd.com      case MISCREG_ICV_IAR1_EL1: {
4747910SBrad.Beckmann@amd.com          int lr_idx = getHPPVILR();
4757910SBrad.Beckmann@amd.com          uint32_t int_id = Gicv3::INTID_SPURIOUS;
4767910SBrad.Beckmann@amd.com
4778162SBrad.Beckmann@amd.com          if (lr_idx >= 0) {
4788162SBrad.Beckmann@amd.com              ICH_LR_EL2 ich_lr_el2 =
4798162SBrad.Beckmann@amd.com                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
4808162SBrad.Beckmann@amd.com
4818162SBrad.Beckmann@amd.com              if (ich_lr_el2.Group && hppviCanPreempt(lr_idx)) {
4828162SBrad.Beckmann@amd.com                  int_id = ich_lr_el2.vINTID;
4838162SBrad.Beckmann@amd.com
4848162SBrad.Beckmann@amd.com                  if (int_id < Gicv3::INTID_SECURE ||
4858162SBrad.Beckmann@amd.com                      int_id > Gicv3::INTID_SPURIOUS) {
4868162SBrad.Beckmann@amd.com                      virtualActivateIRQ(lr_idx);
4878162SBrad.Beckmann@amd.com                  } else {
4888162SBrad.Beckmann@amd.com                      // Bogus... Pseudocode says:
4898162SBrad.Beckmann@amd.com                      // - Move from pending to invalid...
4908162SBrad.Beckmann@amd.com                      // - Return de bogus id...
4918162SBrad.Beckmann@amd.com                      ich_lr_el2.State = ICH_LR_EL2_STATE_INVALID;
4927910SBrad.Beckmann@amd.com                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
4937910SBrad.Beckmann@amd.com                                              ich_lr_el2);
4948162SBrad.Beckmann@amd.com                  }
4958162SBrad.Beckmann@amd.com              }
4967910SBrad.Beckmann@amd.com          }
4977910SBrad.Beckmann@amd.com
4986882SBrad.Beckmann@amd.com          value = int_id;
4996882SBrad.Beckmann@amd.com          virtualUpdate();
5006882SBrad.Beckmann@amd.com          break;
5016882SBrad.Beckmann@amd.com      }
5026882SBrad.Beckmann@amd.com
5036882SBrad.Beckmann@amd.com      // System Register Enable Register EL1
5046882SBrad.Beckmann@amd.com      case MISCREG_ICC_SRE:
5057550SBrad.Beckmann@amd.com      case MISCREG_ICC_SRE_EL1: {
5067915SBrad.Beckmann@amd.com        /*
5078184Ssomayeh@cs.wisc.edu         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
5087550SBrad.Beckmann@amd.com         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
5097915SBrad.Beckmann@amd.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
5107550SBrad.Beckmann@amd.com         */
5117550SBrad.Beckmann@amd.com          ICC_SRE_EL1 icc_sre_el1 = 0;
5127550SBrad.Beckmann@amd.com          icc_sre_el1.SRE = 1;
5137550SBrad.Beckmann@amd.com          icc_sre_el1.DIB = 1;
5147550SBrad.Beckmann@amd.com          icc_sre_el1.DFB = 1;
5157550SBrad.Beckmann@amd.com          value = icc_sre_el1;
5167550SBrad.Beckmann@amd.com          break;
5177550SBrad.Beckmann@amd.com      }
5187550SBrad.Beckmann@amd.com
5197550SBrad.Beckmann@amd.com      // System Register Enable Register EL2
5207550SBrad.Beckmann@amd.com      case MISCREG_ICC_HSRE:
5217550SBrad.Beckmann@amd.com      case MISCREG_ICC_SRE_EL2: {
5227550SBrad.Beckmann@amd.com        /*
5237550SBrad.Beckmann@amd.com         * Enable [3] == 1
5247550SBrad.Beckmann@amd.com         * (EL1 accesses to ICC_SRE_EL1 do not trap to EL2, RAO/WI)
5257550SBrad.Beckmann@amd.com         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
5267550SBrad.Beckmann@amd.com         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
5277550SBrad.Beckmann@amd.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
5287550SBrad.Beckmann@amd.com         */
5297550SBrad.Beckmann@amd.com        ICC_SRE_EL2 icc_sre_el2 = 0;
5307550SBrad.Beckmann@amd.com        icc_sre_el2.SRE = 1;
5317550SBrad.Beckmann@amd.com        icc_sre_el2.DIB = 1;
5327550SBrad.Beckmann@amd.com        icc_sre_el2.DFB = 1;
5338184Ssomayeh@cs.wisc.edu        icc_sre_el2.Enable = 1;
5348184Ssomayeh@cs.wisc.edu        value = icc_sre_el2;
5358184Ssomayeh@cs.wisc.edu        break;
5368184Ssomayeh@cs.wisc.edu      }
5378184Ssomayeh@cs.wisc.edu
5388184Ssomayeh@cs.wisc.edu      // System Register Enable Register EL3
5398184Ssomayeh@cs.wisc.edu      case MISCREG_ICC_MSRE:
5408184Ssomayeh@cs.wisc.edu      case MISCREG_ICC_SRE_EL3: {
5418161SBrad.Beckmann@amd.com        /*
5426882SBrad.Beckmann@amd.com         * Enable [3] == 1
5437550SBrad.Beckmann@amd.com         * (EL1 accesses to ICC_SRE_EL1 do not trap to EL3.
5447550SBrad.Beckmann@amd.com         *  EL2 accesses to ICC_SRE_EL1 and ICC_SRE_EL2 do not trap to EL3.
5458184Ssomayeh@cs.wisc.edu         *  RAO/WI)
5467915SBrad.Beckmann@amd.com         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
5477550SBrad.Beckmann@amd.com         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
5486882SBrad.Beckmann@amd.com         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
5496882SBrad.Beckmann@amd.com         */
5506882SBrad.Beckmann@amd.com        ICC_SRE_EL3 icc_sre_el3 = 0;
5518161SBrad.Beckmann@amd.com        icc_sre_el3.SRE = 1;
5526882SBrad.Beckmann@amd.com        icc_sre_el3.DIB = 1;
5536882SBrad.Beckmann@amd.com        icc_sre_el3.DFB = 1;
5546882SBrad.Beckmann@amd.com        icc_sre_el3.Enable = 1;
5556882SBrad.Beckmann@amd.com        value = icc_sre_el3;
5568161SBrad.Beckmann@amd.com        break;
5576882SBrad.Beckmann@amd.com      }
5586882SBrad.Beckmann@amd.com
5596882SBrad.Beckmann@amd.com      // Control Register
5606882SBrad.Beckmann@amd.com      case MISCREG_ICC_CTLR:
5616882SBrad.Beckmann@amd.com      case MISCREG_ICC_CTLR_EL1: {
5627558SBrad.Beckmann@amd.com          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
5637823Ssteve.reinhardt@amd.com              return readMiscReg(MISCREG_ICV_CTLR_EL1);
5646882SBrad.Beckmann@amd.com          }
5656882SBrad.Beckmann@amd.com
5666882SBrad.Beckmann@amd.com          // Enforce value for RO bits
5676882SBrad.Beckmann@amd.com          // ExtRange [19], INTIDs in the range 1024..8191 not supported
5686882SBrad.Beckmann@amd.com          // RSS [18], SGIs with affinity level 0 values of 0-255 are supported
5696882SBrad.Beckmann@amd.com          // A3V [15], supports non-zero values of the Aff3 field in SGI
5707558SBrad.Beckmann@amd.com          //           generation System registers
5717823Ssteve.reinhardt@amd.com          // SEIS [14], does not support generation of SEIs (deprecated)
5726882SBrad.Beckmann@amd.com          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
5736882SBrad.Beckmann@amd.com          // PRIbits [10:8], number of priority bits implemented, minus one
5746882SBrad.Beckmann@amd.com          ICC_CTLR_EL1 icc_ctlr_el1 = value;
5756882SBrad.Beckmann@amd.com          icc_ctlr_el1.ExtRange = 0;
5766882SBrad.Beckmann@amd.com          icc_ctlr_el1.RSS = 1;
5776882SBrad.Beckmann@amd.com          icc_ctlr_el1.A3V = 1;
5786882SBrad.Beckmann@amd.com          icc_ctlr_el1.SEIS = 0;
5796882SBrad.Beckmann@amd.com          icc_ctlr_el1.IDbits = 1;
5806893SBrad.Beckmann@amd.com          icc_ctlr_el1.PRIbits = PRIORITY_BITS - 1;
5817039Snate@binkert.org          value = icc_ctlr_el1;
5827039Snate@binkert.org          break;
5837039Snate@binkert.org      }
5846882SBrad.Beckmann@amd.com
5858161SBrad.Beckmann@amd.com      // Virtual Control Register
5866882SBrad.Beckmann@amd.com      case MISCREG_ICV_CTLR_EL1: {
5876882SBrad.Beckmann@amd.com          ICV_CTLR_EL1 icv_ctlr_el1 = value;
5886882SBrad.Beckmann@amd.com          icv_ctlr_el1.RSS = 0;
5896882SBrad.Beckmann@amd.com          icv_ctlr_el1.A3V = 1;
5906882SBrad.Beckmann@amd.com          icv_ctlr_el1.SEIS = 0;
5916882SBrad.Beckmann@amd.com          icv_ctlr_el1.IDbits = 1;
5927909Shestness@cs.utexas.edu          icv_ctlr_el1.PRIbits = 7;
5937909Shestness@cs.utexas.edu          value = icv_ctlr_el1;
5947909Shestness@cs.utexas.edu          break;
5957909Shestness@cs.utexas.edu      }
5967909Shestness@cs.utexas.edu
5977909Shestness@cs.utexas.edu      // Control Register
598      case MISCREG_ICC_MCTLR:
599      case MISCREG_ICC_CTLR_EL3: {
600          // Enforce value for RO bits
601          // ExtRange [19], INTIDs in the range 1024..8191 not supported
602          // RSS [18], SGIs with affinity level 0 values of 0-255 are supported
603          // nDS [17], supports disabling of security
604          // A3V [15], supports non-zero values of the Aff3 field in SGI
605          //           generation System registers
606          // SEIS [14], does not support generation of SEIs (deprecated)
607          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
608          // PRIbits [10:8], number of priority bits implemented, minus one
609          ICC_CTLR_EL3 icc_ctlr_el3 = value;
610          icc_ctlr_el3.ExtRange = 0;
611          icc_ctlr_el3.RSS = 1;
612          icc_ctlr_el3.nDS = 0;
613          icc_ctlr_el3.A3V = 1;
614          icc_ctlr_el3.SEIS = 0;
615          icc_ctlr_el3.IDbits = 0;
616          icc_ctlr_el3.PRIbits = PRIORITY_BITS - 1;
617          value = icc_ctlr_el3;
618          break;
619      }
620
621      // Hyp Control Register
622      case MISCREG_ICH_HCR:
623      case MISCREG_ICH_HCR_EL2:
624        break;
625
626      // Hyp Active Priorities Group 0 Registers
627      case MISCREG_ICH_AP0R0:
628      case MISCREG_ICH_AP0R0_EL2:
629        break;
630
631      // Hyp Active Priorities Group 1 Registers
632      case MISCREG_ICH_AP1R0:
633      case MISCREG_ICH_AP1R0_EL2:
634        break;
635
636      // Maintenance Interrupt State Register
637      case MISCREG_ICH_MISR:
638      case MISCREG_ICH_MISR_EL2:
639        value = maintenanceInterruptStatus();
640        break;
641
642      // VGIC Type Register
643      case MISCREG_ICH_VTR:
644      case MISCREG_ICH_VTR_EL2: {
645        ICH_VTR_EL2 ich_vtr_el2 = value;
646
647        ich_vtr_el2.ListRegs = VIRTUAL_NUM_LIST_REGS - 1;
648        ich_vtr_el2.A3V = 1;
649        ich_vtr_el2.IDbits = 1;
650        ich_vtr_el2.PREbits = VIRTUAL_PREEMPTION_BITS - 1;
651        ich_vtr_el2.PRIbits = VIRTUAL_PRIORITY_BITS - 1;
652
653        value = ich_vtr_el2;
654        break;
655      }
656
657      // End of Interrupt Status Register
658      case MISCREG_ICH_EISR:
659      case MISCREG_ICH_EISR_EL2:
660        value = eoiMaintenanceInterruptStatus();
661        break;
662
663      // Empty List Register Status Register
664      case MISCREG_ICH_ELRSR:
665      case MISCREG_ICH_ELRSR_EL2:
666        value = 0;
667
668        for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
669            ICH_LR_EL2 ich_lr_el2 =
670                isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
671
672            if ((ich_lr_el2.State  == ICH_LR_EL2_STATE_INVALID) &&
673                (ich_lr_el2.HW || !ich_lr_el2.EOI)) {
674                value |= (1 << lr_idx);
675            }
676        }
677
678        break;
679
680      // List Registers
681      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15:
682        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
683        value = value >> 32;
684        break;
685
686      // List Registers
687      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15:
688        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
689        value = value & 0xffffffff;
690        break;
691
692      // List Registers
693      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2:
694        break;
695
696      // Virtual Machine Control Register
697      case MISCREG_ICH_VMCR:
698      case MISCREG_ICH_VMCR_EL2:
699        break;
700
701      default:
702        panic("Gicv3CPUInterface::readMiscReg(): unknown register %d (%s)",
703              misc_reg, miscRegName[misc_reg]);
704    }
705
706    DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): register %s value %#x\n",
707            miscRegName[misc_reg], value);
708    return value;
709}
710
711void
712Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val)
713{
714    bool do_virtual_update = false;
715    DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): register %s value %#x\n",
716            miscRegName[misc_reg], val);
717    bool hcr_fmo = getHCREL2FMO();
718    bool hcr_imo = getHCREL2IMO();
719
720    switch (misc_reg) {
721      // Active Priorities Group 1 Registers
722      case MISCREG_ICC_AP1R0:
723      case MISCREG_ICC_AP1R0_EL1:
724        if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
725            return isa->setMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1, val);
726        }
727
728        break;
729
730      case MISCREG_ICC_AP1R1:
731      case MISCREG_ICC_AP1R1_EL1:
732
733        // only implemented if supporting 6 or more bits of priority
734      case MISCREG_ICC_AP1R2:
735      case MISCREG_ICC_AP1R2_EL1:
736
737        // only implemented if supporting 7 or more bits of priority
738      case MISCREG_ICC_AP1R3:
739      case MISCREG_ICC_AP1R3_EL1:
740        // only implemented if supporting 7 or more bits of priority
741        break;
742
743      // Active Priorities Group 0 Registers
744      case MISCREG_ICC_AP0R0:
745      case MISCREG_ICC_AP0R0_EL1:
746        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
747            return isa->setMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1, val);
748        }
749
750        break;
751
752      case MISCREG_ICC_AP0R1:
753      case MISCREG_ICC_AP0R1_EL1:
754
755        // only implemented if supporting 6 or more bits of priority
756      case MISCREG_ICC_AP0R2:
757      case MISCREG_ICC_AP0R2_EL1:
758
759        // only implemented if supporting 7 or more bits of priority
760      case MISCREG_ICC_AP0R3:
761      case MISCREG_ICC_AP0R3_EL1:
762        // only implemented if supporting 7 or more bits of priority
763        break;
764
765      // End Of Interrupt Register 0
766      case MISCREG_ICC_EOIR0:
767      case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0
768          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
769              return setMiscReg(MISCREG_ICV_EOIR0_EL1, val);
770          }
771
772          int int_id = val & 0xffffff;
773
774          // avoid activation for special interrupts
775          if (int_id >= Gicv3::INTID_SECURE) {
776              return;
777          }
778
779          Gicv3::GroupId group = Gicv3::G0S;
780
781          if (highestActiveGroup() != group) {
782              return;
783          }
784
785          dropPriority(group);
786
787          if (!isEOISplitMode()) {
788              deactivateIRQ(int_id, group);
789          }
790
791          break;
792      }
793
794      // Virtual End Of Interrupt Register 0
795      case MISCREG_ICV_EOIR0_EL1: {
796          int int_id = val & 0xffffff;
797
798          // avoid deactivation for special interrupts
799          if (int_id >= Gicv3::INTID_SECURE &&
800                  int_id <= Gicv3::INTID_SPURIOUS) {
801              return;
802          }
803
804          uint8_t drop_prio = virtualDropPriority();
805
806          if (drop_prio == 0xff) {
807              return;
808          }
809
810          int lr_idx = virtualFindActive(int_id);
811
812          if (lr_idx < 0) {
813              // No LR found matching
814              virtualIncrementEOICount();
815          } else {
816              ICH_LR_EL2 ich_lr_el2 =
817                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
818              Gicv3::GroupId lr_group =
819                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
820              uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8;
821
822              if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) {
823                  //if (!virtualIsEOISplitMode())
824                  {
825                      virtualDeactivateIRQ(lr_idx);
826                  }
827              }
828          }
829
830          virtualUpdate();
831          break;
832      }
833
834      // End Of Interrupt Register 1
835      case MISCREG_ICC_EOIR1:
836      case MISCREG_ICC_EOIR1_EL1: {
837          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
838              return setMiscReg(MISCREG_ICV_EOIR1_EL1, val);
839          }
840
841          int int_id = val & 0xffffff;
842
843          // avoid deactivation for special interrupts
844          if (int_id >= Gicv3::INTID_SECURE) {
845              return;
846          }
847
848          Gicv3::GroupId group = inSecureState() ? Gicv3::G1S : Gicv3::G1NS;
849
850          if (highestActiveGroup() == Gicv3::G0S) {
851              return;
852          }
853
854          if (distributor->DS == 0) {
855              if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) {
856                  return;
857              } else if (highestActiveGroup() == Gicv3::G1NS &&
858                         !(!inSecureState() or (currEL() == EL3))) {
859                  return;
860              }
861          }
862
863          dropPriority(group);
864
865          if (!isEOISplitMode()) {
866              deactivateIRQ(int_id, group);
867          }
868
869          break;
870      }
871
872      // Virtual End Of Interrupt Register 1
873      case MISCREG_ICV_EOIR1_EL1: {
874          int int_id = val & 0xffffff;
875
876          // avoid deactivation for special interrupts
877          if (int_id >= Gicv3::INTID_SECURE &&
878              int_id <= Gicv3::INTID_SPURIOUS) {
879              return;
880          }
881
882          uint8_t drop_prio = virtualDropPriority();
883
884          if (drop_prio == 0xff) {
885              return;
886          }
887
888          int lr_idx = virtualFindActive(int_id);
889
890          if (lr_idx < 0) {
891              // No matching LR found
892              virtualIncrementEOICount();
893          } else {
894              ICH_LR_EL2 ich_lr_el2 =
895                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
896              Gicv3::GroupId lr_group =
897                  ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
898              uint8_t lr_group_prio = ich_lr_el2.Priority & 0xf8;
899
900              if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) {
901                  if (!virtualIsEOISplitMode()) {
902                      virtualDeactivateIRQ(lr_idx);
903                  }
904              }
905          }
906
907          virtualUpdate();
908          break;
909      }
910
911      // Deactivate Interrupt Register
912      case MISCREG_ICC_DIR:
913      case MISCREG_ICC_DIR_EL1: {
914          if ((currEL() == EL1) && !inSecureState() &&
915              (hcr_imo || hcr_fmo)) {
916              return setMiscReg(MISCREG_ICV_DIR_EL1, val);
917          }
918
919          int int_id = val & 0xffffff;
920
921          // The following checks are as per spec pseudocode
922          // aarch64/support/ICC_DIR_EL1
923
924          // Check for spurious ID
925          if (int_id >= Gicv3::INTID_SECURE) {
926              return;
927          }
928
929          // EOI mode is not set, so don't deactivate
930          if (!isEOISplitMode()) {
931              return;
932          }
933
934          Gicv3::GroupId group =
935              int_id >= 32 ? distributor->getIntGroup(int_id) :
936              redistributor->getIntGroup(int_id);
937          bool irq_is_grp0 = group == Gicv3::G0S;
938          bool single_sec_state = distributor->DS;
939          bool irq_is_secure = !single_sec_state && (group != Gicv3::G1NS);
940          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
941          bool route_fiq_to_el3 = scr_el3.fiq;
942          bool route_irq_to_el3 = scr_el3.irq;
943          bool route_fiq_to_el2 = hcr_fmo;
944          bool route_irq_to_el2 = hcr_imo;
945
946          switch (currEL()) {
947            case EL3:
948              break;
949
950            case EL2:
951              if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) {
952                  break;
953              }
954
955              if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) {
956                  break;
957              }
958
959              return;
960
961            case EL1:
962              if (!isSecureBelowEL3()) {
963                  if (single_sec_state && irq_is_grp0 &&
964                      !route_fiq_to_el3 && !route_fiq_to_el2) {
965                      break;
966                  }
967
968                  if (!irq_is_secure && !irq_is_grp0 &&
969                      !route_irq_to_el3 && !route_irq_to_el2) {
970                      break;
971                  }
972              } else {
973                  if (irq_is_grp0 && !route_fiq_to_el3) {
974                      break;
975                  }
976
977                  if (!irq_is_grp0 &&
978                      (!irq_is_secure || !single_sec_state) &&
979                      !route_irq_to_el3) {
980                      break;
981                  }
982              }
983
984              return;
985
986            default:
987              break;
988          }
989
990          deactivateIRQ(int_id, group);
991          break;
992      }
993
994      // Deactivate Virtual Interrupt Register
995      case MISCREG_ICV_DIR_EL1: {
996          int int_id = val & 0xffffff;
997
998          // avoid deactivation for special interrupts
999          if (int_id >= Gicv3::INTID_SECURE &&
1000              int_id <= Gicv3::INTID_SPURIOUS) {
1001              return;
1002          }
1003
1004          if (!virtualIsEOISplitMode()) {
1005              return;
1006          }
1007
1008          int lr_idx = virtualFindActive(int_id);
1009
1010          if (lr_idx < 0) {
1011              // No matching LR found
1012              virtualIncrementEOICount();
1013          } else {
1014              virtualDeactivateIRQ(lr_idx);
1015          }
1016
1017          virtualUpdate();
1018          break;
1019      }
1020
1021      // Binary Point Register 0
1022      case MISCREG_ICC_BPR0:
1023      case MISCREG_ICC_BPR0_EL1:
1024      // Binary Point Register 1
1025      case MISCREG_ICC_BPR1:
1026      case MISCREG_ICC_BPR1_EL1: {
1027          if ((currEL() == EL1) && !inSecureState()) {
1028              if (misc_reg == MISCREG_ICC_BPR0_EL1 && hcr_fmo) {
1029                  return setMiscReg(MISCREG_ICV_BPR0_EL1, val);
1030              } else if (misc_reg == MISCREG_ICC_BPR1_EL1 && hcr_imo) {
1031                  return setMiscReg(MISCREG_ICV_BPR1_EL1, val);
1032              }
1033          }
1034
1035          Gicv3::GroupId group =
1036              misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S;
1037
1038          if (group == Gicv3::G1S && !inSecureState()) {
1039              group = Gicv3::G1NS;
1040          }
1041
1042          ICC_CTLR_EL1 icc_ctlr_el1_s =
1043              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1044
1045          if ((group == Gicv3::G1S) && !isEL3OrMon() &&
1046              icc_ctlr_el1_s.CBPR) {
1047              group = Gicv3::G0S;
1048          }
1049
1050          ICC_CTLR_EL1 icc_ctlr_el1_ns =
1051              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1052
1053          if ((group == Gicv3::G1NS) && (currEL() < EL3) &&
1054              icc_ctlr_el1_ns.CBPR) {
1055              // BPR0 + 1 saturated to 7, WI
1056              return;
1057          }
1058
1059          uint8_t min_val = (group == Gicv3::G1NS) ?
1060              GIC_MIN_BPR_NS : GIC_MIN_BPR;
1061          val &= 0x7;
1062
1063          if (val < min_val) {
1064              val = min_val;
1065          }
1066
1067          break;
1068      }
1069
1070      // Virtual Binary Point Register 0
1071      case MISCREG_ICV_BPR0_EL1:
1072      // Virtual Binary Point Register 1
1073      case MISCREG_ICV_BPR1_EL1: {
1074          Gicv3::GroupId group =
1075              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
1076          ICH_VMCR_EL2 ich_vmcr_el2 =
1077              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1078
1079          if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
1080              // BPR0 + 1 saturated to 7, WI
1081              return;
1082          }
1083
1084          uint8_t min_VPBR = 7 - VIRTUAL_PREEMPTION_BITS;
1085
1086          if (group != Gicv3::G0S) {
1087              min_VPBR++;
1088          }
1089
1090          if (val < min_VPBR) {
1091              val = min_VPBR;
1092          }
1093
1094          if (group == Gicv3::G0S) {
1095              ich_vmcr_el2.VBPR0 = val;
1096          } else {
1097              ich_vmcr_el2.VBPR1 = val;
1098          }
1099
1100          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1101          do_virtual_update = true;
1102          break;
1103      }
1104
1105      // Control Register EL1
1106      case MISCREG_ICC_CTLR:
1107      case MISCREG_ICC_CTLR_EL1: {
1108          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
1109              return setMiscReg(MISCREG_ICV_CTLR_EL1, val);
1110          }
1111
1112          /*
1113           * ExtRange is RO.
1114           * RSS is RO.
1115           * A3V is RO.
1116           * SEIS is RO.
1117           * IDbits is RO.
1118           * PRIbits is RO.
1119           */
1120          ICC_CTLR_EL1 requested_icc_ctlr_el1 = val;
1121          ICC_CTLR_EL1 icc_ctlr_el1 =
1122              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1);
1123
1124          ICC_CTLR_EL3 icc_ctlr_el3 =
1125              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1126
1127          // The following could be refactored but it is following
1128          // spec description section 9.2.6 point by point.
1129
1130          // PMHE
1131          if (haveEL(EL3)) {
1132              // PMHE is alias of ICC_CTLR_EL3.PMHE
1133
1134              if (distributor->DS == 0) {
1135                  // PMHE is RO
1136              } else if (distributor->DS == 1) {
1137                  // PMHE is RW
1138                  icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE;
1139                  icc_ctlr_el3.PMHE = icc_ctlr_el1.PMHE;
1140              }
1141          } else {
1142              // PMHE is RW (by implementation choice)
1143              icc_ctlr_el1.PMHE = requested_icc_ctlr_el1.PMHE;
1144          }
1145
1146          // EOImode
1147          icc_ctlr_el1.EOImode = requested_icc_ctlr_el1.EOImode;
1148
1149          if (inSecureState()) {
1150              // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1S
1151              icc_ctlr_el3.EOImode_EL1S = icc_ctlr_el1.EOImode;
1152          } else {
1153              // EOIMode is alias of ICC_CTLR_EL3.EOImode_EL1NS
1154              icc_ctlr_el3.EOImode_EL1NS = icc_ctlr_el1.EOImode;
1155          }
1156
1157          // CBPR
1158          if (haveEL(EL3)) {
1159              // CBPR is alias of ICC_CTLR_EL3.CBPR_EL1{S,NS}
1160
1161              if (distributor->DS == 0) {
1162                  // CBPR is RO
1163              } else {
1164                  // CBPR is RW
1165                  icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR;
1166
1167                  if (inSecureState()) {
1168                      icc_ctlr_el3.CBPR_EL1S = icc_ctlr_el1.CBPR;
1169                  } else {
1170                      icc_ctlr_el3.CBPR_EL1NS = icc_ctlr_el1.CBPR;
1171                  }
1172              }
1173          } else {
1174              // CBPR is RW
1175              icc_ctlr_el1.CBPR = requested_icc_ctlr_el1.CBPR;
1176          }
1177
1178          isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL3, icc_ctlr_el3);
1179
1180          val = icc_ctlr_el1;
1181          break;
1182      }
1183
1184      // Virtual Control Register
1185      case MISCREG_ICV_CTLR_EL1: {
1186         ICV_CTLR_EL1 requested_icv_ctlr_el1 = val;
1187         ICV_CTLR_EL1 icv_ctlr_el1 =
1188             isa->readMiscRegNoEffect(MISCREG_ICV_CTLR_EL1);
1189         icv_ctlr_el1.EOImode = requested_icv_ctlr_el1.EOImode;
1190         icv_ctlr_el1.CBPR = requested_icv_ctlr_el1.CBPR;
1191         val = icv_ctlr_el1;
1192
1193         // Aliases
1194         // ICV_CTLR_EL1.CBPR aliases ICH_VMCR_EL2.VCBPR.
1195         // ICV_CTLR_EL1.EOImode aliases ICH_VMCR_EL2.VEOIM.
1196         ICH_VMCR_EL2 ich_vmcr_el2 =
1197             isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1198         ich_vmcr_el2.VCBPR = icv_ctlr_el1.CBPR;
1199         ich_vmcr_el2.VEOIM = icv_ctlr_el1.EOImode;
1200         isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1201         break;
1202      }
1203
1204      // Control Register EL3
1205      case MISCREG_ICC_MCTLR:
1206      case MISCREG_ICC_CTLR_EL3: {
1207          /*
1208           * ExtRange is RO.
1209           * RSS is RO.
1210           * nDS is RO.
1211           * A3V is RO.
1212           * SEIS is RO.
1213           * IDbits is RO.
1214           * PRIbits is RO.
1215           * PMHE is RAO/WI, priority-based routing is always used.
1216           */
1217          ICC_CTLR_EL3 requested_icc_ctlr_el3 = val;
1218
1219          // Aliases
1220          if (haveEL(EL3))
1221          {
1222              ICC_CTLR_EL1 icc_ctlr_el1_s =
1223                  isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1224              ICC_CTLR_EL1 icc_ctlr_el1_ns =
1225                  isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1226
1227              // ICC_CTLR_EL1(NS).EOImode is an alias of
1228              // ICC_CTLR_EL3.EOImode_EL1NS
1229              icc_ctlr_el1_ns.EOImode = requested_icc_ctlr_el3.EOImode_EL1NS;
1230              // ICC_CTLR_EL1(S).EOImode is an alias of
1231              // ICC_CTLR_EL3.EOImode_EL1S
1232              icc_ctlr_el1_s.EOImode = requested_icc_ctlr_el3.EOImode_EL1S;
1233              // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS
1234              icc_ctlr_el1_ns.CBPR = requested_icc_ctlr_el3.CBPR_EL1NS;
1235              // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S
1236              icc_ctlr_el1_s.CBPR = requested_icc_ctlr_el3.CBPR_EL1S;
1237
1238              isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s);
1239              isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS,
1240                                      icc_ctlr_el1_ns);
1241          }
1242
1243          ICC_CTLR_EL3 icc_ctlr_el3 =
1244              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1245
1246          icc_ctlr_el3.RM = requested_icc_ctlr_el3.RM;
1247          icc_ctlr_el3.EOImode_EL1NS = requested_icc_ctlr_el3.EOImode_EL1NS;
1248          icc_ctlr_el3.EOImode_EL1S = requested_icc_ctlr_el3.EOImode_EL1S;
1249          icc_ctlr_el3.EOImode_EL3 = requested_icc_ctlr_el3.EOImode_EL3;
1250          icc_ctlr_el3.CBPR_EL1NS = requested_icc_ctlr_el3.CBPR_EL1NS;
1251          icc_ctlr_el3.CBPR_EL1S = requested_icc_ctlr_el3.CBPR_EL1S;
1252
1253          val = icc_ctlr_el3;
1254          break;
1255      }
1256
1257      // Priority Mask Register
1258      case MISCREG_ICC_PMR:
1259      case MISCREG_ICC_PMR_EL1: {
1260          if ((currEL() == EL1) && !inSecureState() && (hcr_imo || hcr_fmo)) {
1261              return isa->setMiscRegNoEffect(MISCREG_ICV_PMR_EL1, val);
1262          }
1263
1264          val &= 0xff;
1265          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
1266
1267          if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) {
1268              // Spec section 4.8.1
1269              // For Non-secure access to ICC_PMR_EL1 SCR_EL3.FIQ == 1:
1270              RegVal old_icc_pmr_el1 =
1271                  isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1);
1272
1273              if (!(old_icc_pmr_el1 & 0x80)) {
1274                  // If the current priority mask value is in the range of
1275                  // 0x00-0x7F then WI
1276                  return;
1277              }
1278
1279              // If the current priority mask value is in the range of
1280              // 0x80-0xFF then a write access to ICC_PMR_EL1 succeeds,
1281              // based on the Non-secure read of the priority mask value
1282              // written to the register.
1283
1284              val = (val >> 1) | 0x80;
1285          }
1286
1287          val &= ~0U << (8 - PRIORITY_BITS);
1288          break;
1289      }
1290
1291      // Interrupt Group 0 Enable Register EL1
1292      case MISCREG_ICC_IGRPEN0:
1293      case MISCREG_ICC_IGRPEN0_EL1: {
1294          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1295              return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val);
1296          }
1297
1298          break;
1299      }
1300
1301      // Virtual Interrupt Group 0 Enable register
1302      case MISCREG_ICV_IGRPEN0_EL1: {
1303          bool enable = val & 0x1;
1304          ICH_VMCR_EL2 ich_vmcr_el2 =
1305              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1306          ich_vmcr_el2.VENG0 = enable;
1307          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1308          virtualUpdate();
1309          return;
1310      }
1311
1312      // Interrupt Group 1 Enable register EL1
1313      case MISCREG_ICC_IGRPEN1:
1314      case MISCREG_ICC_IGRPEN1_EL1: {
1315          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1316              return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val);
1317          }
1318
1319          if (haveEL(EL3)) {
1320              ICC_IGRPEN1_EL1 icc_igrpen1_el1 = val;
1321              ICC_IGRPEN1_EL3 icc_igrpen1_el3 =
1322                  isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3);
1323
1324              if (inSecureState()) {
1325                  // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1S
1326                  icc_igrpen1_el3.EnableGrp1S = icc_igrpen1_el1.Enable;
1327              } else {
1328                  // Enable is RW alias of ICC_IGRPEN1_EL3.EnableGrp1NS
1329                  icc_igrpen1_el3.EnableGrp1NS = icc_igrpen1_el1.Enable;
1330              }
1331
1332              isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL3,
1333                                      icc_igrpen1_el3);
1334          }
1335
1336          break;
1337      }
1338
1339      // Virtual Interrupt Group 1 Enable register
1340      case MISCREG_ICV_IGRPEN1_EL1: {
1341          bool enable = val & 0x1;
1342          ICH_VMCR_EL2 ich_vmcr_el2 =
1343              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1344          ich_vmcr_el2.VENG1 = enable;
1345          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1346          virtualUpdate();
1347          return;
1348      }
1349
1350      // Interrupt Group 1 Enable register
1351      case MISCREG_ICC_MGRPEN1:
1352      case MISCREG_ICC_IGRPEN1_EL3: {
1353          ICC_IGRPEN1_EL3 icc_igrpen1_el3 = val;
1354          ICC_IGRPEN1_EL1 icc_igrpen1_el1 =
1355              isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1);
1356
1357          if (inSecureState()) {
1358              // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1S
1359              icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1S;
1360          } else {
1361              // ICC_IGRPEN1_EL1.Enable is RW alias of EnableGrp1NS
1362              icc_igrpen1_el1.Enable = icc_igrpen1_el3.EnableGrp1NS;
1363          }
1364
1365          isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1, icc_igrpen1_el1);
1366          break;
1367      }
1368
1369      // Software Generated Interrupt Group 0 Register
1370      case MISCREG_ICC_SGI0R:
1371      case MISCREG_ICC_SGI0R_EL1:
1372
1373      // Software Generated Interrupt Group 1 Register
1374      case MISCREG_ICC_SGI1R:
1375      case MISCREG_ICC_SGI1R_EL1:
1376
1377      // Alias Software Generated Interrupt Group 1 Register
1378      case MISCREG_ICC_ASGI1R:
1379      case MISCREG_ICC_ASGI1R_EL1: {
1380          bool ns = !inSecureState();
1381          Gicv3::GroupId group;
1382
1383          if (misc_reg == MISCREG_ICC_SGI1R_EL1) {
1384              group = ns ? Gicv3::G1NS : Gicv3::G1S;
1385          } else if (misc_reg == MISCREG_ICC_ASGI1R_EL1) {
1386              group = ns ? Gicv3::G1S : Gicv3::G1NS;
1387          } else {
1388              group = Gicv3::G0S;
1389          }
1390
1391          if (distributor->DS && group == Gicv3::G1S) {
1392              group = Gicv3::G0S;
1393          }
1394
1395          uint8_t aff3 = bits(val, 55, 48);
1396          uint8_t aff2 = bits(val, 39, 32);
1397          uint8_t aff1 = bits(val, 23, 16);;
1398          uint16_t target_list = bits(val, 15, 0);
1399          uint32_t int_id = bits(val, 27, 24);
1400          bool irm = bits(val, 40, 40);
1401          uint8_t rs = bits(val, 47, 44);
1402
1403          for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1404              Gicv3Redistributor * redistributor_i =
1405                  gic->getRedistributor(i);
1406              uint32_t affinity_i = redistributor_i->getAffinity();
1407
1408              if (irm) {
1409                  // Interrupts routed to all PEs in the system,
1410                  // excluding "self"
1411                  if (affinity_i == redistributor->getAffinity()) {
1412                      continue;
1413                  }
1414              } else {
1415                  // Interrupts routed to the PEs specified by
1416                  // Aff3.Aff2.Aff1.<target list>
1417                  if ((affinity_i >> 8) !=
1418                      ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) {
1419                      continue;
1420                  }
1421
1422                  uint8_t aff0_i = bits(affinity_i, 7, 0);
1423
1424                  if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 &&
1425                      ((0x1 << (aff0_i - rs * 16)) & target_list))) {
1426                      continue;
1427                  }
1428              }
1429
1430              redistributor_i->sendSGI(int_id, group, ns);
1431          }
1432
1433          break;
1434      }
1435
1436      // System Register Enable Register EL1
1437      case MISCREG_ICC_SRE:
1438      case MISCREG_ICC_SRE_EL1:
1439      // System Register Enable Register EL2
1440      case MISCREG_ICC_HSRE:
1441      case MISCREG_ICC_SRE_EL2:
1442      // System Register Enable Register EL3
1443      case MISCREG_ICC_MSRE:
1444      case MISCREG_ICC_SRE_EL3:
1445        // All bits are RAO/WI
1446        return;
1447
1448      // Hyp Control Register
1449      case MISCREG_ICH_HCR:
1450      case MISCREG_ICH_HCR_EL2: {
1451        ICH_HCR_EL2 requested_ich_hcr_el2 = val;
1452        ICH_HCR_EL2 ich_hcr_el2 =
1453            isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1454
1455        if (requested_ich_hcr_el2.EOIcount >= ich_hcr_el2.EOIcount)
1456        {
1457            // EOIcount - Permitted behaviors are:
1458            // - Increment EOIcount.
1459            // - Leave EOIcount unchanged.
1460            ich_hcr_el2.EOIcount = requested_ich_hcr_el2.EOIcount;
1461        }
1462
1463        ich_hcr_el2.TDIR = requested_ich_hcr_el2.TDIR;
1464        ich_hcr_el2.TSEI = requested_ich_hcr_el2.TSEI;
1465        ich_hcr_el2.TALL1 = requested_ich_hcr_el2.TALL1;;
1466        ich_hcr_el2.TALL0 = requested_ich_hcr_el2.TALL0;;
1467        ich_hcr_el2.TC = requested_ich_hcr_el2.TC;
1468        ich_hcr_el2.VGrp1DIE = requested_ich_hcr_el2.VGrp1DIE;
1469        ich_hcr_el2.VGrp1EIE = requested_ich_hcr_el2.VGrp1EIE;
1470        ich_hcr_el2.VGrp0DIE = requested_ich_hcr_el2.VGrp0DIE;
1471        ich_hcr_el2.VGrp0EIE = requested_ich_hcr_el2.VGrp0EIE;
1472        ich_hcr_el2.NPIE = requested_ich_hcr_el2.NPIE;
1473        ich_hcr_el2.LRENPIE = requested_ich_hcr_el2.LRENPIE;
1474        ich_hcr_el2.UIE = requested_ich_hcr_el2.UIE;
1475        ich_hcr_el2.En = requested_ich_hcr_el2.En;
1476        val = ich_hcr_el2;
1477        do_virtual_update = true;
1478        break;
1479      }
1480
1481      // List Registers
1482      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15: {
1483        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
1484        ICH_LRC requested_ich_lrc = val;
1485        ICH_LRC ich_lrc = isa->readMiscRegNoEffect(misc_reg);
1486
1487        ich_lrc.State = requested_ich_lrc.State;
1488        ich_lrc.HW = requested_ich_lrc.HW;
1489        ich_lrc.Group = requested_ich_lrc.Group;
1490
1491        // Priority, bits [23:16]
1492        // At least five bits must be implemented.
1493        // Unimplemented bits are RES0 and start from bit[16] up to bit[18].
1494        // We implement 5 bits.
1495        ich_lrc.Priority = (requested_ich_lrc.Priority & 0xf8) |
1496                           (ich_lrc.Priority & 0x07);
1497
1498        // pINTID, bits [12:0]
1499        // When ICH_LR<n>.HW is 0 this field has the following meaning:
1500        // - Bits[12:10] : RES0.
1501        // - Bit[9] : EOI.
1502        // - Bits[8:0] : RES0.
1503        // When ICH_LR<n>.HW is 1:
1504        // - This field is only required to implement enough bits to hold a
1505        // valid value for the implemented INTID size. Any unused higher
1506        // order bits are RES0.
1507        if (requested_ich_lrc.HW == 0) {
1508            ich_lrc.EOI = requested_ich_lrc.EOI;
1509        } else {
1510            ich_lrc.pINTID = requested_ich_lrc.pINTID;
1511        }
1512
1513        val = ich_lrc;
1514        do_virtual_update = true;
1515        break;
1516      }
1517
1518      // List Registers
1519      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: {
1520          // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
1521          RegVal old_val = isa->readMiscRegNoEffect(misc_reg);
1522          val = (old_val & 0xffffffff00000000) | (val & 0xffffffff);
1523          do_virtual_update = true;
1524          break;
1525      }
1526
1527      // List Registers
1528      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64
1529          ICH_LR_EL2 requested_ich_lr_el2 = val;
1530          ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(misc_reg);
1531
1532          ich_lr_el2.State = requested_ich_lr_el2.State;
1533          ich_lr_el2.HW = requested_ich_lr_el2.HW;
1534          ich_lr_el2.Group = requested_ich_lr_el2.Group;
1535
1536          // Priority, bits [55:48]
1537          // At least five bits must be implemented.
1538          // Unimplemented bits are RES0 and start from bit[48] up to bit[50].
1539          // We implement 5 bits.
1540          ich_lr_el2.Priority = (requested_ich_lr_el2.Priority & 0xf8) |
1541                                (ich_lr_el2.Priority & 0x07);
1542
1543          // pINTID, bits [44:32]
1544          // When ICH_LR<n>_EL2.HW is 0 this field has the following meaning:
1545          // - Bits[44:42] : RES0.
1546          // - Bit[41] : EOI.
1547          // - Bits[40:32] : RES0.
1548          // When ICH_LR<n>_EL2.HW is 1:
1549          // - This field is only required to implement enough bits to hold a
1550          // valid value for the implemented INTID size. Any unused higher
1551          // order bits are RES0.
1552          if (requested_ich_lr_el2.HW == 0) {
1553              ich_lr_el2.EOI = requested_ich_lr_el2.EOI;
1554          } else {
1555              ich_lr_el2.pINTID = requested_ich_lr_el2.pINTID;
1556          }
1557
1558          // vINTID, bits [31:0]
1559          // It is IMPLEMENTATION DEFINED how many bits are implemented,
1560          // though at least 16 bits must be implemented.
1561          // Unimplemented bits are RES0.
1562          ich_lr_el2.vINTID = requested_ich_lr_el2.vINTID;
1563
1564          val = ich_lr_el2;
1565          do_virtual_update = true;
1566          break;
1567      }
1568
1569      // Virtual Machine Control Register
1570      case MISCREG_ICH_VMCR:
1571      case MISCREG_ICH_VMCR_EL2: {
1572          ICH_VMCR_EL2 requested_ich_vmcr_el2 = val;
1573          ICH_VMCR_EL2 ich_vmcr_el2 =
1574              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1575          ich_vmcr_el2.VPMR = requested_ich_vmcr_el2.VPMR;
1576          uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS;
1577
1578          if (requested_ich_vmcr_el2.VBPR0 < min_vpr0) {
1579              ich_vmcr_el2.VBPR0 = min_vpr0;
1580          } else {
1581              ich_vmcr_el2.VBPR0 = requested_ich_vmcr_el2.VBPR0;
1582          }
1583
1584          uint8_t min_vpr1 = min_vpr0 + 1;
1585
1586          if (requested_ich_vmcr_el2.VBPR1 < min_vpr1) {
1587              ich_vmcr_el2.VBPR1 = min_vpr1;
1588          } else {
1589              ich_vmcr_el2.VBPR1 = requested_ich_vmcr_el2.VBPR1;
1590          }
1591
1592          ich_vmcr_el2.VEOIM = requested_ich_vmcr_el2.VEOIM;
1593          ich_vmcr_el2.VCBPR = requested_ich_vmcr_el2.VCBPR;
1594          ich_vmcr_el2.VENG1 = requested_ich_vmcr_el2.VENG1;
1595          ich_vmcr_el2.VENG0 = requested_ich_vmcr_el2.VENG0;
1596          val = ich_vmcr_el2;
1597          break;
1598      }
1599
1600      // Hyp Active Priorities Group 0 Registers
1601      case MISCREG_ICH_AP0R0 ... MISCREG_ICH_AP0R3:
1602      case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_AP0R3_EL2:
1603      // Hyp Active Priorities Group 1 Registers
1604      case MISCREG_ICH_AP1R0 ... MISCREG_ICH_AP1R3:
1605      case MISCREG_ICH_AP1R0_EL2 ... MISCREG_ICH_AP1R3_EL2:
1606        break;
1607
1608      default:
1609        panic("Gicv3CPUInterface::setMiscReg(): unknown register %d (%s)",
1610              misc_reg, miscRegName[misc_reg]);
1611    }
1612
1613    isa->setMiscRegNoEffect(misc_reg, val);
1614
1615    if (do_virtual_update) {
1616        virtualUpdate();
1617    }
1618}
1619
1620int
1621Gicv3CPUInterface::virtualFindActive(uint32_t int_id) const
1622{
1623    for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
1624        ICH_LR_EL2 ich_lr_el2 =
1625            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1626
1627        if (((ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE) ||
1628             (ich_lr_el2.State == ICH_LR_EL2_STATE_ACTIVE_PENDING)) &&
1629            (ich_lr_el2.vINTID == int_id)) {
1630            return lr_idx;
1631        }
1632    }
1633
1634    return -1;
1635}
1636
1637uint32_t
1638Gicv3CPUInterface::getHPPIR0() const
1639{
1640    if (hppi.prio == 0xff) {
1641        return Gicv3::INTID_SPURIOUS;
1642    }
1643
1644    bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS;
1645
1646    if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) {
1647        // interrupt for the other state pending
1648        return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE;
1649    }
1650
1651    if ((hppi.group != Gicv3::G0S)) { // && !isEL3OrMon())
1652        return Gicv3::INTID_SPURIOUS;
1653    }
1654
1655    if (irq_is_secure && !inSecureState()) {
1656        // Secure interrupts not visible in Non-secure
1657        return Gicv3::INTID_SPURIOUS;
1658    }
1659
1660    return hppi.intid;
1661}
1662
1663uint32_t
1664Gicv3CPUInterface::getHPPIR1() const
1665{
1666    if (hppi.prio == 0xff) {
1667        return Gicv3::INTID_SPURIOUS;
1668    }
1669
1670    ICC_CTLR_EL3 icc_ctlr_el3 = isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1671    if ((currEL() == EL3) && icc_ctlr_el3.RM) {
1672        if (hppi.group == Gicv3::G0S) {
1673            return Gicv3::INTID_SECURE;
1674        } else if (hppi.group == Gicv3::G1NS) {
1675            return Gicv3::INTID_NONSECURE;
1676        }
1677    }
1678
1679    if (hppi.group == Gicv3::G0S) {
1680        return Gicv3::INTID_SPURIOUS;
1681    }
1682
1683    bool irq_is_secure = (distributor->DS == 0) && (hppi.group != Gicv3::G1NS);
1684
1685    if (irq_is_secure) {
1686        if (!inSecureState()) {
1687            // Secure interrupts not visible in Non-secure
1688            return Gicv3::INTID_SPURIOUS;
1689        }
1690    } else if (!isEL3OrMon() && inSecureState()) {
1691        // Group 1 non-secure interrupts not visible in Secure EL1
1692        return Gicv3::INTID_SPURIOUS;
1693    }
1694
1695    return hppi.intid;
1696}
1697
1698void
1699Gicv3CPUInterface::dropPriority(Gicv3::GroupId group)
1700{
1701    int apr_misc_reg;
1702    RegVal apr;
1703    apr_misc_reg = group == Gicv3::G0S ?
1704                   MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1705    apr = isa->readMiscRegNoEffect(apr_misc_reg);
1706
1707    if (apr) {
1708        apr &= apr - 1;
1709        isa->setMiscRegNoEffect(apr_misc_reg, apr);
1710    }
1711
1712    update();
1713}
1714
1715uint8_t
1716Gicv3CPUInterface::virtualDropPriority()
1717{
1718    int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5);
1719
1720    for (int i = 0; i < apr_max; i++) {
1721        RegVal vapr0 = isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i);
1722        RegVal vapr1 = isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
1723
1724        if (!vapr0 && !vapr1) {
1725            continue;
1726        }
1727
1728        int vapr0_count = ctz32(vapr0);
1729        int vapr1_count = ctz32(vapr1);
1730
1731        if (vapr0_count <= vapr1_count) {
1732            vapr0 &= vapr0 - 1;
1733            isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0);
1734            return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1);
1735        } else {
1736            vapr1 &= vapr1 - 1;
1737            isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1);
1738            return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1);
1739        }
1740    }
1741
1742    return 0xff;
1743}
1744
1745void
1746Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
1747{
1748    // Update active priority registers.
1749    uint32_t prio = hppi.prio & 0xf8;
1750    int apr_bit = prio >> (8 - PRIORITY_BITS);
1751    int reg_bit = apr_bit % 32;
1752    int apr_idx = group == Gicv3::G0S ?
1753                 MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1754    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1755    apr |= (1 << reg_bit);
1756    isa->setMiscRegNoEffect(apr_idx, apr);
1757
1758    // Move interrupt state from pending to active.
1759    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1760        // SGI or PPI, redistributor
1761        redistributor->activateIRQ(int_id);
1762        redistributor->updateAndInformCPUInterface();
1763    } else if (int_id < Gicv3::INTID_SECURE) {
1764        // SPI, distributor
1765        distributor->activateIRQ(int_id);
1766        distributor->updateAndInformCPUInterfaces();
1767    }
1768}
1769
1770void
1771Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx)
1772{
1773    // Update active priority registers.
1774    ICH_LR_EL2 ich_lr_el = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1775            lr_idx);
1776    Gicv3::GroupId group = ich_lr_el.Group ? Gicv3::G1NS : Gicv3::G0S;
1777    uint8_t prio = ich_lr_el.Priority & 0xf8;
1778    int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS);
1779    int reg_no = apr_bit / 32;
1780    int reg_bit = apr_bit % 32;
1781    int apr_idx = group == Gicv3::G0S ?
1782        MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no;
1783    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1784    apr |= (1 << reg_bit);
1785    isa->setMiscRegNoEffect(apr_idx, apr);
1786    // Move interrupt state from pending to active.
1787    ich_lr_el.State = ICH_LR_EL2_STATE_ACTIVE;
1788    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el);
1789}
1790
1791void
1792Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group)
1793{
1794    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1795        // SGI or PPI, redistributor
1796        redistributor->deactivateIRQ(int_id);
1797        redistributor->updateAndInformCPUInterface();
1798    } else if (int_id < Gicv3::INTID_SECURE) {
1799        // SPI, distributor
1800        distributor->deactivateIRQ(int_id);
1801        distributor->updateAndInformCPUInterfaces();
1802    } else {
1803        return;
1804    }
1805}
1806
1807void
1808Gicv3CPUInterface::virtualDeactivateIRQ(int lr_idx)
1809{
1810    ICH_LR_EL2 ich_lr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1811            lr_idx);
1812
1813    if (ich_lr_el2.HW) {
1814        // Deactivate the associated physical interrupt
1815        if (ich_lr_el2.pINTID < Gicv3::INTID_SECURE) {
1816            Gicv3::GroupId group = ich_lr_el2.pINTID >= 32 ?
1817                distributor->getIntGroup(ich_lr_el2.pINTID) :
1818                redistributor->getIntGroup(ich_lr_el2.pINTID);
1819            deactivateIRQ(ich_lr_el2.pINTID, group);
1820        }
1821    }
1822
1823    //  Remove the active bit
1824    ich_lr_el2.State = ich_lr_el2.State & ~ICH_LR_EL2_STATE_ACTIVE;
1825    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, ich_lr_el2);
1826}
1827
1828/*
1829 * Returns the priority group field for the current BPR value for the group.
1830 * GroupBits() Pseudocode from spec.
1831 */
1832uint32_t
1833Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group) const
1834{
1835    ICC_CTLR_EL1 icc_ctlr_el1_s =
1836        isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1837    ICC_CTLR_EL1 icc_ctlr_el1_ns =
1838        isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1839
1840    if ((group == Gicv3::G1S && icc_ctlr_el1_s.CBPR) ||
1841        (group == Gicv3::G1NS && icc_ctlr_el1_ns.CBPR)) {
1842        group = Gicv3::G0S;
1843    }
1844
1845    int bpr;
1846
1847    if (group == Gicv3::G0S) {
1848        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) & 0x7;
1849    } else {
1850        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1) & 0x7;
1851    }
1852
1853    if (group == Gicv3::G1NS) {
1854        assert(bpr > 0);
1855        bpr--;
1856    }
1857
1858    return ~0U << (bpr + 1);
1859}
1860
1861uint32_t
1862Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group) const
1863{
1864    ICH_VMCR_EL2 ich_vmcr_el2 =
1865        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1866
1867    if ((group == Gicv3::G1NS) && ich_vmcr_el2.VCBPR) {
1868        group = Gicv3::G0S;
1869    }
1870
1871    int bpr;
1872
1873    if (group == Gicv3::G0S) {
1874        bpr = ich_vmcr_el2.VBPR0;
1875    } else {
1876        bpr = ich_vmcr_el2.VBPR1;
1877    }
1878
1879    if (group == Gicv3::G1NS) {
1880        assert(bpr > 0);
1881        bpr--;
1882    }
1883
1884    return ~0U << (bpr + 1);
1885}
1886
1887bool
1888Gicv3CPUInterface::isEOISplitMode() const
1889{
1890    if (isEL3OrMon()) {
1891        ICC_CTLR_EL3 icc_ctlr_el3 =
1892            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1893        return icc_ctlr_el3.EOImode_EL3;
1894    } else {
1895        ICC_CTLR_EL1 icc_ctlr_el1 =
1896            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1);
1897        return icc_ctlr_el1.EOImode;
1898    }
1899}
1900
1901bool
1902Gicv3CPUInterface::virtualIsEOISplitMode() const
1903{
1904    ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1905    return ich_vmcr_el2.VEOIM;
1906}
1907
1908int
1909Gicv3CPUInterface::highestActiveGroup() const
1910{
1911    int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1));
1912    int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S));
1913    int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS));
1914
1915    if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) {
1916        return Gicv3::G1NS;
1917    }
1918
1919    if (gq_ctz < g0_ctz) {
1920        return Gicv3::G1S;
1921    }
1922
1923    if (g0_ctz < 32) {
1924        return Gicv3::G0S;
1925    }
1926
1927    return -1;
1928}
1929
1930void
1931Gicv3CPUInterface::update()
1932{
1933    bool signal_IRQ = false;
1934    bool signal_FIQ = false;
1935
1936    if (hppi.group == Gicv3::G1S && !haveEL(EL3)) {
1937        /*
1938         * Secure enabled GIC sending a G1S IRQ to a secure disabled
1939         * CPU -> send G0 IRQ
1940         */
1941        hppi.group = Gicv3::G0S;
1942    }
1943
1944    if (hppiCanPreempt()) {
1945        ArmISA::InterruptTypes int_type = intSignalType(hppi.group);
1946        DPRINTF(GIC, "Gicv3CPUInterface::update(): "
1947                "posting int as %d!\n", int_type);
1948        int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true;
1949    }
1950
1951    if (signal_IRQ) {
1952        gic->postInt(cpuId, ArmISA::INT_IRQ);
1953    } else {
1954        gic->deassertInt(cpuId, ArmISA::INT_IRQ);
1955    }
1956
1957    if (signal_FIQ) {
1958        gic->postInt(cpuId, ArmISA::INT_FIQ);
1959    } else {
1960        gic->deassertInt(cpuId, ArmISA::INT_FIQ);
1961    }
1962}
1963
1964void
1965Gicv3CPUInterface::virtualUpdate()
1966{
1967    bool signal_IRQ = false;
1968    bool signal_FIQ = false;
1969    int lr_idx = getHPPVILR();
1970
1971    if (lr_idx >= 0) {
1972        ICH_LR_EL2 ich_lr_el2 =
1973            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1974
1975        if (hppviCanPreempt(lr_idx)) {
1976            if (ich_lr_el2.Group) {
1977                signal_IRQ = true;
1978            } else {
1979                signal_FIQ = true;
1980            }
1981        }
1982    }
1983
1984    ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1985
1986    if (ich_hcr_el2.En) {
1987        if (maintenanceInterruptStatus()) {
1988            redistributor->sendPPInt(25);
1989        }
1990    }
1991
1992    if (signal_IRQ) {
1993        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
1994                "posting int as %d!\n", ArmISA::INT_VIRT_IRQ);
1995        gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ);
1996    } else {
1997        gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ);
1998    }
1999
2000    if (signal_FIQ) {
2001        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
2002                "posting int as %d!\n", ArmISA::INT_VIRT_FIQ);
2003        gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ);
2004    } else {
2005        gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ);
2006    }
2007}
2008
2009// Returns the index of the LR with the HPPI
2010int
2011Gicv3CPUInterface::getHPPVILR() const
2012{
2013    int idx = -1;
2014    ICH_VMCR_EL2 ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2015
2016    if (!ich_vmcr_el2.VENG0 && !ich_vmcr_el2.VENG1) {
2017        // VG0 and VG1 disabled...
2018        return idx;
2019    }
2020
2021    uint8_t highest_prio = 0xff;
2022
2023    for (int i = 0; i < 16; i++) {
2024        ICH_LR_EL2 ich_lr_el2 =
2025            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i);
2026
2027        if (ich_lr_el2.State != Gicv3::INT_PENDING) {
2028            continue;
2029        }
2030
2031        if (ich_lr_el2.Group) {
2032            // VG1
2033            if (!ich_vmcr_el2.VENG1) {
2034                continue;
2035            }
2036        } else {
2037            // VG0
2038            if (!ich_vmcr_el2.VENG0) {
2039                continue;
2040            }
2041        }
2042
2043        uint8_t prio = ich_lr_el2.Priority;
2044
2045        if (prio < highest_prio) {
2046            highest_prio = prio;
2047            idx = i;
2048        }
2049    }
2050
2051    return idx;
2052}
2053
2054bool
2055Gicv3CPUInterface::hppviCanPreempt(int lr_idx) const
2056{
2057    ICH_HCR_EL2 ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2058    if (!ich_hcr_el2.En) {
2059        // virtual interface is disabled
2060        return false;
2061    }
2062
2063    ICH_LR_EL2 ich_lr_el2 =
2064        isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2065    uint8_t prio = ich_lr_el2.Priority;
2066    uint8_t vpmr =
2067        bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24);
2068
2069    if (prio >= vpmr) {
2070        // prioriry masked
2071        return false;
2072    }
2073
2074    uint8_t rprio = virtualHighestActivePriority();
2075
2076    if (rprio == 0xff) {
2077        return true;
2078    }
2079
2080    Gicv3::GroupId group = ich_lr_el2.Group ? Gicv3::G1NS : Gicv3::G0S;
2081    uint32_t prio_mask = virtualGroupPriorityMask(group);
2082
2083    if ((prio & prio_mask) < (rprio & prio_mask)) {
2084        return true;
2085    }
2086
2087    return false;
2088}
2089
2090uint8_t
2091Gicv3CPUInterface::virtualHighestActivePriority() const
2092{
2093    uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5);
2094
2095    for (int i = 0; i < num_aprs; i++) {
2096        RegVal vapr =
2097            isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) |
2098            isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
2099
2100        if (!vapr) {
2101            continue;
2102        }
2103
2104        return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1);
2105    }
2106
2107    // no active interrups, return idle priority
2108    return 0xff;
2109}
2110
2111void
2112Gicv3CPUInterface::virtualIncrementEOICount()
2113{
2114    // Increment the EOICOUNT field in ICH_HCR_EL2
2115    RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2116    uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27);
2117    EOI_cout++;
2118    ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout);
2119    isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2);
2120}
2121
2122// spec section 4.6.2
2123ArmISA::InterruptTypes
2124Gicv3CPUInterface::intSignalType(Gicv3::GroupId group) const
2125{
2126    bool is_fiq = false;
2127
2128    switch (group) {
2129      case Gicv3::G0S:
2130        is_fiq = true;
2131        break;
2132
2133      case Gicv3::G1S:
2134        is_fiq = (distributor->DS == 0) &&
2135            (!inSecureState() || ((currEL() == EL3) && isAA64()));
2136        break;
2137
2138      case Gicv3::G1NS:
2139        is_fiq = (distributor->DS == 0) && inSecureState();
2140        break;
2141
2142      default:
2143        panic("Gicv3CPUInterface::intSignalType(): invalid group!");
2144    }
2145
2146    if (is_fiq) {
2147        return ArmISA::INT_FIQ;
2148    } else {
2149        return ArmISA::INT_IRQ;
2150    }
2151}
2152
2153bool
2154Gicv3CPUInterface::hppiCanPreempt() const
2155{
2156    if (hppi.prio == 0xff) {
2157        // there is no pending interrupt
2158        return false;
2159    }
2160
2161    if (!groupEnabled(hppi.group)) {
2162        // group disabled at CPU interface
2163        return false;
2164    }
2165
2166    if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) {
2167        // priority masked
2168        return false;
2169    }
2170
2171    uint8_t rprio = highestActivePriority();
2172
2173    if (rprio == 0xff) {
2174        return true;
2175    }
2176
2177    uint32_t prio_mask = groupPriorityMask(hppi.group);
2178
2179    if ((hppi.prio & prio_mask) < (rprio & prio_mask)) {
2180        return true;
2181    }
2182
2183    return false;
2184}
2185
2186uint8_t
2187Gicv3CPUInterface::highestActivePriority() const
2188{
2189    uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) |
2190                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) |
2191                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S);
2192
2193    if (apr) {
2194        return ctz32(apr) << (GIC_MIN_BPR + 1);
2195    }
2196
2197    // no active interrups, return idle priority
2198    return 0xff;
2199}
2200
2201bool
2202Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group) const
2203{
2204    switch (group) {
2205      case Gicv3::G0S: {
2206        ICC_IGRPEN0_EL1 icc_igrpen0_el1 =
2207            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1);
2208        return icc_igrpen0_el1.Enable;
2209      }
2210
2211      case Gicv3::G1S: {
2212        ICC_IGRPEN1_EL1 icc_igrpen1_el1_s =
2213            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S);
2214        return icc_igrpen1_el1_s.Enable;
2215      }
2216
2217      case Gicv3::G1NS: {
2218        ICC_IGRPEN1_EL1 icc_igrpen1_el1_ns =
2219            isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS);
2220        return icc_igrpen1_el1_ns.Enable;
2221      }
2222
2223      default:
2224        panic("Gicv3CPUInterface::groupEnable(): invalid group!\n");
2225    }
2226}
2227
2228bool
2229Gicv3CPUInterface::inSecureState() const
2230{
2231    if (!gic->getSystem()->haveSecurity()) {
2232        return false;
2233    }
2234
2235    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2236    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR);
2237    return ArmISA::inSecureState(scr, cpsr);
2238}
2239
2240int
2241Gicv3CPUInterface::currEL() const
2242{
2243    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2244    bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2245
2246    if (is_64) {
2247        return (ExceptionLevel)(uint8_t) cpsr.el;
2248    } else {
2249        switch (cpsr.mode) {
2250          case MODE_USER:
2251            return 0;
2252
2253          case MODE_HYP:
2254            return 2;
2255
2256          case MODE_MON:
2257            return 3;
2258
2259          default:
2260            return 1;
2261        }
2262    }
2263}
2264
2265bool
2266Gicv3CPUInterface::haveEL(ExceptionLevel el) const
2267{
2268    switch (el) {
2269      case EL0:
2270      case EL1:
2271        return true;
2272
2273      case EL2:
2274        return gic->getSystem()->haveVirtualization();
2275
2276      case EL3:
2277        return gic->getSystem()->haveSecurity();
2278
2279      default:
2280        warn("Unimplemented Exception Level\n");
2281        return false;
2282    }
2283}
2284
2285bool
2286Gicv3CPUInterface::isSecureBelowEL3() const
2287{
2288    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
2289    return haveEL(EL3) && scr.ns == 0;
2290}
2291
2292bool
2293Gicv3CPUInterface::isAA64() const
2294{
2295    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2296    return opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2297}
2298
2299bool
2300Gicv3CPUInterface::isEL3OrMon() const
2301{
2302    if (haveEL(EL3)) {
2303        CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2304        bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2305
2306        if (is_64 && (cpsr.el == EL3)) {
2307            return true;
2308        } else if (!is_64 && (cpsr.mode == MODE_MON)) {
2309            return true;
2310        }
2311    }
2312
2313    return false;
2314}
2315
2316// Computes ICH_EISR_EL2
2317uint64_t
2318Gicv3CPUInterface::eoiMaintenanceInterruptStatus() const
2319{
2320    // ICH_EISR_EL2
2321    // Bits [63:16] - RES0
2322    // Status<n>, bit [n], for n = 0 to 15
2323    //   EOI maintenance interrupt status bit for List register <n>:
2324    //     0 if List register <n>, ICH_LR<n>_EL2, does not have an EOI
2325    //     maintenance interrupt.
2326    //     1 if List register <n>, ICH_LR<n>_EL2, has an EOI maintenance
2327    //     interrupt that has not been handled.
2328    //
2329    // For any ICH_LR<n>_EL2, the corresponding status bit is set to 1 if all
2330    // of the following are true:
2331    // - ICH_LR<n>_EL2.State is 0b00 (ICH_LR_EL2_STATE_INVALID).
2332    // - ICH_LR<n>_EL2.HW is 0.
2333    // - ICH_LR<n>_EL2.EOI (bit [41]) is 1.
2334
2335    uint64_t value = 0;
2336
2337    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2338        ICH_LR_EL2 ich_lr_el2 =
2339            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2340
2341        if ((ich_lr_el2.State == ICH_LR_EL2_STATE_INVALID) &&
2342            !ich_lr_el2.HW && ich_lr_el2.EOI) {
2343            value |= (1 << lr_idx);
2344        }
2345    }
2346
2347    return value;
2348}
2349
2350Gicv3CPUInterface::ICH_MISR_EL2
2351Gicv3CPUInterface::maintenanceInterruptStatus() const
2352{
2353    // Comments are copied from SPEC section 9.4.7 (ID012119)
2354    ICH_MISR_EL2 ich_misr_el2 = 0;
2355    ICH_HCR_EL2 ich_hcr_el2 =
2356        isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2357    ICH_VMCR_EL2 ich_vmcr_el2 =
2358        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2359
2360    // End Of Interrupt. [bit 0]
2361    // This maintenance interrupt is asserted when at least one bit in
2362    // ICH_EISR_EL2 is 1.
2363
2364    if (eoiMaintenanceInterruptStatus()) {
2365        ich_misr_el2.EOI = 1;
2366    }
2367
2368    // Underflow. [bit 1]
2369    // This maintenance interrupt is asserted when ICH_HCR_EL2.UIE==1 and
2370    // zero or one of the List register entries are marked as a valid
2371    // interrupt, that is, if the corresponding ICH_LR<n>_EL2.State bits
2372    // do not equal 0x0.
2373    uint32_t num_valid_interrupts = 0;
2374    uint32_t num_pending_interrupts = 0;
2375
2376    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2377        ICH_LR_EL2 ich_lr_el2 =
2378            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2379
2380        if (ich_lr_el2.State != ICH_LR_EL2_STATE_INVALID) {
2381            num_valid_interrupts++;
2382        }
2383
2384        if (ich_lr_el2.State == ICH_LR_EL2_STATE_PENDING) {
2385            num_pending_interrupts++;
2386        }
2387    }
2388
2389    if (ich_hcr_el2.UIE && (num_valid_interrupts < 2)) {
2390        ich_misr_el2.U = 1;
2391    }
2392
2393    // List Register Entry Not Present. [bit 2]
2394    // This maintenance interrupt is asserted when ICH_HCR_EL2.LRENPIE==1
2395    // and ICH_HCR_EL2.EOIcount is non-zero.
2396    if (ich_hcr_el2.LRENPIE && ich_hcr_el2.EOIcount) {
2397        ich_misr_el2.LRENP = 1;
2398    }
2399
2400    // No Pending. [bit 3]
2401    // This maintenance interrupt is asserted when ICH_HCR_EL2.NPIE==1 and
2402    // no List register is in pending state.
2403    if (ich_hcr_el2.NPIE && (num_pending_interrupts == 0)) {
2404        ich_misr_el2.NP = 1;
2405    }
2406
2407    // vPE Group 0 Enabled. [bit 4]
2408    // This maintenance interrupt is asserted when
2409    // ICH_HCR_EL2.VGrp0EIE==1 and ICH_VMCR_EL2.VENG0==1.
2410    if (ich_hcr_el2.VGrp0EIE && ich_vmcr_el2.VENG0) {
2411        ich_misr_el2.VGrp0E = 1;
2412    }
2413
2414    // vPE Group 0 Disabled. [bit 5]
2415    // This maintenance interrupt is asserted when
2416    // ICH_HCR_EL2.VGrp0DIE==1 and ICH_VMCR_EL2.VENG0==0.
2417    if (ich_hcr_el2.VGrp0DIE && !ich_vmcr_el2.VENG0) {
2418        ich_misr_el2.VGrp0D = 1;
2419    }
2420
2421    // vPE Group 1 Enabled. [bit 6]
2422    // This maintenance interrupt is asserted when
2423    // ICH_HCR_EL2.VGrp1EIE==1 and ICH_VMCR_EL2.VENG1==is 1.
2424    if (ich_hcr_el2.VGrp1EIE && ich_vmcr_el2.VENG1) {
2425        ich_misr_el2.VGrp1E = 1;
2426    }
2427
2428    // vPE Group 1 Disabled. [bit 7]
2429    // This maintenance interrupt is asserted when
2430    // ICH_HCR_EL2.VGrp1DIE==1 and ICH_VMCR_EL2.VENG1==is 0.
2431    if (ich_hcr_el2.VGrp1DIE && !ich_vmcr_el2.VENG1) {
2432        ich_misr_el2.VGrp1D = 1;
2433    }
2434
2435    return ich_misr_el2;
2436}
2437
2438void
2439Gicv3CPUInterface::serialize(CheckpointOut & cp) const
2440{
2441    SERIALIZE_SCALAR(hppi.intid);
2442    SERIALIZE_SCALAR(hppi.prio);
2443    SERIALIZE_ENUM(hppi.group);
2444}
2445
2446void
2447Gicv3CPUInterface::unserialize(CheckpointIn & cp)
2448{
2449    UNSERIALIZE_SCALAR(hppi.intid);
2450    UNSERIALIZE_SCALAR(hppi.prio);
2451    UNSERIALIZE_ENUM(hppi.group);
2452}
2453