summaryrefslogtreecommitdiff
path: root/src/dev/arm/gic_v3_redistributor.hh
blob: 11553974a0c1b8e2f4ddc971c59703435f9ce8d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
/*
 * Copyright (c) 2018 Metempsy Technology Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Jairo Balart
 */

#ifndef __DEV_ARM_GICV3_REDISTRIBUTOR_H__
#define __DEV_ARM_GICV3_REDISTRIBUTOR_H__

#include "base/addr_range.hh"
#include "dev/arm/gic_v3.hh"
#include "sim/serialize.hh"

class Gicv3Distributor;
class Gicv3CPUInterface;

class Gicv3Redistributor : public Serializable
{
  private:

    friend class Gicv3CPUInterface;
    friend class Gicv3Distributor;

  protected:

    Gicv3 * gic;
    Gicv3Distributor * distributor;
    Gicv3CPUInterface * cpuInterface;
    uint32_t cpuId;

    /*
     * GICv3 defines 2 contiguous 64KB frames for each redistributor.
     * Order of frames must be RD_base, SGI_base.
     */
    static const uint32_t RD_base = 0x0;
    static const uint32_t SGI_base = 0x10000;

    enum {
        // Control Register
        GICR_CTLR  = RD_base + 0x0000,
        // Implementer Identification Register
        GICR_IIDR = RD_base + 0x0004,
        // Type Register
        GICR_TYPER = RD_base + 0x0008,
        // Wake Register
        GICR_WAKER = RD_base + 0x0014,
        // Peripheral ID0 Register
        GICR_PIDR0 = RD_base + 0xffe0,
        // Peripheral ID1 Register
        GICR_PIDR1 = RD_base + 0xffe4,
        // Peripheral ID2 Register
        GICR_PIDR2 = RD_base + 0xffe8,
        // Peripheral ID3 Register
        GICR_PIDR3 = RD_base + 0xffec,
        // Peripheral ID4 Register
        GICR_PIDR4 = RD_base + 0xffd0,
        // Peripheral ID5 Register
        GICR_PIDR5 = RD_base + 0xffd4,
        // Peripheral ID6 Register
        GICR_PIDR6 = RD_base + 0xffd8,
        // Peripheral ID7 Register
        GICR_PIDR7 = RD_base + 0xffdc,
    };

    static const uint32_t GICR_WAKER_ProcessorSleep = 1 << 1;
    static const uint32_t GICR_WAKER_ChildrenAsleep = 1 << 2;

    bool peInLowPowerState;

    enum {
        // Interrupt Group Register 0
        GICR_IGROUPR0   = SGI_base + 0x0080,
        // Interrupt Set-Enable Register 0
        GICR_ISENABLER0 = SGI_base + 0x0100,
        // Interrupt Clear-Enable Register 0
        GICR_ICENABLER0 = SGI_base + 0x0180,
        // Interrupt Set-Pending Register 0
        GICR_ISPENDR0 = SGI_base + 0x0200,
        // Interrupt Clear-Pending Register 0
        GICR_ICPENDR0 = SGI_base + 0x0280,
        // Interrupt Set-Active Register 0
        GICR_ISACTIVER0 = SGI_base + 0x0300,
        // Interrupt Clear-Active Register 0
        GICR_ICACTIVER0 = SGI_base + 0x0380,
        // SGI Configuration Register
        GICR_ICFGR0 = SGI_base + 0x0c00,
        // PPI Configuration Register
        GICR_ICFGR1 = SGI_base + 0x0c04,
        // Interrupt Group Modifier Register 0
        GICR_IGRPMODR0 = SGI_base + 0x0d00,
        // Non-secure Access Control Register
        GICR_NSACR = SGI_base + 0x0e00,
    };

    // Interrupt Priority Registers
    static const AddrRange GICR_IPRIORITYR;

    std::vector <uint8_t> irqGroup;
    std::vector <bool> irqEnabled;
    std::vector <bool> irqPending;
    std::vector <bool> irqActive;
    std::vector <uint8_t> irqPriority;
    std::vector <Gicv3::IntTriggerType> irqConfig;
    std::vector <uint8_t> irqGrpmod;
    std::vector <uint8_t> irqNsacr;

    bool DPG1S;
    bool DPG1NS;
    bool DPG0;

    static const uint32_t GICR_CTLR_DPG0 = 1 << 24;
    static const uint32_t GICR_CTLR_DPG1NS = 1 << 25;
    static const uint32_t GICR_CTLR_DPG1S = 1 << 26;

  public:

    /*
     * GICv3 defines only 2 64K consecutive frames for the redistributor
     * (RD_base and SGI_base) but we are using 2 extra 64K stride frames
     * to match GICv4 that defines 4 64K consecutive frames for them.
     * Note this must match with DTB/DTS GIC node definition and boot
     * loader code.
     */
    static const uint32_t ADDR_RANGE_SIZE = 0x40000;

    Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id);
    ~Gicv3Redistributor();
    void init();
    void initState();

    uint64_t read(Addr addr, size_t size, bool is_secure_access);
    void write(Addr addr, uint64_t data, size_t size,
               bool is_secure_access);
    void sendPPInt(uint32_t int_id);
    void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns);
    void serialize(CheckpointOut & cp) const override;
    void unserialize(CheckpointIn & cp) override;
    uint32_t getAffinity();

    Gicv3CPUInterface *
    getCPUInterface() const
    {
        return cpuInterface;
    }

    bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group);

  protected:

    void reset();
    void update();
    void updateAndInformCPUInterface();
    Gicv3::IntStatus intStatus(uint32_t int_id);
    Gicv3::GroupId getIntGroup(int int_id);
    void activateIRQ(uint32_t int_id);
    void deactivateIRQ(uint32_t int_id);
};

#endif //__DEV_ARM_GICV3_REDISTRIBUTOR_H__