gic.cc revision 12111:ec02ad5ff091
17753SWilliam.Wang@arm.com/* 27753SWilliam.Wang@arm.com * Copyright (c) 2015-2017 ARM Limited 37753SWilliam.Wang@arm.com * All rights reserved 47753SWilliam.Wang@arm.com * 57753SWilliam.Wang@arm.com * The license below extends only to copyright in the software and shall 67753SWilliam.Wang@arm.com * not be construed as granting a license to any other intellectual 77753SWilliam.Wang@arm.com * property including but not limited to intellectual property relating 87753SWilliam.Wang@arm.com * to a hardware implementation of the functionality of the software 97753SWilliam.Wang@arm.com * licensed hereunder. You may use the software subject to the license 107753SWilliam.Wang@arm.com * terms below provided that you ensure that this notice is replicated 117753SWilliam.Wang@arm.com * unmodified and in its entirety in all distributions of the software, 127753SWilliam.Wang@arm.com * modified or unmodified, in source code or in binary form. 137753SWilliam.Wang@arm.com * 147753SWilliam.Wang@arm.com * Redistribution and use in source and binary forms, with or without 157753SWilliam.Wang@arm.com * modification, are permitted provided that the following conditions are 167753SWilliam.Wang@arm.com * met: redistributions of source code must retain the above copyright 177753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer; 187753SWilliam.Wang@arm.com * redistributions in binary form must reproduce the above copyright 197753SWilliam.Wang@arm.com * notice, this list of conditions and the following disclaimer in the 207753SWilliam.Wang@arm.com * documentation and/or other materials provided with the distribution; 217753SWilliam.Wang@arm.com * neither the name of the copyright holders nor the names of its 227753SWilliam.Wang@arm.com * contributors may be used to endorse or promote products derived from 237753SWilliam.Wang@arm.com * this software without specific prior written permission. 247753SWilliam.Wang@arm.com * 257753SWilliam.Wang@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 267753SWilliam.Wang@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 277753SWilliam.Wang@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 287753SWilliam.Wang@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 297753SWilliam.Wang@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 307753SWilliam.Wang@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 317753SWilliam.Wang@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 327753SWilliam.Wang@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 337753SWilliam.Wang@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 347753SWilliam.Wang@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 357753SWilliam.Wang@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 367753SWilliam.Wang@arm.com * 377753SWilliam.Wang@arm.com * Authors: Andreas Sandberg 387950SAli.Saidi@ARM.com * Curtis Dunham 397753SWilliam.Wang@arm.com */ 407753SWilliam.Wang@arm.com 418229Snate@binkert.org#include "arch/arm/kvm/gic.hh" 427950SAli.Saidi@ARM.com 437950SAli.Saidi@ARM.com#include <linux/kvm.h> 447753SWilliam.Wang@arm.com 458245Snate@binkert.org#include "arch/arm/kvm/base_cpu.hh" 468245Snate@binkert.org#include "debug/GIC.hh" 477753SWilliam.Wang@arm.com#include "debug/Interrupt.hh" 487753SWilliam.Wang@arm.com#include "params/MuxingKvmGic.hh" 497753SWilliam.Wang@arm.com 507753SWilliam.Wang@arm.comKvmKernelGicV2::KvmKernelGicV2(KvmVM &_vm, Addr cpu_addr, Addr dist_addr, 517753SWilliam.Wang@arm.com unsigned it_lines) 527753SWilliam.Wang@arm.com : cpuRange(RangeSize(cpu_addr, KVM_VGIC_V2_CPU_SIZE)), 538737Skoansin.tan@gmail.com distRange(RangeSize(dist_addr, KVM_VGIC_V2_DIST_SIZE)), 548737Skoansin.tan@gmail.com vm(_vm), 558737Skoansin.tan@gmail.com kdev(vm.createDevice(KVM_DEV_TYPE_ARM_VGIC_V2)) 568737Skoansin.tan@gmail.com{ 577753SWilliam.Wang@arm.com // Tell the VM that we will emulate the GIC in the kernel. This 587753SWilliam.Wang@arm.com // disables IRQ and FIQ handling in the KVM CPU model. 597753SWilliam.Wang@arm.com vm.enableKernelIRQChip(); 607753SWilliam.Wang@arm.com 617753SWilliam.Wang@arm.com kdev.setAttr<uint64_t>( 627753SWilliam.Wang@arm.com KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST, dist_addr); 637950SAli.Saidi@ARM.com kdev.setAttr<uint64_t>( 647753SWilliam.Wang@arm.com KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_CPU, cpu_addr); 657753SWilliam.Wang@arm.com 667753SWilliam.Wang@arm.com kdev.setAttr<uint32_t>(KVM_DEV_ARM_VGIC_GRP_NR_IRQS, 0, it_lines); 677950SAli.Saidi@ARM.com} 687950SAli.Saidi@ARM.com 697753SWilliam.Wang@arm.comKvmKernelGicV2::~KvmKernelGicV2() 707753SWilliam.Wang@arm.com{ 717753SWilliam.Wang@arm.com} 727753SWilliam.Wang@arm.com 737753SWilliam.Wang@arm.comvoid 748661SAli.Saidi@ARM.comKvmKernelGicV2::setSPI(unsigned spi) 757950SAli.Saidi@ARM.com{ 768737Skoansin.tan@gmail.com setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, true); 778737Skoansin.tan@gmail.com} 787950SAli.Saidi@ARM.com 797753SWilliam.Wang@arm.comvoid 807753SWilliam.Wang@arm.comKvmKernelGicV2::clearSPI(unsigned spi) 818737Skoansin.tan@gmail.com{ 827950SAli.Saidi@ARM.com setIntState(KVM_ARM_IRQ_TYPE_SPI, 0, spi, false); 837950SAli.Saidi@ARM.com} 847950SAli.Saidi@ARM.com 857753SWilliam.Wang@arm.comvoid 867753SWilliam.Wang@arm.comKvmKernelGicV2::setPPI(unsigned vcpu, unsigned ppi) 879086Sandreas.hansson@arm.com{ 889086Sandreas.hansson@arm.com setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, true); 899086Sandreas.hansson@arm.com} 909086Sandreas.hansson@arm.com 919086Sandreas.hansson@arm.comvoid 927753SWilliam.Wang@arm.comKvmKernelGicV2::clearPPI(unsigned vcpu, unsigned ppi) 937753SWilliam.Wang@arm.com{ 947753SWilliam.Wang@arm.com setIntState(KVM_ARM_IRQ_TYPE_PPI, vcpu, ppi, false); 957753SWilliam.Wang@arm.com} 967753SWilliam.Wang@arm.com 977753SWilliam.Wang@arm.comvoid 987753SWilliam.Wang@arm.comKvmKernelGicV2::setIntState(unsigned type, unsigned vcpu, unsigned irq, 997753SWilliam.Wang@arm.com bool high) 1007753SWilliam.Wang@arm.com{ 1017950SAli.Saidi@ARM.com assert(type <= KVM_ARM_IRQ_TYPE_MASK); 1027950SAli.Saidi@ARM.com assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK); 1037753SWilliam.Wang@arm.com assert(irq <= KVM_ARM_IRQ_NUM_MASK); 1047950SAli.Saidi@ARM.com const uint32_t line( 1057950SAli.Saidi@ARM.com (type << KVM_ARM_IRQ_TYPE_SHIFT) | 1067753SWilliam.Wang@arm.com (vcpu << KVM_ARM_IRQ_VCPU_SHIFT) | 1077950SAli.Saidi@ARM.com (irq << KVM_ARM_IRQ_NUM_SHIFT)); 1087753SWilliam.Wang@arm.com 1097950SAli.Saidi@ARM.com vm.setIRQLine(line, high); 1107950SAli.Saidi@ARM.com} 1117950SAli.Saidi@ARM.com 1127950SAli.Saidi@ARM.comuint32_t 1137950SAli.Saidi@ARM.comKvmKernelGicV2::getGicReg(unsigned group, unsigned vcpu, unsigned offset) 1147950SAli.Saidi@ARM.com{ 1157950SAli.Saidi@ARM.com uint64_t reg; 1167950SAli.Saidi@ARM.com 1177950SAli.Saidi@ARM.com assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK); 1187950SAli.Saidi@ARM.com const uint32_t attr( 1197950SAli.Saidi@ARM.com (vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) | 1207950SAli.Saidi@ARM.com (offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)); 1217950SAli.Saidi@ARM.com 1227950SAli.Saidi@ARM.com kdev.getAttrPtr(group, attr, ®); 1237950SAli.Saidi@ARM.com return (uint32_t) reg; 1247950SAli.Saidi@ARM.com} 1257950SAli.Saidi@ARM.com 1267950SAli.Saidi@ARM.comvoid 1277950SAli.Saidi@ARM.comKvmKernelGicV2::setGicReg(unsigned group, unsigned vcpu, unsigned offset, 1287950SAli.Saidi@ARM.com unsigned value) 1297950SAli.Saidi@ARM.com{ 1307950SAli.Saidi@ARM.com uint64_t reg = value; 1317950SAli.Saidi@ARM.com 1327950SAli.Saidi@ARM.com assert(vcpu <= KVM_ARM_IRQ_VCPU_MASK); 1337950SAli.Saidi@ARM.com const uint32_t attr( 1347950SAli.Saidi@ARM.com (vcpu << KVM_DEV_ARM_VGIC_CPUID_SHIFT) | 1357950SAli.Saidi@ARM.com (offset << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)); 1367950SAli.Saidi@ARM.com 1377950SAli.Saidi@ARM.com kdev.setAttrPtr(group, attr, ®); 1387950SAli.Saidi@ARM.com} 1397950SAli.Saidi@ARM.com 1407950SAli.Saidi@ARM.comuint32_t 1417950SAli.Saidi@ARM.comKvmKernelGicV2::readDistributor(ContextID ctx, Addr daddr) 1427950SAli.Saidi@ARM.com{ 1437950SAli.Saidi@ARM.com auto vcpu = vm.contextIdToVCpuId(ctx); 1447950SAli.Saidi@ARM.com return getGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr); 1457950SAli.Saidi@ARM.com} 1467950SAli.Saidi@ARM.com 1477950SAli.Saidi@ARM.comuint32_t 1487950SAli.Saidi@ARM.comKvmKernelGicV2::readCpu(ContextID ctx, Addr daddr) 1497950SAli.Saidi@ARM.com{ 1507950SAli.Saidi@ARM.com auto vcpu = vm.contextIdToVCpuId(ctx); 1517950SAli.Saidi@ARM.com return getGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr); 1527950SAli.Saidi@ARM.com} 1537950SAli.Saidi@ARM.com 1547950SAli.Saidi@ARM.comvoid 1557950SAli.Saidi@ARM.comKvmKernelGicV2::writeDistributor(ContextID ctx, Addr daddr, uint32_t data) 1567950SAli.Saidi@ARM.com{ 1577950SAli.Saidi@ARM.com auto vcpu = vm.contextIdToVCpuId(ctx); 1587950SAli.Saidi@ARM.com setGicReg(KVM_DEV_ARM_VGIC_GRP_DIST_REGS, vcpu, daddr, data); 1597950SAli.Saidi@ARM.com} 1607950SAli.Saidi@ARM.com 1617950SAli.Saidi@ARM.comvoid 1627950SAli.Saidi@ARM.comKvmKernelGicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data) 1637950SAli.Saidi@ARM.com{ 1647950SAli.Saidi@ARM.com auto vcpu = vm.contextIdToVCpuId(ctx); 1657950SAli.Saidi@ARM.com setGicReg(KVM_DEV_ARM_VGIC_GRP_CPU_REGS, vcpu, daddr, data); 1667950SAli.Saidi@ARM.com} 1677950SAli.Saidi@ARM.com 1687950SAli.Saidi@ARM.com 1697950SAli.Saidi@ARM.com 1707950SAli.Saidi@ARM.comMuxingKvmGic::MuxingKvmGic(const MuxingKvmGicParams *p) 1717950SAli.Saidi@ARM.com : Pl390(p), 1727950SAli.Saidi@ARM.com system(*p->system), 1737950SAli.Saidi@ARM.com kernelGic(nullptr), 1747950SAli.Saidi@ARM.com usingKvm(false) 1757950SAli.Saidi@ARM.com{ 1767950SAli.Saidi@ARM.com if (auto vm = system.getKvmVM()) { 1777950SAli.Saidi@ARM.com kernelGic = new KvmKernelGicV2(*vm, p->cpu_addr, p->dist_addr, 1787950SAli.Saidi@ARM.com p->it_lines); 1797950SAli.Saidi@ARM.com } 1807950SAli.Saidi@ARM.com} 1817950SAli.Saidi@ARM.com 1827950SAli.Saidi@ARM.comMuxingKvmGic::~MuxingKvmGic() 1837753SWilliam.Wang@arm.com{ 1847950SAli.Saidi@ARM.com} 1857950SAli.Saidi@ARM.com 1867950SAli.Saidi@ARM.comvoid 1877950SAli.Saidi@ARM.comMuxingKvmGic::loadState(CheckpointIn &cp) 1887950SAli.Saidi@ARM.com{ 1897753SWilliam.Wang@arm.com Pl390::loadState(cp); 1907950SAli.Saidi@ARM.com} 1917950SAli.Saidi@ARM.com 1927950SAli.Saidi@ARM.comvoid 1937950SAli.Saidi@ARM.comMuxingKvmGic::startup() 1947950SAli.Saidi@ARM.com{ 1957753SWilliam.Wang@arm.com Pl390::startup(); 1967950SAli.Saidi@ARM.com usingKvm = (kernelGic != nullptr) && system.validKvmEnvironment(); 1977950SAli.Saidi@ARM.com if (usingKvm) 1987950SAli.Saidi@ARM.com fromPl390ToKvm(); 1997753SWilliam.Wang@arm.com} 2007753SWilliam.Wang@arm.com 2017753SWilliam.Wang@arm.comDrainState 2027753SWilliam.Wang@arm.comMuxingKvmGic::drain() 2037753SWilliam.Wang@arm.com{ 2047753SWilliam.Wang@arm.com if (usingKvm) 2057753SWilliam.Wang@arm.com fromKvmToPl390(); 2067753SWilliam.Wang@arm.com return Pl390::drain(); 2077753SWilliam.Wang@arm.com} 2087753SWilliam.Wang@arm.com 2097753SWilliam.Wang@arm.comvoid 2107753SWilliam.Wang@arm.comMuxingKvmGic::drainResume() 2117753SWilliam.Wang@arm.com{ 2127753SWilliam.Wang@arm.com Pl390::drainResume(); 2137753SWilliam.Wang@arm.com bool use_kvm = (kernelGic != nullptr) && system.validKvmEnvironment(); 2147753SWilliam.Wang@arm.com if (use_kvm != usingKvm) { 2157753SWilliam.Wang@arm.com // Should only occur due to CPU switches 2167753SWilliam.Wang@arm.com if (use_kvm) // from simulation to KVM emulation 2177753SWilliam.Wang@arm.com fromPl390ToKvm(); 2187753SWilliam.Wang@arm.com // otherwise, drain() already sync'd the state back to the Pl390 2197753SWilliam.Wang@arm.com 2207753SWilliam.Wang@arm.com usingKvm = use_kvm; 2217753SWilliam.Wang@arm.com } 2227753SWilliam.Wang@arm.com} 2237753SWilliam.Wang@arm.com 2247753SWilliam.Wang@arm.comvoid 2257753SWilliam.Wang@arm.comMuxingKvmGic::serialize(CheckpointOut &cp) const 2267753SWilliam.Wang@arm.com{ 2277753SWilliam.Wang@arm.com // drain() already ensured Pl390 updated with KvmGic state if necessary 2287753SWilliam.Wang@arm.com Pl390::serialize(cp); 2297753SWilliam.Wang@arm.com} 2307753SWilliam.Wang@arm.com 2317753SWilliam.Wang@arm.comvoid 2327753SWilliam.Wang@arm.comMuxingKvmGic::unserialize(CheckpointIn &cp) 2337753SWilliam.Wang@arm.com{ 2347753SWilliam.Wang@arm.com Pl390::unserialize(cp); 2357753SWilliam.Wang@arm.com} 2367753SWilliam.Wang@arm.com 2377753SWilliam.Wang@arm.comTick 2387753SWilliam.Wang@arm.comMuxingKvmGic::read(PacketPtr pkt) 2397753SWilliam.Wang@arm.com{ 2407753SWilliam.Wang@arm.com if (!usingKvm) 2417753SWilliam.Wang@arm.com return Pl390::read(pkt); 2427753SWilliam.Wang@arm.com 2437753SWilliam.Wang@arm.com panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n"); 2447753SWilliam.Wang@arm.com} 2457753SWilliam.Wang@arm.com 2467950SAli.Saidi@ARM.comTick 2477950SAli.Saidi@ARM.comMuxingKvmGic::write(PacketPtr pkt) 2487753SWilliam.Wang@arm.com{ 2497950SAli.Saidi@ARM.com if (!usingKvm) 2507753SWilliam.Wang@arm.com return Pl390::write(pkt); 2517950SAli.Saidi@ARM.com 2527950SAli.Saidi@ARM.com panic("MuxingKvmGic: PIO from gem5 is currently unsupported\n"); 2537753SWilliam.Wang@arm.com} 2547950SAli.Saidi@ARM.com 2557950SAli.Saidi@ARM.comvoid 2567950SAli.Saidi@ARM.comMuxingKvmGic::sendInt(uint32_t num) 2577950SAli.Saidi@ARM.com{ 2587950SAli.Saidi@ARM.com if (!usingKvm) 2597950SAli.Saidi@ARM.com return Pl390::sendInt(num); 2607950SAli.Saidi@ARM.com 2617950SAli.Saidi@ARM.com DPRINTF(Interrupt, "Set SPI %d\n", num); 2627950SAli.Saidi@ARM.com kernelGic->setSPI(num); 2637950SAli.Saidi@ARM.com} 2647950SAli.Saidi@ARM.com 2657950SAli.Saidi@ARM.comvoid 2667950SAli.Saidi@ARM.comMuxingKvmGic::clearInt(uint32_t num) 2677950SAli.Saidi@ARM.com{ 2687950SAli.Saidi@ARM.com if (!usingKvm) 2697950SAli.Saidi@ARM.com return Pl390::clearInt(num); 2707950SAli.Saidi@ARM.com 2717950SAli.Saidi@ARM.com DPRINTF(Interrupt, "Clear SPI %d\n", num); 2727950SAli.Saidi@ARM.com kernelGic->clearSPI(num); 2737950SAli.Saidi@ARM.com} 2747950SAli.Saidi@ARM.com 2757950SAli.Saidi@ARM.comvoid 2768508SAli.Saidi@ARM.comMuxingKvmGic::sendPPInt(uint32_t num, uint32_t cpu) 2777950SAli.Saidi@ARM.com{ 2787950SAli.Saidi@ARM.com if (!usingKvm) 2797950SAli.Saidi@ARM.com return Pl390::sendPPInt(num, cpu); 2807950SAli.Saidi@ARM.com DPRINTF(Interrupt, "Set PPI %d:%d\n", cpu, num); 2817950SAli.Saidi@ARM.com kernelGic->setPPI(cpu, num); 2827950SAli.Saidi@ARM.com} 2837950SAli.Saidi@ARM.com 2847753SWilliam.Wang@arm.comvoid 2857950SAli.Saidi@ARM.comMuxingKvmGic::clearPPInt(uint32_t num, uint32_t cpu) 2867950SAli.Saidi@ARM.com{ 2877950SAli.Saidi@ARM.com if (!usingKvm) 2887950SAli.Saidi@ARM.com return Pl390::clearPPInt(num, cpu); 2897950SAli.Saidi@ARM.com 2907950SAli.Saidi@ARM.com DPRINTF(Interrupt, "Clear PPI %d:%d\n", cpu, num); 2917950SAli.Saidi@ARM.com kernelGic->clearPPI(cpu, num); 2927950SAli.Saidi@ARM.com} 2937950SAli.Saidi@ARM.com 2947950SAli.Saidi@ARM.comvoid 2957950SAli.Saidi@ARM.comMuxingKvmGic::copyDistRegister(BaseGicRegisters* from, BaseGicRegisters* to, 2967950SAli.Saidi@ARM.com ContextID ctx, Addr daddr) 2977950SAli.Saidi@ARM.com{ 2987950SAli.Saidi@ARM.com auto val = from->readDistributor(ctx, daddr); 2997950SAli.Saidi@ARM.com DPRINTF(GIC, "copy dist 0x%x 0x%08x\n", daddr, val); 3007950SAli.Saidi@ARM.com to->writeDistributor(ctx, daddr, val); 3017950SAli.Saidi@ARM.com} 3027950SAli.Saidi@ARM.com 3037950SAli.Saidi@ARM.comvoid 3047950SAli.Saidi@ARM.comMuxingKvmGic::copyCpuRegister(BaseGicRegisters* from, BaseGicRegisters* to, 3057950SAli.Saidi@ARM.com ContextID ctx, Addr daddr) 3067950SAli.Saidi@ARM.com{ 3077950SAli.Saidi@ARM.com auto val = from->readCpu(ctx, daddr); 3087950SAli.Saidi@ARM.com DPRINTF(GIC, "copy cpu 0x%x 0x%08x\n", daddr, val); 3097950SAli.Saidi@ARM.com to->writeCpu(ctx, daddr, val); 3107950SAli.Saidi@ARM.com} 3117950SAli.Saidi@ARM.com 3127950SAli.Saidi@ARM.comvoid 3137950SAli.Saidi@ARM.comMuxingKvmGic::copyBankedDistRange(BaseGicRegisters* from, BaseGicRegisters* to, 3147950SAli.Saidi@ARM.com Addr daddr, size_t size) 3157950SAli.Saidi@ARM.com{ 3167950SAli.Saidi@ARM.com for (int ctx = 0; ctx < system._numContexts; ++ctx) 3177950SAli.Saidi@ARM.com for (auto a = daddr; a < daddr + size; a += 4) 3187950SAli.Saidi@ARM.com copyDistRegister(from, to, ctx, a); 3197950SAli.Saidi@ARM.com} 3207950SAli.Saidi@ARM.com 3217950SAli.Saidi@ARM.comvoid 3227950SAli.Saidi@ARM.comMuxingKvmGic::clearBankedDistRange(BaseGicRegisters* to, 3237950SAli.Saidi@ARM.com Addr daddr, size_t size) 3247950SAli.Saidi@ARM.com{ 3257950SAli.Saidi@ARM.com for (int ctx = 0; ctx < system._numContexts; ++ctx) 3267950SAli.Saidi@ARM.com for (auto a = daddr; a < daddr + size; a += 4) 3277950SAli.Saidi@ARM.com to->writeDistributor(ctx, a, 0xFFFFFFFF); 3287950SAli.Saidi@ARM.com} 3297950SAli.Saidi@ARM.com 3307950SAli.Saidi@ARM.comvoid 3317950SAli.Saidi@ARM.comMuxingKvmGic::copyDistRange(BaseGicRegisters* from, BaseGicRegisters* to, 3327950SAli.Saidi@ARM.com Addr daddr, size_t size) 3337950SAli.Saidi@ARM.com{ 3347950SAli.Saidi@ARM.com for (auto a = daddr; a < daddr + size; a += 4) 3357950SAli.Saidi@ARM.com copyDistRegister(from, to, 0, a); 3367950SAli.Saidi@ARM.com} 3377950SAli.Saidi@ARM.com 3387950SAli.Saidi@ARM.comvoid 3397950SAli.Saidi@ARM.comMuxingKvmGic::clearDistRange(BaseGicRegisters* to, 3407950SAli.Saidi@ARM.com Addr daddr, size_t size) 3417950SAli.Saidi@ARM.com{ 3427950SAli.Saidi@ARM.com for (auto a = daddr; a < daddr + size; a += 4) 3437950SAli.Saidi@ARM.com to->writeDistributor(0, a, 0xFFFFFFFF); 3447950SAli.Saidi@ARM.com} 3457950SAli.Saidi@ARM.com 3467950SAli.Saidi@ARM.comvoid 3477950SAli.Saidi@ARM.comMuxingKvmGic::copyGicState(BaseGicRegisters* from, BaseGicRegisters* to) 3487950SAli.Saidi@ARM.com{ 3497950SAli.Saidi@ARM.com Addr set, clear; 3507950SAli.Saidi@ARM.com size_t size; 3517950SAli.Saidi@ARM.com 3527950SAli.Saidi@ARM.com /// CPU state (GICC_*) 3537950SAli.Saidi@ARM.com // Copy CPU Interface Control Register (CTLR), 3547950SAli.Saidi@ARM.com // Interrupt Priority Mask Register (PMR), and 3557950SAli.Saidi@ARM.com // Binary Point Register (BPR) 3567950SAli.Saidi@ARM.com for (int ctx = 0; ctx < system._numContexts; ++ctx) { 3577950SAli.Saidi@ARM.com copyCpuRegister(from, to, ctx, GICC_CTLR); 3587950SAli.Saidi@ARM.com copyCpuRegister(from, to, ctx, GICC_PMR); 3597950SAli.Saidi@ARM.com copyCpuRegister(from, to, ctx, GICC_BPR); 3607950SAli.Saidi@ARM.com } 3617950SAli.Saidi@ARM.com 3627753SWilliam.Wang@arm.com 3637950SAli.Saidi@ARM.com /// Distributor state (GICD_*) 3647950SAli.Saidi@ARM.com // Copy Distributor Control Register (CTLR) 3657950SAli.Saidi@ARM.com copyDistRegister(from, to, 0, GICD_CTLR); 3667950SAli.Saidi@ARM.com 3677950SAli.Saidi@ARM.com // Copy interrupt-enabled statuses (I[CS]ENABLERn; R0 is per-CPU banked) 3687753SWilliam.Wang@arm.com set = Pl390::GICD_ISENABLER.start(); 3697950SAli.Saidi@ARM.com clear = Pl390::GICD_ICENABLER.start(); 3707950SAli.Saidi@ARM.com size = Pl390::itLines / 8; 3717950SAli.Saidi@ARM.com clearBankedDistRange(to, clear, 4); 3727753SWilliam.Wang@arm.com copyBankedDistRange(from, to, set, 4); 3737753SWilliam.Wang@arm.com 3747753SWilliam.Wang@arm.com set += 4, clear += 4, size -= 4; 3757753SWilliam.Wang@arm.com clearDistRange(to, clear, size); 3767753SWilliam.Wang@arm.com copyDistRange(from, to, set, size); 3777753SWilliam.Wang@arm.com 3787753SWilliam.Wang@arm.com // Copy pending interrupts (I[CS]PENDRn; R0 is per-CPU banked) 3797753SWilliam.Wang@arm.com set = Pl390::GICD_ISPENDR.start(); 3807753SWilliam.Wang@arm.com clear = Pl390::GICD_ICPENDR.start(); 3817950SAli.Saidi@ARM.com size = Pl390::itLines / 8; 3827950SAli.Saidi@ARM.com clearBankedDistRange(to, clear, 4); 3837950SAli.Saidi@ARM.com copyBankedDistRange(from, to, set, 4); 3847950SAli.Saidi@ARM.com 3857950SAli.Saidi@ARM.com set += 4, clear += 4, size -= 4; 3867950SAli.Saidi@ARM.com clearDistRange(to, clear, size); 3877950SAli.Saidi@ARM.com copyDistRange(from, to, set, size); 3887950SAli.Saidi@ARM.com 3897950SAli.Saidi@ARM.com // Copy active interrupts (I[CS]ACTIVERn; R0 is per-CPU banked) 3907950SAli.Saidi@ARM.com set = Pl390::GICD_ISACTIVER.start(); 3917950SAli.Saidi@ARM.com clear = Pl390::GICD_ICACTIVER.start(); 3927950SAli.Saidi@ARM.com size = Pl390::itLines / 8; 3937950SAli.Saidi@ARM.com clearBankedDistRange(to, clear, 4); 3947950SAli.Saidi@ARM.com copyBankedDistRange(from, to, set, 4); 3957950SAli.Saidi@ARM.com 3967950SAli.Saidi@ARM.com set += 4, clear += 4, size -= 4; 3977950SAli.Saidi@ARM.com clearDistRange(to, clear, size); 3987950SAli.Saidi@ARM.com copyDistRange(from, to, set, size); 3997950SAli.Saidi@ARM.com 4007950SAli.Saidi@ARM.com // Copy interrupt priorities (IPRIORITYRn; R0-7 are per-CPU banked) 4017950SAli.Saidi@ARM.com set = Pl390::GICD_IPRIORITYR.start(); 4027950SAli.Saidi@ARM.com copyBankedDistRange(from, to, set, 32); 4037950SAli.Saidi@ARM.com 4047950SAli.Saidi@ARM.com set += 32; 4057950SAli.Saidi@ARM.com size = Pl390::itLines - 32; 4067950SAli.Saidi@ARM.com copyDistRange(from, to, set, size); 4077950SAli.Saidi@ARM.com 4087950SAli.Saidi@ARM.com // Copy interrupt processor target regs (ITARGETRn; R0-7 are read-only) 4097950SAli.Saidi@ARM.com set = Pl390::GICD_ITARGETSR.start() + 32; 4107950SAli.Saidi@ARM.com size = Pl390::itLines - 32; 4117950SAli.Saidi@ARM.com copyDistRange(from, to, set, size); 4127950SAli.Saidi@ARM.com 4137950SAli.Saidi@ARM.com // Copy interrupt configuration registers (ICFGRn) 4147950SAli.Saidi@ARM.com set = Pl390::GICD_ICFGR.start(); 4157950SAli.Saidi@ARM.com size = Pl390::itLines / 4; 4167950SAli.Saidi@ARM.com copyDistRange(from, to, set, size); 4177950SAli.Saidi@ARM.com} 4187950SAli.Saidi@ARM.com 4197950SAli.Saidi@ARM.comvoid 4207950SAli.Saidi@ARM.comMuxingKvmGic::fromPl390ToKvm() 4217950SAli.Saidi@ARM.com{ 4227950SAli.Saidi@ARM.com copyGicState(static_cast<Pl390*>(this), kernelGic); 4237950SAli.Saidi@ARM.com} 4247950SAli.Saidi@ARM.com 4257950SAli.Saidi@ARM.comvoid 4267950SAli.Saidi@ARM.comMuxingKvmGic::fromKvmToPl390() 4277950SAli.Saidi@ARM.com{ 4287950SAli.Saidi@ARM.com copyGicState(kernelGic, static_cast<Pl390*>(this)); 4297950SAli.Saidi@ARM.com 4307753SWilliam.Wang@arm.com // the values read for the Interrupt Priority Mask Register (PMR) 4317753SWilliam.Wang@arm.com // have been shifted by three bits due to its having been emulated by 4327753SWilliam.Wang@arm.com // a VGIC with only 5 PMR bits in its VMCR register. Presently the 4337950SAli.Saidi@ARM.com // Linux kernel does not repair this inaccuracy, so we correct it here. 4347950SAli.Saidi@ARM.com for (int cpu = 0; cpu < system._numContexts; ++cpu) { 4357753SWilliam.Wang@arm.com cpuPriority[cpu] <<= 3; 4367950SAli.Saidi@ARM.com assert((cpuPriority[cpu] & ~0xff) == 0); 4377950SAli.Saidi@ARM.com } 4387950SAli.Saidi@ARM.com} 4397950SAli.Saidi@ARM.com 4407950SAli.Saidi@ARM.comMuxingKvmGic * 4417950SAli.Saidi@ARM.comMuxingKvmGicParams::create() 4427753SWilliam.Wang@arm.com{ 4437823Ssteve.reinhardt@amd.com return new MuxingKvmGic(this); 4447950SAli.Saidi@ARM.com} 4457950SAli.Saidi@ARM.com