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

[Xen-changelog] [xen-unstable] [hvm] Keep track of time offset between domain time and dom0 time.



# HG changeset patch
# User Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
# Date 1175602957 -3600
# Node ID 7e431ea834a877b1f0c90bdb1e6f1346da4e81cc
# Parent  cd01741aaa93daea020f8cba7f2b840255de9846
[hvm] Keep track of time offset between domain time and dom0 time.
On each rtc time update from the hvm domain, we send an ioreq request
to qemu which then updates the time offset xenstore entry.  The time
offset is preserved across reboot and can be set on domain creation
by setting the rtc_timeoffset variable in a config file.

From: Andrei Petrov <andrei.petrov@xxxxxxxxxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
---
 tools/examples/xmexample.hvm            |    4 +
 tools/ioemu/target-i386-dm/helper2.c    |   33 +++++++++++++++
 tools/ioemu/vl.c                        |    3 +
 tools/ioemu/vl.h                        |    6 ++
 tools/ioemu/xenstore.c                  |   69 ++++++++++++++++++++++++++++++++
 tools/python/xen/xend/XendConfig.py     |    3 -
 tools/python/xen/xend/XendDomainInfo.py |    8 +++
 tools/python/xen/xend/image.py          |    3 +
 tools/python/xen/xm/create.py           |    6 ++
 xen/arch/x86/hvm/intercept.c            |   38 ++++++++++-------
 xen/arch/x86/hvm/platform.c             |   20 +++++++++
 xen/arch/x86/hvm/rtc.c                  |    8 +++
 xen/arch/x86/time.c                     |    2 
 xen/include/asm-x86/hvm/io.h            |    2 
 xen/include/asm-x86/time.h              |    5 ++
 xen/include/public/hvm/ioreq.h          |    1 
 16 files changed, 191 insertions(+), 20 deletions(-)

diff -r cd01741aaa93 -r 7e431ea834a8 tools/examples/xmexample.hvm
--- a/tools/examples/xmexample.hvm      Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/examples/xmexample.hvm      Tue Apr 03 13:22:37 2007 +0100
@@ -180,6 +180,10 @@ serial='pty'
 
 
 #-----------------------------------------------------------------------------
+#    set the real time clock offset in seconds [default=0 i.e. same as dom0]
+#rtc_timeoffset=3600
+
+#-----------------------------------------------------------------------------
 #    start in full screen
 #full-screen=1   
 
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c      Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/target-i386-dm/helper2.c      Tue Apr 03 13:22:37 2007 +0100
@@ -73,6 +73,8 @@ int vcpus = 1;
 int vcpus = 1;
 
 int xc_handle;
+
+long time_offset = 0;
 
 shared_iopage_t *shared_page = NULL;
 
@@ -439,6 +441,34 @@ void cpu_ioreq_xor(CPUState *env, ioreq_
     req->data = tmp1;
 }
 
+void timeoffset_get()
+{
+    char *p;
+
+    p = xenstore_vm_read(domid, "rtc/timeoffset", NULL);
+    if (!p)
+       return;
+
+    if (sscanf(p, "%ld", &time_offset) == 1)
+       fprintf(logfile, "Time offset set %ld\n", time_offset);
+    else
+       time_offset = 0;
+
+    xc_domain_set_time_offset(xc_handle, domid, time_offset);
+
+    free(p);
+}
+
+void cpu_ioreq_timeoffset(CPUState *env, ioreq_t *req)
+{
+    char b[64];
+
+    time_offset += (ulong)req->data;
+
+    sprintf(b, "%ld", time_offset);
+    xenstore_vm_write(domid, "rtc/timeoffset", b);
+}
+
 void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
 {
     unsigned long tmp1;
@@ -478,6 +508,9 @@ void __handle_ioreq(CPUState *env, ioreq
     case IOREQ_TYPE_XCHG:
         cpu_ioreq_xchg(env, req);
         break;
+    case IOREQ_TYPE_TIMEOFFSET:
+       cpu_ioreq_timeoffset(env, req);
+       break;
     default:
         hw_error("Invalid ioreq type 0x%x\n", req->type);
     }
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c  Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/vl.c  Tue Apr 03 13:22:37 2007 +0100
@@ -6670,6 +6670,9 @@ int main(int argc, char **argv)
     }
     free(page_array);
 #endif
