[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen master] x86/HVM: RTC code must be in line with WAET flags passed by hvmloader



commit 3fa7fb8b86b89167153fa457b27620436d648969
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Tue May 21 10:15:13 2013 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Tue May 21 10:15:13 2013 +0200

    x86/HVM: RTC code must be in line with WAET flags passed by hvmloader
    
    With hvmloader telling the guest that it may skip REG_C reads during
    the processing of RTC interrupts, the emulation code must not depend
    upon these reads to occur. Introduce two modes of operation for the
    emulation code, and short of a HVM parameter (too late to be
    introduced for 4.3) hard code the mode determination to always assume
    that Windows-conforming one for the time being.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Tested-by: Roger Pau Monné <roger.pau@xxxxxxxxxx> (FreeBSD guest)
---
 tools/firmware/hvmloader/acpi/static_tables.c |   12 ++++++++----
 xen/arch/x86/hvm/rtc.c                        |   19 +++++++++++++++----
 2 files changed, 23 insertions(+), 8 deletions(-)

diff --git a/tools/firmware/hvmloader/acpi/static_tables.c 
b/tools/firmware/hvmloader/acpi/static_tables.c
index f98c8d2..323ae31 100644
--- a/tools/firmware/hvmloader/acpi/static_tables.c
+++ b/tools/firmware/hvmloader/acpi/static_tables.c
@@ -136,11 +136,15 @@ struct acpi_20_rsdp Rsdp = {
     .length    = sizeof(struct acpi_20_rsdp)
 };
 
-#define ACPI_WAET_RTC_GOOD      0x00000001
-#define ACPI_WAET_PM_TIMER_GOOD 0x00000002
+#define ACPI_WAET_RTC_NO_ACK        (1<<0) /* RTC requires no int acknowledge 
*/
+#define ACPI_WAET_TIMER_ONE_READ    (1<<1) /* PM timer requires only one read 
*/
 
-#define ACPI_WAET_FLAGS (ACPI_WAET_RTC_GOOD | \
-                         ACPI_WAET_PM_TIMER_GOOD)
+/*
+ * The state of the RTC flag getting passed to the guest must be in
+ * sync with the mode selection in the hypervisor RTC emulation code.
+ */
+#define ACPI_WAET_FLAGS (ACPI_WAET_RTC_NO_ACK | \
+                         ACPI_WAET_TIMER_ONE_READ)
 
 struct acpi_20_waet Waet = {
     .header = {
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index 77b380f..d1a6848 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -45,6 +45,15 @@
 #define epoch_year     1900
 #define get_year(x)    (x + epoch_year)
 
+enum rtc_mode {
+   rtc_mode_no_ack,
+   rtc_mode_strict
+};
+
+/* This must be in sync with how hvmloader sets the ACPI WAET flags. */
+#define mode_is(d, m) ((void)(d), rtc_mode_##m == rtc_mode_no_ack)
+#define rtc_mode_is(s, m) mode_is(vrtc_domain(s), m)
+
 static void rtc_copy_date(RTCState *s);
 static void rtc_set_time(RTCState *s);
 static inline int from_bcd(RTCState *s, int a);
@@ -54,7 +63,7 @@ static void rtc_update_irq(RTCState *s)
 {
     ASSERT(spin_is_locked(&s->lock));
 
-    if ( s->hw.cmos_data[RTC_REG_C] & RTC_IRQF )
+    if ( rtc_mode_is(s, strict) && (s->hw.cmos_data[RTC_REG_C] & RTC_IRQF) )
         return;
 
     /* IRQ is raised if any source is both raised & enabled */
@@ -64,6 +73,8 @@ static void rtc_update_irq(RTCState *s)
         return;
 
     s->hw.cmos_data[RTC_REG_C] |= RTC_IRQF;
+    if ( rtc_mode_is(s, no_ack) )
+        hvm_isa_irq_deassert(vrtc_domain(s), RTC_IRQ);
     hvm_isa_irq_assert(vrtc_domain(s), RTC_IRQ);
 }
 
@@ -73,8 +84,8 @@ bool_t rtc_periodic_interrupt(void *opaque)
     bool_t ret;
 
     spin_lock(&s->lock);
-    ret = !(s->hw.cmos_data[RTC_REG_C] & RTC_IRQF);
-    if ( !(s->hw.cmos_data[RTC_REG_C] & RTC_PF) )
+    ret = rtc_mode_is(s, no_ack) || !(s->hw.cmos_data[RTC_REG_C] & RTC_IRQF);
+    if ( rtc_mode_is(s, no_ack) || !(s->hw.cmos_data[RTC_REG_C] & RTC_PF) )
     {
         s->hw.cmos_data[RTC_REG_C] |= RTC_PF;
         rtc_update_irq(s);
@@ -633,7 +644,7 @@ static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
     case RTC_REG_C:
         ret = s->hw.cmos_data[s->hw.cmos_index];
         s->hw.cmos_data[RTC_REG_C] = 0x00;
-        if ( ret & RTC_IRQF )
+        if ( (ret & RTC_IRQF) && !rtc_mode_is(s, no_ack) )
             hvm_isa_irq_deassert(d, RTC_IRQ);
         rtc_update_irq(s);
         check_update_timer(s);
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.