/*
 * Copyright (c) 2013 ARM Limited
 * All rights reserved
 *
 * The license below extends only to copyright in the software and shall
 * not be construed as granting a license to any other intellectual
 * property including but not limited to intellectual property relating
 * to a hardware implementation of the functionality of the software
 * licensed hereunder.  You may use the software subject to the license
 * terms below provided that you ensure that this notice is replicated
 * unmodified and in its entirety in all distributions of the software,
 * modified or unmodified, in source code or in binary form.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Matt Evans
 */

#include "dev/arm/vgic.hh"

#include "base/trace.hh"
#include "debug/Checkpoint.hh"
#include "debug/VGIC.hh"
#include "dev/arm/base_gic.hh"
#include "dev/terminal.hh"
#include "mem/packet.hh"
#include "mem/packet_access.hh"

VGic::VGic(const Params *p)
    : PioDevice(p), platform(p->platform), gic(p->gic), vcpuAddr(p->vcpu_addr),
      hvAddr(p->hv_addr), pioDelay(p->pio_delay),
      maintInt(p->ppint)
{
    for (int x = 0; x < VGIC_CPU_MAX; x++) {
        postVIntEvent[x] = new PostVIntEvent(x, p->platform);
        maintIntPosted[x] = false;
        vIntPosted[x] = false;
    }
    assert(sys->numRunningContexts() <= VGIC_CPU_MAX);
}

Tick
VGic::read(PacketPtr pkt)
{
    Addr addr = pkt->getAddr();

    if (addr >= vcpuAddr && addr < vcpuAddr + GICV_SIZE)
        return readVCpu(pkt);
    else if (addr >= hvAddr && addr < hvAddr + GICH_REG_SIZE)
        return readCtrl(pkt);
    else
        panic("Read to unknown address %#x\n", pkt->getAddr());
}

Tick
VGic::write(PacketPtr pkt)
{
    Addr addr = pkt->getAddr();

    if (addr >= vcpuAddr && addr < vcpuAddr + GICV_SIZE)
        return writeVCpu(pkt);
    else if (addr >= hvAddr && addr < hvAddr + GICH_REG_SIZE)
        return writeCtrl(pkt);
    else
        panic("Write to unknown address %#x\n", pkt->getAddr());
}

Tick
VGic::readVCpu(PacketPtr pkt)
{
    Addr daddr = pkt->getAddr() - vcpuAddr;

    ContextID ctx_id = pkt->req->contextId();
    assert(ctx_id < VGIC_CPU_MAX);
    struct vcpuIntData *vid = &vcpuData[ctx_id];

    DPRINTF(VGIC, "VGIC VCPU read register %#x\n", daddr);

    switch (daddr) {
      case GICV_CTLR:
        pkt->set<uint32_t>(vid->vctrl);
        break;
      case GICV_IAR: {
          int i = findHighestPendingLR(vid);
          if (i < 0 || !vid->vctrl.En) {
              pkt->set<uint32_t>(1023); // "No int" marker
          } else {
              ListReg *lr = &vid->LR[i];

              pkt->set<uint32_t>(lr->VirtualID |
                                 (((int)lr->CpuID) << 10));
              // We don't support auto-EOI of HW interrupts via real GIC!
              // Fortunately, KVM doesn't use this.  How about Xen...? Ulp!
              if (lr->HW)
                  panic("VGIC does not support 'HW' List Register feature (LR %#x)!\n",
                        *lr);
              lr->State = LR_ACTIVE;
              DPRINTF(VGIC, "Consumed interrupt %d (cpu%d) from LR%d (EOI%d)\n",
                      lr->VirtualID, lr->CpuID, i, lr->EOI);
          }
      } break;
      default:
        panic("VGIC VCPU read of bad address %#x\n", daddr);
    }

    updateIntState(ctx_id);

    pkt->makeAtomicResponse();
    return pioDelay;
}