+
+    timeoffset_get();
+
 #else  /* !CONFIG_DM */
 
     phys_ram_base = qemu_vmalloc(phys_ram_size);
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h  Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/vl.h  Tue Apr 03 13:22:37 2007 +0100
@@ -1276,6 +1276,12 @@ int xenstore_unsubscribe_from_hotplug_st
                                              const char *inst,
                                              const char *token);
 
+int xenstore_vm_write(int domid, char *key, char *val);
+char *xenstore_vm_read(int domid, char *key, int *len);
+
+/* helper2.c */
+extern long time_offset;
+void timeoffset_get(void);
 
 /* xen_platform.c */
 void pci_xen_platform_init(PCIBus *bus);
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c    Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/xenstore.c    Tue Apr 03 13:22:37 2007 +0100
@@ -567,3 +567,72 @@ int xenstore_unsubscribe_from_hotplug_st
 
     return rc;
 }
+
+char *xenstore_vm_read(int domid, char *key, int *len)
+{
+    char *buf = NULL, *path = NULL, *value = NULL;
+
+    if (xsh == NULL)
+       goto out;
+
+    path = xs_get_domain_path(xsh, domid);
+    if (path == NULL) {
+       fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
+       goto out;
+    }
+
+    pasprintf(&buf, "%s/vm", path);
+    free(path);
+    path = xs_read(xsh, XBT_NULL, buf, NULL);
+    if (path == NULL) {
+       fprintf(logfile, "xs_read(%s): read error\n", buf);
+       goto out;
+    }
+
+    pasprintf(&buf, "%s/%s", path, key);
+    value = xs_read(xsh, XBT_NULL, buf, len);
+    if (value == NULL) {
+       fprintf(logfile, "xs_read(%s): read error\n", buf);
+       goto out;
+    }
+
+ out:
+    free(path);
+    free(buf);
+    return value;
+}
+
+int xenstore_vm_write(int domid, char *key, char *value)
+{
+    char *buf = NULL, *path = NULL;
+    int rc = -1;
+
+    if (xsh == NULL)
+       goto out;
+
+    path = xs_get_domain_path(xsh, domid);
+    if (path == NULL) {
+       fprintf(logfile, "xs_get_domain_path(%d): error\n");
+       goto out;
+    }
+
+    pasprintf(&buf, "%s/vm", path);
+    free(path);
+    path = xs_read(xsh, XBT_NULL, buf, NULL);
+    if (path == NULL) {
+       fprintf(logfile, "xs_read(%s): read error\n", buf);
+       goto out;
+    }
+
+    pasprintf(&buf, "%s/%s", path, key);
+    rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
+    if (rc) {
+       fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
+       goto out;
+    }
+
+ out:
+    free(path);
+    free(buf);
+    return rc;
+}
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Tue Apr 03 13:22:37 2007 +0100
@@ -118,7 +118,7 @@ LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(
 # Platform configuration keys.
 XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display', 
                         'fda', 'fdb', 'keymap', 'isa', 'localtime',
-                        'nographic', 'pae', 'serial', 'sdl',
+                        'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
                         'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
                         'vncconsole', 'vncdisplay', 'vnclisten',
                         'vncpasswd', 'vncunused', 'xauthority']
@@ -203,6 +203,7 @@ LEGACY_CFG_TYPES = {
     'on_xend_stop':  str,
     'on_xend_start': str,
     'online_vcpus':  int,
+    'rtc/timeoffset': str,
 }
 
 # Values that should be stored in xenstore's /vm/<uuid> that is used
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Tue Apr 03 13:22:37 2007 +0100
@@ -859,7 +859,8 @@ class XendDomainInfo:
         # Check whether values in the configuration have
         # changed in Xenstore.
         
