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 <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));
 
@@ -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 <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 *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