Tick
VGic::readCtrl(PacketPtr pkt)
{
    Addr daddr = pkt->getAddr() - hvAddr;

    ContextID ctx_id = pkt->req->contextId();

    DPRINTF(VGIC, "VGIC HVCtrl read register %#x\n", daddr);

    /* Munge the address: 0-0xfff is the usual space banked by requester CPU.
     * Anything > that is 0x200-sized slices of 'per CPU' regs.
     */
    if (daddr & ~0x1ff) {
        ctx_id = (daddr >> 9);
        if (ctx_id > 8)
            panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr);
        daddr &= ~0x1ff;
    }
    assert(ctx_id < VGIC_CPU_MAX);
    struct vcpuIntData *vid = &vcpuData[ctx_id];

    switch (daddr) {
      case GICH_HCR:
        pkt->set<uint32_t>(vid->hcr);
        break;

      case GICH_VTR:
        pkt->set<uint32_t>(0x44000000 | (NUM_LR - 1));
        break;

      case GICH_VMCR:
        pkt->set<uint32_t>(
            ((uint32_t)vid->VMPriMask << 27) |
            ((uint32_t)vid->VMBP << 21) |
            ((uint32_t)vid->VMABP << 18) |
            ((uint32_t)vid->VEM << 9) |
            ((uint32_t)vid->VMCBPR << 4) |
            ((uint32_t)vid->VMFiqEn << 3) |
            ((uint32_t)vid->VMAckCtl << 2) |
            ((uint32_t)vid->VMGrp1En << 1) |
            ((uint32_t)vid->VMGrp0En << 0)
            );
        break;

      case GICH_MISR:
        pkt->set<uint32_t>(getMISR(vid));
        break;

      case GICH_EISR0:
        pkt->set<uint32_t>(vid->eisr & 0xffffffff);
        break;

      case GICH_EISR1:
        pkt->set<uint32_t>(vid->eisr >> 32);
        break;

      case GICH_ELSR0: {
          uint32_t bm = 0;
          for (int i = 0; i < ((NUM_LR < 32) ? NUM_LR : 32); i++) {
              if (!vid->LR[i].State)
                  bm |= 1 << i;
          }
          pkt->set<uint32_t>(bm);
      } break;

      case GICH_ELSR1: {
          uint32_t bm = 0;
          for (int i = 32; i < NUM_LR; i++) {
              if (!vid->LR[i].State)
                  bm |= 1 << (i-32);
          }
          pkt->set<uint32_t>(bm);
      } break;

      case GICH_APR0:
        warn_once("VGIC GICH_APR read!\n");
        pkt->set<uint32_t>(0);
        break;

      case GICH_LR0:
      case GICH_LR1:
      case GICH_LR2:
      case GICH_LR3:
        pkt->set<uint32_t>(vid->LR[(daddr - GICH_LR0) >> 2]);
        break;

      default:
        panic("VGIC HVCtrl read of bad address %#x\n", daddr);
    }

    pkt->makeAtomicResponse();
    return pioDelay;
}

