gic.cc revision 11840
12686Sksewell@umich.edu/*
22686Sksewell@umich.edu * Copyright (c) 2015-2017 ARM Limited
35268Sksewell@umich.edu * All rights reserved
45268Sksewell@umich.edu *
55268Sksewell@umich.edu * The license below extends only to copyright in the software and shall
65268Sksewell@umich.edu * not be construed as granting a license to any other intellectual
75268Sksewell@umich.edu * property including but not limited to intellectual property relating
85268Sksewell@umich.edu * to a hardware implementation of the functionality of the software
95268Sksewell@umich.edu * licensed hereunder.  You may use the software subject to the license
105268Sksewell@umich.edu * terms below provided that you ensure that this notice is replicated
115268Sksewell@umich.edu * unmodified and in its entirety in all distributions of the software,
125268Sksewell@umich.edu * modified or unmodified, in source code or in binary form.
135268Sksewell@umich.edu *
145268Sksewell@umich.edu * Redistribution and use in source and binary forms, with or without
155268Sksewell@umich.edu * modification, are permitted provided that the following conditions are
165268Sksewell@umich.edu * met: redistributions of source code must retain the above copyright
175268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer;
185268Sksewell@umich.edu * redistributions in binary form must reproduce the above copyright
195268Sksewell@umich.edu * notice, this list of conditions and the following disclaimer in the
205268Sksewell@umich.edu * documentation and/or other materials provided with the distribution;
215268Sksewell@umich.edu * neither the name of the copyright holders nor the names of its
225268Sksewell@umich.edu * contributors may be used to endorse or promote products derived from
235268Sksewell@umich.edu * this software without specific prior written permission.
245268Sksewell@umich.edu *
255268Sksewell@umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
265268Sksewell@umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
275268Sksewell@umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
285268Sksewell@umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
295268Sksewell@umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
302706Sksewell@umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
312686Sksewell@umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
322686Sksewell@umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
332686Sksewell@umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
342686Sksewell@umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
352686Sksewell@umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
362686Sksewell@umich.edu *
372686Sksewell@umich.edu * Authors: Andreas Sandberg
382741Sksewell@umich.edu *          Curtis Dunham
392686Sksewell@umich.edu */
404661Sksewell@umich.edu
412686Sksewell@umich.edu#include "arch/arm/kvm/gic.hh"
422686Sksewell@umich.edu
432686Sksewell@umich.edu#include <linux/kvm.h>
442686Sksewell@umich.edu
454661Sksewell@umich.edu#include "arch/arm/kvm/base_cpu.hh"
464661Sksewell@umich.edu#include "debug/Interrupt.hh"
472686Sksewell@umich.edu#include "params/KvmGic.hh"
482686Sksewell@umich.edu#include "params/MuxingKvmGic.hh"
492686Sksewell@umich.edu
504661Sksewell@umich.eduKvmKernelGicV2::KvmKernelGicV2(KvmVM &_vm, Addr cpu_addr, Addr dist_addr,
514661Sksewell@umich.edu                               unsigned it_lines)
524661Sksewell@umich.edu    : cpuRange(RangeSize(cpu_addr, KVM_VGIC_V2_CPU_SIZE)),
534661Sksewell@umich.edu      distRange(RangeSize(dist_addr, KVM_VGIC_V2_DIST_SIZE)),
544661Sksewell@umich.edu      vm(_vm),
554661Sksewell@umich.edu      kdev(vm.createDevice(KVM_DEV_TYPE_ARM_VGIC_V2))
564661Sksewell@umich.edu{
574661Sksewell@umich.edu    kdev.setAttr<uint64_t>(
584661Sksewell@umich.edu        KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST, dist_addr);
594661Sksewell@umich.edu    kdev.setAttr<uint64_t>(
604661Sksewell@umich.edu        KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_CPU, cpu_addr);
614661Sksewell@umich.edu
624661Sksewell@umich.edu    kdev.setAttr<uint32_t>(KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, it_lines);
634661Sksewell@umich.edu}
644661Sksewell@umich.edu
654661Sksewell@umich.eduKvmKernelGicV2::~KvmKernelGicV2()
664661Sksewell@umich.edu{
672686Sksewell@umich.edu}
682686Sksewell@umich.edu
692686Sksewell@umich.eduvoid
702686Sksewell@umich.eduKvmKernelGicV2::setSPI(unsigned spi)
714661Sksewell@umich.edu{
724661Sksewell@umich.edu    setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, true);
734661Sksewell@umich.edu}
744661Sksewell@umich.edu
755269Sksewell@umich.eduvoid
764661Sksewell@umich.eduKvmKernelGicV2::clearSPI(unsigned spi)
775269Sksewell@umich.edu{
784661Sksewell@umich.edu    setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, false);
794661Sksewell@umich.edu}
804661Sksewell@umich.edu
814661Sksewell@umich.eduvoid
824661Sksewell@umich.eduKvmKernelGicV2::setPPI(unsigned vcpu, unsigned ppi)
834661Sksewell@umich.edu{
844661Sksewell@umich.edu    setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, true);
854661Sksewell@umich.edu}
864661Sksewell@umich.edu
874661Sksewell@umich.eduvoid
884661Sksewell@umich.eduKvmKernelGicV2::clearPPI(unsigned vcpu, unsigned ppi)
894661Sksewell@umich.edu{
904661Sksewell@umich.edu    setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, false);
914661Sksewell@umich.edu}
924661Sksewell@umich.edu
934661Sksewell@umich.eduvoid
944661Sksewell@umich.eduKvmKernelGicV2::setIntState(unsigned type, unsigned vcpu, unsigned irq,
954661Sksewell@umich.edu                            bool high)
964661Sksewell@umich.edu{
974661Sksewell@umich.edu    assert(type <= KVM_ARM_IRQ_TYPE_MASK);
984661Sksewell@umich.edu    assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK);
995222Sksewell@umich.edu    assert(irq <= KVM_ARM_IRQ_NUM_MASK);
1004661Sksewell@umich.edu    const uint32_t line(
1014661Sksewell@umich.edu        (type << KVM_ARM_IRQ_TYPE_SHIFT) |
1024661Sksewell@umich.edu        (vcpu << KVM_ARM_IRQ_VCPU_SHIFT) |
1034661Sksewell@umich.edu        (irq << KVM_ARM_IRQ_NUM_SHIFT));
1044661Sksewell@umich.edu
1052686Sksewell@umich.edu    vm.setIRQLine(line, high);
1064661Sksewell@umich.edu}
1074661Sksewell@umich.edu
1084661Sksewell@umich.edu
1094661Sksewell@umich.eduKvmGic::KvmGic(const KvmGicParams *p)
1104661Sksewell@umich.edu    : BaseGic(p),
1114661Sksewell@umich.edu      system(*p->system),
1124661Sksewell@umich.edu      kernelGic(*system.getKvmVM(),
1134661Sksewell@umich.edu                p->cpu_addr, p->dist_addr, p->it_lines),
1144661Sksewell@umich.edu      addrRanges{kernelGic.distRange, kernelGic.cpuRange}
1154661Sksewell@umich.edu{
1164661Sksewell@umich.edu}
1174661Sksewell@umich.edu
1184661Sksewell@umich.eduKvmGic::~KvmGic()
1194661Sksewell@umich.edu{
1204661Sksewell@umich.edu}
1214661Sksewell@umich.edu
1224661Sksewell@umich.eduvoid
1234661Sksewell@umich.eduKvmGic::serialize(CheckpointOut &cp) const
1244661Sksewell@umich.edu{
1254661Sksewell@umich.edu    panic("Checkpointing unsupported\n");
1264661Sksewell@umich.edu}
1274661Sksewell@umich.edu
1284661Sksewell@umich.eduvoid
1294661Sksewell@umich.eduKvmGic::unserialize(CheckpointIn &cp)
1304661Sksewell@umich.edu{
1314661Sksewell@umich.edu    panic("Checkpointing unsupported\n");
1324661Sksewell@umich.edu}
1334661Sksewell@umich.edu
1344661Sksewell@umich.eduTick
1354661Sksewell@umich.eduKvmGic::read(PacketPtr pkt)
1364661Sksewell@umich.edu{
1374661Sksewell@umich.edu    panic("KvmGic: PIO from gem5 is currently unsupported\n");
1385222Sksewell@umich.edu}
1394661Sksewell@umich.edu
1404661Sksewell@umich.eduTick
1414661Sksewell@umich.eduKvmGic::write(PacketPtr pkt)
1424661Sksewell@umich.edu{
1434661Sksewell@umich.edu    panic("KvmGic: PIO from gem5 is currently unsupported\n");
1444661Sksewell@umich.edu}
1454661Sksewell@umich.edu
1464661Sksewell@umich.eduvoid
1472686Sksewell@umich.eduKvmGic::sendInt(uint32_t num)
1482686Sksewell@umich.edu{
1492686Sksewell@umich.edu    DPRINTF(Interrupt, "Set SPI %d\n", num);
1504661Sksewell@umich.edu    kernelGic.setSPI(num);
1512686Sksewell@umich.edu}
1522686Sksewell@umich.edu
1534661Sksewell@umich.eduvoid
1544661Sksewell@umich.eduKvmGic::clearInt(uint32_t num)
1554661Sksewell@umich.edu{
1562686Sksewell@umich.edu    DPRINTF(Interrupt, "Clear SPI %d\n", num);
1574661Sksewell@umich.edu    kernelGic.clearSPI(num);
1584661Sksewell@umich.edu}
1594661Sksewell@umich.edu
1604661Sksewell@umich.eduvoid
1614661Sksewell@umich.eduKvmGic::sendPPInt(uint32_t num, uint32_t cpu)
1624661Sksewell@umich.edu{
1634661Sksewell@umich.edu    DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num);
1644661Sksewell@umich.edu    kernelGic.setPPI(cpu, num);
1654661Sksewell@umich.edu}
1664661Sksewell@umich.edu
1674661Sksewell@umich.eduvoid
1685222Sksewell@umich.eduKvmGic::clearPPInt(uint32_t num, uint32_t cpu)
1694661Sksewell@umich.edu{
1704661Sksewell@umich.edu    DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num);
1714661Sksewell@umich.edu    kernelGic.clearPPI(cpu, num);
1724661Sksewell@umich.edu}
1734661Sksewell@umich.edu
1744661Sksewell@umich.eduvoid
1754661Sksewell@umich.eduKvmGic::verifyMemoryMode() const
1762686Sksewell@umich.edu{
1772686Sksewell@umich.edu    if (!(system.isAtomicMode() && system.bypassCaches())) {
1782686Sksewell@umich.edu        fatal("The in-kernel KVM GIC can only be used with KVM CPUs, but the "
1792686Sksewell@umich.edu              "current memory mode does not support KVM.\n");
1804661Sksewell@umich.edu    }
1814661Sksewell@umich.edu}
1824661Sksewell@umich.edu
1834661Sksewell@umich.edu
1844661Sksewell@umich.eduKvmGic *
1854661Sksewell@umich.eduKvmGicParams::create()
1864661Sksewell@umich.edu{
1874661Sksewell@umich.edu    return new KvmGic(this);
1884661Sksewell@umich.edu}
1894661Sksewell@umich.edu
1904661Sksewell@umich.edu
1912686Sksewell@umich.eduMuxingKvmGic::MuxingKvmGic(const MuxingKvmGicParams *p)
1922686Sksewell@umich.edu    : Pl390(p),
1932686Sksewell@umich.edu      system(*p->system),
1944661Sksewell@umich.edu      kernelGic(nullptr),
1952686Sksewell@umich.edu      usingKvm(false)
1964661Sksewell@umich.edu{
1974661Sksewell@umich.edu    if (auto vm = system.getKvmVM()) {
1984661Sksewell@umich.edu        kernelGic = new KvmKernelGicV2(*vm, p->cpu_addr, p->dist_addr,
1994661Sksewell@umich.edu                                       p->it_lines);
2004661Sksewell@umich.edu    }
2014661Sksewell@umich.edu}
2024661Sksewell@umich.edu
2034661Sksewell@umich.eduMuxingKvmGic::~MuxingKvmGic()
2044661Sksewell@umich.edu{
2054661Sksewell@umich.edu}
2064661Sksewell@umich.edu
2074661Sksewell@umich.eduvoid
2084661Sksewell@umich.eduMuxingKvmGic::startup()
2094661Sksewell@umich.edu{
2104661Sksewell@umich.edu    usingKvm = (kernelGic != nullptr) && validKvmEnvironment();
2114661Sksewell@umich.edu}
2124661Sksewell@umich.edu
2134661Sksewell@umich.eduvoid
2144661Sksewell@umich.eduMuxingKvmGic::drainResume()
2154661Sksewell@umich.edu{
2164661Sksewell@umich.edu    bool use_kvm = (kernelGic != nullptr) && validKvmEnvironment();
2174661Sksewell@umich.edu    if (use_kvm != usingKvm) {
2184661Sksewell@umich.edu        if (use_kvm) // from simulation to KVM emulation
2194661Sksewell@umich.edu            fromPl390ToKvm();
2204661Sksewell@umich.edu        else // from KVM emulation to simulation
2214661Sksewell@umich.edu            fromKvmToPl390();
222
223        usingKvm = use_kvm;
224    }
225}
226
227void
228MuxingKvmGic::serialize(CheckpointOut &cp) const
229{
230    if (!usingKvm)
231        return Pl390::serialize(cp);
232
233    panic("Checkpointing unsupported\n");
234}
235
236void
237MuxingKvmGic::unserialize(CheckpointIn &cp)
238{
239    if (!usingKvm)
240        return Pl390::unserialize(cp);
241
242    panic("Checkpointing unsupported\n");
243}
244
245Tick
246MuxingKvmGic::read(PacketPtr pkt)
247{
248    if (!usingKvm)
249        return Pl390::read(pkt);
250
251    panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n");
252}
253
254Tick
255MuxingKvmGic::write(PacketPtr pkt)
256{
257    if (!usingKvm)
258        return Pl390::write(pkt);
259
260    panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n");
261}
262
263void
264MuxingKvmGic::sendInt(uint32_t num)
265{
266    if (!usingKvm)
267        return Pl390::sendInt(num);
268
269    DPRINTF(Interrupt, "Set SPI %d\n", num);
270    kernelGic->setSPI(num);
271}
272
273void
274MuxingKvmGic::clearInt(uint32_t num)
275{
276    if (!usingKvm)
277        return Pl390::clearInt(num);
278
279    DPRINTF(Interrupt, "Clear SPI %d\n", num);
280    kernelGic->clearSPI(num);
281}
282
283void
284MuxingKvmGic::sendPPInt(uint32_t num, uint32_t cpu)
285{
286    if (!usingKvm)
287        return Pl390::sendPPInt(num, cpu);
288    DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num);
289    kernelGic->setPPI(cpu, num);
290}
291
292void
293MuxingKvmGic::clearPPInt(uint32_t num, uint32_t cpu)
294{
295    if (!usingKvm)
296        return Pl390::clearPPInt(num, cpu);
297
298    DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num);
299    kernelGic->clearPPI(cpu, num);
300}
301
302bool
303MuxingKvmGic::validKvmEnvironment() const
304{
305    if (system.threadContexts.empty())
306        return false;
307
308    for (auto tc : system.threadContexts) {
309        if (dynamic_cast<BaseArmKvmCPU*>(tc->getCpuPtr()) == nullptr) {
310            return false;
311        }
312    }
313    return true;
314}
315
316void
317MuxingKvmGic::fromPl390ToKvm()
318{
319    panic("Gic multiplexing not implemented.\n");
320}
321
322void
323MuxingKvmGic::fromKvmToPl390()
324{
325    panic("Gic multiplexing not implemented.\n");
326}
327
328MuxingKvmGic *
329MuxingKvmGicParams::create()
330{
331    return new MuxingKvmGic(this);
332}
333