2 * Copyright (c) 2013 ARM Limited
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 * Implementiation of a GIC-400 List Register-based VGIC interface.
43 * The VGIC is, in this implementation, completely separate from the GIC itself.
44 * Only a VIRQ line to the CPU and a PPI line to the GIC (for a HV maintenance IRQ)
47 * The mode in which the List Registers may flag (via LR.HW) that a hardware EOI
48 * is to be performed is NOT supported. (This requires tighter integration with
52 #ifndef __DEV_ARM_VGIC_H__
53 #define __DEV_ARM_VGIC_H__
58 #include "base/addr_range.hh"
59 #include "base/bitunion.hh"
60 #include "cpu/intr_control.hh"
61 #include "dev/io_device.hh"
62 #include "dev/platform.hh"
63 #include "params/VGic.hh"
65 class VGic : public PioDevice
68 static const int VGIC_CPU_MAX = 256;
69 static const int NUM_LR = 4;
71 static const int GICH_SIZE = 0x200;
72 static const int GICH_REG_SIZE = 0x2000;
74 static const int GICH_HCR = 0x000;
75 static const int GICH_VTR = 0x004;
76 static const int GICH_VMCR = 0x008;
77 static const int GICH_MISR = 0x010;
78 static const int GICH_EISR0 = 0x020;
79 static const int GICH_EISR1 = 0x024;
80 static const int GICH_ELSR0 = 0x030;
81 static const int GICH_ELSR1 = 0x034;
82 static const int GICH_APR0 = 0x0f0;
83 static const int GICH_LR0 = 0x100;
84 static const int GICH_LR1 = 0x104;
85 static const int GICH_LR2 = 0x108;
86 static const int GICH_LR3 = 0x10c;
88 static const int GICV_SIZE = 0x2000;
89 static const int GICV_CTLR = 0x000;
90 static const int GICV_PMR = 0x004;
91 static const int GICV_BPR = 0x008;
92 static const int GICV_IAR = 0x00c;
93 static const int GICV_EOIR = 0x010;
94 static const int GICV_RPR = 0x014;
95 static const int GICV_HPPIR = 0x018;
96 static const int GICV_ABPR = 0x01c;
97 static const int GICV_AIAR = 0x020;
98 static const int GICV_AEOIR = 0x024;
99 static const int GICV_AHPPIR = 0x028;
100 static const int GICV_APR0 = 0x0d0;
101 static const int GICV_IIDR = 0x0fc;
102 static const int GICV_DIR = 0x1000;
104 static const uint32_t LR_PENDING = 1;
105 static const uint32_t LR_ACTIVE = 2;
107 /** Event definition to post interrupt to CPU after a delay
109 class PostVIntEvent : public Event
115 PostVIntEvent( uint32_t c, Platform* p)
116 : cpu(c), platform(p)
118 void process() { platform->intrctrl->post(cpu, ArmISA::INT_VIRT_IRQ, 0);}
119 const char *description() const { return "Post VInterrupt to CPU"; }
122 PostVIntEvent *postVIntEvent[VGIC_CPU_MAX];
123 bool maintIntPosted[VGIC_CPU_MAX];
124 bool vIntPosted[VGIC_CPU_MAX];
137 Bitfield<29,28> State;
138 Bitfield<27,23> Priority;
140 Bitfield<12,10> CpuID;
141 Bitfield<9,0> VirtualID;
145 Bitfield<31,27> EOICount;
146 Bitfield<7> VGrp1DIE;
147 Bitfield<6> VGrp1EIE;
148 Bitfield<5> VGrp0DIE;
149 Bitfield<4> VGrp0EIE;
162 Bitfield<0> En; // This gets written to enable, not group 1.
165 /* State per CPU. EVERYTHING should be in this struct and simply replicated
168 struct vcpuIntData : public Serializable {
170 : vctrl(0), hcr(0), eisr(0), VMGrp0En(0), VMGrp1En(0),
171 VMAckCtl(0), VMFiqEn(0), VMCBPR(0), VEM(0), VMABP(0), VMBP(0),
174 std::fill(LR.begin(), LR.end(), 0);
176 virtual ~vcpuIntData() {}
178 std::array<ListReg, NUM_LR> LR;
184 /* Host info, guest info (should be 100% accessible via GICH_* regs!) */
195 void serialize(CheckpointOut &cp) const override;
196 void unserialize(CheckpointIn &cp) override;
199 struct std::array<vcpuIntData, VGIC_CPU_MAX> vcpuData;
202 typedef VGicParams Params;
206 return dynamic_cast<const Params *>(_params);
208 VGic(const Params *p);
210 AddrRangeList getAddrRanges() const override;
212 Tick read(PacketPtr pkt) override;
213 Tick write(PacketPtr pkt) override;
215 void serialize(CheckpointOut &cp) const override;
216 void unserialize(CheckpointIn &cp) override;
219 Tick readVCpu(PacketPtr pkt);
220 Tick readCtrl(PacketPtr pkt);
222 Tick writeVCpu(PacketPtr pkt);
223 Tick writeCtrl(PacketPtr pkt);
225 void updateIntState(ContextID ctx_id);
226 uint32_t getMISR(struct vcpuIntData *vid);
227 void postVInt(uint32_t cpu, Tick when);
228 void unPostVInt(uint32_t cpu);
229 void postMaintInt(uint32_t cpu);
230 void unPostMaintInt(uint32_t cpu);
232 unsigned int lrPending(struct vcpuIntData *vid)
234 unsigned int pend = 0;
235 for (int i = 0; i < NUM_LR; i++) {
236 if (vid->LR[i].State & LR_PENDING)
241 unsigned int lrValid(struct vcpuIntData *vid)
243 unsigned int valid = 0;
244 for (int i = 0; i < NUM_LR; i++) {
245 if (vid->LR[i].State)
251 /** Returns LR index or -1 if none pending */
252 int findHighestPendingLR(struct vcpuIntData *vid)
254 unsigned int prio = 0xff;
256 for (int i = 0; i < NUM_LR; i++) {
257 if ((vid->LR[i].State & LR_PENDING) && (vid->LR[i].Priority < prio)) {
259 prio = vid->LR[i].Priority;
265 int findLRForVIRQ(struct vcpuIntData *vid, int virq, int vcpu)
267 for (int i = 0; i < NUM_LR; i++) {
268 if (vid->LR[i].State &&
269 vid->LR[i].VirtualID == virq &&
270 vid->LR[i].CpuID == vcpu)