Tick
VGic::writeVCpu(PacketPtr pkt)
{
    Addr daddr = pkt->getAddr() - vcpuAddr;

    ContextID ctx_id = pkt->req->contextId();
    assert(ctx_id < VGIC_CPU_MAX);
    struct vcpuIntData *vid = &vcpuData[ctx_id];

    DPRINTF(VGIC, "VGIC VCPU write register %#x <= %#x\n", daddr, pkt->get<uint32_t>());

    switch (daddr) {
      case GICV_CTLR:
        vid->vctrl = pkt->get<uint32_t>();
        break;
      case GICV_PMR:
        vid->VMPriMask = pkt->get<uint32_t>();
        break;
      case GICV_EOIR: {
          // We don't handle the split EOI-then-DIR mode.  Linux (guest)
          // doesn't need it though.
          assert(!vid->vctrl.EOImode);
          uint32_t w = pkt->get<uint32_t>();
          unsigned int virq = w & 0x3ff;
          unsigned int vcpu = (w >> 10) & 7;
          int i = findLRForVIRQ(vid, virq, vcpu);
          if (i < 0) {
              DPRINTF(VGIC, "EOIR: No LR for irq %d(cpu%d)\n", virq, vcpu);
          } else {
              DPRINTF(VGIC, "EOIR: Found LR%d for irq %d(cpu%d)\n", i, virq, vcpu);
              ListReg *lr = &vid->LR[i];
              lr->State = 0;
              // Maintenance interrupt -- via eisr -- is flagged when
              // LRs have EOI=1 and State=INVALID!
          }
      } break;
      default:
        panic("VGIC VCPU write %#x to unk address %#x\n", pkt->get<uint32_t>(), daddr);
    }

    // This updates the EISRs and flags IRQs:
    updateIntState(ctx_id);

    pkt->makeAtomicResponse();
    return pioDelay;
}

Tick
VGic::writeCtrl(PacketPtr pkt)
{
    Addr daddr = pkt->getAddr() - hvAddr;

    ContextID ctx_id = pkt->req->contextId();

    DPRINTF(VGIC, "VGIC HVCtrl write register %#x <= %#x\n", daddr, pkt->get<uint32_t>());

    /* Munge the address: 0-0xfff is the usual space banked by requester CPU.
     * Anything > that is 0x200-sized slices of 'per CPU' regs.
     */
    if (daddr & ~0x1ff) {
        ctx_id = (daddr >> 9);
        if (ctx_id > 8)
            panic("VGIC: Weird unbanked hv ctrl address %#x!\n", daddr);
        daddr &= ~0x1ff;
    }
    assert(ctx_id < VGIC_CPU_MAX);
    struct vcpuIntData *vid = &vcpuData[ctx_id];

    switch (daddr) {
      case GICH_HCR:
        vid->hcr = pkt->get<uint32_t>();
        // update int state
        break;

      case GICH_VMCR: {
          uint32_t d = pkt->get<uint32_t>();
          vid->VMPriMask = d >> 27;
          vid->VMBP = (d >> 21) & 7;
          vid->VMABP = (d >> 18) & 7;
          vid->VEM = (d >> 9) & 1;
          vid->VMCBPR = (d >> 4) & 1;
          vid->VMFiqEn = (d >> 3) & 1;
          vid->VMAckCtl = (d >> 2) & 1;
          vid->VMGrp1En = (d >> 1) & 1;
          vid->VMGrp0En = d & 1;
      } break;

      case GICH_APR0:
        warn_once("VGIC GICH_APR0 written, ignored\n");
        break;

      case GICH_LR0:
      case GICH_LR1:
      case GICH_LR2:
      case GICH_LR3:
        vid->LR[(daddr - GICH_LR0) >> 2] = pkt->get<uint32_t>();
        // update int state
        break;

      default:
        panic("VGIC HVCtrl write to bad address %#x\n", daddr);
    }

    updateIntState(ctx_id);

    pkt->makeAtomicResponse();
    return pioDelay;
}


uint32_t
VGic::getMISR(struct vcpuIntData *vid)
{
    return (!!vid->hcr.VGrp1DIE && !vid->VMGrp1En ? 0x80 : 0) |
        (!!vid->hcr.VGrp1EIE &&  vid->VMGrp1En ? 0x40 : 0) |
        (!!vid->hcr.VGrp0DIE && !vid->VMGrp0En ? 0x20 : 0) |
        (!!vid->hcr.VGrp0EIE &&  vid->VMGrp0En ? 0x10 : 0) |
        (!!vid->hcr.NPIE && !lrPending(vid) ? 0x08 : 0) |
        (!!vid->hcr.LRENPIE && vid->hcr.EOICount ? 0x04 : 0) |
        (!!vid->hcr.UIE && lrValid(vid) <= 1 ? 0x02 : 0) |
        (vid->eisr ? 0x01 : 0);
}

