diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/examples/xmexample.hvm | 11 | ||||
-rw-r--r-- | tools/libxc/xc_domain.c | 49 | ||||
-rw-r--r-- | tools/libxc/xc_domain_restore.c | 12 | ||||
-rw-r--r-- | tools/libxc/xc_domain_save.c | 31 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 14 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/xc/xc.c | 17 | ||||
-rw-r--r-- | tools/python/xen/xend/XendConfig.py | 6 | ||||
-rw-r--r-- | tools/python/xen/xend/XendDomainInfo.py | 6 | ||||
-rw-r--r-- | tools/python/xen/xm/create.py | 10 | ||||
-rw-r--r-- | tools/python/xen/xm/xenapi_create.py | 2 |
10 files changed, 128 insertions, 30 deletions
diff --git a/tools/examples/xmexample.hvm b/tools/examples/xmexample.hvm index e5ae97f966..09edda6aac 100644 --- a/tools/examples/xmexample.hvm +++ b/tools/examples/xmexample.hvm @@ -178,11 +178,16 @@ stdvga=0 serial='pty' #---------------------------------------------------------------------------- -# tsc_native : TSC mode (0=emulate TSC, 1=native TSC) +# tsc_mode : TSC mode (0=default, 1=native TSC, 2=never emulate, 3=pvrdtscp) # emulate TSC provides synced TSC for all vcpus, but lose perfomrance. # native TSC leverages hardware's TSC(no perf loss), but vcpu's TSC may lose -# sync due to hardware's unreliable/unsynced TSC between CPUs. -tsc_native=1 +# sync due to hardware's unreliable/unsynced TSC between CPUs. +# default intelligently uses native TSC on machines where it is safe, but +# switches to emulated if necessary after save/restore/migration +# pvrdtscp is for intelligent apps that use special Xen-only paravirtualized +# cpuid instructions to obtain offset/scaling/migration info and maximize +# performance within pools of machines that support the rdtscp instruction +tsc_mode=0 #----------------------------------------------------------------------------- # Qemu Monitor, default is disable diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index f872583926..54a5914e9b 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -466,24 +466,61 @@ int xc_domain_set_time_offset(int xc_handle, return do_domctl(xc_handle, &domctl); } -int xc_domain_set_tsc_native(int xc_handle, uint32_t domid, int is_native) +int xc_domain_disable_migrate(int xc_handle, uint32_t domid) { DECLARE_DOMCTL; - domctl.cmd = XEN_DOMCTL_set_tsc_native; + domctl.cmd = XEN_DOMCTL_disable_migrate; domctl.domain = (domid_t)domid; - domctl.u.set_tsc_native.is_native = is_native; + domctl.u.disable_migrate.disable = 1; return do_domctl(xc_handle, &domctl); } -int xc_domain_disable_migrate(int xc_handle, uint32_t domid) +int xc_domain_set_tsc_info(int xc_handle, + uint32_t domid, + uint32_t tsc_mode, + uint64_t elapsed_nsec, + uint32_t gtsc_khz, + uint32_t incarnation) { DECLARE_DOMCTL; - domctl.cmd = XEN_DOMCTL_disable_migrate; + domctl.cmd = XEN_DOMCTL_settscinfo; domctl.domain = (domid_t)domid; - domctl.u.disable_migrate.disable = 1; + domctl.u.tsc_info.info.tsc_mode = tsc_mode; + domctl.u.tsc_info.info.elapsed_nsec = elapsed_nsec; + domctl.u.tsc_info.info.gtsc_khz = gtsc_khz; + domctl.u.tsc_info.info.incarnation = incarnation; return do_domctl(xc_handle, &domctl); } +int xc_domain_get_tsc_info(int xc_handle, + uint32_t domid, + uint32_t *tsc_mode, + uint64_t *elapsed_nsec, + uint32_t *gtsc_khz, + uint32_t *incarnation) +{ + int rc; + DECLARE_DOMCTL; + xen_guest_tsc_info_t info = { 0 }; + + domctl.cmd = XEN_DOMCTL_gettscinfo; + domctl.domain = (domid_t)domid; + set_xen_guest_handle(domctl.u.tsc_info.out_info, &info); + if ( (rc = lock_pages(&info, sizeof(info))) != 0 ) + return rc; + rc = do_domctl(xc_handle, &domctl); + if ( rc == 0 ) + { + *tsc_mode = info.tsc_mode; + *elapsed_nsec = info.elapsed_nsec; + *gtsc_khz = info.gtsc_khz; + *incarnation = info.incarnation; + } + unlock_pages(&info,sizeof(info)); + return rc; +} + + int xc_domain_memory_increase_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, diff --git a/tools/libxc/xc_domain_restore.c b/tools/libxc/xc_domain_restore.c index 01d7924f07..cf6a63c25a 100644 --- a/tools/libxc/xc_domain_restore.c +++ b/tools/libxc/xc_domain_restore.c @@ -1084,6 +1084,18 @@ static int pagebuf_get_one(pagebuf_t* buf, int fd, int xch, uint32_t dom) return -1; } return pagebuf_get_one(buf, fd, xch, dom); + } else if ( count == -7 ) { + uint32_t tsc_mode, khz, incarn; + uint64_t nsec; + if ( read_exact(fd, &tsc_mode, sizeof(uint32_t)) || + read_exact(fd, &nsec, sizeof(uint64_t)) || + read_exact(fd, &khz, sizeof(uint32_t)) || + read_exact(fd, &incarn, sizeof(uint32_t)) || + xc_domain_set_tsc_info(xch, dom, tsc_mode, nsec, khz, incarn) ) { + ERROR("error reading/restoring tsc info"); + return -1; + } + return pagebuf_get_one(buf, fd, xch, dom); } else if ( (count > MAX_BATCH_SIZE) || (count < 0) ) { ERROR("Max batch size exceeded (%d). Giving up.", count); return -1; diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c index 30c1b6d3a4..9d706a92d3 100644 --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -841,6 +841,24 @@ static xen_pfn_t *map_and_save_p2m_table(int xc_handle, return success ? p2m : NULL; } +/* must be done AFTER suspend_and_state() */ +static int save_tsc_info(int xc_handle, uint32_t dom, int io_fd) +{ + int marker = -7; + uint32_t tsc_mode, khz, incarn; + uint64_t nsec; + + if ( xc_domain_get_tsc_info(xc_handle, dom, &tsc_mode, + &nsec, &khz, &incarn) < 0 || + write_exact(io_fd, &marker, sizeof(marker)) || + write_exact(io_fd, &tsc_mode, sizeof(tsc_mode)) || + write_exact(io_fd, &nsec, sizeof(nsec)) || + write_exact(io_fd, &khz, sizeof(khz)) || + write_exact(io_fd, &incarn, sizeof(incarn)) ) + return -1; + return 0; +} + int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, uint32_t max_factor, uint32_t flags, struct save_callbacks* callbacks, @@ -1100,6 +1118,12 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } + if ( !live && save_tsc_info(xc_handle, dom, io_fd) < 0 ) + { + ERROR("Error when writing to state file (tsc)"); + goto out; + } + copypages: #define write_exact(fd, buf, len) write_buffer(last_iter, &ob, (fd), (buf), (len)) #ifdef ratewrite @@ -1458,6 +1482,13 @@ int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } + if ( save_tsc_info(xc_handle, dom, io_fd) < 0 ) + { + ERROR("Error when writing to state file (tsc)"); + goto out; + } + + } if ( xc_shadow_control(xc_handle, dom, diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index d6ecaf399c..9fc05bb30b 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -628,7 +628,19 @@ int xc_domain_set_time_offset(int xc_handle, uint32_t domid, int32_t time_offset_seconds); -int xc_domain_set_tsc_native(int xc_handle, uint32_t domid, int is_native); +int xc_domain_set_tsc_info(int xc_handle, + uint32_t domid, + uint32_t tsc_mode, + uint64_t elapsed_nsec, + uint32_t gtsc_khz, + uint32_t incarnation); + +int xc_domain_get_tsc_info(int xc_handle, + uint32_t domid, + uint32_t *tsc_mode, + uint64_t *elapsed_nsec, + uint32_t *gtsc_khz, + uint32_t *incarnation); int xc_domain_disable_migrate(int xc_handle, uint32_t domid); diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index 7eaf63b94e..aa780aa303 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -1486,14 +1486,14 @@ static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args) return zero; } -static PyObject *pyxc_domain_set_tsc_native(XcObject *self, PyObject *args) +static PyObject *pyxc_domain_set_tsc_info(XcObject *self, PyObject *args) { - uint32_t dom, is_native; + uint32_t dom, tsc_mode; - if (!PyArg_ParseTuple(args, "ii", &dom, &is_native)) + if (!PyArg_ParseTuple(args, "ii", &dom, &tsc_mode)) return NULL; - if (xc_domain_set_tsc_native(self->xc_handle, dom, is_native) != 0) + if (xc_domain_set_tsc_info(self->xc_handle, dom, tsc_mode, 0, 0, 0) != 0) return pyxc_error_to_exception(); Py_INCREF(zero); @@ -2036,12 +2036,13 @@ static PyMethodDef pyxc_methods[] = { " offset [int]: Time offset from UTC in seconds.\n" "Returns: [int] 0 on success; -1 on error.\n" }, - { "domain_set_tsc_native", - (PyCFunction)pyxc_domain_set_tsc_native, + { "domain_set_tsc_info", + (PyCFunction)pyxc_domain_set_tsc_info, METH_VARARGS, "\n" - "Set a domain's TSC mode (emulate vs native)\n" + "Set a domain's TSC mode\n" " dom [int]: Domain whose TSC mode is being set.\n" - " is_native [int]: 1=native, 0=emulate.\n" + " tsc_mode [int]: 0=default (monotonic, but native where possible)\n" + " 1=always emulate 2=never emulate 3=pvrdtscp\n" "Returns: [int] 0 on success; -1 on error.\n" }, { "domain_disable_migrate", diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 0eadf343d3..3227cd4def 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -163,7 +163,7 @@ XENAPI_PLATFORM_CFG_TYPES = { 'vncdisplay': int, 'vnclisten': str, 'timer_mode': int, - 'tsc_native': int, + 'tsc_mode': int, 'vpt_align': int, 'viridian': int, 'vncpasswd': str, @@ -477,8 +477,8 @@ class XendConfig(dict): if not os.path.exists(self['platform']['device_model']): raise VmError("device model '%s' not found" % str(self['platform']['device_model'])) - if 'tsc_native' not in self['platform']: - self['platform']['tsc_native'] = 0 + if 'tsc_mode' not in self['platform']: + self['platform']['tsc_mode'] = 0 if 'nomigrate' not in self['platform']: self['platform']['nomigrate'] = 0 diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 592ba6fad8..8198228b9f 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2468,9 +2468,9 @@ class XendDomainInfo: self._recreateDom() # Set TSC mode of domain - tsc_native = self.info["platform"].get("tsc_native") - if arch.type == "x86" and tsc_native is not None: - xc.domain_set_tsc_native(self.domid, int(tsc_native)) + tsc_mode = self.info["platform"].get("tsc_mode") + if arch.type == "x86" and tsc_mode is not None: + xc.domain_set_tsc_info(self.domid, int(tsc_mode)) # Set timer configuration of domain timer_mode = self.info["platform"].get("timer_mode") diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index d6485a59a1..32b19235e1 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -221,9 +221,9 @@ gopts.var('timer_mode', val='TIMER_MODE', use="""Timer mode (0=delay virtual time when ticks are missed; 1=virtual time is always wallclock time.""") -gopts.var('tsc_native', val='TSC_NATIVE', +gopts.var('tsc_mode', val='TSC_MODE', fn=set_int, default=0, - use="""TSC mode (0=emulate TSC, 1=native TSC).""") + use="""TSC mode (0=default, 1=always emulate, 2=never emulate, 3=pvrdtscp).""") gopts.var('nomigrate', val='NOMIGRATE', fn=set_int, default=0, @@ -738,8 +738,8 @@ def configure_image(vals): if vals.suppress_spurious_page_faults: config_image.append(['suppress_spurious_page_faults', vals.suppress_spurious_page_faults]) - if vals.tsc_native is not None: - config_image.append(['tsc_native', vals.tsc_native]) + if vals.tsc_mode is not None: + config_image.append(['tsc_mode', vals.tsc_mode]) if vals.nomigrate is not None: config_image.append(['nomigrate', vals.nomigrate]) @@ -1036,7 +1036,7 @@ def make_config(vals): config.append([n, v]) map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory', - 'restart', 'on_poweroff', 'tsc_native', 'nomigrate', + 'restart', 'on_poweroff', 'tsc_mode', 'nomigrate', 'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features', 'on_xend_start', 'on_xend_stop', 'target', 'cpuid', 'cpuid_check', 'machine_address_size', 'suppress_spurious_page_faults']) diff --git a/tools/python/xen/xm/xenapi_create.py b/tools/python/xen/xm/xenapi_create.py index 9cfdb87d7e..4c0177b4aa 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -1108,7 +1108,7 @@ class sxp2xml: 'pci_msitranslate', 'pci_power_mgmt', 'xen_platform_pci', - 'tsc_native' + 'tsc_mode' 'description', 'nomigrate' ] |