[XEN] localtime support for paravirtualized guests
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 21 Jun 2006 16:09:14 +0000 (17:09 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Wed, 21 Jun 2006 16:09:14 +0000 (17:09 +0100)
It is quite minimal
in its approach, satisfying the purposes of the paravirtualized
NetWare operating system as well as any others that expect the time
base to be provided in localtime.

Signed-off-by: Bruce Rogers <brogers@novell.com>
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xm/create.py
xen/arch/x86/time.c
xen/common/dom0_ops.c
xen/include/public/dom0_ops.h
xen/include/xen/sched.h

index 4f1d8561daad56765e8993c923a2caf281e196f2..51117117f407d985f2d9b79d556b1df48e24a93f 100644 (file)
@@ -286,6 +286,17 @@ int xc_domain_setmaxmem(int xc_handle,
     return do_dom0_op(xc_handle, &op);
 }
 
+int xc_domain_set_time_offset(int xc_handle,
+                              uint32_t domid,
+                              int32_t time_offset_seconds)
+{
+    DECLARE_DOM0_OP;
+    op.cmd = DOM0_SETTIMEOFFSET;
+    op.u.settimeoffset.domain = (domid_t)domid;
+    op.u.settimeoffset.time_offset_seconds = time_offset_seconds;
+    return do_dom0_op(xc_handle, &op);
+}
+
 int xc_domain_memory_increase_reservation(int xc_handle,
                                           uint32_t domid,
                                           unsigned long nr_extents,
index f6093752b6020f66907589a18f295631cd1f0f16..c18f1807ab2de1dcb8ef064f9efc5e0823d2d513 100644 (file)
@@ -410,6 +410,10 @@ int xc_domain_setmaxmem(int xc_handle,
                         uint32_t domid,
                         unsigned int max_memkb);
 
+int xc_domain_set_time_offset(int xc_handle,
+                              uint32_t domid,
+                              int32_t time_offset_seconds);
+
 int xc_domain_memory_increase_reservation(int xc_handle,
                                           uint32_t domid,
                                           unsigned long nr_extents,
index d85f0f71070312c0ef4a6bae0bea8040395224a8..db42ab058a5c787b3a5c0b3a3d3ca05a9080f761 100644 (file)
@@ -869,6 +869,30 @@ static PyObject *pyxc_domain_iomem_permission(PyObject *self,
     return zero;
 }
 
+static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args)
+{
+    uint32_t dom;
+    int32_t time_offset_seconds;
+    time_t calendar_time;
+    struct tm local_time;
+    struct tm utc_time;
+
+    if (!PyArg_ParseTuple(args, "i", &dom))
+        return NULL;
+
+    calendar_time = time(NULL);
+    localtime_r(&calendar_time, &local_time);
+    gmtime_r(&calendar_time, &utc_time);
+    /* set up to get calendar time based on utc_time, with local dst setting */
+    utc_time.tm_isdst = local_time.tm_isdst;
+    time_offset_seconds = (int32_t)difftime(calendar_time, mktime(&utc_time));
+
+    if (xc_domain_set_time_offset(self->xc_handle, dom, time_offset_seconds) != 0)
+        return NULL;
+
+    Py_INCREF(zero);
+    return zero;
+}
 
 static PyObject *dom_op(XcObject *self, PyObject *args,
                         int (*fn)(int, uint32_t))
@@ -1208,6 +1232,13 @@ static PyMethodDef pyxc_methods[] = {
       "Returns: [int]: The size in KiB of memory spanning the given number "
       "of pages.\n" },
 
+    { "domain_set_time_offset",
+      (PyCFunction)pyxc_domain_set_time_offset,
+      METH_VARARGS, "\n"
+      "Set a domain's time offset to Dom0's localtime\n"
+      " dom        [int]: Domain whose time offset is being set.\n"
+      "Returns: [int] 0 on success; -1 on error.\n" },
+
     { NULL, NULL, 0, NULL }
 };
 
index 0dd3a54eef76e1cf297b81846e924ef8ac76f16c..665eb927d3f3f3c05f039585f66341d4df7e6b15 100644 (file)
@@ -135,6 +135,7 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [
     ('bootloader', str),
     ('bootloader_args', str),
     ('features', str),
+    ('localtime', int),
     ]
 
 ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS
@@ -1260,6 +1261,10 @@ class XendDomainInfo:
                                       self.info['image'],
                                       self.info['device'])
 
