aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxc/xc_domain.c9
-rw-r--r--tools/libxc/xenctrl.h2
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c22
-rw-r--r--tools/python/xen/xend/XendConfig.py4
-rw-r--r--tools/python/xen/xend/XendDomainInfo.py7
-rw-r--r--tools/python/xen/xm/create.py9
-rw-r--r--tools/python/xen/xm/xenapi_create.py1
-rw-r--r--xen/arch/x86/domain.c2
-rw-r--r--xen/arch/x86/domctl.c20
-rw-r--r--xen/arch/x86/hvm/hvm.c48
-rw-r--r--xen/arch/x86/hvm/save.c11
-rw-r--r--xen/arch/x86/hvm/svm/svm.c11
-rw-r--r--xen/arch/x86/hvm/svm/vmcb.c2
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c6
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c10
-rw-r--r--xen/arch/x86/hvm/vpt.c2
-rw-r--r--xen/arch/x86/time.c34
-rw-r--r--xen/include/asm-x86/domain.h2
-rw-r--r--xen/include/asm-x86/hvm/hvm.h4
-rw-r--r--xen/include/asm-x86/time.h1
-rw-r--r--xen/include/public/domctl.h7
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;