void
VGic::postVInt(uint32_t cpu, Tick when)
{
    DPRINTF(VGIC, "Posting VIRQ to %d\n", cpu);
    if (!(postVIntEvent[cpu]->scheduled()))
        eventq->schedule(postVIntEvent[cpu], when);
}

void
VGic::unPostVInt(uint32_t cpu)
{
    DPRINTF(VGIC, "Unposting VIRQ to %d\n", cpu);
    platform->intrctrl->clear(cpu, ArmISA::INT_VIRT_IRQ, 0);
}

void
VGic::postMaintInt(uint32_t cpu)
{
    DPRINTF(VGIC, "Posting maintenance PPI to GIC/cpu%d\n", cpu);
    // Linux DT configures this as Level.
    gic->sendPPInt(maintInt, cpu);
}

void
VGic::unPostMaintInt(uint32_t cpu)
{
    DPRINTF(VGIC, "Unposting maintenance PPI to GIC/cpu%d\n", cpu);
    gic->clearPPInt(maintInt, cpu);
}

/* Update state (in general); something concerned with ctx_id has changed.
 * This may raise a maintenance interrupt.
 */
void
VGic::updateIntState(ContextID ctx_id)
{
    // @todo This should update APRs!

    // Build EISR contents:
    // (Cached so that regs can read them without messing about again)
    struct vcpuIntData *tvid = &vcpuData[ctx_id];

    tvid->eisr = 0;
    for (int i = 0; i < NUM_LR; i++) {
        if (!tvid->LR[i].State && tvid->LR[i].EOI) {
            tvid->eisr |= 1 << i;
        }
    }

    assert(sys->numRunningContexts() <= VGIC_CPU_MAX);
    for (int i = 0; i < sys->numRunningContexts(); i++) {
        struct vcpuIntData *vid = &vcpuData[i];
        // Are any LRs active that weren't before?
        if (!vIntPosted[i]) {
            if (lrPending(vid) && vid->vctrl.En) {
                vIntPosted[i] = true;
                postVInt(i, curTick() + 1);
            }
        } else if (!lrPending(vid)) {
            vIntPosted[i] = false;
            unPostVInt(i);
        }

        // Any maintenance ints to send?
        if (!maintIntPosted[i]) {
            if (vid->hcr.En && getMISR(vid)) {
                maintIntPosted[i] = true;
                postMaintInt(i);
            }
        } else {
            if (!vid->hcr.En || !getMISR(vid)) {
                unPostMaintInt(i);
                maintIntPosted[i] = false;
            }
        }
    }
}

AddrRangeList
VGic::getAddrRanges() const
{
    AddrRangeList ranges;
    ranges.push_back(RangeSize(hvAddr, GICH_REG_SIZE));
    ranges.push_back(RangeSize(vcpuAddr, GICV_SIZE));
    return ranges;
}

void
VGic::serialize(CheckpointOut &cp) const
{
    Tick interrupt_time[VGIC_CPU_MAX];
    for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) {
        interrupt_time[cpu] = 0;
        if (postVIntEvent[cpu]->scheduled()) {
            interrupt_time[cpu] = postVIntEvent[cpu]->when();
        }
    }

    DPRINTF(Checkpoint, "Serializing VGIC\n");

    SERIALIZE_ARRAY(interrupt_time, VGIC_CPU_MAX);
    SERIALIZE_ARRAY(maintIntPosted, VGIC_CPU_MAX);
    SERIALIZE_ARRAY(vIntPosted, VGIC_CPU_MAX);
    SERIALIZE_SCALAR(vcpuAddr);
    SERIALIZE_SCALAR(hvAddr);
    SERIALIZE_SCALAR(pioDelay);
    SERIALIZE_SCALAR(maintInt);

    for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++)
        vcpuData[cpu].serializeSection(cp, csprintf("vcpuData%d", cpu));
}

