# HG changeset patch
# User Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
# Date 1175602957 -3600
# Node ID 7e431ea834a877b1f0c90bdb1e6f1346da4e81cc
# Parent cd01741aaa93daea020f8cba7f2b840255de9846
[hvm] Keep track of time offset between domain time and dom0 time.
On each rtc time update from the hvm domain, we send an ioreq request
to qemu which then updates the time offset xenstore entry. The time
offset is preserved across reboot and can be set on domain creation
by setting the rtc_timeoffset variable in a config file.
From: Andrei Petrov <andrei.petrov@xxxxxxxxxxxxx>
Signed-off-by: Christian Limpach <Christian.Limpach@xxxxxxxxxxxxx>
---
tools/examples/xmexample.hvm | 4 +
tools/ioemu/target-i386-dm/helper2.c | 33 +++++++++++++++
tools/ioemu/vl.c | 3 +
tools/ioemu/vl.h | 6 ++
tools/ioemu/xenstore.c | 69 ++++++++++++++++++++++++++++++++
tools/python/xen/xend/XendConfig.py | 3 -
tools/python/xen/xend/XendDomainInfo.py | 8 +++
tools/python/xen/xend/image.py | 3 +
tools/python/xen/xm/create.py | 6 ++
xen/arch/x86/hvm/intercept.c | 38 ++++++++++-------
xen/arch/x86/hvm/platform.c | 20 +++++++++
xen/arch/x86/hvm/rtc.c | 8 +++
xen/arch/x86/time.c | 2
xen/include/asm-x86/hvm/io.h | 2
xen/include/asm-x86/time.h | 5 ++
xen/include/public/hvm/ioreq.h | 1
16 files changed, 191 insertions(+), 20 deletions(-)
diff -r cd01741aaa93 -r 7e431ea834a8 tools/examples/xmexample.hvm
--- a/tools/examples/xmexample.hvm Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/examples/xmexample.hvm Tue Apr 03 13:22:37 2007 +0100
@@ -180,6 +180,10 @@ serial='pty'
#-----------------------------------------------------------------------------
+# set the real time clock offset in seconds [default=0 i.e. same as dom0]
+#rtc_timeoffset=3600
+
+#-----------------------------------------------------------------------------
# start in full screen
#full-screen=1
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/target-i386-dm/helper2.c
--- a/tools/ioemu/target-i386-dm/helper2.c Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/target-i386-dm/helper2.c Tue Apr 03 13:22:37 2007 +0100
@@ -73,6 +73,8 @@ int vcpus = 1;
int vcpus = 1;
int xc_handle;
+
+long time_offset = 0;
shared_iopage_t *shared_page = NULL;
@@ -439,6 +441,34 @@ void cpu_ioreq_xor(CPUState *env, ioreq_
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;
@@ -478,6 +508,9 @@ void __handle_ioreq(CPUState *env, ioreq
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);
}
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/vl.c
--- a/tools/ioemu/vl.c Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/vl.c Tue Apr 03 13:22:37 2007 +0100
@@ -6670,6 +6670,9 @@ int main(int argc, char **argv)
}
free(page_array);
#endif
+
+ timeoffset_get();
+
#else /* !CONFIG_DM */
phys_ram_base = qemu_vmalloc(phys_ram_size);
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/vl.h
--- a/tools/ioemu/vl.h Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/vl.h Tue Apr 03 13:22:37 2007 +0100
@@ -1276,6 +1276,12 @@ int xenstore_unsubscribe_from_hotplug_st
const char *inst,
const char *token);
+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);
/* xen_platform.c */
void pci_xen_platform_init(PCIBus *bus);
diff -r cd01741aaa93 -r 7e431ea834a8 tools/ioemu/xenstore.c
--- a/tools/ioemu/xenstore.c Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/ioemu/xenstore.c Tue Apr 03 13:22:37 2007 +0100
@@ -567,3 +567,72 @@ int xenstore_unsubscribe_from_hotplug_st
return rc;
}
+
+char *xenstore_vm_read(int domid, char *key, int *len)
+{
+ char *buf = NULL, *path = NULL, *value = NULL;
+
+ if (xsh == NULL)
+ goto out;
+
+ path = xs_get_domain_path(xsh, domid);
+ if (path == NULL) {
+ fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/vm", path);
+ free(path);
+ path = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (path == NULL) {
+ fprintf(logfile, "xs_read(%s): read error\n", buf);
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/%s", path, key);
+ value = xs_read(xsh, XBT_NULL, buf, len);
+ if (value == NULL) {
+ fprintf(logfile, "xs_read(%s): read error\n", buf);
+ goto out;
+ }
+
+ out:
+ free(path);
+ free(buf);
+ return value;
+}
+
+int xenstore_vm_write(int domid, char *key, char *value)
+{
+ char *buf = NULL, *path = NULL;
+ int rc = -1;
+
+ if (xsh == NULL)
+ goto out;
+
+ path = xs_get_domain_path(xsh, domid);
+ if (path == NULL) {
+ fprintf(logfile, "xs_get_domain_path(%d): error\n");
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/vm", path);
+ free(path);
+ path = xs_read(xsh, XBT_NULL, buf, NULL);
+ if (path == NULL) {
+ fprintf(logfile, "xs_read(%s): read error\n", buf);
+ goto out;
+ }
+
+ pasprintf(&buf, "%s/%s", path, key);
+ rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
+ if (rc) {
+ fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
+ goto out;
+ }
+
+ out:
+ free(path);
+ free(buf);
+ return rc;
+}
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xend/XendConfig.py Tue Apr 03 13:22:37 2007 +0100
@@ -118,7 +118,7 @@ LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(
# Platform configuration keys.
XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display',
'fda', 'fdb', 'keymap', 'isa', 'localtime',
- 'nographic', 'pae', 'serial', 'sdl',
+ 'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
'vncconsole', 'vncdisplay', 'vnclisten',
'vncpasswd', 'vncunused', 'xauthority']
@@ -203,6 +203,7 @@ LEGACY_CFG_TYPES = {
'on_xend_stop': str,
'on_xend_start': str,
'online_vcpus': int,
+ 'rtc/timeoffset': str,
}
# Values that should be stored in xenstore's /vm/<uuid> that is used
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py Tue Apr 03 13:22:37 2007 +0100
@@ -859,7 +859,8 @@ class XendDomainInfo:
# Check whether values in the configuration have
# changed in Xenstore.
- cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash']
+ cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash',
+ 'rtc/timeoffset']
vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
for k in cfg_vm])
@@ -888,6 +889,11 @@ class XendDomainInfo:
self.info.update_with_image_sxp(sxp.from_string(image_sxp))
changed = True
+ # Check if the rtc offset has changes
+ if vm_details.get("rtc/timeoffset", 0) !=
self.info["platform"].get("rtc_timeoffset", 0):
+ self.info["platform"]["rtc_timeoffset"] =
vm_details.get("rtc/timeoffset", 0)
+ changed = True
+
if changed:
# Update the domain section of the store, as this contains some
# parameters derived from the VM configuration.
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xend/image.py
--- a/tools/python/xen/xend/image.py Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xend/image.py Tue Apr 03 13:22:37 2007 +0100
@@ -256,9 +256,12 @@ class HVMImageHandler(ImageHandler):
self.xauthority = vmConfig['platform'].get('xauthority')
self.vncconsole = vmConfig['platform'].get('vncconsole')
+ rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
+
self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
("image/device-model", self.device_model),
("image/display", self.display))
+ self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
self.pid = None
diff -r cd01741aaa93 -r 7e431ea834a8 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py Tue Apr 03 12:22:10 2007 +0100
+++ b/tools/python/xen/xm/create.py Tue Apr 03 13:22:37 2007 +0100
@@ -185,6 +185,10 @@ gopts.var('cpus', val='CPUS',
gopts.var('cpus', val='CPUS',
fn=set_value, default=None,
use="CPUS to run the domain on.")
+
+gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
+ fn=set_value, default="0",
+ use="Set RTC offset.")
gopts.var('pae', val='PAE',
fn=set_int, default=1,
@@ -717,7 +721,7 @@ def configure_hvm(config_image, vals):
args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
- 'sdl', 'display', 'xauthority',
+ 'sdl', 'display', 'xauthority', 'rtc_timeoffset',
'acpi', 'apic', 'usb', 'usbdevice', 'keymap' ]
for a in args:
if a in vals.__dict__ and vals.__dict__[a] is not None:
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/hvm/intercept.c
--- a/xen/arch/x86/hvm/intercept.c Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/hvm/intercept.c Tue Apr 03 13:22:37 2007 +0100
@@ -155,28 +155,13 @@ static inline void hvm_mmio_access(struc
}
}
-int hvm_buffered_io_intercept(ioreq_t *p)
+int hvm_buffered_io_send(ioreq_t *p)
{
struct vcpu *v = current;
spinlock_t *buffered_io_lock;
buffered_iopage_t *buffered_iopage =
(buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
unsigned long tmp_write_pointer = 0;
- int i;
-
- /* ignore READ ioreq_t! */
- if ( p->dir == IOREQ_READ )
- return 0;
-
- for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
- if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
- p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
- hvm_buffered_io_ranges[i]->length )
- break;
- }
-
- if ( i == HVM_BUFFERED_IO_RANGE_NR )
- return 0;
buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
spin_lock(buffered_io_lock);
@@ -205,6 +190,27 @@ int hvm_buffered_io_intercept(ioreq_t *p
return 1;
}
+int hvm_buffered_io_intercept(ioreq_t *p)
+{
+ int i;
+
+ /* ignore READ ioreq_t! */
+ if ( p->dir == IOREQ_READ )
+ return 0;
+
+ for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
+ if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
+ p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
+ hvm_buffered_io_ranges[i]->length )
+ break;
+ }
+
+ if ( i == HVM_BUFFERED_IO_RANGE_NR )
+ return 0;
+
+ return hvm_buffered_io_send(p);
+}
+
int hvm_mmio_intercept(ioreq_t *p)
{
struct vcpu *v = current;
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/hvm/platform.c Tue Apr 03 13:22:37 2007 +0100
@@ -921,6 +921,26 @@ static void send_mmio_req(unsigned char
hvm_send_assist_req(v);
}
+void send_timeoffset_req(unsigned long timeoff)
+{
+ ioreq_t p[1];
+
+ if ( timeoff == 0 )
+ return;
+
+ memset(p, 0, sizeof(*p));
+
+ p->type = IOREQ_TYPE_TIMEOFFSET;
+ p->size = 4;
+ p->dir = IOREQ_WRITE;
+ p->data = timeoff;
+
+ p->state = STATE_IOREQ_READY;
+
+ if ( !hvm_buffered_io_send(p) )
+ printk("Unsuccessful timeoffset update\n");
+}
+
static void mmio_operands(int type, unsigned long gpa,
struct hvm_io_op *mmio_op,
unsigned char op_size)
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/hvm/rtc.c
--- a/xen/arch/x86/hvm/rtc.c Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/hvm/rtc.c Tue Apr 03 13:22:37 2007 +0100
@@ -157,6 +157,10 @@ static void rtc_set_time(RTCState *s)
static void rtc_set_time(RTCState *s)
{
struct tm *tm = &s->current_tm;
+ unsigned long before, after; /* XXX s_time_t */
+
+ before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
@@ -168,6 +172,10 @@ static void rtc_set_time(RTCState *s)
tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100;
+
+ after = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+ send_timeoffset_req(after - before);
}
static void rtc_copy_date(RTCState *s)
diff -r cd01741aaa93 -r 7e431ea834a8 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/arch/x86/time.c Tue Apr 03 13:22:37 2007 +0100
@@ -573,7 +573,7 @@ static void init_platform_timer(void)
* machines were long is 32-bit! (However, as time_t is signed, we
* will already get problems at other places on 2038-01-19 03:14:08)
*/
-static inline unsigned long
+unsigned long
mktime (unsigned int year, unsigned int mon,
unsigned int day, unsigned int hour,
unsigned int min, unsigned int sec)
diff -r cd01741aaa93 -r 7e431ea834a8 xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/include/asm-x86/hvm/io.h Tue Apr 03 13:22:37 2007 +0100
@@ -127,6 +127,7 @@ static inline int hvm_portio_intercept(i
}
extern int hvm_mmio_intercept(ioreq_t *p);
+extern int hvm_buffered_io_send(ioreq_t *p);
extern int hvm_buffered_io_intercept(ioreq_t *p);
static inline int register_portio_handler(
@@ -145,6 +146,7 @@ static inline int irq_masked(unsigned lo
extern void send_pio_req(unsigned long port, unsigned long count, int size,
paddr_t value, int dir, int df, int value_is_ptr);
+void send_timeoffset_req(unsigned long timeoff);
extern void handle_mmio(unsigned long gpa);
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(struct vcpu *v);
diff -r cd01741aaa93 -r 7e431ea834a8 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/include/asm-x86/time.h Tue Apr 03 13:22:37 2007 +0100
@@ -16,4 +16,9 @@ static inline cycles_t get_cycles(void)
return c;
}
+unsigned long
+mktime (unsigned int year, unsigned int mon,
+ unsigned int day, unsigned int hour,
+ unsigned int min, unsigned int sec);
+
#endif /* __X86_TIME_H__ */
diff -r cd01741aaa93 -r 7e431ea834a8 xen/include/public/hvm/ioreq.h
--- a/xen/include/public/hvm/ioreq.h Tue Apr 03 12:22:10 2007 +0100
+++ b/xen/include/public/hvm/ioreq.h Tue Apr 03 13:22:37 2007 +0100
@@ -39,6 +39,7 @@
#define IOREQ_TYPE_XOR 4
#define IOREQ_TYPE_XCHG 5
#define IOREQ_TYPE_ADD 6
+#define IOREQ_TYPE_TIMEOFFSET 7
/*
* VMExit dispatcher should cooperate with instruction decoder to
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|