From: Andreas Sandberg Date: Mon, 24 Apr 2017 16:38:46 +0000 (+0000) Subject: kvm, arm: Don't forward IRQ/FIQ when using the kernel's GIC X-Git-Tag: v19.0.0.0~2708 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=feb91ce576f2da6e1941697100d14bc10ace6a90;p=gem5.git kvm, arm: Don't forward IRQ/FIQ when using the kernel's GIC The BaseArmKvmCPU is responsible for forwarding the IRQ and FIQ signals from gem5's simulated GIC to KVM. However, these signals shouldn't be used when the in-kernel GIC emulator is used. Instead of delivering the interrupts to the guest, we should just ignore them since any such pending interrupts are likely to be an artifact of CPU switching or incorrect draining. Change-Id: I083b72639384272157f92f44a6606bdf0be7413c Signed-off-by: Andreas Sandberg Reviewed-by: Sudhanshu Jha Reviewed-by: Curtis Dunham Reviewed-on: https://gem5-review.googlesource.com/3660 --- diff --git a/src/arch/arm/kvm/base_cpu.cc b/src/arch/arm/kvm/base_cpu.cc index e25112cae..765965092 100644 --- a/src/arch/arm/kvm/base_cpu.cc +++ b/src/arch/arm/kvm/base_cpu.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015 ARM Limited + * Copyright (c) 2012, 2015, 2017 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -88,20 +88,31 @@ BaseArmKvmCPU::startup() Tick BaseArmKvmCPU::kvmRun(Tick ticks) { - bool simFIQ(interrupts[0]->checkRaw(INT_FIQ)); - bool simIRQ(interrupts[0]->checkRaw(INT_IRQ)); + const bool simFIQ(interrupts[0]->checkRaw(INT_FIQ)); + const bool simIRQ(interrupts[0]->checkRaw(INT_IRQ)); - if (fiqAsserted != simFIQ) { - fiqAsserted = simFIQ; - DPRINTF(KvmInt, "KVM: Update FIQ state: %i\n", simFIQ); - vm.setIRQLine(INTERRUPT_VCPU_FIQ(vcpuID), simFIQ); - } - if (irqAsserted != simIRQ) { - irqAsserted = simIRQ; - DPRINTF(KvmInt, "KVM: Update IRQ state: %i\n", simIRQ); - vm.setIRQLine(INTERRUPT_VCPU_IRQ(vcpuID), simIRQ); + if (!vm.hasKernelIRQChip()) { + if (fiqAsserted != simFIQ) { + DPRINTF(KvmInt, "KVM: Update FIQ state: %i\n", simFIQ); + vm.setIRQLine(INTERRUPT_VCPU_FIQ(vcpuID), simFIQ); + } + if (irqAsserted != simIRQ) { + DPRINTF(KvmInt, "KVM: Update IRQ state: %i\n", simIRQ); + vm.setIRQLine(INTERRUPT_VCPU_IRQ(vcpuID), simIRQ); + } + } else { + warn_if(simFIQ && !fiqAsserted, + "FIQ raised by the simulated interrupt controller " \ + "despite in-kernel GIC emulation. This is probably a bug."); + + warn_if(simIRQ && !irqAsserted, + "IRQ raised by the simulated interrupt controller " \ + "despite in-kernel GIC emulation. This is probably a bug."); } + irqAsserted = simIRQ; + fiqAsserted = simFIQ; + return BaseKvmCPU::kvmRun(ticks); } diff --git a/src/arch/arm/kvm/gic.cc b/src/arch/arm/kvm/gic.cc index 498b79faa..ce3baa558 100644 --- a/src/arch/arm/kvm/gic.cc +++ b/src/arch/arm/kvm/gic.cc @@ -54,6 +54,10 @@ KvmKernelGicV2::KvmKernelGicV2(KvmVM &_vm, Addr cpu_addr, Addr dist_addr, vm(_vm), kdev(vm.createDevice(KVM_DEV_TYPE_ARM_VGIC_V2)) { + // Tell the VM that we will emulate the GIC in the kernel. This + // disables IRQ and FIQ handling in the KVM CPU model. + vm.enableKernelIRQChip(); + kdev.setAttr( KVM_DEV_ARM_VGIC_GRP_ADDR, KVM_VGIC_V2_ADDR_TYPE_DIST, dist_addr); kdev.setAttr( diff --git a/src/cpu/kvm/vm.hh b/src/cpu/kvm/vm.hh index df2e4119a..e122bbf86 100644 --- a/src/cpu/kvm/vm.hh +++ b/src/cpu/kvm/vm.hh @@ -351,6 +351,15 @@ class KvmVM : public SimObject * Is in-kernel IRQ chip emulation enabled? */ bool hasKernelIRQChip() const { return _hasKernelIRQChip; } + + /** + * Tell the VM and VCPUs to use an in-kernel IRQ chip for + * interrupt delivery. + * + * @note This is set automatically if the IRQ chip is created + * using the KvmVM::createIRQChip() API. + */ + void enableKernelIRQChip() { _hasKernelIRQChip = true; } /** @} */ struct MemSlot