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