arch-arm: Add basic support for KVM_CAP_ARM_USER_IRQ
KVM_CAP_ARM_USER_IRQ is a KVM extension introduced in newer versions of Linux (>= 4.12). It supports delivering interrupt from the kernel-space timer to the user-space GIC, which means that it will be unnecessary to use the memory-mapped timer and emulate it in gem5 anymore. Using the option provided by this change, Linux is able to boot with 1 CPU successfully, and the speed is slightly faster then the memory- mapped timer option. However, multicore seems to hang during boot and still needs more investigation to be enabled. JIRA: https://gem5.atlassian.net/browse/GEM5-663 Change-Id: I146bbcce3cf66f8f5ebee04ea5f1b9f54868721a Signed-off-by: Hsuan Hsu <hsuan.hsu@mediatek.com> Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30921 Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com> Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
@@ -41,7 +41,9 @@
|
||||
|
||||
#include "arch/arm/interrupts.hh"
|
||||
#include "debug/KvmInt.hh"
|
||||
#include "dev/arm/generic_timer.hh"
|
||||
#include "params/BaseArmKvmCPU.hh"
|
||||
#include "params/GenericTimer.hh"
|
||||
|
||||
#define INTERRUPT_ID(type, vcpu, irq) ( \
|
||||
((type) << KVM_ARM_IRQ_TYPE_SHIFT) | \
|
||||
@@ -57,7 +59,8 @@
|
||||
|
||||
BaseArmKvmCPU::BaseArmKvmCPU(BaseArmKvmCPUParams *params)
|
||||
: BaseKvmCPU(params),
|
||||
irqAsserted(false), fiqAsserted(false)
|
||||
irqAsserted(false), fiqAsserted(false),
|
||||
virtTimerPin(nullptr), prevDeviceIRQLevel(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -82,6 +85,10 @@ BaseArmKvmCPU::startup()
|
||||
target_config.features[0] |= (1 << KVM_ARM_VCPU_EL1_32BIT);
|
||||
}
|
||||
kvmArmVCpuInit(target_config);
|
||||
|
||||
if (!vm.hasKernelIRQChip())
|
||||
virtTimerPin = static_cast<ArmSystem *>(system)\
|
||||
->getGenericTimer()->params()->int_virt->get(tc);
|
||||
}
|
||||
|
||||
Tick
|
||||
@@ -113,7 +120,29 @@ BaseArmKvmCPU::kvmRun(Tick ticks)
|
||||
irqAsserted = simIRQ;
|
||||
fiqAsserted = simFIQ;
|
||||
|
||||
return BaseKvmCPU::kvmRun(ticks);
|
||||
Tick kvmRunTicks = BaseKvmCPU::kvmRun(ticks);
|
||||
|
||||
if (!vm.hasKernelIRQChip()) {
|
||||
uint64_t device_irq_level =
|
||||
getKvmRunState()->s.regs.device_irq_level;
|
||||
|
||||
if (!(prevDeviceIRQLevel & KVM_ARM_DEV_EL1_VTIMER) &&
|
||||
(device_irq_level & KVM_ARM_DEV_EL1_VTIMER)) {
|
||||
|
||||
DPRINTF(KvmInt, "In-kernel vtimer IRQ asserted\n");
|
||||
prevDeviceIRQLevel |= KVM_ARM_DEV_EL1_VTIMER;
|
||||
virtTimerPin->raise();
|
||||
|
||||
} else if ((prevDeviceIRQLevel & KVM_ARM_DEV_EL1_VTIMER) &&
|
||||
!(device_irq_level & KVM_ARM_DEV_EL1_VTIMER)) {
|
||||
|
||||
DPRINTF(KvmInt, "In-kernel vtimer IRQ disasserted\n");
|
||||
prevDeviceIRQLevel &= ~KVM_ARM_DEV_EL1_VTIMER;
|
||||
virtTimerPin->clear();
|
||||
}
|
||||
}
|
||||
|
||||
return kvmRunTicks;
|
||||
}
|
||||
|
||||
const BaseArmKvmCPU::RegIndexVector &
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "cpu/kvm/base.hh"
|
||||
#include "dev/arm/base_gic.hh"
|
||||
|
||||
struct BaseArmKvmCPUParams;
|
||||
|
||||
@@ -61,6 +62,23 @@ class BaseArmKvmCPU : public BaseKvmCPU
|
||||
/** Cached state of the FIQ line */
|
||||
bool fiqAsserted;
|
||||
|
||||
/**
|
||||
* If the user-space GIC and the kernel-space timer are used
|
||||
* simultaneously, set up this interrupt pin to forward interrupt from
|
||||
* the timer to the GIC when timer IRQ level change is intercepted.
|
||||
*/
|
||||
ArmInterruptPin *virtTimerPin;
|
||||
|
||||
/**
|
||||
* KVM records whether each in-kernel device IRQ is asserted or
|
||||
* disasserted in the kvmRunState->s.regs.device_irq_level bit map,
|
||||
* and guarantees at least one KVM exit when the level changes. We
|
||||
* use only the KVM_ARM_DEV_EL1_VTIMER bit field currently to track
|
||||
* the level of the in-kernel timer, and preserve the last level in
|
||||
* this class member.
|
||||
*/
|
||||
uint64_t prevDeviceIRQLevel;
|
||||
|
||||
protected:
|
||||
typedef std::vector<uint64_t> RegIndexVector;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user