[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] x86: Allow TSC mode (emulate vs native) to be configured per domain.



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1254128470 -3600
# Node ID 3e0675c57933be59b8d38bff1e61876e8672b0ab
# Parent  d74302fc00e625221e317900a95ecfb2a7fba37a
x86: Allow TSC mode (emulate vs native) to be configured per domain.

The default is to emulate. Old saved images will be restored with
legacy behaviour however (native TSC, no emulation).

Signed-off-by: Dan Magenheimer <dan.magenheimer@xxxxxxxxxx>
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
 tools/libxc/xc_domain.c                 |    9 +++++
 tools/libxc/xenctrl.h                   |    2 +
 tools/python/xen/lowlevel/xc/xc.c       |   22 ++++++++++++
 tools/python/xen/xend/XendConfig.py     |    4 ++
 tools/python/xen/xend/XendDomainInfo.py |    7 +++-
 tools/python/xen/xm/create.py           |    9 ++++-
 tools/python/xen/xm/xenapi_create.py    |    1 
 xen/arch/x86/domain.c                   |    2 -
 xen/arch/x86/domctl.c                   |   20 +++++++++++
 xen/arch/x86/hvm/hvm.c                  |   56 +++++++++++++++++---------------
 xen/arch/x86/hvm/save.c                 |   11 ++----
 xen/arch/x86/hvm/svm/svm.c              |   11 +++++-
 xen/arch/x86/hvm/svm/vmcb.c             |    2 -
 xen/arch/x86/hvm/vmx/vmcs.c             |    6 ++-
 xen/arch/x86/hvm/vmx/vmx.c              |   10 +++--
 xen/arch/x86/hvm/vpt.c                  |    2 -
 xen/arch/x86/time.c                     |   34 +++++++++++++------
 xen/include/asm-x86/domain.h            |    2 +
 xen/include/asm-x86/hvm/hvm.h           |    4 +-
 xen/include/asm-x86/time.h              |    1 
 xen/include/public/domctl.h             |    7 +++-
 21 files changed, 164 insertions(+), 58 deletions(-)

diff -r d74302fc00e6 -r 3e0675c57933 tools/libxc/xc_domain.c
--- a/tools/libxc/xc_domain.c   Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/libxc/xc_domain.c   Mon Sep 28 10:01:10 2009 +0100
@@ -463,6 +463,15 @@ int xc_domain_set_time_offset(int xc_han
     domctl.cmd = XEN_DOMCTL_settimeoffset;
     domctl.domain = (domid_t)domid;
     domctl.u.settimeoffset.time_offset_seconds = time_offset_seconds;
+    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);
 }
 
diff -r d74302fc00e6 -r 3e0675c57933 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h     Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/libxc/xenctrl.h     Mon Sep 28 10:01:10 2009 +0100
@@ -628,6 +628,8 @@ int xc_domain_set_time_offset(int xc_han
                               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 -r d74302fc00e6 -r 3e0675c57933 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/python/xen/lowlevel/xc/xc.c Mon Sep 28 10:01:10 2009 +0100
@@ -1459,6 +1459,20 @@ static PyObject *pyxc_domain_set_time_of
     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)
