xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH-v2] vpmu intel: Add cpuid handling when vpmu disabled
@ 2013-03-26 11:16 Dietmar Hahn
  2013-03-26 11:45 ` Keir Fraser
  0 siblings, 1 reply; 7+ messages in thread
From: Dietmar Hahn @ 2013-03-26 11:16 UTC (permalink / raw)
  To: xen-devel
  Cc: Eddie Dong, suravee.suthikulpanit, Jun Nakajima,
	Konrad Rzeszutek Wilk

[-- Attachment #1: Type: text/plain, Size: 6089 bytes --]

Even though vpmu is disabled in the hypervisor in the HVM guest the call of
cpuid(0xa) returns informations about usable performance counters.
This may confuse guest software when trying to use the counters and nothing
happens.
This patch clears most bits in registers eax and edx of cpuid(0xa) instruction
for the guest when vpmu is disabled:
 - version ID of architectural performance counting
 - number of general pmu registers
 - width of general pmu registers
 - number of fixed pmu registers
 - width of ixed pmu registers

Thanks.
Dietmar.


Signed-off-by: Dietmar Hahn <dietmar.hahn@ts.fujitsu.com>

---

Changes from v1: As Konrad suggested I added a little bit more of documentation
                 to the defines.


diff -r 2246964a25a8 xen/arch/x86/hvm/svm/vpmu.c
--- a/xen/arch/x86/hvm/svm/vpmu.c	Mon Mar 25 16:57:31 2013 +0100
+++ b/xen/arch/x86/hvm/svm/vpmu.c	Tue Mar 26 12:01:11 2013 +0100
@@ -370,6 +370,10 @@ int svm_vpmu_initialise(struct vcpu *v, 
     uint8_t family = current_cpu_data.x86;
     int ret = 0;
 
+    /* vpmu enabled? */
+    if ( !vpmu_flags )
+        return 0;
+
     switch ( family )
     {
     case 0x10:
diff -r 2246964a25a8 xen/arch/x86/hvm/vmx/vpmu_core2.c
--- a/xen/arch/x86/hvm/vmx/vpmu_core2.c	Mon Mar 25 16:57:31 2013 +0100
+++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c	Tue Mar 26 12:01:11 2013 +0100
@@ -731,6 +731,62 @@ struct arch_vpmu_ops core2_vpmu_ops = {
     .arch_vpmu_load = core2_vpmu_load
 };
 
+/*
+ * See Intel SDM Vol 2a Instruction Set Referenc for CPUID instruction.
+ * cpuid 0xa - Architectural Performance Monitoring Leaf
+ * Register eax
+ */
+#define X86_FEATURE_PMU_VER_OFF   0  /* Version ID */
+#define FEATURE_PMU_VER_BITS      8  /* 8 bits 0..7 */
+#define X86_FEATURE_NUM_GEN_OFF   8  /* Number of general pmu registers */
+#define FEATURE_NUM_GEN_BITS      8  /* 8 bits 8..15 */
+#define X86_FEATURE_GEN_WIDTH_OFF 16 /* Width of general pmu registers */
+#define FEATURE_GEN_WIDTH_BITS    8  /* 8 bits 16..23 */
+/* Register edx */
+#define X86_FEATURE_NUM_FIX_OFF   0  /* Number of fixed pmu registers */
+#define FEATURE_NUM_FIX_BITS      5  /* 5 bits 0..4 */
+#define X86_FEATURE_FIX_WIDTH_OFF 5  /* Width of fixed pmu registers */
+#define FEATURE_FIX_WIDTH_BITS    8  /* 8 bits 5..12 */
+
+static void core2_no_vpmu_do_cpuid(unsigned int input,
+                                unsigned int *eax, unsigned int *ebx,
+                                unsigned int *ecx, unsigned int *edx)
+{
+    /*
+     * As in this case the vpmu is not enabled reset some bits in the
+     * architectural performance monitoring related part.
+     */
+    if ( input == 0xa )
+    {
+        *eax &= ~(((1 << FEATURE_PMU_VER_BITS) -1) << X86_FEATURE_PMU_VER_OFF);
+        *eax &= ~(((1 << FEATURE_NUM_GEN_BITS) -1) << X86_FEATURE_NUM_GEN_OFF);
+        *eax &= ~(((1 << FEATURE_GEN_WIDTH_BITS) -1) << X86_FEATURE_GEN_WIDTH_OFF);
+
+        *edx &= ~(((1 << FEATURE_NUM_FIX_BITS) -1) << X86_FEATURE_NUM_FIX_OFF);
+        *edx &= ~(((1 << FEATURE_FIX_WIDTH_BITS) -1) << X86_FEATURE_FIX_WIDTH_OFF);
+    }
+}
+
+/*
+ * If its a vpmu msr set it to 0.
+ */
+static int core2_no_vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content)
+{
+    int type = -1, index = -1;
+    if ( !is_core2_vpmu_msr(msr, &type, &index) )
+        return 0;
+    *msr_content = 0;
+    return 1;
+}
+
+/*
+ * These functions are used in case vpmu is not enabled.
+ */
+struct arch_vpmu_ops core2_no_vpmu_ops = {
+    .do_rdmsr = core2_no_vpmu_do_rdmsr,
+    .do_cpuid = core2_no_vpmu_do_cpuid,
+};
+
 int vmx_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
@@ -738,6 +794,10 @@ int vmx_vpmu_initialise(struct vcpu *v, 
     uint8_t cpu_model = current_cpu_data.x86_model;
     int ret = 0;
 
+    vpmu->arch_vpmu_ops = &core2_no_vpmu_ops;
+    if ( !vpmu_flags )
+        return 0;
+
     if ( family == 6 )
     {
         switch ( cpu_model )
diff -r 2246964a25a8 xen/arch/x86/hvm/vpmu.c
--- a/xen/arch/x86/hvm/vpmu.c	Mon Mar 25 16:57:31 2013 +0100
+++ b/xen/arch/x86/hvm/vpmu.c	Tue Mar 26 12:01:11 2013 +0100
@@ -67,7 +67,7 @@ int vpmu_do_wrmsr(unsigned int msr, uint
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(current);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_wrmsr )
         return vpmu->arch_vpmu_ops->do_wrmsr(msr, msr_content);
     return 0;
 }
@@ -76,7 +76,7 @@ int vpmu_do_rdmsr(unsigned int msr, uint
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(current);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_rdmsr )
         return vpmu->arch_vpmu_ops->do_rdmsr(msr, msr_content);
     return 0;
 }
@@ -85,7 +85,7 @@ int vpmu_do_interrupt(struct cpu_user_re
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(current);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_interrupt )
         return vpmu->arch_vpmu_ops->do_interrupt(regs);
     return 0;
 }
@@ -104,7 +104,7 @@ void vpmu_save(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_save )
         vpmu->arch_vpmu_ops->arch_vpmu_save(v);
 }
 
@@ -112,7 +112,7 @@ void vpmu_load(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_load )
         vpmu->arch_vpmu_ops->arch_vpmu_load(v);
 }
 
@@ -121,9 +121,6 @@ void vpmu_initialise(struct vcpu *v)
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
     uint8_t vendor = current_cpu_data.x86_vendor;
 
-    if ( !opt_vpmu_enabled )
-        return;
-
     if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
         vpmu_destroy(v);
     vpmu_clear(vpmu);
@@ -153,7 +150,7 @@ void vpmu_destroy(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_destroy )
         vpmu->arch_vpmu_ops->arch_vpmu_destroy(v);
 }
 

[-- Attachment #2: vpmu_no_vpmu.patch --]
[-- Type: text/x-patch, Size: 5358 bytes --]

diff -r 2246964a25a8 xen/arch/x86/hvm/svm/vpmu.c
--- a/xen/arch/x86/hvm/svm/vpmu.c	Mon Mar 25 16:57:31 2013 +0100
+++ b/xen/arch/x86/hvm/svm/vpmu.c	Tue Mar 26 12:01:11 2013 +0100
@@ -370,6 +370,10 @@ int svm_vpmu_initialise(struct vcpu *v, 
     uint8_t family = current_cpu_data.x86;
     int ret = 0;
 
+    /* vpmu enabled? */
+    if ( !vpmu_flags )
+        return 0;
+
     switch ( family )
     {
     case 0x10:
diff -r 2246964a25a8 xen/arch/x86/hvm/vmx/vpmu_core2.c
--- a/xen/arch/x86/hvm/vmx/vpmu_core2.c	Mon Mar 25 16:57:31 2013 +0100
+++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c	Tue Mar 26 12:01:11 2013 +0100
@@ -731,6 +731,62 @@ struct arch_vpmu_ops core2_vpmu_ops = {
     .arch_vpmu_load = core2_vpmu_load
 };
 
+/*
+ * See Intel SDM Vol 2a Instruction Set Referenc for CPUID instruction.
+ * cpuid 0xa - Architectural Performance Monitoring Leaf
+ * Register eax
+ */
+#define X86_FEATURE_PMU_VER_OFF   0  /* Version ID */
+#define FEATURE_PMU_VER_BITS      8  /* 8 bits 0..7 */
+#define X86_FEATURE_NUM_GEN_OFF   8  /* Number of general pmu registers */
+#define FEATURE_NUM_GEN_BITS      8  /* 8 bits 8..15 */
+#define X86_FEATURE_GEN_WIDTH_OFF 16 /* Width of general pmu registers */
+#define FEATURE_GEN_WIDTH_BITS    8  /* 8 bits 16..23 */
+/* Register edx */
+#define X86_FEATURE_NUM_FIX_OFF   0  /* Number of fixed pmu registers */
+#define FEATURE_NUM_FIX_BITS      5  /* 5 bits 0..4 */
+#define X86_FEATURE_FIX_WIDTH_OFF 5  /* Width of fixed pmu registers */
+#define FEATURE_FIX_WIDTH_BITS    8  /* 8 bits 5..12 */
+
+static void core2_no_vpmu_do_cpuid(unsigned int input,
+                                unsigned int *eax, unsigned int *ebx,
+                                unsigned int *ecx, unsigned int *edx)
+{
+    /*
+     * As in this case the vpmu is not enabled reset some bits in the
+     * architectural performance monitoring related part.
+     */
+    if ( input == 0xa )
+    {
+        *eax &= ~(((1 << FEATURE_PMU_VER_BITS) -1) << X86_FEATURE_PMU_VER_OFF);
+        *eax &= ~(((1 << FEATURE_NUM_GEN_BITS) -1) << X86_FEATURE_NUM_GEN_OFF);
+        *eax &= ~(((1 << FEATURE_GEN_WIDTH_BITS) -1) << X86_FEATURE_GEN_WIDTH_OFF);
+
+        *edx &= ~(((1 << FEATURE_NUM_FIX_BITS) -1) << X86_FEATURE_NUM_FIX_OFF);
+        *edx &= ~(((1 << FEATURE_FIX_WIDTH_BITS) -1) << X86_FEATURE_FIX_WIDTH_OFF);
+    }
+}
+
+/*
+ * If its a vpmu msr set it to 0.
+ */
+static int core2_no_vpmu_do_rdmsr(unsigned int msr, uint64_t *msr_content)
+{
+    int type = index = -1;
+    if ( !is_core2_vpmu_msr(msr, &type, &index) )
+        return 0;
+    *msr_content = 0;
+    return 1;
+}
+
+/*
+ * These functions are used in case vpmu is not enabled.
+ */
+struct arch_vpmu_ops core2_no_vpmu_ops = {
+    .do_rdmsr = core2_no_vpmu_do_rdmsr,
+    .do_cpuid = core2_no_vpmu_do_cpuid,
+};
+
 int vmx_vpmu_initialise(struct vcpu *v, unsigned int vpmu_flags)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
@@ -738,6 +794,10 @@ int vmx_vpmu_initialise(struct vcpu *v, 
     uint8_t cpu_model = current_cpu_data.x86_model;
     int ret = 0;
 
+    vpmu->arch_vpmu_ops = &core2_no_vpmu_ops;
+    if ( !vpmu_flags )
+        return 0;
+
     if ( family == 6 )
     {
         switch ( cpu_model )
diff -r 2246964a25a8 xen/arch/x86/hvm/vpmu.c
--- a/xen/arch/x86/hvm/vpmu.c	Mon Mar 25 16:57:31 2013 +0100
+++ b/xen/arch/x86/hvm/vpmu.c	Tue Mar 26 12:01:11 2013 +0100
@@ -67,7 +67,7 @@ int vpmu_do_wrmsr(unsigned int msr, uint
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(current);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_wrmsr )
         return vpmu->arch_vpmu_ops->do_wrmsr(msr, msr_content);
     return 0;
 }
@@ -76,7 +76,7 @@ int vpmu_do_rdmsr(unsigned int msr, uint
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(current);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_rdmsr )
         return vpmu->arch_vpmu_ops->do_rdmsr(msr, msr_content);
     return 0;
 }
@@ -85,7 +85,7 @@ int vpmu_do_interrupt(struct cpu_user_re
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(current);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->do_interrupt )
         return vpmu->arch_vpmu_ops->do_interrupt(regs);
     return 0;
 }
@@ -104,7 +104,7 @@ void vpmu_save(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_save )
         vpmu->arch_vpmu_ops->arch_vpmu_save(v);
 }
 
@@ -112,7 +112,7 @@ void vpmu_load(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_load )
         vpmu->arch_vpmu_ops->arch_vpmu_load(v);
 }
 
@@ -121,9 +121,6 @@ void vpmu_initialise(struct vcpu *v)
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
     uint8_t vendor = current_cpu_data.x86_vendor;
 
-    if ( !opt_vpmu_enabled )
-        return;
-
     if ( vpmu_is_set(vpmu, VPMU_CONTEXT_ALLOCATED) )
         vpmu_destroy(v);
     vpmu_clear(vpmu);
@@ -153,7 +150,7 @@ void vpmu_destroy(struct vcpu *v)
 {
     struct vpmu_struct *vpmu = vcpu_vpmu(v);
 
-    if ( vpmu->arch_vpmu_ops )
+    if ( vpmu->arch_vpmu_ops && vpmu->arch_vpmu_ops->arch_vpmu_destroy )
         vpmu->arch_vpmu_ops->arch_vpmu_destroy(v);
 }
 

[-- Attachment #3: Type: text/plain, Size: 126 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2013-04-05 13:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-03-26 11:16 [PATCH-v2] vpmu intel: Add cpuid handling when vpmu disabled Dietmar Hahn
2013-03-26 11:45 ` Keir Fraser
2013-03-27 14:13   ` [PATCH 1/3] vpmu intel: Better names and replacing numerals with defines Dietmar Hahn
2013-04-04 12:10     ` Dietmar Hahn
2013-04-05 13:34       ` Konrad Rzeszutek Wilk
2013-03-27 14:13   ` [PATCH 3/3] vpmu intel: Dump vpmu infos in 'q' keyhandler Dietmar Hahn
2013-03-27 15:16     ` Konrad Rzeszutek Wilk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).