gic_v3_redistributor.cc revision 13928
113531Sjairo.balart@metempsy.com/*
213531Sjairo.balart@metempsy.com * Copyright (c) 2018 Metempsy Technology Consulting
313531Sjairo.balart@metempsy.com * All rights reserved.
413531Sjairo.balart@metempsy.com *
513531Sjairo.balart@metempsy.com * Redistribution and use in source and binary forms, with or without
613531Sjairo.balart@metempsy.com * modification, are permitted provided that the following conditions are
713531Sjairo.balart@metempsy.com * met: redistributions of source code must retain the above copyright
813531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer;
913531Sjairo.balart@metempsy.com * redistributions in binary form must reproduce the above copyright
1013531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer in the
1113531Sjairo.balart@metempsy.com * documentation and/or other materials provided with the distribution;
1213531Sjairo.balart@metempsy.com * neither the name of the copyright holders nor the names of its
1313531Sjairo.balart@metempsy.com * contributors may be used to endorse or promote products derived from
1413531Sjairo.balart@metempsy.com * this software without specific prior written permission.
1513531Sjairo.balart@metempsy.com *
1613531Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1713531Sjairo.balart@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1813531Sjairo.balart@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1913531Sjairo.balart@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2013531Sjairo.balart@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
2113531Sjairo.balart@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
2213531Sjairo.balart@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2313531Sjairo.balart@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2413531Sjairo.balart@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2513531Sjairo.balart@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2613531Sjairo.balart@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2713531Sjairo.balart@metempsy.com *
2813531Sjairo.balart@metempsy.com * Authors: Jairo Balart
2913531Sjairo.balart@metempsy.com */
3013531Sjairo.balart@metempsy.com
3113531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_redistributor.hh"
3213531Sjairo.balart@metempsy.com
3313531Sjairo.balart@metempsy.com#include "arch/arm/utility.hh"
3413531Sjairo.balart@metempsy.com#include "debug/GIC.hh"
3513531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_cpu_interface.hh"
3613531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_distributor.hh"
3713690Sjairo.balart@metempsy.com#include "mem/fs_translating_port_proxy.hh"
3813531Sjairo.balart@metempsy.com
3913531Sjairo.balart@metempsy.comconst AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
4013756Sjairo.balart@metempsy.com                                                    SGI_base + 0x041f);
4113531Sjairo.balart@metempsy.com
4213531Sjairo.balart@metempsy.comGicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
4313531Sjairo.balart@metempsy.com    : gic(gic),
4413531Sjairo.balart@metempsy.com      distributor(nullptr),
4513531Sjairo.balart@metempsy.com      cpuInterface(nullptr),
4613531Sjairo.balart@metempsy.com      cpuId(cpu_id),
4713928Sgiacomo.travaglini@arm.com      memProxy(nullptr),
4813531Sjairo.balart@metempsy.com      irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
4913531Sjairo.balart@metempsy.com      irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5013531Sjairo.balart@metempsy.com      irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5113531Sjairo.balart@metempsy.com      irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5213531Sjairo.balart@metempsy.com      irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5313531Sjairo.balart@metempsy.com      irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5413531Sjairo.balart@metempsy.com      irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5513878Sgiacomo.travaglini@arm.com      irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX),
5613878Sgiacomo.travaglini@arm.com      addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
5713531Sjairo.balart@metempsy.com{
5813531Sjairo.balart@metempsy.com}
5913531Sjairo.balart@metempsy.com
6013531Sjairo.balart@metempsy.comvoid
6113531Sjairo.balart@metempsy.comGicv3Redistributor::init()
6213531Sjairo.balart@metempsy.com{
6313531Sjairo.balart@metempsy.com    distributor = gic->getDistributor();
6413531Sjairo.balart@metempsy.com    cpuInterface = gic->getCPUInterface(cpuId);
6513928Sgiacomo.travaglini@arm.com
6613928Sgiacomo.travaglini@arm.com    memProxy = &gic->getSystem()->physProxy;
6713531Sjairo.balart@metempsy.com}
6813531Sjairo.balart@metempsy.com
6913531Sjairo.balart@metempsy.comvoid
7013531Sjairo.balart@metempsy.comGicv3Redistributor::initState()
7113531Sjairo.balart@metempsy.com{
7213531Sjairo.balart@metempsy.com    reset();
7313531Sjairo.balart@metempsy.com}
7413531Sjairo.balart@metempsy.com
7513531Sjairo.balart@metempsy.comvoid
7613531Sjairo.balart@metempsy.comGicv3Redistributor::reset()
7713531Sjairo.balart@metempsy.com{
7813531Sjairo.balart@metempsy.com    peInLowPowerState = true;
7913531Sjairo.balart@metempsy.com    std::fill(irqGroup.begin(), irqGroup.end(), 0);
8013531Sjairo.balart@metempsy.com    std::fill(irqEnabled.begin(), irqEnabled.end(), false);
8113531Sjairo.balart@metempsy.com    std::fill(irqPending.begin(), irqPending.end(), false);
8213531Sjairo.balart@metempsy.com    std::fill(irqActive.begin(), irqActive.end(), false);
8313531Sjairo.balart@metempsy.com    std::fill(irqPriority.begin(), irqPriority.end(), 0);
8413531Sjairo.balart@metempsy.com
8513531Sjairo.balart@metempsy.com    // SGIs have edge-triggered behavior
8613531Sjairo.balart@metempsy.com    for (uint32_t int_id = 0; int_id < Gicv3::SGI_MAX; int_id++) {
8713531Sjairo.balart@metempsy.com        irqConfig[int_id] = Gicv3::INT_EDGE_TRIGGERED;
8813531Sjairo.balart@metempsy.com    }
8913531Sjairo.balart@metempsy.com
9013531Sjairo.balart@metempsy.com    std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
9113531Sjairo.balart@metempsy.com    std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
9213531Sjairo.balart@metempsy.com    DPG1S = false;
9313531Sjairo.balart@metempsy.com    DPG1NS = false;
9413531Sjairo.balart@metempsy.com    DPG0 = false;
9513690Sjairo.balart@metempsy.com    EnableLPIs = false;
9613690Sjairo.balart@metempsy.com    lpiConfigurationTablePtr = 0;
9713690Sjairo.balart@metempsy.com    lpiIDBits = 0;
9813690Sjairo.balart@metempsy.com    lpiPendingTablePtr = 0;
9913531Sjairo.balart@metempsy.com}
10013531Sjairo.balart@metempsy.com
10113531Sjairo.balart@metempsy.comuint64_t
10213531Sjairo.balart@metempsy.comGicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
10313531Sjairo.balart@metempsy.com{
10413531Sjairo.balart@metempsy.com    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
10513531Sjairo.balart@metempsy.com        uint64_t value = 0;
10613531Sjairo.balart@metempsy.com        int first_intid = addr - GICR_IPRIORITYR.start();
10713531Sjairo.balart@metempsy.com
10813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
10913531Sjairo.balart@metempsy.com            uint8_t prio = irqPriority[int_id];
11013531Sjairo.balart@metempsy.com
11113531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
11213531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
11313531Sjairo.balart@metempsy.com                    // RAZ/WI for non-secure accesses for secure interrupts
11413531Sjairo.balart@metempsy.com                    continue;
11513531Sjairo.balart@metempsy.com                } else {
11613531Sjairo.balart@metempsy.com                    // NS view
11713531Sjairo.balart@metempsy.com                    prio = (prio << 1) & 0xff;
11813531Sjairo.balart@metempsy.com                }
11913531Sjairo.balart@metempsy.com            }
12013531Sjairo.balart@metempsy.com
12113531Sjairo.balart@metempsy.com            value |= prio << (i * 8);
12213531Sjairo.balart@metempsy.com        }
12313531Sjairo.balart@metempsy.com
12413531Sjairo.balart@metempsy.com        return value;
12513531Sjairo.balart@metempsy.com    }
12613531Sjairo.balart@metempsy.com
12713531Sjairo.balart@metempsy.com    switch (addr) {
12813531Sjairo.balart@metempsy.com      case GICR_CTLR: { // Control Register
12913531Sjairo.balart@metempsy.com          uint64_t value = 0;
13013531Sjairo.balart@metempsy.com
13113531Sjairo.balart@metempsy.com          if (DPG1S) {
13213531Sjairo.balart@metempsy.com              value |= GICR_CTLR_DPG1S;
13313531Sjairo.balart@metempsy.com          }
13413531Sjairo.balart@metempsy.com
13513531Sjairo.balart@metempsy.com          if (DPG1NS) {
13613531Sjairo.balart@metempsy.com              value |= GICR_CTLR_DPG1NS;
13713531Sjairo.balart@metempsy.com          }
13813531Sjairo.balart@metempsy.com
13913531Sjairo.balart@metempsy.com          if (DPG0) {
14013531Sjairo.balart@metempsy.com              value |= GICR_CTLR_DPG0;
14113531Sjairo.balart@metempsy.com          }
14213531Sjairo.balart@metempsy.com
14313690Sjairo.balart@metempsy.com          if (EnableLPIs) {
14413690Sjairo.balart@metempsy.com              value |= GICR_CTLR_ENABLE_LPIS;
14513690Sjairo.balart@metempsy.com          }
14613690Sjairo.balart@metempsy.com
14713531Sjairo.balart@metempsy.com          return value;
14813531Sjairo.balart@metempsy.com      }
14913531Sjairo.balart@metempsy.com
15013531Sjairo.balart@metempsy.com      case GICR_IIDR: // Implementer Identification Register
15113531Sjairo.balart@metempsy.com        //return 0x43b; // r0p0 GIC-500
15213531Sjairo.balart@metempsy.com        return 0;
15313531Sjairo.balart@metempsy.com
15413531Sjairo.balart@metempsy.com      case GICR_TYPER: { // Type Register
15513531Sjairo.balart@metempsy.com          /*
15613531Sjairo.balart@metempsy.com           * Affinity_Value   [63:32] == X
15713531Sjairo.balart@metempsy.com           * (The identity of the PE associated with this Redistributor)
15813531Sjairo.balart@metempsy.com           * CommonLPIAff     [25:24] == 01
15913531Sjairo.balart@metempsy.com           * (All Redistributors with the same Aff3 value must share an
16013531Sjairo.balart@metempsy.com           * LPI Configuration table)
16113531Sjairo.balart@metempsy.com           * Processor_Number [23:8]  == X
16213531Sjairo.balart@metempsy.com           * (A unique identifier for the PE)
16313531Sjairo.balart@metempsy.com           * DPGS             [5]     == 1
16413531Sjairo.balart@metempsy.com           * (GICR_CTLR.DPG* bits are supported)
16513531Sjairo.balart@metempsy.com           * Last             [4]     == X
16613531Sjairo.balart@metempsy.com           * (This Redistributor is the highest-numbered Redistributor in
16713531Sjairo.balart@metempsy.com           * a series of contiguous Redistributor pages)
16813690Sjairo.balart@metempsy.com           * DirectLPI        [3]     == 1
16913690Sjairo.balart@metempsy.com           * (direct injection of LPIs supported)
17013531Sjairo.balart@metempsy.com           * VLPIS            [1]     == 0
17113531Sjairo.balart@metempsy.com           * (virtual LPIs not supported)
17213690Sjairo.balart@metempsy.com           * PLPIS            [0]     == 1
17313690Sjairo.balart@metempsy.com           * (physical LPIs supported)
17413531Sjairo.balart@metempsy.com           */
17513531Sjairo.balart@metempsy.com          uint64_t affinity = getAffinity();
17613531Sjairo.balart@metempsy.com          int last = cpuId == (gic->getSystem()->numContexts() - 1);
17713531Sjairo.balart@metempsy.com          return (affinity << 32) | (1 << 24) | (cpuId << 8) |
17813690Sjairo.balart@metempsy.com              (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
17913531Sjairo.balart@metempsy.com      }
18013531Sjairo.balart@metempsy.com
18113531Sjairo.balart@metempsy.com      case GICR_WAKER: // Wake Register
18213531Sjairo.balart@metempsy.com        if (!distributor->DS && !is_secure_access) {
18313531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
18413531Sjairo.balart@metempsy.com            return 0;
18513531Sjairo.balart@metempsy.com        }
18613531Sjairo.balart@metempsy.com
18713531Sjairo.balart@metempsy.com        if (peInLowPowerState) {
18813531Sjairo.balart@metempsy.com            return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
18913531Sjairo.balart@metempsy.com        } else {
19013531Sjairo.balart@metempsy.com            return 0;
19113531Sjairo.balart@metempsy.com        }
19213531Sjairo.balart@metempsy.com
19313531Sjairo.balart@metempsy.com      case GICR_PIDR0: { // Peripheral ID0 Register
19413756Sjairo.balart@metempsy.com          return 0x92; // Part number, bits[7:0]
19513531Sjairo.balart@metempsy.com      }
19613531Sjairo.balart@metempsy.com
19713531Sjairo.balart@metempsy.com      case GICR_PIDR1: { // Peripheral ID1 Register
19813531Sjairo.balart@metempsy.com          uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
19913531Sjairo.balart@metempsy.com          uint8_t part_1 = 0x4; // Part number, bits[11:8]
20013531Sjairo.balart@metempsy.com          return (des_0 << 4) | (part_1 << 0);
20113531Sjairo.balart@metempsy.com      }
20213531Sjairo.balart@metempsy.com
20313531Sjairo.balart@metempsy.com      case GICR_PIDR2: { // Peripheral ID2 Register
20413531Sjairo.balart@metempsy.com          uint8_t arch_rev = 0x3; // 0x3 GICv3
20513531Sjairo.balart@metempsy.com          uint8_t jedec = 0x1; // JEP code
20613531Sjairo.balart@metempsy.com          uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
20713531Sjairo.balart@metempsy.com          return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
20813531Sjairo.balart@metempsy.com      }
20913531Sjairo.balart@metempsy.com
21013531Sjairo.balart@metempsy.com      case GICR_PIDR3: // Peripheral ID3 Register
21113531Sjairo.balart@metempsy.com        return 0x0; // Implementation defined
21213531Sjairo.balart@metempsy.com
21313531Sjairo.balart@metempsy.com      case GICR_PIDR4: { // Peripheral ID4 Register
21413531Sjairo.balart@metempsy.com          uint8_t size = 0x4; // 64 KB software visible page
21513531Sjairo.balart@metempsy.com          uint8_t des_2 = 0x4; // ARM implementation
21613531Sjairo.balart@metempsy.com          return (size << 4) | (des_2 << 0);
21713531Sjairo.balart@metempsy.com      }
21813531Sjairo.balart@metempsy.com
21913531Sjairo.balart@metempsy.com      case GICR_PIDR5: // Peripheral ID5 Register
22013531Sjairo.balart@metempsy.com      case GICR_PIDR6: // Peripheral ID6 Register
22113531Sjairo.balart@metempsy.com      case GICR_PIDR7: // Peripheral ID7 Register
22213531Sjairo.balart@metempsy.com        return 0; // RES0
22313531Sjairo.balart@metempsy.com
22413531Sjairo.balart@metempsy.com      case GICR_IGROUPR0: { // Interrupt Group Register 0
22513531Sjairo.balart@metempsy.com          uint64_t value = 0;
22613531Sjairo.balart@metempsy.com
22713531Sjairo.balart@metempsy.com          if (!distributor->DS && !is_secure_access) {
22813531Sjairo.balart@metempsy.com              // RAZ/WI for non-secure accesses
22913531Sjairo.balart@metempsy.com              return 0;
23013531Sjairo.balart@metempsy.com          }
23113531Sjairo.balart@metempsy.com
23213531Sjairo.balart@metempsy.com          for (int int_id = 0; int_id < 8 * size; int_id++) {
23313531Sjairo.balart@metempsy.com              value |= (irqGroup[int_id] << int_id);
23413531Sjairo.balart@metempsy.com          }
23513531Sjairo.balart@metempsy.com
23613531Sjairo.balart@metempsy.com          return value;
23713531Sjairo.balart@metempsy.com      }
23813531Sjairo.balart@metempsy.com
23913531Sjairo.balart@metempsy.com      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
24013531Sjairo.balart@metempsy.com      case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
24113531Sjairo.balart@metempsy.com          uint64_t value = 0;
24213531Sjairo.balart@metempsy.com
24313531Sjairo.balart@metempsy.com          for (int int_id = 0; int_id < 8 * size; int_id++) {
24413531Sjairo.balart@metempsy.com              if (!distributor->DS && !is_secure_access) {
24513531Sjairo.balart@metempsy.com                  // RAZ/WI for non-secure accesses for secure interrupts
24613531Sjairo.balart@metempsy.com                  if (getIntGroup(int_id) != Gicv3::G1NS) {
24713531Sjairo.balart@metempsy.com                      continue;
24813531Sjairo.balart@metempsy.com                  }
24913531Sjairo.balart@metempsy.com              }
25013531Sjairo.balart@metempsy.com
25113531Sjairo.balart@metempsy.com              if (irqEnabled[int_id]) {
25213531Sjairo.balart@metempsy.com                  value |= (1 << int_id);
25313531Sjairo.balart@metempsy.com              }
25413531Sjairo.balart@metempsy.com          }
25513531Sjairo.balart@metempsy.com
25613531Sjairo.balart@metempsy.com          return value;
25713531Sjairo.balart@metempsy.com      }
25813531Sjairo.balart@metempsy.com
25913531Sjairo.balart@metempsy.com      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
26013531Sjairo.balart@metempsy.com      case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
26113531Sjairo.balart@metempsy.com          uint64_t value = 0;
26213531Sjairo.balart@metempsy.com
26313531Sjairo.balart@metempsy.com          for (int int_id = 0; int_id < 8 * size; int_id++) {
26413531Sjairo.balart@metempsy.com              if (!distributor->DS && !is_secure_access) {
26513531Sjairo.balart@metempsy.com                  // RAZ/WI for non-secure accesses for secure interrupts
26613531Sjairo.balart@metempsy.com                  if (getIntGroup(int_id) != Gicv3::G1NS) {
26713531Sjairo.balart@metempsy.com                      continue;
26813531Sjairo.balart@metempsy.com                  }
26913531Sjairo.balart@metempsy.com              }
27013531Sjairo.balart@metempsy.com
27113531Sjairo.balart@metempsy.com              value |= (irqPending[int_id] << int_id);
27213531Sjairo.balart@metempsy.com          }
27313531Sjairo.balart@metempsy.com
27413531Sjairo.balart@metempsy.com          return value;
27513531Sjairo.balart@metempsy.com      }
27613531Sjairo.balart@metempsy.com
27713531Sjairo.balart@metempsy.com      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
27813531Sjairo.balart@metempsy.com      case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
27913531Sjairo.balart@metempsy.com          uint64_t value = 0;
28013531Sjairo.balart@metempsy.com
28113531Sjairo.balart@metempsy.com          for (int int_id = 0; int_id < 8 * size; int_id++) {
28213531Sjairo.balart@metempsy.com              if (!distributor->DS && !is_secure_access) {
28313531Sjairo.balart@metempsy.com                  // RAZ/WI for non-secure accesses for secure interrupts
28413531Sjairo.balart@metempsy.com                  if (getIntGroup(int_id) != Gicv3::G1NS) {
28513531Sjairo.balart@metempsy.com                      continue;
28613531Sjairo.balart@metempsy.com                  }
28713531Sjairo.balart@metempsy.com              }
28813531Sjairo.balart@metempsy.com
28913531Sjairo.balart@metempsy.com              value |=  irqActive[int_id] << int_id;
29013531Sjairo.balart@metempsy.com          }
29113531Sjairo.balart@metempsy.com
29213531Sjairo.balart@metempsy.com          return value;
29313531Sjairo.balart@metempsy.com      }
29413531Sjairo.balart@metempsy.com
29513531Sjairo.balart@metempsy.com      case GICR_ICFGR0: // SGI Configuration Register
29613531Sjairo.balart@metempsy.com      case GICR_ICFGR1: { // PPI Configuration Register
29713531Sjairo.balart@metempsy.com          uint64_t value = 0;
29813531Sjairo.balart@metempsy.com          uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
29913531Sjairo.balart@metempsy.com
30013531Sjairo.balart@metempsy.com          for (int i = 0, int_id = first_int_id; i < 32;
30113756Sjairo.balart@metempsy.com               i = i + 2, int_id++) {
30213531Sjairo.balart@metempsy.com              if (!distributor->DS && !is_secure_access) {
30313531Sjairo.balart@metempsy.com                  // RAZ/WI for non-secure accesses for secure interrupts
30413531Sjairo.balart@metempsy.com                  if (getIntGroup(int_id) != Gicv3::G1NS) {
30513531Sjairo.balart@metempsy.com                      continue;
30613531Sjairo.balart@metempsy.com                  }
30713531Sjairo.balart@metempsy.com              }
30813531Sjairo.balart@metempsy.com
30913531Sjairo.balart@metempsy.com              if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
31013531Sjairo.balart@metempsy.com                  value |= (0x2) << i;
31113531Sjairo.balart@metempsy.com              }
31213531Sjairo.balart@metempsy.com          }
31313531Sjairo.balart@metempsy.com
31413531Sjairo.balart@metempsy.com          return value;
31513531Sjairo.balart@metempsy.com      }
31613531Sjairo.balart@metempsy.com
31713531Sjairo.balart@metempsy.com      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
31813531Sjairo.balart@metempsy.com          uint64_t value = 0;
31913531Sjairo.balart@metempsy.com
32013531Sjairo.balart@metempsy.com          if (distributor->DS) {
32113531Sjairo.balart@metempsy.com              value = 0;
32213531Sjairo.balart@metempsy.com          } else {
32313531Sjairo.balart@metempsy.com              if (!is_secure_access) {
32413531Sjairo.balart@metempsy.com                  // RAZ/WI for non-secure accesses
32513531Sjairo.balart@metempsy.com                  value = 0;
32613531Sjairo.balart@metempsy.com              } else {
32713531Sjairo.balart@metempsy.com                  for (int int_id = 0; int_id < 8 * size; int_id++) {
32813531Sjairo.balart@metempsy.com                      value |= irqGrpmod[int_id] << int_id;
32913531Sjairo.balart@metempsy.com                  }
33013531Sjairo.balart@metempsy.com              }
33113531Sjairo.balart@metempsy.com          }
33213531Sjairo.balart@metempsy.com
33313531Sjairo.balart@metempsy.com          return value;
33413531Sjairo.balart@metempsy.com      }
33513531Sjairo.balart@metempsy.com
33613531Sjairo.balart@metempsy.com      case GICR_NSACR: { // Non-secure Access Control Register
33713531Sjairo.balart@metempsy.com          uint64_t value = 0;
33813531Sjairo.balart@metempsy.com
33913531Sjairo.balart@metempsy.com          if (distributor->DS) {
34013531Sjairo.balart@metempsy.com              // RAZ/WI
34113531Sjairo.balart@metempsy.com              value = 0;
34213531Sjairo.balart@metempsy.com          } else {
34313531Sjairo.balart@metempsy.com              if (!is_secure_access) {
34413531Sjairo.balart@metempsy.com                  // RAZ/WI
34513531Sjairo.balart@metempsy.com                  value = 0;
34613531Sjairo.balart@metempsy.com              } else {
34713531Sjairo.balart@metempsy.com                  for (int i = 0, int_id = 0; i < 8 * size;
34813756Sjairo.balart@metempsy.com                       i = i + 2, int_id++) {
34913531Sjairo.balart@metempsy.com                      value |= irqNsacr[int_id] << i;
35013531Sjairo.balart@metempsy.com                  }
35113531Sjairo.balart@metempsy.com              }
35213531Sjairo.balart@metempsy.com          }
35313531Sjairo.balart@metempsy.com
35413531Sjairo.balart@metempsy.com          return value;
35513531Sjairo.balart@metempsy.com      }
35613531Sjairo.balart@metempsy.com
35713690Sjairo.balart@metempsy.com      case GICR_PROPBASER: // Redistributor Properties Base Address Register
35813690Sjairo.balart@metempsy.com        // OuterCache, bits [58:56]
35913690Sjairo.balart@metempsy.com        //   000 Memory type defined in InnerCache field
36013690Sjairo.balart@metempsy.com        // Physical_Address, bits [51:12]
36113690Sjairo.balart@metempsy.com        //   Bits [51:12] of the physical address containing the LPI
36213690Sjairo.balart@metempsy.com        //   Configuration table
36313690Sjairo.balart@metempsy.com        // Shareability, bits [11:10]
36413690Sjairo.balart@metempsy.com        //   00 Non-shareable
36513690Sjairo.balart@metempsy.com        // InnerCache, bits [9:7]
36613690Sjairo.balart@metempsy.com        //   000 Device-nGnRnE
36713690Sjairo.balart@metempsy.com        // IDbits, bits [4:0]
36813690Sjairo.balart@metempsy.com        //   limited by GICD_TYPER.IDbits
36913690Sjairo.balart@metempsy.com        return lpiConfigurationTablePtr | lpiIDBits;
37013690Sjairo.balart@metempsy.com
37113690Sjairo.balart@metempsy.com      // Redistributor LPI Pending Table Base Address Register
37213690Sjairo.balart@metempsy.com      case GICR_PENDBASER:
37313690Sjairo.balart@metempsy.com        // PTZ, bit [62]
37413690Sjairo.balart@metempsy.com        //   Pending Table Zero
37513690Sjairo.balart@metempsy.com        // OuterCache, bits [58:56]
37613690Sjairo.balart@metempsy.com        //   000 Memory type defined in InnerCache field
37713690Sjairo.balart@metempsy.com        // Physical_Address, bits [51:16]
37813690Sjairo.balart@metempsy.com        //   Bits [51:16] of the physical address containing the LPI Pending
37913690Sjairo.balart@metempsy.com        //   table
38013690Sjairo.balart@metempsy.com        // Shareability, bits [11:10]
38113690Sjairo.balart@metempsy.com        //   00 Non-shareable
38213690Sjairo.balart@metempsy.com        // InnerCache, bits [9:7]
38313690Sjairo.balart@metempsy.com        //   000 Device-nGnRnE
38413690Sjairo.balart@metempsy.com        return lpiPendingTablePtr;
38513690Sjairo.balart@metempsy.com
38613690Sjairo.balart@metempsy.com      // Redistributor Synchronize Register
38713690Sjairo.balart@metempsy.com      case GICR_SYNCR:
38813690Sjairo.balart@metempsy.com        return 0;
38913690Sjairo.balart@metempsy.com
39013531Sjairo.balart@metempsy.com      default:
39113531Sjairo.balart@metempsy.com        panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
39213531Sjairo.balart@metempsy.com        break;
39313531Sjairo.balart@metempsy.com    }
39413531Sjairo.balart@metempsy.com}
39513531Sjairo.balart@metempsy.com
39613531Sjairo.balart@metempsy.comvoid
39713531Sjairo.balart@metempsy.comGicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
39813531Sjairo.balart@metempsy.com                          bool is_secure_access)
39913531Sjairo.balart@metempsy.com{
40013531Sjairo.balart@metempsy.com    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
40113531Sjairo.balart@metempsy.com        int first_intid = addr - GICR_IPRIORITYR.start();
40213531Sjairo.balart@metempsy.com
40313531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
40413531Sjairo.balart@metempsy.com            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
40513531Sjairo.balart@metempsy.com
40613531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
40713531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
40813531Sjairo.balart@metempsy.com                    // RAZ/WI for non-secure accesses for secure interrupts
40913531Sjairo.balart@metempsy.com                    continue;
41013531Sjairo.balart@metempsy.com                } else {
41113531Sjairo.balart@metempsy.com                    // NS view
41213531Sjairo.balart@metempsy.com                    prio = 0x80 | (prio >> 1);
41313531Sjairo.balart@metempsy.com                }
41413531Sjairo.balart@metempsy.com            }
41513531Sjairo.balart@metempsy.com
41613531Sjairo.balart@metempsy.com            irqPriority[int_id] = prio;
41713531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Redistributor::write(): "
41813531Sjairo.balart@metempsy.com                    "int_id %d priority %d\n", int_id, irqPriority[int_id]);
41913531Sjairo.balart@metempsy.com        }
42013531Sjairo.balart@metempsy.com
42113531Sjairo.balart@metempsy.com        return;
42213531Sjairo.balart@metempsy.com    }
42313531Sjairo.balart@metempsy.com
42413531Sjairo.balart@metempsy.com    switch (addr) {
42513531Sjairo.balart@metempsy.com      case GICR_CTLR: {
42613690Sjairo.balart@metempsy.com          // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
42713690Sjairo.balart@metempsy.com          EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
42813531Sjairo.balart@metempsy.com          DPG1S = data & GICR_CTLR_DPG1S;
42913531Sjairo.balart@metempsy.com          DPG1NS = data & GICR_CTLR_DPG1NS;
43013531Sjairo.balart@metempsy.com          DPG0 = data & GICR_CTLR_DPG0;
43113531Sjairo.balart@metempsy.com          break;
43213531Sjairo.balart@metempsy.com      }
43313531Sjairo.balart@metempsy.com
43413531Sjairo.balart@metempsy.com      case GICR_WAKER: // Wake Register
43513531Sjairo.balart@metempsy.com        if (!distributor->DS && !is_secure_access) {
43613531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
43713531Sjairo.balart@metempsy.com            return;
43813531Sjairo.balart@metempsy.com        }
43913531Sjairo.balart@metempsy.com
44013531Sjairo.balart@metempsy.com        if (not peInLowPowerState and
44113756Sjairo.balart@metempsy.com            (data & GICR_WAKER_ProcessorSleep)) {
44213531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Redistributor::write(): "
44313531Sjairo.balart@metempsy.com                    "PE entering in low power state\n");
44413531Sjairo.balart@metempsy.com        } else if (peInLowPowerState and
44513756Sjairo.balart@metempsy.com                   not(data & GICR_WAKER_ProcessorSleep)) {
44613531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
44713531Sjairo.balart@metempsy.com        }
44813531Sjairo.balart@metempsy.com
44913531Sjairo.balart@metempsy.com        peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
45013531Sjairo.balart@metempsy.com        break;
45113531Sjairo.balart@metempsy.com
45213531Sjairo.balart@metempsy.com      case GICR_IGROUPR0: // Interrupt Group Register 0
45313531Sjairo.balart@metempsy.com        if (!distributor->DS && !is_secure_access) {
45413531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
45513531Sjairo.balart@metempsy.com            return;
45613531Sjairo.balart@metempsy.com        }
45713531Sjairo.balart@metempsy.com
45813531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
45913531Sjairo.balart@metempsy.com            irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
46013531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Redistributor::write(): "
46113531Sjairo.balart@metempsy.com                    "int_id %d group %d\n", int_id, irqGroup[int_id]);
46213531Sjairo.balart@metempsy.com        }
46313531Sjairo.balart@metempsy.com
46413531Sjairo.balart@metempsy.com        break;
46513531Sjairo.balart@metempsy.com
46613531Sjairo.balart@metempsy.com      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
46713531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
46813531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
46913531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses for secure interrupts
47013531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
47113531Sjairo.balart@metempsy.com                    continue;
47213531Sjairo.balart@metempsy.com                }
47313531Sjairo.balart@metempsy.com            }
47413531Sjairo.balart@metempsy.com
47513531Sjairo.balart@metempsy.com            bool enable = data & (1 << int_id) ? 1 : 0;
47613531Sjairo.balart@metempsy.com
47713531Sjairo.balart@metempsy.com            if (enable) {
47813531Sjairo.balart@metempsy.com                irqEnabled[int_id] = true;
47913531Sjairo.balart@metempsy.com            }
48013531Sjairo.balart@metempsy.com
48113531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Redistributor::write(): "
48213531Sjairo.balart@metempsy.com                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
48313531Sjairo.balart@metempsy.com        }
48413531Sjairo.balart@metempsy.com
48513531Sjairo.balart@metempsy.com        break;
48613531Sjairo.balart@metempsy.com
48713531Sjairo.balart@metempsy.com      case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
48813531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
48913531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
49013531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses for secure interrupts
49113531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
49213531Sjairo.balart@metempsy.com                    continue;
49313531Sjairo.balart@metempsy.com                }
49413531Sjairo.balart@metempsy.com            }
49513531Sjairo.balart@metempsy.com
49613531Sjairo.balart@metempsy.com            bool disable = data & (1 << int_id) ? 1 : 0;
49713531Sjairo.balart@metempsy.com
49813531Sjairo.balart@metempsy.com            if (disable) {
49913531Sjairo.balart@metempsy.com                irqEnabled[int_id] = false;
50013531Sjairo.balart@metempsy.com            }
50113531Sjairo.balart@metempsy.com
50213531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Redistributor::write(): "
50313531Sjairo.balart@metempsy.com                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
50413531Sjairo.balart@metempsy.com        }
50513531Sjairo.balart@metempsy.com
50613531Sjairo.balart@metempsy.com        break;
50713531Sjairo.balart@metempsy.com
50813531Sjairo.balart@metempsy.com      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
50913531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
51013531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
51113531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses for secure interrupts
51213531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
51313531Sjairo.balart@metempsy.com                    continue;
51413531Sjairo.balart@metempsy.com                }
51513531Sjairo.balart@metempsy.com            }
51613531Sjairo.balart@metempsy.com
51713531Sjairo.balart@metempsy.com            bool pending = data & (1 << int_id) ? 1 : 0;
51813531Sjairo.balart@metempsy.com
51913531Sjairo.balart@metempsy.com            if (pending) {
52013531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Redistributor::write() "
52113531Sjairo.balart@metempsy.com                        "(GICR_ISPENDR0): int_id %d (PPI) "
52213531Sjairo.balart@metempsy.com                        "pending bit set\n", int_id);
52313531Sjairo.balart@metempsy.com                irqPending[int_id] = true;
52413531Sjairo.balart@metempsy.com            }
52513531Sjairo.balart@metempsy.com        }
52613531Sjairo.balart@metempsy.com
52713531Sjairo.balart@metempsy.com        updateAndInformCPUInterface();
52813531Sjairo.balart@metempsy.com        break;
52913531Sjairo.balart@metempsy.com
53013531Sjairo.balart@metempsy.com      case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
53113531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
53213531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
53313531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses for secure interrupts
53413531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
53513531Sjairo.balart@metempsy.com                    continue;
53613531Sjairo.balart@metempsy.com                }
53713531Sjairo.balart@metempsy.com            }
53813531Sjairo.balart@metempsy.com
53913531Sjairo.balart@metempsy.com            bool clear = data & (1 << int_id) ? 1 : 0;
54013531Sjairo.balart@metempsy.com
54113531Sjairo.balart@metempsy.com            if (clear) {
54213531Sjairo.balart@metempsy.com                irqPending[int_id] = false;
54313531Sjairo.balart@metempsy.com            }
54413531Sjairo.balart@metempsy.com        }
54513531Sjairo.balart@metempsy.com
54613531Sjairo.balart@metempsy.com        break;
54713531Sjairo.balart@metempsy.com
54813531Sjairo.balart@metempsy.com      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
54913531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
55013531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
55113531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses for secure interrupts
55213531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
55313531Sjairo.balart@metempsy.com                    continue;
55413531Sjairo.balart@metempsy.com                }
55513531Sjairo.balart@metempsy.com            }
55613531Sjairo.balart@metempsy.com
55713531Sjairo.balart@metempsy.com            bool activate = data & (1 << int_id) ? 1 : 0;
55813531Sjairo.balart@metempsy.com
55913531Sjairo.balart@metempsy.com            if (activate) {
56013531Sjairo.balart@metempsy.com                if (!irqActive[int_id]) {
56113531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
56213531Sjairo.balart@metempsy.com                            "int_id %d active set\n", int_id);
56313531Sjairo.balart@metempsy.com                }
56413531Sjairo.balart@metempsy.com
56513531Sjairo.balart@metempsy.com                irqActive[int_id] = true;
56613531Sjairo.balart@metempsy.com            }
56713531Sjairo.balart@metempsy.com        }
56813531Sjairo.balart@metempsy.com
56913531Sjairo.balart@metempsy.com        break;
57013531Sjairo.balart@metempsy.com
57113531Sjairo.balart@metempsy.com      case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
57213531Sjairo.balart@metempsy.com        for (int int_id = 0; int_id < 8 * size; int_id++) {
57313531Sjairo.balart@metempsy.com            if (!distributor->DS && !is_secure_access) {
57413531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses for secure interrupts
57513531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
57613531Sjairo.balart@metempsy.com                    continue;
57713531Sjairo.balart@metempsy.com                }
57813531Sjairo.balart@metempsy.com            }
57913531Sjairo.balart@metempsy.com
58013531Sjairo.balart@metempsy.com            bool clear = data & (1 << int_id) ? 1 : 0;
58113531Sjairo.balart@metempsy.com
58213531Sjairo.balart@metempsy.com            if (clear) {
58313531Sjairo.balart@metempsy.com                if (irqActive[int_id]) {
58413531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
58513531Sjairo.balart@metempsy.com                            "int_id %d active cleared\n", int_id);
58613531Sjairo.balart@metempsy.com                }
58713531Sjairo.balart@metempsy.com
58813531Sjairo.balart@metempsy.com                irqActive[int_id] = false;
58913531Sjairo.balart@metempsy.com            }
59013531Sjairo.balart@metempsy.com        }
59113531Sjairo.balart@metempsy.com
59213531Sjairo.balart@metempsy.com        break;
59313531Sjairo.balart@metempsy.com
59413531Sjairo.balart@metempsy.com      case GICR_ICFGR1: { // PPI Configuration Register
59513531Sjairo.balart@metempsy.com          int first_intid = Gicv3::SGI_MAX;
59613531Sjairo.balart@metempsy.com
59713531Sjairo.balart@metempsy.com          for (int i = 0, int_id = first_intid; i < 8 * size;
59813756Sjairo.balart@metempsy.com               i = i + 2, int_id++) {
59913531Sjairo.balart@metempsy.com              if (!distributor->DS && !is_secure_access) {
60013531Sjairo.balart@metempsy.com                  // RAZ/WI for non-secure accesses for secure interrupts
60113531Sjairo.balart@metempsy.com                  if (getIntGroup(int_id) != Gicv3::G1NS) {
60213531Sjairo.balart@metempsy.com                      continue;
60313531Sjairo.balart@metempsy.com                  }
60413531Sjairo.balart@metempsy.com              }
60513531Sjairo.balart@metempsy.com
60613756Sjairo.balart@metempsy.com              irqConfig[int_id] = data & (0x2 << i) ?
60713756Sjairo.balart@metempsy.com                                  Gicv3::INT_EDGE_TRIGGERED :
60813756Sjairo.balart@metempsy.com                                  Gicv3::INT_LEVEL_SENSITIVE;
60913531Sjairo.balart@metempsy.com              DPRINTF(GIC, "Gicv3Redistributor::write(): "
61013531Sjairo.balart@metempsy.com                      "int_id %d (PPI) config %d\n",
61113531Sjairo.balart@metempsy.com                      int_id, irqConfig[int_id]);
61213531Sjairo.balart@metempsy.com          }
61313531Sjairo.balart@metempsy.com
61413531Sjairo.balart@metempsy.com          break;
61513531Sjairo.balart@metempsy.com      }
61613531Sjairo.balart@metempsy.com
61713531Sjairo.balart@metempsy.com      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
61813531Sjairo.balart@metempsy.com          if (distributor->DS) {
61913531Sjairo.balart@metempsy.com              // RAZ/WI if secutiry disabled
62013531Sjairo.balart@metempsy.com          } else {
62113531Sjairo.balart@metempsy.com              for (int int_id = 0; int_id < 8 * size; int_id++) {
62213531Sjairo.balart@metempsy.com                  if (!is_secure_access) {
62313531Sjairo.balart@metempsy.com                      // RAZ/WI for non-secure accesses
62413531Sjairo.balart@metempsy.com                      continue;
62513531Sjairo.balart@metempsy.com                  }
62613531Sjairo.balart@metempsy.com
62713531Sjairo.balart@metempsy.com                  irqGrpmod[int_id] = data & (1 << int_id);
62813531Sjairo.balart@metempsy.com              }
62913531Sjairo.balart@metempsy.com          }
63013531Sjairo.balart@metempsy.com
63113531Sjairo.balart@metempsy.com          break;
63213531Sjairo.balart@metempsy.com      }
63313531Sjairo.balart@metempsy.com
63413531Sjairo.balart@metempsy.com      case GICR_NSACR: { // Non-secure Access Control Register
63513531Sjairo.balart@metempsy.com          if (distributor->DS) {
63613531Sjairo.balart@metempsy.com              // RAZ/WI
63713531Sjairo.balart@metempsy.com          } else {
63813531Sjairo.balart@metempsy.com              if (!is_secure_access) {
63913531Sjairo.balart@metempsy.com                  // RAZ/WI
64013531Sjairo.balart@metempsy.com              } else {
64113531Sjairo.balart@metempsy.com                  for (int i = 0, int_id = 0; i < 8 * size;
64213756Sjairo.balart@metempsy.com                       i = i + 2, int_id++) {
64313531Sjairo.balart@metempsy.com                      irqNsacr[int_id] = (data >> i) & 0x3;
64413531Sjairo.balart@metempsy.com                  }
64513531Sjairo.balart@metempsy.com              }
64613531Sjairo.balart@metempsy.com          }
64713531Sjairo.balart@metempsy.com
64813531Sjairo.balart@metempsy.com          break;
64913531Sjairo.balart@metempsy.com      }
65013531Sjairo.balart@metempsy.com
65113690Sjairo.balart@metempsy.com      case GICR_SETLPIR: // Set LPI Pending Register
65213690Sjairo.balart@metempsy.com        setClrLPI(data, true);
65313690Sjairo.balart@metempsy.com        break;
65413690Sjairo.balart@metempsy.com
65513690Sjairo.balart@metempsy.com      case GICR_CLRLPIR: // Clear LPI Pending Register
65613690Sjairo.balart@metempsy.com        setClrLPI(data, false);
65713690Sjairo.balart@metempsy.com        break;
65813690Sjairo.balart@metempsy.com
65913690Sjairo.balart@metempsy.com      case GICR_PROPBASER: { // Redistributor Properties Base Address Register
66013690Sjairo.balart@metempsy.com          // OuterCache, bits [58:56]
66113690Sjairo.balart@metempsy.com          //   000 Memory type defined in InnerCache field
66213690Sjairo.balart@metempsy.com          // Physical_Address, bits [51:12]
66313690Sjairo.balart@metempsy.com          //   Bits [51:12] of the physical address containing the LPI
66413690Sjairo.balart@metempsy.com          //   Configuration table
66513690Sjairo.balart@metempsy.com          // Shareability, bits [11:10]
66613690Sjairo.balart@metempsy.com          //   00 Non-shareable
66713690Sjairo.balart@metempsy.com          // InnerCache, bits [9:7]
66813690Sjairo.balart@metempsy.com          //   000 Device-nGnRnE
66913690Sjairo.balart@metempsy.com          // IDbits, bits [4:0]
67013690Sjairo.balart@metempsy.com          //   limited by GICD_TYPER.IDbits (= 0xf)
67113690Sjairo.balart@metempsy.com          lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
67213690Sjairo.balart@metempsy.com          lpiIDBits = data & 0x1f;
67313690Sjairo.balart@metempsy.com
67413690Sjairo.balart@metempsy.com          // 0xf here matches the value of GICD_TYPER.IDbits.
67513690Sjairo.balart@metempsy.com          // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
67613690Sjairo.balart@metempsy.com          // value
67713690Sjairo.balart@metempsy.com          if (lpiIDBits > 0xf) {
67813690Sjairo.balart@metempsy.com              lpiIDBits = 0xf;
67913690Sjairo.balart@metempsy.com          }
68013690Sjairo.balart@metempsy.com
68113690Sjairo.balart@metempsy.com          break;
68213690Sjairo.balart@metempsy.com      }
68313690Sjairo.balart@metempsy.com
68413690Sjairo.balart@metempsy.com      // Redistributor LPI Pending Table Base Address Register
68513690Sjairo.balart@metempsy.com      case GICR_PENDBASER:
68613690Sjairo.balart@metempsy.com        // PTZ, bit [62]
68713690Sjairo.balart@metempsy.com        //   Pending Table Zero
68813690Sjairo.balart@metempsy.com        // OuterCache, bits [58:56]
68913690Sjairo.balart@metempsy.com        //   000 Memory type defined in InnerCache field
69013690Sjairo.balart@metempsy.com        // Physical_Address, bits [51:16]
69113690Sjairo.balart@metempsy.com        //   Bits [51:16] of the physical address containing the LPI Pending
69213690Sjairo.balart@metempsy.com        //   table
69313690Sjairo.balart@metempsy.com        // Shareability, bits [11:10]
69413690Sjairo.balart@metempsy.com        //   00 Non-shareable
69513690Sjairo.balart@metempsy.com        // InnerCache, bits [9:7]
69613690Sjairo.balart@metempsy.com        //   000 Device-nGnRnE
69713690Sjairo.balart@metempsy.com        lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
69813690Sjairo.balart@metempsy.com        break;
69913690Sjairo.balart@metempsy.com
70013690Sjairo.balart@metempsy.com      case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
70113921Sgiacomo.travaglini@arm.com          // Do nothing: no caching supported
70213690Sjairo.balart@metempsy.com          break;
70313690Sjairo.balart@metempsy.com      }
70413690Sjairo.balart@metempsy.com
70513690Sjairo.balart@metempsy.com      case GICR_INVALLR: { // Redistributor Invalidate All Register
70613921Sgiacomo.travaglini@arm.com          // Do nothing: no caching supported
70713690Sjairo.balart@metempsy.com          break;
70813690Sjairo.balart@metempsy.com      }
70913690Sjairo.balart@metempsy.com
71013531Sjairo.balart@metempsy.com      default:
71113531Sjairo.balart@metempsy.com        panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
71213531Sjairo.balart@metempsy.com        break;
71313531Sjairo.balart@metempsy.com    }
71413531Sjairo.balart@metempsy.com}
71513531Sjairo.balart@metempsy.com
71613531Sjairo.balart@metempsy.comvoid
71713531Sjairo.balart@metempsy.comGicv3Redistributor::sendPPInt(uint32_t int_id)
71813531Sjairo.balart@metempsy.com{
71913531Sjairo.balart@metempsy.com    assert((int_id >= Gicv3::SGI_MAX) &&
72013531Sjairo.balart@metempsy.com           (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
72113531Sjairo.balart@metempsy.com    irqPending[int_id] = true;
72213531Sjairo.balart@metempsy.com    DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
72313531Sjairo.balart@metempsy.com            "int_id %d (PPI) pending bit set\n", int_id);
72413531Sjairo.balart@metempsy.com    updateAndInformCPUInterface();
72513531Sjairo.balart@metempsy.com}
72613531Sjairo.balart@metempsy.com
72713531Sjairo.balart@metempsy.comvoid
72813531Sjairo.balart@metempsy.comGicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
72913531Sjairo.balart@metempsy.com{
73013531Sjairo.balart@metempsy.com    assert(int_id < Gicv3::SGI_MAX);
73113531Sjairo.balart@metempsy.com    Gicv3::GroupId int_group = getIntGroup(int_id);
73213531Sjairo.balart@metempsy.com
73313531Sjairo.balart@metempsy.com    // asked for secure group 1
73413531Sjairo.balart@metempsy.com    // configured as group 0
73513531Sjairo.balart@metempsy.com    // send group 0
73613531Sjairo.balart@metempsy.com    if (int_group == Gicv3::G0S && group == Gicv3::G1S) {
73713531Sjairo.balart@metempsy.com        group = Gicv3::G0S;
73813531Sjairo.balart@metempsy.com    }
73913531Sjairo.balart@metempsy.com
74013531Sjairo.balart@metempsy.com    if (group == Gicv3::G0S and int_group != Gicv3::G0S) {
74113531Sjairo.balart@metempsy.com        return;
74213531Sjairo.balart@metempsy.com    }
74313531Sjairo.balart@metempsy.com
74413531Sjairo.balart@metempsy.com    if (ns && distributor->DS == 0) {
74513531Sjairo.balart@metempsy.com        int nsaccess = irqNsacr[int_id];
74613531Sjairo.balart@metempsy.com
74713531Sjairo.balart@metempsy.com        if ((int_group == Gicv3::G0S && nsaccess < 1) ||
74813756Sjairo.balart@metempsy.com            (int_group == Gicv3::G1S && nsaccess < 2)) {
74913531Sjairo.balart@metempsy.com            return;
75013531Sjairo.balart@metempsy.com        }
75113531Sjairo.balart@metempsy.com    }
75213531Sjairo.balart@metempsy.com
75313531Sjairo.balart@metempsy.com    irqPending[int_id] = true;
75413531Sjairo.balart@metempsy.com    DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
75513531Sjairo.balart@metempsy.com            "int_id %d (SGI) pending bit set\n", int_id);
75613531Sjairo.balart@metempsy.com    updateAndInformCPUInterface();
75713531Sjairo.balart@metempsy.com}
75813531Sjairo.balart@metempsy.com
75913531Sjairo.balart@metempsy.comGicv3::IntStatus
76013756Sjairo.balart@metempsy.comGicv3Redistributor::intStatus(uint32_t int_id) const
76113531Sjairo.balart@metempsy.com{
76213531Sjairo.balart@metempsy.com    assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
76313531Sjairo.balart@metempsy.com
76413531Sjairo.balart@metempsy.com    if (irqPending[int_id]) {
76513531Sjairo.balart@metempsy.com        if (irqActive[int_id]) {
76613531Sjairo.balart@metempsy.com            return Gicv3::INT_ACTIVE_PENDING;
76713531Sjairo.balart@metempsy.com        }
76813531Sjairo.balart@metempsy.com
76913531Sjairo.balart@metempsy.com        return Gicv3::INT_PENDING;
77013531Sjairo.balart@metempsy.com    } else if (irqActive[int_id]) {
77113531Sjairo.balart@metempsy.com        return Gicv3::INT_ACTIVE;
77213531Sjairo.balart@metempsy.com    } else {
77313531Sjairo.balart@metempsy.com        return Gicv3::INT_INACTIVE;
77413531Sjairo.balart@metempsy.com    }
77513531Sjairo.balart@metempsy.com}
77613531Sjairo.balart@metempsy.com
77713531Sjairo.balart@metempsy.com/*
77813531Sjairo.balart@metempsy.com * Recalculate the highest priority pending interrupt after a
77913531Sjairo.balart@metempsy.com * change to redistributor state.
78013531Sjairo.balart@metempsy.com */
78113531Sjairo.balart@metempsy.comvoid
78213531Sjairo.balart@metempsy.comGicv3Redistributor::update()
78313531Sjairo.balart@metempsy.com{
78413531Sjairo.balart@metempsy.com    bool new_hppi = false;
78513531Sjairo.balart@metempsy.com
78613531Sjairo.balart@metempsy.com    for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
78713531Sjairo.balart@metempsy.com        Gicv3::GroupId int_group = getIntGroup(int_id);
78813531Sjairo.balart@metempsy.com        bool group_enabled = distributor->groupEnabled(int_group);
78913531Sjairo.balart@metempsy.com
79013531Sjairo.balart@metempsy.com        if (irqPending[int_id] && irqEnabled[int_id] &&
79113531Sjairo.balart@metempsy.com                !irqActive[int_id] && group_enabled) {
79213531Sjairo.balart@metempsy.com            if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
79313756Sjairo.balart@metempsy.com                /*
79413756Sjairo.balart@metempsy.com                 * Multiple pending ints with same priority.
79513756Sjairo.balart@metempsy.com                 * Implementation choice which one to signal.
79613756Sjairo.balart@metempsy.com                 * Our implementation selects the one with the lower id.
79713756Sjairo.balart@metempsy.com                 */
79813756Sjairo.balart@metempsy.com                (irqPriority[int_id] == cpuInterface->hppi.prio &&
79913756Sjairo.balart@metempsy.com                 int_id < cpuInterface->hppi.intid)) {
80013531Sjairo.balart@metempsy.com                cpuInterface->hppi.intid = int_id;
80113531Sjairo.balart@metempsy.com                cpuInterface->hppi.prio = irqPriority[int_id];
80213531Sjairo.balart@metempsy.com                cpuInterface->hppi.group = int_group;
80313531Sjairo.balart@metempsy.com                new_hppi = true;
80413531Sjairo.balart@metempsy.com            }
80513531Sjairo.balart@metempsy.com        }
80613531Sjairo.balart@metempsy.com    }
80713531Sjairo.balart@metempsy.com
80813690Sjairo.balart@metempsy.com    // Check LPIs
80913920Sgiacomo.travaglini@arm.com    if (EnableLPIs) {
81013921Sgiacomo.travaglini@arm.com
81113920Sgiacomo.travaglini@arm.com        const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
81213921Sgiacomo.travaglini@arm.com        const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
81313921Sgiacomo.travaglini@arm.com
81413921Sgiacomo.travaglini@arm.com        uint8_t lpi_pending_table[largest_lpi_id / 8];
81513921Sgiacomo.travaglini@arm.com        uint8_t lpi_config_table[number_lpis];
81613921Sgiacomo.travaglini@arm.com
81713928Sgiacomo.travaglini@arm.com        memProxy->readBlob(lpiPendingTablePtr,
81813928Sgiacomo.travaglini@arm.com                           (uint8_t *) lpi_pending_table,
81913928Sgiacomo.travaglini@arm.com                           sizeof(lpi_pending_table));
82013919Sgiacomo.travaglini@arm.com
82113928Sgiacomo.travaglini@arm.com        memProxy->readBlob(lpiConfigurationTablePtr,
82213928Sgiacomo.travaglini@arm.com                           (uint8_t*) lpi_config_table,
82313928Sgiacomo.travaglini@arm.com                           sizeof(lpi_config_table));
82413921Sgiacomo.travaglini@arm.com
82513920Sgiacomo.travaglini@arm.com        for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
82613920Sgiacomo.travaglini@arm.com             lpi_id++) {
82713920Sgiacomo.travaglini@arm.com            uint32_t lpi_pending_entry_byte = lpi_id / 8;
82813920Sgiacomo.travaglini@arm.com            uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
82913920Sgiacomo.travaglini@arm.com            bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
83013920Sgiacomo.travaglini@arm.com                                  1 << lpi_pending_entry_bit_position;
83113920Sgiacomo.travaglini@arm.com            uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
83213921Sgiacomo.travaglini@arm.com
83313921Sgiacomo.travaglini@arm.com            LPIConfigurationTableEntry config_entry =
83413921Sgiacomo.travaglini@arm.com                lpi_config_table[lpi_configuration_entry_index];
83513921Sgiacomo.travaglini@arm.com
83613921Sgiacomo.travaglini@arm.com            bool lpi_is_enable = config_entry.enable;
83713921Sgiacomo.travaglini@arm.com
83813920Sgiacomo.travaglini@arm.com            // LPIs are always Non-secure Group 1 interrupts,
83913920Sgiacomo.travaglini@arm.com            // in a system where two Security states are enabled.
84013920Sgiacomo.travaglini@arm.com            Gicv3::GroupId lpi_group = Gicv3::G1NS;
84113920Sgiacomo.travaglini@arm.com            bool group_enabled = distributor->groupEnabled(lpi_group);
84213690Sjairo.balart@metempsy.com
84313920Sgiacomo.travaglini@arm.com            if (lpi_is_pending && lpi_is_enable && group_enabled) {
84413922Sgiacomo.travaglini@arm.com                uint8_t lpi_priority = config_entry.priority << 2;
84513690Sjairo.balart@metempsy.com
84613920Sgiacomo.travaglini@arm.com                if ((lpi_priority < cpuInterface->hppi.prio) ||
84713920Sgiacomo.travaglini@arm.com                    (lpi_priority == cpuInterface->hppi.prio &&
84813920Sgiacomo.travaglini@arm.com                     lpi_id < cpuInterface->hppi.intid)) {
84913920Sgiacomo.travaglini@arm.com                    cpuInterface->hppi.intid = lpi_id;
85013920Sgiacomo.travaglini@arm.com                    cpuInterface->hppi.prio = lpi_priority;
85113920Sgiacomo.travaglini@arm.com                    cpuInterface->hppi.group = lpi_group;
85213920Sgiacomo.travaglini@arm.com                    new_hppi = true;
85313920Sgiacomo.travaglini@arm.com                }
85413690Sjairo.balart@metempsy.com            }
85513690Sjairo.balart@metempsy.com        }
85613690Sjairo.balart@metempsy.com    }
85713690Sjairo.balart@metempsy.com
85813531Sjairo.balart@metempsy.com    if (!new_hppi && cpuInterface->hppi.prio != 0xff &&
85913923Sgiacomo.travaglini@arm.com        (cpuInterface->hppi.intid < Gicv3::SGI_MAX + Gicv3::PPI_MAX ||
86013923Sgiacomo.travaglini@arm.com         cpuInterface->hppi.intid > SMALLEST_LPI_ID)) {
86113531Sjairo.balart@metempsy.com        distributor->fullUpdate();
86213531Sjairo.balart@metempsy.com    }
86313531Sjairo.balart@metempsy.com}
86413531Sjairo.balart@metempsy.com
86513924Sgiacomo.travaglini@arm.comuint8_t
86613924Sgiacomo.travaglini@arm.comGicv3Redistributor::readEntryLPI(uint32_t lpi_id)
86713924Sgiacomo.travaglini@arm.com{
86813924Sgiacomo.travaglini@arm.com    Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
86913924Sgiacomo.travaglini@arm.com
87013924Sgiacomo.travaglini@arm.com    uint8_t lpi_pending_entry;
87113928Sgiacomo.travaglini@arm.com    memProxy->readBlob(lpi_pending_entry_ptr,
87213928Sgiacomo.travaglini@arm.com                       (uint8_t*) &lpi_pending_entry,
87313928Sgiacomo.travaglini@arm.com                       sizeof(lpi_pending_entry));
87413924Sgiacomo.travaglini@arm.com
87513924Sgiacomo.travaglini@arm.com    return lpi_pending_entry;
87613924Sgiacomo.travaglini@arm.com}
87713924Sgiacomo.travaglini@arm.com
87813924Sgiacomo.travaglini@arm.comvoid
87913924Sgiacomo.travaglini@arm.comGicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
88013924Sgiacomo.travaglini@arm.com{
88113924Sgiacomo.travaglini@arm.com    Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
88213924Sgiacomo.travaglini@arm.com
88313928Sgiacomo.travaglini@arm.com    memProxy->writeBlob(lpi_pending_entry_ptr,
88413928Sgiacomo.travaglini@arm.com                        (uint8_t*) &lpi_pending_entry,
88513928Sgiacomo.travaglini@arm.com                        sizeof(lpi_pending_entry));
88613924Sgiacomo.travaglini@arm.com}
88713924Sgiacomo.travaglini@arm.com
88813924Sgiacomo.travaglini@arm.combool
88913924Sgiacomo.travaglini@arm.comGicv3Redistributor::isPendingLPI(uint32_t lpi_id)
89013924Sgiacomo.travaglini@arm.com{
89113924Sgiacomo.travaglini@arm.com    // Fetch the LPI pending entry from memory
89213924Sgiacomo.travaglini@arm.com    uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
89313924Sgiacomo.travaglini@arm.com
89413924Sgiacomo.travaglini@arm.com    uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
89513924Sgiacomo.travaglini@arm.com    bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
89613924Sgiacomo.travaglini@arm.com
89713924Sgiacomo.travaglini@arm.com    return is_set;
89813924Sgiacomo.travaglini@arm.com}
89913924Sgiacomo.travaglini@arm.com
90013531Sjairo.balart@metempsy.comvoid
90113690Sjairo.balart@metempsy.comGicv3Redistributor::setClrLPI(uint64_t data, bool set)
90213690Sjairo.balart@metempsy.com{
90313690Sjairo.balart@metempsy.com    if (!EnableLPIs) {
90413690Sjairo.balart@metempsy.com        // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
90513690Sjairo.balart@metempsy.com        // GICR_CTLR.EnableLPIs == 0.
90613690Sjairo.balart@metempsy.com        return;
90713690Sjairo.balart@metempsy.com    }
90813690Sjairo.balart@metempsy.com
90913690Sjairo.balart@metempsy.com    uint32_t lpi_id = data & 0xffffffff;
91013917Sgiacomo.travaglini@arm.com    uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
91113690Sjairo.balart@metempsy.com
91213690Sjairo.balart@metempsy.com    if (lpi_id > largest_lpi_id) {
91313690Sjairo.balart@metempsy.com        // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
91413690Sjairo.balart@metempsy.com        // pINTID value specifies an unimplemented LPI.
91513690Sjairo.balart@metempsy.com        return;
91613690Sjairo.balart@metempsy.com    }
91713690Sjairo.balart@metempsy.com
91813924Sgiacomo.travaglini@arm.com    // Fetch the LPI pending entry from memory
91913924Sgiacomo.travaglini@arm.com    uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
92013924Sgiacomo.travaglini@arm.com
92113690Sjairo.balart@metempsy.com    uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
92213690Sjairo.balart@metempsy.com    bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
92313690Sjairo.balart@metempsy.com
92413690Sjairo.balart@metempsy.com    if (set) {
92513690Sjairo.balart@metempsy.com        if (is_set) {
92613690Sjairo.balart@metempsy.com            // Writes to GICR_SETLPIR have not effect if the pINTID field
92713690Sjairo.balart@metempsy.com            // corresponds to an LPI that is already pending.
92813690Sjairo.balart@metempsy.com            return;
92913690Sjairo.balart@metempsy.com        }
93013690Sjairo.balart@metempsy.com
93113690Sjairo.balart@metempsy.com        lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
93213690Sjairo.balart@metempsy.com    } else {
93313690Sjairo.balart@metempsy.com        if (!is_set) {
93413690Sjairo.balart@metempsy.com            // Writes to GICR_SETLPIR have not effect if the pINTID field
93513690Sjairo.balart@metempsy.com            // corresponds to an LPI that is not pending.
93613690Sjairo.balart@metempsy.com            return;
93713690Sjairo.balart@metempsy.com        }
93813690Sjairo.balart@metempsy.com
93913690Sjairo.balart@metempsy.com        lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
94013690Sjairo.balart@metempsy.com    }
94113690Sjairo.balart@metempsy.com
94213924Sgiacomo.travaglini@arm.com    writeEntryLPI(lpi_id, lpi_pending_entry);
94313924Sgiacomo.travaglini@arm.com
94413690Sjairo.balart@metempsy.com    updateAndInformCPUInterface();
94513690Sjairo.balart@metempsy.com}
94613690Sjairo.balart@metempsy.com
94713690Sjairo.balart@metempsy.comvoid
94813531Sjairo.balart@metempsy.comGicv3Redistributor::updateAndInformCPUInterface()
94913531Sjairo.balart@metempsy.com{
95013531Sjairo.balart@metempsy.com    update();
95113531Sjairo.balart@metempsy.com    cpuInterface->update();
95213531Sjairo.balart@metempsy.com}
95313531Sjairo.balart@metempsy.com
95413531Sjairo.balart@metempsy.comGicv3::GroupId
95513756Sjairo.balart@metempsy.comGicv3Redistributor::getIntGroup(int int_id) const
95613531Sjairo.balart@metempsy.com{
95713531Sjairo.balart@metempsy.com    assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
95813531Sjairo.balart@metempsy.com
95913531Sjairo.balart@metempsy.com    if (distributor->DS) {
96013531Sjairo.balart@metempsy.com        if (irqGroup[int_id] == 0) {
96113531Sjairo.balart@metempsy.com            return Gicv3::G0S;
96213531Sjairo.balart@metempsy.com        } else {
96313531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
96413531Sjairo.balart@metempsy.com        }
96513531Sjairo.balart@metempsy.com    } else {
96613531Sjairo.balart@metempsy.com        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
96713531Sjairo.balart@metempsy.com            return Gicv3::G0S;
96813531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
96913531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
97013531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
97113531Sjairo.balart@metempsy.com            return Gicv3::G1S;
97213531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
97313531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
97413531Sjairo.balart@metempsy.com        }
97513531Sjairo.balart@metempsy.com    }
97613531Sjairo.balart@metempsy.com
97713531Sjairo.balart@metempsy.com    M5_UNREACHABLE;
97813531Sjairo.balart@metempsy.com}
97913531Sjairo.balart@metempsy.com
98013531Sjairo.balart@metempsy.comvoid
98113531Sjairo.balart@metempsy.comGicv3Redistributor::activateIRQ(uint32_t int_id)
98213531Sjairo.balart@metempsy.com{
98313531Sjairo.balart@metempsy.com    irqPending[int_id] = false;
98413531Sjairo.balart@metempsy.com    irqActive[int_id] = true;
98513531Sjairo.balart@metempsy.com}
98613531Sjairo.balart@metempsy.com
98713531Sjairo.balart@metempsy.comvoid
98813531Sjairo.balart@metempsy.comGicv3Redistributor::deactivateIRQ(uint32_t int_id)
98913531Sjairo.balart@metempsy.com{
99013531Sjairo.balart@metempsy.com    irqActive[int_id] = false;
99113531Sjairo.balart@metempsy.com}
99213531Sjairo.balart@metempsy.com
99313531Sjairo.balart@metempsy.comuint32_t
99413756Sjairo.balart@metempsy.comGicv3Redistributor::getAffinity() const
99513531Sjairo.balart@metempsy.com{
99613531Sjairo.balart@metempsy.com    ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
99713531Sjairo.balart@metempsy.com    uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
99813531Sjairo.balart@metempsy.com    /*
99913531Sjairo.balart@metempsy.com     * Aff3 = MPIDR[39:32]
100013531Sjairo.balart@metempsy.com     * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
100113531Sjairo.balart@metempsy.com     * Aff2 = MPIDR[23:16]
100213531Sjairo.balart@metempsy.com     * Aff1 = MPIDR[15:8]
100313531Sjairo.balart@metempsy.com     * Aff0 = MPIDR[7:0]
100413531Sjairo.balart@metempsy.com     * affinity = Aff3.Aff2.Aff1.Aff0
100513531Sjairo.balart@metempsy.com     */
100613531Sjairo.balart@metempsy.com    uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
100713531Sjairo.balart@metempsy.com    return affinity;
100813531Sjairo.balart@metempsy.com}
100913531Sjairo.balart@metempsy.com
101013531Sjairo.balart@metempsy.combool
101113756Sjairo.balart@metempsy.comGicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
101213531Sjairo.balart@metempsy.com{
101313531Sjairo.balart@metempsy.com    if (peInLowPowerState) {
101413531Sjairo.balart@metempsy.com        return false;
101513531Sjairo.balart@metempsy.com    }
101613531Sjairo.balart@metempsy.com
101713531Sjairo.balart@metempsy.com    if (!distributor->groupEnabled(group)) {
101813531Sjairo.balart@metempsy.com        return false;
101913531Sjairo.balart@metempsy.com    }
102013531Sjairo.balart@metempsy.com
102113531Sjairo.balart@metempsy.com    if ((group == Gicv3::G1S) && DPG1S) {
102213531Sjairo.balart@metempsy.com        return false;
102313531Sjairo.balart@metempsy.com    }
102413531Sjairo.balart@metempsy.com
102513531Sjairo.balart@metempsy.com    if ((group == Gicv3::G1NS) && DPG1NS) {
102613531Sjairo.balart@metempsy.com        return false;
102713531Sjairo.balart@metempsy.com    }
102813531Sjairo.balart@metempsy.com
102913531Sjairo.balart@metempsy.com    if ((group == Gicv3::G0S) && DPG0) {
103013531Sjairo.balart@metempsy.com        return false;
103113531Sjairo.balart@metempsy.com    }
103213531Sjairo.balart@metempsy.com
103313531Sjairo.balart@metempsy.com    return true;
103413531Sjairo.balart@metempsy.com}
103513531Sjairo.balart@metempsy.com
103613531Sjairo.balart@metempsy.comvoid
103713531Sjairo.balart@metempsy.comGicv3Redistributor::serialize(CheckpointOut & cp) const
103813531Sjairo.balart@metempsy.com{
103913531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(peInLowPowerState);
104013531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqGroup);
104113531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqEnabled);
104213531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqPending);
104313531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqActive);
104413531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqPriority);
104513531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqConfig);
104613531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqGrpmod);
104713531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqNsacr);
104813531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(DPG1S);
104913531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(DPG1NS);
105013531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(DPG0);
105113690Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableLPIs);
105213690Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(lpiConfigurationTablePtr);
105313690Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(lpiIDBits);
105413690Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(lpiPendingTablePtr);
105513531Sjairo.balart@metempsy.com}
105613531Sjairo.balart@metempsy.com
105713531Sjairo.balart@metempsy.comvoid
105813531Sjairo.balart@metempsy.comGicv3Redistributor::unserialize(CheckpointIn & cp)
105913531Sjairo.balart@metempsy.com{
106013531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(peInLowPowerState);
106113531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqGroup);
106213531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqEnabled);
106313531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqPending);
106413531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqActive);
106513531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqPriority);
106613531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqConfig);
106713531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqGrpmod);
106813531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqNsacr);
106913531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(DPG1S);
107013531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(DPG1NS);
107113531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(DPG0);
107213690Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableLPIs);
107313690Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
107413690Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(lpiIDBits);
107513690Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(lpiPendingTablePtr);
107613531Sjairo.balart@metempsy.com}
1077