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");
+ }
}
}
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);
+ }
}
}
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
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));
}
}
#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"
void counterLimitReached();
EventFunctionWrapper _counterLimitReachedEvent;
+ virtual bool scheduleEvents() { return true; }
+
public:
ArchTimer(const std::string &name,
SimObject &parent,
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:
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
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;