diff -r 85b7a341207e tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Thu Mar 30 13:06:11 2006 +++ b/tools/libxc/xc_domain.c Fri Mar 31 13:18:41 2006 @@ -257,6 +257,17 @@ 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, diff -r 85b7a341207e tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Thu Mar 30 13:06:11 2006 +++ b/tools/libxc/xenctrl.h Fri Mar 31 13:18:41 2006 @@ -385,6 +385,10 @@ 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, diff -r 85b7a341207e tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Thu Mar 30 13:06:11 2006 +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Mar 31 13:18:41 2006 @@ -826,6 +826,19 @@ return zero; } +static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args) +{ + uint32_t dom; + int32_t time_offset_seconds; + + if (!PyArg_ParseTuple(args, "i", &dom)) + return NULL; + + time_offset_seconds = -__timezone; + if (xc_domain_set_time_offset(self->xc_handle, dom, time_offset_seconds) != 0) + return NULL; + return zero; +} static PyObject *dom_op(XcObject *self, PyObject *args, int (*fn)(int, uint32_t)) @@ -1146,6 +1159,13 @@ METH_VARARGS, "\n" "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 } }; diff -r 85b7a341207e tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Thu Mar 30 13:06:11 2006 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Mar 31 13:18:41 2006 @@ -127,6 +127,7 @@ ('memory', int), ('maxmem', int), ('bootloader', str), + ('localtime', str), ] ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS @@ -1203,6 +1204,10 @@ self.info['image'], self.info['device']) + localtime = self.info['localtime'] + if localtime is not None and localtime == 'yes': + 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 diff -r 85b7a341207e tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Thu Mar 30 13:06:11 2006 +++ b/tools/python/xen/xm/create.py Fri Mar 31 13:18:41 2006 @@ -610,6 +610,8 @@ config.append(['backend', ['netif']]) if vals.tpmif: config.append(['backend', ['tpmif']]) + if vals.localtime: + config.append(['localtime', vals.localtime]) if vals.bootloader: config.append(['bootloader', vals.bootloader]) diff -r 85b7a341207e xen/arch/x86/time.c --- a/xen/arch/x86/time.c Thu Mar 30 13:06:11 2006 +++ b/xen/arch/x86/time.c Fri Mar 31 13:18:41 2006 @@ -716,7 +716,7 @@ { s = d->shared_info; version_update_begin(&s->wc_version); - s->wc_sec = _wc_sec; + s->wc_sec = _wc_sec + d->time_offset_seconds; s->wc_nsec = _wc_nsec; version_update_end(&s->wc_version); } @@ -725,11 +725,21 @@ read_unlock(&domlist_lock); } +void do_settimeoffset(struct domain *d, int32_t time_offset_seconds) +{ + shared_info_t *s; + + s = d->shared_info; + version_update_begin(&s->wc_version); + d->time_offset_seconds = time_offset_seconds; + version_update_end(&s->wc_version); +} + void init_domain_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); diff -r 85b7a341207e xen/common/dom0_ops.c --- a/xen/common/dom0_ops.c Thu Mar 30 13:06:11 2006 +++ b/xen/common/dom0_ops.c Fri Mar 31 13:18:42 2006 @@ -682,6 +682,20 @@ break; #endif + case DOM0_SETTIMEOFFSET: + { + struct domain *d; + + ret = -ESRCH; + d = find_domain_by_id(op->u.settimeoffset.domain); + if ( d != NULL ) + { + do_settimeoffset(d, op->u.settimeoffset.time_offset_seconds); + ret = 0; + } + } + break; + default: ret = arch_do_dom0_op(op, u_dom0_op); break; diff -r 85b7a341207e xen/include/public/dom0_ops.h --- a/xen/include/public/dom0_ops.h Thu Mar 30 13:06:11 2006 +++ b/xen/include/public/dom0_ops.h Fri Mar 31 13:18:42 2006 @@ -470,6 +470,12 @@ unsigned long mfn; /* machine frame to be initialised */ } dom0_hypercall_init_t; DEFINE_GUEST_HANDLE(dom0_hypercall_init_t); + +#define DOM0_SETTIMEOFFSET 49 +typedef struct dom0_settimeoffset { + domid_t domain; + int32_t time_offset_seconds; /* applied to domain wallclock time */ +} dom0_settimeoffset_t; typedef struct dom0_op { uint32_t cmd; @@ -512,6 +518,7 @@ struct dom0_irq_permission irq_permission; struct dom0_iomem_permission iomem_permission; struct dom0_hypercall_init hypercall_init; + struct dom0_settimeoffset settimeoffset; uint8_t pad[128]; } u; } dom0_op_t; diff -r 85b7a341207e xen/include/xen/sched.h --- a/xen/include/xen/sched.h Thu Mar 30 13:06:11 2006 +++ b/xen/include/xen/sched.h Fri Mar 31 13:18:42 2006 @@ -155,6 +155,7 @@ /* Control-plane tools handle for this domain. */ xen_domain_handle_t handle; + s32 time_offset_seconds; }; struct domain_setup_info diff -r 85b7a341207e xen/include/xen/time.h --- a/xen/include/xen/time.h Thu Mar 30 13:06:11 2006 +++ b/xen/include/xen/time.h Fri Mar 31 13:18:42 2006 @@ -59,6 +59,7 @@ extern void do_settime( unsigned long secs, unsigned long nsecs, u64 system_time_base); +extern void do_settimeoffset(struct domain *d, int32_t wc_offset); extern void send_timer_event(struct vcpu *v); #endif /* __XEN_TIME_H__ */