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