WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH] replace rdtsc emulation-vs-native xen boot option wi

To: "Xen-Devel (E-mail)" <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: [Xen-devel] [PATCH] replace rdtsc emulation-vs-native xen boot option with per-domain (hypervisor part)
From: Dan Magenheimer <dan.magenheimer@xxxxxxxxxx>
Date: Sun, 27 Sep 2009 12:22:12 -0700 (PDT)
Delivery-date: Sun, 27 Sep 2009 12:23:03 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
(I'm still struggling against the coils of python on
the tools part of this patch, so thought I'd post the
hypervisor side separately first.)

Switches rdtsc emulation from boot option to per-domain
and enables it by default.  Also removes hvm tsc scaling
as it is no longer necessary.

Signed-off-by: Dan Magenheimer <dan.magenheimer@xxxxxxxxxx>

diff -r 72d130772f36 xen/arch/x86/domain.c
--- a/xen/arch/x86/domain.c     Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/domain.c     Sun Sep 27 13:08:12 2009 -0600
@@ -494,6 +494,10 @@ int arch_domain_create(struct domain *d,
         mce_init_msr(d);
     }
 
+    if ( d->domain_id == 0 )
+        d->arch.tsc_native = 1;
+    spin_lock_init(&d->arch.vtsc_lock);
+
     if ( is_hvm_domain(d) )
     {
         if ( (rc = hvm_domain_initialise(d)) != 0 )
@@ -503,11 +507,9 @@ int arch_domain_create(struct domain *d,
         }
     }
     else
-    {
         /* 32-bit PV guest by default only if Xen is not 64-bit. */
         d->arch.is_32bit_pv = d->arch.has_32bit_shinfo =
             (CONFIG_PAGING_LEVELS != 4);
-    }
 
     memset(d->arch.cpuids, 0, sizeof(d->arch.cpuids));
     for ( i = 0; i < MAX_CPUID_INPUT; i++ )
