ia64/xen-unstable

changeset 14707:7e431ea834a8

[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@xensource.com>
Signed-off-by: Christian Limpach <Christian.Limpach@xensource.com>
author Christian Limpach <Christian.Limpach@xensource.com>
date Tue Apr 03 13:22:37 2007 +0100 (2007-04-03)
parents cd01741aaa93
children f378c424e0ce 2d25db73ddc1
files tools/examples/xmexample.hvm tools/ioemu/target-i386-dm/helper2.c tools/ioemu/vl.c tools/ioemu/vl.h tools/ioemu/xenstore.c tools/python/xen/xend/XendConfig.py tools/python/xen/xend/XendDomainInfo.py tools/python/xen/xend/image.py tools/python/xen/xm/create.py xen/arch/x86/hvm/intercept.c xen/arch/x86/hvm/platform.c xen/arch/x86/hvm/rtc.c xen/arch/x86/time.c xen/include/asm-x86/hvm/io.h xen/include/asm-x86/time.h xen/include/public/hvm/ioreq.h
line diff
     1.1 --- a/tools/examples/xmexample.hvm	Tue Apr 03 12:22:10 2007 +0100
     1.2 +++ b/tools/examples/xmexample.hvm	Tue Apr 03 13:22:37 2007 +0100
     1.3 @@ -180,6 +180,10 @@ serial='pty'
     1.4  
     1.5  
     1.6  #-----------------------------------------------------------------------------
     1.7 +#    set the real time clock offset in seconds [default=0 i.e. same as dom0]
     1.8 +#rtc_timeoffset=3600
     1.9 +
    1.10 +#-----------------------------------------------------------------------------
    1.11  #    start in full screen
    1.12  #full-screen=1   
    1.13  
     2.1 --- a/tools/ioemu/target-i386-dm/helper2.c	Tue Apr 03 12:22:10 2007 +0100
     2.2 +++ b/tools/ioemu/target-i386-dm/helper2.c	Tue Apr 03 13:22:37 2007 +0100
     2.3 @@ -74,6 +74,8 @@ int vcpus = 1;
     2.4  
     2.5  int xc_handle;
     2.6  
     2.7 +long time_offset = 0;
     2.8 +
     2.9  shared_iopage_t *shared_page = NULL;
    2.10  
    2.11  #define BUFFER_IO_MAX_DELAY  100
    2.12 @@ -439,6 +441,34 @@ void cpu_ioreq_xor(CPUState *env, ioreq_
    2.13      req->data = tmp1;
    2.14  }
    2.15  
    2.16 +void timeoffset_get()
    2.17 +{
    2.18 +    char *p;
    2.19 +
    2.20 +    p = xenstore_vm_read(domid, "rtc/timeoffset", NULL);
    2.21 +    if (!p)
    2.22 +	return;
    2.23 +
    2.24 +    if (sscanf(p, "%ld", &time_offset) == 1)
    2.25 +	fprintf(logfile, "Time offset set %ld\n", time_offset);
    2.26 +    else
    2.27 +	time_offset = 0;
    2.28 +
    2.29 +    xc_domain_set_time_offset(xc_handle, domid, time_offset);
    2.30 +
    2.31 +    free(p);
    2.32 +}
    2.33 +
    2.34 +void cpu_ioreq_timeoffset(CPUState *env, ioreq_t *req)
    2.35 +{
    2.36 +    char b[64];
    2.37 +
    2.38 +    time_offset += (ulong)req->data;
    2.39 +
    2.40 +    sprintf(b, "%ld", time_offset);
    2.41 +    xenstore_vm_write(domid, "rtc/timeoffset", b);
    2.42 +}
    2.43 +
    2.44  void cpu_ioreq_xchg(CPUState *env, ioreq_t *req)
    2.45  {
    2.46      unsigned long tmp1;
    2.47 @@ -478,6 +508,9 @@ void __handle_ioreq(CPUState *env, ioreq
    2.48      case IOREQ_TYPE_XCHG:
    2.49          cpu_ioreq_xchg(env, req);
    2.50          break;
    2.51 +    case IOREQ_TYPE_TIMEOFFSET:
    2.52 +	cpu_ioreq_timeoffset(env, req);
    2.53 +	break;
    2.54      default:
    2.55          hw_error("Invalid ioreq type 0x%x\n", req->type);
    2.56      }
     3.1 --- a/tools/ioemu/vl.c	Tue Apr 03 12:22:10 2007 +0100
     3.2 +++ b/tools/ioemu/vl.c	Tue Apr 03 13:22:37 2007 +0100
     3.3 @@ -6670,6 +6670,9 @@ int main(int argc, char **argv)
     3.4      }
     3.5      free(page_array);
     3.6  #endif
     3.7 +
     3.8 +    timeoffset_get();
     3.9 +
    3.10  #else  /* !CONFIG_DM */
    3.11  
    3.12      phys_ram_base = qemu_vmalloc(phys_ram_size);
     4.1 --- a/tools/ioemu/vl.h	Tue Apr 03 12:22:10 2007 +0100
     4.2 +++ b/tools/ioemu/vl.h	Tue Apr 03 13:22:37 2007 +0100
     4.3 @@ -1276,6 +1276,12 @@ int xenstore_unsubscribe_from_hotplug_st
     4.4                                               const char *inst,
     4.5                                               const char *token);
     4.6  
     4.7 +int xenstore_vm_write(int domid, char *key, char *val);
     4.8 +char *xenstore_vm_read(int domid, char *key, int *len);
     4.9 +
    4.10 +/* helper2.c */
    4.11 +extern long time_offset;
    4.12 +void timeoffset_get(void);
    4.13  
    4.14  /* xen_platform.c */
    4.15  void pci_xen_platform_init(PCIBus *bus);
     5.1 --- a/tools/ioemu/xenstore.c	Tue Apr 03 12:22:10 2007 +0100
     5.2 +++ b/tools/ioemu/xenstore.c	Tue Apr 03 13:22:37 2007 +0100
     5.3 @@ -567,3 +567,72 @@ int xenstore_unsubscribe_from_hotplug_st
     5.4  
     5.5      return rc;
     5.6  }
     5.7 +
     5.8 +char *xenstore_vm_read(int domid, char *key, int *len)
     5.9 +{
    5.10 +    char *buf = NULL, *path = NULL, *value = NULL;
    5.11 +
    5.12 +    if (xsh == NULL)
    5.13 +	goto out;
    5.14 +
    5.15 +    path = xs_get_domain_path(xsh, domid);
    5.16 +    if (path == NULL) {
    5.17 +	fprintf(logfile, "xs_get_domain_path(%d): error\n", domid);
    5.18 +	goto out;
    5.19 +    }
    5.20 +
    5.21 +    pasprintf(&buf, "%s/vm", path);
    5.22 +    free(path);
    5.23 +    path = xs_read(xsh, XBT_NULL, buf, NULL);
    5.24 +    if (path == NULL) {
    5.25 +	fprintf(logfile, "xs_read(%s): read error\n", buf);
    5.26 +	goto out;
    5.27 +    }
    5.28 +
    5.29 +    pasprintf(&buf, "%s/%s", path, key);
    5.30 +    value = xs_read(xsh, XBT_NULL, buf, len);
    5.31 +    if (value == NULL) {
    5.32 +	fprintf(logfile, "xs_read(%s): read error\n", buf);
    5.33 +	goto out;
    5.34 +    }
    5.35 +
    5.36 + out:
    5.37 +    free(path);
    5.38 +    free(buf);
    5.39 +    return value;
    5.40 +}
    5.41 +
    5.42 +int xenstore_vm_write(int domid, char *key, char *value)
    5.43 +{
    5.44 +    char *buf = NULL, *path = NULL;
    5.45 +    int rc = -1;
    5.46 +
    5.47 +    if (xsh == NULL)
    5.48 +	goto out;
    5.49 +
    5.50 +    path = xs_get_domain_path(xsh, domid);
    5.51 +    if (path == NULL) {
    5.52 +	fprintf(logfile, "xs_get_domain_path(%d): error\n");
    5.53 +	goto out;
    5.54 +    }
    5.55 +
    5.56 +    pasprintf(&buf, "%s/vm", path);
    5.57 +    free(path);
    5.58 +    path = xs_read(xsh, XBT_NULL, buf, NULL);
    5.59 +    if (path == NULL) {
    5.60 +	fprintf(logfile, "xs_read(%s): read error\n", buf);
    5.61 +	goto out;
    5.62 +    }
    5.63 +
    5.64 +    pasprintf(&buf, "%s/%s", path, key);
    5.65 +    rc = xs_write(xsh, XBT_NULL, buf, value, strlen(value));
    5.66 +    if (rc) {
    5.67 +	fprintf(logfile, "xs_write(%s, %s): write error\n", buf, key);
    5.68 +	goto out;
    5.69 +    }
    5.70 +
    5.71 + out:
    5.72 +    free(path);
    5.73 +    free(buf);
    5.74 +    return rc;
    5.75 +}
     6.1 --- a/tools/python/xen/xend/XendConfig.py	Tue Apr 03 12:22:10 2007 +0100
     6.2 +++ b/tools/python/xen/xend/XendConfig.py	Tue Apr 03 13:22:37 2007 +0100
     6.3 @@ -118,7 +118,7 @@ LEGACY_CFG_TO_XENAPI_CFG = reverse_dict(
     6.4  # Platform configuration keys.
     6.5  XENAPI_PLATFORM_CFG = [ 'acpi', 'apic', 'boot', 'device_model', 'display', 
     6.6                          'fda', 'fdb', 'keymap', 'isa', 'localtime',
     6.7 -                        'nographic', 'pae', 'serial', 'sdl',
     6.8 +                        'nographic', 'pae', 'rtc_timeoffset', 'serial', 'sdl',
     6.9                          'soundhw','stdvga', 'usb', 'usbdevice', 'vnc',
    6.10                          'vncconsole', 'vncdisplay', 'vnclisten',
    6.11                          'vncpasswd', 'vncunused', 'xauthority']
    6.12 @@ -203,6 +203,7 @@ LEGACY_CFG_TYPES = {
    6.13      'on_xend_stop':  str,
    6.14      'on_xend_start': str,
    6.15      'online_vcpus':  int,
    6.16 +    'rtc/timeoffset': str,
    6.17  }
    6.18  
    6.19  # Values that should be stored in xenstore's /vm/<uuid> that is used
     7.1 --- a/tools/python/xen/xend/XendDomainInfo.py	Tue Apr 03 12:22:10 2007 +0100
     7.2 +++ b/tools/python/xen/xend/XendDomainInfo.py	Tue Apr 03 13:22:37 2007 +0100
     7.3 @@ -859,7 +859,8 @@ class XendDomainInfo:
     7.4          # Check whether values in the configuration have
     7.5          # changed in Xenstore.
     7.6          
     7.7 -        cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash']
     7.8 +        cfg_vm = ['name', 'on_poweroff', 'on_reboot', 'on_crash',
     7.9 +                  'rtc/timeoffset']
    7.10          
    7.11          vm_details = self._readVMDetails([(k,XendConfig.LEGACY_CFG_TYPES[k])
    7.12                                             for k in cfg_vm])
    7.13 @@ -888,6 +889,11 @@ class XendDomainInfo:
    7.14              self.info.update_with_image_sxp(sxp.from_string(image_sxp))
    7.15              changed = True
    7.16  
    7.17 +        # Check if the rtc offset has changes
    7.18 +        if vm_details.get("rtc/timeoffset", 0) != self.info["platform"].get("rtc_timeoffset", 0):
    7.19 +            self.info["platform"]["rtc_timeoffset"] = vm_details.get("rtc/timeoffset", 0)
    7.20 +            changed = True
    7.21 + 
    7.22          if changed:
    7.23              # Update the domain section of the store, as this contains some
    7.24              # parameters derived from the VM configuration.
     8.1 --- a/tools/python/xen/xend/image.py	Tue Apr 03 12:22:10 2007 +0100
     8.2 +++ b/tools/python/xen/xend/image.py	Tue Apr 03 13:22:37 2007 +0100
     8.3 @@ -256,9 +256,12 @@ class HVMImageHandler(ImageHandler):
     8.4          self.xauthority = vmConfig['platform'].get('xauthority')
     8.5          self.vncconsole = vmConfig['platform'].get('vncconsole')
     8.6  
     8.7 +        rtc_timeoffset = vmConfig['platform'].get('rtc_timeoffset')
     8.8 +
     8.9          self.vm.storeVm(("image/dmargs", " ".join(self.dmargs)),
    8.10                          ("image/device-model", self.device_model),
    8.11                          ("image/display", self.display))
    8.12 +        self.vm.storeVm(("rtc/timeoffset", rtc_timeoffset))
    8.13  
    8.14          self.pid = None
    8.15  
     9.1 --- a/tools/python/xen/xm/create.py	Tue Apr 03 12:22:10 2007 +0100
     9.2 +++ b/tools/python/xen/xm/create.py	Tue Apr 03 13:22:37 2007 +0100
     9.3 @@ -186,6 +186,10 @@ gopts.var('cpus', val='CPUS',
     9.4            fn=set_value, default=None,
     9.5            use="CPUS to run the domain on.")
     9.6  
     9.7 +gopts.var('rtc_timeoffset', val='RTC_TIMEOFFSET',
     9.8 +          fn=set_value, default="0",
     9.9 +          use="Set RTC offset.")
    9.10 +
    9.11  gopts.var('pae', val='PAE',
    9.12            fn=set_int, default=1,
    9.13            use="Disable or enable PAE of HVM domain.")
    9.14 @@ -717,7 +721,7 @@ def configure_hvm(config_image, vals):
    9.15      args = [ 'device_model', 'pae', 'vcpus', 'boot', 'fda', 'fdb',
    9.16               'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'soundhw',
    9.17               'vnc', 'vncdisplay', 'vncunused', 'vncconsole', 'vnclisten',
    9.18 -             'sdl', 'display', 'xauthority',
    9.19 +             'sdl', 'display', 'xauthority', 'rtc_timeoffset',
    9.20               'acpi', 'apic', 'usb', 'usbdevice', 'keymap' ]
    9.21      for a in args:
    9.22          if a in vals.__dict__ and vals.__dict__[a] is not None:
    10.1 --- a/xen/arch/x86/hvm/intercept.c	Tue Apr 03 12:22:10 2007 +0100
    10.2 +++ b/xen/arch/x86/hvm/intercept.c	Tue Apr 03 13:22:37 2007 +0100
    10.3 @@ -155,28 +155,13 @@ static inline void hvm_mmio_access(struc
    10.4      }
    10.5  }
    10.6  
    10.7 -int hvm_buffered_io_intercept(ioreq_t *p)
    10.8 +int hvm_buffered_io_send(ioreq_t *p)
    10.9  {
   10.10      struct vcpu *v = current;
   10.11      spinlock_t  *buffered_io_lock;
   10.12      buffered_iopage_t *buffered_iopage =
   10.13          (buffered_iopage_t *)(v->domain->arch.hvm_domain.buffered_io_va);
   10.14      unsigned long tmp_write_pointer = 0;
   10.15 -    int i;
   10.16 -
   10.17 -    /* ignore READ ioreq_t! */
   10.18 -    if ( p->dir == IOREQ_READ )
   10.19 -        return 0;
   10.20 -
   10.21 -    for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
   10.22 -        if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
   10.23 -             p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
   10.24 -                                     hvm_buffered_io_ranges[i]->length )
   10.25 -            break;
   10.26 -    }
   10.27 -
   10.28 -    if ( i == HVM_BUFFERED_IO_RANGE_NR )
   10.29 -        return 0;
   10.30  
   10.31      buffered_io_lock = &v->domain->arch.hvm_domain.buffered_io_lock;
   10.32      spin_lock(buffered_io_lock);
   10.33 @@ -205,6 +190,27 @@ int hvm_buffered_io_intercept(ioreq_t *p
   10.34      return 1;
   10.35  }
   10.36  
   10.37 +int hvm_buffered_io_intercept(ioreq_t *p)
   10.38 +{
   10.39 +    int i;
   10.40 +
   10.41 +    /* ignore READ ioreq_t! */
   10.42 +    if ( p->dir == IOREQ_READ )
   10.43 +        return 0;
   10.44 +
   10.45 +    for ( i = 0; i < HVM_BUFFERED_IO_RANGE_NR; i++ ) {
   10.46 +        if ( p->addr >= hvm_buffered_io_ranges[i]->start_addr &&
   10.47 +             p->addr + p->size - 1 < hvm_buffered_io_ranges[i]->start_addr +
   10.48 +                                     hvm_buffered_io_ranges[i]->length )
   10.49 +            break;
   10.50 +    }
   10.51 +
   10.52 +    if ( i == HVM_BUFFERED_IO_RANGE_NR )
   10.53 +        return 0;
   10.54 +
   10.55 +    return hvm_buffered_io_send(p);
   10.56 +}
   10.57 +
   10.58  int hvm_mmio_intercept(ioreq_t *p)
   10.59  {
   10.60      struct vcpu *v = current;
    11.1 --- a/xen/arch/x86/hvm/platform.c	Tue Apr 03 12:22:10 2007 +0100
    11.2 +++ b/xen/arch/x86/hvm/platform.c	Tue Apr 03 13:22:37 2007 +0100
    11.3 @@ -921,6 +921,26 @@ static void send_mmio_req(unsigned char 
    11.4      hvm_send_assist_req(v);
    11.5  }
    11.6  
    11.7 +void send_timeoffset_req(unsigned long timeoff)
    11.8 +{
    11.9 +    ioreq_t p[1];
   11.10 +
   11.11 +    if ( timeoff == 0 )
   11.12 +        return;
   11.13 +
   11.14 +    memset(p, 0, sizeof(*p));
   11.15 +
   11.16 +    p->type = IOREQ_TYPE_TIMEOFFSET;
   11.17 +    p->size = 4;
   11.18 +    p->dir = IOREQ_WRITE;
   11.19 +    p->data = timeoff;
   11.20 +
   11.21 +    p->state = STATE_IOREQ_READY;
   11.22 +
   11.23 +    if ( !hvm_buffered_io_send(p) )
   11.24 +        printk("Unsuccessful timeoffset update\n");
   11.25 +}
   11.26 +
   11.27  static void mmio_operands(int type, unsigned long gpa,
   11.28                            struct hvm_io_op *mmio_op,
   11.29                            unsigned char op_size)
    12.1 --- a/xen/arch/x86/hvm/rtc.c	Tue Apr 03 12:22:10 2007 +0100
    12.2 +++ b/xen/arch/x86/hvm/rtc.c	Tue Apr 03 13:22:37 2007 +0100
    12.3 @@ -157,6 +157,10 @@ static inline int from_bcd(RTCState *s, 
    12.4  static void rtc_set_time(RTCState *s)
    12.5  {
    12.6      struct tm *tm = &s->current_tm;
    12.7 +    unsigned long before, after; /* XXX s_time_t */
    12.8 +      
    12.9 +    before = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
   12.10 +		    tm->tm_hour, tm->tm_min, tm->tm_sec);
   12.11      
   12.12      tm->tm_sec = from_bcd(s, s->hw.cmos_data[RTC_SECONDS]);
   12.13      tm->tm_min = from_bcd(s, s->hw.cmos_data[RTC_MINUTES]);
   12.14 @@ -168,6 +172,10 @@ static void rtc_set_time(RTCState *s)
   12.15      tm->tm_mday = from_bcd(s, s->hw.cmos_data[RTC_DAY_OF_MONTH]);
   12.16      tm->tm_mon = from_bcd(s, s->hw.cmos_data[RTC_MONTH]) - 1;
   12.17      tm->tm_year = from_bcd(s, s->hw.cmos_data[RTC_YEAR]) + 100;
   12.18 +
   12.19 +    after = mktime(tm->tm_year, tm->tm_mon, tm->tm_mday,
   12.20 +                   tm->tm_hour, tm->tm_min, tm->tm_sec);
   12.21 +    send_timeoffset_req(after - before);
   12.22  }
   12.23  
   12.24  static void rtc_copy_date(RTCState *s)
    13.1 --- a/xen/arch/x86/time.c	Tue Apr 03 12:22:10 2007 +0100
    13.2 +++ b/xen/arch/x86/time.c	Tue Apr 03 13:22:37 2007 +0100
    13.3 @@ -573,7 +573,7 @@ static void init_platform_timer(void)
    13.4   * machines were long is 32-bit! (However, as time_t is signed, we
    13.5   * will already get problems at other places on 2038-01-19 03:14:08)
    13.6   */
    13.7 -static inline unsigned long
    13.8 +unsigned long
    13.9  mktime (unsigned int year, unsigned int mon,
   13.10          unsigned int day, unsigned int hour,
   13.11          unsigned int min, unsigned int sec)
    14.1 --- a/xen/include/asm-x86/hvm/io.h	Tue Apr 03 12:22:10 2007 +0100
    14.2 +++ b/xen/include/asm-x86/hvm/io.h	Tue Apr 03 13:22:37 2007 +0100
    14.3 @@ -127,6 +127,7 @@ static inline int hvm_portio_intercept(i
    14.4  }
    14.5  
    14.6  extern int hvm_mmio_intercept(ioreq_t *p);
    14.7 +extern int hvm_buffered_io_send(ioreq_t *p);
    14.8  extern int hvm_buffered_io_intercept(ioreq_t *p);
    14.9  
   14.10  static inline int register_portio_handler(
   14.11 @@ -145,6 +146,7 @@ static inline int irq_masked(unsigned lo
   14.12  
   14.13  extern void send_pio_req(unsigned long port, unsigned long count, int size,
   14.14                           paddr_t value, int dir, int df, int value_is_ptr);
   14.15 +void send_timeoffset_req(unsigned long timeoff);
   14.16  extern void handle_mmio(unsigned long gpa);
   14.17  extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
   14.18  extern void hvm_io_assist(struct vcpu *v);
    15.1 --- a/xen/include/asm-x86/time.h	Tue Apr 03 12:22:10 2007 +0100
    15.2 +++ b/xen/include/asm-x86/time.h	Tue Apr 03 13:22:37 2007 +0100
    15.3 @@ -16,4 +16,9 @@ static inline cycles_t get_cycles(void)
    15.4      return c;
    15.5  }
    15.6  
    15.7 +unsigned long
    15.8 +mktime (unsigned int year, unsigned int mon,
    15.9 +        unsigned int day, unsigned int hour,
   15.10 +        unsigned int min, unsigned int sec);
   15.11 +
   15.12  #endif /* __X86_TIME_H__ */
    16.1 --- a/xen/include/public/hvm/ioreq.h	Tue Apr 03 12:22:10 2007 +0100
    16.2 +++ b/xen/include/public/hvm/ioreq.h	Tue Apr 03 13:22:37 2007 +0100
    16.3 @@ -39,6 +39,7 @@
    16.4  #define IOREQ_TYPE_XOR          4
    16.5  #define IOREQ_TYPE_XCHG         5
    16.6  #define IOREQ_TYPE_ADD          6
    16.7 +#define IOREQ_TYPE_TIMEOFFSET   7
    16.8  
    16.9  /*
   16.10   * VMExit dispatcher should cooperate with instruction decoder to