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 | 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 | 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 | 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 | 163 pkt->setLE<uint32_t>(vid->hcr); |
164 break; 165 166 case GICH_VTR: | 164 break; 165 166 case GICH_VTR: |
167 pkt->set | 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 | 185 pkt->setLE<uint32_t>(getMISR(vid)); |
186 break; 187 188 case GICH_EISR0: | 186 break; 187 188 case GICH_EISR0: |
189 pkt->set | 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 | 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 | 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 | 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 | 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 | 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 --- |