@@ -515,10 +517,6 @@ int arch_domain_create(struct domain *d,
         d->arch.cpuids[i].input[0] = XEN_CPUID_INPUT_UNUSED;
         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 72d130772f36 xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c     Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/domctl.c     Sun Sep 27 13:08:12 2009 -0600
@@ -1060,6 +1060,20 @@ 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;
+        d->arch.tsc_native = 1;
+        rcu_unlock_domain(d);
+        ret = 0;
+    }
+    break;
+
     case XEN_DOMCTL_suppress_spurious_page_faults:
     {
         struct domain *d;
diff -r 72d130772f36 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c    Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/hvm/hvm.c    Sun Sep 27 13:08:12 2009 -0600
@@ -146,63 +146,39 @@ void hvm_enable_rdtsc_exiting(struct dom
 {
     struct vcpu *v;
 
-    if ( opt_softtsc || !hvm_funcs.enable_rdtsc_exiting )
+    if ( !hvm_funcs.enable_rdtsc_exiting )
         return;
 
     for_each_vcpu ( d, v )
         hvm_funcs.enable_rdtsc_exiting(v);
 }
 
-int hvm_gtsc_need_scale(struct domain *d)
-{
-    uint32_t gtsc_mhz, htsc_mhz;
-
-    gtsc_mhz = d->arch.hvm_domain.gtsc_khz / 1000;
-    htsc_mhz = opt_softtsc ? 1000 : ((uint32_t)cpu_khz / 1000);
-
-    d->arch.hvm_domain.tsc_scaled = (gtsc_mhz && (gtsc_mhz != htsc_mhz));
-    return d->arch.hvm_domain.tsc_scaled;
-}
-
-static u64 hvm_h2g_scale_tsc(struct vcpu *v, u64 host_tsc)
-{
-    uint32_t gtsc_khz, htsc_khz;
-
-    if ( !v->domain->arch.hvm_domain.tsc_scaled )
-        return host_tsc;
-
-    htsc_khz = opt_softtsc ? 1000000 : 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 host_tsc;
 
-    if ( opt_softtsc )
+    if ( v->domain->arch.tsc_native )
+        rdtscll(host_tsc);
+    else
         host_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;
+    v->arch.hvm_vcpu.cache_tsc_offset = guest_tsc - host_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.tsc_native )
+        rdtscll(tsc);
     else
-        rdtscll(host_tsc);
+    {
+        v->domain->arch.vtsc_kerncount++;
+        tsc = hvm_get_guest_time(v);
+    }
 
-    scaled_htsc = hvm_h2g_scale_tsc(v, host_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 -r 72d130772f36 xen/arch/x86/hvm/save.c
--- a/xen/arch/x86/hvm/save.c   Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/hvm/save.c   Sun Sep 27 13:08:12 2009 -0600
@@ -31,9 +31,6 @@ void arch_hvm_save(struct domain *d, str
     /* Save some CPUID bits */
     cpuid(1, &eax, &ebx, &ecx, &edx);
     hdr->cpuid = eax;
-
-    /* Save guest's preferred TSC. */
-    hdr->gtsc_khz = d->arch.hvm_domain.gtsc_khz;
 }
 
 int arch_hvm_load(struct domain *d, struct hvm_save_header *hdr)
@@ -60,17 +57,8 @@ int arch_hvm_load(struct domain *d, stru
         gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") "
                "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 ( !d->arch.tsc_native )
         hvm_enable_rdtsc_exiting(d);
-        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);
-    }
 
     /* VGA state is not saved/restored, so we nobble the cache. */
     d->arch.hvm_domain.stdvga.cache = 0;
diff -r 72d130772f36 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Sun Sep 27 13:08:12 2009 -0600
@@ -167,7 +167,7 @@ static int construct_vmcb(struct vcpu *v
 
     /* TSC. */
     vmcb->tsc_offset = 0;
-    if ( opt_softtsc )
+    if ( !v->domain->arch.tsc_native )
         vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
 
     /* Guest EFER. */
diff -r 72d130772f36 xen/arch/x86/hvm/vmx/vmcs.c
--- a/xen/arch/x86/hvm/vmx/vmcs.c       Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/hvm/vmx/vmcs.c       Sun Sep 27 13:08:12 2009 -0600
@@ -133,7 +133,7 @@ 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 |
diff -r 72d130772f36 xen/arch/x86/hvm/vpt.c
--- a/xen/arch/x86/hvm/vpt.c    Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/hvm/vpt.c    Sun Sep 27 13:08:12 2009 -0600
@@ -32,9 +32,6 @@ void hvm_init_guest_time(struct domain *
     spin_lock_init(&pl->pl_time_lock);
     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.tsc_scaled = 0;
 }
 
 u64 hvm_get_guest_time(struct vcpu *v)
diff -r 72d130772f36 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/time.c       Sun Sep 27 13:08:12 2009 -0600
@@ -35,9 +35,6 @@
 /* opt_clocksource: Force clocksource to one of: pit, hpet, cyclone, acpi. */
 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
@@ -1438,20 +1435,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 )
@@ -1464,10 +1459,27 @@ 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.tsc_native )
+        {
+            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 tsc_native enabled\n");
 }
 
 static struct keyhandler dump_softtsc_keyhandler = {
@@ -1478,8 +1490,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 72d130772f36 xen/arch/x86/traps.c
--- a/xen/arch/x86/traps.c      Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/arch/x86/traps.c      Sun Sep 27 13:08:12 2009 -0600
@@ -2010,7 +2010,7 @@ static int emulate_privileged_op(struct 
      */
     opcode = insn_fetch(u8, code_base, eip, code_limit);
     if ( !guest_kernel_mode(v, regs) &&
-         !((opcode == 0x31) && v->domain->arch.vtsc) )
+         !((opcode == 0x31) && !v->domain->arch.tsc_native) )
         goto fail;
 
     if ( lock && (opcode & ~3) != 0x20 )
diff -r 72d130772f36 xen/include/asm-x86/domain.h
--- a/xen/include/asm-x86/domain.h      Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/include/asm-x86/domain.h      Sun Sep 27 13:08:12 2009 -0600
@@ -301,9 +301,11 @@ struct arch_domain
     struct domain_mca_msrs vmca_msrs;
 
     /* SoftTSC emulation */
-    bool_t vtsc;
+    bool_t tsc_native;  /* true means vtsc is disabled */
     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;
 
@@ -435,7 +437,7 @@ unsigned long pv_guest_cr4_fixup(unsigne
 #define pv_guest_cr4_to_real_cr4(v)                         \
     (((v)->arch.guest_context.ctrlreg[4]                    \
       | (mmu_cr4_features & (X86_CR4_PGE | X86_CR4_PSE))    \
-      | ((v)->domain->arch.vtsc ? X86_CR4_TSD : 0))         \
+      | ((v)->domain->arch.tsc_native ? 0: X86_CR4_TSD))    \
       & ~X86_CR4_DE)
 #define real_cr4_to_pv_guest_cr4(c) \
     ((c) & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_TSD))
diff -r 72d130772f36 xen/include/asm-x86/hvm/domain.h
--- a/xen/include/asm-x86/hvm/domain.h  Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/include/asm-x86/hvm/domain.h  Sun Sep 27 13:08:12 2009 -0600
@@ -45,8 +45,6 @@ struct hvm_domain {
     struct hvm_ioreq_page  ioreq;
     struct hvm_ioreq_page  buf_ioreq;
 
-    uint32_t               gtsc_khz; /* kHz */
-    bool_t                 tsc_scaled;
     struct pl_time         pl_time;
 
     struct hvm_io_handler  io_handler;
diff -r 72d130772f36 xen/include/asm-x86/hvm/hvm.h
--- a/xen/include/asm-x86/hvm/hvm.h     Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/include/asm-x86/hvm/hvm.h     Sun Sep 27 13:08:12 2009 -0600
@@ -286,7 +286,6 @@ uint8_t hvm_combine_hw_exceptions(uint8_
 uint8_t hvm_combine_hw_exceptions(uint8_t vec1, uint8_t vec2);
 
 void hvm_enable_rdtsc_exiting(struct domain *d);
-int hvm_gtsc_need_scale(struct domain *d);
 
 static inline int hvm_cpu_up(void)
 {
diff -r 72d130772f36 xen/include/asm-x86/time.h
--- a/xen/include/asm-x86/time.h        Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/include/asm-x86/time.h        Sun Sep 27 13:08:12 2009 -0600
@@ -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 72d130772f36 xen/include/public/arch-x86/hvm/save.h
--- a/xen/include/public/arch-x86/hvm/save.h    Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/include/public/arch-x86/hvm/save.h    Sun Sep 27 13:08:12 2009 -0600
@@ -38,7 +38,6 @@ struct hvm_save_header {
     uint32_t version;           /* File format version */
     uint64_t changeset;         /* Version of Xen that saved this file */
     uint32_t cpuid;             /* CPUID[0x01][%eax] on the saving machine */
-    uint32_t gtsc_khz;        /* Guest's TSC frequency in kHz */
 };
 
 DECLARE_HVM_SAVE_TYPE(HEADER, 1, struct hvm_save_header);
diff -r 72d130772f36 xen/include/public/domctl.h
--- a/xen/include/public/domctl.h       Wed Sep 16 09:30:41 2009 +0100
+++ b/xen/include/public/domctl.h       Sun Sep 27 13:08:12 2009 -0600
@@ -400,7 +400,8 @@ struct xen_domctl_settimeoffset {
 };
 typedef struct xen_domctl_settimeoffset xen_domctl_settimeoffset_t;
 DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t);
-
+/* allow rdtsc to be natively executed (is trapped/emulated by default */
+#define XEN_DOMCTL_set_tsc_native    57
  
 #define XEN_DOMCTL_gethvmcontext     33
 #define XEN_DOMCTL_sethvmcontext     34

Attachment: tsc-native-hyp.patch
Description: Binary data

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