diff -r 5b11da5e72fb Config.mk --- a/Config.mk Fri Feb 29 15:07:40 2008 -0800 +++ b/Config.mk Thu Mar 06 10:12:18 2008 -0800 @@ -1,7 +1,10 @@ # -*- mode: Makefile; -*- # A debug build of Xen and tools? -debug ?= n +debug ?= y + +# flag for time dilation +tdf ?= y XEN_COMPILE_ARCH ?= $(shell uname -m | sed -e s/i.86/x86_32/ \ -e s/ppc/powerpc/ -e s/i86pc/x86_32/) @@ -35,6 +38,10 @@ CFLAGS += -DNDEBUG CFLAGS += -DNDEBUG else CFLAGS += -g +endif + +ifeq ($(tdf), y) +CFLAGS += -DTDF endif CFLAGS += -std=gnu99 diff -r 5b11da5e72fb linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Fri Feb 29 15:07:40 2008 -0800 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Thu Mar 06 10:12:18 2008 -0800 @@ -101,6 +101,9 @@ EXPORT_SYMBOL(rtc_lock); #include #endif +#define TDF 1 +static u32 tdf = 1; + DEFINE_SPINLOCK(i8253_lock); EXPORT_SYMBOL(i8253_lock); @@ -117,6 +120,9 @@ struct shadow_time_info { u32 tsc_to_usec_mul; int tsc_shift; u32 version; +#ifdef TDF + u32 tdf; +#endif }; static DEFINE_PER_CPU(struct shadow_time_info, shadow_time); static struct timespec shadow_tv; @@ -171,6 +177,11 @@ static void delay_tsc(unsigned long loop static void delay_tsc(unsigned long loops) { unsigned long bclock, now; + +#ifdef TDF + if(tdf > 0 && tdf < 1000) // some sanity checking + loops = loops * tdf; +#endif rdtscl(bclock); do { @@ -318,6 +329,10 @@ static void get_time_values_from_xen(voi dst->system_timestamp = src->system_time; dst->tsc_to_nsec_mul = src->tsc_to_system_mul; dst->tsc_shift = src->tsc_shift; +#ifdef TDF + dst->tdf = src->tdf; + tdf = src->tdf; +#endif rmb(); } while ((src->version & 1) | (dst->version ^ src->version)); @@ -639,6 +654,19 @@ irqreturn_t timer_interrupt(int irq, voi barrier(); } while (sched_time != runstate->state_entry_time); } while (!time_values_up_to_date(cpu)); + +#ifdef TDF + /* FIXME: this is a bad hack. Need a better solution. In particular, + why does procesed_system_time advance further than shadow? */ + if(tdf > 1) + { + if ((unlikely(delta < -(s64)permitted_clock_jitter) || + unlikely(delta_cpu < -(s64)permitted_clock_jitter))) + { + delta = delta_cpu = get_nsec_offset(shadow); + } + } +#endif if ((unlikely(delta < -(s64)permitted_clock_jitter) || unlikely(delta_cpu < -(s64)permitted_clock_jitter)) diff -r 5b11da5e72fb tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/libxc/xc_domain.c Thu Mar 06 10:12:18 2008 -0800 @@ -9,11 +9,20 @@ #include "xc_private.h" #include +#ifdef TDF +int xc_domain_create(int xc_handle, + uint32_t ssidref, + uint32_t tdf, + xen_domain_handle_t handle, + uint32_t flags, + uint32_t *pdomid) +#else int xc_domain_create(int xc_handle, uint32_t ssidref, xen_domain_handle_t handle, uint32_t flags, uint32_t *pdomid) +#endif { int err; DECLARE_DOMCTL; @@ -22,6 +31,9 @@ int xc_domain_create(int xc_handle, domctl.domain = (domid_t)*pdomid; domctl.u.createdomain.ssidref = ssidref; domctl.u.createdomain.flags = flags; +#ifdef TDF + domctl.u.createdomain.tdf = tdf; +#endif memcpy(domctl.u.createdomain.handle, handle, sizeof(xen_domain_handle_t)); if ( (err = do_domctl(xc_handle, &domctl)) != 0 ) return err; diff -r 5b11da5e72fb tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/libxc/xenctrl.h Thu Mar 06 10:12:18 2008 -0800 @@ -148,6 +148,9 @@ typedef struct xc_dominfo { typedef struct xc_dominfo { uint32_t domid; uint32_t ssidref; +#ifdef TDF + uint32_t tdf; +#endif unsigned int dying:1, crashed:1, shutdown:1, paused:1, blocked:1, running:1, hvm:1; @@ -164,6 +167,9 @@ typedef xen_domctl_getdomaininfo_t xc_do typedef xen_domctl_getdomaininfo_t xc_domaininfo_t; int xc_domain_create(int xc_handle, uint32_t ssidref, +#ifdef TDF + uint32_t tdf, +#endif xen_domain_handle_t handle, uint32_t flags, uint32_t *pdomid); diff -r 5b11da5e72fb tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/python/xen/lowlevel/xc/xc.c Thu Mar 06 10:12:18 2008 -0800 @@ -89,17 +89,30 @@ static PyObject *pyxc_domain_create(XcOb PyObject *kwds) { uint32_t dom = 0, ssidref = 0, flags = 0; +#ifdef TDF + uint32_t tdf = 1; +#endif int ret, i, hvm = 0; PyObject *pyhandle = NULL; xen_domain_handle_t handle = { 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef }; +#ifdef TDF + static char *kwd_list[] = { "domid", "ssidref", "tdf", "handle", "hvm", NULL}; +#else static char *kwd_list[] = { "domid", "ssidref", "handle", "hvm", NULL }; - +#endif + +#ifdef TDF + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiiOi", kwd_list, + &dom, &ssidref, &tdf, &pyhandle, &hvm)) + return NULL; +#else if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiOi", kwd_list, &dom, &ssidref, &pyhandle, &hvm)) return NULL; +#endif if ( pyhandle != NULL ) { @@ -119,9 +132,15 @@ static PyObject *pyxc_domain_create(XcOb if ( hvm ) flags |= XEN_DOMCTL_CDF_hvm_guest; +#ifdef TDF + if ( (ret = xc_domain_create(self->xc_handle, ssidref, + tdf, handle, flags, &dom)) < 0 ) + return pyxc_error_to_exception(); +#else if ( (ret = xc_domain_create(self->xc_handle, ssidref, handle, flags, &dom)) < 0 ) return pyxc_error_to_exception(); +#endif return PyInt_FromLong(dom); diff -r 5b11da5e72fb tools/python/xen/xend/XendConfig.py --- a/tools/python/xen/xend/XendConfig.py Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/python/xen/xend/XendConfig.py Thu Mar 06 10:12:18 2008 -0800 @@ -167,6 +167,7 @@ LEGACY_UNSUPPORTED_BY_XENAPI_CFG = [ 'cpu_weight', 'cpu_cap', 'features', + 'tdf', # read/write 'on_xend_start', 'on_xend_stop', @@ -201,6 +202,7 @@ LEGACY_CFG_TYPES = { 'on_xend_stop': str, 'on_xend_start': str, 'online_vcpus': int, + 'tdf': int, } # Values that should be stored in xenstore's /vm/ that is used @@ -352,6 +354,7 @@ class XendConfig(dict): 'on_xend_stop': 'ignore', 'cpus': [], 'cpu_weight': 256, + 'tdf': 1, 'cpu_cap': 0, 'vcpus_number': 1, 'online_vcpus': 1, @@ -717,6 +720,7 @@ class XendConfig(dict): _set_cfg_if_exists('on_xend_start') _set_cfg_if_exists('vcpu_avail') _set_cfg_if_exists('max_vcpu_id') # needed for vcpuDomDetails + _set_cfg_if_exists('tdf') # Parse and store runtime configuration _set_cfg_if_exists('start_time') diff -r 5b11da5e72fb tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/python/xen/xend/XendDomainInfo.py Thu Mar 06 10:12:18 2008 -0800 @@ -1298,6 +1298,7 @@ class XendDomainInfo: self.domid = xc.domain_create( domid = 0, ssidref = security.get_security_info(self.info, 'ssidref'), + tdf = self.info['tdf'], handle = uuid.fromString(self.info['uuid']), hvm = int(hvm)) diff -r 5b11da5e72fb tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/python/xen/xend/image.py Thu Mar 06 10:12:18 2008 -0800 @@ -478,6 +478,7 @@ class HVMImageHandler(ImageHandler): args = [self.device_model] args = args + ([ "-d", "%d" % self.vm.getDomid(), "-m", "%s" % (self.getRequiredInitialReservation() / 1024)]) + args = args + ([ "-tdf", "%d" % self.vm.info['tdf']]) args = args + self.dmargs env = dict(os.environ) if self.display: diff -r 5b11da5e72fb tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Feb 29 15:07:40 2008 -0800 +++ b/tools/python/xen/xm/create.py Thu Mar 06 10:12:18 2008 -0800 @@ -164,6 +164,10 @@ gopts.var('shadow_memory', val='MEMORY', gopts.var('shadow_memory', val='MEMORY', fn=set_int, default=0, use="Domain shadow memory in MB.") + +gopts.var('tdf', val='TDF', + fn=set_int, default=1, + use="Time Dilation Factor") gopts.var('cpu', val='CPU', fn=set_int, default=None, @@ -738,6 +742,8 @@ def make_config(vals): 'on_reboot', 'on_crash', 'vcpus', 'features', 'on_xend_start', 'on_xend_stop']) + if vals.tdf is not None: + config.append(['tdf', vals.tdf]) if vals.uuid is not None: config.append(['uuid', vals.uuid]) if vals.cpu is not None: diff -r 5b11da5e72fb xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/arch/x86/setup.c Thu Mar 06 10:12:18 2008 -0800 @@ -544,7 +544,11 @@ void __init __start_xen(multiboot_info_t BUILD_BUG_ON(sizeof(start_info_t) > PAGE_SIZE); BUILD_BUG_ON(sizeof(shared_info_t) > PAGE_SIZE); +#ifdef TDF + BUILD_BUG_ON(sizeof(vcpu_info_t) != 72); +#else BUILD_BUG_ON(sizeof(vcpu_info_t) != 64); +#endif /* Check definitions in public headers match internal defs. */ BUILD_BUG_ON(__HYPERVISOR_VIRT_START != HYPERVISOR_VIRT_START); diff -r 5b11da5e72fb xen/arch/x86/time.c --- a/xen/arch/x86/time.c Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/arch/x86/time.c Thu Mar 06 10:12:18 2008 -0800 @@ -675,15 +675,56 @@ static inline void __update_vcpu_system_ struct cpu_time *t; struct vcpu_time_info *u; +#ifdef TDF + uint32_t tdf = v->domain->tdf; + /* Used by guest to interpolate time between ticks */ + uint64_t dilated_tsc_timestamp; + /* Nano seconds since boot */ + uint64_t dilated_system_time; + /* How many TSC increments make one nano second? */ + uint32_t dilated_tsc_to_system_mul; + /* Another calibration metric */ + int8_t dilated_tsc_shift; +#endif + t = &this_cpu(cpu_time); u = &v->vcpu_info->time; version_update_begin(&u->version); +#ifdef TDF + /* Initialize to original values */ + dilated_tsc_timestamp = t->local_tsc_stamp; + dilated_system_time = t->stime_local_stamp; + dilated_tsc_to_system_mul = t->tsc_scale.mul_frac; + dilated_tsc_shift = (s8)t->tsc_scale.shift; + + if(tdf < 0 || tdf > 1000) + { + printk("Oops, seen bad TDF %d for domain %d\n", + tdf, v->domain->domain_id); + tdf = 1; + v->domain->tdf = 1; + } + + if(v->domain->domain_id !=0 && tdf > 1) /* Nothing to do if TDF is 1 */ + { + /* Normal dilation: slow down time */ + do_div(dilated_system_time, tdf); /* ignore the remainder for now */ + dilated_tsc_to_system_mul = dilated_tsc_to_system_mul/tdf; + } + + u->tsc_timestamp = dilated_tsc_timestamp; + u->system_time = dilated_system_time; + u->tsc_to_system_mul = dilated_tsc_to_system_mul; + u->tsc_shift = (s8) dilated_tsc_shift; + u->tdf = tdf; +#else u->tsc_timestamp = t->local_tsc_stamp; u->system_time = t->stime_local_stamp; u->tsc_to_system_mul = t->tsc_scale.mul_frac; u->tsc_shift = (s8)t->tsc_scale.shift; +#endif version_update_end(&u->version); } @@ -697,10 +738,28 @@ void update_vcpu_system_time(struct vcpu void update_domain_wallclock_time(struct domain *d) { +#ifdef TDF + u32 remainder; +#endif spin_lock(&wc_lock); version_update_begin(&d->shared_info->wc_version); +#ifdef TDF + if(d->tdf < 0 || d->tdf > 1000) + { + printk("Oops, seen bad TDF %d for domain %d\n", + d->tdf, d->domain_id); + d->tdf = 1; + } + // when running dilated, "offset" doesn't really make much sense + d->shared_info->wc_sec = wc_sec; + remainder = do_div(d->shared_info->wc_sec, d->tdf); + d->shared_info->wc_nsec = wc_nsec + remainder * 1000000000L; + do_div(d->shared_info->wc_nsec, d->tdf); + d->shared_info->tdf = d->tdf; +#else d->shared_info->wc_sec = wc_sec + d->time_offset_seconds; d->shared_info->wc_nsec = wc_nsec; +#endif version_update_end(&d->shared_info->wc_version); spin_unlock(&wc_lock); } diff -r 5b11da5e72fb xen/common/domain.c --- a/xen/common/domain.c Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/common/domain.c Thu Mar 06 10:12:18 2008 -0800 @@ -182,6 +182,12 @@ struct domain *domain_create(domid_t dom write_unlock(&domlist_lock); } +#ifdef TDF + /* Set the default value */ + d->tdf = 1; + d->shared_info->tdf = 1; +#endif + return d; fail4: diff -r 5b11da5e72fb xen/common/domctl.c --- a/xen/common/domctl.c Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/common/domctl.c Thu Mar 06 10:12:18 2008 -0800 @@ -286,6 +286,33 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domc memcpy(d->handle, op->u.createdomain.handle, sizeof(xen_domain_handle_t)); +#ifdef TDF + /* Make sure we have a sane value for dilation mode + * Either normal (0) or reverse (1) */ + /*if(op->u.createdomain.dilation_mode != 0 &&*/ + /*op->u.createdomain.dilation_mode != 1) {*/ + /*ret = -EINVAL;*/ + /*break;*/ + /*}*/ + /*else*/ + /*d->shared_info->dilation_mode = op->u.createdomain.dilation_mode;*/ + d->shared_info->dilation_mode = 0; + d->dilation_mode = 0; + + /* Ensure Dom-0 _always_ has TDF = 1 */ + if(d->domain_id == 0) + { + d->shared_info->tdf = 1; + d->tdf = op->u.createdomain.tdf; + } + else + { + d->shared_info->tdf = op->u.createdomain.tdf; + d->tdf = op->u.createdomain.tdf; + } + printk("Creating domain %d with TDF %d\n", + d->domain_id, d->shared_info->tdf); +#endif ret = 0; op->domain = d->domain_id; diff -r 5b11da5e72fb xen/common/schedule.c --- a/xen/common/schedule.c Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/common/schedule.c Thu Mar 06 10:12:18 2008 -0800 @@ -448,7 +448,13 @@ long do_set_timer_op(s_time_t timeout) long do_set_timer_op(s_time_t timeout) { struct vcpu *v = current; +#ifdef TDF + s_time_t offset; + timeout *= v->domain->tdf; + offset = timeout - NOW(); +#else s_time_t offset = timeout - NOW(); +#endif if ( timeout == 0 ) { @@ -644,7 +650,22 @@ static void t_timer_fn(void *unused) { struct vcpu *v = current; +#ifdef TDF + unsigned int delay; +#endif + this_cpu(schedule_data).tick++; + +#ifdef TDF + if(v->domain->domain_id == 0 || is_idle_vcpu(v)) + { + delay = 10; + } + else + { + delay = v->domain->tdf * 10; + } +#endif if ( !is_idle_vcpu(v) ) { @@ -656,7 +677,11 @@ static void t_timer_fn(void *unused) SCHED_OP(tick, smp_processor_id()); +#ifdef TDF + set_timer(&this_cpu(t_timer), NOW() + MILLISECS(delay)); +#else set_timer(&this_cpu(t_timer), NOW() + MILLISECS(10)); +#endif } /* Per-VCPU timer function: sends a virtual timer interrupt. */ diff -r 5b11da5e72fb xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/include/asm-x86/config.h Thu Mar 06 10:12:18 2008 -0800 @@ -38,7 +38,7 @@ #define CONFIG_VGA 1 -#define HZ 100 +#define HZ 1000 #define OPT_CONSOLE_STR "com1,vga" diff -r 5b11da5e72fb xen/include/public/domctl.h --- a/xen/include/public/domctl.h Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/include/public/domctl.h Thu Mar 06 10:12:18 2008 -0800 @@ -49,6 +49,10 @@ struct xen_domctl_createdomain { struct xen_domctl_createdomain { /* IN parameters */ uint32_t ssidref; +#ifdef TDF + uint32_t tdf; + uint32_t dilation_mode; +#endif xen_domain_handle_t handle; /* Is this an HVM guest (as opposed to a PV guest)? */ #define _XEN_DOMCTL_CDF_hvm_guest 0 diff -r 5b11da5e72fb xen/include/public/xen.h --- a/xen/include/public/xen.h Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/include/public/xen.h Thu Mar 06 10:12:18 2008 -0800 @@ -373,7 +373,9 @@ struct vcpu_time_info { uint32_t tsc_to_system_mul; int8_t tsc_shift; int8_t pad1[3]; -}; /* 32 bytes */ + uint32_t tdf; + uint32_t pad2; +}; /* 40 bytes */ typedef struct vcpu_time_info vcpu_time_info_t; struct vcpu_info { @@ -463,6 +465,11 @@ struct shared_info { uint32_t wc_sec; /* Secs 00:00:00 UTC, Jan 1, 1970. */ uint32_t wc_nsec; /* Nsecs 00:00:00 UTC, Jan 1, 1970. */ +#ifdef TDF + uint32_t tdf; + uint32_t dilation_mode; +#endif + struct arch_shared_info arch; }; diff -r 5b11da5e72fb xen/include/xen/sched.h --- a/xen/include/xen/sched.h Fri Feb 29 15:07:40 2008 -0800 +++ b/xen/include/xen/sched.h Thu Mar 06 10:12:18 2008 -0800 @@ -172,6 +172,11 @@ struct domain /* OProfile support. */ struct xenoprof *xenoprof; int32_t time_offset_seconds; + +#ifdef TDF + uint32_t tdf; + uint32_t dilation_mode; +#endif }; struct domain_setup_info