summaryrefslogtreecommitdiff
path: root/src/dev/arm/generic_timer.cc
diff options
context:
space:
mode:
authorCurtis Dunham <Curtis.Dunham@arm.com>2017-05-22 19:22:14 +0000
committerAndreas Sandberg <andreas.sandberg@arm.com>2017-07-05 14:24:03 +0000
commite1c8c1f8603672823c89e5ed4c98502350c600d6 (patch)
tree8d8c921888ab7eaaeb9a14be6e0ec51445689854 /src/dev/arm/generic_timer.cc
parente2a049e089b4878d6abd8e816973b175e2be2d7c (diff)
downloadgem5-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/arm/generic_timer.cc')
-rw-r--r--src/dev/arm/generic_timer.cc21
1 files changed, 14 insertions, 7 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));
}
}