Hsuan Hsu has submitted this change. (
https://gem5-review.googlesource.com/c/public/gem5/+/30921 )
Change subject: arch-arm: Add basic support for KVM_CAP_ARM_USER_IRQ
......................................................................
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 <[email protected]>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/30921
Tested-by: kokoro <[email protected]>
Reviewed-by: Andreas Sandberg <[email protected]>
Maintainer: Andreas Sandberg <[email protected]>
---
M src/arch/arm/kvm/base_cpu.cc
M src/arch/arm/kvm/base_cpu.hh
2 files changed, 49 insertions(+), 2 deletions(-)
Approvals:
Andreas Sandberg: Looks good to me, approved; Looks good to me, approved
kokoro: Regressions pass
diff --git a/src/arch/arm/kvm/base_cpu.cc b/src/arch/arm/kvm/base_cpu.cc
index c028106..04c5d0f 100644
--- a/src/arch/arm/kvm/base_cpu.cc
+++ b/src/arch/arm/kvm/base_cpu.cc
@@ -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 @@
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 @@
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 &
diff --git a/src/arch/arm/kvm/base_cpu.hh b/src/arch/arm/kvm/base_cpu.hh
index 4ee35ca..028cd39 100644
--- a/src/arch/arm/kvm/base_cpu.hh
+++ b/src/arch/arm/kvm/base_cpu.hh
@@ -41,6 +41,7 @@
#include <vector>
#include "cpu/kvm/base.hh"
+#include "dev/arm/base_gic.hh"
struct BaseArmKvmCPUParams;
@@ -61,6 +62,23 @@
/** 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;
--
To view, visit https://gem5-review.googlesource.com/c/public/gem5/+/30921
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: develop
Gerrit-Change-Id: I146bbcce3cf66f8f5ebee04ea5f1b9f54868721a
Gerrit-Change-Number: 30921
Gerrit-PatchSet: 17
Gerrit-Owner: Hsuan Hsu <[email protected]>
Gerrit-Reviewer: Andreas Sandberg <[email protected]>
Gerrit-Reviewer: Giacomo Travaglini <[email protected]>
Gerrit-Reviewer: Hsuan Hsu <[email protected]>
Gerrit-Reviewer: kokoro <[email protected]>
Gerrit-MessageType: merged
_______________________________________________
gem5-dev mailing list -- [email protected]
To unsubscribe send an email to [email protected]
%(web_page_url)slistinfo%(cgiext)s/%(_internal_name)s