aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/vmx
diff options
context:
space:
mode:
authorDietmar Hahn <dietmar.hahn@ts.fujitsu.com>2013-03-26 14:24:25 +0100
committerJan Beulich <jbeulich@suse.com>2013-03-26 14:24:25 +0100
commit25250ed7c8094a905c5f03b8ae25c8694d3fa9b3 (patch)
treedadd1ea3edda3aa7e14b5113f09dd7890b8fd005 /xen/arch/x86/hvm/vmx
parentdb537fe3023bf157b85c8246782cb72a6f989b31 (diff)
downloadxen-25250ed7c8094a905c5f03b8ae25c8694d3fa9b3.tar.gz
xen-25250ed7c8094a905c5f03b8ae25c8694d3fa9b3.tar.bz2
xen-25250ed7c8094a905c5f03b8ae25c8694d3fa9b3.zip
vpmu intel: Add cpuid handling when vpmu disabled
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 Signed-off-by: Dietmar Hahn <dietmar.hahn@ts.fujitsu.com> Acked-by: Keir Fraser <keir@xen.org>
Diffstat (limited to 'xen/arch/x86/hvm/vmx')
-rw-r--r--xen/arch/x86/hvm/vmx/vpmu_core2.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/xen/arch/x86/hvm/vmx/vpmu_core2.c b/xen/arch/x86/hvm/vmx/vpmu_core2.c
index afad35b04c..1c6a87c3b9 100644
--- a/xen/arch/x86/hvm/vmx/vpmu_core2.c
+++ b/xen/arch/x86/hvm/vmx/vpmu_core2.c
@@ -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, unsigned int vpmu_flags)
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 )