+            localtime = self.info['localtime']
+            if localtime is not None and localtime == 1:
+                xc.domain_set_time_offset(self.domid)
+
             xc.domain_setcpuweight(self.domid, self.info['cpu_weight'])
 
             # repin domain vcpus if a restricted cpus list is provided
index f4e05ae6678c32c50dde5d3119461a3107452839..3eadebb37dcb89ec0dae6dade1b0652d4c75c6e5 100644 (file)
@@ -672,6 +672,8 @@ def make_config(vals):
         config.append(['backend', ['netif']])
     if vals.tpmif:
         config.append(['backend', ['tpmif']])
+    if vals.localtime:
+        config.append(['localtime', vals.localtime])
 
     config_image = configure_image(vals)
     if vals.bootloader:
index 54a3ce41d4101d4ed36a21c6136358a69178c057..9d344b83492e986351da280d5228f56aef654ee8 100644 (file)
@@ -699,7 +699,7 @@ void update_domain_wallclock_time(struct domain *d)
 {
     spin_lock(&wc_lock);
     version_update_begin(&d->shared_info->wc_version);
-    d->shared_info->wc_sec  = wc_sec;
+    d->shared_info->wc_sec  = wc_sec + d->time_offset_seconds;
     d->shared_info->wc_nsec = wc_nsec;
     version_update_end(&d->shared_info->wc_version);
     spin_unlock(&wc_lock);
index a6e437abd1aeefd174c0916b6c5b12b0aaf8b1e2..91cbc60be8d4ae96e7e51c26b48126db2691896f 100644 (file)
@@ -693,6 +693,21 @@ long do_dom0_op(XEN_GUEST_HANDLE(dom0_op_t) u_dom0_op)
     break;
 #endif
 
+    case DOM0_SETTIMEOFFSET:
+    {
+        struct domain *d;
+
+        ret = -ESRCH;
+        d = find_domain_by_id(op->u.settimeoffset.domain);
+        if ( d != NULL )
+        {
+            d->time_offset_seconds = op->u.settimeoffset.time_offset_seconds;
+            put_domain(d);
+            ret = 0;
+        }
+    }
+    break;
+
     default:
         ret = arch_do_dom0_op(op, u_dom0_op);
         break;
index 07affaa6997a42f1a7ee9dbbe0945b0f02296439..d1113b655bfe851646caf3baca9489d9e749d821 100644 (file)
@@ -527,6 +527,14 @@ typedef struct dom0_domain_setup {
 } dom0_domain_setup_t;
 DEFINE_XEN_GUEST_HANDLE(dom0_domain_setup_t);
 
+#define DOM0_SETTIMEOFFSET    50
+struct dom0_settimeoffset {
+    domid_t  domain;
+    int32_t  time_offset_seconds; /* applied to domain wallclock time */
+};
+typedef struct dom0_settimeoffset dom0_settimeoffset_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_settimeoffset_t);
+
 struct dom0_op {
     uint32_t cmd;
     uint32_t interface_version; /* DOM0_INTERFACE_VERSION */
@@ -569,6 +577,7 @@ struct dom0_op {
         struct dom0_iomem_permission  iomem_permission;
         struct dom0_hypercall_init    hypercall_init;
         struct dom0_domain_setup      domain_setup;
+        struct dom0_settimeoffset     settimeoffset;
         uint8_t                       pad[128];
     } u;
 };
index 70869a51aff6dcd97116f324f2599ff1d7e19d05..e78ff4f619320ae8c18fd90fd4574bfe849a6a5d 100644 (file)
@@ -159,6 +159,7 @@ struct domain
 
     /* OProfile support. */
     struct xenoprof *xenoprof;
+    int32_t time_offset_seconds;
 };
 
 struct domain_setup_info