diff options
Diffstat (limited to 'src/dev/arm')
-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; |