kvm, arm: Switch to the device EQ when accessing ISA devices
authorAndreas Sandberg <andreas.sandberg@arm.com>
Thu, 27 Jul 2017 09:26:07 +0000 (09:26 +0000)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 1 Aug 2017 16:20:24 +0000 (16:20 +0000)
ISA devices typically run in the device event queue. Previously, we
assumed that devices would perform their own EQ migrations as
needed. This isn't ideal since it means we have different conventions
for IO devices and ISA devices. Switch to doing migrations in the KVM
CPU instead to make the behavior consistent.

Change-Id: I33b74480fb2126b0786dbdbfdcfa86083384250c
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/4288
Reviewed-by: Jason Lowe-Power <jason@lowepower.com>
src/arch/arm/kvm/armv8_cpu.cc
src/dev/arm/generic_timer.cc

index db2b9c07acf8c07d91c228cf104ff72aeb2db085..209f49efa2399d4b399f0376ed6deffd4bb1dd26 100644 (file)
@@ -260,7 +260,17 @@ ArmV8KvmCPU::updateKvmState()
     }
 
     for (const auto &ri : getSysRegMap()) {
-        const uint64_t value(tc->readMiscReg(ri.idx));
+        uint64_t value;
+        if (ri.is_device) {
+            // This system register is backed by a device. This means
+            // we need to lock the device event queue.
+            EventQueue::ScopedMigration migrate(deviceEventQueue());
+
+            value = tc->readMiscReg(ri.idx);
+        } else {
+            value = tc->readMiscReg(ri.idx);
+        }
+
         DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
         setOneReg(ri.kvm, value);
     }
@@ -323,10 +333,15 @@ ArmV8KvmCPU::updateThreadContext()
     for (const auto &ri : getSysRegMap()) {
         const auto value(getOneRegU64(ri.kvm));
         DPRINTF(KvmContext, "  %s := 0x%x\n", ri.name, value);
-        if (ri.is_device)
+        if (ri.is_device) {
+            // This system register is backed by a device. This means
+            // we need to lock the device event queue.
+            EventQueue::ScopedMigration migrate(deviceEventQueue());
+
             tc->setMiscReg(ri.idx, value);
-        else
+        } else {
             tc->setMiscRegNoEffect(ri.idx, value);
+        }
     }
 
     PCState pc(getOneRegU64(INT_REG(regs.pc)));
index 6332b8f4d54e948b4ddb5806248f5ac3a41650a9..35086748840c161d19759062402d95ccbee5a3df 100644 (file)
@@ -318,11 +318,6 @@ GenericTimer::createTimers(unsigned cpus)
 void
 GenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val)
 {
-    // This method might have been called from another context if we
-    // are running in multi-core KVM. Migrate to the SimObject's event
-    // queue to prevent surprising race conditions.
-    EventQueue::ScopedMigration migrate(eventQueue());
-
     CoreTimers &core(getTimers(cpu));
 
     switch (reg) {
@@ -415,11 +410,6 @@ GenericTimer::setMiscReg(int reg, unsigned cpu, MiscReg val)
 MiscReg
 GenericTimer::readMiscReg(int reg, unsigned cpu)
 {
-    // This method might have been called from another context if we
-    // are running in multi-core KVM. Migrate to the SimObject's event
-    // queue to prevent surprising race conditions.
-    EventQueue::ScopedMigration migrate(eventQueue());
-
     CoreTimers &core(getTimers(cpu));
 
     switch (reg) {