x86/vhpet: fix RTC special casing
authorRoger Pau Monné <roger.pau@citrix.com>
Fri, 7 May 2021 08:43:29 +0000 (10:43 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 7 May 2021 08:43:29 +0000 (10:43 +0200)
Restore setting the virtual timer callback private data to NULL if the
timer is not level triggered. This fixes the special casing done in
pt_update_irq so that the RTC interrupt when originating from the HPET
is suspended if the interrupt source is masked.

Note the RTC special casing done in pt_update_irq should only apply to
the RTC interrupt originating from the emulated RTC device (which does
set the callback private data), as in that case the callback itself
will destroy the virtual timer if the interrupt is ignored.

While there also use RTC_IRQ instead of 8 when the HPET is configured
in LegacyReplacement Mode.

Fixes: be07023be115 ("x86/vhpet: add support for level triggered interrupts")
Reported-by: Jan Beulich <jbeulich@suse.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
xen/arch/x86/hvm/hpet.c

index ca94e8b4538c092743f081651b2655e5f6c6e05e..ee756abb824de13ababc0863595c9bb19714b989 100644 (file)
@@ -22,6 +22,7 @@
 #include <asm/hvm/trace.h>
 #include <asm/current.h>
 #include <asm/hpet.h>
+#include <asm/mc146818rtc.h>
 #include <xen/sched.h>
 #include <xen/event.h>
 #include <xen/trace.h>
@@ -290,7 +291,7 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
         /* if LegacyReplacementRoute bit is set, HPET specification requires
            timer0 be routed to IRQ0 in NON-APIC or IRQ2 in the I/O APIC,
            timer1 be routed to IRQ8 in NON-APIC or IRQ8 in the I/O APIC. */
-        irq = (tn == 0) ? 0 : 8;
+        irq = (tn == 0) ? 0 : RTC_IRQ;
         h->pt[tn].source = PTSRC_isa;
     }
     else
@@ -318,7 +319,8 @@ static void hpet_set_timer(HPETState *h, unsigned int tn,
                          hpet_tick_to_ns(h, diff),
                          oneshot ? 0 : hpet_tick_to_ns(h, h->hpet.period[tn]),
                          irq, timer_level(h, tn) ? hpet_timer_fired : NULL,
-                         (void *)(unsigned long)tn, timer_level(h, tn));
+                         timer_level(h, tn) ? (void *)(unsigned long)tn : NULL,
+                         timer_level(h, tn));
 }
 
 static inline uint64_t hpet_fixup_reg(