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

Reply via email to