-        cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash']
+        cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash',
+                  'rtc/timeoffset']
         
         vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
                                            for k in cfg_vm])
@@ -888,6 +889,11 @@ class XendDomainInfo:
             self.info.update_with_image_sxp(sxp.from_string(image_sxp))
             changed = True
 
+        # Check if the rtc offset has changes
+        if vm_details.get("rtc/timeoffset", 0) != 
self.info["platform"].get("rtc_timeoffset", 0):
+            self.info["platform"]["rtc_timeoffset"] = 
vm_details.get("rtc/timeoffset", 0)
+            changed = True
+ 
         if changed:
             # Update the domain section of the store, as this contains some
             # parameters derived from the VM configuration.
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py    Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xend/image.py    Tue Apr 03 13:22:37 2007 +0100
@@ -256,9 +256,12 @@ class HVMImageHandler(ImageHandler):
         self.xauthority = vmConfig['platform'].get('xauthority')
         self.vncconsole = vmConfig['platform'].get('vncconsole')
 
+        rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
+
         self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
                         ("image/device-model", self.device_model),
                         ("image/display", self.display))
+        self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
 
         self.pid = None
 
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xm/create.py     Tue Apr 03 13:22:37 2007 +0100
@@ -185,6 +185,10 @@ gopts.var('cpus', val='CPUS',
 gopts.var('cpus', val='CPUS',
           fn=set_value, default=None,
           use="CPUS to run the domain on.")
+
+gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
+          fn=set_value, default="0",
+          use="Set RTC offset.")
 
 gopts.var('pae', val='PAE',
           fn=set_int, default=1,
@@ -717,7 +721,7 @@ def configure_hvm(config_image, vals):
     args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
              'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
              'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
-             'sdl', 'display', 'xauthority',
+             'sdl', 'display', 'xauthority', 'rtc_timeoffset',
              'acpi', 'apic', 'usb', 'usbdevice', 'keymap' ]
     for a in args:
         if a in vals.__dict__ and vals.__dict__[a] is not None:
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c      Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/hvm/intercept.c      Tue Apr 03 13:22:37 2007 +0100
@@ -155,28 +155,13 @@ static inline void hvm_mmio_access(struc
     }
 }
 
-int hvm_buffered_io_intercept(ioreq_t *p)
+int hvm_buffered_io_send(ioreq_t *p)
 {
     struct vcpu *v = current;
     spinlock_t  *buffered_io_lock;
     buffered_iopage_t *buffered_iopage =
         (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
     unsigned long tmp_write_pointer = 0;
-    int i;
-
-    /* ignore READ ioreq_t! */
-    if ( p->dir == IOREQ_READ )
-        return 0;
-
-    for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
-        if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
-             p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
-                                     hvm_buffered_io_ranges[i]->length )
-            break;
-    }
-
-    if ( i == HVM_BUFFERED_IO_RANGE_NR )
-        return 0;
 
     buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
     spin_lock(buffered_io_lock);
@@ -205,6 +190,27 @@ int hvm_buffered_io_intercept(ioreq_t *p
     return 1;
 }
 
