summaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorLaurent Vivier <laurent@vivier.eu>2019-11-25 15:14:14 +0100
committerDavid Gibson <david@gibson.dropbear.id.au>2019-11-26 10:11:50 +1100
commit6cf80f90c441e86f2e92c8a07d6b29ca3f1d43e8 (patch)
treea6e3485788a5591e579a25da904f7e9d4a4bf0bb /hw
parentb14848f5d757cbe89dfd1ee68ce701a8277c2f17 (diff)
downloadqemu-6cf80f90c441e86f2e92c8a07d6b29ca3f1d43e8.zip
mos6522: update counters when timer interrupts are off
Even if the interrupts are off, counters must be updated because they are running anyway and kernel can try to read them (it's the case with g3beige kernel). Reported-by: Andrew Randrianasulu <randrianasulu@gmail.com> Signed-off-by: Laurent Vivier <laurent@vivier.eu> Message-Id: <20191125141414.5015-1-laurent@vivier.eu> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'hw')
-rw-r--r--hw/misc/mos6522.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c
index aa3bfe1afd..cecf0be59e 100644
--- a/hw/misc/mos6522.c
+++ b/hw/misc/mos6522.c
@@ -113,6 +113,10 @@ static int64_t get_next_irq_time(MOS6522State *s, MOS6522Timer *ti,
int64_t d, next_time;
unsigned int counter;
+ if (ti->frequency == 0) {
+ return INT64_MAX;
+ }
+
/* current counter value */
d = muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - ti->load_time,
ti->frequency, NANOSECONDS_PER_SECOND);
@@ -149,10 +153,10 @@ static void mos6522_timer1_update(MOS6522State *s, MOS6522Timer *ti,
if (!ti->timer) {
return;
}
+ ti->next_irq_time = get_next_irq_time(s, ti, current_time);
if ((s->ier & T1_INT) == 0 || (s->acr & T1MODE) != T1MODE_CONT) {
timer_del(ti->timer);
} else {
- ti->next_irq_time = get_next_irq_time(s, ti, current_time);
timer_mod(ti->timer, ti->next_irq_time);
}
}
@@ -163,10 +167,10 @@ static void mos6522_timer2_update(MOS6522State *s, MOS6522Timer *ti,
if (!ti->timer) {
return;
}
+ ti->next_irq_time = get_next_irq_time(s, ti, current_time);
if ((s->ier & T2_INT) == 0) {
timer_del(ti->timer);
} else {
- ti->next_irq_time = get_next_irq_time(s, ti, current_time);
timer_mod(ti->timer, ti->next_irq_time);
}
}