Index: ioemu/hw/mc146818rtc.c
===================================================================
--- ioemu.orig/hw/mc146818rtc.c	2007-05-03 15:38:35.000000000 +0100
+++ ioemu/hw/mc146818rtc.c	2007-05-03 15:38:45.000000000 +0100
@@ -178,10 +178,27 @@
     }
 }
 
+static void send_timeoffset_msg(time_t delta)
+{
+
+/* This routine is used to inform another entity that the
+   base time offset has changed. For instance, if you
+   were using xenstore, you might want to write to the store
+   at this point.  Or, you might use some other method.
+   Whatever you might choose, here's a hook point to implement it.
+
+   One item of note is that this delta is in addition to
+   any existing offset you might be already using. */
+
+    return;
+}
+
 static void rtc_set_time(RTCState *s)
 {
     struct tm *tm = &s->current_tm;
-
+    time_t before, after;
+    
+    before = mktime(tm);
     tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
     tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
     tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
@@ -193,6 +210,12 @@
     tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
     tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
     tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
+
+    /* Compute, and send, the additional time delta
+       We could compute the total time delta, but this is
+       sufficient, and simple. */
+    after = mktime(tm);
+    send_timeoffset_msg(after-before);
 }
 
 static void rtc_copy_date(RTCState *s)
Index: ioemu/hw/pc.c
===================================================================
--- ioemu.orig/hw/pc.c	2007-05-03 15:38:44.000000000 +0100
+++ ioemu/hw/pc.c	2007-05-03 15:38:45.000000000 +0100
@@ -159,7 +159,7 @@
 }
 
 /* hd_table must contain 4 block drivers */
-static void cmos_init(uint64_t ram_size, int boot_device, BlockDriverState **hd_table)
+static void cmos_init(uint64_t ram_size, int boot_device, BlockDriverState **hd_table, time_t timeoffset)
 {
     RTCState *s = rtc_state;
     int val;
@@ -170,6 +170,7 @@
 
     /* set the CMOS date */
     time(&ti);
+    ti += timeoffset;
     if (rtc_utc)
         tm = gmtime(&ti);
     else
@@ -619,7 +620,7 @@
 static void pc_init1(uint64_t ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename,
+                     const char *initrd_filename, time_t timeoffset,
                      int pci_enabled)
 {
 #ifndef NOBIOS
@@ -871,7 +872,7 @@
 
     floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
 
-    cmos_init(ram_size, boot_device, bs_table);
+    cmos_init(ram_size, boot_device, bs_table, timeoffset);
 
     /* using PIIX4 acpi model */
     if (pci_enabled && acpi_enabled)
@@ -920,12 +921,13 @@
                         int snapshot, 
                         const char *kernel_filename, 
                         const char *kernel_cmdline,
-                        const char *initrd_filename)
+                        const char *initrd_filename,
+                        time_t timeoffset)
 {
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,
              kernel_filename, kernel_cmdline,
-             initrd_filename, 1);
+             initrd_filename, timeoffset, 1);
 }
 
 static void pc_init_isa(uint64_t ram_size, int vga_ram_size, int boot_device,
@@ -933,12 +935,13 @@
                         int snapshot, 
                         const char *kernel_filename, 
                         const char *kernel_cmdline,
-                        const char *initrd_filename)
+                        const char *initrd_filename,
+                        time_t timeoffset)
 {
     pc_init1(ram_size, vga_ram_size, boot_device,
              ds, fd_filename, snapshot,
              kernel_filename, kernel_cmdline,
-             initrd_filename, 0);
+             initrd_filename, timeoffset, 0);
 }
 
 QEMUMachine pc_machine = {
Index: ioemu/vl.c
===================================================================
--- ioemu.orig/vl.c	2007-05-03 15:38:45.000000000 +0100
+++ ioemu/vl.c	2007-05-03 15:38:45.000000000 +0100
@@ -167,6 +167,8 @@
 
 int xc_handle;
 
+time_t timeoffset = 0;
+
 char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
 extern int domid;
 
@@ -5435,6 +5437,7 @@
            "-vncviewer      start a vncviewer process for this domain\n"
            "-vncunused      bind the VNC server to an unused port\n"
            "-vnclisten      bind the VNC server to this address\n"
+           "-timeoffset     time offset (in seconds) from local time\n"
            "-acpi           disable or enable ACPI of HVM domain \n"
            "\n"
            "During emulation, the following keys are useful:\n"
@@ -5522,6 +5525,7 @@
 
     QEMU_OPTION_d,
     QEMU_OPTION_vcpus,
+    QEMU_OPTION_timeoffset,
     QEMU_OPTION_acpi,
     QEMU_OPTION_vncviewer,
     QEMU_OPTION_vncunused,
@@ -5613,6 +5617,7 @@
     
     { "d", HAS_ARG, QEMU_OPTION_d },
     { "vcpus", 1, QEMU_OPTION_vcpus },
+    { "timeoffset", HAS_ARG, QEMU_OPTION_timeoffset },
     { "acpi", 0, QEMU_OPTION_acpi },
     { NULL },
 };
