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 <asm/i8253.h>
 #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 <xen/memory.h>
 
+#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/<uuid> 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
