vgic.cc (12239:ae1686aaebc5) vgic.cc (13230:2988dc5d1d6f)
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

--- 92 unchanged lines hidden (view full) ---

101 ContextID ctx_id = pkt->req->contextId();
102 assert(ctx_id < VGIC_CPU_MAX);
103 struct vcpuIntData *vid = &vcpuData[ctx_id];
104
105 DPRINTF(VGIC, "VGIC VCPU read register %#x\n", daddr);
106
107 switch (daddr) {
108 case GICV_CTLR:
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

--- 92 unchanged lines hidden (view full) ---

101 ContextID ctx_id = pkt->req->contextId();
102 assert(ctx_id < VGIC_CPU_MAX);
103 struct vcpuIntData *vid = &vcpuData[ctx_id];
104
105 DPRINTF(VGIC, "VGIC VCPU read register %#x\n", daddr);
106
107 switch (daddr) {
108 case GICV_CTLR:
109 pkt->set(vid->vctrl);
109 pkt->setLE<uint32_t>(vid->vctrl);
110 break;
111 case GICV_IAR: {
112 int i = findHighestPendingLR(vid);
113 if (i < 0 || !vid->vctrl.En) {
110 break;
111 case GICV_IAR: {
112 int i = findHighestPendingLR(vid);
113 if (i < 0 || !vid->vctrl.En) {
114 pkt->set(1023); // "No int" marker
114 pkt->setLE<uint32_t>(1023); // "No int" marker
115 } else {
116 ListReg *lr = &vid->LR[i];
117
115 } else {
116 ListReg *lr = &vid->LR[i];
117
118 pkt->set(lr->VirtualID |
118 pkt->setLE<uint32_t>(lr->VirtualID |
119 (((int)lr->CpuID) << 10));
120 // We don't support auto-EOI of HW interrupts via real GIC!
121 // Fortunately, KVM doesn't use this. How about Xen...? Ulp!
122 if (lr->HW)
123 panic("VGIC does not support 'HW' List Register feature (LR %#x)!\n",
124 *lr);
125 lr->State = LR_ACTIVE;
126 DPRINTF(VGIC, "Consumed interrupt %d (cpu%d) from LR%d (EOI%d)\n",

--- 28 unchanged lines hidden (view full) ---

155 panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr);
156 daddr &= ~0x1ff;
157 }
158 assert(ctx_id < VGIC_CPU_MAX);
159 struct vcpuIntData *vid = &vcpuData[ctx_id];
160
161 switch (daddr) {
162 case GICH_HCR:
119 (((int)lr->CpuID) << 10));
120 // We don't support auto-EOI of HW interrupts via real GIC!
121 // Fortunately, KVM doesn't use this. How about Xen...? Ulp!
122 if (lr->HW)
123 panic("VGIC does not support 'HW' List Register feature (LR %#x)!\n",
124 *lr);
125 lr->State = LR_ACTIVE;
126 DPRINTF(VGIC, "Consumed interrupt %d (cpu%d) from LR%d (EOI%d)\n",

--- 28 unchanged lines hidden (view full) ---

155 panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr);
156 daddr &= ~0x1ff;
157 }
158 assert(ctx_id < VGIC_CPU_MAX);
159 struct vcpuIntData *vid = &vcpuData[ctx_id];
160
161 switch (daddr) {
162 case GICH_HCR:
163 pkt->set(vid->hcr);
163 pkt->setLE<uint32_t>(vid->hcr);
164 break;
165
166 case GICH_VTR:
164 break;
165
166 case GICH_VTR:
167 pkt->set(0x44000000 | (NUM_LR - 1));
167 pkt->setLE<uint32_t>(0x44000000 | (NUM_LR - 1));
168 break;
169
170 case GICH_VMCR:
168 break;
169
170 case GICH_VMCR:
171 pkt->set(
171 pkt->setLE<uint32_t>(
172 ((uint32_t)vid->VMPriMask << 27) |
173 ((uint32_t)vid->VMBP << 21) |
174 ((uint32_t)vid->VMABP << 18) |
175 ((uint32_t)vid->VEM << 9) |
176 ((uint32_t)vid->VMCBPR << 4) |
177 ((uint32_t)vid->VMFiqEn << 3) |
178 ((uint32_t)vid->VMAckCtl << 2) |
179 ((uint32_t)vid->VMGrp1En << 1) |
180 ((uint32_t)vid->VMGrp0En << 0)
181 );
182 break;
183
184 case GICH_MISR:
172 ((uint32_t)vid->VMPriMask << 27) |
173 ((uint32_t)vid->VMBP << 21) |
174 ((uint32_t)vid->VMABP << 18) |
175 ((uint32_t)vid->VEM << 9) |
176 ((uint32_t)vid->VMCBPR << 4) |
177 ((uint32_t)vid->VMFiqEn << 3) |
178 ((uint32_t)vid->VMAckCtl << 2) |
179 ((uint32_t)vid->VMGrp1En << 1) |
180 ((uint32_t)vid->VMGrp0En << 0)
181 );
182 break;
183
184 case GICH_MISR:
185 pkt->set(getMISR(vid));
185 pkt->setLE<uint32_t>(getMISR(vid));
186 break;
187
188 case GICH_EISR0:
186 break;
187
188 case GICH_EISR0:
189 pkt->set(vid->eisr & 0xffffffff);
189 pkt->setLE<uint32_t>(vid->eisr & 0xffffffff);
190 break;
191
192 case GICH_EISR1:
190 break;
191
192 case GICH_EISR1:
193 pkt->set(vid->eisr >> 32);
193 pkt->setLE<uint32_t>(vid->eisr >> 32);
194 break;
195
196 case GICH_ELSR0: {
197 uint32_t bm = 0;
198 for (int i = 0; i < ((NUM_LR < 32) ? NUM_LR : 32); i++) {
199 if (!vid->LR[i].State)
200 bm |= 1 << i;
201 }
194 break;
195
196 case GICH_ELSR0: {
197 uint32_t bm = 0;
198 for (int i = 0; i < ((NUM_LR < 32) ? NUM_LR : 32); i++) {
199 if (!vid->LR[i].State)
200 bm |= 1 << i;
201 }
202 pkt->set(bm);
202 pkt->setLE<uint32_t>(bm);
203 } break;
204
205 case GICH_ELSR1: {
206 uint32_t bm = 0;
207 for (int i = 32; i < NUM_LR; i++) {
208 if (!vid->LR[i].State)
209 bm |= 1 << (i-32);
210 }
203 } break;
204
205 case GICH_ELSR1: {
206 uint32_t bm = 0;
207 for (int i = 32; i < NUM_LR; i++) {
208 if (!vid->LR[i].State)
209 bm |= 1 << (i-32);
210 }
211 pkt->set(bm);
211 pkt->setLE<uint32_t>(bm);
212 } break;
213
214 case GICH_APR0:
215 warn_once("VGIC GICH_APR read!\n");
212 } break;
213
214 case GICH_APR0:
215 warn_once("VGIC GICH_APR read!\n");
216 pkt->set(0);
216 pkt->setLE<uint32_t>(0);
217 break;
218
219 case GICH_LR0:
220 case GICH_LR1:
221 case GICH_LR2:
222 case GICH_LR3:
217 break;
218
219 case GICH_LR0:
220 case GICH_LR1:
221 case GICH_LR2:
222 case GICH_LR3:
223 pkt->set(vid->LR[(daddr - GICH_LR0) >> 2]);
223 pkt->setLE<uint32_t>(vid->LR[(daddr - GICH_LR0) >> 2]);
224 break;
225
226 default:
227 panic("VGIC HVCtrl read of bad address %#x\n", daddr);
228 }
229
230 pkt->makeAtomicResponse();
231 return pioDelay;
232}
233
234Tick
235VGic::writeVCpu(PacketPtr pkt)
236{
237 Addr daddr = pkt->getAddr() - vcpuAddr;
238
239 ContextID ctx_id = pkt->req->contextId();
240 assert(ctx_id < VGIC_CPU_MAX);
241 struct vcpuIntData *vid = &vcpuData[ctx_id];
242
224 break;
225
226 default:
227 panic("VGIC HVCtrl read of bad address %#x\n", daddr);
228 }
229
230 pkt->makeAtomicResponse();
231 return pioDelay;
232}
233
234Tick
235VGic::writeVCpu(PacketPtr pkt)
236{
237 Addr daddr = pkt->getAddr() - vcpuAddr;
238
239 ContextID ctx_id = pkt->req->contextId();
240 assert(ctx_id < VGIC_CPU_MAX);
241 struct vcpuIntData *vid = &vcpuData[ctx_id];
242
243 DPRINTF(VGIC, "VGIC VCPU write register %#x <= %#x\n", daddr, pkt->get<uint32_t>());
243 DPRINTF(VGIC, "VGIC VCPU write register %#x <= %#x\n",
244 daddr, pkt->getLE<uint32_t>());
244
245 switch (daddr) {
246 case GICV_CTLR:
245
246 switch (daddr) {
247 case GICV_CTLR:
247 vid->vctrl = pkt->get();
248 vid->vctrl = pkt->getLE<uint32_t>();
248 break;
249 case GICV_PMR:
249 break;
250 case GICV_PMR:
250 vid->VMPriMask = pkt->get();
251 vid->VMPriMask = pkt->getLE<uint32_t>();
251 break;
252 case GICV_EOIR: {
253 // We don't handle the split EOI-then-DIR mode. Linux (guest)
254 // doesn't need it though.
255 assert(!vid->vctrl.EOImode);
252 break;
253 case GICV_EOIR: {
254 // We don't handle the split EOI-then-DIR mode. Linux (guest)
255 // doesn't need it though.
256 assert(!vid->vctrl.EOImode);
256 uint32_t w = pkt->get();
257 uint32_t w = pkt->getLE<uint32_t>();
257 unsigned int virq = w & 0x3ff;
258 unsigned int vcpu = (w >> 10) & 7;
259 int i = findLRForVIRQ(vid, virq, vcpu);
260 if (i < 0) {
261 DPRINTF(VGIC, "EOIR: No LR for irq %d(cpu%d)\n", virq, vcpu);
262 } else {
263 DPRINTF(VGIC, "EOIR: Found LR%d for irq %d(cpu%d)\n", i, virq, vcpu);
264 ListReg *lr = &vid->LR[i];
265 lr->State = 0;
266 // Maintenance interrupt -- via eisr -- is flagged when
267 // LRs have EOI=1 and State=INVALID!
268 }
269 } break;
270 default:
258 unsigned int virq = w & 0x3ff;
259 unsigned int vcpu = (w >> 10) & 7;
260 int i = findLRForVIRQ(vid, virq, vcpu);
261 if (i < 0) {
262 DPRINTF(VGIC, "EOIR: No LR for irq %d(cpu%d)\n", virq, vcpu);
263 } else {
264 DPRINTF(VGIC, "EOIR: Found LR%d for irq %d(cpu%d)\n", i, virq, vcpu);
265 ListReg *lr = &vid->LR[i];
266 lr->State = 0;
267 // Maintenance interrupt -- via eisr -- is flagged when
268 // LRs have EOI=1 and State=INVALID!
269 }
270 } break;
271 default:
271 panic("VGIC VCPU write %#x to unk address %#x\n", pkt->get<uint32_t>(), daddr);
272 panic("VGIC VCPU write %#x to unk address %#x\n",
273 pkt->getLE<uint32_t>(), daddr);
272 }
273
274 // This updates the EISRs and flags IRQs:
275 updateIntState(ctx_id);
276
277 pkt->makeAtomicResponse();
278 return pioDelay;
279}
280
281Tick
282VGic::writeCtrl(PacketPtr pkt)
283{
284 Addr daddr = pkt->getAddr() - hvAddr;
285
286 ContextID ctx_id = pkt->req->contextId();
287
274 }
275
276 // This updates the EISRs and flags IRQs:
277 updateIntState(ctx_id);
278
279 pkt->makeAtomicResponse();
280 return pioDelay;
281}
282
283Tick
284VGic::writeCtrl(PacketPtr pkt)
285{
286 Addr daddr = pkt->getAddr() - hvAddr;
287
288 ContextID ctx_id = pkt->req->contextId();
289
288 DPRINTF(VGIC, "VGIC HVCtrl write register %#x <= %#x\n", daddr, pkt->get<uint32_t>());
290 DPRINTF(VGIC, "VGIC HVCtrl write register %#x <= %#x\n",
291 daddr, pkt->getLE<uint32_t>());
289
290 /* Munge the address: 0-0xfff is the usual space banked by requester CPU.
291 * Anything > that is 0x200-sized slices of 'per CPU' regs.
292 */
293 if (daddr & ~0x1ff) {
294 ctx_id = (daddr >> 9);
295 if (ctx_id > 8)
296 panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr);
297 daddr &= ~0x1ff;
298 }
299 assert(ctx_id < VGIC_CPU_MAX);
300 struct vcpuIntData *vid = &vcpuData[ctx_id];
301
302 switch (daddr) {
303 case GICH_HCR:
292
293 /* Munge the address: 0-0xfff is the usual space banked by requester CPU.
294 * Anything > that is 0x200-sized slices of 'per CPU' regs.
295 */
296 if (daddr & ~0x1ff) {
297 ctx_id = (daddr >> 9);
298 if (ctx_id > 8)
299 panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr);
300 daddr &= ~0x1ff;
301 }
302 assert(ctx_id < VGIC_CPU_MAX);
303 struct vcpuIntData *vid = &vcpuData[ctx_id];
304
305 switch (daddr) {
306 case GICH_HCR:
304 vid->hcr = pkt->get();
307 vid->hcr = pkt->getLE<uint32_t>();
305 // update int state
306 break;
307
308 case GICH_VMCR: {
308 // update int state
309 break;
310
311 case GICH_VMCR: {
309 uint32_t d = pkt->get();
312 uint32_t d = pkt->getLE<uint32_t>();
310 vid->VMPriMask = d >> 27;
311 vid->VMBP = (d >> 21) & 7;
312 vid->VMABP = (d >> 18) & 7;
313 vid->VEM = (d >> 9) & 1;
314 vid->VMCBPR = (d >> 4) & 1;
315 vid->VMFiqEn = (d >> 3) & 1;
316 vid->VMAckCtl = (d >> 2) & 1;
317 vid->VMGrp1En = (d >> 1) & 1;
318 vid->VMGrp0En = d & 1;
319 } break;
320
321 case GICH_APR0:
322 warn_once("VGIC GICH_APR0 written, ignored\n");
323 break;
324
325 case GICH_LR0:
326 case GICH_LR1:
327 case GICH_LR2:
328 case GICH_LR3:
313 vid->VMPriMask = d >> 27;
314 vid->VMBP = (d >> 21) & 7;
315 vid->VMABP = (d >> 18) & 7;
316 vid->VEM = (d >> 9) & 1;
317 vid->VMCBPR = (d >> 4) & 1;
318 vid->VMFiqEn = (d >> 3) & 1;
319 vid->VMAckCtl = (d >> 2) & 1;
320 vid->VMGrp1En = (d >> 1) & 1;
321 vid->VMGrp0En = d & 1;
322 } break;
323
324 case GICH_APR0:
325 warn_once("VGIC GICH_APR0 written, ignored\n");
326 break;
327
328 case GICH_LR0:
329 case GICH_LR1:
330 case GICH_LR2:
331 case GICH_LR3:
329 vid->LR[(daddr - GICH_LR0) >> 2] = pkt->get();
332 vid->LR[(daddr - GICH_LR0) >> 2] = pkt->getLE<uint32_t>();
330 // update int state
331 break;
332
333 default:
334 panic("VGIC HVCtrl write to bad address %#x\n", daddr);
335 }
336
337 updateIntState(ctx_id);

--- 218 unchanged lines hidden ---
333 // update int state
334 break;
335
336 default:
337 panic("VGIC HVCtrl write to bad address %#x\n", daddr);
338 }
339
340 updateIntState(ctx_id);

--- 218 unchanged lines hidden ---