@@ -6377,6 +6382,9 @@
                 vcpus = atoi(optarg);
                 fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus);
                 break;
+            case QEMU_OPTION_timeoffset:
+                timeoffset = strtol(optarg, NULL, 0);
+                break;
             case QEMU_OPTION_acpi:
                 acpi_enabled = 1;
                 break;
@@ -6531,6 +6539,9 @@
     }
     free(page_array);
 #endif
+
+    timeoffset_get();
+
 #else  /* !CONFIG_DM */
 
     phys_ram_base = qemu_vmalloc(phys_ram_size);
@@ -6662,7 +6673,8 @@
 
     machine->init(ram_size, vga_ram_size, boot_device,
                   ds, fd_filename, snapshot,
-                  kernel_filename, kernel_cmdline, initrd_filename);
+                  kernel_filename, kernel_cmdline, initrd_filename,
+                  timeoffset);
 
     /* init USB devices */
     if (usb_enabled) {
Index: ioemu/vl.h
===================================================================
--- ioemu.orig/vl.h	2007-05-03 15:38:45.000000000 +0100
+++ ioemu/vl.h	2007-05-03 15:38:45.000000000 +0100
@@ -581,7 +581,7 @@
                                  int boot_device,
              DisplayState *ds, const char **fd_filename, int snapshot,
              const char *kernel_filename, const char *kernel_cmdline,
-             const char *initrd_filename);
+             const char *initrd_filename, time_t timeoffset);
 
 typedef struct QEMUMachine {
     const char *name;
@@ -1216,6 +1216,10 @@
 int xenstore_vm_write(int domid, char *key, char *val);
 char *xenstore_vm_read(int domid, char *key, int *len);
 
+/* helper2.c */
+extern long time_offset;
+void timeoffset_get(void);
+
 void kqemu_record_dump(void);
 
 extern char domain_name[];
Index: ioemu/target-i386-dm/helper2.c
===================================================================
--- ioemu.orig/target-i386-dm/helper2.c	2007-05-03 15:38:44.000000000 +0100
+++ ioemu/target-i386-dm/helper2.c	2007-05-03 15:38:45.000000000 +0100
@@ -74,6 +74,8 @@
 
 int xc_handle;
 
+long time_offset = 0;
+
 shared_iopage_t *shared_page = NULL;
 
 /* the evtchn fd for polling */
@@ -447,6 +449,34 @@
     req->data = tmp1;
 }
 
+void timeoffset_get()
+{
+    char *p;
+
+    p = xenstore_vm_read(domid, "rtc/timeoffset", NULL);
+    if (!p)
+	return;
+
+    if (sscanf(p, "%ld", &time_offset) == 1)
+	fprintf(logfile, "Time offset set %ld\n", time_offset);
+    else
+	time_offset = 0;
+
+    xc_domain_set_time_offset(xc_handle, domid, time_offset);
+
+    free(p);
+}
+
+void cpu_ioreq_timeoffset(CPUState *env, ioreq_t *req)
+{
+    char b[64];
+
+    time_offset += (ulong)req->data;
+
+    sprintf(b, "%ld", time_offset);
+    xenstore_vm_write(domid, "rtc/timeoffset", b);
+}
+
 void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
 {
     unsigned long tmp1;
@@ -497,6 +527,9 @@
         case IOREQ_TYPE_XCHG:
             cpu_ioreq_xchg(env, req);
             break;
+	case IOREQ_TYPE_TIMEOFFSET:
+            cpu_ioreq_timeoffset(env, req);
+            break;
         default:
             hw_error("Invalid ioreq type 0x%x\n", req->type);
         }