@@ -1979,6 +1993,14 @@ static PyMethodDef pyxc_methods[] = {
       "Set a domain's time offset to Dom0's localtime\n"
       " dom        [int]: Domain whose time offset is being set.\n"
       " 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",
diff -r d74302fc00e6 -r 3e0675c57933 tools/python/xen/xend/XendConfig.py
--- a/tools/python/xen/xend/XendConfig.py       Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/python/xen/xend/XendConfig.py       Mon Sep 28 10:01:10 2009 +0100
@@ -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,
@@ -472,6 +473,9 @@ class XendConfig(dict):
                     auxbin.pathTo(self['platform']['device_model'])
             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']:
diff -r d74302fc00e6 -r 3e0675c57933 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py   Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/python/xen/xend/XendDomainInfo.py   Mon Sep 28 10:01:10 2009 +0100
@@ -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 -r d74302fc00e6 -r 3e0675c57933 tools/python/xen/xm/create.py
--- a/tools/python/xen/xm/create.py     Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/python/xen/xm/create.py     Mon Sep 28 10:01:10 2009 +0100
@@ -220,6 +220,10 @@ gopts.var('timer_mode', val='TIMER_MODE'
           fn=set_int, default=1,
           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,
@@ -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 -r d74302fc00e6 -r 3e0675c57933 tools/python/xen/xm/xenapi_create.py
--- a/tools/python/xen/xm/xenapi_create.py      Mon Sep 28 08:28:26 2009 +0100
+++ b/tools/python/xen/xm/xenapi_create.py      Mon Sep 28 10:01:10 2009 +0100
@@ -1066,6 +1066,7 @@ class sxp2xml:
             'pci_msitranslate',
             'pci_power_mgmt',
             'xen_platform_pci',
+            'tsc_native'
         ]
 
         platform_configs = []
diff -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/domain.c     Mon Sep 28 10:01:10 2009 +0100
@@ -520,8 +520,6 @@ int arch_domain_create(struct domain *d,
         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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/domctl.c     Mon Sep 28 10:01:10 2009 +0100
@@ -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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Mon Sep 28 10:01:10 2009 +0100
@@ -142,23 +142,23 @@ uint8_t hvm_combine_hw_exceptions(uint8_
     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
     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;
-
-    if ( opt_softtsc )
-        host_tsc = hvm_get_guest_time(v);
+    uint64_t tsc;
+
+    if ( v->domain->arch.vtsc )
+    {
+        tsc = hvm_get_guest_time(v);
+    }
     else
-        rdtscll(host_tsc);
-
-    scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc);
-
-    v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - scaled_htsc;
+    {
+        rdtscll(tsc);
+        tsc = hvm_h2g_scale_tsc(v, tsc);
+    }
+
+    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;
-
-    if ( opt_softtsc )
-        host_tsc = hvm_get_guest_time(v);
+    uint64_t tsc;
+
+    if ( v->domain->arch.vtsc )
+    {
+        tsc = hvm_get_guest_time(v);
+    }
     else
-        rdtscll(host_tsc);
-
-    scaled_htsc = hvm_h2g_scale_tsc(v, host_tsc);
-
-    return scaled_htsc + v->arch.hvm_vcpu.cache_tsc_offset;
+    {
+        rdtscll(tsc);
+        tsc = hvm_h2g_scale_tsc(v, tsc);
+    }
+
+    return tsc + v->arch.hvm_vcpu.cache_tsc_offset;
 }
 
 void hvm_migrate_timers(struct vcpu *v)
diff -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/save.c
--- a/xen/arch/x86/hvm/save.c   Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/save.c   Mon Sep 28 10:01:10 2009 +0100
@@ -61,15 +61,14 @@ int arch_hvm_load(struct domain *d, stru
                "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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Sep 28 10:01:10 2009 +0100
@@ -619,6 +619,14 @@ static void svm_set_tsc_offset(struct vc
     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_fun
     .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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Mon Sep 28 10:01:10 2009 +0100
@@ -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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Mon Sep 28 10:01:10 2009 +0100
@@ -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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c        Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmx.c        Mon Sep 28 10:01:10 2009 +0100
@@ -949,13 +949,15 @@ static void vmx_set_tsc_offset(struct vc
     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_fun
     .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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c    Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/hvm/vpt.c    Mon Sep 28 10:01:10 2009 +0100
@@ -33,7 +33,7 @@ void hvm_init_guest_time(struct domain *
     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 -r d74302fc00e6 -r 3e0675c57933 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/arch/x86/time.c       Mon Sep 28 10:01:10 2009 +0100
@@ -36,9 +36,6 @@ static char __initdata opt_clocksource[1
 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, struc
     }
 }
 
+/* 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_ke
 
 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 -r d74302fc00e6 -r 3e0675c57933 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/include/asm-x86/domain.h      Mon Sep 28 10:01:10 2009 +0100
@@ -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 -r d74302fc00e6 -r 3e0675c57933 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Mon Sep 28 10:01:10 2009 +0100
@@ -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 
 
 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 -r d74302fc00e6 -r 3e0675c57933 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/include/asm-x86/time.h        Mon Sep 28 10:01:10 2009 +0100
@@ -41,7 +41,6 @@ uint64_t acpi_pm_tick_to_ns(uint64_t tic
 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 -r d74302fc00e6 -r 3e0675c57933 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Mon Sep 28 08:28:26 2009 +0100
+++ b/xen/include/public/domctl.h       Mon Sep 28 10:01:10 2009 +0100
@@ -401,7 +401,11 @@ typedef 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;

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.