diff options
author | Curtis Dunham <Curtis.Dunham@arm.com> | 2017-05-22 19:22:14 +0000 |
---|---|---|
committer | Andreas Sandberg <andreas.sandberg@arm.com> | 2017-07-05 14:24:03 +0000 |
commit | e1c8c1f8603672823c89e5ed4c98502350c600d6 (patch) | |
tree | 8d8c921888ab7eaaeb9a14be6e0ec51445689854 /src/dev | |
parent | e2a049e089b4878d6abd8e816973b175e2be2d7c (diff) | |
download | gem5-e1c8c1f8603672823c89e5ed4c98502350c600d6.tar.xz |
dev,arm: add Kvm mode of operation for CP15 timer
The timer device exposed via the ARM ISA, also known as the
"CP15 timer" due to its legacy coprocessor encodings, is
implemented by the GenericTimerISA class. During Kvm
execution, however, this functionality is directly emulated
by the hardware.
This commit subclasses the GenericTimer, which is (solely)
used by GenericTimerISA, to facilitate Kvm in much the same
way as the prior GIC changes: the gem5 model is used as the
backing store for state, so checkpointing and CPU switching
work correctly, but isn't used during Kvm execution.
The added indirection prevents the timer device from creating
events when we're just updating its state, but not actually
using it for simulation.
Change-Id: I427540d11ccf049c334afe318f575146aa888672
Reviewed-on: https://gem5-review.googlesource.com/3542
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
Diffstat (limited to 'src/dev')
-rw-r--r-- | src/dev/arm/generic_timer.cc | 21 | ||||
-rw-r--r-- | src/dev/arm/generic_timer.hh | 38 |
2 files changed, 47 insertions, 12 deletions
diff --git a/src/dev/arm/generic_timer.cc b/src/dev/arm/generic_timer.cc index 48f70e135..6332b8f4d 100644 --- a/src/dev/arm/generic_timer.cc +++ b/src/dev/arm/generic_timer.cc @@ -109,8 +109,12 @@ ArchTimer::counterLimitReached() DPRINTF(Timer, "Counter limit reached\n"); if (!_control.imask) { - DPRINTF(Timer, "Causing interrupt\n"); - _interrupt.send(); + if (scheduleEvents()) { + DPRINTF(Timer, "Causing interrupt\n"); + _interrupt.send(); + } else { + DPRINTF(Timer, "Kvm mode; skipping simulated interrupt\n"); + } } } @@ -122,10 +126,12 @@ ArchTimer::updateCounter() if (value() >= _counterLimit) { counterLimitReached(); } else { - const auto period(_systemCounter.period()); _control.istatus = 0; - _parent.schedule(_counterLimitReachedEvent, - curTick() + (_counterLimit - value()) * period); + if (scheduleEvents()) { + const auto period(_systemCounter.period()); + _parent.schedule(_counterLimitReachedEvent, + curTick() + (_counterLimit - value()) * period); + } } } @@ -234,12 +240,13 @@ ArchTimer::Interrupt::clear() GenericTimer::GenericTimer(GenericTimerParams *p) : SimObject(p), + system(*p->system), gic(p->gic), irqPhys(p->int_phys), irqVirt(p->int_virt) { fatal_if(!p->system, "No system specified, can't instantiate timer.\n"); - p->system->setGenericTimer(this); + system.setGenericTimer(this); } void @@ -303,7 +310,7 @@ GenericTimer::createTimers(unsigned cpus) timers.resize(cpus); for (unsigned i = old_cpu_count; i < cpus; ++i) { timers[i].reset( - new CoreTimers(*this, i, irqPhys, irqVirt)); + new CoreTimers(*this, system, i, irqPhys, irqVirt)); } } diff --git a/src/dev/arm/generic_timer.hh b/src/dev/arm/generic_timer.hh index 3eec1d42e..ccfb1277f 100644 --- a/src/dev/arm/generic_timer.hh +++ b/src/dev/arm/generic_timer.hh @@ -42,6 +42,7 @@ #define __DEV_ARM_GENERIC_TIMER_HH__ #include "arch/arm/isa_device.hh" +#include "arch/arm/system.hh" #include "base/bitunion.hh" #include "dev/arm/base_gic.hh" #include "sim/core.hh" @@ -159,6 +160,8 @@ class ArchTimer : public Serializable, public Drainable void counterLimitReached(); EventFunctionWrapper _counterLimitReachedEvent; + virtual bool scheduleEvents() { return true; } + public: ArchTimer(const std::string &name, SimObject &parent, @@ -201,6 +204,28 @@ class ArchTimer : public Serializable, public Drainable ArchTimer(const ArchTimer &t); }; +class ArchTimerKvm : public ArchTimer +{ + private: + ArmSystem &system; + + public: + ArchTimerKvm(const std::string &name, + ArmSystem &system, + SimObject &parent, + SystemCounter &sysctr, + const Interrupt &interrupt) + : ArchTimer(name, parent, sysctr, interrupt), system(system) {} + + protected: + // For ArchTimer's in a GenericTimerISA with Kvm execution about + // to begin, skip rescheduling the event. + // Otherwise, we should reschedule the event (if necessary). + bool scheduleEvents() override { + return !system.validKvmEnvironment(); + } +}; + class GenericTimer : public SimObject { public: @@ -215,25 +240,25 @@ class GenericTimer : public SimObject protected: struct CoreTimers { - CoreTimers(GenericTimer &parent, unsigned cpu, + CoreTimers(GenericTimer &parent, ArmSystem &system, unsigned cpu, unsigned _irqPhys, unsigned _irqVirt) : irqPhys(*parent.gic, _irqPhys, cpu), irqVirt(*parent.gic, _irqVirt, cpu), // This should really be phys_timerN, but we are stuck with // arch_timer for backwards compatibility. phys(csprintf("%s.arch_timer%d", parent.name(), cpu), - parent, parent.systemCounter, + system, parent, parent.systemCounter, irqPhys), virt(csprintf("%s.virt_timer%d", parent.name(), cpu), - parent, parent.systemCounter, + system, parent, parent.systemCounter, irqVirt) {} ArchTimer::Interrupt irqPhys; ArchTimer::Interrupt irqVirt; - ArchTimer phys; - ArchTimer virt; + ArchTimerKvm phys; + ArchTimerKvm virt; private: // Disable copying @@ -250,6 +275,9 @@ class GenericTimer : public SimObject std::vector<std::unique_ptr<CoreTimers>> timers; protected: // Configuration + /// ARM system containing this timer + ArmSystem &system; + /// Pointer to the GIC, needed to trigger timer interrupts. BaseGic *const gic; |