gic_v3_distributor.cc revision 13756
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 */
3013756Sjairo.balart@metempsy.com
3113531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_distributor.hh"
3213531Sjairo.balart@metempsy.com
3313531Sjairo.balart@metempsy.com#include <algorithm>
3413531Sjairo.balart@metempsy.com
3513531Sjairo.balart@metempsy.com#include "debug/GIC.hh"
3613531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3.hh"
3713531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_cpu_interface.hh"
3813531Sjairo.balart@metempsy.com#include "dev/arm/gic_v3_redistributor.hh"
3913531Sjairo.balart@metempsy.com
4013756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IGROUPR   (0x0080, 0x00ff);
4113756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x017f);
4213756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x01ff);
4313756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ISPENDR   (0x0200, 0x027f);
4413756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICPENDR   (0x0280, 0x02ff);
4513756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x037f);
4613756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x03ff);
4713531Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x07ff);
4813756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x08ff);
4913756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_ICFGR     (0x0c00, 0x0cff);
5013756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IGRPMODR  (0x0d00, 0x0d7f);
5113756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_NSACR     (0x0e00, 0x0eff);
5213756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f1f);
5313756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f2f);
5413756Sjairo.balart@metempsy.comconst AddrRange Gicv3Distributor::GICD_IROUTER   (0x6000, 0x7fe0);
5513531Sjairo.balart@metempsy.com
5613531Sjairo.balart@metempsy.comGicv3Distributor::Gicv3Distributor(Gicv3 * gic, uint32_t it_lines)
5713531Sjairo.balart@metempsy.com    : gic(gic),
5813531Sjairo.balart@metempsy.com      itLines(it_lines),
5913531Sjairo.balart@metempsy.com      irqGroup(it_lines),
6013531Sjairo.balart@metempsy.com      irqEnabled(it_lines),
6113531Sjairo.balart@metempsy.com      irqPending(it_lines),
6213531Sjairo.balart@metempsy.com      irqActive(it_lines),
6313531Sjairo.balart@metempsy.com      irqPriority(it_lines),
6413531Sjairo.balart@metempsy.com      irqConfig(it_lines),
6513531Sjairo.balart@metempsy.com      irqGrpmod(it_lines),
6613531Sjairo.balart@metempsy.com      irqNsacr(it_lines),
6713531Sjairo.balart@metempsy.com      irqAffinityRouting(it_lines)
6813531Sjairo.balart@metempsy.com{
6913531Sjairo.balart@metempsy.com    panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
7013531Sjairo.balart@metempsy.com}
7113531Sjairo.balart@metempsy.com
7213531Sjairo.balart@metempsy.comvoid
7313531Sjairo.balart@metempsy.comGicv3Distributor::init()
7413531Sjairo.balart@metempsy.com{
7513531Sjairo.balart@metempsy.com}
7613531Sjairo.balart@metempsy.com
7713531Sjairo.balart@metempsy.comvoid
7813531Sjairo.balart@metempsy.comGicv3Distributor::initState()
7913531Sjairo.balart@metempsy.com{
8013531Sjairo.balart@metempsy.com    reset();
8113531Sjairo.balart@metempsy.com}
8213531Sjairo.balart@metempsy.com
8313531Sjairo.balart@metempsy.comvoid
8413531Sjairo.balart@metempsy.comGicv3Distributor::reset()
8513531Sjairo.balart@metempsy.com{
8613531Sjairo.balart@metempsy.com    std::fill(irqGroup.begin(), irqGroup.end(), 0);
8713531Sjairo.balart@metempsy.com    // Imp. defined reset value
8813531Sjairo.balart@metempsy.com    std::fill(irqEnabled.begin(), irqEnabled.end(), false);
8913531Sjairo.balart@metempsy.com    std::fill(irqPending.begin(), irqPending.end(), false);
9013531Sjairo.balart@metempsy.com    std::fill(irqActive.begin(), irqActive.end(), false);
9113531Sjairo.balart@metempsy.com    // Imp. defined reset value
9213531Sjairo.balart@metempsy.com    std::fill(irqPriority.begin(), irqPriority.end(), 0xAAAAAAAA);
9313531Sjairo.balart@metempsy.com    std::fill(irqConfig.begin(), irqConfig.end(),
9413531Sjairo.balart@metempsy.com              Gicv3::INT_LEVEL_SENSITIVE); // Imp. defined reset value
9513531Sjairo.balart@metempsy.com    std::fill(irqGrpmod.begin(), irqGrpmod.end(), 0);
9613531Sjairo.balart@metempsy.com    std::fill(irqNsacr.begin(), irqNsacr.end(), 0);
9713531Sjairo.balart@metempsy.com    /*
9813531Sjairo.balart@metempsy.com     * For our implementation affinity routing is always enabled,
9913531Sjairo.balart@metempsy.com     * no GICv2 legacy
10013531Sjairo.balart@metempsy.com     */
10113531Sjairo.balart@metempsy.com    ARE = true;
10213531Sjairo.balart@metempsy.com
10313531Sjairo.balart@metempsy.com    if (gic->getSystem()->haveSecurity()) {
10413531Sjairo.balart@metempsy.com        DS = false;
10513531Sjairo.balart@metempsy.com    } else {
10613531Sjairo.balart@metempsy.com        DS = true;
10713531Sjairo.balart@metempsy.com    }
10813531Sjairo.balart@metempsy.com
10913531Sjairo.balart@metempsy.com    EnableGrp0 = 0;
11013531Sjairo.balart@metempsy.com    EnableGrp1NS = 0;
11113531Sjairo.balart@metempsy.com    EnableGrp1S = 0;
11213531Sjairo.balart@metempsy.com}
11313531Sjairo.balart@metempsy.com
11413531Sjairo.balart@metempsy.comuint64_t
11513531Sjairo.balart@metempsy.comGicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
11613531Sjairo.balart@metempsy.com{
11713531Sjairo.balart@metempsy.com    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
11813531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
11913531Sjairo.balart@metempsy.com
12013531Sjairo.balart@metempsy.com        if (!DS && !is_secure_access) {
12113531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
12213531Sjairo.balart@metempsy.com            return 0;
12313531Sjairo.balart@metempsy.com        }
12413531Sjairo.balart@metempsy.com
12513531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
12613531Sjairo.balart@metempsy.com
12713531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
12813531Sjairo.balart@metempsy.com            return 0;
12913531Sjairo.balart@metempsy.com        }
13013531Sjairo.balart@metempsy.com
13113531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
13213756Sjairo.balart@metempsy.com             i++, int_id++) {
13313531Sjairo.balart@metempsy.com            val |= irqGroup[int_id] << i;
13413531Sjairo.balart@metempsy.com        }
13513531Sjairo.balart@metempsy.com
13613531Sjairo.balart@metempsy.com        return val;
13713756Sjairo.balart@metempsy.com    } else if (GICD_ISENABLER.contains(addr)) {
13813531Sjairo.balart@metempsy.com        // Interrupt Set-Enable Registers
13913531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
14013531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
14113531Sjairo.balart@metempsy.com
14213531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
14313531Sjairo.balart@metempsy.com            return 0;
14413531Sjairo.balart@metempsy.com        }
14513531Sjairo.balart@metempsy.com
14613531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
14713756Sjairo.balart@metempsy.com             i++, int_id++) {
14813756Sjairo.balart@metempsy.com
14913531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
15013531Sjairo.balart@metempsy.com            {
15113531Sjairo.balart@metempsy.com                continue;
15213531Sjairo.balart@metempsy.com            }
15313531Sjairo.balart@metempsy.com
15413531Sjairo.balart@metempsy.com            val |= irqEnabled[int_id] << i;
15513531Sjairo.balart@metempsy.com        }
15613531Sjairo.balart@metempsy.com
15713531Sjairo.balart@metempsy.com        return val;
15813531Sjairo.balart@metempsy.com    } else if (GICD_ICENABLER.contains(addr)) {
15913531Sjairo.balart@metempsy.com        // Interrupt Clear-Enable Registers
16013531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
16113531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
16213531Sjairo.balart@metempsy.com
16313531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
16413531Sjairo.balart@metempsy.com            return 0;
16513531Sjairo.balart@metempsy.com        }
16613531Sjairo.balart@metempsy.com
16713531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
16813756Sjairo.balart@metempsy.com             i++, int_id++) {
16913756Sjairo.balart@metempsy.com
17013531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
17113531Sjairo.balart@metempsy.com            {
17213531Sjairo.balart@metempsy.com                continue;
17313531Sjairo.balart@metempsy.com            }
17413531Sjairo.balart@metempsy.com
17513531Sjairo.balart@metempsy.com            val |= (irqEnabled[int_id] << i);
17613531Sjairo.balart@metempsy.com        }
17713531Sjairo.balart@metempsy.com
17813531Sjairo.balart@metempsy.com        return val;
17913531Sjairo.balart@metempsy.com    } else if (GICD_ISPENDR.contains(addr)) {
18013756Sjairo.balart@metempsy.com        // Interrupt Set-Pending Registers
18113531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
18213531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
18313531Sjairo.balart@metempsy.com
18413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
18513531Sjairo.balart@metempsy.com            return 0;
18613531Sjairo.balart@metempsy.com        }
18713531Sjairo.balart@metempsy.com
18813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
18913756Sjairo.balart@metempsy.com             i++, int_id++) {
19013756Sjairo.balart@metempsy.com
19113531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
19213531Sjairo.balart@metempsy.com            {
19313531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] == 0) {
19413531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
19513531Sjairo.balart@metempsy.com                    continue;
19613531Sjairo.balart@metempsy.com                }
19713531Sjairo.balart@metempsy.com            }
19813531Sjairo.balart@metempsy.com
19913531Sjairo.balart@metempsy.com            val |= (irqPending[int_id] << i);
20013531Sjairo.balart@metempsy.com        }
20113531Sjairo.balart@metempsy.com
20213531Sjairo.balart@metempsy.com        return val;
20313531Sjairo.balart@metempsy.com    } else if (GICD_ICPENDR.contains(addr)) {
20413756Sjairo.balart@metempsy.com        // Interrupt Clear-Pending Registers
20513531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
20613531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
20713531Sjairo.balart@metempsy.com
20813531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
20913531Sjairo.balart@metempsy.com            return 0;
21013531Sjairo.balart@metempsy.com        }
21113531Sjairo.balart@metempsy.com
21213531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
21313756Sjairo.balart@metempsy.com             i++, int_id++) {
21413756Sjairo.balart@metempsy.com
21513531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
21613531Sjairo.balart@metempsy.com            {
21713531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
21813531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
21913531Sjairo.balart@metempsy.com                    continue;
22013531Sjairo.balart@metempsy.com                }
22113531Sjairo.balart@metempsy.com            }
22213531Sjairo.balart@metempsy.com
22313531Sjairo.balart@metempsy.com            val |= (irqPending[int_id] << i);
22413531Sjairo.balart@metempsy.com        }
22513531Sjairo.balart@metempsy.com
22613531Sjairo.balart@metempsy.com        return val;
22713756Sjairo.balart@metempsy.com    } else if (GICD_ISACTIVER.contains(addr)) {
22813531Sjairo.balart@metempsy.com        // Interrupt Set-Active Registers
22913531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
23013531Sjairo.balart@metempsy.com
23113531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
23213531Sjairo.balart@metempsy.com            return 0;
23313531Sjairo.balart@metempsy.com        }
23413531Sjairo.balart@metempsy.com
23513531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
23613531Sjairo.balart@metempsy.com
23713531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
23813756Sjairo.balart@metempsy.com             i++, int_id++) {
23913756Sjairo.balart@metempsy.com
24013531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
24113531Sjairo.balart@metempsy.com            {
24213531Sjairo.balart@metempsy.com                // Group 0 or Secure Group 1 interrupts are RAZ/WI
24313531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
24413531Sjairo.balart@metempsy.com                    continue;
24513531Sjairo.balart@metempsy.com                }
24613531Sjairo.balart@metempsy.com            }
24713531Sjairo.balart@metempsy.com
24813531Sjairo.balart@metempsy.com            val |= (irqActive[int_id] << i);
24913531Sjairo.balart@metempsy.com        }
25013531Sjairo.balart@metempsy.com
25113531Sjairo.balart@metempsy.com        return val;
25213756Sjairo.balart@metempsy.com    } else if (GICD_ICACTIVER.contains(addr)) {
25313531Sjairo.balart@metempsy.com        // Interrupt Clear-Active Registers
25413531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
25513531Sjairo.balart@metempsy.com
25613531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
25713531Sjairo.balart@metempsy.com            return 0;
25813531Sjairo.balart@metempsy.com        }
25913531Sjairo.balart@metempsy.com
26013531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
26113531Sjairo.balart@metempsy.com
26213531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
26313756Sjairo.balart@metempsy.com             i++, int_id++) {
26413756Sjairo.balart@metempsy.com
26513531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
26613531Sjairo.balart@metempsy.com            {
26713531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
26813531Sjairo.balart@metempsy.com                    continue;
26913531Sjairo.balart@metempsy.com                }
27013531Sjairo.balart@metempsy.com            }
27113531Sjairo.balart@metempsy.com
27213531Sjairo.balart@metempsy.com            val |= (irqActive[int_id] << i);
27313531Sjairo.balart@metempsy.com        }
27413531Sjairo.balart@metempsy.com
27513531Sjairo.balart@metempsy.com        return val;
27613756Sjairo.balart@metempsy.com    } else if (GICD_IPRIORITYR.contains(addr)) {
27713531Sjairo.balart@metempsy.com        // Interrupt Priority Registers
27813531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
27913531Sjairo.balart@metempsy.com        int first_intid = addr - GICD_IPRIORITYR.start();
28013531Sjairo.balart@metempsy.com
28113531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
28213531Sjairo.balart@metempsy.com            return 0;
28313531Sjairo.balart@metempsy.com        }
28413531Sjairo.balart@metempsy.com
28513531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
28613756Sjairo.balart@metempsy.com             i++, int_id++) {
28713756Sjairo.balart@metempsy.com
28813531Sjairo.balart@metempsy.com            uint8_t prio = irqPriority[int_id];
28913531Sjairo.balart@metempsy.com
29013531Sjairo.balart@metempsy.com            if (!DS && !is_secure_access) {
29113531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
29213531Sjairo.balart@metempsy.com                    // RAZ/WI for non-secure accesses for secure interrupts
29313531Sjairo.balart@metempsy.com                    continue;
29413531Sjairo.balart@metempsy.com                } else {
29513531Sjairo.balart@metempsy.com                    // NS view
29613531Sjairo.balart@metempsy.com                    prio = (prio << 1) & 0xff;
29713531Sjairo.balart@metempsy.com                }
29813531Sjairo.balart@metempsy.com            }
29913531Sjairo.balart@metempsy.com
30013531Sjairo.balart@metempsy.com            val |= prio << (i * 8);
30113531Sjairo.balart@metempsy.com        }
30213531Sjairo.balart@metempsy.com
30313531Sjairo.balart@metempsy.com        return val;
30413531Sjairo.balart@metempsy.com    } else if (GICD_ITARGETSR.contains(addr)) {
30513531Sjairo.balart@metempsy.com        // Interrupt Processor Targets Registers
30613531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
30713531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::read(): "
30813531Sjairo.balart@metempsy.com             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
30913531Sjairo.balart@metempsy.com        return 0;
31013756Sjairo.balart@metempsy.com    } else if (GICD_ICFGR.contains(addr)) {
31113531Sjairo.balart@metempsy.com        // Interrupt Configuration Registers
31213531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICFGR.start()) * 4;
31313531Sjairo.balart@metempsy.com
31413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
31513531Sjairo.balart@metempsy.com            return 0;
31613531Sjairo.balart@metempsy.com        }
31713531Sjairo.balart@metempsy.com
31813531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
31913531Sjairo.balart@metempsy.com
32013531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
32113756Sjairo.balart@metempsy.com             i = i + 2, int_id++) {
32213756Sjairo.balart@metempsy.com
32313531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
32413531Sjairo.balart@metempsy.com            {
32513531Sjairo.balart@metempsy.com                continue;
32613531Sjairo.balart@metempsy.com            }
32713531Sjairo.balart@metempsy.com
32813531Sjairo.balart@metempsy.com            if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
32913531Sjairo.balart@metempsy.com                val |= (0x2 << i);
33013531Sjairo.balart@metempsy.com            }
33113531Sjairo.balart@metempsy.com        }
33213531Sjairo.balart@metempsy.com
33313531Sjairo.balart@metempsy.com        return val;
33413531Sjairo.balart@metempsy.com    } else if (GICD_IGRPMODR.contains(addr)) {
33513531Sjairo.balart@metempsy.com        // Interrupt Group Modifier Registers
33613531Sjairo.balart@metempsy.com        if (DS) {
33713531Sjairo.balart@metempsy.com            // RAZ/WI if security disabled
33813531Sjairo.balart@metempsy.com            return 0;
33913531Sjairo.balart@metempsy.com        } else {
34013531Sjairo.balart@metempsy.com            if (!is_secure_access) {
34113531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses
34213531Sjairo.balart@metempsy.com                return 0;
34313531Sjairo.balart@metempsy.com            } else {
34413531Sjairo.balart@metempsy.com                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
34513531Sjairo.balart@metempsy.com
34613531Sjairo.balart@metempsy.com                if (isNotSPI(first_intid)) {
34713531Sjairo.balart@metempsy.com                    return 0;
34813531Sjairo.balart@metempsy.com                }
34913531Sjairo.balart@metempsy.com
35013531Sjairo.balart@metempsy.com                uint64_t val = 0x0;
35113531Sjairo.balart@metempsy.com
35213531Sjairo.balart@metempsy.com                for (int i = 0, int_id = first_intid;
35313756Sjairo.balart@metempsy.com                     i < 8 * size && int_id < itLines; i++, int_id++) {
35413531Sjairo.balart@metempsy.com                    val |= irqGrpmod[int_id] << i;
35513531Sjairo.balart@metempsy.com                }
35613531Sjairo.balart@metempsy.com
35713531Sjairo.balart@metempsy.com                return val;
35813531Sjairo.balart@metempsy.com            }
35913531Sjairo.balart@metempsy.com        }
36013756Sjairo.balart@metempsy.com    } else if (GICD_NSACR.contains(addr)) {
36113531Sjairo.balart@metempsy.com        // Non-secure Access Control Registers
36213531Sjairo.balart@metempsy.com        // 2 bits per interrupt
36313531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_NSACR.start()) * 4;
36413531Sjairo.balart@metempsy.com
36513531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
36613531Sjairo.balart@metempsy.com            return 0;
36713531Sjairo.balart@metempsy.com        }
36813531Sjairo.balart@metempsy.com
36913531Sjairo.balart@metempsy.com        if (DS || (!DS && !is_secure_access)) {
37013531Sjairo.balart@metempsy.com            return 0;
37113531Sjairo.balart@metempsy.com        }
37213531Sjairo.balart@metempsy.com
37313531Sjairo.balart@metempsy.com        uint64_t val = 0x0;
37413531Sjairo.balart@metempsy.com
37513531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid;
37613756Sjairo.balart@metempsy.com             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
37713531Sjairo.balart@metempsy.com            val |= irqNsacr[int_id] << i;
37813531Sjairo.balart@metempsy.com        }
37913531Sjairo.balart@metempsy.com
38013531Sjairo.balart@metempsy.com        return val;
38113531Sjairo.balart@metempsy.com    } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
38213531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
38313531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::read(): "
38413531Sjairo.balart@metempsy.com             "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
38513531Sjairo.balart@metempsy.com        return 0x0;
38613531Sjairo.balart@metempsy.com    } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
38713531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
38813531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::read(): "
38913531Sjairo.balart@metempsy.com             "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
39013531Sjairo.balart@metempsy.com        return 0x0;
39113531Sjairo.balart@metempsy.com    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
39213531Sjairo.balart@metempsy.com        // 64 bit registers. 2 or 1 access.
39313531Sjairo.balart@metempsy.com        int int_id = (addr - GICD_IROUTER.start()) / 8;
39413531Sjairo.balart@metempsy.com
39513531Sjairo.balart@metempsy.com        if (isNotSPI(int_id)) {
39613531Sjairo.balart@metempsy.com            return 0;
39713531Sjairo.balart@metempsy.com        }
39813531Sjairo.balart@metempsy.com
39913531Sjairo.balart@metempsy.com        if (nsAccessToSecInt(int_id, is_secure_access))
40013531Sjairo.balart@metempsy.com        {
40113531Sjairo.balart@metempsy.com            if (irqNsacr[int_id] < 3) {
40213531Sjairo.balart@metempsy.com                return 0;
40313531Sjairo.balart@metempsy.com            }
40413531Sjairo.balart@metempsy.com        }
40513531Sjairo.balart@metempsy.com
40613531Sjairo.balart@metempsy.com        if (size == 4) {
40713531Sjairo.balart@metempsy.com            if (addr & 7) { // high half of 64 bit register
40813531Sjairo.balart@metempsy.com                return irqAffinityRouting[int_id] >> 32;
40913531Sjairo.balart@metempsy.com            } else { // high low of 64 bit register
41013531Sjairo.balart@metempsy.com                return irqAffinityRouting[int_id] & 0xFFFFFFFF;
41113531Sjairo.balart@metempsy.com            }
41213531Sjairo.balart@metempsy.com        } else {
41313531Sjairo.balart@metempsy.com            return irqAffinityRouting[int_id];
41413531Sjairo.balart@metempsy.com        }
41513531Sjairo.balart@metempsy.com    }
41613531Sjairo.balart@metempsy.com
41713531Sjairo.balart@metempsy.com    switch (addr) {
41813531Sjairo.balart@metempsy.com      case GICD_CTLR: // Control Register
41913531Sjairo.balart@metempsy.com        if (!DS) {
42013531Sjairo.balart@metempsy.com            if (is_secure_access) {
42113531Sjairo.balart@metempsy.com                // E1NWF [7] RAZ/WI
42213531Sjairo.balart@metempsy.com                // DS [6] - Disable Security
42313531Sjairo.balart@metempsy.com                // ARE_NS [5] RAO/WI
42413531Sjairo.balart@metempsy.com                // ARE_S [4] RAO/WI
42513531Sjairo.balart@metempsy.com                // EnableGrp1S [2]
42613531Sjairo.balart@metempsy.com                // EnableGrp1NS [1]
42713531Sjairo.balart@metempsy.com                // EnableGrp0 [0]
42813531Sjairo.balart@metempsy.com                return (EnableGrp0 << 0) |
42913531Sjairo.balart@metempsy.com                    (EnableGrp1NS << 1) |
43013531Sjairo.balart@metempsy.com                    (EnableGrp1S << 2) |
43113531Sjairo.balart@metempsy.com                    (1 << 4) |
43213531Sjairo.balart@metempsy.com                    (1 << 5) |
43313531Sjairo.balart@metempsy.com                    (DS << 6);
43413531Sjairo.balart@metempsy.com            } else {
43513531Sjairo.balart@metempsy.com                // ARE_NS [4] RAO/WI;
43613531Sjairo.balart@metempsy.com                // EnableGrp1A [1] is a read-write alias of the Secure
43713531Sjairo.balart@metempsy.com                // GICD_CTLR.EnableGrp1NS
43813531Sjairo.balart@metempsy.com                // EnableGrp1 [0] RES0
43913531Sjairo.balart@metempsy.com                return (1 << 4) | (EnableGrp1NS << 1);
44013531Sjairo.balart@metempsy.com            }
44113531Sjairo.balart@metempsy.com        } else {
44213531Sjairo.balart@metempsy.com            return (DS << 6) | (ARE << 4) |
44313531Sjairo.balart@metempsy.com                (EnableGrp1NS << 1) | (EnableGrp0 << 0);
44413531Sjairo.balart@metempsy.com        }
44513531Sjairo.balart@metempsy.com
44613531Sjairo.balart@metempsy.com      case GICD_TYPER: // Interrupt Controller Type Register
44713531Sjairo.balart@metempsy.com        /*
44813531Sjairo.balart@metempsy.com         * RSS           [26]    == 1
44913531Sjairo.balart@metempsy.com         * (The implementation does supports targeted SGIs with affinity
45013531Sjairo.balart@metempsy.com         * level 0 values of 0 - 255)
45113531Sjairo.balart@metempsy.com         * No1N          [25]    == 1
45213531Sjairo.balart@metempsy.com         * (1 of N SPI interrupts are not supported)
45313531Sjairo.balart@metempsy.com         * A3V           [24]    == 1
45413531Sjairo.balart@metempsy.com         * (Supports nonzero values of Affinity level 3)
45513531Sjairo.balart@metempsy.com         * IDbits        [23:19] == 0xf
45613531Sjairo.balart@metempsy.com         * (The number of interrupt identifier bits supported, minus one)
45713531Sjairo.balart@metempsy.com         * DVIS          [18]    == 0
45813531Sjairo.balart@metempsy.com         * (The implementation does not support Direct Virtual LPI
45913531Sjairo.balart@metempsy.com         * injection)
46013690Sjairo.balart@metempsy.com         * LPIS          [17]    == 1
46113531Sjairo.balart@metempsy.com         * (The implementation does not support LPIs)
46213531Sjairo.balart@metempsy.com         * MBIS          [16]    == 0
46313531Sjairo.balart@metempsy.com         * (The implementation does not support message-based interrupts
46413531Sjairo.balart@metempsy.com         * by writing to Distributor registers)
46513531Sjairo.balart@metempsy.com         * SecurityExtn  [10]    == X
46613531Sjairo.balart@metempsy.com         * (The GIC implementation supports two Security states)
46713531Sjairo.balart@metempsy.com         * CPUNumber     [7:5]   == 0
46813531Sjairo.balart@metempsy.com         * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
46913531Sjairo.balart@metempsy.com         * ITLinesNumber [4:0]   == N
47013531Sjairo.balart@metempsy.com         * (MaxSPIIntId = 32 (N + 1) - 1)
47113531Sjairo.balart@metempsy.com         */
47213531Sjairo.balart@metempsy.com        {
47313531Sjairo.balart@metempsy.com            int max_spi_int_id = itLines - 1;
47413531Sjairo.balart@metempsy.com            int it_lines_number = ceil((max_spi_int_id + 1) / 32.0) - 1;
47513531Sjairo.balart@metempsy.com            return (1 << 26) | (1 << 25) | (1 << 24) | (0xf << 19) |
47613690Sjairo.balart@metempsy.com                (1 << 17) | (gic->getSystem()->haveSecurity() << 10) |
47713531Sjairo.balart@metempsy.com                (it_lines_number << 0);
47813531Sjairo.balart@metempsy.com        }
47913531Sjairo.balart@metempsy.com
48013531Sjairo.balart@metempsy.com      case GICD_IIDR: // Implementer Identification Register
48113531Sjairo.balart@metempsy.com        //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
48213531Sjairo.balart@metempsy.com        return 0;
48313531Sjairo.balart@metempsy.com
48413531Sjairo.balart@metempsy.com      case GICD_STATUSR: // Error Reporting Status Register
48513531Sjairo.balart@metempsy.com        // Optional register, RAZ/WI
48613531Sjairo.balart@metempsy.com        return 0x0;
48713531Sjairo.balart@metempsy.com
48813756Sjairo.balart@metempsy.com      case GICD_PIDR0: // Peripheral ID0 Register
48913756Sjairo.balart@metempsy.com          return 0x92; // Part number, bits[7:0]
49013531Sjairo.balart@metempsy.com
49113531Sjairo.balart@metempsy.com      case GICD_PIDR1: { // Peripheral ID1 Register
49213531Sjairo.balart@metempsy.com          uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
49313531Sjairo.balart@metempsy.com          uint8_t part_1 = 0x4; // Part number, bits[11:8]
49413531Sjairo.balart@metempsy.com          return (des_0 << 4) | (part_1 << 0);
49513531Sjairo.balart@metempsy.com      }
49613531Sjairo.balart@metempsy.com
49713531Sjairo.balart@metempsy.com      case GICD_PIDR2: { // Peripheral ID2 Register
49813531Sjairo.balart@metempsy.com          uint8_t arch_rev = 0x3; // 0x3 GICv3
49913531Sjairo.balart@metempsy.com          uint8_t jdec = 0x1; // JEP code
50013531Sjairo.balart@metempsy.com          uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
50113531Sjairo.balart@metempsy.com          return (arch_rev << 4) | (jdec << 3) | (des_1 << 0);
50213531Sjairo.balart@metempsy.com      }
50313531Sjairo.balart@metempsy.com
50413531Sjairo.balart@metempsy.com      case GICD_PIDR3: // Peripheral ID3 Register
50513531Sjairo.balart@metempsy.com        return 0x0; // Implementation defined
50613531Sjairo.balart@metempsy.com
50713531Sjairo.balart@metempsy.com      case GICD_PIDR4: { // Peripheral ID4 Register
50813531Sjairo.balart@metempsy.com          uint8_t size = 0x4; // 64 KB software visible page
50913531Sjairo.balart@metempsy.com          uint8_t des_2 = 0x4; // ARM implementation
51013531Sjairo.balart@metempsy.com          return (size << 4) | (des_2 << 0);
51113531Sjairo.balart@metempsy.com      }
51213531Sjairo.balart@metempsy.com
51313531Sjairo.balart@metempsy.com      case GICD_PIDR5: // Peripheral ID5 Register
51413531Sjairo.balart@metempsy.com      case GICD_PIDR6: // Peripheral ID6 Register
51513531Sjairo.balart@metempsy.com      case GICD_PIDR7: // Peripheral ID7 Register
51613531Sjairo.balart@metempsy.com        return 0; // RES0
51713531Sjairo.balart@metempsy.com
51813531Sjairo.balart@metempsy.com      default:
51913531Sjairo.balart@metempsy.com        panic("Gicv3Distributor::read(): invalid offset %#x\n", addr);
52013531Sjairo.balart@metempsy.com        break;
52113531Sjairo.balart@metempsy.com    }
52213531Sjairo.balart@metempsy.com}
52313531Sjairo.balart@metempsy.com
52413531Sjairo.balart@metempsy.comvoid
52513531Sjairo.balart@metempsy.comGicv3Distributor::write(Addr addr, uint64_t data, size_t size,
52613531Sjairo.balart@metempsy.com                        bool is_secure_access)
52713531Sjairo.balart@metempsy.com{
52813531Sjairo.balart@metempsy.com    if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
52913531Sjairo.balart@metempsy.com        if (!DS && !is_secure_access) {
53013531Sjairo.balart@metempsy.com            // RAZ/WI for non-secure accesses
53113531Sjairo.balart@metempsy.com            return;
53213531Sjairo.balart@metempsy.com        }
53313531Sjairo.balart@metempsy.com
53413531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_IGROUPR.start()) * 8;
53513531Sjairo.balart@metempsy.com
53613531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
53713531Sjairo.balart@metempsy.com            return;
53813531Sjairo.balart@metempsy.com        }
53913531Sjairo.balart@metempsy.com
54013531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
54113756Sjairo.balart@metempsy.com             i++, int_id++) {
54213531Sjairo.balart@metempsy.com            irqGroup[int_id] = data & (1 << i) ? 1 : 0;
54313531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
54413531Sjairo.balart@metempsy.com                    int_id, irqGroup[int_id]);
54513531Sjairo.balart@metempsy.com        }
54613531Sjairo.balart@metempsy.com
54713531Sjairo.balart@metempsy.com        return;
54813756Sjairo.balart@metempsy.com    } else if (GICD_ISENABLER.contains(addr)) {
54913531Sjairo.balart@metempsy.com        // Interrupt Set-Enable Registers
55013531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISENABLER.start()) * 8;
55113531Sjairo.balart@metempsy.com
55213531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
55313531Sjairo.balart@metempsy.com            return;
55413531Sjairo.balart@metempsy.com        }
55513531Sjairo.balart@metempsy.com
55613531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
55713756Sjairo.balart@metempsy.com             i++, int_id++) {
55813756Sjairo.balart@metempsy.com
55913531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
56013531Sjairo.balart@metempsy.com            {
56113531Sjairo.balart@metempsy.com                continue;
56213531Sjairo.balart@metempsy.com            }
56313531Sjairo.balart@metempsy.com
56413531Sjairo.balart@metempsy.com            bool enable = data & (1 << i) ? 1 : 0;
56513531Sjairo.balart@metempsy.com
56613531Sjairo.balart@metempsy.com            if (enable) {
56713531Sjairo.balart@metempsy.com                if (!irqEnabled[int_id]) {
56813531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
56913531Sjairo.balart@metempsy.com                            "int_id %d enabled\n", int_id);
57013531Sjairo.balart@metempsy.com                }
57113531Sjairo.balart@metempsy.com
57213531Sjairo.balart@metempsy.com                irqEnabled[int_id] = true;
57313531Sjairo.balart@metempsy.com            }
57413531Sjairo.balart@metempsy.com        }
57513531Sjairo.balart@metempsy.com
57613531Sjairo.balart@metempsy.com        return;
57713531Sjairo.balart@metempsy.com    } else if (GICD_ICENABLER.contains(addr)) {
57813531Sjairo.balart@metempsy.com        // Interrupt Clear-Enable Registers
57913531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICENABLER.start()) * 8;
58013531Sjairo.balart@metempsy.com
58113531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
58213756Sjairo.balart@metempsy.com             i++, int_id++) {
58313756Sjairo.balart@metempsy.com
58413531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
58513531Sjairo.balart@metempsy.com            {
58613531Sjairo.balart@metempsy.com                continue;
58713531Sjairo.balart@metempsy.com            }
58813531Sjairo.balart@metempsy.com
58913531Sjairo.balart@metempsy.com            bool disable = data & (1 << i) ? 1 : 0;
59013531Sjairo.balart@metempsy.com
59113531Sjairo.balart@metempsy.com            if (disable) {
59213531Sjairo.balart@metempsy.com                if (irqEnabled[int_id]) {
59313531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
59413531Sjairo.balart@metempsy.com                            "int_id %d disabled\n", int_id);
59513531Sjairo.balart@metempsy.com                }
59613531Sjairo.balart@metempsy.com
59713531Sjairo.balart@metempsy.com                irqEnabled[int_id] = false;
59813531Sjairo.balart@metempsy.com            }
59913531Sjairo.balart@metempsy.com        }
60013531Sjairo.balart@metempsy.com
60113531Sjairo.balart@metempsy.com        return;
60213531Sjairo.balart@metempsy.com    } else if (GICD_ISPENDR.contains(addr)) {
60313756Sjairo.balart@metempsy.com        // Interrupt Set-Pending Registers
60413531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISPENDR.start()) * 8;
60513531Sjairo.balart@metempsy.com
60613531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
60713531Sjairo.balart@metempsy.com            return;
60813531Sjairo.balart@metempsy.com        }
60913531Sjairo.balart@metempsy.com
61013531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
61113756Sjairo.balart@metempsy.com             i++, int_id++) {
61213756Sjairo.balart@metempsy.com
61313531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
61413531Sjairo.balart@metempsy.com            {
61513531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] == 0) {
61613531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
61713531Sjairo.balart@metempsy.com                    continue;
61813531Sjairo.balart@metempsy.com                }
61913531Sjairo.balart@metempsy.com            }
62013531Sjairo.balart@metempsy.com
62113531Sjairo.balart@metempsy.com            bool pending = data & (1 << i) ? 1 : 0;
62213531Sjairo.balart@metempsy.com
62313531Sjairo.balart@metempsy.com            if (pending) {
62413531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
62513531Sjairo.balart@metempsy.com                        "int_id %d (SPI) pending bit set\n", int_id);
62613531Sjairo.balart@metempsy.com                irqPending[int_id] = true;
62713531Sjairo.balart@metempsy.com            }
62813531Sjairo.balart@metempsy.com        }
62913531Sjairo.balart@metempsy.com
63013531Sjairo.balart@metempsy.com        updateAndInformCPUInterfaces();
63113531Sjairo.balart@metempsy.com        return;
63213531Sjairo.balart@metempsy.com    } else if (GICD_ICPENDR.contains(addr)) {
63313756Sjairo.balart@metempsy.com        // Interrupt Clear-Pending Registers
63413531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICPENDR.start()) * 8;
63513531Sjairo.balart@metempsy.com
63613531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
63713531Sjairo.balart@metempsy.com            return;
63813531Sjairo.balart@metempsy.com        }
63913531Sjairo.balart@metempsy.com
64013531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
64113756Sjairo.balart@metempsy.com             i++, int_id++) {
64213756Sjairo.balart@metempsy.com
64313531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
64413531Sjairo.balart@metempsy.com            {
64513531Sjairo.balart@metempsy.com                if (irqNsacr[int_id] < 2) {
64613531Sjairo.balart@metempsy.com                    // Group 0 or Secure Group 1 interrupts are RAZ/WI
64713531Sjairo.balart@metempsy.com                    continue;
64813531Sjairo.balart@metempsy.com                }
64913531Sjairo.balart@metempsy.com            }
65013531Sjairo.balart@metempsy.com
65113531Sjairo.balart@metempsy.com            bool clear = data & (1 << i) ? 1 : 0;
65213531Sjairo.balart@metempsy.com
65313531Sjairo.balart@metempsy.com            if (clear) {
65413531Sjairo.balart@metempsy.com                irqPending[int_id] = false;
65513531Sjairo.balart@metempsy.com            }
65613531Sjairo.balart@metempsy.com        }
65713531Sjairo.balart@metempsy.com
65813531Sjairo.balart@metempsy.com        updateAndInformCPUInterfaces();
65913531Sjairo.balart@metempsy.com        return;
66013756Sjairo.balart@metempsy.com    } else if (GICD_ISACTIVER.contains(addr)) {
66113531Sjairo.balart@metempsy.com        // Interrupt Set-Active Registers
66213531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
66313531Sjairo.balart@metempsy.com
66413531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
66513531Sjairo.balart@metempsy.com            return;
66613531Sjairo.balart@metempsy.com        }
66713531Sjairo.balart@metempsy.com
66813531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
66913756Sjairo.balart@metempsy.com             i++, int_id++) {
67013756Sjairo.balart@metempsy.com
67113531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
67213531Sjairo.balart@metempsy.com            {
67313531Sjairo.balart@metempsy.com                continue;
67413531Sjairo.balart@metempsy.com            }
67513531Sjairo.balart@metempsy.com
67613531Sjairo.balart@metempsy.com            bool active = data & (1 << i) ? 1 : 0;
67713531Sjairo.balart@metempsy.com
67813531Sjairo.balart@metempsy.com            if (active) {
67913531Sjairo.balart@metempsy.com                irqActive[int_id] = 1;
68013531Sjairo.balart@metempsy.com            }
68113531Sjairo.balart@metempsy.com        }
68213531Sjairo.balart@metempsy.com
68313531Sjairo.balart@metempsy.com        return;
68413531Sjairo.balart@metempsy.com    } else if (GICD_ICACTIVER.contains(addr)) {
68513531Sjairo.balart@metempsy.com        // Interrupt Clear-Active Registers
68613531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
68713531Sjairo.balart@metempsy.com
68813531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
68913531Sjairo.balart@metempsy.com            return;
69013531Sjairo.balart@metempsy.com        }
69113531Sjairo.balart@metempsy.com
69213531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
69313756Sjairo.balart@metempsy.com             i++, int_id++) {
69413756Sjairo.balart@metempsy.com
69513531Sjairo.balart@metempsy.com            if (nsAccessToSecInt(int_id, is_secure_access))
69613531Sjairo.balart@metempsy.com            {
69713531Sjairo.balart@metempsy.com                continue;
69813531Sjairo.balart@metempsy.com            }
69913531Sjairo.balart@metempsy.com
70013531Sjairo.balart@metempsy.com            bool clear = data & (1 << i) ? 1 : 0;
70113531Sjairo.balart@metempsy.com
70213531Sjairo.balart@metempsy.com            if (clear) {
70313531Sjairo.balart@metempsy.com                if (irqActive[int_id]) {
70413531Sjairo.balart@metempsy.com                    DPRINTF(GIC, "Gicv3Distributor::write(): "
70513531Sjairo.balart@metempsy.com                            "int_id %d active cleared\n", int_id);
70613531Sjairo.balart@metempsy.com                }
70713531Sjairo.balart@metempsy.com
70813531Sjairo.balart@metempsy.com                irqActive[int_id] = false;
70913531Sjairo.balart@metempsy.com            }
71013531Sjairo.balart@metempsy.com        }
71113531Sjairo.balart@metempsy.com
71213531Sjairo.balart@metempsy.com        return;
71313756Sjairo.balart@metempsy.com    } else if (GICD_IPRIORITYR.contains(addr)) {
71413531Sjairo.balart@metempsy.com        // Interrupt Priority Registers
71513531Sjairo.balart@metempsy.com        int first_intid = addr - GICD_IPRIORITYR.start();
71613531Sjairo.balart@metempsy.com
71713531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
71813531Sjairo.balart@metempsy.com            return;
71913531Sjairo.balart@metempsy.com        }
72013531Sjairo.balart@metempsy.com
72113531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
72213531Sjairo.balart@metempsy.com                i++, int_id++) {
72313531Sjairo.balart@metempsy.com            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
72413531Sjairo.balart@metempsy.com
72513531Sjairo.balart@metempsy.com            if (!DS && !is_secure_access) {
72613531Sjairo.balart@metempsy.com                if (getIntGroup(int_id) != Gicv3::G1NS) {
72713531Sjairo.balart@metempsy.com                    // RAZ/WI for non-secure accesses to secure interrupts
72813531Sjairo.balart@metempsy.com                    continue;
72913531Sjairo.balart@metempsy.com                } else {
73013531Sjairo.balart@metempsy.com                    prio = 0x80 | (prio >> 1);
73113531Sjairo.balart@metempsy.com                }
73213531Sjairo.balart@metempsy.com            }
73313531Sjairo.balart@metempsy.com
73413531Sjairo.balart@metempsy.com            irqPriority[int_id] = prio;
73513531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
73613531Sjairo.balart@metempsy.com                    int_id, irqPriority[int_id]);
73713531Sjairo.balart@metempsy.com        }
73813531Sjairo.balart@metempsy.com
73913531Sjairo.balart@metempsy.com        return;
74013531Sjairo.balart@metempsy.com    } else if (GICD_ITARGETSR.contains(addr)) {
74113531Sjairo.balart@metempsy.com        // Interrupt Processor Targets Registers
74213531Sjairo.balart@metempsy.com        // ARE always on, RAZ/WI
74313531Sjairo.balart@metempsy.com        warn("Gicv3Distributor::write(): "
74413531Sjairo.balart@metempsy.com             "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
74513531Sjairo.balart@metempsy.com        return;
74613756Sjairo.balart@metempsy.com    } else if (GICD_ICFGR.contains(addr)) {
74713531Sjairo.balart@metempsy.com        // Interrupt Configuration Registers
74813756Sjairo.balart@metempsy.com        // for x = 0 to 15:
74913756Sjairo.balart@metempsy.com        //   GICD_ICFGR[2x] = RES0
75013756Sjairo.balart@metempsy.com        //   GICD_ICFGR[2x + 1] =
75113756Sjairo.balart@metempsy.com        //     0 level-sensitive
75213756Sjairo.balart@metempsy.com        //     1 edge-triggered
75313531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_ICFGR.start()) * 4;
75413531Sjairo.balart@metempsy.com
75513531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
75613531Sjairo.balart@metempsy.com            return;
75713531Sjairo.balart@metempsy.com        }
75813531Sjairo.balart@metempsy.com
75913531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
76013756Sjairo.balart@metempsy.com             i = i + 2, int_id++) {
76113531Sjairo.balart@metempsy.com            irqConfig[int_id] = data & (0x2 << i) ?
76213531Sjairo.balart@metempsy.com                                Gicv3::INT_EDGE_TRIGGERED :
76313531Sjairo.balart@metempsy.com                                Gicv3::INT_LEVEL_SENSITIVE;
76413531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
76513531Sjairo.balart@metempsy.com                    int_id, irqConfig[int_id]);
76613531Sjairo.balart@metempsy.com        }
76713531Sjairo.balart@metempsy.com
76813531Sjairo.balart@metempsy.com        return;
76913531Sjairo.balart@metempsy.com    } else if (GICD_IGRPMODR.contains(addr)) {
77013531Sjairo.balart@metempsy.com        // Interrupt Group Modifier Registers
77113531Sjairo.balart@metempsy.com        if (DS) {
77213531Sjairo.balart@metempsy.com            return;
77313531Sjairo.balart@metempsy.com        } else {
77413531Sjairo.balart@metempsy.com            if (!is_secure_access) {
77513531Sjairo.balart@metempsy.com                // RAZ/WI for non-secure accesses
77613531Sjairo.balart@metempsy.com                return;
77713531Sjairo.balart@metempsy.com            } else {
77813531Sjairo.balart@metempsy.com                int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
77913531Sjairo.balart@metempsy.com
78013531Sjairo.balart@metempsy.com                if (isNotSPI(first_intid)) {
78113531Sjairo.balart@metempsy.com                    return;
78213531Sjairo.balart@metempsy.com                }
78313531Sjairo.balart@metempsy.com
78413531Sjairo.balart@metempsy.com                for (int i = 0, int_id = first_intid;
78513756Sjairo.balart@metempsy.com                     i < 8 * size && int_id < itLines; i++, int_id++) {
78613531Sjairo.balart@metempsy.com                    irqGrpmod[int_id] = data & (0x1 << i);
78713531Sjairo.balart@metempsy.com                }
78813531Sjairo.balart@metempsy.com
78913531Sjairo.balart@metempsy.com                return ;
79013531Sjairo.balart@metempsy.com            }
79113531Sjairo.balart@metempsy.com        }
79213531Sjairo.balart@metempsy.com
79313756Sjairo.balart@metempsy.com    } else if (GICD_NSACR.contains(addr)) {
79413531Sjairo.balart@metempsy.com        // Non-secure Access Control Registers
79513531Sjairo.balart@metempsy.com        // 2 bits per interrupt
79613531Sjairo.balart@metempsy.com        int first_intid = (addr - GICD_NSACR.start()) * 4;
79713531Sjairo.balart@metempsy.com
79813531Sjairo.balart@metempsy.com        if (isNotSPI(first_intid)) {
79913531Sjairo.balart@metempsy.com            return;
80013531Sjairo.balart@metempsy.com        }
80113531Sjairo.balart@metempsy.com
80213531Sjairo.balart@metempsy.com        if (DS || (!DS && !is_secure_access)) {
80313531Sjairo.balart@metempsy.com            return;
80413531Sjairo.balart@metempsy.com        }
80513531Sjairo.balart@metempsy.com
80613531Sjairo.balart@metempsy.com        for (int i = 0, int_id = first_intid;
80713756Sjairo.balart@metempsy.com             i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
80813531Sjairo.balart@metempsy.com            irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
80913531Sjairo.balart@metempsy.com        }
81013531Sjairo.balart@metempsy.com
81113531Sjairo.balart@metempsy.com        return;
81213531Sjairo.balart@metempsy.com    } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
81313531Sjairo.balart@metempsy.com        // 64 bit registers. 2 accesses.
81413531Sjairo.balart@metempsy.com        int int_id = (addr - GICD_IROUTER.start()) / 8;
81513531Sjairo.balart@metempsy.com
81613531Sjairo.balart@metempsy.com        if (isNotSPI(int_id)) {
81713531Sjairo.balart@metempsy.com            return;
81813531Sjairo.balart@metempsy.com        }
81913531Sjairo.balart@metempsy.com
82013531Sjairo.balart@metempsy.com        if (nsAccessToSecInt(int_id, is_secure_access))
82113531Sjairo.balart@metempsy.com        {
82213531Sjairo.balart@metempsy.com            if (irqNsacr[int_id] < 3) {
82313531Sjairo.balart@metempsy.com                // Group 0 or Secure Group 1 interrupts are RAZ/WI
82413531Sjairo.balart@metempsy.com                return;
82513531Sjairo.balart@metempsy.com            }
82613531Sjairo.balart@metempsy.com        }
82713531Sjairo.balart@metempsy.com
82813531Sjairo.balart@metempsy.com        if (size == 4) {
82913531Sjairo.balart@metempsy.com            if (addr & 7) { // high half of 64 bit register
83013531Sjairo.balart@metempsy.com                irqAffinityRouting[int_id] =
83113531Sjairo.balart@metempsy.com                    (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
83213531Sjairo.balart@metempsy.com            } else { // low half of 64 bit register
83313531Sjairo.balart@metempsy.com                irqAffinityRouting[int_id] =
83413531Sjairo.balart@metempsy.com                    (irqAffinityRouting[int_id] & 0xffffffff00000000) |
83513531Sjairo.balart@metempsy.com                    (data & 0xffffffff);
83613531Sjairo.balart@metempsy.com            }
83713531Sjairo.balart@metempsy.com        } else {
83813531Sjairo.balart@metempsy.com            irqAffinityRouting[int_id] = data;
83913531Sjairo.balart@metempsy.com        }
84013531Sjairo.balart@metempsy.com
84113531Sjairo.balart@metempsy.com        DPRINTF(GIC, "Gicv3Distributor::write(): "
84213531Sjairo.balart@metempsy.com                "int_id %d GICD_IROUTER %#llx\n",
84313531Sjairo.balart@metempsy.com                int_id, irqAffinityRouting[int_id]);
84413531Sjairo.balart@metempsy.com        return;
84513531Sjairo.balart@metempsy.com    }
84613531Sjairo.balart@metempsy.com
84713531Sjairo.balart@metempsy.com    switch (addr) {
84813531Sjairo.balart@metempsy.com      case GICD_CTLR: // Control Register
84913531Sjairo.balart@metempsy.com        if (DS) {
85013531Sjairo.balart@metempsy.com            /*
85113531Sjairo.balart@metempsy.com             * E1NWF [7]
85213531Sjairo.balart@metempsy.com             * 1 of N wakeup functionality not supported, RAZ/WI
85313531Sjairo.balart@metempsy.com             * DS [6] - RAO/WI
85413531Sjairo.balart@metempsy.com             * ARE [4]
85513531Sjairo.balart@metempsy.com             * affinity routing always on, no GICv2 legacy, RAO/WI
85613531Sjairo.balart@metempsy.com             * EnableGrp1 [1]
85713531Sjairo.balart@metempsy.com             * EnableGrp0 [0]
85813531Sjairo.balart@metempsy.com             */
85913531Sjairo.balart@metempsy.com            if ((data & (1 << 4)) == 0) {
86013531Sjairo.balart@metempsy.com                warn("Gicv3Distributor::write(): "
86113531Sjairo.balart@metempsy.com                        "setting ARE to 0 is not supported!\n");
86213531Sjairo.balart@metempsy.com            }
86313531Sjairo.balart@metempsy.com
86413531Sjairo.balart@metempsy.com            EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
86513531Sjairo.balart@metempsy.com            EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
86613531Sjairo.balart@metempsy.com            DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
86713531Sjairo.balart@metempsy.com                    "EnableGrp1NS %d EnableGrp0 %d\n",
86813531Sjairo.balart@metempsy.com                    EnableGrp1NS, EnableGrp0);
86913531Sjairo.balart@metempsy.com        } else {
87013531Sjairo.balart@metempsy.com            if (is_secure_access) {
87113531Sjairo.balart@metempsy.com                /*
87213531Sjairo.balart@metempsy.com                 * E1NWF [7]
87313531Sjairo.balart@metempsy.com                 * 1 of N wakeup functionality not supported, RAZ/WI
87413531Sjairo.balart@metempsy.com                 * DS [6]
87513531Sjairo.balart@metempsy.com                 * ARE_NS [5]
87613531Sjairo.balart@metempsy.com                 * affinity routing always on, no GICv2 legacy, RAO/WI
87713531Sjairo.balart@metempsy.com                 * ARE_S [4]
87813531Sjairo.balart@metempsy.com                 * affinity routing always on, no GICv2 legacy, RAO/WI
87913531Sjairo.balart@metempsy.com                 * EnableGrp1S [2]
88013531Sjairo.balart@metempsy.com                 * EnableGrp1NS [1]
88113531Sjairo.balart@metempsy.com                 * EnableGrp0 [0]
88213531Sjairo.balart@metempsy.com                 */
88313531Sjairo.balart@metempsy.com                if ((data & (1 << 5)) == 0) {
88413531Sjairo.balart@metempsy.com                    warn("Gicv3Distributor::write(): "
88513531Sjairo.balart@metempsy.com                            "setting ARE_NS to 0 is not supported!\n");
88613531Sjairo.balart@metempsy.com                }
88713531Sjairo.balart@metempsy.com
88813531Sjairo.balart@metempsy.com                if ((data & (1 << 4)) == 0) {
88913531Sjairo.balart@metempsy.com                    warn("Gicv3Distributor::write(): "
89013531Sjairo.balart@metempsy.com                            "setting ARE_S to 0 is not supported!\n");
89113531Sjairo.balart@metempsy.com                }
89213531Sjairo.balart@metempsy.com
89313531Sjairo.balart@metempsy.com                DS = data & GICD_CTLR_DS;
89413531Sjairo.balart@metempsy.com                EnableGrp1S = data & GICD_CTLR_ENABLEGRP1S;
89513531Sjairo.balart@metempsy.com                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1NS;
89613531Sjairo.balart@metempsy.com                EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
89713531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
89813531Sjairo.balart@metempsy.com                        "DS %d "
89913531Sjairo.balart@metempsy.com                        "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
90013531Sjairo.balart@metempsy.com                        DS, EnableGrp1S, EnableGrp1NS, EnableGrp0);
90113531Sjairo.balart@metempsy.com
90213531Sjairo.balart@metempsy.com                if (data & GICD_CTLR_DS) {
90313531Sjairo.balart@metempsy.com                    EnableGrp1S = 0;
90413531Sjairo.balart@metempsy.com                }
90513531Sjairo.balart@metempsy.com            } else {
90613531Sjairo.balart@metempsy.com                /*
90713531Sjairo.balart@metempsy.com                 * ARE_NS [4] RAO/WI;
90813531Sjairo.balart@metempsy.com                 * EnableGrp1A [1] is a read-write alias of the Secure
90913531Sjairo.balart@metempsy.com                 * GICD_CTLR.EnableGrp1NS
91013531Sjairo.balart@metempsy.com                 * EnableGrp1 [0] RES0
91113531Sjairo.balart@metempsy.com                 */
91213531Sjairo.balart@metempsy.com                if ((data & (1 << 4)) == 0) {
91313531Sjairo.balart@metempsy.com                    warn("Gicv3Distributor::write(): "
91413531Sjairo.balart@metempsy.com                            "setting ARE_NS to 0 is not supported!\n");
91513531Sjairo.balart@metempsy.com                }
91613531Sjairo.balart@metempsy.com
91713531Sjairo.balart@metempsy.com                EnableGrp1NS = data & GICD_CTLR_ENABLEGRP1A;
91813531Sjairo.balart@metempsy.com                DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
91913531Sjairo.balart@metempsy.com                        "EnableGrp1NS %d\n", EnableGrp1NS);
92013531Sjairo.balart@metempsy.com            }
92113531Sjairo.balart@metempsy.com        }
92213531Sjairo.balart@metempsy.com
92313531Sjairo.balart@metempsy.com        break;
92413531Sjairo.balart@metempsy.com
92513531Sjairo.balart@metempsy.com      default:
92613531Sjairo.balart@metempsy.com        panic("Gicv3Distributor::write(): invalid offset %#x\n", addr);
92713531Sjairo.balart@metempsy.com        break;
92813531Sjairo.balart@metempsy.com    }
92913531Sjairo.balart@metempsy.com}
93013531Sjairo.balart@metempsy.com
93113531Sjairo.balart@metempsy.comvoid
93213531Sjairo.balart@metempsy.comGicv3Distributor::sendInt(uint32_t int_id)
93313531Sjairo.balart@metempsy.com{
93413531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
93513531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
93613531Sjairo.balart@metempsy.com    irqPending[int_id] = true;
93713531Sjairo.balart@metempsy.com    DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
93813531Sjairo.balart@metempsy.com            "int_id %d (SPI) pending bit set\n", int_id);
93913531Sjairo.balart@metempsy.com    updateAndInformCPUInterfaces();
94013531Sjairo.balart@metempsy.com}
94113531Sjairo.balart@metempsy.com
94213531Sjairo.balart@metempsy.comvoid
94313756Sjairo.balart@metempsy.comGicv3Distributor::deassertSPI(uint32_t int_id)
94413531Sjairo.balart@metempsy.com{
94513531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
94613531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
94713531Sjairo.balart@metempsy.com    irqPending[int_id] = false;
94813531Sjairo.balart@metempsy.com    updateAndInformCPUInterfaces();
94913531Sjairo.balart@metempsy.com}
95013531Sjairo.balart@metempsy.com
95113531Sjairo.balart@metempsy.comvoid
95213531Sjairo.balart@metempsy.comGicv3Distributor::updateAndInformCPUInterfaces()
95313531Sjairo.balart@metempsy.com{
95413531Sjairo.balart@metempsy.com    update();
95513531Sjairo.balart@metempsy.com
95613531Sjairo.balart@metempsy.com    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
95713531Sjairo.balart@metempsy.com        gic->getCPUInterface(i)->update();
95813531Sjairo.balart@metempsy.com    }
95913531Sjairo.balart@metempsy.com}
96013531Sjairo.balart@metempsy.com
96113531Sjairo.balart@metempsy.comvoid
96213531Sjairo.balart@metempsy.comGicv3Distributor::fullUpdate()
96313531Sjairo.balart@metempsy.com{
96413531Sjairo.balart@metempsy.com    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
96513531Sjairo.balart@metempsy.com        Gicv3CPUInterface * cpu_interface_i = gic->getCPUInterface(i);
96613531Sjairo.balart@metempsy.com        cpu_interface_i->hppi.prio = 0xff;
96713531Sjairo.balart@metempsy.com    }
96813531Sjairo.balart@metempsy.com
96913531Sjairo.balart@metempsy.com    update();
97013531Sjairo.balart@metempsy.com
97113531Sjairo.balart@metempsy.com    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
97213531Sjairo.balart@metempsy.com        Gicv3Redistributor * redistributor_i = gic->getRedistributor(i);
97313531Sjairo.balart@metempsy.com        redistributor_i->update();
97413531Sjairo.balart@metempsy.com    }
97513531Sjairo.balart@metempsy.com}
97613531Sjairo.balart@metempsy.com
97713531Sjairo.balart@metempsy.comvoid
97813531Sjairo.balart@metempsy.comGicv3Distributor::update()
97913531Sjairo.balart@metempsy.com{
98013531Sjairo.balart@metempsy.com    std::vector<bool> new_hppi(gic->getSystem()->numContexts(), false);
98113531Sjairo.balart@metempsy.com
98213531Sjairo.balart@metempsy.com    // Find the highest priority pending SPI
98313531Sjairo.balart@metempsy.com    for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
98413756Sjairo.balart@metempsy.com         int_id++) {
98513531Sjairo.balart@metempsy.com        Gicv3::GroupId int_group = getIntGroup(int_id);
98613531Sjairo.balart@metempsy.com        bool group_enabled = groupEnabled(int_group);
98713531Sjairo.balart@metempsy.com
98813531Sjairo.balart@metempsy.com        if (irqPending[int_id] && irqEnabled[int_id] &&
98913756Sjairo.balart@metempsy.com            !irqActive[int_id] && group_enabled) {
99013531Sjairo.balart@metempsy.com            IROUTER affinity_routing = irqAffinityRouting[int_id];
99113531Sjairo.balart@metempsy.com            Gicv3Redistributor * target_redistributor = nullptr;
99213531Sjairo.balart@metempsy.com
99313531Sjairo.balart@metempsy.com            if (affinity_routing.IRM) {
99413531Sjairo.balart@metempsy.com                // Interrupts routed to any PE defined as a participating node
99513531Sjairo.balart@metempsy.com                for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
99613531Sjairo.balart@metempsy.com                    Gicv3Redistributor * redistributor_i =
99713531Sjairo.balart@metempsy.com                        gic->getRedistributor(i);
99813531Sjairo.balart@metempsy.com
99913531Sjairo.balart@metempsy.com                    if (redistributor_i->
100013531Sjairo.balart@metempsy.com                            canBeSelectedFor1toNInterrupt(int_group)) {
100113531Sjairo.balart@metempsy.com                        target_redistributor = redistributor_i;
100213531Sjairo.balart@metempsy.com                        break;
100313531Sjairo.balart@metempsy.com                    }
100413531Sjairo.balart@metempsy.com                }
100513531Sjairo.balart@metempsy.com            } else {
100613531Sjairo.balart@metempsy.com                uint32_t affinity = (affinity_routing.Aff3 << 24) |
100713531Sjairo.balart@metempsy.com                                    (affinity_routing.Aff3 << 16) |
100813531Sjairo.balart@metempsy.com                                    (affinity_routing.Aff1 << 8) |
100913531Sjairo.balart@metempsy.com                                    (affinity_routing.Aff0 << 0);
101013531Sjairo.balart@metempsy.com                target_redistributor =
101113531Sjairo.balart@metempsy.com                    gic->getRedistributorByAffinity(affinity);
101213531Sjairo.balart@metempsy.com            }
101313531Sjairo.balart@metempsy.com
101413531Sjairo.balart@metempsy.com            if (!target_redistributor) {
101513531Sjairo.balart@metempsy.com                // Interrrupts targeting not present cpus must remain pending
101613531Sjairo.balart@metempsy.com                return;
101713531Sjairo.balart@metempsy.com            }
101813531Sjairo.balart@metempsy.com
101913531Sjairo.balart@metempsy.com            Gicv3CPUInterface * target_cpu_interface =
102013531Sjairo.balart@metempsy.com                target_redistributor->getCPUInterface();
102113531Sjairo.balart@metempsy.com            uint32_t target_cpu = target_redistributor->cpuId;
102213531Sjairo.balart@metempsy.com
102313531Sjairo.balart@metempsy.com            if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
102413756Sjairo.balart@metempsy.com                /*
102513756Sjairo.balart@metempsy.com                 * Multiple pending ints with same priority.
102613756Sjairo.balart@metempsy.com                 * Implementation choice which one to signal.
102713756Sjairo.balart@metempsy.com                 * Our implementation selects the one with the lower id.
102813756Sjairo.balart@metempsy.com                 */
102913756Sjairo.balart@metempsy.com                (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
103013756Sjairo.balart@metempsy.com                int_id < target_cpu_interface->hppi.intid)) {
103113531Sjairo.balart@metempsy.com                target_cpu_interface->hppi.intid = int_id;
103213531Sjairo.balart@metempsy.com                target_cpu_interface->hppi.prio = irqPriority[int_id];
103313531Sjairo.balart@metempsy.com                target_cpu_interface->hppi.group = int_group;
103413531Sjairo.balart@metempsy.com                new_hppi[target_cpu] = true;
103513531Sjairo.balart@metempsy.com            }
103613531Sjairo.balart@metempsy.com        }
103713531Sjairo.balart@metempsy.com    }
103813531Sjairo.balart@metempsy.com
103913531Sjairo.balart@metempsy.com    for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
104013531Sjairo.balart@metempsy.com        Gicv3Redistributor * redistributor_i = gic->getRedistributor(i);
104113531Sjairo.balart@metempsy.com        Gicv3CPUInterface * cpu_interface_i =
104213531Sjairo.balart@metempsy.com            redistributor_i->getCPUInterface();
104313531Sjairo.balart@metempsy.com
104413531Sjairo.balart@metempsy.com        if (!new_hppi[i] && cpu_interface_i->hppi.prio != 0xff &&
104513756Sjairo.balart@metempsy.com            cpu_interface_i->hppi.intid >= (Gicv3::SGI_MAX + Gicv3::PPI_MAX) &&
104613756Sjairo.balart@metempsy.com            cpu_interface_i->hppi.intid < Gicv3::INTID_SECURE) {
104713531Sjairo.balart@metempsy.com            fullUpdate();
104813531Sjairo.balart@metempsy.com        }
104913531Sjairo.balart@metempsy.com    }
105013531Sjairo.balart@metempsy.com}
105113531Sjairo.balart@metempsy.com
105213531Sjairo.balart@metempsy.comGicv3::IntStatus
105313756Sjairo.balart@metempsy.comGicv3Distributor::intStatus(uint32_t int_id) const
105413531Sjairo.balart@metempsy.com{
105513531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
105613531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
105713531Sjairo.balart@metempsy.com
105813531Sjairo.balart@metempsy.com    if (irqPending[int_id]) {
105913531Sjairo.balart@metempsy.com        if (irqActive[int_id]) {
106013531Sjairo.balart@metempsy.com            return Gicv3::INT_ACTIVE_PENDING;
106113531Sjairo.balart@metempsy.com        }
106213531Sjairo.balart@metempsy.com
106313531Sjairo.balart@metempsy.com        return Gicv3::INT_PENDING;
106413531Sjairo.balart@metempsy.com    } else if (irqActive[int_id]) {
106513531Sjairo.balart@metempsy.com        return Gicv3::INT_ACTIVE;
106613531Sjairo.balart@metempsy.com    } else {
106713531Sjairo.balart@metempsy.com        return Gicv3::INT_INACTIVE;
106813531Sjairo.balart@metempsy.com    }
106913531Sjairo.balart@metempsy.com}
107013531Sjairo.balart@metempsy.com
107113531Sjairo.balart@metempsy.comGicv3::GroupId
107213756Sjairo.balart@metempsy.comGicv3Distributor::getIntGroup(int int_id) const
107313531Sjairo.balart@metempsy.com{
107413531Sjairo.balart@metempsy.com    panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
107513531Sjairo.balart@metempsy.com    panic_if(int_id > itLines, "Invalid SPI!");
107613531Sjairo.balart@metempsy.com
107713531Sjairo.balart@metempsy.com    if (DS) {
107813531Sjairo.balart@metempsy.com        if (irqGroup[int_id] == 1) {
107913531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
108013531Sjairo.balart@metempsy.com        } else {
108113531Sjairo.balart@metempsy.com            return Gicv3::G0S;
108213531Sjairo.balart@metempsy.com        }
108313531Sjairo.balart@metempsy.com    } else {
108413531Sjairo.balart@metempsy.com        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
108513531Sjairo.balart@metempsy.com            return Gicv3::G0S;
108613531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
108713531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
108813531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
108913531Sjairo.balart@metempsy.com            return Gicv3::G1S;
109013531Sjairo.balart@metempsy.com        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
109113531Sjairo.balart@metempsy.com            return Gicv3::G1NS;
109213531Sjairo.balart@metempsy.com        }
109313531Sjairo.balart@metempsy.com    }
109413531Sjairo.balart@metempsy.com
109513531Sjairo.balart@metempsy.com    M5_UNREACHABLE;
109613531Sjairo.balart@metempsy.com}
109713531Sjairo.balart@metempsy.com
109813531Sjairo.balart@metempsy.comvoid
109913531Sjairo.balart@metempsy.comGicv3Distributor::activateIRQ(uint32_t int_id)
110013531Sjairo.balart@metempsy.com{
110113531Sjairo.balart@metempsy.com    irqPending[int_id] = false;
110213531Sjairo.balart@metempsy.com    irqActive[int_id] = true;
110313531Sjairo.balart@metempsy.com}
110413531Sjairo.balart@metempsy.com
110513531Sjairo.balart@metempsy.comvoid
110613531Sjairo.balart@metempsy.comGicv3Distributor::deactivateIRQ(uint32_t int_id)
110713531Sjairo.balart@metempsy.com{
110813531Sjairo.balart@metempsy.com    irqActive[int_id] = false;
110913531Sjairo.balart@metempsy.com}
111013531Sjairo.balart@metempsy.com
111113531Sjairo.balart@metempsy.comvoid
111213531Sjairo.balart@metempsy.comGicv3Distributor::serialize(CheckpointOut & cp) const
111313531Sjairo.balart@metempsy.com{
111413531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(ARE);
111513531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(DS);
111613531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableGrp1S);
111713531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableGrp1NS);
111813531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(EnableGrp0);
111913531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqGroup);
112013531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqEnabled);
112113531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqPending);
112213531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqActive);
112313531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqPriority);
112413531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqConfig);
112513531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqGrpmod);
112613531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqNsacr);
112713531Sjairo.balart@metempsy.com    SERIALIZE_CONTAINER(irqAffinityRouting);
112813531Sjairo.balart@metempsy.com}
112913531Sjairo.balart@metempsy.com
113013531Sjairo.balart@metempsy.comvoid
113113531Sjairo.balart@metempsy.comGicv3Distributor::unserialize(CheckpointIn & cp)
113213531Sjairo.balart@metempsy.com{
113313531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(ARE);
113413531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(DS);
113513531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableGrp1S);
113613531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableGrp1NS);
113713531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(EnableGrp0);
113813531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqGroup);
113913531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqEnabled);
114013531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqPending);
114113531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqActive);
114213531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqPriority);
114313531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqConfig);
114413531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqGrpmod);
114513531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqNsacr);
114613531Sjairo.balart@metempsy.com    UNSERIALIZE_CONTAINER(irqAffinityRouting);
114713531Sjairo.balart@metempsy.com}
1148