void
VGic::vcpuIntData::serialize(CheckpointOut &cp) const
{
    uint32_t vctrl_val = vctrl;
    SERIALIZE_SCALAR(vctrl_val);
    uint32_t hcr_val = hcr;
    SERIALIZE_SCALAR(hcr_val);
    uint64_t eisr_val = eisr;
    SERIALIZE_SCALAR(eisr_val);
    uint8_t VMGrp0En_val = VMGrp0En;
    SERIALIZE_SCALAR(VMGrp0En_val);
    uint8_t VMGrp1En_val = VMGrp1En;
    SERIALIZE_SCALAR(VMGrp1En_val);
    uint8_t VMAckCtl_val = VMAckCtl;
    SERIALIZE_SCALAR(VMAckCtl_val);
    uint8_t VMFiqEn_val = VMFiqEn;
    SERIALIZE_SCALAR(VMFiqEn_val);
    uint8_t VMCBPR_val = VMCBPR;
    SERIALIZE_SCALAR(VMCBPR_val);
    uint8_t VEM_val = VEM;
    SERIALIZE_SCALAR(VEM_val);
    uint8_t VMABP_val = VMABP;
    SERIALIZE_SCALAR(VMABP_val);
    uint8_t VMBP_val = VMBP;
    SERIALIZE_SCALAR(VMBP_val);
    uint8_t VMPriMask_val = VMPriMask;
    SERIALIZE_SCALAR(VMPriMask_val);

    for (int i = 0; i < NUM_LR; i++) {
        ScopedCheckpointSection sec_lr(cp, csprintf("LR%d", i));
        paramOut(cp, "lr", LR[i]);
    }
}

void VGic::unserialize(CheckpointIn &cp)
{
    DPRINTF(Checkpoint, "Unserializing Arm GIC\n");

    Tick interrupt_time[VGIC_CPU_MAX];
    UNSERIALIZE_ARRAY(interrupt_time, VGIC_CPU_MAX);
    for (uint32_t cpu = 0; cpu < VGIC_CPU_MAX; cpu++) {
        if (interrupt_time[cpu])
            schedule(postVIntEvent[cpu], interrupt_time[cpu]);

        vcpuData[cpu].unserializeSection(cp, csprintf("vcpuData%d", cpu));
    }
    UNSERIALIZE_ARRAY(maintIntPosted, VGIC_CPU_MAX);
    UNSERIALIZE_ARRAY(vIntPosted, VGIC_CPU_MAX);
    UNSERIALIZE_SCALAR(vcpuAddr);
    UNSERIALIZE_SCALAR(hvAddr);
    UNSERIALIZE_SCALAR(pioDelay);
    UNSERIALIZE_SCALAR(maintInt);
}

void
VGic::vcpuIntData::unserialize(CheckpointIn &cp)
{
    paramIn(cp, "vctrl_val", vctrl);
    paramIn(cp, "hcr_val", hcr);
    paramIn(cp, "eisr_val", eisr);
    paramIn(cp, "VMGrp0En_val", VMGrp0En);
    paramIn(cp, "VMGrp1En_val", VMGrp1En);
    paramIn(cp, "VMAckCtl_val", VMAckCtl);
    paramIn(cp, "VMFiqEn_val", VMFiqEn);
    paramIn(cp, "VMCBPR_val", VMCBPR);
    paramIn(cp, "VEM_val", VEM);
    paramIn(cp, "VMABP_val", VMABP);
    paramIn(cp, "VMPriMask_val", VMPriMask);

    for (int i = 0; i < NUM_LR; i++) {
        ScopedCheckpointSection sec_lr(cp, csprintf("LR%d", i));
        paramIn(cp, "lr", LR[i]);
    }
}

VGic *
VGicParams::create()
{
    return new VGic(this);
}
