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__
55 #include "base/addr_range.hh"
56 #include "base/bitunion.hh"
57 #include "cpu/intr_control.hh"
58 #include "dev/io_device.hh"
59 #include "dev/platform.hh"
60 #include "params/VGic.hh"
62 class VGic : public PioDevice
65 static const int VGIC_CPU_MAX = 256;
66 static const int NUM_LR = 4;
68 static const int GICH_SIZE = 0x200;
69 static const int GICH_REG_SIZE = 0x2000;
71 static const int GICH_HCR = 0x000;
72 static const int GICH_VTR = 0x004;
73 static const int GICH_VMCR = 0x008;
74 static const int GICH_MISR = 0x010;
75 static const int GICH_EISR0 = 0x020;
76 static const int GICH_EISR1 = 0x024;
77 static const int GICH_ELSR0 = 0x030;
78 static const int GICH_ELSR1 = 0x034;
79 static const int GICH_APR0 = 0x0f0;
80 static const int GICH_LR0 = 0x100;
81 static const int GICH_LR1 = 0x104;
82 static const int GICH_LR2 = 0x108;
83 static const int GICH_LR3 = 0x10c;
85 static const int GICV_SIZE = 0x2000;
86 static const int GICV_CTLR = 0x000;
87 static const int GICV_PMR = 0x004;
88 static const int GICV_BPR = 0x008;
89 static const int GICV_IAR = 0x00c;
90 static const int GICV_EOIR = 0x010;
91 static const int GICV_RPR = 0x014;
92 static const int GICV_HPPIR = 0x018;
93 static const int GICV_ABPR = 0x01c;
94 static const int GICV_AIAR = 0x020;
95 static const int GICV_AEOIR = 0x024;
96 static const int GICV_AHPPIR = 0x028;
97 static const int GICV_APR0 = 0x0d0;
98 static const int GICV_IIDR = 0x0fc;
99 static const int GICV_DIR = 0x1000;
101 static const uint32_t LR_PENDING = 1;
102 static const uint32_t LR_ACTIVE = 2;
104 /** Event definition to post interrupt to CPU after a delay
106 class PostVIntEvent : public Event
112 PostVIntEvent( uint32_t c, Platform* p)
113 : cpu(c), platform(p)
115 void process() { platform->intrctrl->post(cpu, ArmISA::INT_VIRT_IRQ, 0);}
116 const char *description() const { return "Post VInterrupt to CPU"; }
119 PostVIntEvent *postVIntEvent[VGIC_CPU_MAX];
120 bool maintIntPosted[VGIC_CPU_MAX];
121 bool vIntPosted[VGIC_CPU_MAX];
134 Bitfield<29,28> State;
135 Bitfield<27,23> Priority;
137 Bitfield<12,10> CpuID;
138 Bitfield<9,0> VirtualID;
142 Bitfield<31,27> EOICount;
143 Bitfield<7> VGrp1DIE;
144 Bitfield<6> VGrp1EIE;
145 Bitfield<5> VGrp0DIE;
146 Bitfield<4> VGrp0EIE;
159 Bitfield<0> En; // This gets written to enable, not group 1.
162 /* State per CPU. EVERYTHING should be in this struct and simply replicated
172 /* Host info, guest info (should be 100% accessible via GICH_* regs!) */
184 struct vcpuIntData vcpuData[VGIC_CPU_MAX];
187 typedef VGicParams Params;
191 return dynamic_cast<const Params *>(_params);
193 VGic(const Params *p);
195 virtual AddrRangeList getAddrRanges() const;
197 virtual Tick read(PacketPtr pkt);
198 virtual Tick write(PacketPtr pkt);
200 virtual void serialize(std::ostream &os);
201 virtual void unserialize(Checkpoint *cp, const std::string §ion);
204 Tick readVCpu(PacketPtr pkt);
205 Tick readCtrl(PacketPtr pkt);
207 Tick writeVCpu(PacketPtr pkt);
208 Tick writeCtrl(PacketPtr pkt);
210 void updateIntState(int ctx_id);
211 uint32_t getMISR(struct vcpuIntData *vid);
212 void postVInt(uint32_t cpu, Tick when);
213 void unPostVInt(uint32_t cpu);
214 void postMaintInt(uint32_t cpu);
215 void unPostMaintInt(uint32_t cpu);
217 unsigned int lrPending(struct vcpuIntData *vid)
219 unsigned int pend = 0;
220 for (int i = 0; i < NUM_LR; i++) {
221 if (vid->LR[i].State & LR_PENDING)
226 unsigned int lrValid(struct vcpuIntData *vid)
228 unsigned int valid = 0;
229 for (int i = 0; i < NUM_LR; i++) {
230 if (vid->LR[i].State)
236 /** Returns LR index or -1 if none pending */
237 int findHighestPendingLR(struct vcpuIntData *vid)
239 unsigned int prio = 0xff;
241 for (int i = 0; i < NUM_LR; i++) {
242 if ((vid->LR[i].State & LR_PENDING) && (vid->LR[i].Priority < prio)) {
244 prio = vid->LR[i].Priority;
250 int findLRForVIRQ(struct vcpuIntData *vid, int virq, int vcpu)
252 for (int i = 0; i < NUM_LR; i++) {
253 if (vid->LR[i].State &&
254 vid->LR[i].VirtualID == virq &&
255 vid->LR[i].CpuID == vcpu)