diff -r cbfaeada1c78 Config.mk --- a/Config.mk Fri Feb 29 15:05:48 2008 -0800 +++ b/Config.mk Fri Feb 29 15:08:47 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/) @@ -30,6 +33,10 @@ INSTALL_DIR = $(INSTALL) -d -m0755 INSTALL_DIR = $(INSTALL) -d -m0755 INSTALL_DATA = $(INSTALL) -m0644 INSTALL_PROG = $(INSTALL) -m0755 + +ifeq ($(tdf), y) +CFLAGS += -DTDF +endif ifneq ($(debug),y) # Optimisation flags are overridable diff -r cbfaeada1c78 config/x86_32.mk --- a/config/x86_32.mk Fri Feb 29 15:05:48 2008 -0800 +++ b/config/x86_32.mk Fri Feb 29 15:08:47 2008 -0800 @@ -2,7 +2,7 @@ CONFIG_HVM := y CONFIG_HVM := y CONFIG_MIGRATE := y CONFIG_XCUTILS := y -CONFIG_IOEMU := y +# CONFIG_IOEMU := y CONFIG_MBOOTPACK := y CFLAGS += -m32 -march=i686 diff -r cbfaeada1c78 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:05:48 2008 -0800 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/time-xen.c Fri Feb 29 15:08:47 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)); @@ -640,6 +655,19 @@ irqreturn_t timer_interrupt(int irq, voi } 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)) && printk_ratelimit()) { @@ -1000,8 +1028,8 @@ static void stop_hz_timer(void) j = jiffies + 1; } - if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0) - BUG(); + if (HYPERVISOR_set_timer_op(jiffies_to_st(j)) != 0) + BUG(); } static void start_hz_timer(void) diff -r cbfaeada1c78 tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Fri Feb 29 15:05:48 2008 -0800 +++ b/tools/libxc/xc_domain.c Fri Feb 29 15:08:47 2008 -0800 @@ -9,10 +9,18 @@ #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 *pdomid) +#else int xc_domain_create(int xc_handle, uint32_t ssidref, xen_domain_handle_t handle, uint32_t *pdomid) +#endif { int err; DECLARE_DOMCTL; @@ -20,6 +28,9 @@ int xc_domain_create(int xc_handle, domctl.cmd = XEN_DOMCTL_createdomain; domctl.domain = (domid_t)*pdomid; domctl.u.createdomain.ssidref = ssidref; +#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 cbfaeada1c78 tools/libxc/xenctrl.h --- a/tools/libxc/xenctrl.h Fri Feb 29 15:05:48 2008 -0800 +++ b/tools/libxc/xenctrl.h Fri Feb 29 15:08:47 2008 -0800 @@ -142,6 +142,9 @@ typedef struct { typedef struct { 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; unsigned int shutdown_reason; /* only meaningful if shutdown==1 */ @@ -157,6 +160,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 *pdomid); diff -r cbfaeada1c78 tools/python/xen/lowlevel/xc/xc.c --- a/tools/python/xen/lowlevel/xc/xc.c Fri Feb 29 15:05:48 2008 -0800 +++ b/tools/python/xen/lowlevel/xc/xc.c Fri Feb 29 15:08:47 2008 -0800 @@ -68,16 +68,29 @@ static PyObject *pyxc_domain_create(XcOb uint32_t dom = 0; int ret, i; uint32_t ssidref = 0; +#ifdef TDF + uint32_t tdf = 1; +#endif 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[] = { "dom", "ssidref", "tdf", "handle", NULL}; +#else static char *kwd_list[] = { "dom", "ssidref", "handle", NULL }; - +#endif + +#ifdef TDF + if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiiO", kwd_list, + &dom, &ssidref, &tdf, &pyhandle)) + return NULL; +#else if ( !PyArg_ParseTupleAndKeywords(args, kwds, "|iiO", kwd_list, &dom, &ssidref, &pyhandle)) return NULL; +#endif if ( pyhandle != NULL ) { @@ -94,8 +107,13 @@ static PyObject *pyxc_domain_create(XcOb } } +#ifdef TDF + if ( (ret = xc_domain_create(self->xc_handle, ssidref, tdf, handle, &dom)) < 0 ) + return PyErr_SetFromErrno(xc_error); +#else if ( (ret = xc_domain_create(self->xc_handle, ssidref, handle, &dom)) < 0 ) return PyErr_SetFromErrno(xc_error); +#endif return PyInt_FromLong(dom); diff -r cbfaeada1c78 tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Fri Feb 29 15:05:48 2008 -0800 +++ b/tools/python/xen/xend/XendDomainInfo.py Fri Feb 29 15:08:47 2008 -0800 @@ -139,6 +139,7 @@ ROUNDTRIPPING_CONFIG_ENTRIES = [ ('bootloader_args', str), ('features', str), ('localtime', int), + ('tdf', int), ] ROUNDTRIPPING_CONFIG_ENTRIES += VM_CONFIG_PARAMS @@ -156,6 +157,7 @@ VM_STORE_ENTRIES = [ ('shadow_memory', int), ('maxmem', int), ('start_time', float), + ('tdf', int), ] VM_STORE_ENTRIES += VM_CONFIG_PARAMS @@ -1254,6 +1256,7 @@ class XendDomainInfo: self.domid = xc.domain_create( dom = 0, ssidref = security.get_security_info(self.info, 'ssidref'), + tdf = self.info['tdf'], handle = uuid.fromString(self.info['uuid'])) if self.domid < 0: diff -r cbfaeada1c78 tools/python/xen/xm/create.py --- a/tools/python/xen/xm/create.py Fri Feb 29 15:05:48 2008 -0800 +++ b/tools/python/xen/xm/create.py Fri Feb 29 15:08:47 2008 -0800 @@ -157,9 +157,10 @@ gopts.var('maxmem', val='MEMORY', fn=set_int, default=None, use="Maximum domain memory in MB.") -gopts.var('shadow_memory', val='MEMORY', - fn=set_int, default=0, - use="Domain shadow memory in MB.") +# DG: TDF +gopts.var('tdf', val='TDF', + fn=set_int, default=1, + use="Time Dilation Factor") gopts.var('cpu', val='CPU', fn=set_int, default=None, @@ -676,6 +677,9 @@ def make_config(vals): 'restart', 'on_poweroff', 'on_reboot', 'on_crash', 'vcpus', 'features']) +# DG: TDF + 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 cbfaeada1c78 xen/arch/x86/setup.c --- a/xen/arch/x86/setup.c Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/arch/x86/setup.c Fri Feb 29 15:08:47 2008 -0800 @@ -433,7 +433,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 cbfaeada1c78 xen/arch/x86/time.c --- a/xen/arch/x86/time.c Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/arch/x86/time.c Fri Feb 29 15:08:47 2008 -0800 @@ -675,16 +675,57 @@ 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 cbfaeada1c78 xen/common/domain.c --- a/xen/common/domain.c Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/common/domain.c Fri Feb 29 15:08:47 2008 -0800 @@ -161,6 +161,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 cbfaeada1c78 xen/common/domctl.c --- a/xen/common/domctl.c Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/common/domctl.c Fri Feb 29 15:08:47 2008 -0800 @@ -280,6 +280,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 cbfaeada1c78 xen/common/schedule.c --- a/xen/common/schedule.c Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/common/schedule.c Fri Feb 29 15:08:47 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 ) { @@ -643,7 +649,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) ) { @@ -655,7 +676,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 cbfaeada1c78 xen/include/asm-x86/config.h --- a/xen/include/asm-x86/config.h Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/include/asm-x86/config.h Fri Feb 29 15:08:47 2008 -0800 @@ -33,7 +33,7 @@ #define CONFIG_VGA 1 -#define HZ 100 +#define HZ 1000 #define OPT_CONSOLE_STR "com1,vga" diff -r cbfaeada1c78 xen/include/public/domctl.h --- a/xen/include/public/domctl.h Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/include/public/domctl.h Fri Feb 29 15:08:47 2008 -0800 @@ -31,6 +31,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; }; typedef struct xen_domctl_createdomain xen_domctl_createdomain_t; diff -r cbfaeada1c78 xen/include/public/xen.h --- a/xen/include/public/xen.h Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/include/public/xen.h Fri Feb 29 15:08:47 2008 -0800 @@ -357,6 +357,8 @@ struct vcpu_time_info { uint32_t tsc_to_system_mul; int8_t tsc_shift; int8_t pad1[3]; + uint32_t tdf; + uint32_t pad2; }; /* 32 bytes */ typedef struct vcpu_time_info vcpu_time_info_t; @@ -447,6 +449,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 cbfaeada1c78 xen/include/xen/sched.h --- a/xen/include/xen/sched.h Fri Feb 29 15:05:48 2008 -0800 +++ b/xen/include/xen/sched.h Fri Feb 29 15:08:47 2008 -0800 @@ -166,6 +166,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