vgic.cc revision 12239:ae1686aaebc5
1955SN/A/* 2955SN/A * Copyright (c) 2013 ARM Limited 31762SN/A * All rights reserved 4955SN/A * 5955SN/A * The license below extends only to copyright in the software and shall 6955SN/A * not be construed as granting a license to any other intellectual 7955SN/A * property including but not limited to intellectual property relating 8955SN/A * to a hardware implementation of the functionality of the software 9955SN/A * licensed hereunder. You may use the software subject to the license 10955SN/A * terms below provided that you ensure that this notice is replicated 11955SN/A * unmodified and in its entirety in all distributions of the software, 12955SN/A * modified or unmodified, in source code or in binary form. 13955SN/A * 14955SN/A * Redistribution and use in source and binary forms, with or without 15955SN/A * modification, are permitted provided that the following conditions are 16955SN/A * met: redistributions of source code must retain the above copyright 17955SN/A * notice, this list of conditions and the following disclaimer; 18955SN/A * redistributions in binary form must reproduce the above copyright 19955SN/A * notice, this list of conditions and the following disclaimer in the 20955SN/A * documentation and/or other materials provided with the distribution; 21955SN/A * neither the name of the copyright holders nor the names of its 22955SN/A * contributors may be used to endorse or promote products derived from 23955SN/A * this software without specific prior written permission. 24955SN/A * 25955SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26955SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27955SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 282665Ssaidi@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 292665Ssaidi@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30955SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31955SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32955SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33955SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34955SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 352632Sstever@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 362632Sstever@eecs.umich.edu * 372632Sstever@eecs.umich.edu * Authors: Matt Evans 382632Sstever@eecs.umich.edu */ 39955SN/A 402632Sstever@eecs.umich.edu#include "dev/arm/vgic.hh" 412632Sstever@eecs.umich.edu 422761Sstever@eecs.umich.edu#include "base/trace.hh" 432632Sstever@eecs.umich.edu#include "debug/Checkpoint.hh" 442632Sstever@eecs.umich.edu#include "debug/VGIC.hh" 452632Sstever@eecs.umich.edu#include "dev/arm/base_gic.hh" 462761Sstever@eecs.umich.edu#include "mem/packet.hh" 472761Sstever@eecs.umich.edu#include "mem/packet_access.hh" 482761Sstever@eecs.umich.edu 492632Sstever@eecs.umich.eduVGic::VGic(const Params *p) 502632Sstever@eecs.umich.edu : PioDevice(p), platform(p->platform), gic(p->gic), vcpuAddr(p->vcpu_addr), 512761Sstever@eecs.umich.edu hvAddr(p->hv_addr), pioDelay(p->pio_delay), 522761Sstever@eecs.umich.edu maintInt(p->ppint) 532761Sstever@eecs.umich.edu{ 542761Sstever@eecs.umich.edu for (int x = 0; x < VGIC_CPU_MAX; x++) { 552761Sstever@eecs.umich.edu postVIntEvent[x] = new EventFunctionWrapper( 562632Sstever@eecs.umich.edu [this, x]{ processPostVIntEvent(x); }, 572632Sstever@eecs.umich.edu "Post VInterrupt to CPU"); 582632Sstever@eecs.umich.edu maintIntPosted[x] = false; 592632Sstever@eecs.umich.edu vIntPosted[x] = false; 602632Sstever@eecs.umich.edu } 612632Sstever@eecs.umich.edu assert(sys->numRunningContexts() <= VGIC_CPU_MAX); 622632Sstever@eecs.umich.edu} 63955SN/A 64955SN/AVGic::~VGic() 65955SN/A{ 66955SN/A for (int x = 0; x < VGIC_CPU_MAX; x++) 67955SN/A delete postVIntEvent[x]; 68955SN/A} 69955SN/A 702656Sstever@eecs.umich.eduTick 712656Sstever@eecs.umich.eduVGic::read(PacketPtr pkt) 722656Sstever@eecs.umich.edu{ 732656Sstever@eecs.umich.edu Addr addr = pkt->getAddr(); 742656Sstever@eecs.umich.edu 752656Sstever@eecs.umich.edu if (addr >= vcpuAddr && addr < vcpuAddr + GICV_SIZE) 762656Sstever@eecs.umich.edu return readVCpu(pkt); 772653Sstever@eecs.umich.edu else if (addr >= hvAddr && addr < hvAddr + GICH_REG_SIZE) 782653Sstever@eecs.umich.edu return readCtrl(pkt); 792653Sstever@eecs.umich.edu else 802653Sstever@eecs.umich.edu panic("Read to unknown address %#x\n", pkt->getAddr()); 812653Sstever@eecs.umich.edu} 822653Sstever@eecs.umich.edu 832653Sstever@eecs.umich.eduTick 842653Sstever@eecs.umich.eduVGic::write(PacketPtr pkt) 852653Sstever@eecs.umich.edu{ 862653Sstever@eecs.umich.edu Addr addr = pkt->getAddr(); 872653Sstever@eecs.umich.edu 881852SN/A if (addr >= vcpuAddr && addr < vcpuAddr + GICV_SIZE) 89955SN/A return writeVCpu(pkt); 90955SN/A else if (addr >= hvAddr && addr < hvAddr + GICH_REG_SIZE) 91955SN/A return writeCtrl(pkt); 922632Sstever@eecs.umich.edu else 932632Sstever@eecs.umich.edu panic("Write to unknown address %#x\n", pkt->getAddr()); 94955SN/A} 951533SN/A 962632Sstever@eecs.umich.eduTick 971533SN/AVGic::readVCpu(PacketPtr pkt) 98955SN/A{ 99955SN/A Addr daddr = pkt->getAddr() - vcpuAddr; 1002632Sstever@eecs.umich.edu 1012632Sstever@eecs.umich.edu ContextID ctx_id = pkt->req->contextId(); 102955SN/A assert(ctx_id < VGIC_CPU_MAX); 103955SN/A struct vcpuIntData *vid = &vcpuData[ctx_id]; 104955SN/A 105955SN/A DPRINTF(VGIC, "VGIC VCPU read register %#x\n", daddr); 1062632Sstever@eecs.umich.edu 107955SN/A switch (daddr) { 1082632Sstever@eecs.umich.edu case GICV_CTLR: 109955SN/A pkt->set<uint32_t>(vid->vctrl); 110955SN/A break; 1112632Sstever@eecs.umich.edu case GICV_IAR: { 1122632Sstever@eecs.umich.edu int i = findHighestPendingLR(vid); 1132632Sstever@eecs.umich.edu if (i < 0 || !vid->vctrl.En) { 1142632Sstever@eecs.umich.edu pkt->set<uint32_t>(1023); // "No int" marker 1152632Sstever@eecs.umich.edu } else { 1162632Sstever@eecs.umich.edu ListReg *lr = &vid->LR[i]; 1172632Sstever@eecs.umich.edu 1182632Sstever@eecs.umich.edu pkt->set<uint32_t>(lr->VirtualID | 1192632Sstever@eecs.umich.edu (((int)lr->CpuID) << 10)); 1202632Sstever@eecs.umich.edu // We don't support auto-EOI of HW interrupts via real GIC! 1212632Sstever@eecs.umich.edu // Fortunately, KVM doesn't use this. How about Xen...? Ulp! 1222632Sstever@eecs.umich.edu if (lr->HW) 1232632Sstever@eecs.umich.edu panic("VGIC does not support 'HW' List Register feature (LR %#x)!\n", 1242632Sstever@eecs.umich.edu *lr); 1252632Sstever@eecs.umich.edu lr->State = LR_ACTIVE; 1262632Sstever@eecs.umich.edu DPRINTF(VGIC, "Consumed interrupt %d (cpu%d) from LR%d (EOI%d)\n", 1272632Sstever@eecs.umich.edu lr->VirtualID, lr->CpuID, i, lr->EOI); 1282634Sstever@eecs.umich.edu } 1292634Sstever@eecs.umich.edu } break; 1302632Sstever@eecs.umich.edu default: 1312638Sstever@eecs.umich.edu panic("VGIC VCPU read of bad address %#x\n", daddr); 1322632Sstever@eecs.umich.edu } 1332632Sstever@eecs.umich.edu 1342632Sstever@eecs.umich.edu updateIntState(ctx_id); 1352632Sstever@eecs.umich.edu 1362632Sstever@eecs.umich.edu pkt->makeAtomicResponse(); 1372632Sstever@eecs.umich.edu return pioDelay; 1381858SN/A} 1392638Sstever@eecs.umich.edu 1402638Sstever@eecs.umich.eduTick 1412638Sstever@eecs.umich.eduVGic::readCtrl(PacketPtr pkt) 1422638Sstever@eecs.umich.edu{ 1432638Sstever@eecs.umich.edu Addr daddr = pkt->getAddr() - hvAddr; 1442638Sstever@eecs.umich.edu 1452638Sstever@eecs.umich.edu ContextID ctx_id = pkt->req->contextId(); 1462638Sstever@eecs.umich.edu 1472634Sstever@eecs.umich.edu DPRINTF(VGIC, "VGIC HVCtrl read register %#x\n", daddr); 1482634Sstever@eecs.umich.edu 1492634Sstever@eecs.umich.edu /* Munge the address: 0-0xfff is the usual space banked by requester CPU. 150955SN/A * Anything > that is 0x200-sized slices of 'per CPU' regs. 151955SN/A */ 152955SN/A if (daddr & ~0x1ff) { 153955SN/A ctx_id = (daddr >> 9); 154955SN/A if (ctx_id > 8) 155955SN/A panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr); 156955SN/A daddr &= ~0x1ff; 157955SN/A } 1581858SN/A assert(ctx_id < VGIC_CPU_MAX); 1591858SN/A struct vcpuIntData *vid = &vcpuData[ctx_id]; 1602632Sstever@eecs.umich.edu 161955SN/A switch (daddr) { 1622776Sstever@eecs.umich.edu case GICH_HCR: 1631105SN/A pkt->set<uint32_t>(vid->hcr); 1642667Sstever@eecs.umich.edu break; 1652667Sstever@eecs.umich.edu 1662667Sstever@eecs.umich.edu case GICH_VTR: 1672667Sstever@eecs.umich.edu pkt->set<uint32_t>(0x44000000 | (NUM_LR - 1)); 1682667Sstever@eecs.umich.edu break; 1692667Sstever@eecs.umich.edu 1701869SN/A case GICH_VMCR: 1711869SN/A pkt->set<uint32_t>( 1721869SN/A ((uint32_t)vid->VMPriMask << 27) | 1731869SN/A ((uint32_t)vid->VMBP << 21) | 1741869SN/A ((uint32_t)vid->VMABP << 18) | 1751065SN/A ((uint32_t)vid->VEM << 9) | 1762632Sstever@eecs.umich.edu ((uint32_t)vid->VMCBPR << 4) | 1772632Sstever@eecs.umich.edu ((uint32_t)vid->VMFiqEn << 3) | 178955SN/A ((uint32_t)vid->VMAckCtl << 2) | 1791858SN/A ((uint32_t)vid->VMGrp1En << 1) | 1801858SN/A ((uint32_t)vid->VMGrp0En << 0) 1811858SN/A ); 1821858SN/A break; 1831851SN/A 1841851SN/A case GICH_MISR: 1851858SN/A pkt->set<uint32_t>(getMISR(vid)); 1862632Sstever@eecs.umich.edu break; 187955SN/A 1882656Sstever@eecs.umich.edu case GICH_EISR0: 1892656Sstever@eecs.umich.edu pkt->set<uint32_t>(vid->eisr & 0xffffffff); 1902656Sstever@eecs.umich.edu break; 1912656Sstever@eecs.umich.edu 1922656Sstever@eecs.umich.edu case GICH_EISR1: 1932656Sstever@eecs.umich.edu pkt->set<uint32_t>(vid->eisr >> 32); 1942656Sstever@eecs.umich.edu break; 1952656Sstever@eecs.umich.edu 1962656Sstever@eecs.umich.edu case GICH_ELSR0: { 1972656Sstever@eecs.umich.edu uint32_t bm = 0; 1982656Sstever@eecs.umich.edu for (int i = 0; i < ((NUM_LR < 32) ? NUM_LR : 32); i++) { 1992656Sstever@eecs.umich.edu if (!vid->LR[i].State) 2002656Sstever@eecs.umich.edu bm |= 1 << i; 2012656Sstever@eecs.umich.edu } 2022656Sstever@eecs.umich.edu pkt->set<uint32_t>(bm); 2032656Sstever@eecs.umich.edu } break; 2042655Sstever@eecs.umich.edu 2052667Sstever@eecs.umich.edu case GICH_ELSR1: { 2062667Sstever@eecs.umich.edu uint32_t bm = 0; 2072667Sstever@eecs.umich.edu for (int i = 32; i < NUM_LR; i++) { 2082667Sstever@eecs.umich.edu if (!vid->LR[i].State) 2092667Sstever@eecs.umich.edu bm |= 1 << (i-32); 2102667Sstever@eecs.umich.edu } 2112667Sstever@eecs.umich.edu pkt->set<uint32_t>(bm); 2122667Sstever@eecs.umich.edu } break; 2132667Sstever@eecs.umich.edu 2142667Sstever@eecs.umich.edu case GICH_APR0: 2152667Sstever@eecs.umich.edu warn_once("VGIC GICH_APR read!\n"); 2162667Sstever@eecs.umich.edu pkt->set<uint32_t>(0); 2172667Sstever@eecs.umich.edu break; 2182655Sstever@eecs.umich.edu 2191858SN/A case GICH_LR0: 2201858SN/A case GICH_LR1: 2212638Sstever@eecs.umich.edu case GICH_LR2: 2222638Sstever@eecs.umich.edu case GICH_LR3: 2232638Sstever@eecs.umich.edu pkt->set<uint32_t>(vid->LR[(daddr - GICH_LR0) >> 2]); 2242638Sstever@eecs.umich.edu break; 2252638Sstever@eecs.umich.edu 2261858SN/A default: 2271858SN/A panic("VGIC HVCtrl read of bad address %#x\n", daddr); 2281858SN/A } 2291858SN/A 2301858SN/A pkt->makeAtomicResponse(); 2311858SN/A return pioDelay; 2321858SN/A} 2331859SN/A 2341858SN/ATick 2351858SN/AVGic::writeVCpu(PacketPtr pkt) 2361858SN/A{ 2371859SN/A Addr daddr = pkt->getAddr() - vcpuAddr; 2381859SN/A 2391862SN/A ContextID ctx_id = pkt->req->contextId(); 2401862SN/A assert(ctx_id < VGIC_CPU_MAX); 2411862SN/A struct vcpuIntData *vid = &vcpuData[ctx_id]; 2421862SN/A 2431859SN/A DPRINTF(VGIC, "VGIC VCPU write register %#x <= %#x\n", daddr, pkt->get<uint32_t>()); 2441859SN/A 2451963SN/A switch (daddr) { 2461963SN/A case GICV_CTLR: 2471859SN/A vid->vctrl = pkt->get<uint32_t>(); 2481859SN/A break; 2491859SN/A case GICV_PMR: 2501859SN/A vid->VMPriMask = pkt->get<uint32_t>(); 2511859SN/A break; 2521859SN/A case GICV_EOIR: { 2531859SN/A // We don't handle the split EOI-then-DIR mode. Linux (guest) 2541859SN/A // doesn't need it though. 2551862SN/A assert(!vid->vctrl.EOImode); 2561859SN/A uint32_t w = pkt->get<uint32_t>(); 2571859SN/A unsigned int virq = w & 0x3ff; 2581859SN/A unsigned int vcpu = (w >> 10) & 7; 2591858SN/A int i = findLRForVIRQ(vid, virq, vcpu); 2601858SN/A if (i < 0) { 2612139SN/A DPRINTF(VGIC, "EOIR: No LR for irq %d(cpu%d)\n", virq, vcpu); 2622139SN/A } else { 2632139SN/A DPRINTF(VGIC, "EOIR: Found LR%d for irq %d(cpu%d)\n", i, virq, vcpu); 2642155SN/A ListReg *lr = &vid->LR[i]; 2652623SN/A lr->State = 0; 2662817Sksewell@umich.edu // Maintenance interrupt -- via eisr -- is flagged when 2672792Sktlim@umich.edu // LRs have EOI=1 and State=INVALID! 2682155SN/A } 2691869SN/A } break; 2701869SN/A default: 2711869SN/A panic("VGIC VCPU write %#x to unk address %#x\n", pkt->get<uint32_t>(), daddr); 2721869SN/A } 2731869SN/A 2742139SN/A // This updates the EISRs and flags IRQs: 2751869SN/A updateIntState(ctx_id); 2762508SN/A 2772508SN/A pkt->makeAtomicResponse(); 2782508SN/A return pioDelay; 2792508SN/A} 2802635Sstever@eecs.umich.edu 2812635Sstever@eecs.umich.eduTick 2821869SN/AVGic::writeCtrl(PacketPtr pkt) 2831869SN/A{ 2841869SN/A Addr daddr = pkt->getAddr() - hvAddr; 2851869SN/A 2861869SN/A ContextID ctx_id = pkt->req->contextId(); 2871869SN/A 2881869SN/A DPRINTF(VGIC, "VGIC HVCtrl write register %#x <= %#x\n", daddr, pkt->get<uint32_t>()); 2891869SN/A 2901965SN/A /* Munge the address: 0-0xfff is the usual space banked by requester CPU. 2911965SN/A * Anything > that is 0x200-sized slices of 'per CPU' regs. 2921965SN/A */ 2931869SN/A if (daddr & ~0x1ff) { 2941869SN/A ctx_id = (daddr >> 9); 2952733Sktlim@umich.edu if (ctx_id > 8) 2961869SN/A panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr); 2971884SN/A daddr &= ~0x1ff; 2981884SN/A } 2991884SN/A assert(ctx_id < VGIC_CPU_MAX); 3001869SN/A struct vcpuIntData *vid = &vcpuData[ctx_id]; 3011858SN/A 3021869SN/A switch (daddr) { 3031869SN/A case GICH_HCR: 3041869SN/A vid->hcr = pkt->get<uint32_t>(); 3052953Sktlim@umich.edu // update int state 3062953Sktlim@umich.edu break; 3071869SN/A 3081869SN/A case GICH_VMCR: { 3091858SN/A uint32_t d = pkt->get<uint32_t>(); 3102761Sstever@eecs.umich.edu vid->VMPriMask = d >> 27; 3111869SN/A vid->VMBP = (d >> 21) & 7; 3122733Sktlim@umich.edu vid->VMABP = (d >> 18) & 7; 3132733Sktlim@umich.edu vid->VEM = (d >> 9) & 1; 3141869SN/A vid->VMCBPR = (d >> 4) & 1; 3151869SN/A vid->VMFiqEn = (d >> 3) & 1; 3161869SN/A vid->VMAckCtl = (d >> 2) & 1; 3171869SN/A vid->VMGrp1En = (d >> 1) & 1; 3181869SN/A vid->VMGrp0En = d & 1; 3191869SN/A } break; 3201858SN/A 321955SN/A case GICH_APR0: 322955SN/A warn_once("VGIC GICH_APR0 written, ignored\n"); 3231869SN/A break; 3241869SN/A 3251869SN/A case GICH_LR0: 3261869SN/A case GICH_LR1: 3271869SN/A case GICH_LR2: 3281869SN/A case GICH_LR3: 3291869SN/A vid->LR[(daddr - GICH_LR0) >> 2] = pkt->get<uint32_t>(); 3301869SN/A // update int state 3311869SN/A break; 3321869SN/A 3331869SN/A default: 3341869SN/A panic("VGIC HVCtrl write to bad address %#x\n", daddr); 3351869SN/A } 3361869SN/A 3371869SN/A updateIntState(ctx_id); 3381869SN/A 3391869SN/A pkt->makeAtomicResponse(); 3401869SN/A return pioDelay; 3411869SN/A} 3421869SN/A 3431869SN/A 3441869SN/Auint32_t 3451869SN/AVGic::getMISR(struct vcpuIntData *vid) 3461869SN/A{ 3471869SN/A return (!!vid->hcr.VGrp1DIE && !vid->VMGrp1En ? 0x80 : 0) | 3481869SN/A (!!vid->hcr.VGrp1EIE && vid->VMGrp1En ? 0x40 : 0) | 3491869SN/A (!!vid->hcr.VGrp0DIE && !vid->VMGrp0En ? 0x20 : 0) | 3501869SN/A (!!vid->hcr.VGrp0EIE && vid->VMGrp0En ? 0x10 : 0) | 3511869SN/A (!!vid->hcr.NPIE && !lrPending(vid) ? 0x08 : 0) | 3521869SN/A (!!vid->hcr.LRENPIE && vid->hcr.EOICount ? 0x04 : 0) | 3531869SN/A (!!vid->hcr.UIE && lrValid(vid) <= 1 ? 0x02 : 0) | 3541869SN/A (vid->eisr ? 0x01 : 0); 3551869SN/A} 3561869SN/A 3571869SN/Avoid 3581869SN/AVGic::postVInt(uint32_t cpu, Tick when) 3591869SN/A{ 3601869SN/A DPRINTF(VGIC, "Posting VIRQ to %d\n", cpu); 3611869SN/A if (!(postVIntEvent[cpu]->scheduled())) 3622655Sstever@eecs.umich.edu eventq->schedule(postVIntEvent[cpu], when); 3632655Sstever@eecs.umich.edu} 3642655Sstever@eecs.umich.edu 3652655Sstever@eecs.umich.eduvoid 3662655Sstever@eecs.umich.eduVGic::unPostVInt(uint32_t cpu) 3672655Sstever@eecs.umich.edu{ 3682655Sstever@eecs.umich.edu DPRINTF(VGIC, "Unposting VIRQ to %d\n", cpu); 3692655Sstever@eecs.umich.edu platform->intrctrl->clear(cpu, ArmISA::INT_VIRT_IRQ, 0); 3702655Sstever@eecs.umich.edu} 3712655Sstever@eecs.umich.edu 3722655Sstever@eecs.umich.eduvoid 3732655Sstever@eecs.umich.eduVGic::processPostVIntEvent(uint32_t cpu) 3742655Sstever@eecs.umich.edu{ 3752655Sstever@eecs.umich.edu platform->intrctrl->post(cpu, ArmISA::INT_VIRT_IRQ, 0); 3762655Sstever@eecs.umich.edu} 3772655Sstever@eecs.umich.edu 3782655Sstever@eecs.umich.edu 3792655Sstever@eecs.umich.eduvoid 3802655Sstever@eecs.umich.eduVGic::postMaintInt(uint32_t cpu) 3812655Sstever@eecs.umich.edu{ 3822655Sstever@eecs.umich.edu DPRINTF(VGIC, "Posting maintenance PPI to GIC/cpu%d\n", cpu); 3832655Sstever@eecs.umich.edu // Linux DT configures this as Level. 3842655Sstever@eecs.umich.edu gic->sendPPInt(maintInt, cpu); 3852655Sstever@eecs.umich.edu} 3862655Sstever@eecs.umich.edu 3872655Sstever@eecs.umich.eduvoid 3882634Sstever@eecs.umich.eduVGic::unPostMaintInt(uint32_t cpu) 3892634Sstever@eecs.umich.edu{ 3902634Sstever@eecs.umich.edu DPRINTF(VGIC, "Unposting maintenance PPI to GIC/cpu%d\n", cpu); 3912634Sstever@eecs.umich.edu gic->clearPPInt(maintInt, cpu); 3922634Sstever@eecs.umich.edu} 3932634Sstever@eecs.umich.edu 3942638Sstever@eecs.umich.edu/* Update state (in general); something concerned with ctx_id has changed. 3952638Sstever@eecs.umich.edu * This may raise a maintenance interrupt. 3962638Sstever@eecs.umich.edu */ 3972638Sstever@eecs.umich.eduvoid 3982638Sstever@eecs.umich.eduVGic::updateIntState(ContextID ctx_id) 3991869SN/A{ 4001869SN/A // @todo This should update APRs! 401955SN/A 402955SN/A // Build EISR contents: 403955SN/A // (Cached so that regs can read them without messing about again) 404955SN/A struct vcpuIntData *tvid = &vcpuData[ctx_id]; 4051858SN/A 4061858SN/A tvid->eisr = 0; 4071858SN/A for (int i = 0; i < NUM_LR; i++) { 4082632Sstever@eecs.umich.edu if (!tvid->LR[i].State && tvid->LR[i].EOI) { 4092632Sstever@eecs.umich.edu tvid->eisr |= 1 << i; 4102632Sstever@eecs.umich.edu } 4112632Sstever@eecs.umich.edu } 4122632Sstever@eecs.umich.edu 4132634Sstever@eecs.umich.edu assert(sys->numRunningContexts() <= VGIC_CPU_MAX); 4142638Sstever@eecs.umich.edu for (int i = 0; i < sys->numRunningContexts(); i++) { 4152023SN/A struct vcpuIntData *vid = &vcpuData[i]; 4162632Sstever@eecs.umich.edu // Are any LRs active that weren't before? 4172632Sstever@eecs.umich.edu if (!vIntPosted[i]) { 4182632Sstever@eecs.umich.edu if (lrPending(vid) && vid->vctrl.En) { 4192632Sstever@eecs.umich.edu vIntPosted[i] = true; 4202632Sstever@eecs.umich.edu postVInt(i, curTick() + 1); 4212632Sstever@eecs.umich.edu } 4222632Sstever@eecs.umich.edu } else if (!lrPending(vid)) { 4232632Sstever@eecs.umich.edu vIntPosted[i] = false; 4242632Sstever@eecs.umich.edu unPostVInt(i); 4252632Sstever@eecs.umich.edu } 4262632Sstever@eecs.umich.edu 4272023SN/A // Any maintenance ints to send? 4282632Sstever@eecs.umich.edu if (!maintIntPosted[i]) { 4292632Sstever@eecs.umich.edu if (vid->hcr.En && getMISR(vid)) { 4301889SN/A maintIntPosted[i] = true; 4311889SN/A postMaintInt(i); 4322632Sstever@eecs.umich.edu } 4332632Sstever@eecs.umich.edu } else { 4342632Sstever@eecs.umich.edu if (!vid->hcr.En || !getMISR(vid)) { 4352632Sstever@eecs.umich.edu unPostMaintInt(i); 4362632Sstever@eecs.umich.edu maintIntPosted[i] = false; 4372632Sstever@eecs.umich.edu } 4382632Sstever@eecs.umich.edu } 4392632Sstever@eecs.umich.edu } 4402632Sstever@eecs.umich.edu} 4412632Sstever@eecs.umich.edu 4422632Sstever@eecs.umich.eduAddrRangeList 4432632Sstever@eecs.umich.eduVGic::getAddrRanges() const 4442632Sstever@eecs.umich.edu{ 4452632Sstever@eecs.umich.edu AddrRangeList ranges; 4461888SN/A ranges.push_back(RangeSize(hvAddr, GICH_REG_SIZE)); 4471888SN/A ranges.push_back(RangeSize(vcpuAddr, GICV_SIZE)); 4481869SN/A return ranges; 4491869SN/A} 4501858SN/A 4512598SN/Avoid 4522598SN/AVGic::serialize(CheckpointOut &cp) const 4532598SN/A{ 4542598SN/A Tick interrupt_time[VGIC_CPU_MAX]; 4552598SN/A for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) { 4561858SN/A interrupt_time[cpu] = 0; 4571858SN/A if (postVIntEvent[cpu]->scheduled()) { 4581858SN/A interrupt_time[cpu] = postVIntEvent[cpu]->when(); 4591858SN/A } 4601858SN/A } 4611858SN/A 4621858SN/A DPRINTF(Checkpoint, "Serializing VGIC\n"); 4631858SN/A 4641858SN/A SERIALIZE_ARRAY(interrupt_time, VGIC_CPU_MAX); 4651871SN/A SERIALIZE_ARRAY(maintIntPosted, VGIC_CPU_MAX); 4661858SN/A SERIALIZE_ARRAY(vIntPosted, VGIC_CPU_MAX); 4671858SN/A SERIALIZE_SCALAR(vcpuAddr); 4681858SN/A SERIALIZE_SCALAR(hvAddr); 4691858SN/A SERIALIZE_SCALAR(pioDelay); 4701858SN/A SERIALIZE_SCALAR(maintInt); 4711858SN/A 4721858SN/A for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) 4731858SN/A vcpuData[cpu].serializeSection(cp, csprintf("vcpuData%d", cpu)); 4741858SN/A} 4751858SN/A 4761858SN/Avoid 4771859SN/AVGic::vcpuIntData::serialize(CheckpointOut &cp) const 4781859SN/A{ 4791869SN/A uint32_t vctrl_val = vctrl; 4801888SN/A SERIALIZE_SCALAR(vctrl_val); 4812632Sstever@eecs.umich.edu uint32_t hcr_val = hcr; 4821869SN/A SERIALIZE_SCALAR(hcr_val); 4831884SN/A uint64_t eisr_val = eisr; 4841884SN/A SERIALIZE_SCALAR(eisr_val); 4851884SN/A uint8_t VMGrp0En_val = VMGrp0En; 4861884SN/A SERIALIZE_SCALAR(VMGrp0En_val); 4871884SN/A uint8_t VMGrp1En_val = VMGrp1En; 4881884SN/A SERIALIZE_SCALAR(VMGrp1En_val); 4891965SN/A uint8_t VMAckCtl_val = VMAckCtl; 4901965SN/A SERIALIZE_SCALAR(VMAckCtl_val); 4911965SN/A uint8_t VMFiqEn_val = VMFiqEn; 4922761Sstever@eecs.umich.edu SERIALIZE_SCALAR(VMFiqEn_val); 4931869SN/A uint8_t VMCBPR_val = VMCBPR; 4941869SN/A SERIALIZE_SCALAR(VMCBPR_val); 4952632Sstever@eecs.umich.edu uint8_t VEM_val = VEM; 4962667Sstever@eecs.umich.edu SERIALIZE_SCALAR(VEM_val); 4971869SN/A uint8_t VMABP_val = VMABP; 4981869SN/A SERIALIZE_SCALAR(VMABP_val); 4992929Sktlim@umich.edu uint8_t VMBP_val = VMBP; 5002929Sktlim@umich.edu SERIALIZE_SCALAR(VMBP_val); 5012929Sktlim@umich.edu uint8_t VMPriMask_val = VMPriMask; 5022929Sktlim@umich.edu SERIALIZE_SCALAR(VMPriMask_val); 503955SN/A 5042598SN/A for (int i = 0; i < NUM_LR; i++) { 5052598SN/A ScopedCheckpointSection sec_lr(cp, csprintf("LR%d", i)); 506955SN/A paramOut(cp, "lr", LR[i]); 507955SN/A } 508955SN/A} 5091530SN/A 510955SN/Avoid VGic::unserialize(CheckpointIn &cp) 511955SN/A{ 512955SN/A DPRINTF(Checkpoint, "Unserializing Arm GIC\n"); 513 514 Tick interrupt_time[VGIC_CPU_MAX]; 515 UNSERIALIZE_ARRAY(interrupt_time, VGIC_CPU_MAX); 516 for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) { 517 if (interrupt_time[cpu]) 518 schedule(postVIntEvent[cpu], interrupt_time[cpu]); 519 520 vcpuData[cpu].unserializeSection(cp, csprintf("vcpuData%d", cpu)); 521 } 522 UNSERIALIZE_ARRAY(maintIntPosted, VGIC_CPU_MAX); 523 UNSERIALIZE_ARRAY(vIntPosted, VGIC_CPU_MAX); 524 UNSERIALIZE_SCALAR(vcpuAddr); 525 UNSERIALIZE_SCALAR(hvAddr); 526 UNSERIALIZE_SCALAR(pioDelay); 527 UNSERIALIZE_SCALAR(maintInt); 528} 529 530void 531VGic::vcpuIntData::unserialize(CheckpointIn &cp) 532{ 533 paramIn(cp, "vctrl_val", vctrl); 534 paramIn(cp, "hcr_val", hcr); 535 paramIn(cp, "eisr_val", eisr); 536 paramIn(cp, "VMGrp0En_val", VMGrp0En); 537 paramIn(cp, "VMGrp1En_val", VMGrp1En); 538 paramIn(cp, "VMAckCtl_val", VMAckCtl); 539 paramIn(cp, "VMFiqEn_val", VMFiqEn); 540 paramIn(cp, "VMCBPR_val", VMCBPR); 541 paramIn(cp, "VEM_val", VEM); 542 paramIn(cp, "VMABP_val", VMABP); 543 paramIn(cp, "VMPriMask_val", VMPriMask); 544 545 for (int i = 0; i < NUM_LR; i++) { 546 ScopedCheckpointSection sec_lr(cp, csprintf("LR%d", i)); 547 paramIn(cp, "lr", LR[i]); 548 } 549} 550 551VGic * 552VGicParams::create() 553{ 554 return new VGic(this); 555} 556