diff options
-rw-r--r-- | tools/libxc/xc_domain.c | 9 | ||||
-rw-r--r-- | tools/libxc/xenctrl.h | 2 | ||||
-rw-r--r-- | tools/python/xen/lowlevel/xc/xc.c | 22 | ||||
-rw-r--r-- | tools/python/xen/xend/XendConfig.py | 4 | ||||
-rw-r--r-- | tools/python/xen/xend/XendDomainInfo.py | 7 | ||||
-rw-r--r-- | tools/python/xen/xm/create.py | 9 | ||||
-rw-r--r-- | tools/python/xen/xm/xenapi_create.py | 1 | ||||
-rw-r--r-- | xen/arch/x86/domain.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/domctl.c | 20 | ||||
-rw-r--r-- | xen/arch/x86/hvm/hvm.c | 48 | ||||
-rw-r--r-- | xen/arch/x86/hvm/save.c | 11 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/svm.c | 11 | ||||
-rw-r--r-- | xen/arch/x86/hvm/svm/vmcb.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmcs.c | 6 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vmx/vmx.c | 10 | ||||
-rw-r--r-- | xen/arch/x86/hvm/vpt.c | 2 | ||||
-rw-r--r-- | xen/arch/x86/time.c | 34 | ||||
-rw-r--r-- | xen/include/asm-x86/domain.h | 2 | ||||
-rw-r--r-- | xen/include/asm-x86/hvm/hvm.h | 4 | ||||
-rw-r--r-- | xen/include/asm-x86/time.h | 1 | ||||
-rw-r--r-- | xen/include/public/domctl.h | 7 |
21 files changed, 160 insertions, 54 deletions
diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 6ed4f52ec3..61cde9af39 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -466,6 +466,15 @@ 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) +{ + DECLARE_DOMCTL; + domctl.cmd = XEN_DOMCTL_set_tsc_native; + domctl.domain = (domid_t)domid; + domctl.u.set_tsc_native.is_native = is_native; + return do_domctl(xc_handle, &domctl); +} + int xc_domain_memory_increase_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 1eade658a0..81ba26d616 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -628,6 +628,8 @@ 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_memory_increase_reservation(int xc_handle, uint32_t domid, unsigned long nr_extents, diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c index c7b484f983..3bff6a7f97 100644 --- a/tools/python/xen/lowlevel/xc/xc.c +++ b/tools/python/xen/lowlevel/xc/xc.c @@ -1459,6 +1459,20 @@ static PyObject *pyxc_domain_set_time_offset(XcObject *self, PyObject *args) return zero; } +static PyObject *pyxc_domain_set_tsc_native(XcObject *self, PyObject *args) +{ + uint32_t dom, is_native; + + if (!PyArg_ParseTuple(args, "ii", &dom, &is_native)) + return NULL; + + if (xc_domain_set_tsc_native(self->xc_handle, dom, is_native) != 0) + return pyxc_error_to_exception(); + + Py_INCREF(zero); + return zero; +} + static PyObject *pyxc_domain_send_trigger(XcObject *self, PyObject *args, PyObject *kwds) @@ -1981,6 +1995,14 @@ 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, + METH_VARARGS, "\n" + "Set a domain's TSC mode (emulate vs native)\n" + " dom [int]: Domain whose TSC mode is being set.\n" + " is_native [int]: 1=native, 0=emulate.\n" + "Returns: [int] 0 on success; -1 on error.\n" }, + { "domain_send_trigger", (PyCFunction)pyxc_domain_send_trigger, METH_VARARGS | METH_KEYWORDS, "\n" diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index d5cd17cf1b..9c84c26c65 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -162,6 +162,7 @@ XENAPI_PLATFORM_CFG_TYPES = { 'vncdisplay': int, 'vnclisten': str, 'timer_mode': int, + 'tsc_native': int, 'vpt_align': int, 'viridian': int, 'vncpasswd': str, @@ -473,6 +474,9 @@ 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 self.is_hvm(): if 'timer_mode' not in self['platform']: self['platform']['timer_mode'] = 1 diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index b7a4307ebb..b38a5fea4b 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -2423,7 +2423,12 @@ class XendDomainInfo: self._recreateDom() - # Set timer configration of domain + # 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, tsc_native) + + # Set timer configuration of domain timer_mode = self.info["platform"].get("timer_mode") if hvm and timer_mode is not None: xc.hvm_set_param(self.domid, HVM_PARAM_TIMER_MODE, diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py index d7ed07b3c6..14f8aa6425 100644 --- a/tools/python/xen/xm/create.py +++ b/tools/python/xen/xm/create.py @@ -221,6 +221,10 @@ 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', + fn=set_int, default=0, + use="""TSC mode (0=emulate TSC, 1=native TSC).""") + gopts.var('vpt_align', val='VPT_ALIGN', fn=set_int, default=1, use="Enable aligning all periodic vpt to reduce timer interrupts.") @@ -715,6 +719,9 @@ 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]) + return config_image def configure_disks(config_devs, vals): @@ -984,7 +991,7 @@ def make_config(vals): config.append([n, v]) map(add_conf, ['name', 'memory', 'maxmem', 'shadow_memory', - 'restart', 'on_poweroff', + 'restart', 'on_poweroff', 'tsc_native', '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 27702635ae..903b29d21a 100644 --- a/tools/python/xen/xm/xenapi_create.py +++ b/tools/python/xen/xm/xenapi_create.py @@ -1066,6 +1066,7 @@ class sxp2xml: 'pci_msitranslate', 'pci_power_mgmt', 'xen_platform_pci', + 'tsc_native' ] platform_configs = [] diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 85e0ba0d59..d9d6fb075e 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -520,8 +520,6 @@ int arch_domain_create(struct domain *d, unsigned int domcr_flags) d->arch.cpuids[i].input[1] = XEN_CPUID_INPUT_UNUSED; } - /* For now, per-domain SoftTSC status is taken from global boot param. */ - d->arch.vtsc = opt_softtsc; spin_lock_init(&d->arch.vtsc_lock); return 0; diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index cb5bec7f71..c5684c9a22 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -1060,6 +1060,26 @@ long arch_do_domctl( } break; + case XEN_DOMCTL_set_tsc_native: + { + struct domain *d; + + ret = -ESRCH; + d = rcu_lock_domain_by_id(domctl->domain); + if ( d == NULL ) + break; + + domain_pause(d); + d->arch.vtsc = !domctl->u.set_tsc_native.is_native; + if ( is_hvm_domain(d) ) + hvm_set_rdtsc_exiting(d, d->arch.vtsc || hvm_gtsc_need_scale(d)); + domain_unpause(d); + + rcu_unlock_domain(d); + ret = 0; + } + break; + case XEN_DOMCTL_suppress_spurious_page_faults: { struct domain *d; diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 7748b4579e..b4e3708ca7 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -142,23 +142,23 @@ uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2) return TRAP_double_fault; } -void hvm_enable_rdtsc_exiting(struct domain *d) +void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable) { struct vcpu *v; - if ( opt_softtsc || !hvm_funcs.enable_rdtsc_exiting ) - return; - for_each_vcpu ( d, v ) - hvm_funcs.enable_rdtsc_exiting(v); + hvm_funcs.set_rdtsc_exiting(v, enable); } int hvm_gtsc_need_scale(struct domain *d) { uint32_t gtsc_mhz, htsc_mhz; + if ( d->arch.vtsc ) + return 0; + gtsc_mhz = d->arch.hvm_domain.gtsc_khz / 1000; - htsc_mhz = opt_softtsc ? 1000 : ((uint32_t)cpu_khz / 1000); + htsc_mhz = (uint32_t)cpu_khz / 1000; d->arch.hvm_domain.tsc_scaled = (gtsc_mhz && (gtsc_mhz != htsc_mhz)); return d->arch.hvm_domain.tsc_scaled; @@ -171,38 +171,44 @@ static u64 hvm_h2g_scale_tsc(struct vcpu *v, u64 host_tsc) if ( !v->domain->arch.hvm_domain.tsc_scaled ) return host_tsc; - htsc_khz = opt_softtsc ? 1000000 : cpu_khz; + htsc_khz = cpu_khz; gtsc_khz = v->domain->arch.hvm_domain.gtsc_khz; return muldiv64(host_tsc, gtsc_khz, htsc_khz); } void hvm_set_guest_tsc(struct vcpu *v, u64 guest_tsc) { - uint64_t host_tsc, scaled_htsc; + uint64_t tsc; - if ( opt_softtsc ) - host_tsc = hvm_get_guest_time(v); + if ( v->domain->arch.vtsc ) + { + tsc = hvm_get_guest_time(v); + } else - rdtscll(host_tsc); - - scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc); + { + rdtscll(tsc); + tsc = hvm_h2g_scale_tsc(v, tsc); + } - v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - scaled_htsc; + v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - tsc; hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset); } u64 hvm_get_guest_tsc(struct vcpu *v) { - uint64_t host_tsc, scaled_htsc; + uint64_t tsc; - if ( opt_softtsc ) - host_tsc = hvm_get_guest_time(v); + if ( v->domain->arch.vtsc ) + { + tsc = hvm_get_guest_time(v); + } else - rdtscll(host_tsc); - - scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc); + { + rdtscll(tsc); + tsc = hvm_h2g_scale_tsc(v, tsc); + } - return scaled_htsc + v->arch.hvm_vcpu.cache_tsc_offset; + return tsc + v->arch.hvm_vcpu.cache_tsc_offset; } void hvm_migrate_timers(struct vcpu *v) diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c index af5aad7221..e409add6b6 100644 --- a/xen/arch/x86/hvm/save.c +++ b/xen/arch/x86/hvm/save.c @@ -61,15 +61,14 @@ int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr) "does not match host (%#"PRIx32").\n", hdr->cpuid, eax); /* Restore guest's preferred TSC frequency. */ - d->arch.hvm_domain.gtsc_khz = hdr->gtsc_khz; - - if ( hdr->gtsc_khz && hvm_gtsc_need_scale(d) ) + if ( hdr->gtsc_khz ) + d->arch.hvm_domain.gtsc_khz = hdr->gtsc_khz; + if ( hvm_gtsc_need_scale(d) ) { - hvm_enable_rdtsc_exiting(d); + hvm_set_rdtsc_exiting(d, 1); gdprintk(XENLOG_WARNING, "Domain %d expects freq %uMHz " "but host's freq is %luMHz: trap and emulate rdtsc\n", - d->domain_id, hdr->gtsc_khz / 1000, opt_softtsc ? 1000ul : - cpu_khz / 1000); + d->domain_id, hdr->gtsc_khz / 1000, cpu_khz / 1000); } /* VGA state is not saved/restored, so we nobble the cache. */ diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index ead3eeca31..b34289878b 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -619,6 +619,14 @@ static void svm_set_tsc_offset(struct vcpu *v, u64 offset) v->arch.hvm_svm.vmcb->tsc_offset = offset; } +static void svm_set_rdtsc_exiting(struct vcpu *v, bool_t enable) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_RDTSC; + if ( enable ) + vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC; +} + static void svm_init_hypercall_page(struct domain *d, void *hypercall_page) { char *p; @@ -845,7 +853,8 @@ static struct hvm_function_table svm_function_table = { .fpu_dirty_intercept = svm_fpu_dirty_intercept, .msr_read_intercept = svm_msr_read_intercept, .msr_write_intercept = svm_msr_write_intercept, - .invlpg_intercept = svm_invlpg_intercept + .invlpg_intercept = svm_invlpg_intercept, + .set_rdtsc_exiting = svm_set_rdtsc_exiting }; static int svm_cpu_up(struct cpuinfo_x86 *c) diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 6f1f087d88..202cc9810d 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -167,7 +167,7 @@ static int construct_vmcb(struct vcpu *v) /* TSC. */ vmcb->tsc_offset = 0; - if ( opt_softtsc ) + if ( v->domain->arch.vtsc ) vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC; /* Guest EFER. */ diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 11dc468521..724d0a61d3 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -133,13 +133,14 @@ static void vmx_init_vmcs_config(void) CPU_BASED_MOV_DR_EXITING | CPU_BASED_ACTIVATE_IO_BITMAP | CPU_BASED_USE_TSC_OFFSETING | - (opt_softtsc ? CPU_BASED_RDTSC_EXITING : 0)); + CPU_BASED_RDTSC_EXITING); opt = (CPU_BASED_ACTIVATE_MSR_BITMAP | CPU_BASED_TPR_SHADOW | CPU_BASED_MONITOR_TRAP_FLAG | CPU_BASED_ACTIVATE_SECONDARY_CONTROLS); _vmx_cpu_based_exec_control = adjust_vmx_controls( min, opt, MSR_IA32_VMX_PROCBASED_CTLS); + _vmx_cpu_based_exec_control &= ~CPU_BASED_RDTSC_EXITING; #ifdef __x86_64__ if ( !(_vmx_cpu_based_exec_control & CPU_BASED_TPR_SHADOW) ) { @@ -553,6 +554,9 @@ static int construct_vmcs(struct vcpu *v) __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); v->arch.hvm_vmx.exec_control = vmx_cpu_based_exec_control; + if ( d->arch.vtsc ) + v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING; + v->arch.hvm_vmx.secondary_exec_control = vmx_secondary_exec_control; if ( paging_mode_hap(d) ) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index c51f560ab3..151d3a5be0 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -949,13 +949,15 @@ static void vmx_set_tsc_offset(struct vcpu *v, u64 offset) vmx_vmcs_exit(v); } -static void vmx_enable_rdtsc_exiting(struct vcpu *v) +static void vmx_set_rdtsc_exiting(struct vcpu *v, bool_t enable) { vmx_vmcs_enter(v); - v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING; + v->arch.hvm_vmx.exec_control &= ~CPU_BASED_RDTSC_EXITING; + if ( enable ) + v->arch.hvm_vmx.exec_control |= CPU_BASED_RDTSC_EXITING; __vmwrite(CPU_BASED_VM_EXEC_CONTROL, v->arch.hvm_vmx.exec_control); vmx_vmcs_exit(v); - } +} static void vmx_init_hypercall_page(struct domain *d, void *hypercall_page) { @@ -1414,7 +1416,7 @@ static struct hvm_function_table vmx_function_table = { .invlpg_intercept = vmx_invlpg_intercept, .set_uc_mode = vmx_set_uc_mode, .set_info_guest = vmx_set_info_guest, - .enable_rdtsc_exiting = vmx_enable_rdtsc_exiting + .set_rdtsc_exiting = vmx_set_rdtsc_exiting }; static unsigned long *vpid_bitmap; diff --git a/xen/arch/x86/hvm/vpt.c b/xen/arch/x86/hvm/vpt.c index 9a0bb06429..22d66f6fed 100644 --- a/xen/arch/x86/hvm/vpt.c +++ b/xen/arch/x86/hvm/vpt.c @@ -33,7 +33,7 @@ void hvm_init_guest_time(struct domain *d) pl->stime_offset = -(u64)get_s_time(); pl->last_guest_time = 0; - d->arch.hvm_domain.gtsc_khz = opt_softtsc ? 1000000 : cpu_khz; + d->arch.hvm_domain.gtsc_khz = cpu_khz; d->arch.hvm_domain.tsc_scaled = 0; } diff --git a/xen/arch/x86/time.c b/xen/arch/x86/time.c index a4bb329524..f21861d7e6 100644 --- a/xen/arch/x86/time.c +++ b/xen/arch/x86/time.c @@ -36,9 +36,6 @@ static char __initdata opt_clocksource[10]; string_param("clocksource", opt_clocksource); -int opt_softtsc; -boolean_param("softtsc", opt_softtsc); - /* * opt_consistent_tscs: All TSCs tick at the exact same rate, allowing * simplified system time handling. @@ -1436,20 +1433,18 @@ struct tm wallclock_time(void) * PV SoftTSC Emulation. */ -static unsigned long rdtsc_kerncount, rdtsc_usercount; - void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs) { s_time_t now; if ( guest_kernel_mode(v, regs) ) { - rdtsc_kerncount++; + v->domain->arch.vtsc_kerncount++; rdtsc(regs->eax, regs->edx); } else { - rdtsc_usercount++; + v->domain->arch.vtsc_kerncount++; spin_lock(&v->domain->arch.vtsc_lock); now = get_s_time() + v->domain->arch.vtsc_stime_offset; if ( (int64_t)(now - v->domain->arch.vtsc_last) > 0 ) @@ -1462,10 +1457,28 @@ void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs) } } +/* vtsc may incur measurable performance degradation, diagnose with this */ static void dump_softtsc(unsigned char key) { - printk("softtsc count: %lu kernel, %lu user\n", - rdtsc_kerncount, rdtsc_usercount); + struct domain *d; + int domcnt = 0; + + for_each_domain ( d ) + { + if ( !d->arch.vtsc ) + continue; + if ( is_hvm_domain(d) ) + printk("dom%u (hvm) vtsc count: %"PRIu64" total\n", + d->domain_id, d->arch.vtsc_kerncount); + else + printk("dom%u vtsc count: %"PRIu64" kernel, %"PRIu64" user\n", + d->domain_id, d->arch.vtsc_kerncount, + d->arch.vtsc_usercount); + domcnt++; + } + + if ( !domcnt ) + printk("All domains have native TSC\n"); } static struct keyhandler dump_softtsc_keyhandler = { @@ -1476,8 +1489,7 @@ static struct keyhandler dump_softtsc_keyhandler = { static int __init setup_dump_softtsc(void) { - if ( opt_softtsc ) - register_keyhandler('s', &dump_softtsc_keyhandler); + register_keyhandler('s', &dump_softtsc_keyhandler); return 0; } __initcall(setup_dump_softtsc); diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index cf65772ebb..6edbe3b215 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -304,6 +304,8 @@ struct arch_domain bool_t vtsc; s_time_t vtsc_last; spinlock_t vtsc_lock; + uint64_t vtsc_kerncount; /* for hvm, counts all vtsc */ + uint64_t vtsc_usercount; /* not used for hvm */ int64_t vtsc_stime_offset; } __cacheline_aligned; diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 76e06d7db6..327a1c9737 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -131,7 +131,7 @@ struct hvm_function_table { void (*invlpg_intercept)(unsigned long vaddr); void (*set_uc_mode)(struct vcpu *v); void (*set_info_guest)(struct vcpu *v); - void (*enable_rdtsc_exiting)(struct vcpu *v); + void (*set_rdtsc_exiting)(struct vcpu *v, bool_t); }; extern struct hvm_function_table hvm_funcs; @@ -288,7 +288,7 @@ int hvm_event_needs_reinjection(uint8_t type, uint8_t vector); uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2); -void hvm_enable_rdtsc_exiting(struct domain *d); +void hvm_set_rdtsc_exiting(struct domain *d, bool_t enable); int hvm_gtsc_need_scale(struct domain *d); static inline int hvm_cpu_up(void) diff --git a/xen/include/asm-x86/time.h b/xen/include/asm-x86/time.h index ec06313f95..dac53bcc25 100644 --- a/xen/include/asm-x86/time.h +++ b/xen/include/asm-x86/time.h @@ -41,7 +41,6 @@ int pit_broadcast_is_available(void); uint64_t acpi_pm_tick_to_ns(uint64_t ticks); uint64_t ns_to_acpi_pm_tick(uint64_t ns); -extern int opt_softtsc; void pv_soft_rdtsc(struct vcpu *v, struct cpu_user_regs *regs); #endif /* __X86_TIME_H__ */ diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index f7b1fc5ec7..3b4cb51796 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -401,7 +401,11 @@ struct xen_domctl_settimeoffset { typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); - +#define XEN_DOMCTL_set_tsc_native 57 +typedef struct xen_domctl_set_tsc_native { + uint32_t is_native; /* IN: 0: TSC is emulated; 1: TSC is host TSC */ +} xen_domctl_set_tsc_native_t; + #define XEN_DOMCTL_gethvmcontext 33 #define XEN_DOMCTL_sethvmcontext 34 typedef struct xen_domctl_hvmcontext { @@ -672,6 +676,7 @@ struct xen_domctl { struct xen_domctl_hypercall_init hypercall_init; struct xen_domctl_arch_setup arch_setup; struct xen_domctl_settimeoffset settimeoffset; + struct xen_domctl_set_tsc_native set_tsc_native; struct xen_domctl_real_mode_area real_mode_area; struct xen_domctl_hvmcontext hvmcontext; struct xen_domctl_hvmcontext_partial hvmcontext_partial; |