aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/rtc.c
diff options
context:
space:
mode:
authorYang Zhang <yang.z.zhang@Intel.com>2012-03-07 07:36:15 +0000
committerYang Zhang <yang.z.zhang@Intel.com>2012-03-07 07:36:15 +0000
commit197c12b1a19f5fe05adf8359ff9013f43ba027da (patch)
treec24022d74341258720c5981d8e84d5235b9e72d9 /xen/arch/x86/hvm/rtc.c
parent6c44cee772fbbf3d35698ed544079e02f4e7c97e (diff)
downloadxen-197c12b1a19f5fe05adf8359ff9013f43ba027da.tar.gz
xen-197c12b1a19f5fe05adf8359ff9013f43ba027da.tar.bz2
xen-197c12b1a19f5fe05adf8359ff9013f43ba027da.zip
RTC: Add UIP(update in progress) check logic
The UIP(update in progress) is set when RTC is in updating. And the update cycle begins 244us later after UIP is set. Signed-off-by: Yang Zhang <yang.z.zhang@Intel.com> Committed-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/hvm/rtc.c')
-rw-r--r--xen/arch/x86/hvm/rtc.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c
index b5fffc1634..00e5c83125 100644
--- a/xen/arch/x86/hvm/rtc.c
+++ b/xen/arch/x86/hvm/rtc.c
@@ -28,6 +28,8 @@
#include <asm/hvm/support.h>
#include <asm/current.h>
+#define USEC_PER_SEC 1000000UL
+
#define domain_vrtc(x) (&(x)->arch.hvm_domain.pl_time.vrtc)
#define vcpu_vrtc(x) (domain_vrtc((x)->domain))
#define vrtc_domain(x) (container_of((x), struct domain, \
@@ -239,6 +241,22 @@ static void rtc_copy_date(RTCState *s)
s->hw.cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
}
+static int update_in_progress(RTCState *s)
+{
+ uint64_t guest_usec;
+ struct domain *d = vrtc_domain(s);
+
+ if (s->hw.cmos_data[RTC_REG_B] & RTC_SET)
+ return 0;
+
+ guest_usec = get_localtime_us(d);
+ /* UIP bit will be set at last 244us of every second. */
+ if ((guest_usec % USEC_PER_SEC) >= (USEC_PER_SEC - 244))
+ return 1;
+
+ return 0;
+}
+
static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
{
int ret;
@@ -268,6 +286,8 @@ static uint32_t rtc_ioport_read(RTCState *s, uint32_t addr)
break;
case RTC_REG_A:
ret = s->hw.cmos_data[s->hw.cmos_index];
+ if (update_in_progress(s))
+ ret |= RTC_UIP;
break;
case RTC_REG_C:
ret = s->hw.cmos_data[s->hw.cmos_index];