vgic.cc revision 13506:7803580f48d4
12810Srdreslin@umich.edu/* 211375Sandreas.hansson@arm.com * Copyright (c) 2013,2018 ARM Limited 311051Sandreas.hansson@arm.com * All rights reserved 411051Sandreas.hansson@arm.com * 511051Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 611051Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 711051Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 811051Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 911051Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 1011051Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 1111051Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 1211051Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 1311051Sandreas.hansson@arm.com * 1411051Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 1511051Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 162810Srdreslin@umich.edu * met: redistributions of source code must retain the above copyright 172810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer; 182810Srdreslin@umich.edu * redistributions in binary form must reproduce the above copyright 192810Srdreslin@umich.edu * notice, this list of conditions and the following disclaimer in the 202810Srdreslin@umich.edu * documentation and/or other materials provided with the distribution; 212810Srdreslin@umich.edu * neither the name of the copyright holders nor the names of its 222810Srdreslin@umich.edu * contributors may be used to endorse or promote products derived from 232810Srdreslin@umich.edu * this software without specific prior written permission. 242810Srdreslin@umich.edu * 252810Srdreslin@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 262810Srdreslin@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 272810Srdreslin@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282810Srdreslin@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292810Srdreslin@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 302810Srdreslin@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 312810Srdreslin@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 322810Srdreslin@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 332810Srdreslin@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 342810Srdreslin@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352810Srdreslin@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362810Srdreslin@umich.edu * 372810Srdreslin@umich.edu * Authors: Matt Evans 382810Srdreslin@umich.edu */ 392810Srdreslin@umich.edu 402810Srdreslin@umich.edu#include "dev/arm/vgic.hh" 412810Srdreslin@umich.edu 4211051Sandreas.hansson@arm.com#include "base/trace.hh" 4311051Sandreas.hansson@arm.com#include "debug/Checkpoint.hh" 442810Srdreslin@umich.edu#include "debug/VGIC.hh" 4511051Sandreas.hansson@arm.com#include "dev/arm/base_gic.hh" 4611051Sandreas.hansson@arm.com#include "mem/packet.hh" 472810Srdreslin@umich.edu#include "mem/packet_access.hh" 482810Srdreslin@umich.edu 492810Srdreslin@umich.eduVGic::VGic(const Params *p) 502810Srdreslin@umich.edu : PioDevice(p), gicvIIDR(p->gicv_iidr), platform(p->platform), 5111051Sandreas.hansson@arm.com gic(p->gic), vcpuAddr(p->vcpu_addr), hvAddr(p->hv_addr), 522810Srdreslin@umich.edu pioDelay(p->pio_delay), maintInt(p->ppint) 532810Srdreslin@umich.edu{ 5411051Sandreas.hansson@arm.com for (int x = 0; x < VGIC_CPU_MAX; x++) { 552810Srdreslin@umich.edu postVIntEvent[x] = new EventFunctionWrapper( 5611051Sandreas.hansson@arm.com [this, x]{ processPostVIntEvent(x); }, 5711051Sandreas.hansson@arm.com "Post VInterrupt to CPU"); 5811051Sandreas.hansson@arm.com maintIntPosted[x] = false; 5911051Sandreas.hansson@arm.com vIntPosted[x] = false; 6011051Sandreas.hansson@arm.com } 6111288Ssteve.reinhardt@amd.com assert(sys->numRunningContexts() <= VGIC_CPU_MAX); 6211051Sandreas.hansson@arm.com} 6311051Sandreas.hansson@arm.com 6411051Sandreas.hansson@arm.comVGic::~VGic() 6511051Sandreas.hansson@arm.com{ 6611051Sandreas.hansson@arm.com for (int x = 0; x < VGIC_CPU_MAX; x++) 6711053Sandreas.hansson@arm.com delete postVIntEvent[x]; 6811053Sandreas.hansson@arm.com} 6911051Sandreas.hansson@arm.com 7011051Sandreas.hansson@arm.comTick 7111051Sandreas.hansson@arm.comVGic::read(PacketPtr pkt) 7211197Sandreas.hansson@arm.com{ 7311197Sandreas.hansson@arm.com Addr addr = pkt->getAddr(); 7411199Sandreas.hansson@arm.com 7511197Sandreas.hansson@arm.com if (addr >= vcpuAddr && addr < vcpuAddr + GICV_SIZE) 7611197Sandreas.hansson@arm.com return readVCpu(pkt); 7711197Sandreas.hansson@arm.com else if (addr >= hvAddr && addr < hvAddr + GICH_REG_SIZE) 7811051Sandreas.hansson@arm.com return readCtrl(pkt); 7911051Sandreas.hansson@arm.com else 8011051Sandreas.hansson@arm.com panic("Read to unknown address %#x\n", pkt->getAddr()); 8111051Sandreas.hansson@arm.com} 8211051Sandreas.hansson@arm.com 8311051Sandreas.hansson@arm.comTick 8411051Sandreas.hansson@arm.comVGic::write(PacketPtr pkt) 8511051Sandreas.hansson@arm.com{ 8611051Sandreas.hansson@arm.com Addr addr = pkt->getAddr(); 8711051Sandreas.hansson@arm.com 8811051Sandreas.hansson@arm.com if (addr >= vcpuAddr && addr < vcpuAddr + GICV_SIZE) 8911051Sandreas.hansson@arm.com return writeVCpu(pkt); 9011051Sandreas.hansson@arm.com else if (addr >= hvAddr && addr < hvAddr + GICH_REG_SIZE) 9111051Sandreas.hansson@arm.com return writeCtrl(pkt); 9211051Sandreas.hansson@arm.com else 9311051Sandreas.hansson@arm.com panic("Write to unknown address %#x\n", pkt->getAddr()); 9411051Sandreas.hansson@arm.com} 9511051Sandreas.hansson@arm.com 9611051Sandreas.hansson@arm.comTick 9711051Sandreas.hansson@arm.comVGic::readVCpu(PacketPtr pkt) 9811051Sandreas.hansson@arm.com{ 9911051Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - vcpuAddr; 10011051Sandreas.hansson@arm.com 10111051Sandreas.hansson@arm.com ContextID ctx_id = pkt->req->contextId(); 10211051Sandreas.hansson@arm.com assert(ctx_id < VGIC_CPU_MAX); 10311051Sandreas.hansson@arm.com struct vcpuIntData *vid = &vcpuData[ctx_id]; 10411051Sandreas.hansson@arm.com 10511051Sandreas.hansson@arm.com DPRINTF(VGIC, "VGIC VCPU read register %#x\n", daddr); 10611051Sandreas.hansson@arm.com 10711051Sandreas.hansson@arm.com switch (daddr) { 10811051Sandreas.hansson@arm.com case GICV_CTLR: 10911051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(vid->vctrl); 11011051Sandreas.hansson@arm.com break; 11111051Sandreas.hansson@arm.com case GICV_IAR: { 11211051Sandreas.hansson@arm.com int i = findHighestPendingLR(vid); 11311051Sandreas.hansson@arm.com if (i < 0 || !vid->vctrl.En) { 11411051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(1023); // "No int" marker 11511051Sandreas.hansson@arm.com } else { 11611051Sandreas.hansson@arm.com ListReg *lr = &vid->LR[i]; 11711051Sandreas.hansson@arm.com 11811051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(lr->VirtualID | 11911051Sandreas.hansson@arm.com (((int)lr->CpuID) << 10)); 12011051Sandreas.hansson@arm.com // We don't support auto-EOI of HW interrupts via real GIC! 12111051Sandreas.hansson@arm.com // Fortunately, KVM doesn't use this. How about Xen...? Ulp! 12211051Sandreas.hansson@arm.com if (lr->HW) 12311051Sandreas.hansson@arm.com panic("VGIC does not support 'HW' List Register feature (LR %#x)!\n", 12411051Sandreas.hansson@arm.com *lr); 12511051Sandreas.hansson@arm.com lr->State = LR_ACTIVE; 12611051Sandreas.hansson@arm.com DPRINTF(VGIC, "Consumed interrupt %d (cpu%d) from LR%d (EOI%d)\n", 12711051Sandreas.hansson@arm.com lr->VirtualID, lr->CpuID, i, lr->EOI); 12811051Sandreas.hansson@arm.com } 12911051Sandreas.hansson@arm.com } break; 13011051Sandreas.hansson@arm.com case GICV_IIDR: 13111051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(gicvIIDR); 13211051Sandreas.hansson@arm.com break; 13311051Sandreas.hansson@arm.com default: 13411051Sandreas.hansson@arm.com panic("VGIC VCPU read of bad address %#x\n", daddr); 13511051Sandreas.hansson@arm.com } 13611051Sandreas.hansson@arm.com 13711051Sandreas.hansson@arm.com updateIntState(ctx_id); 13811051Sandreas.hansson@arm.com 13911051Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 14011051Sandreas.hansson@arm.com return pioDelay; 14111051Sandreas.hansson@arm.com} 14211051Sandreas.hansson@arm.com 14311051Sandreas.hansson@arm.comTick 14411051Sandreas.hansson@arm.comVGic::readCtrl(PacketPtr pkt) 14511051Sandreas.hansson@arm.com{ 14611051Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - hvAddr; 14711051Sandreas.hansson@arm.com 14811051Sandreas.hansson@arm.com ContextID ctx_id = pkt->req->contextId(); 14911051Sandreas.hansson@arm.com 15011051Sandreas.hansson@arm.com DPRINTF(VGIC, "VGIC HVCtrl read register %#x\n", daddr); 15111051Sandreas.hansson@arm.com 15211051Sandreas.hansson@arm.com /* Munge the address: 0-0xfff is the usual space banked by requester CPU. 15311051Sandreas.hansson@arm.com * Anything > that is 0x200-sized slices of 'per CPU' regs. 15411051Sandreas.hansson@arm.com */ 15511051Sandreas.hansson@arm.com if (daddr & ~0x1ff) { 15611051Sandreas.hansson@arm.com ctx_id = (daddr >> 9); 15711051Sandreas.hansson@arm.com if (ctx_id > 8) 15811051Sandreas.hansson@arm.com panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr); 15911051Sandreas.hansson@arm.com daddr &= ~0x1ff; 16011051Sandreas.hansson@arm.com } 16111284Sandreas.hansson@arm.com assert(ctx_id < VGIC_CPU_MAX); 16211051Sandreas.hansson@arm.com struct vcpuIntData *vid = &vcpuData[ctx_id]; 16311051Sandreas.hansson@arm.com 16411051Sandreas.hansson@arm.com switch (daddr) { 16511051Sandreas.hansson@arm.com case GICH_HCR: 16611051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(vid->hcr); 16711051Sandreas.hansson@arm.com break; 16811051Sandreas.hansson@arm.com 16911284Sandreas.hansson@arm.com case GICH_VTR: 17011284Sandreas.hansson@arm.com pkt->setLE<uint32_t>(0x44000000 | (NUM_LR - 1)); 17111284Sandreas.hansson@arm.com break; 17211284Sandreas.hansson@arm.com 17311051Sandreas.hansson@arm.com case GICH_VMCR: 17411284Sandreas.hansson@arm.com pkt->setLE<uint32_t>( 17511051Sandreas.hansson@arm.com ((uint32_t)vid->VMPriMask << 27) | 17611051Sandreas.hansson@arm.com ((uint32_t)vid->VMBP << 21) | 17711051Sandreas.hansson@arm.com ((uint32_t)vid->VMABP << 18) | 17811284Sandreas.hansson@arm.com ((uint32_t)vid->VEM << 9) | 17911284Sandreas.hansson@arm.com ((uint32_t)vid->VMCBPR << 4) | 18011284Sandreas.hansson@arm.com ((uint32_t)vid->VMFiqEn << 3) | 18111284Sandreas.hansson@arm.com ((uint32_t)vid->VMAckCtl << 2) | 18211051Sandreas.hansson@arm.com ((uint32_t)vid->VMGrp1En << 1) | 18311288Ssteve.reinhardt@amd.com ((uint32_t)vid->VMGrp0En << 0) 18411288Ssteve.reinhardt@amd.com ); 18511051Sandreas.hansson@arm.com break; 18611051Sandreas.hansson@arm.com 18711051Sandreas.hansson@arm.com case GICH_MISR: 18811051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(getMISR(vid)); 18911286Sandreas.hansson@arm.com break; 19011286Sandreas.hansson@arm.com 19111286Sandreas.hansson@arm.com case GICH_EISR0: 19211051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(vid->eisr & 0xffffffff); 19311286Sandreas.hansson@arm.com break; 19411051Sandreas.hansson@arm.com 19511051Sandreas.hansson@arm.com case GICH_EISR1: 19611051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(vid->eisr >> 32); 19711051Sandreas.hansson@arm.com break; 19811051Sandreas.hansson@arm.com 19911051Sandreas.hansson@arm.com case GICH_ELSR0: { 20011051Sandreas.hansson@arm.com uint32_t bm = 0; 20111051Sandreas.hansson@arm.com for (int i = 0; i < ((NUM_LR < 32) ? NUM_LR : 32); i++) { 20211051Sandreas.hansson@arm.com if (!vid->LR[i].State) 20311051Sandreas.hansson@arm.com bm |= 1 << i; 20411051Sandreas.hansson@arm.com } 20511284Sandreas.hansson@arm.com pkt->setLE<uint32_t>(bm); 20611051Sandreas.hansson@arm.com } break; 20711051Sandreas.hansson@arm.com 20811051Sandreas.hansson@arm.com case GICH_ELSR1: { 20911051Sandreas.hansson@arm.com uint32_t bm = 0; 21011051Sandreas.hansson@arm.com for (int i = 32; i < NUM_LR; i++) { 21111284Sandreas.hansson@arm.com if (!vid->LR[i].State) 21211051Sandreas.hansson@arm.com bm |= 1 << (i-32); 21311284Sandreas.hansson@arm.com } 21411051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(bm); 21511197Sandreas.hansson@arm.com } break; 21611197Sandreas.hansson@arm.com 21711197Sandreas.hansson@arm.com case GICH_APR0: 21811197Sandreas.hansson@arm.com warn_once("VGIC GICH_APR read!\n"); 21911051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(0); 22011284Sandreas.hansson@arm.com break; 22111051Sandreas.hansson@arm.com 22211284Sandreas.hansson@arm.com case GICH_LR0: 22311284Sandreas.hansson@arm.com case GICH_LR1: 22411284Sandreas.hansson@arm.com case GICH_LR2: 22511051Sandreas.hansson@arm.com case GICH_LR3: 22611051Sandreas.hansson@arm.com pkt->setLE<uint32_t>(vid->LR[(daddr - GICH_LR0) >> 2]); 22711051Sandreas.hansson@arm.com break; 22811284Sandreas.hansson@arm.com 22911284Sandreas.hansson@arm.com default: 23011284Sandreas.hansson@arm.com panic("VGIC HVCtrl read of bad address %#x\n", daddr); 23111284Sandreas.hansson@arm.com } 23211051Sandreas.hansson@arm.com 23311051Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 23411051Sandreas.hansson@arm.com return pioDelay; 23511284Sandreas.hansson@arm.com} 23611284Sandreas.hansson@arm.com 23711284Sandreas.hansson@arm.comTick 23811197Sandreas.hansson@arm.comVGic::writeVCpu(PacketPtr pkt) 23911284Sandreas.hansson@arm.com{ 24011284Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - vcpuAddr; 24111284Sandreas.hansson@arm.com 24211284Sandreas.hansson@arm.com ContextID ctx_id = pkt->req->contextId(); 24311284Sandreas.hansson@arm.com assert(ctx_id < VGIC_CPU_MAX); 24411284Sandreas.hansson@arm.com struct vcpuIntData *vid = &vcpuData[ctx_id]; 24511284Sandreas.hansson@arm.com 24611284Sandreas.hansson@arm.com DPRINTF(VGIC, "VGIC VCPU write register %#x <= %#x\n", 24711284Sandreas.hansson@arm.com daddr, pkt->getLE<uint32_t>()); 24811284Sandreas.hansson@arm.com 24911284Sandreas.hansson@arm.com switch (daddr) { 25011284Sandreas.hansson@arm.com case GICV_CTLR: 25111284Sandreas.hansson@arm.com vid->vctrl = pkt->getLE<uint32_t>(); 25211284Sandreas.hansson@arm.com break; 25311284Sandreas.hansson@arm.com case GICV_PMR: 25411197Sandreas.hansson@arm.com vid->VMPriMask = pkt->getLE<uint32_t>(); 25511284Sandreas.hansson@arm.com break; 25611284Sandreas.hansson@arm.com case GICV_EOIR: { 25711284Sandreas.hansson@arm.com // We don't handle the split EOI-then-DIR mode. Linux (guest) 25811284Sandreas.hansson@arm.com // doesn't need it though. 25911284Sandreas.hansson@arm.com assert(!vid->vctrl.EOImode); 26011284Sandreas.hansson@arm.com uint32_t w = pkt->getLE<uint32_t>(); 26111284Sandreas.hansson@arm.com unsigned int virq = w & 0x3ff; 26211197Sandreas.hansson@arm.com unsigned int vcpu = (w >> 10) & 7; 26311051Sandreas.hansson@arm.com int i = findLRForVIRQ(vid, virq, vcpu); 26411051Sandreas.hansson@arm.com if (i < 0) { 26511051Sandreas.hansson@arm.com DPRINTF(VGIC, "EOIR: No LR for irq %d(cpu%d)\n", virq, vcpu); 26611051Sandreas.hansson@arm.com } else { 26711051Sandreas.hansson@arm.com DPRINTF(VGIC, "EOIR: Found LR%d for irq %d(cpu%d)\n", i, virq, vcpu); 26811284Sandreas.hansson@arm.com ListReg *lr = &vid->LR[i]; 26911284Sandreas.hansson@arm.com lr->State = 0; 27011051Sandreas.hansson@arm.com // Maintenance interrupt -- via eisr -- is flagged when 27111051Sandreas.hansson@arm.com // LRs have EOI=1 and State=INVALID! 27211051Sandreas.hansson@arm.com } 27311051Sandreas.hansson@arm.com } break; 27411284Sandreas.hansson@arm.com default: 27511051Sandreas.hansson@arm.com panic("VGIC VCPU write %#x to unk address %#x\n", 27611051Sandreas.hansson@arm.com pkt->getLE<uint32_t>(), daddr); 27711051Sandreas.hansson@arm.com } 27811284Sandreas.hansson@arm.com 27911051Sandreas.hansson@arm.com // This updates the EISRs and flags IRQs: 28011197Sandreas.hansson@arm.com updateIntState(ctx_id); 28111197Sandreas.hansson@arm.com 28211197Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 28311197Sandreas.hansson@arm.com return pioDelay; 28411288Ssteve.reinhardt@amd.com} 28511051Sandreas.hansson@arm.com 28611051Sandreas.hansson@arm.comTick 28711051Sandreas.hansson@arm.comVGic::writeCtrl(PacketPtr pkt) 28811051Sandreas.hansson@arm.com{ 28911051Sandreas.hansson@arm.com Addr daddr = pkt->getAddr() - hvAddr; 29011051Sandreas.hansson@arm.com 29111051Sandreas.hansson@arm.com ContextID ctx_id = pkt->req->contextId(); 29211051Sandreas.hansson@arm.com 29311051Sandreas.hansson@arm.com DPRINTF(VGIC, "VGIC HVCtrl write register %#x <= %#x\n", 29411051Sandreas.hansson@arm.com daddr, pkt->getLE<uint32_t>()); 29511051Sandreas.hansson@arm.com 29611051Sandreas.hansson@arm.com /* Munge the address: 0-0xfff is the usual space banked by requester CPU. 29711051Sandreas.hansson@arm.com * Anything > that is 0x200-sized slices of 'per CPU' regs. 29811051Sandreas.hansson@arm.com */ 29911051Sandreas.hansson@arm.com if (daddr & ~0x1ff) { 30011051Sandreas.hansson@arm.com ctx_id = (daddr >> 9); 30111051Sandreas.hansson@arm.com if (ctx_id > 8) 30211051Sandreas.hansson@arm.com panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr); 30311051Sandreas.hansson@arm.com daddr &= ~0x1ff; 30411051Sandreas.hansson@arm.com } 30511051Sandreas.hansson@arm.com assert(ctx_id < VGIC_CPU_MAX); 30611288Ssteve.reinhardt@amd.com struct vcpuIntData *vid = &vcpuData[ctx_id]; 30711051Sandreas.hansson@arm.com 30811051Sandreas.hansson@arm.com switch (daddr) { 30911051Sandreas.hansson@arm.com case GICH_HCR: 31011051Sandreas.hansson@arm.com vid->hcr = pkt->getLE<uint32_t>(); 31111051Sandreas.hansson@arm.com // update int state 31211051Sandreas.hansson@arm.com break; 31311051Sandreas.hansson@arm.com 31411051Sandreas.hansson@arm.com case GICH_VMCR: { 31511051Sandreas.hansson@arm.com uint32_t d = pkt->getLE<uint32_t>(); 31611051Sandreas.hansson@arm.com vid->VMPriMask = d >> 27; 31711199Sandreas.hansson@arm.com vid->VMBP = (d >> 21) & 7; 31811051Sandreas.hansson@arm.com vid->VMABP = (d >> 18) & 7; 31911051Sandreas.hansson@arm.com vid->VEM = (d >> 9) & 1; 32011051Sandreas.hansson@arm.com vid->VMCBPR = (d >> 4) & 1; 32111051Sandreas.hansson@arm.com vid->VMFiqEn = (d >> 3) & 1; 32211051Sandreas.hansson@arm.com vid->VMAckCtl = (d >> 2) & 1; 32311051Sandreas.hansson@arm.com vid->VMGrp1En = (d >> 1) & 1; 32411051Sandreas.hansson@arm.com vid->VMGrp0En = d & 1; 32511484Snikos.nikoleris@arm.com } break; 32611051Sandreas.hansson@arm.com 32711051Sandreas.hansson@arm.com case GICH_APR0: 32811051Sandreas.hansson@arm.com warn_once("VGIC GICH_APR0 written, ignored\n"); 32911051Sandreas.hansson@arm.com break; 33011051Sandreas.hansson@arm.com 33111051Sandreas.hansson@arm.com case GICH_LR0: 33211051Sandreas.hansson@arm.com case GICH_LR1: 33311051Sandreas.hansson@arm.com case GICH_LR2: 33411051Sandreas.hansson@arm.com case GICH_LR3: 33511051Sandreas.hansson@arm.com vid->LR[(daddr - GICH_LR0) >> 2] = pkt->getLE<uint32_t>(); 33611051Sandreas.hansson@arm.com // update int state 33711051Sandreas.hansson@arm.com break; 33811051Sandreas.hansson@arm.com 33911051Sandreas.hansson@arm.com default: 34011051Sandreas.hansson@arm.com panic("VGIC HVCtrl write to bad address %#x\n", daddr); 34111051Sandreas.hansson@arm.com } 34211051Sandreas.hansson@arm.com 34311199Sandreas.hansson@arm.com updateIntState(ctx_id); 34411051Sandreas.hansson@arm.com 34511051Sandreas.hansson@arm.com pkt->makeAtomicResponse(); 34611051Sandreas.hansson@arm.com return pioDelay; 34711051Sandreas.hansson@arm.com} 34811051Sandreas.hansson@arm.com 34911051Sandreas.hansson@arm.com 35011051Sandreas.hansson@arm.comuint32_t 35111051Sandreas.hansson@arm.comVGic::getMISR(struct vcpuIntData *vid) 35211375Sandreas.hansson@arm.com{ 35311375Sandreas.hansson@arm.com return (!!vid->hcr.VGrp1DIE && !vid->VMGrp1En ? 0x80 : 0) | 35411375Sandreas.hansson@arm.com (!!vid->hcr.VGrp1EIE && vid->VMGrp1En ? 0x40 : 0) | 35511199Sandreas.hansson@arm.com (!!vid->hcr.VGrp0DIE && !vid->VMGrp0En ? 0x20 : 0) | 35611199Sandreas.hansson@arm.com (!!vid->hcr.VGrp0EIE && vid->VMGrp0En ? 0x10 : 0) | 35711199Sandreas.hansson@arm.com (!!vid->hcr.NPIE && !lrPending(vid) ? 0x08 : 0) | 35811199Sandreas.hansson@arm.com (!!vid->hcr.LRENPIE && vid->hcr.EOICount ? 0x04 : 0) | 35911199Sandreas.hansson@arm.com (!!vid->hcr.UIE && lrValid(vid) <= 1 ? 0x02 : 0) | 36011199Sandreas.hansson@arm.com (vid->eisr ? 0x01 : 0); 36111199Sandreas.hansson@arm.com} 36211199Sandreas.hansson@arm.com 36311199Sandreas.hansson@arm.comvoid 36411199Sandreas.hansson@arm.comVGic::postVInt(uint32_t cpu, Tick when) 36511199Sandreas.hansson@arm.com{ 36611199Sandreas.hansson@arm.com DPRINTF(VGIC, "Posting VIRQ to %d\n", cpu); 36711199Sandreas.hansson@arm.com if (!(postVIntEvent[cpu]->scheduled())) 36811199Sandreas.hansson@arm.com eventq->schedule(postVIntEvent[cpu], when); 36911199Sandreas.hansson@arm.com} 37011199Sandreas.hansson@arm.com 37111199Sandreas.hansson@arm.comvoid 37211199Sandreas.hansson@arm.comVGic::unPostVInt(uint32_t cpu) 37311199Sandreas.hansson@arm.com{ 37411199Sandreas.hansson@arm.com DPRINTF(VGIC, "Unposting VIRQ to %d\n", cpu); 37511375Sandreas.hansson@arm.com platform->intrctrl->clear(cpu, ArmISA::INT_VIRT_IRQ, 0); 37611199Sandreas.hansson@arm.com} 37711199Sandreas.hansson@arm.com 37811051Sandreas.hansson@arm.comvoid 37911051Sandreas.hansson@arm.comVGic::processPostVIntEvent(uint32_t cpu) 38011051Sandreas.hansson@arm.com{ 38111051Sandreas.hansson@arm.com platform->intrctrl->post(cpu, ArmISA::INT_VIRT_IRQ, 0); 38211051Sandreas.hansson@arm.com} 38311199Sandreas.hansson@arm.com 38411051Sandreas.hansson@arm.com 38511199Sandreas.hansson@arm.comvoid 38611199Sandreas.hansson@arm.comVGic::postMaintInt(uint32_t cpu) 38711199Sandreas.hansson@arm.com{ 38811199Sandreas.hansson@arm.com DPRINTF(VGIC, "Posting maintenance PPI to GIC/cpu%d\n", cpu); 38911199Sandreas.hansson@arm.com // Linux DT configures this as Level. 39011199Sandreas.hansson@arm.com gic->sendPPInt(maintInt, cpu); 39111199Sandreas.hansson@arm.com} 39211199Sandreas.hansson@arm.com 39311199Sandreas.hansson@arm.comvoid 39411199Sandreas.hansson@arm.comVGic::unPostMaintInt(uint32_t cpu) 39511199Sandreas.hansson@arm.com{ 39611199Sandreas.hansson@arm.com DPRINTF(VGIC, "Unposting maintenance PPI to GIC/cpu%d\n", cpu); 39711484Snikos.nikoleris@arm.com gic->clearPPInt(maintInt, cpu); 39811051Sandreas.hansson@arm.com} 39911051Sandreas.hansson@arm.com 40011484Snikos.nikoleris@arm.com/* Update state (in general); something concerned with ctx_id has changed. 40111051Sandreas.hansson@arm.com * This may raise a maintenance interrupt. 40211051Sandreas.hansson@arm.com */ 40311051Sandreas.hansson@arm.comvoid 40411051Sandreas.hansson@arm.comVGic::updateIntState(ContextID ctx_id) 40511051Sandreas.hansson@arm.com{ 40611051Sandreas.hansson@arm.com // @todo This should update APRs! 40711051Sandreas.hansson@arm.com 40811051Sandreas.hansson@arm.com // Build EISR contents: 40911051Sandreas.hansson@arm.com // (Cached so that regs can read them without messing about again) 41011051Sandreas.hansson@arm.com struct vcpuIntData *tvid = &vcpuData[ctx_id]; 41111051Sandreas.hansson@arm.com 41211199Sandreas.hansson@arm.com tvid->eisr = 0; 41311199Sandreas.hansson@arm.com for (int i = 0; i < NUM_LR; i++) { 41411199Sandreas.hansson@arm.com if (!tvid->LR[i].State && tvid->LR[i].EOI) { 41511199Sandreas.hansson@arm.com tvid->eisr |= 1 << i; 41611199Sandreas.hansson@arm.com } 41711284Sandreas.hansson@arm.com } 41811284Sandreas.hansson@arm.com 41911284Sandreas.hansson@arm.com assert(sys->numRunningContexts() <= VGIC_CPU_MAX); 42011284Sandreas.hansson@arm.com for (int i = 0; i < sys->numRunningContexts(); i++) { 42111051Sandreas.hansson@arm.com struct vcpuIntData *vid = &vcpuData[i]; 42211051Sandreas.hansson@arm.com // Are any LRs active that weren't before? 42311051Sandreas.hansson@arm.com if (!vIntPosted[i]) { 42411051Sandreas.hansson@arm.com if (lrPending(vid) && vid->vctrl.En) { 42511051Sandreas.hansson@arm.com vIntPosted[i] = true; 42611051Sandreas.hansson@arm.com postVInt(i, curTick() + 1); 42711051Sandreas.hansson@arm.com } 42811051Sandreas.hansson@arm.com } else if (!lrPending(vid)) { 42911051Sandreas.hansson@arm.com vIntPosted[i] = false; 43011484Snikos.nikoleris@arm.com unPostVInt(i); 43111051Sandreas.hansson@arm.com } 43211051Sandreas.hansson@arm.com 43311051Sandreas.hansson@arm.com // Any maintenance ints to send? 43411051Sandreas.hansson@arm.com if (!maintIntPosted[i]) { 43511051Sandreas.hansson@arm.com if (vid->hcr.En && getMISR(vid)) { 43611051Sandreas.hansson@arm.com maintIntPosted[i] = true; 43711051Sandreas.hansson@arm.com postMaintInt(i); 43811051Sandreas.hansson@arm.com } 43911051Sandreas.hansson@arm.com } else { 44011051Sandreas.hansson@arm.com if (!vid->hcr.En || !getMISR(vid)) { 44111051Sandreas.hansson@arm.com unPostMaintInt(i); 44211484Snikos.nikoleris@arm.com maintIntPosted[i] = false; 44311483Snikos.nikoleris@arm.com } 44411483Snikos.nikoleris@arm.com } 44511051Sandreas.hansson@arm.com } 44611051Sandreas.hansson@arm.com} 44711051Sandreas.hansson@arm.com 44811051Sandreas.hansson@arm.comAddrRangeList 44911051Sandreas.hansson@arm.comVGic::getAddrRanges() const 45011051Sandreas.hansson@arm.com{ 45111484Snikos.nikoleris@arm.com AddrRangeList ranges; 45211284Sandreas.hansson@arm.com ranges.push_back(RangeSize(hvAddr, GICH_REG_SIZE)); 45311051Sandreas.hansson@arm.com ranges.push_back(RangeSize(vcpuAddr, GICV_SIZE)); 45411051Sandreas.hansson@arm.com return ranges; 45511051Sandreas.hansson@arm.com} 45611484Snikos.nikoleris@arm.com 45711051Sandreas.hansson@arm.comvoid 45811051Sandreas.hansson@arm.comVGic::serialize(CheckpointOut &cp) const 45911051Sandreas.hansson@arm.com{ 46011051Sandreas.hansson@arm.com Tick interrupt_time[VGIC_CPU_MAX]; 46111051Sandreas.hansson@arm.com for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) { 46211051Sandreas.hansson@arm.com interrupt_time[cpu] = 0; 46311051Sandreas.hansson@arm.com if (postVIntEvent[cpu]->scheduled()) { 46411051Sandreas.hansson@arm.com interrupt_time[cpu] = postVIntEvent[cpu]->when(); 46511051Sandreas.hansson@arm.com } 46611051Sandreas.hansson@arm.com } 46711051Sandreas.hansson@arm.com 46811051Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Serializing VGIC\n"); 46911051Sandreas.hansson@arm.com 47011051Sandreas.hansson@arm.com SERIALIZE_ARRAY(interrupt_time, VGIC_CPU_MAX); 47111051Sandreas.hansson@arm.com SERIALIZE_ARRAY(maintIntPosted, VGIC_CPU_MAX); 47211051Sandreas.hansson@arm.com SERIALIZE_ARRAY(vIntPosted, VGIC_CPU_MAX); 47311051Sandreas.hansson@arm.com SERIALIZE_SCALAR(vcpuAddr); 47411051Sandreas.hansson@arm.com SERIALIZE_SCALAR(hvAddr); 47511051Sandreas.hansson@arm.com SERIALIZE_SCALAR(pioDelay); 47611051Sandreas.hansson@arm.com SERIALIZE_SCALAR(maintInt); 47711051Sandreas.hansson@arm.com 47811051Sandreas.hansson@arm.com for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) 47911051Sandreas.hansson@arm.com vcpuData[cpu].serializeSection(cp, csprintf("vcpuData%d", cpu)); 48011051Sandreas.hansson@arm.com} 48111199Sandreas.hansson@arm.com 48211199Sandreas.hansson@arm.comvoid 48311199Sandreas.hansson@arm.comVGic::vcpuIntData::serialize(CheckpointOut &cp) const 48411199Sandreas.hansson@arm.com{ 48511199Sandreas.hansson@arm.com uint32_t vctrl_val = vctrl; 48611051Sandreas.hansson@arm.com SERIALIZE_SCALAR(vctrl_val); 48711199Sandreas.hansson@arm.com uint32_t hcr_val = hcr; 48811051Sandreas.hansson@arm.com SERIALIZE_SCALAR(hcr_val); 48911051Sandreas.hansson@arm.com uint64_t eisr_val = eisr; 49011051Sandreas.hansson@arm.com SERIALIZE_SCALAR(eisr_val); 49111051Sandreas.hansson@arm.com uint8_t VMGrp0En_val = VMGrp0En; 49211051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VMGrp0En_val); 49311051Sandreas.hansson@arm.com uint8_t VMGrp1En_val = VMGrp1En; 49411051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VMGrp1En_val); 49511051Sandreas.hansson@arm.com uint8_t VMAckCtl_val = VMAckCtl; 49611051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VMAckCtl_val); 49711051Sandreas.hansson@arm.com uint8_t VMFiqEn_val = VMFiqEn; 49811051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VMFiqEn_val); 49911051Sandreas.hansson@arm.com uint8_t VMCBPR_val = VMCBPR; 50011051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VMCBPR_val); 50111051Sandreas.hansson@arm.com uint8_t VEM_val = VEM; 50211051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VEM_val); 50311051Sandreas.hansson@arm.com uint8_t VMABP_val = VMABP; 50411051Sandreas.hansson@arm.com SERIALIZE_SCALAR(VMABP_val); 50511130Sali.jafri@arm.com uint8_t VMBP_val = VMBP; 50611130Sali.jafri@arm.com SERIALIZE_SCALAR(VMBP_val); 50711130Sali.jafri@arm.com uint8_t VMPriMask_val = VMPriMask; 50811130Sali.jafri@arm.com SERIALIZE_SCALAR(VMPriMask_val); 50911130Sali.jafri@arm.com 51011130Sali.jafri@arm.com for (int i = 0; i < NUM_LR; i++) { 51111130Sali.jafri@arm.com ScopedCheckpointSection sec_lr(cp, csprintf("LR%d", i)); 51211130Sali.jafri@arm.com paramOut(cp, "lr", LR[i]); 51311130Sali.jafri@arm.com } 51411199Sandreas.hansson@arm.com} 51511130Sali.jafri@arm.com 51611130Sali.jafri@arm.comvoid VGic::unserialize(CheckpointIn &cp) 51711130Sali.jafri@arm.com{ 51811130Sali.jafri@arm.com DPRINTF(Checkpoint, "Unserializing Arm GIC\n"); 51911130Sali.jafri@arm.com 52011130Sali.jafri@arm.com Tick interrupt_time[VGIC_CPU_MAX]; 52111130Sali.jafri@arm.com UNSERIALIZE_ARRAY(interrupt_time, VGIC_CPU_MAX); 52211130Sali.jafri@arm.com for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) { 52311130Sali.jafri@arm.com if (interrupt_time[cpu]) 52411130Sali.jafri@arm.com schedule(postVIntEvent[cpu], interrupt_time[cpu]); 52511130Sali.jafri@arm.com 52611130Sali.jafri@arm.com vcpuData[cpu].unserializeSection(cp, csprintf("vcpuData%d", cpu)); 52711130Sali.jafri@arm.com } 52811130Sali.jafri@arm.com UNSERIALIZE_ARRAY(maintIntPosted, VGIC_CPU_MAX); 52911130Sali.jafri@arm.com UNSERIALIZE_ARRAY(vIntPosted, VGIC_CPU_MAX); 53011130Sali.jafri@arm.com UNSERIALIZE_SCALAR(vcpuAddr); 53111130Sali.jafri@arm.com UNSERIALIZE_SCALAR(hvAddr); 53211130Sali.jafri@arm.com UNSERIALIZE_SCALAR(pioDelay); 53311130Sali.jafri@arm.com UNSERIALIZE_SCALAR(maintInt); 53411130Sali.jafri@arm.com} 53511130Sali.jafri@arm.com 53611130Sali.jafri@arm.comvoid 53711130Sali.jafri@arm.comVGic::vcpuIntData::unserialize(CheckpointIn &cp) 53811051Sandreas.hansson@arm.com{ 53911051Sandreas.hansson@arm.com paramIn(cp, "vctrl_val", vctrl); 54011051Sandreas.hansson@arm.com paramIn(cp, "hcr_val", hcr); 54111051Sandreas.hansson@arm.com paramIn(cp, "eisr_val", eisr); 54211051Sandreas.hansson@arm.com paramIn(cp, "VMGrp0En_val", VMGrp0En); 54311051Sandreas.hansson@arm.com paramIn(cp, "VMGrp1En_val", VMGrp1En); 54411051Sandreas.hansson@arm.com paramIn(cp, "VMAckCtl_val", VMAckCtl); 54511051Sandreas.hansson@arm.com paramIn(cp, "VMFiqEn_val", VMFiqEn); 54611051Sandreas.hansson@arm.com paramIn(cp, "VMCBPR_val", VMCBPR); 54711051Sandreas.hansson@arm.com paramIn(cp, "VEM_val", VEM); 54811276Sandreas.hansson@arm.com paramIn(cp, "VMABP_val", VMABP); 54911276Sandreas.hansson@arm.com paramIn(cp, "VMPriMask_val", VMPriMask); 55011276Sandreas.hansson@arm.com 55111276Sandreas.hansson@arm.com for (int i = 0; i < NUM_LR; i++) { 55211276Sandreas.hansson@arm.com ScopedCheckpointSection sec_lr(cp, csprintf("LR%d", i)); 55311276Sandreas.hansson@arm.com paramIn(cp, "lr", LR[i]); 55411276Sandreas.hansson@arm.com } 55511276Sandreas.hansson@arm.com} 55611276Sandreas.hansson@arm.com 55711051Sandreas.hansson@arm.comVGic * 55811276Sandreas.hansson@arm.comVGicParams::create() 55911276Sandreas.hansson@arm.com{ 56011276Sandreas.hansson@arm.com return new VGic(this); 56111276Sandreas.hansson@arm.com} 56211276Sandreas.hansson@arm.com