vgic.hh (10037:5cac77888310) vgic.hh (10905:a6ca6831e775)
1/*
2 * Copyright (c) 2013 ARM Limited
3 * All rights reserved
4 *
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.
13 *
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.
24 *
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.
36 *
37 * Authors: Matt Evans
38 */
39
40
41/** @file
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)
45 * is required.
46 *
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
49 * the GIC.)
50 */
51
52#ifndef __DEV_ARM_VGIC_H__
53#define __DEV_ARM_VGIC_H__
54
1/*
2 * Copyright (c) 2013 ARM Limited
3 * All rights reserved
4 *
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.
13 *
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.
24 *
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.
36 *
37 * Authors: Matt Evans
38 */
39
40
41/** @file
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)
45 * is required.
46 *
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
49 * the GIC.)
50 */
51
52#ifndef __DEV_ARM_VGIC_H__
53#define __DEV_ARM_VGIC_H__
54
55#include <algorithm>
56#include <array>
57
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"
61
62class VGic : public PioDevice
63{
64 private:
65 static const int VGIC_CPU_MAX = 256;
66 static const int NUM_LR = 4;
67
68 static const int GICH_SIZE = 0x200;
69 static const int GICH_REG_SIZE = 0x2000;
70
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;
84
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;
100
101 static const uint32_t LR_PENDING = 1;
102 static const uint32_t LR_ACTIVE = 2;
103
104 /** Event definition to post interrupt to CPU after a delay
105 */
106 class PostVIntEvent : public Event
107 {
108 private:
109 uint32_t cpu;
110 Platform *platform;
111 public:
112 PostVIntEvent( uint32_t c, Platform* p)
113 : cpu(c), platform(p)
114 { }
115 void process() { platform->intrctrl->post(cpu, ArmISA::INT_VIRT_IRQ, 0);}
116 const char *description() const { return "Post VInterrupt to CPU"; }
117 };
118
119 PostVIntEvent *postVIntEvent[VGIC_CPU_MAX];
120 bool maintIntPosted[VGIC_CPU_MAX];
121 bool vIntPosted[VGIC_CPU_MAX];
122
123 Platform *platform;
124 BaseGic *gic;
125
126 Addr vcpuAddr;
127 Addr hvAddr;
128 Tick pioDelay;
129 int maintInt;
130
131 BitUnion32(ListReg)
132 Bitfield<31> HW;
133 Bitfield<30> Grp1;
134 Bitfield<29,28> State;
135 Bitfield<27,23> Priority;
136 Bitfield<19> EOI;
137 Bitfield<12,10> CpuID;
138 Bitfield<9,0> VirtualID;
139 EndBitUnion(ListReg)
140
141 BitUnion32(HCR)
142 Bitfield<31,27> EOICount;
143 Bitfield<7> VGrp1DIE;
144 Bitfield<6> VGrp1EIE;
145 Bitfield<5> VGrp0DIE;
146 Bitfield<4> VGrp0EIE;
147 Bitfield<3> NPIE;
148 Bitfield<2> LRENPIE;
149 Bitfield<1> UIE;
150 Bitfield<0> En;
151 EndBitUnion(HCR)
152
153 BitUnion32(VCTLR)
154 Bitfield<9> EOImode;
155 Bitfield<4> CPBR;
156 Bitfield<3> FIQEn;
157 Bitfield<2> AckCtl;
158 Bitfield<1> EnGrp1;
159 Bitfield<0> En; // This gets written to enable, not group 1.
160 EndBitUnion(VCTLR)
161
162 /* State per CPU. EVERYTHING should be in this struct and simply replicated
163 * N times.
164 */
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"
64
65class VGic : public PioDevice
66{
67 private:
68 static const int VGIC_CPU_MAX = 256;
69 static const int NUM_LR = 4;
70
71 static const int GICH_SIZE = 0x200;
72 static const int GICH_REG_SIZE = 0x2000;
73
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;
87
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;
103
104 static const uint32_t LR_PENDING = 1;
105 static const uint32_t LR_ACTIVE = 2;
106
107 /** Event definition to post interrupt to CPU after a delay
108 */
109 class PostVIntEvent : public Event
110 {
111 private:
112 uint32_t cpu;
113 Platform *platform;
114 public:
115 PostVIntEvent( uint32_t c, Platform* p)
116 : cpu(c), platform(p)
117 { }
118 void process() { platform->intrctrl->post(cpu, ArmISA::INT_VIRT_IRQ, 0);}
119 const char *description() const { return "Post VInterrupt to CPU"; }
120 };
121
122 PostVIntEvent *postVIntEvent[VGIC_CPU_MAX];
123 bool maintIntPosted[VGIC_CPU_MAX];
124 bool vIntPosted[VGIC_CPU_MAX];
125
126 Platform *platform;
127 BaseGic *gic;
128
129 Addr vcpuAddr;
130 Addr hvAddr;
131 Tick pioDelay;
132 int maintInt;
133
134 BitUnion32(ListReg)
135 Bitfield<31> HW;
136 Bitfield<30> Grp1;
137 Bitfield<29,28> State;
138 Bitfield<27,23> Priority;
139 Bitfield<19> EOI;
140 Bitfield<12,10> CpuID;
141 Bitfield<9,0> VirtualID;
142 EndBitUnion(ListReg)
143
144 BitUnion32(HCR)
145 Bitfield<31,27> EOICount;
146 Bitfield<7> VGrp1DIE;
147 Bitfield<6> VGrp1EIE;
148 Bitfield<5> VGrp0DIE;
149 Bitfield<4> VGrp0EIE;
150 Bitfield<3> NPIE;
151 Bitfield<2> LRENPIE;
152 Bitfield<1> UIE;
153 Bitfield<0> En;
154 EndBitUnion(HCR)
155
156 BitUnion32(VCTLR)
157 Bitfield<9> EOImode;
158 Bitfield<4> CPBR;
159 Bitfield<3> FIQEn;
160 Bitfield<2> AckCtl;
161 Bitfield<1> EnGrp1;
162 Bitfield<0> En; // This gets written to enable, not group 1.
163 EndBitUnion(VCTLR)
164
165 /* State per CPU. EVERYTHING should be in this struct and simply replicated
166 * N times.
167 */
165 struct vcpuIntData {
166 ListReg LR[NUM_LR];
168 struct vcpuIntData : public Serializable {
169 vcpuIntData()
170 : vctrl(0), hcr(0), eisr(0), VMGrp0En(0), VMGrp1En(0),
171 VMAckCtl(0), VMFiqEn(0), VMCBPR(0), VEM(0), VMABP(0), VMBP(0),
172 VMPriMask(0)
173 {
174 std::fill(LR.begin(), LR.end(), 0);
175 }
176 virtual ~vcpuIntData() {}
177
178 std::array<ListReg, NUM_LR> LR;
167 VCTLR vctrl;
168
169 HCR hcr;
170 uint64_t eisr;
171
172 /* Host info, guest info (should be 100% accessible via GICH_* regs!) */
173 uint8_t VMGrp0En;
174 uint8_t VMGrp1En;
175 uint8_t VMAckCtl;
176 uint8_t VMFiqEn;
177 uint8_t VMCBPR;
178 uint8_t VEM;
179 uint8_t VMABP;
180 uint8_t VMBP;
181 uint8_t VMPriMask;
179 VCTLR vctrl;
180
181 HCR hcr;
182 uint64_t eisr;
183
184 /* Host info, guest info (should be 100% accessible via GICH_* regs!) */
185 uint8_t VMGrp0En;
186 uint8_t VMGrp1En;
187 uint8_t VMAckCtl;
188 uint8_t VMFiqEn;
189 uint8_t VMCBPR;
190 uint8_t VEM;
191 uint8_t VMABP;
192 uint8_t VMBP;
193 uint8_t VMPriMask;
194
195 void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
196 void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
182 };
183
197 };
198
184 struct vcpuIntData vcpuData[VGIC_CPU_MAX];
199 struct std::array<vcpuIntData, VGIC_CPU_MAX> vcpuData;
185
186 public:
187 typedef VGicParams Params;
188 const Params *
189 params() const
190 {
191 return dynamic_cast<const Params *>(_params);
192 }
193 VGic(const Params *p);
194
195 virtual AddrRangeList getAddrRanges() const;
196
197 virtual Tick read(PacketPtr pkt);
198 virtual Tick write(PacketPtr pkt);
199
200
201 public:
202 typedef VGicParams Params;
203 const Params *
204 params() const
205 {
206 return dynamic_cast<const Params *>(_params);
207 }
208 VGic(const Params *p);
209
210 virtual AddrRangeList getAddrRanges() const;
211
212 virtual Tick read(PacketPtr pkt);
213 virtual Tick write(PacketPtr pkt);
214
200 virtual void serialize(std::ostream &os);
201 virtual void unserialize(Checkpoint *cp, const std::string &section);
215 void serialize(CheckpointOut &cp) const M5_ATTR_OVERRIDE;
216 void unserialize(CheckpointIn &cp) M5_ATTR_OVERRIDE;
202
203 private:
204 Tick readVCpu(PacketPtr pkt);
205 Tick readCtrl(PacketPtr pkt);
206
207 Tick writeVCpu(PacketPtr pkt);
208 Tick writeCtrl(PacketPtr pkt);
209
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);
216
217 unsigned int lrPending(struct vcpuIntData *vid)
218 {
219 unsigned int pend = 0;
220 for (int i = 0; i < NUM_LR; i++) {
221 if (vid->LR[i].State & LR_PENDING)
222 pend++;
223 }
224 return pend;
225 }
226 unsigned int lrValid(struct vcpuIntData *vid)
227 {
228 unsigned int valid = 0;
229 for (int i = 0; i < NUM_LR; i++) {
230 if (vid->LR[i].State)
231 valid++;
232 }
233 return valid;
234 }
235
236 /** Returns LR index or -1 if none pending */
237 int findHighestPendingLR(struct vcpuIntData *vid)
238 {
239 unsigned int prio = 0xff;
240 int p = -1;
241 for (int i = 0; i < NUM_LR; i++) {
242 if ((vid->LR[i].State & LR_PENDING) && (vid->LR[i].Priority < prio)) {
243 p = i;
244 prio = vid->LR[i].Priority;
245 }
246 }
247 return p;
248 }
249
250 int findLRForVIRQ(struct vcpuIntData *vid, int virq, int vcpu)
251 {
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)
256 return i;
257 }
258 return -1;
259 }
260};
261
262#endif
217
218 private:
219 Tick readVCpu(PacketPtr pkt);
220 Tick readCtrl(PacketPtr pkt);
221
222 Tick writeVCpu(PacketPtr pkt);
223 Tick writeCtrl(PacketPtr pkt);
224
225 void updateIntState(int 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);
231
232 unsigned int lrPending(struct vcpuIntData *vid)
233 {
234 unsigned int pend = 0;
235 for (int i = 0; i < NUM_LR; i++) {
236 if (vid->LR[i].State & LR_PENDING)
237 pend++;
238 }
239 return pend;
240 }
241 unsigned int lrValid(struct vcpuIntData *vid)
242 {
243 unsigned int valid = 0;
244 for (int i = 0; i < NUM_LR; i++) {
245 if (vid->LR[i].State)
246 valid++;
247 }
248 return valid;
249 }
250
251 /** Returns LR index or -1 if none pending */
252 int findHighestPendingLR(struct vcpuIntData *vid)
253 {
254 unsigned int prio = 0xff;
255 int p = -1;
256 for (int i = 0; i < NUM_LR; i++) {
257 if ((vid->LR[i].State & LR_PENDING) && (vid->LR[i].Priority < prio)) {
258 p = i;
259 prio = vid->LR[i].Priority;
260 }
261 }
262 return p;
263 }
264
265 int findLRForVIRQ(struct vcpuIntData *vid, int virq, int vcpu)
266 {
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)
271 return i;
272 }
273 return -1;
274 }
275};
276
277#endif