+int hvm_buffered_io_intercept(ioreq_t *p)
+{
+    int i;
+
+    /* ignore READ ioreq_t! */
+    if ( p->dir == IOREQ_READ )
+        return 0;
+
+    for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
+        if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
+             p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
+                                     hvm_buffered_io_ranges[i]->length )
+            break;
+    }
+
+    if ( i == HVM_BUFFERED_IO_RANGE_NR )
+        return 0;
+
+    return hvm_buffered_io_send(p);
+}
+
 int hvm_mmio_intercept(ioreq_t *p)
 {
     struct vcpu *v = current;
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c       Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/hvm/platform.c       Tue Apr 03 13:22:37 2007 +0100
@@ -921,6 +921,26 @@ static void send_mmio_req(unsigned char 
     hvm_send_assist_req(v);
 }
 
+void send_timeoffset_req(unsigned long timeoff)
+{
+    ioreq_t p[1];
+
+    if ( timeoff == 0 )
+        return;
+
+    memset(p, 0, sizeof(*p));
+
+    p->type = IOREQ_TYPE_TIMEOFFSET;
+    p->size = 4;
+    p->dir = IOREQ_WRITE;
+    p->data = timeoff;
+
+    p->state = STATE_IOREQ_READY;
+
+    if ( !hvm_buffered_io_send(p) )
+        printk("Unsuccessful timeoffset update\n");
+}
+
 static void mmio_operands(int type, unsigned long gpa,
                           struct hvm_io_op *mmio_op,
                           unsigned char op_size)
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c    Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/hvm/rtc.c    Tue Apr 03 13:22:37 2007 +0100
@@ -157,6 +157,10 @@ static void rtc_set_time(RTCState *s)
 static void rtc_set_time(RTCState *s)
 {
     struct tm *tm = &s->current_tm;
+    unsigned long before, after; /* XXX s_time_t */
+      
+    before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+                   tm->tm_hour, tm->tm_min, tm->tm_sec);
     
     tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
     tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
@@ -168,6 +172,10 @@ static void rtc_set_time(RTCState *s)
     tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
     tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
     tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100;
+
+    after = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+                   tm->tm_hour, tm->tm_min, tm->tm_sec);
+    send_timeoffset_req(after - before);
 }
 
 static void rtc_copy_date(RTCState *s)
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/time.c       Tue Apr 03 13:22:37 2007 +0100
@@ -573,7 +573,7 @@ static void init_platform_timer(void)
  * machines were long is 32-bit! (However, as time_t is signed, we
  * will already get problems at other places on 2038-01-19 03:14:08)
  */
-static inline unsigned long
+unsigned long
 mktime (unsigned int year, unsigned int mon,
         unsigned int day, unsigned int hour,
         unsigned int min, unsigned int sec)
diff -r cd01741aaa93 -r 7e431ea834a8 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h      Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/include/asm-x86/hvm/io.h      Tue Apr 03 13:22:37 2007 +0100
@@ -127,6 +127,7 @@ static inline int hvm_portio_intercept(i
 }
 
 extern int hvm_mmio_intercept(ioreq_t *p);
+extern int hvm_buffered_io_send(ioreq_t *p);
 extern int hvm_buffered_io_intercept(ioreq_t *p);
 
 static inline int register_portio_handler(
@@ -145,6 +146,7 @@ static inline int irq_masked(unsigned lo
 
 extern void send_pio_req(unsigned long port, unsigned long count, int size,
                          paddr_t value, int dir, int df, int value_is_ptr);
+void send_timeoffset_req(unsigned long timeoff);
 extern void handle_mmio(unsigned long gpa);
 extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
 extern void hvm_io_assist(struct vcpu *v);
diff -r cd01741aaa93 -r 7e431ea834a8 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/include/asm-x86/time.h        Tue Apr 03 13:22:37 2007 +0100
@@ -16,4 +16,9 @@ static inline cycles_t get_cycles(void)
     return c;
 }
 
+unsigned long
+mktime (unsigned int year, unsigned int mon,
+        unsigned int day, unsigned int hour,
+        unsigned int min, unsigned int sec);
+
 #endif /* __X86_TIME_H__ */
diff -r cd01741aaa93 -r 7e431ea834a8 xen/include/public/hvm/ioreq.h
--- a/xen/include/public/hvm/ioreq.h    Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/include/public/hvm/ioreq.h    Tue Apr 03 13:22:37 2007 +0100
@@ -39,6 +39,7 @@
 #define IOREQ_TYPE_XOR          4
 #define IOREQ_TYPE_XCHG         5
 #define IOREQ_TYPE_ADD          6
+#define IOREQ_TYPE_TIMEOFFSET   7
 
 /*
  * VMExit dispatcher should cooperate with instruction decoder to

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
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®.